Artur
2020-04-23 09:55:28 +03:00
parent 055606b81b
commit 80b47ec1c0
368 changed files with 29034 additions and 6568 deletions
+308 -37
View File
@@ -7,10 +7,9 @@ SUBSYSTEM_DEF(shuttle)
flags = SS_KEEP_TIMING|SS_NO_TICK_CHECK
runlevels = RUNLEVEL_SETUP | RUNLEVEL_GAME
var/obj/machinery/shuttle_manipulator/manipulator
var/list/mobile = list()
var/list/stationary = list()
var/list/beacons = list()
var/list/transit = list()
var/list/transit_requesters = list()
@@ -59,6 +58,15 @@ SUBSYSTEM_DEF(shuttle)
var/realtimeofstart = 0
var/datum/map_template/shuttle/selected
var/obj/docking_port/mobile/existing_shuttle
var/obj/docking_port/mobile/preview_shuttle
var/datum/map_template/shuttle/preview_template
var/datum/turf_reservation/preview_reservation
/datum/controller/subsystem/shuttle/Initialize(timeofday)
ordernum = rand(1, 9000)
@@ -82,9 +90,6 @@ SUBSYSTEM_DEF(shuttle)
return ..()
/datum/controller/subsystem/shuttle/proc/initial_load()
if(!istype(manipulator))
CRASH("No shuttle manipulator found.")
for(var/s in stationary)
var/obj/docking_port/stationary/S = s
S.load_roundstart()
@@ -148,11 +153,13 @@ SUBSYSTEM_DEF(shuttle)
++alive
var/total = GLOB.joined_player_list.len
if(total <= 0)
return //no players no autoevac
if(alive / total <= threshold)
var/msg = "Automatically dispatching shuttle due to crew death."
var/msg = "Automatically dispatching emergency shuttle due to crew death."
message_admins(msg)
log_game("[msg] Alive: [alive], Roundstart: [total], Threshold: [threshold]")
log_shuttle("[msg] Alive: [alive], Roundstart: [total], Threshold: [threshold]")
emergencyNoRecall = TRUE
priority_announce("Catastrophic casualties detected: crisis shuttle protocols activated - jamming recall signals across all frequencies.")
if(emergency.timeLeft(1) > emergencyCallTime * 0.4)
@@ -177,6 +184,34 @@ SUBSYSTEM_DEF(shuttle)
return S
WARNING("couldn't find dock with id: [id]")
/datum/controller/subsystem/shuttle/proc/canEvac(mob/user)
var/srd = CONFIG_GET(number/shuttle_refuel_delay)
if(world.time - SSticker.round_start_time < srd)
to_chat(user, "<span class='alert'>The emergency shuttle is refueling. Please wait [DisplayTimeText(srd - (world.time - SSticker.round_start_time))] before trying again.</span>")
return FALSE
switch(emergency.mode)
if(SHUTTLE_RECALL)
to_chat(user, "<span class='alert'>The emergency shuttle may not be called while returning to CentCom.</span>")
return FALSE
if(SHUTTLE_CALL)
to_chat(user, "<span class='alert'>The emergency shuttle is already on its way.</span>")
return FALSE
if(SHUTTLE_DOCKED)
to_chat(user, "<span class='alert'>The emergency shuttle is already here.</span>")
return FALSE
if(SHUTTLE_IGNITING)
to_chat(user, "<span class='alert'>The emergency shuttle is firing its engines to leave.</span>")
return FALSE
if(SHUTTLE_ESCAPE)
to_chat(user, "<span class='alert'>The emergency shuttle is moving away to a safe distance.</span>")
return FALSE
if(SHUTTLE_STRANDED)
to_chat(user, "<span class='alert'>The emergency shuttle has been disabled by CentCom.</span>")
return FALSE
return TRUE
/datum/controller/subsystem/shuttle/proc/requestEvac(mob/user, call_reason)
if(!emergency)
WARNING("requestEvac(): There is no emergency shuttle, but the \
@@ -190,35 +225,14 @@ SUBSYSTEM_DEF(shuttle)
manually, and then calling register() on the mobile docking port. \
Good luck.")
emergency = backup_shuttle
var/srd = CONFIG_GET(number/shuttle_refuel_delay)
if(world.time - SSticker.round_start_time < srd)
to_chat(user, "The emergency shuttle is refueling. Please wait [DisplayTimeText(srd - (world.time - SSticker.round_start_time))] before trying again.")
return
switch(emergency.mode)
if(SHUTTLE_RECALL)
to_chat(user, "The emergency shuttle may not be called while returning to CentCom.")
return
if(SHUTTLE_CALL)
to_chat(user, "The emergency shuttle is already on its way.")
return
if(SHUTTLE_DOCKED)
to_chat(user, "The emergency shuttle is already here.")
return
if(SHUTTLE_IGNITING)
to_chat(user, "The emergency shuttle is firing its engines to leave.")
return
if(SHUTTLE_ESCAPE)
to_chat(user, "The emergency shuttle is moving away to a safe distance.")
return
if(SHUTTLE_STRANDED)
to_chat(user, "The emergency shuttle has been disabled by CentCom.")
return
if(!canEvac(user))
return
call_reason = trim(html_encode(call_reason))
if(length(call_reason) < CALL_SHUTTLE_REASON_LENGTH && seclevel2num(get_security_level()) > SEC_LEVEL_GREEN)
to_chat(user, "You must provide a reason.")
to_chat(user, "<span class='alert'>You must provide a reason.</span>")
return
var/area/signal_origin = get_area(user)
@@ -240,11 +254,11 @@ SUBSYSTEM_DEF(shuttle)
var/area/A = get_area(user)
log_game("[key_name(user)] has called the shuttle.")
deadchat_broadcast("<span class='deadsay'><span class='name'>[user.real_name]</span> has called the shuttle at <span class='name'>[A.name]</span>.</span>", user)
log_shuttle("[key_name(user)] has called the emergency shuttle.")
deadchat_broadcast(" has called the shuttle at <span class='name'>[A.name]</span>.", "<span class='name'>[user.real_name]</span>", user, message_type=DEADCHAT_ANNOUNCEMENT)
if(call_reason)
SSblackbox.record_feedback("text", "shuttle_reason", 1, "[call_reason]")
log_game("Shuttle call reason: [call_reason]")
log_shuttle("Shuttle call reason: [call_reason]")
message_admins("[ADMIN_LOOKUPFLW(user)] has called the shuttle. (<A HREF='?_src_=holder;[HrefToken()];trigger_centcom_recall=1'>TRIGGER CENTCOM RECALL</A>)")
/datum/controller/subsystem/shuttle/proc/centcom_recall(old_timer, admiral_message)
@@ -277,7 +291,7 @@ SUBSYSTEM_DEF(shuttle)
/datum/controller/subsystem/shuttle/proc/cancelEvac(mob/user)
if(canRecall())
emergency.cancel(get_area(user))
log_game("[key_name(user)] has recalled the shuttle.")
log_shuttle("[key_name(user)] has recalled the shuttle.")
message_admins("[ADMIN_LOOKUPFLW(user)] has recalled the shuttle.")
deadchat_broadcast("<span class='deadsay'><span class='name'>[user.real_name]</span> has recalled the shuttle from <span class='name'>[get_area_name(user, TRUE)]</span>.</span>", user)
return 1
@@ -327,7 +341,7 @@ SUBSYSTEM_DEF(shuttle)
if(callShuttle)
if(EMERGENCY_IDLE_OR_RECALLED)
emergency.request(null, set_coefficient = 2.5)
log_game("There is no means of calling the shuttle anymore. Shuttle automatically called.")
log_shuttle("There is no means of calling the emergency shuttle anymore. Shuttle automatically called.")
message_admins("All the communications consoles were destroyed and all AIs are inactive. Shuttle called.")
/datum/controller/subsystem/shuttle/proc/registerHostileEnvironment(datum/bad)
@@ -380,7 +394,7 @@ SUBSYSTEM_DEF(shuttle)
emergency.setTimer(emergencyDockTime)
priority_announce("Hostile environment resolved. \
You have 3 minutes to board the Emergency Shuttle.",
null, "shuttledock", "Priority")
null, 'sound/ai/shuttledock.ogg', "Priority")
//try to move/request to dockHome if possible, otherwise dockAway. Mainly used for admin buttons
/datum/controller/subsystem/shuttle/proc/toggleShuttle(shuttleId, dockHome, dockAway, timed)
@@ -565,6 +579,14 @@ SUBSYSTEM_DEF(shuttle)
shuttle_purchased = SSshuttle.shuttle_purchased
lockdown = SSshuttle.lockdown
selected = SSshuttle.selected
existing_shuttle = SSshuttle.existing_shuttle
preview_shuttle = SSshuttle.preview_shuttle
preview_template = SSshuttle.preview_template
preview_reservation = SSshuttle.preview_reservation
/datum/controller/subsystem/shuttle/proc/is_in_shuttle_bounds(atom/A)
var/area/current = get_area(A)
@@ -647,3 +669,252 @@ SUBSYSTEM_DEF(shuttle)
message_admins("Round end vote passed. Shuttle has been auto-called.")
emergencyNoRecall = TRUE
endvote_passed = TRUE
/datum/controller/subsystem/shuttle/proc/action_load(datum/map_template/shuttle/loading_template, obj/docking_port/stationary/destination_port)
// Check for an existing preview
if(preview_shuttle && (loading_template != preview_template))
preview_shuttle.jumpToNullSpace()
preview_shuttle = null
preview_template = null
QDEL_NULL(preview_reservation)
if(!preview_shuttle)
if(load_template(loading_template))
preview_shuttle.linkup(loading_template, destination_port)
preview_template = loading_template
// get the existing shuttle information, if any
var/timer = 0
var/mode = SHUTTLE_IDLE
var/obj/docking_port/stationary/D
if(istype(destination_port))
D = destination_port
else if(existing_shuttle)
timer = existing_shuttle.timer
mode = existing_shuttle.mode
D = existing_shuttle.get_docked()
if(!D)
D = generate_transit_dock(preview_shuttle)
if(!D)
CRASH("No dock found for preview shuttle ([preview_template.name]), aborting.")
var/result = preview_shuttle.canDock(D)
// truthy value means that it cannot dock for some reason
// but we can ignore the someone else docked error because we'll
// be moving into their place shortly
if((result != SHUTTLE_CAN_DOCK) && (result != SHUTTLE_SOMEONE_ELSE_DOCKED))
WARNING("Template shuttle [preview_shuttle] cannot dock at [D] ([result]).")
return
if(existing_shuttle)
existing_shuttle.jumpToNullSpace()
var/list/force_memory = preview_shuttle.movement_force
preview_shuttle.movement_force = list("KNOCKDOWN" = 0, "THROW" = 0)
preview_shuttle.initiate_docking(D)
preview_shuttle.movement_force = force_memory
. = preview_shuttle
// Shuttle state involves a mode and a timer based on world.time, so
// plugging the existing shuttles old values in works fine.
preview_shuttle.timer = timer
preview_shuttle.mode = mode
preview_shuttle.register()
// TODO indicate to the user that success happened, rather than just
// blanking the modification tab
preview_shuttle = null
preview_template = null
existing_shuttle = null
selected = null
QDEL_NULL(preview_reservation)
/datum/controller/subsystem/shuttle/proc/load_template(datum/map_template/shuttle/S)
. = FALSE
// load shuttle template, centred at shuttle import landmark,
preview_reservation = SSmapping.RequestBlockReservation(S.width, S.height, SSmapping.transit.z_value, /datum/turf_reservation/transit)
if(!preview_reservation)
CRASH("failed to reserve an area for shuttle template loading")
var/turf/BL = TURF_FROM_COORDS_LIST(preview_reservation.bottom_left_coords)
S.load(BL, centered = FALSE, register = FALSE)
var/affected = S.get_affected_turfs(BL, centered=FALSE)
var/found = 0
// Search the turfs for docking ports
// - We need to find the mobile docking port because that is the heart of
// the shuttle.
// - We need to check that no additional ports have slipped in from the
// template, because that causes unintended behaviour.
for(var/T in affected)
for(var/obj/docking_port/P in T)
if(istype(P, /obj/docking_port/mobile))
found++
if(found > 1)
qdel(P, force=TRUE)
log_world("Map warning: Shuttle Template [S.mappath] has multiple mobile docking ports.")
else
preview_shuttle = P
if(istype(P, /obj/docking_port/stationary))
log_world("Map warning: Shuttle Template [S.mappath] has a stationary docking port.")
if(!found)
var/msg = "load_template(): Shuttle Template [S.mappath] has no mobile docking port. Aborting import."
for(var/T in affected)
var/turf/T0 = T
T0.empty()
message_admins(msg)
WARNING(msg)
return
//Everything fine
S.post_load(preview_shuttle)
return TRUE
/datum/controller/subsystem/shuttle/proc/unload_preview()
if(preview_shuttle)
preview_shuttle.jumpToNullSpace()
preview_shuttle = null
/datum/controller/subsystem/shuttle/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, datum/tgui/master_ui = null, datum/ui_state/state = GLOB.admin_state)
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
if(!ui)
ui = new(user, src, ui_key, "ShuttleManipulator", name, 800, 600, master_ui, state)
ui.open()
/datum/controller/subsystem/shuttle/ui_data(mob/user)
var/list/data = list()
data["tabs"] = list("Status", "Templates", "Modification")
// Templates panel
data["templates"] = list()
var/list/templates = data["templates"]
data["templates_tabs"] = list()
data["selected"] = list()
for(var/shuttle_id in SSmapping.shuttle_templates)
var/datum/map_template/shuttle/S = SSmapping.shuttle_templates[shuttle_id]
if(!templates[S.port_id])
data["templates_tabs"] += S.port_id
templates[S.port_id] = list(
"port_id" = S.port_id,
"templates" = list())
var/list/L = list()
L["name"] = S.name
L["shuttle_id"] = S.shuttle_id
L["port_id"] = S.port_id
L["description"] = S.description
L["admin_notes"] = S.admin_notes
if(selected == S)
data["selected"] = L
templates[S.port_id]["templates"] += list(L)
data["templates_tabs"] = sortList(data["templates_tabs"])
data["existing_shuttle"] = null
// Status panel
data["shuttles"] = list()
for(var/i in mobile)
var/obj/docking_port/mobile/M = i
var/timeleft = M.timeLeft(1)
var/list/L = list()
L["name"] = M.name
L["id"] = M.id
L["timer"] = M.timer
L["timeleft"] = M.getTimerStr()
if (timeleft > 1 HOURS)
L["timeleft"] = "Infinity"
L["can_fast_travel"] = M.timer && timeleft >= 50
L["can_fly"] = TRUE
if(istype(M, /obj/docking_port/mobile/emergency))
L["can_fly"] = FALSE
else if(!M.destination)
L["can_fast_travel"] = FALSE
if (M.mode != SHUTTLE_IDLE)
L["mode"] = capitalize(M.mode)
L["status"] = M.getDbgStatusText()
if(M == existing_shuttle)
data["existing_shuttle"] = L
data["shuttles"] += list(L)
return data
/datum/controller/subsystem/shuttle/ui_act(action, params)
if(..())
return
var/mob/user = usr
// Preload some common parameters
var/shuttle_id = params["shuttle_id"]
var/datum/map_template/shuttle/S = SSmapping.shuttle_templates[shuttle_id]
switch(action)
if("select_template")
if(S)
existing_shuttle = getShuttle(S.port_id)
selected = S
. = TRUE
if("jump_to")
if(params["type"] == "mobile")
for(var/i in mobile)
var/obj/docking_port/mobile/M = i
if(M.id == params["id"])
user.forceMove(get_turf(M))
. = TRUE
break
if("fly")
for(var/i in mobile)
var/obj/docking_port/mobile/M = i
if(M.id == params["id"])
. = TRUE
M.admin_fly_shuttle(user)
break
if("fast_travel")
for(var/i in mobile)
var/obj/docking_port/mobile/M = i
if(M.id == params["id"] && M.timer && M.timeLeft(1) >= 50)
M.setTimer(50)
. = TRUE
message_admins("[key_name_admin(usr)] fast travelled [M]")
log_admin("[key_name(usr)] fast travelled [M]")
SSblackbox.record_feedback("text", "shuttle_manipulator", 1, "[M.name]")
break
if("preview")
if(S)
. = TRUE
unload_preview()
load_template(S)
if(preview_shuttle)
preview_template = S
user.forceMove(get_turf(preview_shuttle))
if("load")
if(existing_shuttle == backup_shuttle)
// TODO make the load button disabled
WARNING("The shuttle that the selected shuttle will replace \
is the backup shuttle. Backup shuttle is required to be \
intact for round sanity.")
else if(S)
. = TRUE
// If successful, returns the mobile docking port
var/obj/docking_port/mobile/mdp = action_load(S)
if(mdp)
user.forceMove(get_turf(mdp))
message_admins("[key_name_admin(usr)] loaded [mdp] with the shuttle manipulator.")
log_admin("[key_name(usr)] loaded [mdp] with the shuttle manipulator.</span>")
SSblackbox.record_feedback("text", "shuttle_manipulator", 1, "[mdp.name]")
@@ -1,21 +1,18 @@
/datum/component/personal_crafting/Initialize()
if(!ismob(parent))
return COMPONENT_INCOMPATIBLE
RegisterSignal(parent, COMSIG_MOB_CLIENT_LOGIN, .proc/create_mob_button)
if(ismob(parent))
RegisterSignal(parent, COMSIG_MOB_CLIENT_LOGIN, .proc/create_mob_button)
/datum/component/personal_crafting/proc/create_mob_button(mob/user, client/CL)
var/datum/hud/H = user.hud_used
var/obj/screen/craft/C = new()
C.icon = H.ui_style
H.static_inventory += C
if(!CL.prefs.widescreenpref)
C.screen_loc = ui_boxcraft
CL.screen += C
RegisterSignal(C, COMSIG_CLICK, .proc/component_ui_interact)
/datum/component/personal_crafting
var/busy
var/viewing_category = 1
var/viewing_category = 1 //typical powergamer starting on the Weapons tab
var/viewing_subcategory = 1
var/list/categories = list(
CAT_WEAPONRY = list(
@@ -58,9 +55,6 @@
var/display_craftable_only = FALSE
var/display_compact = TRUE
/* This is what procs do:
get_environment - gets a list of things accessable for crafting by user
get_surroundings - takes a list of things and makes a list of key-types to values-amounts of said type in the list
@@ -70,8 +64,6 @@
del_reqs - takes recipe and a user, loops over the recipes reqs var and tries to find everything in the list make by get_environment and delete it/add to parts list, then returns the said list
*/
/**
* Check that the contents of the recipe meet the requirements.
*
@@ -79,7 +71,7 @@
* R: The /datum/crafting_recipe being attempted.
* contents: List of items to search for R's reqs.
*/
/datum/component/personal_crafting/proc/check_contents(mob/user, datum/crafting_recipe/R, list/contents)
/datum/component/personal_crafting/proc/check_contents(atom/a, datum/crafting_recipe/R, list/contents)
var/list/item_instances = contents["instances"]
contents = contents["other"]
@@ -91,7 +83,7 @@
var/needed_amount = R.reqs[requirement_path]
for(var/content_item_path in contents)
// Right path and not blacklisted
if(!ispath(content_item_path, requirement_path) || R.blacklist.Find(requirement_path))
if(!ispath(content_item_path, requirement_path) || R.blacklist.Find(content_item_path))
continue
needed_amount -= contents[content_item_path]
@@ -113,32 +105,25 @@
if(contents[requirement_path] < R.chem_catalysts[requirement_path])
return FALSE
return R.check_requirements(user, requirements_list)
return R.check_requirements(a, requirements_list)
/datum/component/personal_crafting/proc/get_environment(mob/user)
/datum/component/personal_crafting/proc/get_environment(atom/a, list/blacklist = null, radius_range = 1)
. = list()
for(var/obj/item/I in user.held_items)
. += I
if(!isturf(user.loc))
return
var/list/L = block(get_step(user, SOUTHWEST), get_step(user, NORTHEAST))
for(var/A in L)
var/turf/T = A
if(T.Adjacent(user))
for(var/B in T)
var/atom/movable/AM = B
if(AM.flags_1 & HOLOGRAM_1)
continue
. += AM
for(var/slot in list(SLOT_R_STORE, SLOT_L_STORE))
. += user.get_item_by_slot(slot)
/datum/component/personal_crafting/proc/get_surroundings(mob/user)
if(!isturf(a.loc))
return
for(var/atom/movable/AM in range(radius_range, a))
if(AM.flags_1 & HOLOGRAM_1)
continue
. += AM
/datum/component/personal_crafting/proc/get_surroundings(atom/a)
. = list()
.["tool_behaviour"] = list()
.["other"] = list()
.["instances"] = list()
for(var/obj/item/I in get_environment(user))
for(var/obj/item/I in get_environment(a))
if(I.flags_1 & HOLOGRAM_1)
continue
if(.["instances"][I.type])
@@ -159,13 +144,13 @@
.["other"][A.type] += A.volume
.["other"][I.type] += 1
/datum/component/personal_crafting/proc/check_tools(mob/user, datum/crafting_recipe/R, list/contents)
/datum/component/personal_crafting/proc/check_tools(atom/a, datum/crafting_recipe/R, list/contents)
if(!R.tools.len)
return TRUE
var/list/possible_tools = list()
var/list/present_qualities = list()
present_qualities |= contents["tool_behaviour"]
for(var/obj/item/I in user.contents)
for(var/obj/item/I in a.contents)
if(istype(I, /obj/item/storage))
for(var/obj/item/SI in I.contents)
possible_tools += SI.type
@@ -190,43 +175,28 @@
return FALSE
return TRUE
/datum/component/personal_crafting/proc/construct_item(mob/user, datum/crafting_recipe/R)
var/list/contents = get_surroundings(user)
var/send_feedback = TRUE
if(check_contents(user, R, contents))
if(check_tools(user, R, contents))
if(do_after(user, R.time, target = user))
contents = get_surroundings(user)
if(!check_contents(user, R, contents))
return ", missing component."
if(!check_tools(user, R, contents))
return ", missing tool."
var/list/parts = del_reqs(R, user)
var/atom/movable/I = new R.result (get_turf(user.loc))
I.CheckParts(parts, R)
if(isitem(I))
if(isfood(I))
var/obj/item/reagent_containers/food/food_result = I
var/total_quality = 0
var/total_items = 0
for(var/obj/item/ingredient in parts)
var/obj/item/reagent_containers/food/food_ingredient = ingredient
total_items += 1
total_quality += food_ingredient.food_quality
if(total_items == 0)
food_result.adjust_food_quality(50)
else
food_result.adjust_food_quality(total_quality / total_items)
user.put_in_hands(I)
if(send_feedback)
SSblackbox.record_feedback("tally", "object_crafted", 1, I.type)
log_craft("[I] crafted by [user] at [loc_name(I.loc)]")
return FALSE
return "."
/datum/component/personal_crafting/proc/construct_item(atom/a, datum/crafting_recipe/R)
var/list/contents = get_surroundings(a)
var/send_feedback = 1
if(check_contents(a, R, contents))
if(check_tools(a, R, contents))
//If we're a mob we'll try a do_after; non mobs will instead instantly construct the item
if(ismob(a) && !do_after(a, R.time, target = a))
return "."
contents = get_surroundings(a)
if(!check_contents(a, R, contents))
return ", missing component."
if(!check_tools(a, R, contents))
return ", missing tool."
var/list/parts = del_reqs(R, a)
var/atom/movable/I = new R.result (get_turf(a.loc))
I.CheckParts(parts, R)
if(send_feedback)
SSblackbox.record_feedback("tally", "object_crafted", 1, I.type)
return I //Send the item back to whatever called this proc so it can handle whatever it wants to do with the new item
return ", missing tool."
return ", missing component."
/*Del reqs works like this:
Loop over reqs var of the recipe
@@ -251,7 +221,7 @@
del_reqs return the list of parts resulting object will receive as argument of CheckParts proc, on the atom level it will add them all to the contents, on all other levels it calls ..() and does whatever is needed afterwards but from contents list already
*/
/datum/component/personal_crafting/proc/del_reqs(datum/crafting_recipe/R, mob/user)
/datum/component/personal_crafting/proc/del_reqs(datum/crafting_recipe/R, atom/a)
var/list/surroundings
var/list/Deletion = list()
. = list()
@@ -260,7 +230,7 @@
main_loop:
for(var/A in R.reqs)
amt = R.reqs[A]
surroundings = get_environment(user)
surroundings = get_environment(a, R.blacklist)
surroundings -= Deletion
if(ispath(A, /datum/reagent))
var/datum/reagent/RG = new A
@@ -353,6 +323,7 @@
if(user == parent)
ui_interact(user)
//For the UI related things we're going to assume the user is a mob rather than typesetting it to an atom as the UI isn't generated if the parent is an atom
/datum/component/personal_crafting/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, datum/tgui/master_ui = null, datum/ui_state/state = GLOB.not_incapacitated_turf_state)
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
if(!ui)
@@ -362,10 +333,9 @@
cur_subcategory = subcats[1]
else
cur_subcategory = CAT_NONE
ui = new(user, src, ui_key, "personal_crafting", "Crafting Menu", 700, 800, master_ui, state)
ui = new(user, src, ui_key, "PersonalCrafting", "Crafting Menu", 700, 800, master_ui, state)
ui.open()
/datum/component/personal_crafting/ui_data(mob/user)
var/list/data = list()
data["busy"] = busy
@@ -417,23 +387,24 @@
data["crafting_recipes"] = crafting_recipes
return data
/datum/component/personal_crafting/ui_act(action, params)
if(..())
return
switch(action)
if("make")
var/mob/user = usr
var/datum/crafting_recipe/TR = locate(params["recipe"]) in GLOB.crafting_recipes
ui_interact(usr)
if(busy)
to_chat(usr, "<span class='warning'>You are already making something!</span>")
return
busy = TRUE
var/fail_msg = construct_item(usr, TR)
if(!fail_msg)
to_chat(usr, "<span class='notice'>[TR.name] constructed.</span>")
ui_interact(user)
var/atom/movable/result = construct_item(user, TR)
if(!istext(result)) //We made an item and didn't get a fail message
if(ismob(user) && isitem(result)) //In case the user is actually possessing a non mob like a machine
user.put_in_hands(result)
else
result.forceMove(user.drop_location())
to_chat(user, "<span class='notice'>[TR.name] constructed.</span>")
else
to_chat(usr, "<span class='warning'>Construction failed[fail_msg]</span>")
to_chat(user, "<span class='warning'>Construction failed[result]</span>")
busy = FALSE
if("toggle_recipes")
display_craftable_only = !display_craftable_only
+153
View File
@@ -0,0 +1,153 @@
///Global GPS_list. All GPS components get saved in here for easy reference.
GLOBAL_LIST_EMPTY(GPS_list)
///GPS component. Atoms that have this show up on gps. Pretty simple stuff.
/datum/component/gps
var/gpstag = "COM0"
var/tracking = TRUE
var/emped = FALSE
/datum/component/gps/Initialize(_gpstag = "COM0")
if(!isatom(parent))
return COMPONENT_INCOMPATIBLE
gpstag = _gpstag
GLOB.GPS_list += src
/datum/component/gps/Destroy()
GLOB.GPS_list -= src
return ..()
///GPS component subtype. Only gps/item's can be used to open the UI.
/datum/component/gps/item
var/updating = TRUE //Automatic updating of GPS list. Can be set to manual by user.
var/global_mode = TRUE //If disabled, only GPS signals of the same Z level are shown
/datum/component/gps/item/Initialize(_gpstag = "COM0", emp_proof = FALSE)
. = ..()
if(. == COMPONENT_INCOMPATIBLE || !isitem(parent))
return COMPONENT_INCOMPATIBLE
var/atom/A = parent
A.add_overlay("working")
A.name = "[initial(A.name)] ([gpstag])"
RegisterSignal(parent, COMSIG_ITEM_ATTACK_SELF, .proc/interact)
if(!emp_proof)
RegisterSignal(parent, COMSIG_ATOM_EMP_ACT, .proc/on_emp_act)
RegisterSignal(parent, COMSIG_PARENT_EXAMINE, .proc/on_examine)
RegisterSignal(parent, COMSIG_CLICK_ALT, .proc/on_AltClick)
///Called on COMSIG_ITEM_ATTACK_SELF
/datum/component/gps/item/proc/interact(datum/source, mob/user)
if(user)
ui_interact(user)
///Called on COMSIG_PARENT_EXAMINE
/datum/component/gps/item/proc/on_examine(datum/source, mob/user, list/examine_list)
examine_list += "<span class='notice'>Alt-click to switch it [tracking ? "off":"on"].</span>"
///Called on COMSIG_ATOM_EMP_ACT
/datum/component/gps/item/proc/on_emp_act(datum/source, severity)
emped = TRUE
var/atom/A = parent
A.cut_overlay("working")
A.add_overlay("emp")
addtimer(CALLBACK(src, .proc/reboot), 300, TIMER_UNIQUE|TIMER_OVERRIDE) //if a new EMP happens, remove the old timer so it doesn't reactivate early
SStgui.close_uis(src) //Close the UI control if it is open.
///Restarts the GPS after getting turned off by an EMP.
/datum/component/gps/item/proc/reboot()
emped = FALSE
var/atom/A = parent
A.cut_overlay("emp")
A.add_overlay("working")
///Calls toggletracking
/datum/component/gps/item/proc/on_AltClick(datum/source, mob/user)
toggletracking(user)
///Toggles the tracking for the gps
/datum/component/gps/item/proc/toggletracking(mob/user)
if(!user.canUseTopic(parent, BE_CLOSE))
return //user not valid to use gps
if(emped)
to_chat(user, "<span class='warning'>It's busted!</span>")
return
var/atom/A = parent
if(tracking)
A.cut_overlay("working")
to_chat(user, "<span class='notice'>[parent] is no longer tracking, or visible to other GPS devices.</span>")
tracking = FALSE
else
A.add_overlay("working")
to_chat(user, "<span class='notice'>[parent] is now tracking, and visible to other GPS devices.</span>")
tracking = TRUE
/datum/component/gps/item/ui_interact(mob/user, ui_key = "gps", datum/tgui/ui = null, force_open = FALSE, datum/tgui/master_ui = null, datum/ui_state/state = GLOB.default_state) // Remember to use the appropriate state.
if(emped)
to_chat(user, "<span class='hear'>[parent] fizzles weakly.</span>")
return
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
if(!ui)
// Variable window height, depending on how many GPS units there are
// to show, clamped to relatively safe range.
var/gps_window_height = clamp(325 + GLOB.GPS_list.len * 14, 325, 700)
ui = new(user, src, ui_key, "Gps", "Global Positioning System", 470, gps_window_height, master_ui, state) //width, height
ui.open()
ui.set_autoupdate(state = updating)
/datum/component/gps/item/ui_data(mob/user)
var/list/data = list()
data["power"] = tracking
data["tag"] = gpstag
data["updating"] = updating
data["globalmode"] = global_mode
if(!tracking || emped) //Do not bother scanning if the GPS is off or EMPed
return data
var/turf/curr = get_turf(parent)
data["currentArea"] = "[get_area_name(curr, TRUE)]"
data["currentCoords"] = "[curr.x], [curr.y], [curr.z]"
var/list/signals = list()
data["signals"] = list()
for(var/gps in GLOB.GPS_list)
var/datum/component/gps/G = gps
if(G.emped || !G.tracking || G == src)
continue
var/turf/pos = get_turf(G.parent)
if(!pos || !global_mode && pos.z != curr.z)
continue
var/list/signal = list()
signal["entrytag"] = G.gpstag //Name or 'tag' of the GPS
signal["coords"] = "[pos.x], [pos.y], [pos.z]"
if(pos.z == curr.z) //Distance/Direction calculations for same z-level only
signal["dist"] = max(get_dist(curr, pos), 0) //Distance between the src and remote GPS turfs
signal["degrees"] = round(Get_Angle(curr, pos)) //0-360 degree directional bearing, for more precision.
signals += list(signal) //Add this signal to the list of signals
data["signals"] = signals
return data
/datum/component/gps/item/ui_act(action, params)
if(..())
return
switch(action)
if("rename")
var/atom/parentasatom = parent
var/a = stripped_input(usr, "Please enter desired tag.", parentasatom.name, gpstag, 20)
if (!a)
return
gpstag = a
. = TRUE
parentasatom.name = "global positioning system ([gpstag])"
if("power")
toggletracking(usr)
. = TRUE
if("updating")
updating = !updating
. = TRUE
if("globalmode")
global_mode = !global_mode
. = TRUE
+2 -4
View File
@@ -140,9 +140,8 @@ GLOBAL_LIST_EMPTY(uplinks)
active = TRUE
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
if(!ui)
ui = new(user, src, ui_key, "uplink", name, 620, 580, master_ui, state)
ui = new(user, src, ui_key, "Uplink", name, 620, 580, master_ui, state)
ui.set_autoupdate(FALSE) // This UI is only ever opened by one person, and never is updated outside of user input.
ui.set_style("syndicate")
ui.open()
/datum/component/uplink/ui_host(mob/user)
@@ -157,8 +156,7 @@ GLOBAL_LIST_EMPTY(uplinks)
var/list/data = list()
data["telecrystals"] = telecrystals
data["lockable"] = lockable
data["compact_mode"] = compact_mode
data["compactMode"] = compact_mode
return data
/datum/component/uplink/ui_static_data(mob/user)
+1 -1
View File
@@ -9,7 +9,7 @@
/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)
if(!ui)
ui = new(user, src, ui_key, "spawners_menu", "Spawners Menu", 700, 600, master_ui, state)
ui = new(user, src, ui_key, "SpawnersMenu", "Spawners Menu", 700, 600, master_ui, state)
ui.open()
/datum/spawners_menu/ui_data(mob/user)
+2 -2
View File
@@ -214,8 +214,8 @@
/datum/wires/ui_interact(mob/user, ui_key = "wires", datum/tgui/ui = null, force_open = FALSE, \
datum/tgui/master_ui = null, datum/ui_state/state = GLOB.physical_state)
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
if(!ui)
ui = new(user, src, ui_key, "wires", "[holder.name] Wires", 350, 150 + wires.len * 30, master_ui, state)
if (!ui)
ui = new(user, src, ui_key, "Wires", "[holder.name] Wires", 350, 150 + wires.len * 30, master_ui, state)
ui.open()
/datum/wires/ui_data(mob/user)
+1 -1
View File
@@ -202,7 +202,7 @@
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
if(!ui)
ui = new(user, src, ui_key, "sleeper", name, 550, 700, master_ui, state)
ui = new(user, src, ui_key, "Sleeper", name, 550, 700, master_ui, state)
ui.open()
/obj/machinery/sleeper/ui_data()
+4 -6
View File
@@ -105,12 +105,10 @@ GLOBAL_LIST_EMPTY(announcement_systems)
/obj/machinery/announcement_system/ui_interact(mob/user)
. = ..()
if(!user.canUseTopic(src, !hasSiliconAccessInArea(user)))
return
if(stat & BROKEN)
visible_message("<span class='warning'>[src] buzzes.</span>", "<span class='italics'>You hear a faint buzz.</span>")
playsound(src.loc, 'sound/machines/buzz-two.ogg', 50, 1)
return
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
if(!ui)
ui = new(user, src, ui_key, "AutomatedAnnouncement", "Automated Announcement System", 500, 225, master_ui, state)
ui.open()
var/contents = "Arrival Announcement: <A href='?src=[REF(src)];ArrivalT-Topic=1'>([(arrivalToggle ? "On" : "Off")])</a><br>\n<A href='?src=[REF(src)];ArrivalTopic=1'>[arrival]</a><br><br>\n"
+1 -1
View File
@@ -56,7 +56,7 @@
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, "bank_machine", name, 320, 165, master_ui, state)
ui = new(user, src, ui_key, "BankMachine", name, 320, 165, master_ui, state)
ui.open()
/obj/machinery/computer/bank_machine/ui_data(mob/user)
+44 -1
View File
@@ -46,7 +46,7 @@
/obj/machinery/computer/operating/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = 0, datum/tgui/master_ui = null, datum/ui_state/state = GLOB.not_incapacitated_state)
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
if(!ui)
ui = new(user, src, ui_key, "operating_computer", name, 350, 470, master_ui, state)
ui = new(user, src, ui_key, "OperatingComputer", name, 350, 470, master_ui, state)
ui.open()
/obj/machinery/computer/operating/ui_data(mob/user)
@@ -108,6 +108,49 @@
))
else
data["patient"] = null
return data
switch(patient.stat)
if(CONSCIOUS)
data["patient"]["stat"] = "Conscious"
data["patient"]["statstate"] = "good"
if(SOFT_CRIT)
data["patient"]["stat"] = "Conscious"
data["patient"]["statstate"] = "average"
if(UNCONSCIOUS)
data["patient"]["stat"] = "Unconscious"
data["patient"]["statstate"] = "average"
if(DEAD)
data["patient"]["stat"] = "Dead"
data["patient"]["statstate"] = "bad"
data["patient"]["health"] = patient.health
data["patient"]["blood_type"] = patient.dna.blood_type
data["patient"]["maxHealth"] = patient.maxHealth
data["patient"]["minHealth"] = HEALTH_THRESHOLD_DEAD
data["patient"]["bruteLoss"] = patient.getBruteLoss()
data["patient"]["fireLoss"] = patient.getFireLoss()
data["patient"]["toxLoss"] = patient.getToxLoss()
data["patient"]["oxyLoss"] = patient.getOxyLoss()
data["procedures"] = list()
if(patient.surgeries.len)
for(var/datum/surgery/procedure in patient.surgeries)
var/datum/surgery_step/surgery_step = procedure.get_surgery_step()
var/chems_needed = surgery_step.get_chem_list()
var/alternative_step
var/alt_chems_needed = ""
if(surgery_step.repeatable)
var/datum/surgery_step/next_step = procedure.get_surgery_next_step()
if(next_step)
alternative_step = capitalize(next_step.name)
alt_chems_needed = next_step.get_chem_list()
else
alternative_step = "Finish operation"
data["procedures"] += list(list(
"name" = capitalize("[parse_zone(procedure.location)] [procedure.name]"),
"next_step" = capitalize(surgery_step.name),
"chems_needed" = chems_needed,
"alternative_step" = alternative_step,
"alt_chems_needed" = alt_chems_needed
))
return data
/obj/machinery/computer/operating/ui_act(action, params)
+8 -2
View File
@@ -8,6 +8,8 @@
icon_keyboard = "tech_key"
icon_screen = "ai-fixer"
light_color = LIGHT_COLOR_PINK
ui_x = 370
ui_y = 360
/obj/machinery/computer/aifixer/attackby(obj/I, mob/user, params)
if(occupier && istype(I, /obj/item/screwdriver))
@@ -18,8 +20,12 @@
else
return ..()
/obj/machinery/computer/aifixer/ui_interact(mob/user)
. = ..()
/obj/machinery/computer/aifixer/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)
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
if(!ui)
ui = new(user, src, ui_key, "AiRestorer", name, ui_x, ui_y, master_ui, state)
ui.open()
var/dat = ""
+1 -1
View File
@@ -23,7 +23,7 @@
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, "atmos_alert", name, 350, 300, master_ui, state)
ui = new(user, src, ui_key, "AtmosAlertConsole", name, 350, 300, master_ui, state)
ui.open()
/obj/machinery/computer/atmos_alert/ui_data(mob/user)
@@ -127,7 +127,7 @@ GLOBAL_LIST_EMPTY(atmos_air_controllers)
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, "atmos_control", name, ui_x, ui_y, master_ui, state)
ui = new(user, src, ui_key, "AtmosControlConsole", name, ui_x, ui_y, master_ui, state)
ui.open()
/obj/machinery/computer/atmos_control/ui_data(mob/user)
@@ -269,7 +269,7 @@ GLOBAL_LIST_EMPTY(atmos_air_controllers)
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, "atmos_control", name, ui_x, ui_y, master_ui, state)
ui = new(user, src, ui_key, "AtmosControlConsole", name, ui_x, ui_y, master_ui, state)
ui.open()
/obj/machinery/computer/atmos_control/tank/ui_data(mob/user)
+175 -95
View File
@@ -4,109 +4,166 @@
icon_screen = "cameras"
icon_keyboard = "security_key"
circuit = /obj/item/circuitboard/computer/security
var/last_pic = 1
var/list/network = list("ss13")
var/list/watchers = list() //who's using the console, associated with the camera they're on.
light_color = LIGHT_COLOR_RED
ui_x = 870
ui_y = 708
var/list/network = list("ss13")
var/obj/machinery/camera/active_camera
var/list/concurrent_users = list()
// Stuff needed to render the map
var/map_name
var/const/default_map_size = 15
var/obj/screen/cam_screen
var/obj/screen/plane_master/lighting/cam_plane_master
var/obj/screen/background/cam_background
/obj/machinery/computer/security/Initialize()
. = ..()
// Map name has to start and end with an A-Z character,
// and definitely NOT with a square bracket or even a number.
// I wasted 6 hours on this. :agony:
map_name = "camera_console_[REF(src)]_map"
// Convert networks to lowercase
for(var/i in network)
network -= i
network += lowertext(i)
/obj/machinery/computer/security/check_eye(mob/user)
if(!can_interact(user) || !(user in watchers) || !watchers[user])
user.unset_machine()
return
var/obj/machinery/camera/C = watchers[user]
if(!C.can_use())
user.unset_machine()
return
/obj/machinery/computer/security/on_unset_machine(mob/user)
watchers.Remove(user)
user.reset_perspective(null)
// Initialize map objects
cam_screen = new
cam_screen.name = "screen"
cam_screen.assigned_map = map_name
cam_screen.del_on_map_removal = FALSE
cam_screen.screen_loc = "[map_name]:1,1"
cam_plane_master = new
cam_plane_master.name = "plane_master"
cam_plane_master.assigned_map = map_name
cam_plane_master.del_on_map_removal = FALSE
cam_plane_master.screen_loc = "[map_name]:CENTER"
cam_background = new
cam_background.assigned_map = map_name
cam_background.del_on_map_removal = FALSE
/obj/machinery/computer/security/Destroy()
if(watchers.len)
for(var/mob/M in watchers)
M.unset_machine() //to properly reset the view of the users if the console is deleted.
qdel(cam_screen)
qdel(cam_plane_master)
qdel(cam_background)
return ..()
/obj/machinery/computer/security/can_interact(mob/user)
if((!hasSiliconAccessInArea(user) && !Adjacent(user)) || is_blind(user) || !in_view_range(user, src))
return FALSE
return ..()
/obj/machinery/computer/security/connect_to_shuttle(obj/docking_port/mobile/port, obj/docking_port/stationary/dock, idnum, override=FALSE)
for(var/i in network)
network -= i
network += "[idnum][i]"
/obj/machinery/computer/security/interact(mob/user, special_state)
/obj/machinery/computer/security/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)
// Update UI
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
// Show static if can't use the camera
if(!active_camera?.can_use())
show_camera_static()
if(!ui)
var/user_ref = REF(user)
var/is_living = isliving(user)
// Ghosts shouldn't count towards concurrent users, which produces
// an audible terminal_on click.
if(is_living)
concurrent_users += user_ref
// Turn on the console
if(length(concurrent_users) == 1 && is_living)
playsound(src, 'sound/machines/terminal_on.ogg', 25, FALSE)
use_power(active_power_usage)
// Register map objects
user.client.register_map_obj(cam_screen)
user.client.register_map_obj(cam_plane_master)
user.client.register_map_obj(cam_background)
// Open UI
ui = new(user, src, ui_key, "CameraConsole", name, ui_x, ui_y, master_ui, state)
ui.open()
/obj/machinery/computer/security/ui_data()
var/list/data = list()
data["network"] = network
data["activeCamera"] = null
if(active_camera)
data["activeCamera"] = list(
name = active_camera.c_tag,
status = active_camera.status,
)
return data
/obj/machinery/computer/security/ui_static_data()
var/list/data = list()
data["mapRef"] = map_name
var/list/cameras = get_available_cameras()
data["cameras"] = list()
for(var/i in cameras)
var/obj/machinery/camera/C = cameras[i]
data["cameras"] += list(list(
name = C.c_tag,
))
return data
/obj/machinery/computer/security/ui_act(action, params)
. = ..()
if (ismob(user) && !isliving(user)) // ghosts don't need cameras
return
if (!network)
stack_trace("No camera network")
user.unset_machine()
return FALSE
if (!(islist(network)))
stack_trace("Camera network is not a list")
user.unset_machine()
return FALSE
var/list/camera_list = get_available_cameras()
if(!(user in watchers))
for(var/Num in camera_list)
var/obj/machinery/camera/CAM = camera_list[Num]
if(istype(CAM) && CAM.can_use())
watchers[user] = CAM //let's give the user the first usable camera, and then let him change to the camera he wants.
break
if(!(user in watchers))
user.unset_machine() // no usable camera on the network, we disconnect the user from the computer.
return FALSE
playsound(src, 'sound/machines/terminal_prompt.ogg', 25, 0)
use_camera_console(user)
/obj/machinery/computer/security/proc/use_camera_console(mob/user)
var/list/camera_list = get_available_cameras()
var/t = input(user, "Which camera should you change to?") as null|anything in camera_list
if(!src || user.machine != src) //while we were choosing we got disconnected from our computer or are using another machine.
return
if(!t || t == "Cancel")
user.unset_machine()
playsound(src, 'sound/machines/terminal_off.ogg', 25, 0)
if(.)
return
var/obj/machinery/camera/C = camera_list[t]
if(action == "switch_camera")
var/c_tag = params["name"]
var/list/cameras = get_available_cameras()
var/obj/machinery/camera/C = cameras[c_tag]
active_camera = C
playsound(src, get_sfx("terminal_type"), 25, FALSE)
if(!C || !C.can_use() || !can_interact(user))
user.unset_machine()
return FALSE
// Show static if can't use the camera
if(!active_camera?.can_use())
show_camera_static()
return TRUE
playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 25, 0)
if(isAI(user))
var/mob/living/silicon/ai/A = user
A.eyeobj.setLoc(get_turf(C))
A.client.eye = A.eyeobj
else
user.reset_perspective(C)
user.overlay_fullscreen("flash", /obj/screen/fullscreen/flash/static)
user.clear_fullscreen("flash", 5)
watchers[user] = C
use_power(50)
addtimer(CALLBACK(src, .proc/use_camera_console, user), 5)
var/list/visible_turfs = list()
for(var/turf/T in (C.isXRay() \
? range(C.view_range, C) \
: view(C.view_range, C)))
visible_turfs += T
//returns the list of cameras accessible from this computer
var/list/bbox = get_bbox_of_atoms(visible_turfs)
var/size_x = bbox[3] - bbox[1] + 1
var/size_y = bbox[4] - bbox[2] + 1
cam_screen.vis_contents = visible_turfs
cam_background.icon_state = "clear"
cam_background.fill_rect(1, 1, size_x, size_y)
return TRUE
/obj/machinery/computer/security/ui_close(mob/user)
var/user_ref = REF(user)
var/is_living = isliving(user)
// Living creature or not, we remove you anyway.
concurrent_users -= user_ref
// Unregister map objects
user.client.clear_map(map_name)
// Turn off the console
if(length(concurrent_users) == 0 && is_living)
active_camera = null
playsound(src, 'sound/machines/terminal_off.ogg', 25, FALSE)
use_power(0)
/obj/machinery/computer/security/proc/show_camera_static()
cam_screen.vis_contents.Cut()
cam_background.icon_state = "scanline2"
cam_background.fill_rect(1, 1, default_map_size, default_map_size)
// Returns the list of cameras accessible from this computer
/obj/machinery/computer/security/proc/get_available_cameras()
var/list/L = list()
for (var/obj/machinery/camera/C in GLOB.cameranet.cameras)
if((is_away_level(z) || is_away_level(C.z)) && (C.z != z))//if on away mission, can only receive feed from same z_level cameras
continue
L.Add(C)
camera_sort(L)
var/list/D = list()
D["Cancel"] = "Cancel"
for(var/obj/machinery/camera/C in L)
if(!C.network)
stack_trace("Camera in a cameranet has no camera network")
@@ -114,9 +171,9 @@
if(!(islist(C.network)))
stack_trace("Camera in a cameranet has a non-list camera network")
continue
var/list/tempnetwork = C.network&network
var/list/tempnetwork = C.network & network
if(tempnetwork.len)
D["[C.c_tag][(C.status ? null : " (Deactivated)")]"] = C
D["[C.c_tag]"] = C
return D
// SECURITY MONITORS
@@ -127,7 +184,6 @@
icon_state = "television"
icon_keyboard = null
icon_screen = "detective_tv"
clockwork = TRUE //it'd look weird
pass_flags = PASSTABLE
/obj/machinery/computer/security/mining
@@ -145,7 +201,7 @@
circuit = /obj/item/circuitboard/computer/research
/obj/machinery/computer/security/hos
name = "Head of Security's camera console"
name = "\improper Head of Security's camera console"
desc = "A custom security console with added access to the labor camp network."
network = list("ss13", "labor")
circuit = null
@@ -157,7 +213,7 @@
circuit = null
/obj/machinery/computer/security/qm
name = "Quartermaster's camera console"
name = "\improper Quartermaster's camera console"
desc = "A console with access to the mining, auxillary base and vault camera networks."
network = list("mine", "auxbase", "vault")
circuit = null
@@ -169,10 +225,10 @@
desc = "Used for watching an empty arena."
icon = 'icons/obj/stationobjs.dmi'
icon_state = "telescreen"
layer = SIGN_LAYER
network = list("thunder")
density = FALSE
circuit = null
clockwork = TRUE //it'd look very weird
light_power = 0
/obj/machinery/computer/security/telescreen/update_icon_state()
@@ -184,38 +240,62 @@
name = "entertainment monitor"
desc = "Damn, they better have the /tg/ channel on these things."
icon = 'icons/obj/status_display.dmi'
icon_state = "entertainment"
icon_state = "entertainment_blank"
network = list("thunder")
density = FALSE
circuit = null
interaction_flags_atom = NONE // interact() is called by BigClick()
var/icon_state_off = "entertainment_blank"
var/icon_state_on = "entertainment"
/obj/machinery/computer/security/telescreen/entertainment/Initialize()
. = ..()
RegisterSignal(src, COMSIG_CLICK, .proc/BigClick)
// Bypass clickchain to allow humans to use the telescreen from a distance
/obj/machinery/computer/security/telescreen/entertainment/proc/BigClick()
interact(usr)
/obj/machinery/computer/security/telescreen/entertainment/proc/notify(on)
if(on && icon_state == icon_state_off)
say(pick(
"Feats of bravery live now at the thunderdome!",
"Two enter, one leaves! Tune in now!",
"Violence like you've never seen it before!",
"Spears! Camera! Action! LIVE NOW!"))
icon_state = icon_state_on
else
icon_state = icon_state_off
/obj/machinery/computer/security/telescreen/rd
name = "Research Director's telescreen"
name = "\improper Research Director's telescreen"
desc = "Used for watching the AI and the RD's goons from the safety of his office."
network = list("rd", "aicore", "aiupload", "minisat", "xeno", "test")
/obj/machinery/computer/security/telescreen/circuitry
name = "circuitry telescreen"
desc = "Used for watching the other eggheads from the safety of the circuitry lab."
/obj/machinery/computer/security/telescreen/research
name = "research telescreen"
desc = "A telescreen with access to the research division's camera network."
network = list("rd")
/obj/machinery/computer/security/telescreen/ce
name = "Chief Engineer's telescreen"
name = "\improper Chief Engineer's telescreen"
desc = "Used for watching the engine, telecommunications and the minisat."
network = list("engine", "singularity", "tcomms", "minisat")
/obj/machinery/computer/security/telescreen/cmo
name = "Chief Medical Officer's telescreen"
name = "\improper Chief Medical Officer's telescreen"
desc = "A telescreen with access to the medbay's camera network."
network = list("medbay")
/obj/machinery/computer/security/telescreen/vault
name = "Vault monitor"
name = "vault monitor"
desc = "A telescreen that connects to the vault's camera network."
network = list("vault")
/obj/machinery/computer/security/telescreen/toxins
name = "Bomb test site monitor"
name = "bomb test site monitor"
desc = "A telescreen that connects to the bomb test site's camera."
network = list("toxin")
network = list("toxins")
/obj/machinery/computer/security/telescreen/engine
name = "engine monitor"
@@ -248,6 +328,6 @@
network = list("minisat")
/obj/machinery/computer/security/telescreen/aiupload
name = "AI upload monitor"
name = "\improper AI upload monitor"
desc = "A telescreen that connects to the AI upload's camera network."
network = list("aiupload")
+1 -1
View File
@@ -80,7 +80,7 @@ GLOBAL_DATUM_INIT(crewmonitor, /datum/crewmonitor, new)
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, "crew", "crew monitor", 800, 600 , master_ui, state)
ui = new(user, src, ui_key, "CrewConsole", "crew monitor", 800, 600 , master_ui, state)
ui.open()
/datum/crewmonitor/proc/show(mob/M, source)
+3 -13
View File
@@ -441,19 +441,9 @@
var/location = viable_occupant.dna.mutation_index.Find(mutation) //We do this because we dont want people using sysexp or similair tools to just read the mutations.
if(!location) //Do this only when needed, dont make a list with mutations for every iteration if you dont need to
var/list/mutations = get_mutation_list(TRUE)
if(mutation in mutations)
location = mutations.Find(mutation)
if(mutation == current_mutation)
class = "selected"
if(location > DNA_MUTATION_BLOCKS)
temp_html += "<a class='clean' href='?src=[REF(src)];task=inspect;num=[location];'><img class='[class]' src='dna_extra.gif' width = '65' alt='Extra Mutation'></a>"
else if(mutation in stored_research.discovered_mutations)
temp_html += "<a class='clean' href='?src=[REF(src)];task=inspect;num=[location];'><img class='[class]' src='dna_discovered.gif' width = '65' alt='Discovered Mutation'></a>"
else
temp_html += "<a class='clean' clean href='?src=[REF(src)];task=inspect;num=[location];'><img class='[class]' src='dna_undiscovered.gif' width = '65' alt=Undiscovered Mutation'></a>"
return temp_html
if(!ui)
ui = new(user, src, ui_key, "DnaConsole", name, 539, 710, master_ui, state)
ui.open()
/obj/machinery/computer/scan_consolenew/proc/display_sequence(mutation, storage_slot) //Storage slot is for when viewing from the stored mutations
var/temp_html = ""
@@ -56,7 +56,7 @@
/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 = new(user, src, ui_key, "LaunchpadConsole", name, ui_x, ui_y, master_ui, state)
ui.open()
/obj/machinery/computer/launchpad/ui_data(mob/user)
@@ -25,7 +25,7 @@
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, "gulag_console", name, ui_x, ui_y, master_ui, state)
ui = new(user, src, ui_key, "GulagTeleporterConsole", name, ui_x, ui_y, master_ui, state)
ui.open()
/obj/machinery/computer/prisoner/gulag_teleporter_computer/ui_data(mob/user)
+21 -8
View File
@@ -8,6 +8,8 @@
var/temp = null
light_color = LIGHT_COLOR_PINK
ui_x = 500
ui_y = 460
/obj/machinery/computer/robotics/proc/can_control(mob/user, mob/living/silicon/robot/R)
if(!istype(R))
@@ -25,14 +27,25 @@
return FALSE
return TRUE
/obj/machinery/computer/robotics/ui_interact(mob/user)
. = ..()
if (src.z > 6)
to_chat(user, "<span class='boldannounce'>Unable to establish a connection</span>: \black You're too far away from the station!")
return
user.set_machine(src)
var/dat
var/robots = 0
/obj/machinery/computer/robotics/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)
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
if(!ui)
ui = new(user, src, ui_key, "RoboticsControlConsole", name, ui_x, ui_y, master_ui, state)
ui.open()
/obj/machinery/computer/robotics/ui_data(mob/user)
var/list/data = list()
data["can_hack"] = FALSE
if(issilicon(user))
var/mob/living/silicon/S = user
if(S.hack_software)
data["can_hack"] = TRUE
else if(IsAdminGhost(user))
data["can_hack"] = TRUE
data["cyborgs"] = list()
for(var/mob/living/silicon/robot/R in GLOB.silicon_mobs)
if(!can_control(user, R))
continue
@@ -20,7 +20,7 @@
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, "station_alert", name, 325, 500, master_ui, state)
ui = new(user, src, ui_key, "StationAlertConsole", name, 325, 500, master_ui, state)
ui.open()
/obj/machinery/computer/station_alert/ui_data(mob/user)
+1 -1
View File
@@ -38,7 +38,7 @@ obj/machinery/computer/teleporter/ui_interact(mob/user, ui_key = "main", datum/t
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, "teleporter", name, ui_x, ui_y, master_ui, state)
ui = new(user, src, ui_key, "Teleporter", name, ui_x, ui_y, master_ui, state)
ui.open()
/obj/machinery/computer/teleporter/ui_data(mob/user)
+1 -1
View File
@@ -1434,7 +1434,7 @@
datum/tgui/master_ui = null, datum/ui_state/state = GLOB.default_state)
SStgui.try_update_ui(user, src, ui_key, ui, force_open)
if(!ui)
ui = new(user, src, ui_key, "ai_airlock", name, 500, 390, master_ui, state)
ui = new(user, src, ui_key, "AiAirlock", name, 500, 390, master_ui, state)
ui.open()
return TRUE
@@ -14,7 +14,7 @@
datum/tgui/master_ui = null, datum/ui_state/state = GLOB.hands_state)
SStgui.try_update_ui(user, src, ui_key, ui, force_open)
if(!ui)
ui = new(user, src, ui_key, "airlock_electronics", name, 420, 485, master_ui, state)
ui = new(user, src, ui_key, "AirlockElectronics", name, 420, 485, master_ui, state)
ui.open()
/obj/item/electronics/airlock/ui_data()
+1 -1
View File
@@ -143,7 +143,7 @@
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, "brig_timer", name, 300, 138, master_ui, state)
ui = new(user, src, ui_key, "BrigTimer", name, 300, 138, master_ui, state)
ui.open()
//icon update function
+1 -1
View File
@@ -31,7 +31,7 @@
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, "gulag_item_reclaimer", name, 300, 400, master_ui, state)
ui = new(user, src, ui_key, "GulagItemReclaimer", name, 300, 400, master_ui, state)
ui.open()
/obj/machinery/gulag_item_reclaimer/ui_data(mob/user)
+1 -2
View File
@@ -285,8 +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)
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
if(!ui)
ui = new(user, src, ui_key, "launchpad_remote", "Briefcase Launchpad Remote", 300, 240, master_ui, state) //width, height
ui.set_style("syndicate")
ui = new(user, src, ui_key, "LaunchpadRemote", "Briefcase Launchpad Remote", 300, 240, master_ui, state) //width, height
ui.open()
ui.set_autoupdate(TRUE)
+1 -1
View File
@@ -170,7 +170,7 @@
datum/tgui/master_ui = null, datum/ui_state/state = GLOB.physical_state)
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
if(!ui)
ui = new(user, src, ui_key, "space_heater", name, 400, 305, master_ui, state)
ui = new(user, src, ui_key, "SpaceHeater", name, 400, 305, master_ui, state)
ui.open()
/obj/machinery/space_heater/ui_data()
+1 -1
View File
@@ -383,7 +383,7 @@
datum/tgui/master_ui = null, datum/ui_state/state = GLOB.notcontained_state)
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
if(!ui)
ui = new(user, src, ui_key, "suit_storage_unit", name, 400, 305, master_ui, state)
ui = new(user, src, ui_key, "SuitStorageUnit", name, 400, 305, master_ui, state)
ui.open()
/obj/machinery/suit_storage_unit/ui_data()
+1 -1
View File
@@ -84,7 +84,7 @@
/obj/machinery/computer/mech_bay_power_console/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)
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
if(!ui)
ui = new(user, src, ui_key, "mech_bay_power_console", "Mech Bay Power Control Console", 400, 200, master_ui, state)
ui = new(user, src, ui_key, "MechBayPowerConsole", "Mech Bay Power Control Console", 400, 200, master_ui, state)
ui.open()
/obj/machinery/computer/mech_bay_power_console/ui_act(action, params)
+9 -16
View File
@@ -8,22 +8,15 @@
var/list/located = list()
var/screen = 0
var/stored_data
/obj/machinery/computer/mecha/ui_interact(mob/user)
. = ..()
var/dat = "<html><head><meta http-equiv='Content-Type' content='text/html; charset=UTF-8'><title>[src.name]</title><style>h3 {margin: 0px; padding: 0px;}</style></head><body>"
if(screen == 0)
dat += "<h3>Tracking beacons data</h3>"
var/list/trackerlist = list()
for(var/obj/mecha/MC in GLOB.mechas_list)
trackerlist += MC.trackers
for(var/obj/item/mecha_parts/mecha_tracking/TR in trackerlist)
var/answer = TR.get_mecha_info()
if(answer)
dat += {"<hr>[answer]<br/>
<a href='?src=[REF(src)];send_message=[REF(TR)]'>Send message</a><br/>
<a href='?src=[REF(src)];get_log=[REF(TR)]'>Show exosuit log</a><br/>
[TR.recharging?"Recharging EMP Pulse...<br>":"<a style='color: #f00;' href='?src=[REF(src)];shock=[REF(TR)]'>(EMP Pulse)</a><br>"]"}
ui_x = 500
ui_y = 500
/obj/machinery/computer/mecha/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)
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
if(!ui)
ui = new(user, src, ui_key, "ExosuitControlConsole", name, ui_x, ui_y, master_ui, state)
ui.open()
if(screen==1)
dat += "<h3>Log contents</h3>"
+1 -1
View File
@@ -249,7 +249,7 @@ GLOBAL_LIST_INIT(transit_tube_recipes, list(
var/datum/asset/assets = get_asset_datum(/datum/asset/spritesheet/pipes)
assets.send(user)
ui = new(user, src, ui_key, "rpd", name, 425, 472, master_ui, state)
ui = new(user, src, ui_key, "RapidPipeDispenser", name, 425, 515, master_ui, state)
ui.open()
/obj/item/pipe_dispenser/ui_data(mob/user)
+1 -1
View File
@@ -147,7 +147,7 @@
SStgui.try_update_ui(user, src, ui_key, ui, force_open)
if(!ui)
ui = new(user, src, ui_key, "crayon", name, 600, 600,
ui = new(user, src, ui_key, "Crayon", name, 600, 600,
master_ui, state)
ui.open()
+1 -1
View File
@@ -58,7 +58,7 @@
datum/tgui/master_ui = null, datum/ui_state/state = GLOB.hands_state)
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
if(!ui)
ui = new(user, src, ui_key, "intellicard", name, 500, 500, master_ui, state)
ui = new(user, src, ui_key, "Intellicard", name, 500, 500, master_ui, state)
ui.open()
/obj/item/aicard/ui_data()
@@ -16,6 +16,9 @@
var/on = TRUE
var/shock_cooldown = FALSE
var/ui_x = 260
var/ui_y = 137
/obj/item/electropack/suicide_act(mob/living/carbon/user)
user.visible_message("<span class='suicide'>[user] hooks [user.p_them()]self to the electropack and spams the trigger! It looks like [user.p_theyre()] trying to commit suicide!</span>")
return (FIRELOSS)
@@ -128,22 +131,12 @@
if(!ishuman(user))
return
user.set_machine(src)
var/dat = {"
<TT>
Turned [on ? "On" : "Off"] - <A href='?src=[REF(src)];set=power'>Toggle</A><BR>
<B>Frequency/Code</B> for electropack:<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>
</TT>"}
user << browse(dat, "window=radio")
onclose(user, "radio")
return
/obj/item/electropack/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, \
datum/tgui/master_ui = null, datum/ui_state/state = GLOB.hands_state)
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
if(!ui)
ui = new(user, src, ui_key, "Electropack", name, ui_x, ui_y, master_ui, state)
ui.open()
/obj/item/electropack/shockcollar
name = "shock collar"
@@ -119,7 +119,7 @@
ui_height += 6 + channels.len * 21
else
ui_height += 24
ui = new(user, src, ui_key, "radio", name, ui_width, ui_height, master_ui, state)
ui = new(user, src, ui_key, "Radio", name, ui_width, ui_height, master_ui, state)
ui.open()
/obj/item/radio/ui_data(mob/user)
@@ -76,6 +76,9 @@ effective or pretty fucking useless.
var/used = 0 // is it cooling down?
var/stealth = FALSE
var/ui_x = 320
var/ui_y = 335
/obj/item/healthanalyzer/rad_laser/attack(mob/living/M, mob/living/user)
if(!stealth || !irradiate)
..()
@@ -111,7 +114,12 @@ effective or pretty fucking useless.
ui_interact(user)
/obj/item/healthanalyzer/rad_laser/ui_interact(mob/user)
. = ..()
/obj/item/healthanalyzer/rad_laser/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, \
datum/tgui/master_ui = null, datum/ui_state/state = GLOB.hands_state)
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
if(!ui)
ui = new(user, src, ui_key, "RadioactiveMicrolaser", "Radioactive Microlaser", ui_x, ui_y, master_ui, state)
ui.open()
var/dat = "Irradiation: <A href='?src=[REF(src)];rad=1'>[irradiate ? "On" : "Off"]</A><br>"
dat += "Stealth Mode (NOTE: Deactivates automatically while Irradiation is off): <A href='?src=[REF(src)];stealthy=[TRUE]'>[stealth ? "On" : "Off"]</A><br>"
@@ -13,6 +13,8 @@
var/mob/attacher = null
var/valve_open = FALSE
var/toggle = 1
var/ui_x = 310
var/ui_y = 320
/obj/item/transfer_valve/IsAssemblyHolder()
return TRUE
@@ -235,3 +237,52 @@
// eventually maybe have it update icon to show state (timer, prox etc.) like old bombs
/obj/item/transfer_valve/proc/c_state()
return
/obj/item/transfer_valve/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, \
datum/tgui/master_ui = null, datum/ui_state/state = GLOB.hands_state)
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
if(!ui)
ui = new(user, src, ui_key, "TransferValve", name, ui_x, ui_y, master_ui, state)
ui.open()
/obj/item/transfer_valve/ui_data(mob/user)
var/list/data = list()
data["tank_one"] = tank_one
data["tank_two"] = tank_two
data["attached_device"] = attached_device
data["valve"] = valve_open
return data
/obj/item/transfer_valve/ui_act(action, params)
if(..())
return
switch(action)
if("tankone")
if(tank_one)
split_gases()
valve_open = FALSE
tank_one.forceMove(drop_location())
tank_one = null
. = TRUE
if("tanktwo")
if(tank_two)
split_gases()
valve_open = FALSE
tank_two.forceMove(drop_location())
tank_two = null
. = TRUE
if("toggle")
toggle_valve()
. = TRUE
if("device")
if(attached_device)
attached_device.attack_self(usr)
. = TRUE
if("remove_device")
if(attached_device)
attached_device.on_detach()
attached_device = null
. = TRUE
update_icon()
+1 -1
View File
@@ -196,7 +196,7 @@
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
if(!ui)
ui = new(user, src, ui_key, "eightball", name, 400, 600, master_ui, state)
ui = new(user, src, ui_key, "EightBallVote", name, 400, 600, master_ui, state)
ui.open()
/obj/item/toy/eightball/haunted/ui_data(mob/user)
+1 -1
View File
@@ -159,7 +159,7 @@
datum/tgui/master_ui = null, datum/ui_state/state = GLOB.hands_state)
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
if(!ui)
ui = new(user, src, ui_key, "tanks", name, 400, 120, master_ui, state)
ui = new(user, src, ui_key, "Tank", name, 400, 120, master_ui, state)
ui.open()
/obj/item/tank/ui_data(mob/user)
+343 -76
View File
@@ -35,101 +35,368 @@
else
painting = null
//////////////
// CANVASES //
//////////////
#define AMT_OF_CANVASES 4 //Keep this up to date or shit will break.
//To safe memory on making /icons we cache the blanks..
GLOBAL_LIST_INIT(globalBlankCanvases, new(AMT_OF_CANVASES))
/obj/item/canvas
name = "canvas"
desc = "Draw out your soul on this canvas!"
icon = 'icons/obj/artstuff.dmi'
icon_state = "11x11"
resistance_flags = FLAMMABLE
var/whichGlobalBackup = 1 //List index
var/width = 11
var/height = 11
var/list/grid
var/canvas_color = "#ffffff" //empty canvas color
var/ui_x = 400
var/ui_y = 400
var/used = FALSE
var/painting_name //Painting name, this is set after framing.
var/finalized = FALSE //Blocks edits
var/author_ckey
var/icon_generated = FALSE
var/icon/generated_icon
/obj/item/canvas/nineteenXnineteen
icon_state = "19x19"
whichGlobalBackup = 2
// Painting overlay offset when framed
var/framed_offset_x = 11
var/framed_offset_y = 10
/obj/item/canvas/twentythreeXnineteen
icon_state = "23x19"
whichGlobalBackup = 3
pixel_x = 10
pixel_y = 9
/obj/item/canvas/twentythreeXtwentythree
icon_state = "23x23"
whichGlobalBackup = 4
//HEY YOU
//ARE YOU READING THE CODE FOR CANVASES?
//ARE YOU AWARE THEY CRASH HALF THE SERVER WHEN SOMEONE DRAWS ON THEM...
//...AND NOBODY CAN FIGURE OUT WHY?
//THEN GO ON BRAVE TRAVELER
//TRY TO FIX THEM AND REMOVE THIS CODE
/obj/item/canvas/Initialize()
..()
return INITIALIZE_HINT_QDEL //Delete on creation
. = ..()
reset_grid()
//Find the right size blank canvas
/obj/item/canvas/proc/getGlobalBackup()
. = null
if(GLOB.globalBlankCanvases[whichGlobalBackup])
. = GLOB.globalBlankCanvases[whichGlobalBackup]
else
var/icon/I = icon(initial(icon),initial(icon_state))
GLOB.globalBlankCanvases[whichGlobalBackup] = I
. = I
/obj/item/canvas/proc/reset_grid()
grid = new/list(width,height)
for(var/x in 1 to width)
for(var/y in 1 to height)
grid[x][y] = canvas_color
/obj/item/canvas/attack_self(mob/user)
. = ..()
ui_interact(user)
/obj/item/canvas/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)
//One pixel increments
/obj/item/canvas/attackby(obj/item/I, mob/user, params)
//Click info
var/list/click_params = params2list(params)
var/pixX = text2num(click_params["icon-x"])
var/pixY = text2num(click_params["icon-y"])
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
if(!ui)
ui = new(user, src, ui_key, "Canvas", name, ui_x, ui_y, master_ui, state)
ui.set_autoupdate(FALSE)
ui.open()
//Should always be true, otherwise you didn't click the object, but let's check because SS13~
if(!click_params || !click_params["icon-x"] || !click_params["icon-y"])
return
//Cleaning one pixel with a soap or rag
if(istype(I, /obj/item/soap) || istype(I, /obj/item/reagent_containers/rag))
//Pixel info created only when needed
var/icon/masterpiece = icon(icon,icon_state)
var/thePix = masterpiece.GetPixel(pixX,pixY)
var/icon/Ico = getGlobalBackup()
if(!Ico)
qdel(masterpiece)
return
var/theOriginalPix = Ico.GetPixel(pixX,pixY)
if(thePix != theOriginalPix) //colour changed
DrawPixelOn(theOriginalPix,pixX,pixY)
qdel(masterpiece)
//Drawing one pixel with a crayon
else if(istype(I, /obj/item/toy/crayon))
var/obj/item/toy/crayon/C = I
DrawPixelOn(C.paint_color, pixX, pixY)
/obj/item/canvas/attackby(obj/item/I, mob/living/user, params)
if(user.a_intent == INTENT_HELP)
ui_interact(user)
else
return ..()
/obj/item/canvas/ui_data(mob/user)
. = ..()
.["grid"] = grid
.["name"] = painting_name
.["finalized"] = finalized
//Clean the whole canvas
/obj/item/canvas/attack_self(mob/user)
if(!user)
/obj/item/canvas/examine(mob/user)
. = ..()
ui_interact(user)
/obj/item/canvas/ui_act(action, params)
. = ..()
if(. || finalized)
return
var/icon/blank = getGlobalBackup()
if(blank)
//it's basically a giant etch-a-sketch
icon = blank
user.visible_message("<span class='notice'>[user] cleans the canvas.</span>","<span class='notice'>You clean the canvas.</span>")
var/mob/user = usr
switch(action)
if("paint")
var/obj/item/I = user.get_active_held_item()
var/color = get_paint_tool_color(I)
if(!color)
return FALSE
var/x = text2num(params["x"])
var/y = text2num(params["y"])
grid[x][y] = color
used = TRUE
update_icon()
. = TRUE
if("finalize")
. = TRUE
if(!finalized)
finalize(user)
/obj/item/canvas/proc/finalize(mob/user)
finalized = TRUE
author_ckey = user.ckey
generate_proper_overlay()
try_rename(user)
/obj/item/canvas/update_overlays()
. = ..()
if(!icon_generated)
if(used)
var/mutable_appearance/detail = mutable_appearance(icon,"[icon_state]wip")
detail.pixel_x = 1
detail.pixel_y = 1
. += detail
else
var/mutable_appearance/detail = mutable_appearance(generated_icon)
detail.pixel_x = 1
detail.pixel_y = 1
. += detail
/obj/item/canvas/proc/generate_proper_overlay()
if(icon_generated)
return
var/png_filename = "data/paintings/temp_painting.png"
var/result = rustg_dmi_create_png(png_filename,"[width]","[height]",get_data_string())
if(result)
CRASH("Error generating painting png : [result]")
generated_icon = new(png_filename)
icon_generated = TRUE
update_icon()
/obj/item/canvas/proc/get_data_string()
var/list/data = list()
for(var/y in 1 to height)
for(var/x in 1 to width)
data += grid[x][y]
return data.Join("")
//Todo make this element ?
/obj/item/canvas/proc/get_paint_tool_color(obj/item/I)
if(!I)
return
if(istype(I, /obj/item/toy/crayon))
var/obj/item/toy/crayon/C = I
return C.paint_color
else if(istype(I, /obj/item/pen))
var/obj/item/pen/P = I
switch(P.colour)
if("black")
return "#000000"
if("blue")
return "#0000ff"
if("red")
return "#ff0000"
return P.colour
else if(istype(I, /obj/item/soap) || istype(I, /obj/item/reagent_containers/glass/rag))
return canvas_color
/obj/item/canvas/proc/try_rename(mob/user)
var/new_name = stripped_input(user,"What do you want to name the painting?")
if(!painting_name && new_name && user.canUseTopic(src,BE_CLOSE))
painting_name = new_name
SStgui.update_uis(src)
/obj/item/canvas/nineteenXnineteen
icon_state = "19x19"
width = 19
height = 19
ui_x = 600
ui_y = 600
pixel_x = 6
pixel_y = 9
framed_offset_x = 8
framed_offset_y = 9
/obj/item/canvas/twentythreeXnineteen
icon_state = "23x19"
width = 23
height = 19
ui_x = 800
ui_y = 600
pixel_x = 4
pixel_y = 10
framed_offset_x = 6
framed_offset_y = 8
/obj/item/canvas/twentythreeXtwentythree
icon_state = "23x23"
width = 23
height = 23
ui_x = 800
ui_y = 800
pixel_x = 5
pixel_y = 9
framed_offset_x = 5
framed_offset_y = 6
/obj/item/wallframe/painting
name = "painting frame"
desc = "The perfect showcase for your favorite deathtrap memories."
icon = 'icons/obj/decals.dmi'
custom_materials = null
flags_1 = 0
icon_state = "frame-empty"
result_path = /obj/structure/sign/painting
/obj/structure/sign/painting
name = "Painting"
desc = "Art or \"Art\"? You decide."
icon = 'icons/obj/decals.dmi'
icon_state = "frame-empty"
buildable_sign = FALSE
var/obj/item/canvas/C
var/persistence_id
/obj/structure/sign/painting/Initialize(mapload, dir, building)
. = ..()
SSpersistence.painting_frames += src
AddComponent(/datum/component/art, 20)
if(dir)
setDir(dir)
if(building)
pixel_x = (dir & 3)? 0 : (dir == 4 ? -30 : 30)
pixel_y = (dir & 3)? (dir ==1 ? -30 : 30) : 0
/obj/structure/sign/painting/Destroy()
. = ..()
SSpersistence.painting_frames -= src
/obj/structure/sign/painting/attackby(obj/item/I, mob/user, params)
if(!C && istype(I, /obj/item/canvas))
frame_canvas(user,I)
else if(C && !C.painting_name && istype(I,/obj/item/pen))
try_rename(user)
else
return ..()
/obj/structure/sign/painting/examine(mob/user)
. = ..()
if(C)
C.ui_interact(user,state = GLOB.physical_obscured_state)
/obj/structure/sign/painting/wirecutter_act(mob/living/user, obj/item/I)
. = ..()
if(C)
C.forceMove(drop_location())
C = null
to_chat(user, "<span class='notice'>You remove the painting from the frame.</span>")
update_icon()
return TRUE
/obj/structure/sign/painting/proc/frame_canvas(mob/user,obj/item/canvas/new_canvas)
if(user.transferItemToLoc(new_canvas,src))
C = new_canvas
if(!C.finalized)
C.finalize(user)
to_chat(user,"<span class='notice'>You frame [C].</span>")
update_icon()
/obj/structure/sign/painting/proc/try_rename(mob/user)
if(!C.painting_name)
C.try_rename(user)
/obj/structure/sign/painting/update_icon_state()
. = ..()
if(C && C.generated_icon)
icon_state = null
else
icon_state = "frame-empty"
#undef AMT_OF_CANVASES
/obj/structure/sign/painting/update_overlays()
. = ..()
if(C && C.generated_icon)
var/mutable_appearance/MA = mutable_appearance(C.generated_icon)
MA.pixel_x = C.framed_offset_x
MA.pixel_y = C.framed_offset_y
. += MA
var/mutable_appearance/frame = mutable_appearance(C.icon,"[C.icon_state]frame")
frame.pixel_x = C.framed_offset_x - 1
frame.pixel_y = C.framed_offset_y - 1
. += frame
/obj/structure/sign/painting/proc/load_persistent()
if(!persistence_id)
return
if(!SSpersistence.paintings || !SSpersistence.paintings[persistence_id] || !length(SSpersistence.paintings[persistence_id]))
return
var/list/chosen = pick(SSpersistence.paintings[persistence_id])
var/title = chosen["title"]
var/author = chosen["ckey"]
var/png = "data/paintings/[persistence_id]/[chosen["md5"]].png"
if(!fexists(png))
stack_trace("Persistent painting [chosen["md5"]].png was not found in [persistence_id] directory.")
return
var/icon/I = new(png)
var/obj/item/canvas/new_canvas
var/w = I.Width()
var/h = I.Height()
for(var/T in typesof(/obj/item/canvas))
new_canvas = T
if(initial(new_canvas.width) == w && initial(new_canvas.height) == h)
new_canvas = new T(src)
break
new_canvas.fill_grid_from_icon(I)
new_canvas.generated_icon = I
new_canvas.icon_generated = TRUE
new_canvas.finalized = TRUE
new_canvas.painting_name = title
new_canvas.author_ckey = author
C = new_canvas
update_icon()
/obj/structure/sign/painting/proc/save_persistent()
if(!persistence_id || !C)
return
if(sanitize_filename(persistence_id) != persistence_id)
stack_trace("Invalid persistence_id - [persistence_id]")
return
var/data = C.get_data_string()
var/md5 = md5(data)
var/list/current = SSpersistence.paintings[persistence_id]
if(!current)
current = list()
for(var/list/entry in current)
if(entry["md5"] == md5)
return
var/png_directory = "data/paintings/[persistence_id]/"
var/png_path = png_directory + "[md5].png"
var/result = rustg_dmi_create_png(png_path,"[C.width]","[C.height]",data)
if(result)
CRASH("Error saving persistent painting: [result]")
current += list(list("title" = C.painting_name , "md5" = md5, "ckey" = C.author_ckey))
SSpersistence.paintings[persistence_id] = current
/obj/item/canvas/proc/fill_grid_from_icon(icon/I)
var/h = I.Height() + 1
for(var/x in 1 to width)
for(var/y in 1 to height)
grid[x][y] = I.GetPixel(x,h-y)
//Presets for art gallery mapping, for paintings to be shared across stations
/obj/structure/sign/painting/library
persistence_id = "library"
/obj/structure/sign/painting/library_secure
persistence_id = "library_secure"
/obj/structure/sign/painting/library_private // keep your smut away from prying eyes, or non-librarians at least
persistence_id = "library_private"
/obj/structure/sign/painting/vv_get_dropdown()
. = ..()
VV_DROPDOWN_OPTION(VV_HK_REMOVE_PAINTING, "Remove Persistent Painting")
/obj/structure/sign/painting/vv_do_topic(list/href_list)
. = ..()
if(href_list[VV_HK_REMOVE_PAINTING])
if(!check_rights(NONE))
return
var/mob/user = usr
if(!persistence_id || !C)
to_chat(user,"<span class='warning'>This is not a persistent painting.</span>")
return
var/md5 = md5(C.get_data_string())
var/author = C.author_ckey
var/list/current = SSpersistence.paintings[persistence_id]
if(current)
for(var/list/entry in current)
if(entry["md5"] == md5)
current -= entry
var/png = "data/paintings/[persistence_id]/[md5].png"
fdel(png)
for(var/obj/structure/sign/painting/P in SSpersistence.painting_frames)
if(P.C && md5(P.C.get_data_string()) == md5)
QDEL_NULL(P.C)
log_admin("[key_name(user)] has deleted a persistent painting made by [author].")
message_admins("<span class='notice'>[key_name_admin(user)] has deleted persistent painting made by [author].</span>")
@@ -71,7 +71,7 @@
datum/tgui/master_ui = null, datum/ui_state/state = GLOB.physical_state)
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
if(!ui)
ui = new(user, src, ui_key, "tank_dispenser", name, 275, 103, master_ui, state)
ui = new(user, src, ui_key, "TankDispenser", name, 275, 103, master_ui, state)
ui.open()
/obj/structure/tank_dispenser/ui_data(mob/user)
+1 -1
View File
@@ -69,7 +69,7 @@
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
if(!ui)
ui = new(user, src, ui_key, "ntnet_relay", "NTNet Quantum Relay", ui_x, ui_y, master_ui, state)
ui = new(user, src, ui_key, "NtnetRelay", "NTNet Quantum Relay", ui_x, ui_y, master_ui, state)
ui.open()
+1 -1
View File
@@ -36,7 +36,7 @@
/datum/borgpanel/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, datum/tgui/master_ui = null, datum/ui_state/state = GLOB.admin_state)
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
if(!ui)
ui = new(user, src, ui_key, "borgopanel", "Borg Panel", 700, 700, master_ui, state)
ui = new(user, src, ui_key, "BorgPanel", "Borg Panel", 700, 700, master_ui, state)
ui.open()
/datum/borgpanel/ui_data(mob/user)
@@ -16,7 +16,7 @@
/datum/cellular_emporium/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, datum/tgui/master_ui = null, datum/ui_state/state = GLOB.always_state)
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
if(!ui)
ui = new(user, src, ui_key, "cellular_emporium", name, 900, 480, master_ui, state)
ui = new(user, src, ui_key, "CellularEmporium", name, 900, 480, master_ui, state)
ui.open()
/datum/cellular_emporium/ui_data(mob/user)
@@ -7,6 +7,9 @@
density = TRUE
resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | UNACIDABLE | ACID_PROOF
ui_x = 350
ui_y = 442
var/timer_set = 90
var/default_timer_set = 90
var/minimum_timer_set = 90
@@ -262,8 +265,7 @@
/obj/machinery/nuclearbomb/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, "nuclear_bomb", name, 350, 442, master_ui, state)
ui.set_style(ui_style)
ui = new(user, src, ui_key, "NuclearBomb", name, ui_x, ui_y, master_ui, state)
ui.open()
/obj/machinery/nuclearbomb/ui_data(mob/user)
+6 -37
View File
@@ -4,7 +4,6 @@
icon_state = "health"
custom_materials = list(/datum/material/iron=800, /datum/material/glass=200)
attachable = TRUE
secured = FALSE
var/scanning = FALSE
var/health_scan
@@ -12,7 +11,8 @@
/obj/item/assembly/health/examine(mob/user)
. = ..()
. += "<span class='notice'>Use a multitool to swap between \"detect death\" mode and \"detect critical state\" mode.</span>"
. += "Use it in hand to turn it off/on and Alt-click to swap between \"detect death\" mode and \"detect critical state\" mode."
. += "[src.scanning ? "The sensor is on and you can see [health_scan] displayed on the screen" : "The sensor is off"]."
/obj/item/assembly/health/activate()
if(!..())
@@ -30,14 +30,13 @@
update_icon()
return secured
/obj/item/assembly/health/multitool_act(mob/living/user, obj/item/I)
/obj/item/assembly/health/AltClick(mob/living/user)
if(alarm_health == HEALTH_THRESHOLD_CRIT)
alarm_health = HEALTH_THRESHOLD_DEAD
to_chat(user, "<span class='notice'>You toggle [src] to \"detect death\" mode.</span>")
else
alarm_health = HEALTH_THRESHOLD_CRIT
to_chat(user, "<span class='notice'>You toggle [src] to \"detect critical state\" mode.</span>")
return TRUE
/obj/item/assembly/health/process()
if(!scanning || !secured)
@@ -46,7 +45,6 @@
var/atom/A = src
if(connected && connected.holder)
A = connected.holder
for(A, A && !ismob(A), A=A.loc);
// like get_turf(), but for mobs.
var/mob/living/M = A
@@ -71,36 +69,7 @@
STOP_PROCESSING(SSobj, src)
return
/obj/item/assembly/health/ui_interact(mob/user as mob)//TODO: Change this to the wires thingy
/obj/item/assembly/health/attack_self(mob/user)
. = ..()
if(!secured)
user.show_message("<span class='warning'>The [name] is unsecured!</span>")
return FALSE
var/dat = "<TT><B>Health Sensor</B></TT>"
dat += "<BR><A href='?src=[REF(src)];scanning=1'>[scanning?"On":"Off"]</A>"
if(scanning && health_scan)
dat += "<BR>Health: [health_scan]"
user << browse(dat, "window=hscan")
onclose(user, "hscan")
/obj/item/assembly/health/Topic(href, href_list)
..()
if(!ismob(usr))
return
var/mob/user = usr
if(!user.canUseTopic(src))
usr << browse(null, "window=hscan")
onclose(usr, "hscan")
return
if(href_list["scanning"])
toggle_scan()
if(href_list["close"])
usr << browse(null, "window=hscan")
return
attack_self(user)
return
to_chat(user, "<span class='notice'>You toggle [src] [src.scanning ? "off" : "on"].</span>")
toggle_scan()
+42 -38
View File
@@ -4,7 +4,10 @@
icon_state = "infrared"
custom_materials = list(/datum/material/iron=1000, /datum/material/glass=500)
is_position_sensitive = TRUE
drop_sound = 'sound/items/handling/component_drop.ogg'
pickup_sound = 'sound/items/handling/component_pickup.ogg'
var/ui_x = 225
var/ui_y = 110
var/on = FALSE
var/visible = FALSE
var/maxlength = 8
@@ -38,7 +41,7 @@
/obj/item/assembly/infra/activate()
if(!..())
return FALSE//Cooldown check
return FALSE //Cooldown check
on = !on
refreshBeam()
update_icon()
@@ -69,7 +72,7 @@
holder.update_icon()
return
/obj/item/assembly/infra/dropped(mob/user)
/obj/item/assembly/infra/dropped()
. = ..()
if(holder)
holder_movement() //sync the dir of the device as well if it's contained in a TTV or an assembly holder
@@ -133,7 +136,7 @@
. = ..()
setDir(t)
/obj/item/assembly/infra/throw_at(atom/target, range, speed, mob/thrower, spin=1, diagonals_first = 0, datum/callback/callback)
/obj/item/assembly/infra/throw_at(atom/target, range, speed, mob/thrower, spin=1, diagonals_first = 0, datum/callback/callback, force, gentle = FALSE)
. = ..()
olddir = dir
@@ -176,55 +179,56 @@
return
return refreshBeam()
/obj/item/assembly/infra/ui_interact(mob/user)//TODO: change this this to the wire control panel
. = ..()
if(is_secured(user))
user.set_machine(src)
var/dat = "<TT><B>Infrared Laser</B></TT>"
dat += "<BR><B>Status</B>: [on ? "<A href='?src=[REF(src)];state=0'>On</A>" : "<A href='?src=[REF(src)];state=1'>Off</A>"]"
dat += "<BR><B>Visibility</B>: [visible ? "<A href='?src=[REF(src)];visible=0'>Visible</A>" : "<A href='?src=[REF(src)];visible=1'>Invisible</A>"]"
dat += "<BR><BR><A href='?src=[REF(src)];refresh=1'>Refresh</A>"
dat += "<BR><BR><A href='?src=[REF(src)];close=1'>Close</A>"
user << browse(dat, "window=infra")
onclose(user, "infra")
return
/obj/item/assembly/infra/Topic(href, href_list)
..()
if(usr.incapacitated() || !in_range(loc, usr))
usr << browse(null, "window=infra")
onclose(usr, "infra")
return
if(href_list["state"])
on = !(on)
update_icon()
refreshBeam()
if(href_list["visible"])
visible = !(visible)
update_icon()
refreshBeam()
if(href_list["close"])
usr << browse(null, "window=infra")
return
if(usr)
attack_self(usr)
/obj/item/assembly/infra/setDir()
. = ..()
refreshBeam()
/obj/item/assembly/infra/ui_status(mob/user)
if(is_secured(user))
return ..()
return UI_CLOSE
/obj/item/assembly/infra/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, \
datum/tgui/master_ui = null, datum/ui_state/state = GLOB.hands_state)
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
if(!ui)
ui = new(user, src, ui_key, "InfraredEmitter", name, ui_x, ui_y, master_ui, state)
ui.open()
/obj/item/assembly/infra/ui_data(mob/user)
var/list/data = list()
data["on"] = on
data["visible"] = visible
return data
/obj/item/assembly/infra/ui_act(action, params)
if(..())
return
switch(action)
if("power")
on = !on
. = TRUE
if("visibility")
visible = !visible
. = TRUE
update_icon()
refreshBeam()
/***************************IBeam*********************************/
/obj/effect/beam/i_beam
name = "infrared beam"
icon = 'icons/obj/projectiles.dmi'
icon_state = "ibeam"
var/obj/item/assembly/infra/master
anchored = TRUE
density = FALSE
pass_flags = PASSTABLE|PASSGLASS|PASSGRILLE|LETPASSTHROW
var/obj/item/assembly/infra/master
/obj/effect/beam/i_beam/Crossed(atom/movable/AM as mob|obj)
. = ..()
if(istype(AM, /obj/effect/beam))
return
if (isitem(AM))
+46 -50
View File
@@ -4,7 +4,10 @@
icon_state = "prox"
custom_materials = list(/datum/material/iron=800, /datum/material/glass=200)
attachable = TRUE
drop_sound = 'sound/items/handling/component_drop.ogg'
pickup_sound = 'sound/items/handling/component_pickup.ogg'
var/ui_x = 250
var/ui_y = 185
var/scanning = FALSE
var/timing = FALSE
var/time = 10
@@ -26,7 +29,7 @@
/obj/item/assembly/prox_sensor/activate()
if(!..())
return FALSE//Cooldown check
return FALSE //Cooldown check
if(!scanning)
timing = !timing
else
@@ -41,7 +44,6 @@
else
proximity_monitor.SetHost(src,src)
/obj/item/assembly/prox_sensor/toggle_secure()
secured = !secured
if(!secured)
@@ -56,8 +58,6 @@
update_icon()
return secured
/obj/item/assembly/prox_sensor/HasProximity(atom/movable/AM as mob|obj)
if (istype(AM, /obj/effect/beam))
return
@@ -75,7 +75,6 @@
next_activate = world.time + 30
return TRUE
/obj/item/assembly/prox_sensor/process()
if(!timing)
return
@@ -111,50 +110,47 @@
holder.update_icon()
return
/obj/item/assembly/prox_sensor/ui_interact(mob/user)//TODO: Change this to the wires thingy
. = ..()
/obj/item/assembly/prox_sensor/ui_status(mob/user)
if(is_secured(user))
var/second = time % 60
var/minute = (time - second) / 60
var/dat = "<TT><B>Proximity Sensor</B></TT>"
if(!scanning)
dat += "<BR>[(timing ? "<A href='?src=[REF(src)];time=0'>Arming</A>" : "<A href='?src=[REF(src)];time=1'>Not Arming</A>")] [minute]:[second]"
dat += "<BR><A href='?src=[REF(src)];tp=-30'>-</A> <A href='?src=[REF(src)];tp=-1'>-</A> <A href='?src=[REF(src)];tp=1'>+</A> <A href='?src=[REF(src)];tp=30'>+</A>"
dat += "<BR><A href='?src=[REF(src)];scanning=[scanning?"0'>Armed":"1'>Unarmed (Movement sensor active when armed!)"]</A>"
dat += "<BR>Detection range: <A href='?src=[REF(src)];sense=down'>-</A> [sensitivity] <A href='?src=[REF(src)];sense=up'>+</A>"
dat += "<BR><BR><A href='?src=[REF(src)];refresh=1'>Refresh</A>"
dat += "<BR><BR><A href='?src=[REF(src)];close=1'>Close</A>"
user << browse(dat, "window=prox")
onclose(user, "prox")
return ..()
return UI_CLOSE
/obj/item/assembly/prox_sensor/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, \
datum/tgui/master_ui = null, datum/ui_state/state = GLOB.hands_state)
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
if(!ui)
ui = new(user, src, ui_key, "ProximitySensor", name, ui_x, ui_y, master_ui, state)
ui.open()
/obj/item/assembly/prox_sensor/ui_data(mob/user)
var/list/data = list()
data["seconds"] = round(time % 60)
data["minutes"] = round((time - data["seconds"]) / 60)
data["timing"] = timing
data["scanning"] = scanning
data["sensitivity"] = sensitivity
return data
/obj/item/assembly/prox_sensor/ui_act(action, params)
if(..())
return
/obj/item/assembly/prox_sensor/Topic(href, href_list)
..()
if(usr.incapacitated() || !in_range(loc, usr))
usr << browse(null, "window=prox")
onclose(usr, "prox")
return
if(href_list["sense"])
sensitivity_change(((href_list["sense"] == "up") ? 1 : -1))
if(href_list["scanning"])
toggle_scan(text2num(href_list["scanning"]))
if(href_list["time"])
timing = text2num(href_list["time"])
update_icon()
if(href_list["tp"])
var/tp = text2num(href_list["tp"])
time += tp
time = min(max(round(time), 0), 600)
if(href_list["close"])
usr << browse(null, "window=prox")
return
if(usr)
attack_self(usr)
switch(action)
if("scanning")
toggle_scan(!scanning)
. = TRUE
if("sense")
var/value = text2num(params["range"])
if(value)
sensitivity_change(value)
. = TRUE
if("time")
timing = !timing
update_icon()
. = TRUE
if("input")
var/value = text2num(params["adjust"])
if(value)
value = round(time + value)
time = clamp(value, 0, 600)
. = TRUE
+39 -22
View File
@@ -8,32 +8,49 @@
custom_materials = list(/datum/material/iron=400, /datum/material/glass=120)
wires = WIRE_RECEIVE | WIRE_PULSE | WIRE_RADIO_PULSE | WIRE_RADIO_RECEIVE
attachable = TRUE
drop_sound = 'sound/items/handling/component_drop.ogg'
pickup_sound = 'sound/items/handling/component_pickup.ogg'
var/ui_x = 280
var/ui_y = 132
var/code = DEFAULT_SIGNALER_CODE
var/frequency = FREQ_SIGNALER
var/datum/radio_frequency/radio_connection
var/suicider = null
///Holds the mind that commited suicide.
var/datum/mind/suicider
///Holds a reference string to the mob, decides how much of a gamer you are.
var/suicide_mob
var/hearing_range = 1
/obj/item/assembly/signaler/suicide_act(mob/living/carbon/user)
user.visible_message("<span class='suicide'>[user] eats \the [src]! If it is signaled, [user.p_they()] will die!</span>")
playsound(src, 'sound/items/eatfood.ogg', 50, TRUE)
user.transferItemToLoc(src, user, TRUE)
suicider = user
return MANUAL_SUICIDE
moveToNullspace()
suicider = user.mind
suicide_mob = REF(user)
return MANUAL_SUICIDE_NONLETHAL
/obj/item/assembly/signaler/proc/manual_suicide(mob/living/carbon/user)
user.visible_message("<span class='suicide'>[user]'s \the [src] receives a signal, killing [user.p_them()] instantly!</span>")
/obj/item/assembly/signaler/proc/manual_suicide(datum/mind/suicidee)
var/mob/living/user = suicidee.current
if(!istype(user))
return
if(suicide_mob == REF(user))
user.visible_message("<span class='suicide'>[user]'s [src] receives a signal, killing [user.p_them()] instantly!</span>")
else
user.visible_message("<span class='suicide'>[user]'s [src] receives a signal and [user.p_they()] die[user.p_s()] like a gamer!</span>")
user.adjustOxyLoss(200)//it sends an electrical pulse to their heart, killing them. or something.
user.death(0)
user.set_suicide(TRUE)
user.suicide_log()
playsound(user, 'sound/machines/triple_beep.ogg', ASSEMBLY_BEEP_VOLUME, TRUE)
qdel(src)
/obj/item/assembly/signaler/Initialize()
. = ..()
set_frequency(frequency)
/obj/item/assembly/signaler/Destroy()
SSradio.remove_object(src,frequency)
suicider = null
. = ..()
/obj/item/assembly/signaler/activate()
@@ -47,14 +64,16 @@
holder.update_icon()
return
/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))
return
/obj/item/assembly/signaler/ui_status(mob/user)
if(is_secured(user))
return ..()
return UI_CLOSE
/obj/item/assembly/signaler/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, \
datum/tgui/master_ui = null, datum/ui_state/state = GLOB.hands_state)
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 = new(user, src, ui_key, "Signaler", name, ui_x, ui_y, master_ui, state)
ui.open()
/obj/item/assembly/signaler/ui_data(mob/user)
@@ -63,12 +82,12 @@
data["code"] = code
data["minFrequency"] = MIN_FREE_FREQ
data["maxFrequency"] = MAX_FREE_FREQ
return data
/obj/item/assembly/signaler/ui_act(action, params)
if(..())
return
switch(action)
if("signal")
INVOKE_ASYNC(src, .proc/signal)
@@ -90,7 +109,7 @@
. = TRUE
update_icon()
/obj/item/assembly/signaler/attackby(obj/item/W, mob/user, params)
if(issignaler(W))
var/obj/item/assembly/signaler/signaler2 = W
@@ -112,9 +131,6 @@
if(usr)
GLOB.lastsignalers.Add("[time] <B>:</B> [usr.key] used [src] @ location ([T.x],[T.y],[T.z]) <B>:</B> [format_frequency(frequency)]/[code]")
return
/obj/item/assembly/signaler/receive_signal(datum/signal/signal)
. = FALSE
if(!signal)
@@ -125,6 +141,7 @@
return
if(suicider)
manual_suicide(suicider)
return
pulse(TRUE)
audible_message("[icon2html(src, hearers(src))] *beep* *beep* *beep*", null, hearing_range)
for(var/CHM in get_hearers_in_view(hearing_range, src))
@@ -133,7 +150,6 @@
LM.playsound_local(get_turf(src), 'sound/machines/triple_beep.ogg', ASSEMBLY_BEEP_VOLUME, TRUE)
return TRUE
/obj/item/assembly/signaler/proc/set_frequency(new_frequency)
SSradio.remove_object(src, frequency)
frequency = new_frequency
@@ -162,7 +178,6 @@
return
return ..(signal)
// Embedded signaller used in anomalies.
/obj/item/assembly/signaler/anomaly
name = "anomaly core"
@@ -179,6 +194,8 @@
return FALSE
if(signal.data["code"] != code)
return FALSE
if(suicider)
manual_suicide(suicider)
for(var/obj/effect/anomaly/A in get_turf(src))
A.anomalyNeutralize()
return TRUE
@@ -191,4 +208,4 @@
/obj/item/assembly/signaler/cyborg/attackby(obj/item/W, mob/user, params)
return
/obj/item/assembly/signaler/cyborg/screwdriver_act(mob/living/user, obj/item/I)
return
return
+40 -47
View File
@@ -4,7 +4,10 @@
icon_state = "timer"
custom_materials = list(/datum/material/iron=500, /datum/material/glass=50)
attachable = TRUE
drop_sound = 'sound/items/handling/component_drop.ogg'
pickup_sound = 'sound/items/handling/component_pickup.ogg'
var/ui_x = 275
var/ui_y = 115
var/timing = FALSE
var/time = 5
var/saved_time = 5
@@ -41,7 +44,6 @@
update_icon()
return TRUE
/obj/item/assembly/timer/toggle_secure()
secured = !secured
if(secured)
@@ -52,7 +54,6 @@
update_icon()
return secured
/obj/item/assembly/timer/proc/timer_end()
if(!secured || next_activate > world.time)
return FALSE
@@ -66,7 +67,6 @@
timing = TRUE
update_icon()
/obj/item/assembly/timer/process()
if(!timing)
return
@@ -76,7 +76,6 @@
timer_end()
time = saved_time
/obj/item/assembly/timer/update_icon()
cut_overlays()
attached_overlays = list()
@@ -86,50 +85,44 @@
if(holder)
holder.update_icon()
/obj/item/assembly/timer/ui_interact(mob/user)//TODO: Have this use the wires
. = ..()
/obj/item/assembly/timer/ui_status(mob/user)
if(is_secured(user))
var/second = time % 60
var/minute = (time - second) / 60
var/dat = "<TT><B>Timing Unit</B></TT>"
dat += "<BR>[(timing ? "<A href='?src=[REF(src)];time=0'>Timing</A>" : "<A href='?src=[REF(src)];time=1'>Not Timing</A>")] [minute]:[second]"
dat += "<BR><A href='?src=[REF(src)];tp=-30'>-</A> <A href='?src=[REF(src)];tp=-1'>-</A> <A href='?src=[REF(src)];tp=1'>+</A> <A href='?src=[REF(src)];tp=30'>+</A>"
dat += "<BR><BR><A href='?src=[REF(src)];repeat=[(loop ? "0'>Stop repeating" : "1'>Set to repeat")]</A>"
dat += "<BR><BR><A href='?src=[REF(src)];refresh=1'>Refresh</A>"
dat += "<BR><BR><A href='?src=[REF(src)];close=1'>Close</A>"
var/datum/browser/popup = new(user, "timer", name)
popup.set_content(dat)
popup.open()
return ..()
return UI_CLOSE
/obj/item/assembly/timer/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, \
datum/tgui/master_ui = null, datum/ui_state/state = GLOB.hands_state)
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
if(!ui)
ui = new(user, src, ui_key, "Timer", name, ui_x, ui_y, master_ui, state)
ui.open()
/obj/item/assembly/timer/Topic(href, href_list)
..()
if(!usr.canUseTopic(src, BE_CLOSE))
usr << browse(null, "window=timer")
onclose(usr, "timer")
/obj/item/assembly/timer/ui_data(mob/user)
var/list/data = list()
data["seconds"] = round(time % 60)
data["minutes"] = round((time - data["seconds"]) / 60)
data["timing"] = timing
data["loop"] = loop
return data
/obj/item/assembly/timer/ui_act(action, params)
if(..())
return
if(href_list["time"])
timing = text2num(href_list["time"])
if(timing && istype(holder, /obj/item/transfer_valve))
var/timer_message = "[ADMIN_LOOKUPFLW(usr)] activated [src] attachment on [holder]."
message_admins(timer_message)
GLOB.bombers += timer_message
log_game("[key_name(usr)] activated [src] attachment on [holder]")
update_icon()
if(href_list["repeat"])
loop = text2num(href_list["repeat"])
if(href_list["tp"])
var/tp = text2num(href_list["tp"])
time += tp
time = min(max(round(time), 1), 600)
saved_time = time
if(href_list["close"])
usr << browse(null, "window=timer")
return
if(usr)
attack_self(usr)
switch(action)
if("time")
timing = !timing
if(timing && istype(holder, /obj/item/transfer_valve))
log_bomber(usr, "activated a", src, "attachment on [holder]")
update_icon()
. = TRUE
if("repeat")
loop = !loop
. = TRUE
if("input")
var/value = text2num(params["adjust"])
if(value)
value = round(time + value)
time = clamp(value, 1, 600)
saved_time = time
. = TRUE
@@ -239,7 +239,7 @@
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, "airalarm", name, 440, 650, master_ui, state)
ui = new(user, src, ui_key, "AirAlarm", name, 440, 650, master_ui, state)
ui.open()
/obj/machinery/airalarm/ui_data(mob/user)
@@ -26,6 +26,21 @@ Passive gate is similar to the regular pump except:
construction_type = /obj/item/pipe/directional
pipe_state = "passivegate"
ui_x = 335
ui_y = 115
/obj/machinery/atmospherics/components/binary/passive_gate/CtrlClick(mob/user)
if(can_interact(user))
on = !on
update_icon()
return ..()
/obj/machinery/atmospherics/components/binary/passive_gate/AltClick(mob/user)
if(can_interact(user))
target_pressure = MAX_OUTPUT_PRESSURE
update_icon()
return ..()
/obj/machinery/atmospherics/components/binary/passive_gate/Destroy()
SSradio.remove_object(src,frequency)
return ..()
@@ -91,7 +106,7 @@ Passive gate is similar to the regular pump except:
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, "atmos_pump", name, 335, 115, master_ui, state)
ui = new(user, src, ui_key, "AtmosPump", name, ui_x, ui_y, master_ui, state)
ui.open()
/obj/machinery/atmospherics/components/binary/passive_gate/ui_data()
@@ -111,7 +111,7 @@
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, "atmos_pump", name, 335, 115, master_ui, state)
ui = new(user, src, ui_key, "AtmosPump", name, 335, 115, master_ui, state)
ui.open()
/obj/machinery/atmospherics/components/binary/pump/ui_data()
@@ -212,4 +212,4 @@
/obj/machinery/atmospherics/components/binary/pump/on/layer3
piping_layer = 3
icon_state= "pump_on_map-3"
icon_state= "pump_on_map-3"
@@ -96,7 +96,7 @@
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, "atmos_pump", name, 310, 115, master_ui, state)
ui = new(user, src, ui_key, "AtmosPump", name, 310, 115, master_ui, state)
ui.open()
/obj/machinery/atmospherics/components/binary/volume_pump/ui_data()
@@ -200,4 +200,4 @@
/obj/machinery/atmospherics/components/binary/volume_pump/on/layer3
piping_layer = 3
icon_state = "volpump_map-3"
icon_state = "volpump_map-3"
@@ -138,7 +138,7 @@
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, "atmos_filter", name, 475, 185, master_ui, state)
ui = new(user, src, ui_key, "AtmosFilter", name, 475, 185, master_ui, state)
ui.open()
/obj/machinery/atmospherics/components/trinary/filter/ui_data()
@@ -280,4 +280,4 @@
critical_machine = TRUE
/obj/machinery/atmospherics/components/trinary/filter/flipped/critical
critical_machine = TRUE
critical_machine = TRUE
@@ -131,7 +131,7 @@
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, "atmos_mixer", name, ui_x, ui_y, master_ui, state)
ui = new(user, src, ui_key, "AtmosMixer", name, ui_x, ui_y, master_ui, state)
ui.open()
/obj/machinery/atmospherics/components/trinary/mixer/ui_data()
@@ -317,7 +317,7 @@
datum/tgui/master_ui = null, datum/ui_state/state = GLOB.notcontained_state)
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
if(!ui)
ui = new(user, src, ui_key, "cryo", name, 400, 550, master_ui, state)
ui = new(user, src, ui_key, "Cryo", name, 400, 550, master_ui, state)
ui.open()
/obj/machinery/atmospherics/components/unary/cryo_cell/ui_data()
@@ -20,6 +20,21 @@
pipe_state = "injector"
ui_x = 310
ui_y = 115
/obj/machinery/atmospherics/components/unary/outlet_injector/CtrlClick(mob/user)
if(can_interact(user))
on = !on
update_icon()
return ..()
/obj/machinery/atmospherics/components/unary/outlet_injector/AltClick(mob/user)
if(can_interact(user))
volume_rate = MAX_TRANSFER_RATE
update_icon()
return ..()
/obj/machinery/atmospherics/components/unary/outlet_injector/Destroy()
SSradio.remove_object(src,frequency)
return ..()
@@ -140,7 +155,7 @@
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, "atmos_pump", name, 310, 115, master_ui, state)
ui = new(user, src, ui_key, "AtmosPump", name, ui_x, ui_y, master_ui, state)
ui.open()
/obj/machinery/atmospherics/components/unary/outlet_injector/ui_data()
@@ -128,7 +128,7 @@
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, "thermomachine", name, ui_x, ui_y, master_ui, state)
ui = new(user, src, ui_key, "ThermoMachine", name, ui_x, ui_y, master_ui, state)
ui.open()
/obj/machinery/atmospherics/components/unary/thermomachine/ui_data(mob/user)
@@ -321,7 +321,7 @@
datum/tgui/master_ui = null, datum/ui_state/state = GLOB.physical_state)
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
if(!ui)
ui = new(user, src, ui_key, "canister", name, 420, 405, master_ui, state)
ui = new(user, src, ui_key, "Canister", name, 420, 405, master_ui, state)
ui.open()
/obj/machinery/portable_atmospherics/canister/ui_data()
@@ -8,6 +8,8 @@
name = "portable air pump"
icon_state = "psiphon:0"
density = TRUE
ui_x = 300
ui_y = 315
var/on = FALSE
var/direction = PUMP_OUT
@@ -32,7 +34,6 @@
/obj/machinery/portable_atmospherics/pump/update_icon_state()
icon_state = "psiphon:[on]"
/obj/machinery/portable_atmospherics/pump/update_overlays()
. = ..()
if(holding)
@@ -79,14 +80,14 @@
on = FALSE
update_icon()
else if(on && holding && direction == PUMP_OUT)
investigate_log("[key_name(user)] started a transfer into [holding].<br>", INVESTIGATE_ATMOS)
investigate_log("[key_name(user)] started a transfer into [holding].", INVESTIGATE_ATMOS)
/obj/machinery/portable_atmospherics/pump/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, \
datum/tgui/master_ui = null, datum/ui_state/state = GLOB.physical_state)
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
if(!ui)
ui = new(user, src, ui_key, "portable_pump", name, 300, 315, master_ui, state)
ui = new(user, src, ui_key, "PortablePump", name, ui_x, ui_y, master_ui, state)
ui.open()
/obj/machinery/portable_atmospherics/pump/ui_data()
@@ -121,14 +122,14 @@
message_admins("[ADMIN_LOOKUPFLW(usr)] turned on a pump that contains [n2o ? "N2O" : ""][n2o && plasma ? " & " : ""][plasma ? "Plasma" : ""] at [ADMIN_VERBOSEJMP(src)]")
log_admin("[key_name(usr)] turned on a pump that contains [n2o ? "N2O" : ""][n2o && plasma ? " & " : ""][plasma ? "Plasma" : ""] at [AREACOORD(src)]")
else if(on && direction == PUMP_OUT)
investigate_log("[key_name(usr)] started a transfer into [holding].<br>", INVESTIGATE_ATMOS)
investigate_log("[key_name(usr)] started a transfer into [holding].", INVESTIGATE_ATMOS)
. = TRUE
if("direction")
if(direction == PUMP_OUT)
direction = PUMP_IN
else
if(on && holding)
investigate_log("[key_name(usr)] started a transfer into [holding].<br>", INVESTIGATE_ATMOS)
investigate_log("[key_name(usr)] started a transfer into [holding].", INVESTIGATE_ATMOS)
direction = PUMP_OUT
. = TRUE
if("pressure")
@@ -142,19 +143,14 @@
else if(pressure == "max")
pressure = PUMP_MAX_PRESSURE
. = TRUE
else if(pressure == "input")
pressure = input("New release pressure ([PUMP_MIN_PRESSURE]-[PUMP_MAX_PRESSURE] kPa):", name, pump.target_pressure) as num|null
if(!isnull(pressure) && !..())
. = TRUE
else if(text2num(pressure) != null)
pressure = text2num(pressure)
. = TRUE
if(.)
pump.target_pressure = CLAMP(round(pressure), PUMP_MIN_PRESSURE, PUMP_MAX_PRESSURE)
pump.target_pressure = clamp(round(pressure), PUMP_MIN_PRESSURE, PUMP_MAX_PRESSURE)
investigate_log("was set to [pump.target_pressure] kPa by [key_name(usr)].", INVESTIGATE_ATMOS)
if("eject")
if(holding)
holding.forceMove(drop_location())
holding = null
replace_tank(usr, FALSE)
. = TRUE
update_icon()
@@ -2,6 +2,8 @@
name = "portable air scrubber"
icon_state = "pscrubber:0"
density = TRUE
ui_x = 320
ui_y = 350
var/on = FALSE
var/volume_rate = 1000
@@ -71,7 +73,7 @@
datum/tgui/master_ui = null, datum/ui_state/state = GLOB.physical_state)
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
if(!ui)
ui = new(user, src, ui_key, "portable_scrubber", name, 320, 335, master_ui, state)
ui = new(user, src, ui_key, "PortableScrubber", name, ui_x, ui_y, master_ui, state)
ui.open()
/obj/machinery/portable_atmospherics/scrubber/ui_data()
+290 -209
View File
@@ -1,246 +1,327 @@
/// Station home gateway
GLOBAL_DATUM(the_gateway, /obj/machinery/gateway/centerstation)
/// List of possible gateway destinations.
GLOBAL_LIST_EMPTY(gateway_destinations)
/**
* Corresponds to single entry in gateway control.
*
* Will NOT be added automatically to GLOB.gateway_destinations list.
*/
/datum/gateway_destination
var/name = "Unknown Destination"
var/wait = 0 /// How long after roundstart this destination becomes active
var/enabled = TRUE /// If disabled, the destination won't be availible
var/hidden = FALSE /// Will not show on gateway controls at all.
/* Can a gateway link to this destination right now. */
/datum/gateway_destination/proc/is_availible()
return enabled && (world.time - SSticker.round_start_time >= wait)
/* Returns user-friendly description why you can't connect to this destination, displayed in UI */
/datum/gateway_destination/proc/get_availible_reason()
. = "Unreachable"
if(world.time - SSticker.round_start_time < wait)
. = "Connection desynchronized. Recalibration in progress."
/* Check if the movable is allowed to arrive at this destination (exile implants mostly) */
/datum/gateway_destination/proc/incoming_pass_check(atom/movable/AM)
return TRUE
/* Get the actual turf we'll arrive at */
/datum/gateway_destination/proc/get_target_turf()
CRASH("get target turf not implemented for this destination type")
/* Called after moving the movable to target turf */
/datum/gateway_destination/proc/post_transfer(atom/movable/AM)
if (ismob(AM))
var/mob/M = AM
if (M.client)
M.client.move_delay = max(world.time + 5, M.client.move_delay)
/* Called when gateway activates with this destination. */
/datum/gateway_destination/proc/activate(obj/machinery/gateway/activated)
return
/* Called when gateway targeting this destination deactivates. */
/datum/gateway_destination/proc/deactivate(obj/machinery/gateway/deactivated)
return
/* Returns data used by gateway controller ui */
/datum/gateway_destination/proc/get_ui_data()
. = list()
.["ref"] = REF(src)
.["name"] = name
.["availible"] = is_availible()
.["reason"] = get_availible_reason()
if(wait)
.["timeout"] = max(1 - (wait - (world.time - SSticker.round_start_time)) / wait, 0)
/* Destination is another gateway */
/datum/gateway_destination/gateway
/// The gateway this destination points at
var/obj/machinery/gateway/target_gateway
/* We set the target gateway target to activator gateway */
/datum/gateway_destination/gateway/activate(obj/machinery/gateway/activated)
if(!target_gateway.target)
target_gateway.activate(activated)
/* We turn off the target gateway if it's linked with us */
/datum/gateway_destination/gateway/deactivate(obj/machinery/gateway/deactivated)
if(target_gateway.target == deactivated.destination)
target_gateway.deactivate()
/datum/gateway_destination/gateway/is_availible()
return ..() && target_gateway.calibrated && !target_gateway.target && target_gateway.powered()
/datum/gateway_destination/gateway/get_availible_reason()
. = ..()
if(!target_gateway.calibrated)
. = "Exit gateway malfunction. Manual recalibration required."
if(target_gateway.target)
. = "Exit gateway in use."
if(!target_gateway.powered())
. = "Exit gateway unpowered."
/datum/gateway_destination/gateway/get_target_turf()
return get_step(target_gateway.portal,SOUTH)
/datum/gateway_destination/gateway/post_transfer(atom/movable/AM)
. = ..()
addtimer(CALLBACK(AM,/atom/movable.proc/setDir,SOUTH),0)
/* Special home destination, so we can check exile implants */
/datum/gateway_destination/gateway/home
/datum/gateway_destination/gateway/home/incoming_pass_check(atom/movable/AM)
if(isliving(AM))
if(check_exile_implant(AM))
return FALSE
else
for(var/mob/living/L in AM.contents)
if(check_exile_implant(L))
target_gateway.say("Rejecting [AM]: Exile implant detected in contained lifeform.")
return FALSE
if(AM.has_buckled_mobs())
for(var/mob/living/L in AM.buckled_mobs)
if(check_exile_implant(L))
target_gateway.say("Rejecting [AM]: Exile implant detected in close proximity lifeform.")
return FALSE
return TRUE
/datum/gateway_destination/gateway/home/proc/check_exile_implant(mob/living/L)
for(var/obj/item/implant/exile/E in L.implants)//Checking that there is an exile implant
to_chat(L, "<span class='userdanger'>The station gate has detected your exile implant and is blocking your entry.</span>")
return TRUE
return FALSE
/* Destination is one ore more turfs - created by landmarks */
/datum/gateway_destination/point
var/list/target_turfs = list()
/// Used by away landmarks
var/id
/datum/gateway_destination/point/get_target_turf()
return pick(target_turfs)
/* Dense invisible object starting the teleportation. Created by gateways on activation. */
/obj/effect/gateway_portal_bumper
var/obj/machinery/gateway/gateway
density = TRUE
invisibility = INVISIBILITY_ABSTRACT
/obj/effect/gateway_portal_bumper/Bumped(atom/movable/AM)
if(get_dir(src,AM) == SOUTH)
gateway.Transfer(AM)
/obj/effect/gateway_portal_bumper/Destroy(force)
. = ..()
gateway = null
/obj/machinery/gateway
name = "gateway"
desc = "A mysterious gateway built by unknown hands, it allows for faster than light travel to far-flung locations."
icon = 'icons/obj/machines/gateway.dmi'
icon_state = "off"
density = TRUE
resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | UNACIDABLE | ACID_PROOF
var/active = 0
var/checkparts = TRUE
var/list/obj/effect/landmark/randomspawns = list()
// 3x2 offset by one row
pixel_x = -32
pixel_y = -32
bound_height = 64
bound_width = 96
bound_x = -32
bound_y = 0
density = TRUE
use_power = IDLE_POWER_USE
idle_power_usage = 100
active_power_usage = 5000
var/calibrated = TRUE
var/list/linked = list()
var/can_link = FALSE //Is this the centerpiece?
/// Type of instanced gateway destination, needs to be subtype of /datum/gateway_destination/gateway
var/destination_type = /datum/gateway_destination/gateway
/// Name of the generated destination
var/destination_name = "Unknown Gateway"
/// This is our own destination, pointing at this gateway
var/datum/gateway_destination/gateway/destination
/// This is current active destination
var/datum/gateway_destination/target
/// bumper object, the thing that starts actual teleport
var/obj/effect/gateway_portal_bumper/portal
/obj/machinery/gateway/Initialize()
randomspawns = GLOB.awaydestinations
generate_destination()
update_icon()
if(!istype(src, /obj/machinery/gateway/centerstation) && !istype(src, /obj/machinery/gateway/centeraway))
switch(dir)
if(SOUTH,SOUTHEAST,SOUTHWEST)
density = FALSE
return ..()
/obj/machinery/gateway/proc/toggleoff()
for(var/obj/machinery/gateway/G in linked)
G.active = 0
G.update_icon()
active = 0
/obj/machinery/gateway/proc/generate_destination()
destination = new destination_type
destination.name = destination_name
destination.target_gateway = src
GLOB.gateway_destinations += destination
/obj/machinery/gateway/proc/deactivate()
var/datum/gateway_destination/dest = target
target = null
dest.deactivate(src)
QDEL_NULL(portal)
use_power = IDLE_POWER_USE
update_icon()
/obj/machinery/gateway/proc/detect()
if(!can_link)
return FALSE
linked = list() //clear the list
var/turf/T = loc
var/ready = FALSE
for(var/i in GLOB.alldirs)
T = get_step(loc, i)
var/obj/machinery/gateway/G = locate(/obj/machinery/gateway) in T
if(G)
linked.Add(G)
continue
//this is only done if we fail to find a part
ready = FALSE
toggleoff()
break
if((linked.len == 8) || !checkparts)
ready = TRUE
return ready
/obj/machinery/gateway/process()
if((stat & (NOPOWER)) && use_power)
if(target)
deactivate()
return
/obj/machinery/gateway/update_icon_state()
icon_state = active ? "on" : "off"
if(target)
icon_state = "on"
else
icon_state = "off"
/obj/machinery/gateway/attack_hand(mob/user)
. = ..()
if(.)
return
if(!detect())
return
if(!active)
toggleon(user)
return
toggleoff()
/obj/machinery/gateway/proc/toggleon(mob/user)
return FALSE
/obj/machinery/gateway/safe_throw_at()
/obj/machinery/gateway/safe_throw_at(atom/target, range, speed, mob/thrower, spin = TRUE, diagonals_first = FALSE, datum/callback/callback, force = MOVE_FORCE_STRONG, gentle = FALSE)
return
/obj/machinery/gateway/proc/generate_bumper()
portal = new(get_turf(src))
portal.gateway = src
/obj/machinery/gateway/proc/activate(datum/gateway_destination/D)
if(!powered() || target)
return
target = D
target.activate(destination)
generate_bumper()
use_power = ACTIVE_POWER_USE
update_icon()
/obj/machinery/gateway/proc/Transfer(atom/movable/AM)
if(!target || !target.incoming_pass_check(AM))
return
AM.forceMove(target.get_target_turf())
target.post_transfer(AM)
/* Station's primary gateway */
/obj/machinery/gateway/centerstation
destination_type = /datum/gateway_destination/gateway/home
destination_name = "Home Gateway"
/obj/machinery/gateway/centerstation/Initialize()
. = ..()
if(!GLOB.the_gateway)
GLOB.the_gateway = src
update_icon()
wait = world.time + CONFIG_GET(number/gateway_delay) //+ thirty minutes default
awaygate = locate(/obj/machinery/gateway/centeraway)
/obj/machinery/gateway/centerstation/Destroy()
if(GLOB.the_gateway == src)
GLOB.the_gateway = null
return ..()
//this is da important part wot makes things go
/obj/machinery/gateway/centerstation
density = TRUE
icon_state = "offcenter"
use_power = IDLE_POWER_USE
//warping vars
var/wait = 0 //this just grabs world.time at world start
var/obj/machinery/gateway/centeraway/awaygate = null
can_link = TRUE
/obj/machinery/gateway/centerstation/update_icon_state()
icon_state = active ? "oncenter" : "offcenter"
/obj/machinery/gateway/centerstation/process()
if((stat & (NOPOWER)) && use_power)
if(active)
toggleoff()
return
if(active)
use_power(5000)
/obj/machinery/gateway/centerstation/toggleon(mob/user)
if(!detect())
return
if(!powered())
return
if(!awaygate)
to_chat(user, "<span class='notice'>Error: No destination found.</span>")
return
if(world.time < wait)
to_chat(user, "<span class='notice'>Error: Warpspace triangulation in progress. Estimated time to completion: [DisplayTimeText(wait - world.time)].</span>")
return
for(var/obj/machinery/gateway/G in linked)
G.active = 1
G.update_icon()
active = 1
update_icon()
//okay, here's the good teleporting stuff
/obj/machinery/gateway/centerstation/Bumped(atom/movable/AM)
if(!active)
return
if(!detect())
return
if(!awaygate || QDELETED(awaygate))
return
if(awaygate.calibrated)
AM.forceMove(get_step(awaygate.loc, SOUTH))
AM.setDir(SOUTH)
if (ismob(AM))
var/mob/M = AM
if (M.client)
M.client.move_delay = max(world.time + 5, M.client.move_delay)
return
/obj/machinery/gateway/multitool_act(mob/living/user, obj/item/I)
if(calibrated)
to_chat(user, "<span class='alert'>The gate is already calibrated, there is no work for you to do here.</span>")
else
var/obj/effect/landmark/dest = pick(randomspawns)
if(dest)
AM.forceMove(get_turf(dest))
AM.setDir(SOUTH)
use_power(5000)
return
/obj/machinery/gateway/centeraway/attackby(obj/item/W, mob/user, params)
if(istype(W, /obj/item/multitool))
if(calibrated)
to_chat(user, "\black The gate is already calibrated, there is no work for you to do here.")
return
else
to_chat(user, "<span class='boldnotice'>Recalibration successful!</span>: \black This gate's systems have been fine tuned. Travel to this gate will now be on target.")
calibrated = TRUE
return
/////////////////////////////////////Away////////////////////////
/obj/machinery/gateway/centeraway
density = TRUE
icon_state = "offcenter"
use_power = NO_POWER_USE
var/obj/machinery/gateway/centerstation/stationgate = null
can_link = TRUE
/obj/machinery/gateway/centeraway/Initialize()
. = ..()
update_icon()
stationgate = locate(/obj/machinery/gateway/centerstation)
/obj/machinery/gateway/centeraway/update_icon_state()
icon_state = active ? "oncenter" : "offcenter"
/obj/machinery/gateway/centeraway/toggleon(mob/user)
if(!detect())
return
if(!stationgate)
to_chat(user, "<span class='notice'>Error: No destination found.</span>")
return
for(var/obj/machinery/gateway/G in linked)
G.active = 1
G.update_icon()
active = 1
update_icon()
/obj/machinery/gateway/centeraway/proc/check_exile_implant(mob/living/L)
for(var/obj/item/implant/exile/E in L.implants)//Checking that there is an exile implant
to_chat(L, "\black The station gate has detected your exile implant and is blocking your entry.")
return TRUE
return FALSE
/obj/machinery/gateway/centeraway/Bumped(atom/movable/AM)
if(!detect())
return
if(!active)
return
if(!stationgate || QDELETED(stationgate))
return
if(isliving(AM))
if(check_exile_implant(AM))
return
else
for(var/mob/living/L in AM.contents)
if(check_exile_implant(L))
say("Rejecting [AM]: Exile implant detected in contained lifeform.")
return
if(AM.has_buckled_mobs())
for(var/mob/living/L in AM.buckled_mobs)
if(check_exile_implant(L))
say("Rejecting [AM]: Exile implant detected in close proximity lifeform.")
return
AM.forceMove(get_step(stationgate.loc, SOUTH))
AM.setDir(SOUTH)
if (ismob(AM))
var/mob/M = AM
if (M.client)
M.client.move_delay = max(world.time + 5, M.client.move_delay)
/obj/machinery/gateway/centeraway/admin
desc = "A mysterious gateway built by unknown hands, this one seems more compact."
/obj/machinery/gateway/centeraway/admin/Initialize()
. = ..()
if(stationgate && !stationgate.awaygate)
stationgate.awaygate = src
/obj/machinery/gateway/centeraway/admin/detect()
to_chat(user, "<span class='boldnotice'>Recalibration successful!</span>: \black This gate's systems have been fine tuned. Travel to this gate will now be on target.")
calibrated = TRUE
return TRUE
/* Doesn't need control console or power, always links to home when interacting. */
/obj/machinery/gateway/away
density = TRUE
use_power = NO_POWER_USE
/obj/machinery/gateway/away/interact(mob/user, special_state)
. = ..()
if(!target)
if(!GLOB.the_gateway)
to_chat(user,"<span class='warning'>Home gateway is not responding!</span>")
if(GLOB.the_gateway.target)
to_chat(user,"<span class='warning'>Home gateway already in use!</span>")
return
activate(GLOB.the_gateway.destination)
else
deactivate()
/* Gateway control computer */
/obj/machinery/computer/gateway_control
name = "Gateway Control"
desc = "Human friendly interface to the mysterious gate next to it."
var/obj/machinery/gateway/G
/obj/machinery/computer/gateway_control/Initialize(mapload, obj/item/circuitboard/C)
. = ..()
try_to_linkup()
/obj/machinery/computer/gateway_control/ui_interact(mob/user, ui_key = "main", datum/tgui/ui, force_open, datum/tgui/master_ui, 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, "Gateway", name, ui_x, ui_y, master_ui, state)
ui.open()
/obj/machinery/computer/gateway_control/ui_data(mob/user)
. = ..()
.["gateway_present"] = G
.["gateway_status"] = G ? G.powered() : FALSE
.["current_target"] = G?.target?.get_ui_data()
var/list/destinations = list()
if(G)
for(var/datum/gateway_destination/D in GLOB.gateway_destinations)
if(D == G.destination)
continue
destinations += list(D.get_ui_data())
.["destinations"] = destinations
/obj/machinery/computer/gateway_control/ui_act(action, list/params)
. = ..()
if(.)
return
switch(action)
if("linkup")
try_to_linkup()
return TRUE
if("activate")
var/datum/gateway_destination/D = locate(params["destination"]) in GLOB.gateway_destinations
try_to_connect(D)
return TRUE
if("deactivate")
if(G && G.target)
G.deactivate()
return TRUE
/obj/machinery/computer/gateway_control/proc/try_to_linkup()
G = locate(/obj/machinery/gateway) in view(7,get_turf(src))
/obj/machinery/computer/gateway_control/proc/try_to_connect(datum/gateway_destination/D)
if(!D || !G)
return
if(!D.is_availible() || G.target)
return
G.activate(D)
/obj/item/paper/fluff/gateway
info = "Congratulations,<br><br>Your station has been selected to carry out the Gateway Project.<br><br>The equipment will be shipped to you at the start of the next quarter.<br> You are to prepare a secure location to house the equipment as outlined in the attached documents.<br><br>--Nanotrasen Blue Space Research"
info = "Congratulations,<br><br>Your station has been selected to carry out the Gateway Project.<br><br>The equipment will be shipped to you at the start of the next quarter.<br> You are to prepare a secure location to house the equipment as outlined in the attached documents.<br><br>--Nanotrasen Bluespace Research"
name = "Confidential Correspondence, Pg 1"
+1 -1
View File
@@ -55,7 +55,7 @@ force_open = FALSE, datum/tgui/master_ui = null, datum/ui_state/state = GLOB.adm
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
if(!ui)
ui = new(user, src, ui_key, "centcom_podlauncher", "Config/Launch Supplypod", 700, 700, master_ui, state)
ui = new(user, src, ui_key, "CentcomPodLauncher", "Config/Launch Supplypod", 700, 700, master_ui, state)
ui.open()
/datum/centcom_podlauncher/ui_data(mob/user) //Sends info about the pod to the UI.
+32 -5
View File
@@ -68,15 +68,18 @@
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, "cargo", name, ui_x, ui_y, master_ui, state)
ui = new(user, src, ui_key, "Cargo", name, ui_x, ui_y, master_ui, state)
ui.open()
/obj/machinery/computer/cargo/ui_data()
var/list/data = list()
data["location"] = SSshuttle.supply.getStatusText()
/*var/datum/bank_account/D = SSeconomy.get_dep_account(ACCOUNT_CAR)
if(D)
data["points"] = D.account_balance*/
data["away"] = SSshuttle.supply.getDockedId() == "supply_away"
//data["self_paid"] = self_paid
data["docked"] = SSshuttle.supply.mode == SHUTTLE_IDLE
data["points"] = SSshuttle.points
data["loan"] = !!SSshuttle.shuttle_loan
data["loan_dispatched"] = SSshuttle.shuttle_loan && SSshuttle.shuttle_loan.dispatched
var/message = "Remember to stamp and send back the supply manifests."
@@ -92,6 +95,7 @@
"cost" = SO.pack.cost,
"id" = SO.id,
"orderer" = SO.orderer,
"paid" = !isnull(SO.paying_account) //paid by requester
))
data["requests"] = list()
@@ -124,6 +128,7 @@
"cost" = P.cost,
"id" = pack,
"desc" = P.desc || P.name, // If there is a description, use it. Otherwise use the pack's name.
//"small_item" = P.small_item,
"access" = P.access
))
return data
@@ -162,6 +167,8 @@
else
SSshuttle.shuttle_loan.loan_shuttle()
say("The supply shuttle has been loaned to CentCom.")
investigate_log("[key_name(usr)] accepted a shuttle loan event.", INVESTIGATE_CARGO)
log_game("[key_name(usr)] accepted a shuttle loan event.")
. = TRUE
if("add")
var/id = text2path(params["id"])
@@ -182,19 +189,36 @@
name = usr.real_name
rank = "Silicon"
/* var/datum/bank_account/account
if(self_paid && ishuman(usr))
var/mob/living/carbon/human/H = usr
var/obj/item/card/id/id_card = H.get_idcard(TRUE)
if(!istype(id_card))
say("No ID card detected.")
return
account = id_card.registered_account
if(!istype(account))
say("Invalid bank account.")
return
*/
var/reason = ""
if(requestonly)
if(requestonly && !self_paid)
reason = stripped_input("Reason:", name, "")
if(isnull(reason) || ..())
return
var/turf/T = get_turf(src)
var/datum/supply_order/SO = new(pack, name, rank, ckey, reason)
var/datum/supply_order/SO = new(pack, name, rank, ckey, reason, account)
SO.generateRequisition(T)
if(requestonly)
if(requestonly && !self_paid)
SSshuttle.requestlist += SO
else
SSshuttle.shoppinglist += SO
if(self_paid)
say("Order processed. The price will be charged to [account.account_holder]'s bank account on delivery.")
if(requestonly && message_cooldown < world.time)
radio.talk_into(src, "A new order has been requested.", RADIO_CHANNEL_SUPPLY)
message_cooldown = world.time + 30 SECONDS
. = TRUE
if("remove")
var/id = text2num(params["id"])
@@ -224,6 +248,9 @@
if("denyall")
SSshuttle.requestlist.Cut()
. = TRUE
/* if("toggleprivate")
self_paid = !self_paid
*/ . = TRUE
if(.)
post_signal("supply")
+36 -28
View File
@@ -1,5 +1,5 @@
#define MAX_EMAG_ROCKETS 8
#define BEACON_COST 5000
#define BEACON_COST 500
#define SP_LINKED 1
#define SP_READY 2
#define SP_LAUNCH 3
@@ -13,8 +13,11 @@
All sales are near instantaneous - please choose carefully"
icon_screen = "supply_express"
circuit = /obj/item/circuitboard/computer/cargo/express
ui_x = 600
ui_y = 700
blockade_warning = "Bluespace instability detected. Delivery impossible."
req_access = list(ACCESS_QM)
var/message
var/printed_beacons = 0 //number of beacons printed. Used to determine beacon names.
var/list/meme_pack_data
@@ -40,7 +43,7 @@
to_chat(user, "<span class='notice'>You [locked ? "lock" : "unlock"] the interface.</span>")
return
else if(istype(W, /obj/item/disk/cargo/bluespace_pod))
podType = /obj/structure/closet/supplypod/bluespacepod
podType = /obj/structure/closet/supplypod/bluespacepod//doesnt effect circuit board, making reversal possible
to_chat(user, "<span class='notice'>You insert the disk into [src], allowing for advanced supply delivery vehicles.</span>")
qdel(W)
return TRUE
@@ -50,22 +53,20 @@
sb.link_console(src, user)
return TRUE
else
to_chat(user, "<span class='notice'>[src] is already linked to [sb].</span>")
to_chat(user, "<span class='alert'>[src] is already linked to [sb].</span>")
..()
/obj/machinery/computer/cargo/express/emag_act(mob/living/user)
. = SEND_SIGNAL(src, COMSIG_ATOM_EMAG_ACT)
if(obj_flags & EMAGGED)
return
user.visible_message("<span class='warning'>[user] swipes a suspicious card through [src]!</span>",
"<span class='notice'>You change the routing protocols, allowing the Supply Pod to land anywhere on the station.</span>")
if(user)
user.visible_message("<span class='warning'>[user] swipes a suspicious card through [src]!</span>",
"<span class='notice'>You change the routing protocols, allowing the Supply Pod to land anywhere on the station.</span>")
obj_flags |= EMAGGED
// This also sets this on the circuit board
var/obj/item/circuitboard/computer/cargo/board = circuit
board.obj_flags |= EMAGGED
packin_up()
req_access = list()
return TRUE
/obj/machinery/computer/cargo/express/proc/packin_up() // oh shit, I'm sorry
meme_pack_data = list() // sorry for what?
@@ -90,23 +91,25 @@
/obj/machinery/computer/cargo/express/ui_interact(mob/living/user, ui_key = "main", datum/tgui/ui = null, force_open = 0, datum/tgui/master_ui = null, datum/ui_state/state = GLOB.default_state) // Remember to use the appropriate state.
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
if(!ui)
ui = new(user, src, ui_key, "cargo_express", name, 600, 700, master_ui, state)
ui = new(user, src, ui_key, "CargoExpress", name, ui_x, ui_y, master_ui, state)
ui.open()
/obj/machinery/computer/cargo/express/ui_data(mob/user)
var/canBeacon = beacon && (isturf(beacon.loc) || ismob(beacon.loc))//is the beacon in a valid location?
var/list/data = list()
var/datum/bank_account/D = SSeconomy.get_dep_account(ACCOUNT_CAR)
if(D)
data["points"] = D.account_balance
data["locked"] = locked//swipe an ID to unlock
data["siliconUser"] = hasSiliconAccessInArea(user)
data["siliconUser"] = user.has_unlimited_silicon_privilege
data["beaconzone"] = beacon ? get_area(beacon) : ""//where is the beacon located? outputs in the tgui
data["usingBeacon"] = usingBeacon //is the mode set to deliver to the beacon or the cargobay?
data["canBeacon"] = !usingBeacon || canBeacon //is the mode set to beacon delivery, and is the beacon in a valid location?
data["canBuyBeacon"] = cooldown <= 0 && SSshuttle.points >= BEACON_COST
data["canBuyBeacon"] = cooldown <= 0 && D.account_balance >= BEACON_COST
data["beaconError"] = usingBeacon && !canBeacon ? "(BEACON ERROR)" : ""//changes button text to include an error alert if necessary
data["hasBeacon"] = beacon != null//is there a linked beacon?
data["beaconName"] = beacon ? beacon.name : "No Beacon Found"
data["printMsg"] = cooldown > 0 ? "Print Beacon for [BEACON_COST] credits ([cooldown])" : "Print Beacon for [BEACON_COST] credits"//buttontext for printing beacons
data["points"] = SSshuttle.points
data["supplies"] = list()
message = "Sales are near-instantaneous - please choose carefully."
if(SSshuttle.supplyBlocked)
@@ -137,13 +140,15 @@
if (beacon)
beacon.update_status(SP_READY) //turns on the beacon's ready light
if("printBeacon")
if (SSshuttle.points >= BEACON_COST)
cooldown = 10//a ~ten second cooldown for printing beacons to prevent spam
var/obj/item/supplypod_beacon/C = new /obj/item/supplypod_beacon(drop_location())
C.link_console(src, usr)//rather than in beacon's Initialize(), we can assign the computer to the beacon by reusing this proc)
printed_beacons++//printed_beacons starts at 0, so the first one out will be called beacon # 1
beacon.name = "Supply Pod Beacon #[printed_beacons]"
SSshuttle.points -= BEACON_COST
var/datum/bank_account/D = SSeconomy.get_dep_account(ACCOUNT_CAR)
if(D)
if(D.adjust_money(-BEACON_COST))
cooldown = 10//a ~ten second cooldown for printing beacons to prevent spam
var/obj/item/supplypod_beacon/C = new /obj/item/supplypod_beacon(drop_location())
C.link_console(src, usr)//rather than in beacon's Initialize(), we can assign the computer to the beacon by reusing this proc)
printed_beacons++//printed_beacons starts at 0, so the first one out will be called beacon # 1
beacon.name = "Supply Pod Beacon #[printed_beacons]"
if("add")//Generate Supply Order first
var/id = text2path(params["id"])
@@ -163,8 +168,12 @@
var/reason = ""
var/list/empty_turfs
var/datum/supply_order/SO = new(pack, name, rank, ckey, reason)
var/points_to_check
var/datum/bank_account/D = SSeconomy.get_dep_account(ACCOUNT_CAR)
if(D)
points_to_check = D.account_balance
if(!(obj_flags & EMAGGED))
if(SO.pack.cost <= SSshuttle.points)
if(SO.pack.cost <= points_to_check)
var/LZ
if (istype(beacon) && usingBeacon)//prioritize beacons over landing in cargobay
LZ = get_turf(beacon)
@@ -181,14 +190,13 @@
CHECK_TICK
if(empty_turfs && empty_turfs.len)
LZ = pick(empty_turfs)
if (SO.pack.cost <= SSshuttle.points && LZ)//we need to call the cost check again because of the CHECK_TICK call
SSshuttle.points -= SO.pack.cost
SSblackbox.record_feedback("nested tally", "cargo_imports", 1, list("[SO.pack.cost]", "[SO.pack.name]"))
new /obj/effect/abstract/DPtarget(LZ, podType, SO)
if (SO.pack.cost <= points_to_check && LZ)//we need to call the cost check again because of the CHECK_TICK call
D.adjust_money(-SO.pack.cost)
new /obj/effect/DPtarget(LZ, podType, SO)
. = TRUE
update_icon()
else
if(SO.pack.cost * (0.72*MAX_EMAG_ROCKETS) <= SSshuttle.points) // bulk discount :^)
if(SO.pack.cost * (0.72*MAX_EMAG_ROCKETS) <= points_to_check) // bulk discount :^)
landingzone = GLOB.areas_by_type[pick(GLOB.the_station_areas)] //override default landing zone
for(var/turf/open/floor/T in landingzone.contents)
if(is_blocked_turf(T))
@@ -196,13 +204,13 @@
LAZYADD(empty_turfs, T)
CHECK_TICK
if(empty_turfs && empty_turfs.len)
SSshuttle.points -= SO.pack.cost * (0.72*MAX_EMAG_ROCKETS)
SSblackbox.record_feedback("nested tally", "cargo_imports", MAX_EMAG_ROCKETS, list("[SO.pack.cost * 0.72]", "[SO.pack.name]"))
D.adjust_money(-(SO.pack.cost * (0.72*MAX_EMAG_ROCKETS)))
SO.generateRequisition(get_turf(src))
for(var/i in 1 to MAX_EMAG_ROCKETS)
var/LZ = pick(empty_turfs)
LAZYREMOVE(empty_turfs, LZ)
new /obj/effect/abstract/DPtarget(LZ, podType, SO)
new /obj/effect/DPtarget(LZ, podType, SO)
. = TRUE
update_icon()
CHECK_TICK
+109 -101
View File
@@ -5,7 +5,7 @@
max_occurrences = 1
min_players = 10
earliest_start = 30 MINUTES
gamemode_blacklist = list("nuclear","dynamic")
gamemode_blacklist = list("nuclear")
/datum/round_event_control/pirates/preRunEvent()
if (!SSmapping.empty_space)
@@ -15,8 +15,9 @@
/datum/round_event/pirates
startWhen = 60 //2 minutes to answer
var/datum/comm_message/threat_message
var/datum/comm_message/threat
var/payoff = 0
var/payoff_min = 20000
var/paid_off = FALSE
var/ship_name = "Space Privateers Association"
var/shuttle_spawned = FALSE
@@ -25,30 +26,38 @@
ship_name = pick(strings(PIRATE_NAMES_FILE, "ship_names"))
/datum/round_event/pirates/announce(fake)
priority_announce("A report has been downloaded and printed out at all communications consoles.", "Incoming Classified Message", "commandreport") // CITADEL EDIT metabreak
priority_announce("Incoming subspace communication. Secure channel opened at all communication consoles.", "Incoming Message", 'sound/ai/commandreport.ogg')
if(fake)
return
threat_message = new
payoff = round(SSshuttle.points * 0.80)
threat_message.title = "Business proposition"
threat_message.content = "This is [ship_name]. Pay up [payoff] credits or you'll walk the plank."
threat_message.possible_answers = list("We'll pay.","No way.")
threat_message.answer_callback = CALLBACK(src,.proc/answered)
SScommunications.send_message(threat_message,unique = TRUE)
threat = new
var/datum/bank_account/D = SSeconomy.get_dep_account(ACCOUNT_CAR)
if(D)
payoff = max(payoff_min, FLOOR(D.account_balance * 0.80, 1000))
threat.title = "Business proposition"
threat.content = "This is [ship_name]. Pay up [payoff] credits or you'll walk the plank."
threat.possible_answers = list("We'll pay.","No way.")
threat.answer_callback = CALLBACK(src,.proc/answered)
SScommunications.send_message(threat,unique = TRUE)
/datum/round_event/pirates/proc/answered()
if(threat_message && threat_message.answered == 1)
if(SSshuttle.points >= payoff)
SSshuttle.points -= payoff
priority_announce("Thanks for the credits, landlubbers.",sender_override = ship_name)
paid_off = TRUE
return
else
priority_announce("Trying to cheat us? You'll regret this!",sender_override = ship_name)
if(threat && threat.answered == 1)
var/datum/bank_account/D = SSeconomy.get_dep_account(ACCOUNT_CAR)
if(D)
if(D.adjust_money(-payoff))
priority_announce("Thanks for the credits, landlubbers.", sender_override = ship_name)
paid_off = TRUE
return
else
priority_announce("Trying to cheat us? You'll regret this!", sender_override = ship_name)
if(!shuttle_spawned)
spawn_shuttle()
else
priority_announce("Too late to beg for mercy!", sender_override = ship_name)
/datum/round_event/pirates/start()
if(threat && !threat.answered)
threat.possible_answers = list("Too late")
threat.answered = 1
if(!paid_off && !shuttle_spawned)
spawn_shuttle()
@@ -59,8 +68,8 @@
shuffle_inplace(candidates)
var/datum/map_template/shuttle/pirate/default/ship = new
var/x = rand(TRANSITIONEDGE,world.maxx - TRANSITIONEDGE - ship.width)
var/y = rand(TRANSITIONEDGE,world.maxy - TRANSITIONEDGE - ship.height)
var/x = rand(TRANSITIONEDGE, world.maxx - TRANSITIONEDGE - ship.width)
var/y = rand(TRANSITIONEDGE, world.maxy - TRANSITIONEDGE - ship.height)
var/z = SSmapping.empty_space.z_value
var/turf/T = locate(x,y,z)
if(!T)
@@ -68,16 +77,18 @@
if(!ship.load(T))
CRASH("Loading pirate ship failed!")
for(var/turf/A in ship.get_affected_turfs(T))
for(var/obj/effect/mob_spawn/human/pirate/spawner in A)
if(candidates.len > 0)
var/mob/M = candidates[1]
spawner.create(M.ckey)
candidates -= M
announce_to_ghosts(M)
else
notify_ghosts("Space pirates are waking up!", source = spawner, action=NOTIFY_ATTACK, flashwindow = FALSE, ignore_dnr_observers = TRUE)
announce_to_ghosts(spawner)
priority_announce("A report has been downloaded and printed out at all communications consoles.", "Incoming Classified Message", "commandreport") //CITADEL EDIT also metabreak here too
priority_announce("Unidentified armed ship detected near the station.")
//Shuttle equipment
@@ -94,16 +105,16 @@
/obj/machinery/shuttle_scrambler/Initialize(mapload)
. = ..()
gps = new/obj/item/gps/internal/pirate(src)
gps.tracking = FALSE
update_icon()
/obj/machinery/shuttle_scrambler/process()
if(active)
if(is_station_level(z))
var/siphoned = min(SSshuttle.points,siphon_per_tick)
SSshuttle.points -= siphoned
credits_stored += siphoned
var/datum/bank_account/D = SSeconomy.get_dep_account(ACCOUNT_CAR)
if(D)
var/siphoned = min(D.account_balance,siphon_per_tick)
D.adjust_money(-siphoned)
credits_stored += siphoned
interrupt_research()
else
return
@@ -122,7 +133,7 @@
if(!active)
if(alert(user, "Turning the scrambler on will make the shuttle trackable by GPS. Are you sure you want to do it?", "Scrambler", "Yes", "Cancel") == "Cancel")
return
if(active || !user.canUseTopic(src))
if(active || !user.canUseTopic(src, BE_CLOSE))
return
toggle_on(user)
update_icon()
@@ -139,14 +150,12 @@
new /obj/effect/temp_visual/emp(get_turf(S))
/obj/machinery/shuttle_scrambler/proc/dump_loot(mob/user)
if(credits_stored < 200)
to_chat(user,"<span class='notice'>Not enough credits to retrieve.</span>")
return
while(credits_stored >= 200)
new /obj/item/stack/spacecash/c200(drop_location())
credits_stored -= 200
to_chat(user,"<span class='notice'>You retrieve the siphoned credits!</span>")
credits_stored = 0
if(credits_stored) // Prevents spamming empty holochips
new /obj/item/holochip(drop_location(), credits_stored)
to_chat(user,"<span class='notice'>You retrieve the siphoned credits!</span>")
credits_stored = 0
else
to_chat(user,"<span class='notice'>There's nothing to withdraw.</span>")
/obj/machinery/shuttle_scrambler/proc/send_notification()
priority_announce("Data theft signal detected, source registered on local gps units.")
@@ -171,7 +180,6 @@
/obj/item/gps/internal/pirate
gpstag = "Nautical Signal"
desc = "You can hear shanties over the static."
/obj/machinery/computer/shuttle/pirate
name = "pirate shuttle console"
shuttleId = "pirateship"
@@ -195,40 +203,19 @@
/obj/docking_port/mobile/pirate
name = "pirate shuttle"
id = "pirateship"
var/engines_cooling = FALSE
var/engine_cooldown = 3 MINUTES
/obj/docking_port/mobile/pirate/getStatusText()
. = ..()
if(engines_cooling)
return "[.] - Engines cooling."
/obj/docking_port/mobile/pirate/initiate_docking(obj/docking_port/stationary/new_dock, movement_direction, force=FALSE)
. = ..()
if(. == DOCKING_SUCCESS && !is_reserved_level(new_dock.z))
engines_cooling = TRUE
addtimer(CALLBACK(src,.proc/reset_cooldown),engine_cooldown,TIMER_UNIQUE)
/obj/docking_port/mobile/pirate/proc/reset_cooldown()
engines_cooling = FALSE
/obj/docking_port/mobile/pirate/canMove()
if(engines_cooling)
return FALSE
return ..()
rechargeTime = 3 MINUTES
/obj/machinery/suit_storage_unit/pirate
suit_type = /obj/item/clothing/suit/space
helmet_type = /obj/item/clothing/head/helmet/space
mask_type = /obj/item/clothing/mask/breath
storage_type = /obj/item/tank/jetpack/void
storage_type = /obj/item/tank/internals/oxygen
/obj/machinery/loot_locator
name = "Booty Locator"
desc = "This sophisticated machine scans the nearby space for items of value."
icon = 'icons/obj/machines/research.dmi'
icon_state = "tdoppler"
resistance_flags = INDESTRUCTIBLE
density = TRUE
var/cooldown = 300
var/next_use = 0
@@ -262,13 +249,13 @@
name = "cargo hold pad"
icon = 'icons/obj/telescience.dmi'
icon_state = "lpad-idle-o"
resistance_flags = INDESTRUCTIBLE
var/idle_state = "lpad-idle-o"
var/warmup_state = "lpad-idle"
var/sending_state = "lpad-beam"
var/cargo_hold_id
/obj/machinery/piratepad/multitool_act(mob/living/user, obj/item/multitool/I)
. = ..()
if (istype(I))
to_chat(user, "<span class='notice'>You register [src] in [I]s buffer.</span>")
I.buffer = src
@@ -276,8 +263,9 @@
/obj/machinery/computer/piratepad_control
name = "cargo hold control terminal"
resistance_flags = INDESTRUCTIBLE
var/status_report = "Idle"
ui_x = 600
ui_y = 230
var/status_report = "Ready for delivery."
var/obj/machinery/piratepad/pad
var/warmup_time = 100
var/sending = FALSE
@@ -291,10 +279,10 @@
return INITIALIZE_HINT_LATELOAD
/obj/machinery/computer/piratepad_control/multitool_act(mob/living/user, obj/item/multitool/I)
. = ..()
if (istype(I) && istype(I.buffer,/obj/machinery/piratepad))
to_chat(user, "<span class='notice'>You link [src] with [I.buffer] in [I] buffer.</span>")
pad = I.buffer
updateDialog()
return TRUE
/obj/machinery/computer/piratepad_control/LateInitialize()
@@ -307,29 +295,44 @@
else
pad = locate() in range(4,src)
/obj/machinery/computer/piratepad_control/ui_interact(mob/user)
. = ..()
var/list/t = list()
t += "<div class='statusDisplay'>Cargo Hold Control<br>"
t += "Current cargo value : [points]"
t += "</div>"
if(!pad)
t += "<div class='statusDisplay'>No pad located.</div><BR>"
else
t += "<br>[status_report]<br>"
if(!sending)
t += "<a href='?src=[REF(src)];recalc=1;'>Recalculate Value</a><a href='?src=[REF(src)];send=1'>Send</a>"
else
t += "<a href='?src=[REF(src)];stop=1'>Stop sending</a>"
/obj/machinery/computer/piratepad_control/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)
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
if(!ui)
ui = new(user, src, ui_key, "CargoHoldTerminal", name, ui_x, ui_y, master_ui, state)
ui.open()
var/datum/browser/popup = new(user, "piratepad", name, 300, 500)
popup.set_content(t.Join())
popup.open()
/obj/machinery/computer/piratepad_control/ui_data(mob/user)
var/list/data = list()
data["points"] = points
data["pad"] = pad ? TRUE : FALSE
data["sending"] = sending
data["status_report"] = status_report
return data
/obj/machinery/computer/piratepad_control/ui_act(action, params)
if(..())
return
if(!pad)
return
switch(action)
if("recalc")
recalc()
. = TRUE
if("send")
start_sending()
. = TRUE
if("stop")
stop_sending()
. = TRUE
/obj/machinery/computer/piratepad_control/proc/recalc()
if(sending)
return
status_report = "Predicted value:<br>"
status_report = "Predicted value: "
var/value = 0
var/datum/export_report/ex = new
for(var/atom/movable/AM in get_turf(pad))
if(AM == pad)
@@ -337,7 +340,12 @@
export_item_and_contents(AM, EXPORT_PIRATE | EXPORT_CARGO | EXPORT_CONTRABAND | EXPORT_EMAG, apply_elastic = FALSE, dry_run = TRUE, external_report = ex)
for(var/datum/export/E in ex.total_amount)
status_report += E.total_printout(ex,notes = FALSE) + "<br>"
status_report += E.total_printout(ex,notes = FALSE)
status_report += " "
value += ex.total_value[E]
if(!value)
status_report += "0"
/obj/machinery/computer/piratepad_control/proc/send()
if(!sending)
@@ -350,14 +358,15 @@
continue
export_item_and_contents(AM, EXPORT_PIRATE | EXPORT_CARGO | EXPORT_CONTRABAND | EXPORT_EMAG, apply_elastic = FALSE, delete_unsold = FALSE, external_report = ex)
status_report = "Sold:<br>"
status_report = "Sold: "
var/value = 0
for(var/datum/export/E in ex.total_amount)
var/export_text = E.total_printout(ex,notes = FALSE) //Don't want nanotrasen messages, makes no sense here.
if(!export_text)
continue
status_report += export_text + "<br>"
status_report += export_text
status_report += " "
value += ex.total_value[E]
if(!total_report)
@@ -370,11 +379,13 @@
points += value
if(!value)
status_report += "Nothing"
pad.visible_message("<span class='notice'>[pad] activates!</span>")
flick(pad.sending_state,pad)
pad.icon_state = pad.idle_state
sending = FALSE
updateDialog()
/obj/machinery/computer/piratepad_control/proc/start_sending()
if(sending)
@@ -389,24 +400,10 @@
if(!sending)
return
sending = FALSE
status_report = "Idle"
status_report = "Ready for delivery."
pad.icon_state = pad.idle_state
deltimer(sending_timer)
/obj/machinery/computer/piratepad_control/Topic(href, href_list)
if(..())
return
if(pad)
if(href_list["recalc"])
recalc()
if(href_list["send"])
start_sending()
if(href_list["stop"])
stop_sending()
updateDialog()
else
updateDialog()
/datum/export/pirate
export_category = EXPORT_PIRATE
@@ -431,6 +428,8 @@
var/mob/living/carbon/human/H = AM
if(H.stat != CONSCIOUS || !H.mind || !H.mind.assigned_role) //mint condition only
return 0
else if("pirate" in H.faction) //can't ransom your fellow pirates to CentCom!
return 0
else
if(H.mind.assigned_role in GLOB.command_positions)
return 3000
@@ -456,3 +455,12 @@
/datum/export/pirate/cash/get_amount(obj/O)
var/obj/item/stack/spacecash/C = O
return ..() * C.amount * C.value
/datum/export/pirate/holochip
cost = 1
unit_name = "holochip"
export_types = list(/obj/item/holochip)
/datum/export/pirate/holochip/get_cost(atom/movable/AM)
var/obj/item/holochip/H = AM
return H.credits
@@ -160,7 +160,7 @@
/obj/machinery/smartfridge/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)
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
if(!ui)
ui = new(user, src, ui_key, "smartvend", name, 440, 550, master_ui, state)
ui = new(user, src, ui_key, "SmartVend", name, 440, 550, master_ui, state)
ui.set_autoupdate(FALSE)
ui.open()
+1 -1
View File
@@ -83,7 +83,7 @@
/obj/machinery/computer/holodeck/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)
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
if(!ui)
ui = new(user, src, ui_key, "holodeck", name, 400, 500, master_ui, state)
ui = new(user, src, ui_key, "Holodeck", name, 400, 500, master_ui, state)
ui.open()
/obj/machinery/computer/holodeck/ui_data(mob/user)
+1 -1
View File
@@ -11,7 +11,7 @@
/datum/language_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.language_menu_state)
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
if(!ui)
ui = new(user, src, ui_key, "language_menu", "Language Menu", 700, 600, master_ui, state)
ui = new(user, src, ui_key, "LanguageMenu", "Language Menu", 700, 600, master_ui, state)
ui.open()
/datum/language_menu/ui_data(mob/user)
+1 -1
View File
@@ -99,7 +99,7 @@
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, "codex_gigas", name, 450, 450, master_ui, state)
ui = new(user, src, ui_key, "CodexGigas", name, 450, 450, master_ui, state)
ui.open()
/obj/item/book/codex_gigas/ui_data(mob/user)
+1 -1
View File
@@ -209,7 +209,7 @@
/obj/structure/chisel_message/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, datum/tgui/master_ui = null, datum/ui_state/state = GLOB.always_state)
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
if(!ui)
ui = new(user, src, ui_key, "engraved_message", name, 600, 300, master_ui, state)
ui = new(user, src, ui_key, "EngravedMessage", name, 600, 300, master_ui, state)
ui.open()
/obj/structure/chisel_message/ui_data(mob/user)
@@ -8,6 +8,9 @@ GLOBAL_LIST(labor_sheet_values)
icon = 'icons/obj/machines/mining_machines.dmi'
icon_state = "console"
density = FALSE
ui_x = 315
ui_y = 430
var/obj/machinery/mineral/stacking_machine/laborstacker/stacking_machine = null
var/machinedir = SOUTH
var/obj/machinery/door/airlock/release_door
@@ -36,7 +39,7 @@ GLOBAL_LIST(labor_sheet_values)
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, "labor_claim_console", name, 315, 430, master_ui, state)
ui = new(user, src, ui_key, "LaborClaimConsole", name, ui_x, ui_y, master_ui, state)
ui.open()
/obj/machinery/mineral/labor_claim_console/ui_data(mob/user)
@@ -100,7 +103,6 @@ GLOBAL_LIST(labor_sheet_values)
Radio.talk_into(src, "A prisoner has returned to the station. Minerals and Prisoner ID card ready for retrieval.", FREQ_SECURITY)
to_chat(usr, "<span class='notice'>Shuttle received message and will be sent shortly.</span>")
. = TRUE
/obj/machinery/mineral/labor_claim_console/proc/locate_stacking_machine()
stacking_machine = locate(/obj/machinery/mineral/stacking_machine, get_step(src, machinedir))
@@ -110,19 +112,16 @@ GLOBAL_LIST(labor_sheet_values)
qdel(src)
/obj/machinery/mineral/labor_claim_console/emag_act(mob/user)
. = ..()
if(obj_flags & EMAGGED)
return
obj_flags |= EMAGGED
to_chat(user, "<span class='warning'>PZZTTPFFFT</span>")
return TRUE
if(!(obj_flags & EMAGGED))
obj_flags |= EMAGGED
to_chat(user, "<span class='warning'>PZZTTPFFFT</span>")
/**********************Prisoner Collection Unit**************************/
/obj/machinery/mineral/stacking_machine/laborstacker
force_connect = TRUE
var/points = 0 //The unclaimed value of ore stacked.
damage_deflection = 21
/obj/machinery/mineral/stacking_machine/laborstacker/process_sheet(obj/item/stack/sheet/inp)
points += inp.point_value * inp.amount
..()
+1 -1
View File
@@ -193,7 +193,7 @@
/obj/machinery/mineral/ore_redemption/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)
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
if(!ui)
ui = new(user, src, ui_key, "ore_redemption_machine", "Ore Redemption Machine", 440, 550, master_ui, state)
ui = new(user, src, ui_key, "OreRedemptionMachine", "Ore Redemption Machine", 440, 550, master_ui, state)
ui.open()
/obj/machinery/mineral/ore_redemption/ui_data(mob/user)
+16 -4
View File
@@ -93,10 +93,22 @@
else
icon_state = "[initial(icon_state)]-off"
/obj/machinery/mineral/equipment_vendor/ui_interact(mob/user)
. = ..()
var/list/dat = list()
dat += "<br><b>Equipment point cost list:</b><BR><table border='0' width='300'>"
/obj/machinery/mineral/equipment_vendor/ui_base_html(html)
var/datum/asset/spritesheet/assets = get_asset_datum(/datum/asset/spritesheet/vending)
. = replacetext(html, "<!--customheadhtml-->", assets.css_tag())
/obj/machinery/mineral/equipment_vendor/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)
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
if(!ui)
var/datum/asset/assets = get_asset_datum(/datum/asset/spritesheet/vending)
assets.send(user)
ui = new(user, src, ui_key, "MiningVendor", name, ui_x, ui_y, master_ui, state)
ui.open()
/obj/machinery/mineral/equipment_vendor/ui_static_data(mob/user)
. = list()
.["product_records"] = list()
for(var/datum/data/mining_equipment/prize in prize_list)
dat += "<tr><td>[prize.equipment_name]</td><td>[prize.cost]</td><td><A href='?src=[REF(src)];purchase=[REF(prize)]'>Purchase</A></td></tr>"
dat += "</table>"
+92 -76
View File
@@ -6,11 +6,14 @@
icon = 'icons/obj/economy.dmi'
icon_state = "coinpress0"
density = TRUE
var/newCoins = 0 //how many coins the machine made in it's last load
input_dir = EAST
ui_x = 300
ui_y = 250
needs_item_input = TRUE
var/produced_coins = 0 // how many coins the machine has made in it's last cycle
var/processing = FALSE
var/chosen = /datum/material/iron //which material will be used to make coins
var/coinsToProduce = 10
speed_process = TRUE
/obj/machinery/mineral/mint/Initialize()
@@ -28,89 +31,102 @@
/datum/material/mythril,
/datum/material/plastic,
/datum/material/runite
), MINERAL_MATERIAL_AMOUNT * 50, FALSE, /obj/item/stack)
chosen = SSmaterials.GetMaterialRef(chosen)
), MINERAL_MATERIAL_AMOUNT * 75, FALSE, /obj/item/stack)
chosen = SSmaterials.GetMaterialRef(chosen)
/obj/machinery/mineral/mint/process()
var/turf/T = get_step(src, input_dir)
if(!T)
/obj/machinery/mineral/mint/pickup_item(datum/source, atom/movable/target, atom/oldLoc)
if(!istype(target, /obj/item/stack))
return
var/datum/component/material_container/materials = GetComponent(/datum/component/material_container)
for(var/obj/item/stack/sheet/O in T)
var/inserted = materials.insert_item(O)
if(inserted)
qdel(O)
var/obj/item/stack/S = target
/obj/machinery/mineral/mint/attack_hand(mob/user)
if(materials.insert_item(S))
qdel(S)
/obj/machinery/mineral/mint/process()
if(processing)
var/datum/component/material_container/materials = GetComponent(/datum/component/material_container)
var/datum/material/M = chosen
if(!M)
processing = FALSE
icon_state = "coinpress0"
return
icon_state = "coinpress1"
var/coin_mat = MINERAL_MATERIAL_AMOUNT
for(var/sheets in 1 to 2)
if(materials.use_amount_mat(coin_mat, chosen))
for(var/coin_to_make in 1 to 5)
create_coins()
produced_coins++
else
var/found_new = FALSE
for(var/datum/material/inserted_material in materials.materials)
var/amount = materials.get_material_amount(inserted_material)
if(amount)
chosen = inserted_material
found_new = TRUE
if(!found_new)
processing = FALSE
else
end_processing()
icon_state = "coinpress0"
/obj/machinery/mineral/mint/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)
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
if(!ui)
ui = new(user, src, ui_key, "Mint", name, ui_x, ui_y, master_ui, state)
ui.open()
/obj/machinery/mineral/mint/ui_data()
var/list/data = list()
data["inserted_materials"] = list()
data["chosen_material"] = null
var/datum/component/material_container/materials = GetComponent(/datum/component/material_container)
for(var/datum/material/inserted_material in materials.materials)
var/amount = materials.get_material_amount(inserted_material)
if(!amount)
continue
data["inserted_materials"] += list(list(
"material" = inserted_material.name,
"amount" = amount,
))
if(chosen == inserted_material)
data["chosen_material"] = inserted_material.name
data["produced_coins"] = produced_coins
data["processing"] = processing
return data;
/obj/machinery/mineral/mint/ui_act(action, params, datum/tgui/ui)
. = ..()
if(.)
return
var/dat = "<b>Coin Press</b><br>"
var/datum/component/material_container/materials = GetComponent(/datum/component/material_container)
for(var/datum/material/M in materials.materials)
var/amount = materials.get_material_amount(M)
if(!amount && chosen != M)
continue
dat += "<br><b>[M.name] amount:</b> [amount] cm<sup>3</sup> "
if (chosen == M)
dat += "<b>Chosen</b>"
else
dat += "<A href='?src=[REF(src)];choose=[REF(M)]'>Choose</A>"
var/datum/material/M = chosen
dat += "<br><br>Will produce [coinsToProduce] [lowertext(M.name)] coins if enough materials are available.<br>"
dat += "<A href='?src=[REF(src)];chooseAmt=-10'>-10</A> "
dat += "<A href='?src=[REF(src)];chooseAmt=-5'>-5</A> "
dat += "<A href='?src=[REF(src)];chooseAmt=-1'>-1</A> "
dat += "<A href='?src=[REF(src)];chooseAmt=1'>+1</A> "
dat += "<A href='?src=[REF(src)];chooseAmt=5'>+5</A> "
dat += "<A href='?src=[REF(src)];chooseAmt=10'>+10</A> "
dat += "<br><br>In total this machine produced <font color='green'><b>[newCoins]</b></font> coins."
dat += "<br><A href='?src=[REF(src)];makeCoins=[1]'>Make coins</A>"
user << browse(dat, "window=mint")
/obj/machinery/mineral/mint/Topic(href, href_list)
if(..())
return
usr.set_machine(src)
src.add_fingerprint(usr)
if(processing==1)
to_chat(usr, "<span class='notice'>The machine is processing.</span>")
return
var/datum/component/material_container/materials = GetComponent(/datum/component/material_container)
if(href_list["choose"])
var/datum/material/new_material = locate(href_list["choose"])
if(istype(new_material))
chosen = new_material
if(href_list["chooseAmt"])
coinsToProduce = CLAMP(coinsToProduce + text2num(href_list["chooseAmt"]), 0, 1000)
updateUsrDialog()
if(href_list["makeCoins"])
var/temp_coins = coinsToProduce
if(action == "startpress")
if (!processing)
produced_coins = 0
processing = TRUE
icon_state = "coinpress1"
var/coin_mat = MINERAL_MATERIAL_AMOUNT * 0.2
var/datum/material/M = chosen
if(!M)
updateUsrDialog()
return
while(coinsToProduce > 0 && materials.use_amount_mat(coin_mat, chosen))
create_coins()
coinsToProduce--
newCoins++
src.updateUsrDialog()
sleep(5)
icon_state = "coinpress0"
begin_processing()
return TRUE
if (action == "stoppress")
processing = FALSE
coinsToProduce = temp_coins
src.updateUsrDialog()
return
end_processing()
return TRUE
if (action == "changematerial")
var/datum/component/material_container/materials = GetComponent(/datum/component/material_container)
for(var/datum/material/mat in materials.materials)
if (params["material_name"] == mat.name)
chosen = mat
return TRUE
/obj/machinery/mineral/mint/proc/create_coins()
var/turf/T = get_step(src,output_dir)
+7 -4
View File
@@ -9,6 +9,9 @@
density = TRUE
pressure_resistance = 5*ONE_ATMOSPHERE
var/ui_x = 335
var/ui_y = 415
/obj/structure/ore_box/attackby(obj/item/W, mob/user, params)
if (istype(W, /obj/item/stack/ore))
user.transferItemToLoc(W, src)
@@ -24,16 +27,16 @@
/obj/structure/ore_box/crowbar_act(mob/living/user, obj/item/I)
if(I.use_tool(src, user, 50, volume=50))
user.visible_message("[user] pries \the [src] apart.",
user.visible_message("<span class='notice'>[user] pries \the [src] apart.</span>",
"<span class='notice'>You pry apart \the [src].</span>",
"<span class='italics'>You hear splitting wood.</span>")
"<span class='hear'>You hear splitting wood.</span>")
deconstruct(TRUE, user)
return TRUE
/obj/structure/ore_box/examine(mob/living/user)
if(Adjacent(user) && istype(user))
ui_interact(user)
return ..()
. = ..()
/obj/structure/ore_box/attack_hand(mob/user)
. = ..()
@@ -62,7 +65,7 @@
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, "ore_box", name, 335, 415, master_ui, state)
ui = new(user, src, ui_key, "OreBox", name, ui_x, ui_y, master_ui, state)
ui.open()
/obj/structure/ore_box/ui_data()
@@ -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)
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
if(!ui)
ui = new(user, src, ui_key, "notificationpanel", "Notification Preferences", 270, 360, master_ui, state)
ui = new(user, src, ui_key, "NotificationPreferences", "Notification Preferences", 270, 360, master_ui, state)
ui.open()
/datum/notificationpanel/ui_data(mob/user)
@@ -302,7 +302,7 @@
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
if(!ui)
ui = new(user, src, ui_key, "slime_swap_body", name, 400, 400, master_ui, state)
ui = new(user, src, ui_key, "SlimeBodySwapper", name, 400, 400, master_ui, state)
ui.open()
/datum/action/innate/swap_body/ui_data(mob/user)
@@ -0,0 +1,74 @@
/datum/robot_control
var/mob/living/silicon/ai/owner
/datum/robot_control/New(mob/living/silicon/ai/new_owner)
if(!istype(new_owner))
qdel(src)
owner = new_owner
/datum/robot_control/proc/is_interactable(mob/user)
if(user != owner || owner.incapacitated())
return FALSE
if(owner.control_disabled)
to_chat(user, "<span class='warning'>Wireless control is disabled.</span>")
return FALSE
return TRUE
/datum/robot_control/ui_status(mob/user)
if(is_interactable(user))
return ..()
return UI_CLOSE
/datum/robot_control/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, \
datum/tgui/master_ui = null, datum/ui_state/state = GLOB.always_state)
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
if(!ui)
ui = new(user, src, ui_key, "RemoteRobotControl", "Remote Robot Control", 500, 500, master_ui, state)
ui.open()
/datum/robot_control/ui_data(mob/user)
if(!owner || user != owner)
return
var/list/data = list()
var/turf/ai_current_turf = get_turf(owner)
var/ai_zlevel = ai_current_turf.z
data["robots"] = list()
for(var/mob/living/simple_animal/bot/B in GLOB.bots_list)
if(B.z != ai_zlevel || B.remote_disabled) //Only non-emagged bots on the same Z-level are detected!
continue
var/list/robot_data = list(
name = B.name,
model = B.model,
mode = B.get_mode(),
hacked = B.hacked,
location = get_area_name(B, TRUE),
ref = REF(B)
)
data["robots"] += list(robot_data)
return data
/datum/robot_control/ui_act(action, params)
if(..())
return
if(!is_interactable(usr))
return
switch(action)
if("callbot") //Command a bot to move to a selected location.
if(owner.call_bot_cooldown > world.time)
to_chat(usr, "<span class='danger'>Error: Your last call bot command is still processing, please wait for the bot to finish calculating a route.</span>")
return
owner.Bot = locate(params["ref"]) in GLOB.bots_list
if(!owner.Bot || owner.Bot.remote_disabled || owner.control_disabled)
return
owner.waypoint_mode = TRUE
to_chat(usr, "<span class='notice'>Set your waypoint by clicking on a valid location free of obstructions.</span>")
. = TRUE
if("interface") //Remotely connect to a bot!
owner.Bot = locate(params["ref"]) in GLOB.bots_list
if(!owner.Bot || owner.Bot.remote_disabled || owner.control_disabled)
return
owner.Bot.attack_ai(usr)
. = TRUE
@@ -174,7 +174,7 @@
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, "mulebot", name, ui_x, ui_y, master_ui, state)
ui = new(user, src, ui_key, "Mule", name, ui_x, ui_y, master_ui, state)
ui.open()
/mob/living/simple_animal/bot/mulebot/ui_data(mob/user)
@@ -37,9 +37,9 @@
if (!ui)
var/datum/asset/assets = get_asset_datum(/datum/asset/simple/headers)
assets.send(user)
ui = new(user, src, ui_key, "ntos_main", "NtOS Main menu", 400, 500, master_ui, state)
ui.set_style("ntos")
assets = get_asset_datum(/datum/asset/simple/arcade)
assets.send(user)
ui = new(user, src, ui_key, "NtosMain", "NtOS Main menu", 400, 500, master_ui, state)
ui.open()
ui.set_autoupdate(state = 1)
@@ -7,9 +7,9 @@
requires_ntnet = 0
usage_flags = PROGRAM_CONSOLE
transfer_access = ACCESS_HEADS
available_on_ntnet = 1
tgui_id = "ntos_ai_restorer"
ui_x = 600
available_on_ntnet = TRUE
tgui_id = "NtosAiRestorer"
ui_x = 370
ui_y = 400
var/restoring = FALSE
@@ -118,4 +118,4 @@
/datum/computer_file/program/aidiag/kill_program(forced)
restoring = FALSE
return ..(forced)
return ..(forced)
@@ -7,7 +7,7 @@
requires_ntnet = 1
network_destination = "alarm monitoring network"
size = 5
tgui_id = "ntos_station_alert"
tgui_id = "NtosStationAlertConsole"
ui_x = 315
ui_y = 500
@@ -8,9 +8,8 @@
available_on_ntnet = 0
unsendable = 1
undeletable = 1
tgui_id = "synd_contract"
ui_style = "syndicate"
ui_x = 600
tgui_id = "SyndContractor"
ui_x = 500
ui_y = 600
var/error = ""
var/page = CONTRACT_UPLINK_PAGE_CONTRACTS
@@ -165,4 +164,4 @@
screen_to_be = "assign"
program_icon_state = screen_to_be
update_computer_icon()
return data
return data
@@ -4,11 +4,10 @@
program_icon_state = "hostile"
extended_desc = "This advanced script can perform denial of service attacks against NTNet quantum relays. The system administrator will probably notice this. Multiple devices can run this program together against same relay for increased effect"
size = 20
requires_ntnet = 1
available_on_ntnet = 0
available_on_syndinet = 1
tgui_id = "ntos_net_dos"
ui_style = "syndicate"
requires_ntnet = TRUE
available_on_ntnet = FALSE
available_on_syndinet = TRUE
tgui_id = "NtosNetDos"
ui_x = 400
ui_y = 250
@@ -97,4 +96,4 @@
data["relays"] += list(list("id" = R.uid))
data["focus"] = target ? target.uid : null
return data
return data
@@ -4,11 +4,10 @@
program_icon_state = "hostile"
extended_desc = "This virus can destroy hard drive of system it is executed on. It may be obfuscated to look like another non-malicious program. Once armed, it will destroy the system upon next execution."
size = 13
requires_ntnet = 0
available_on_ntnet = 0
available_on_syndinet = 1
tgui_id = "ntos_revelation"
ui_style = "syndicate"
requires_ntnet = FALSE
available_on_ntnet = FALSE
available_on_syndinet = TRUE
tgui_id = "NtosRevelation"
ui_x = 400
ui_y = 250
@@ -68,4 +67,4 @@
data["armed"] = armed
return data
return data
@@ -0,0 +1,176 @@
/datum/computer_file/program/arcade
filename = "arcade"
filedesc = "Nanotrasen Micro Arcade"
program_icon_state = "arcade"
extended_desc = "This port of the classic game 'Outbomb Cuban Pete', redesigned to run on tablets, with thrilling graphics and chilling storytelling."
requires_ntnet = FALSE
network_destination = "arcade network"
size = 6
tgui_id = "NtosArcade"
ui_x = 450
ui_y = 350
///Returns TRUE if the game is being played.
var/game_active = TRUE
///This disables buttom actions from having any impact if TRUE. Resets to FALSE when the player is allowed to make an action again.
var/pause_state = FALSE
var/boss_hp = 45
var/boss_mp = 15
var/player_hp = 30
var/player_mp = 10
var/ticket_count = 0
///Shows what text is shown on the app, usually showing the log of combat actions taken by the player.
var/heads_up = "Nanotrasen says, winners make us money."
var/boss_name = "Cuban Pete's Minion"
///Determines which boss image to use on the UI.
var/boss_id = 1
/datum/computer_file/program/arcade/proc/game_check(mob/user)
sleep(5)
user?.mind?.adjust_experience(/datum/skill/gaming, 1)
if(boss_hp <= 0)
heads_up = "You have crushed [boss_name]! Rejoice!"
playsound(computer.loc, 'sound/arcade/win.ogg', 50, TRUE, extrarange = -3, falloff = 10)
game_active = FALSE
program_icon_state = "arcade_off"
if(istype(computer))
computer.update_icon()
ticket_count += 1
user?.mind?.adjust_experience(/datum/skill/gaming, 50)
sleep(10)
else if(player_hp <= 0 || player_mp <= 0)
heads_up = "You have been defeated... how will the station survive?"
playsound(computer.loc, 'sound/arcade/lose.ogg', 50, TRUE, extrarange = -3, falloff = 10)
game_active = FALSE
program_icon_state = "arcade_off"
if(istype(computer))
computer.update_icon()
user?.mind?.adjust_experience(/datum/skill/gaming, 10)
sleep(10)
/datum/computer_file/program/arcade/proc/enemy_check(mob/user)
var/boss_attackamt = 0 //Spam protection from boss attacks as well.
var/boss_mpamt = 0
var/bossheal = 0
if(pause_state == TRUE)
boss_attackamt = rand(3,6)
boss_mpamt = rand (2,4)
bossheal = rand (4,6)
if(game_active == FALSE)
return
if (boss_mp <= 5)
heads_up = "[boss_mpamt] magic power has been stolen from you!"
playsound(computer.loc, 'sound/arcade/steal.ogg', 50, TRUE, extrarange = -3, falloff = 10)
player_mp -= boss_mpamt
boss_mp += boss_mpamt
else if(boss_mp > 5 && boss_hp <12)
heads_up = "[boss_name] heals for [bossheal] health!"
playsound(computer.loc, 'sound/arcade/heal.ogg', 50, TRUE, extrarange = -3, falloff = 10)
boss_hp += bossheal
boss_mp -= boss_mpamt
else
heads_up = "[boss_name] attacks you for [boss_attackamt] damage!"
playsound(computer.loc, 'sound/arcade/hit.ogg', 50, TRUE, extrarange = -3, falloff = 10)
player_hp -= boss_attackamt
pause_state = FALSE
game_check()
/datum/computer_file/program/arcade/ui_interact(mob/user, ui_key, datum/tgui/ui, force_open, datum/tgui/master_ui, datum/ui_state/state)
. = ..()
var/datum/asset/assets = get_asset_datum(/datum/asset/simple/arcade)
assets.send(user)
/datum/computer_file/program/arcade/ui_data(mob/user)
var/list/data = get_header_data()
data["Hitpoints"] = boss_hp
data["PlayerHitpoints"] = player_hp
data["PlayerMP"] = player_mp
data["TicketCount"] = ticket_count
data["GameActive"] = game_active
data["PauseState"] = pause_state
data["Status"] = heads_up
data["BossID"] = "boss[boss_id].gif"
return data
/datum/computer_file/program/arcade/ui_act(action, list/params)
if(..())
return TRUE
var/obj/item/computer_hardware/printer/printer
if(computer)
printer = computer.all_components[MC_PRINT]
var/gamerSkillLevel = usr.mind?.get_skill_level(/datum/skill/gaming)
var/gamerSkill = usr.mind?.get_skill_modifier(/datum/skill/gaming, SKILL_RANDS_MODIFIER)
switch(action)
if("Attack")
var/attackamt = 0 //Spam prevention.
if(pause_state == FALSE)
attackamt = rand(2,6) + rand(0, gamerSkill)
pause_state = TRUE
heads_up = "You attack for [attackamt] damage."
playsound(computer.loc, 'sound/arcade/hit.ogg', 50, TRUE, extrarange = -3, falloff = 10)
boss_hp -= attackamt
sleep(10)
game_check()
enemy_check()
return TRUE
if("Heal")
var/healamt = 0 //More Spam Prevention.
var/healcost = 0
if(pause_state == FALSE)
healamt = rand(6,8) + rand(0, gamerSkill)
var/maxPointCost = 3
if(gamerSkillLevel >= SKILL_LEVEL_JOURNEYMAN)
maxPointCost = 2
healcost = rand(1, maxPointCost)
pause_state = TRUE
heads_up = "You heal for [healamt] damage."
playsound(computer.loc, 'sound/arcade/heal.ogg', 50, TRUE, extrarange = -3, falloff = 10)
player_hp += healamt
player_mp -= healcost
sleep(10)
game_check()
enemy_check()
return TRUE
if("Recharge_Power")
var/rechargeamt = 0 //As above.
if(pause_state == FALSE)
rechargeamt = rand(4,7) + rand(0, gamerSkill)
pause_state = TRUE
heads_up = "You regain [rechargeamt] magic power."
playsound(computer.loc, 'sound/arcade/mana.ogg', 50, TRUE, extrarange = -3, falloff = 10)
player_mp += rechargeamt
sleep(10)
game_check()
enemy_check()
return TRUE
if("Dispense_Tickets")
if(!printer)
to_chat(usr, "<span class='notice'>Hardware error: A printer is required to redeem tickets.</span>")
return
if(printer.stored_paper <= 0)
to_chat(usr, "<span class='notice'>Hardware error: Printer is out of paper.</span>")
return
else
computer.visible_message("<span class='notice'>\The [computer] prints out paper.</span>")
if(ticket_count >= 1)
new /obj/item/stack/arcadeticket((get_turf(computer)), 1)
to_chat(usr, "<span class='notice'>[src] dispenses a ticket!</span>")
ticket_count -= 1
printer.stored_paper -= 1
else
to_chat(usr, "<span class='notice'>You don't have any stored tickets!</span>")
return TRUE
if("Start_Game")
game_active = TRUE
boss_hp = 45
player_hp = 30
player_mp = 10
heads_up = "You stand before [boss_name]! Prepare for battle!"
program_icon_state = "arcade"
boss_id = rand(1,6)
pause_state = FALSE
if(istype(computer))
computer.update_icon()
@@ -0,0 +1,33 @@
/datum/computer_file/program/atmosscan
filename = "atmosscan"
filedesc = "Atmospheric Scanner"
program_icon_state = "air"
extended_desc = "A small built-in sensor reads out the atmospheric conditions around the device."
network_destination = "atmos scan"
size = 4
tgui_id = "NtosAtmos"
ui_x = 300
ui_y = 350
/datum/computer_file/program/atmosscan/ui_data(mob/user)
var/list/data = get_header_data()
var/list/airlist = list()
var/turf/T = get_turf(ui_host())
if(T)
var/datum/gas_mixture/environment = T.return_air()
var/list/env_gases = environment.gases
var/pressure = environment.return_pressure()
var/total_moles = environment.total_moles()
data["AirPressure"] = round(pressure,0.1)
data["AirTemp"] = round(environment.temperature-T0C)
if (total_moles)
for(var/id in env_gases)
var/gas_level = env_gases[id][MOLES]/total_moles
if(gas_level > 0)
airlist += list(list("name" = "[env_gases[id][GAS_META][META_GAS_NAME]]", "percentage" = round(gas_level*100, 0.01)))
data["AirData"] = airlist
return data
/datum/computer_file/program/atmosscan/ui_act(action, list/params)
if(..())
return TRUE
@@ -0,0 +1,69 @@
/datum/computer_file/program/borg_monitor
filename = "cyborgmonitor"
filedesc = "Cyborg Remote Monitoring"
ui_header = "borg_mon.gif"
program_icon_state = "generic"
extended_desc = "This program allows for remote monitoring of station cyborgs."
requires_ntnet = TRUE
transfer_access = ACCESS_ROBOTICS
network_destination = "cyborg remote monitoring"
size = 5
tgui_id = "NtosCyborgRemoteMonitor"
ui_x = 600
ui_y = 800
/datum/computer_file/program/borg_monitor/ui_data(mob/user)
var/list/data = get_header_data()
data["card"] = FALSE
if(computer.GetID())
data["card"] = TRUE
data["cyborgs"] = list()
for(var/mob/living/silicon/robot/R in GLOB.silicon_mobs)
if((get_turf(computer)).z != (get_turf(R)).z)
continue
if(R.scrambledcodes)
continue
var/list/upgrade
for(var/obj/item/borg/upgrade/I in R.upgrades)
upgrade += "\[[I.name]\] "
var/shell = FALSE
if(R.shell && !R.ckey)
shell = TRUE
var/list/cyborg_data = list(
name = R.name,
locked_down = R.lockcharge,
status = R.stat,
shell_discon = shell,
charge = R.cell ? round(R.cell.percent()) : null,
module = R.module ? "[R.module.name] Module" : "No Module Detected",
upgrades = upgrade,
ref = REF(R)
)
data["cyborgs"] += list(cyborg_data)
return data
/datum/computer_file/program/borg_monitor/ui_act(action, params)
if(..())
return
switch(action)
if("messagebot")
var/mob/living/silicon/robot/R = locate(params["ref"]) in GLOB.silicon_mobs
if(!istype(R))
return
var/obj/item/card/id/ID = computer.GetID()
if(!ID)
return
var/message = stripped_input(usr, message = "Enter message to be sent to remote cyborg.", title = "Send Message")
if(!message)
return
to_chat(R, "<br><br><span class='notice'>Message from [ID.registered_name] -- \"[message]\"</span><br>")
SEND_SOUND(R, 'sound/machines/twobeep_high.ogg')
if(R.connected_ai)
to_chat(R.connected_ai, "<br><br><span class='notice'>Message from [ID.registered_name] to [R] -- \"[message]\"</span><br>")
SEND_SOUND(R.connected_ai, 'sound/machines/twobeep_high.ogg')
@@ -6,91 +6,84 @@
transfer_access = ACCESS_HEADS
requires_ntnet = 0
size = 8
tgui_id = "ntos_card"
ui_x = 600
ui_y = 700
tgui_id = "NtosCard"
ui_x = 450
ui_y = 520
var/mod_mode = 1
var/is_centcom = 0
var/show_assignments = 0
var/minor = 0
var/authenticated = 0
var/list/reg_ids = list()
var/list/region_access = null
var/list/head_subordinates = null
var/target_dept = 0 //Which department this computer has access to. 0=all departments
var/change_position_cooldown = 30
//Jobs you cannot open new positions for
var/list/blacklisted = list(
"AI",
"Assistant",
"Cyborg",
"Captain",
"Head of Personnel",
"Head of Security",
"Chief Engineer",
"Research Director",
"Chief Medical Officer")
var/is_centcom = FALSE
var/minor = FALSE
var/authenticated = FALSE
var/list/region_access
var/list/head_subordinates
///Which departments this computer has access to. Defined as access regions. null = all departments
var/target_dept
//The scaling factor of max total positions in relation to the total amount of people on board the station in %
var/max_relative_positions = 30 //30%: Seems reasonable, limit of 6 @ 20 players
//For some reason everything was exploding if this was static.
var/list/sub_managers
//This is used to keep track of opened positions for jobs to allow instant closing
//Assoc array: "JobName" = (int)<Opened Positions>
var/list/opened_positions = list();
/datum/computer_file/program/card_mod/New(obj/item/modular_computer/comp)
. = ..()
sub_managers = list(
"[ACCESS_HOP]" = list(
"department" = list(CARDCON_DEPARTMENT_SERVICE, CARDCON_DEPARTMENT_COMMAND),
"region" = 1,
"head" = "Head of Personnel"
),
"[ACCESS_HOS]" = list(
"department" = CARDCON_DEPARTMENT_SECURITY,
"region" = 2,
"head" = "Head of Security"
),
"[ACCESS_CMO]" = list(
"department" = CARDCON_DEPARTMENT_MEDICAL,
"region" = 3,
"head" = "Chief Medical Officer"
),
"[ACCESS_RD]" = list(
"department" = CARDCON_DEPARTMENT_SCIENCE,
"region" = 4,
"head" = "Research Director"
),
"[ACCESS_CE]" = list(
"department" = CARDCON_DEPARTMENT_ENGINEERING,
"region" = 5,
"head" = "Chief Engineer"
)
)
/datum/computer_file/program/card_mod/New()
..()
addtimer(CALLBACK(src, .proc/SetConfigCooldown), 0)
/datum/computer_file/program/card_mod/proc/authenticate(mob/user, obj/item/card/id/id_card)
if(!id_card)
return
/datum/computer_file/program/card_mod/proc/SetConfigCooldown()
change_position_cooldown = CONFIG_GET(number/id_console_jobslot_delay)
region_access = list()
if(!target_dept && (ACCESS_CHANGE_IDS in id_card.access))
minor = FALSE
authenticated = TRUE
update_static_data(user)
return TRUE
/datum/computer_file/program/card_mod/event_idremoved(background, slot)
if(!slot || slot == 2)// slot being false means both are removed
minor = 0
authenticated = 0
head_subordinates = null
region_access = null
var/list/head_types = list()
for(var/access_text in sub_managers)
var/list/info = sub_managers[access_text]
var/access = text2num(access_text)
if((access in id_card.access) && ((info["region"] in target_dept) || !length(target_dept)))
region_access += info["region"]
//I don't even know what I'm doing anymore
head_types += info["head"]
head_subordinates = list()
if(length(head_types))
for(var/j in SSjob.occupations)
var/datum/job/job = j
for(var/head in head_types)//god why
if(head in job.department_head)
head_subordinates += job.title
/datum/computer_file/program/card_mod/proc/job_blacklisted(jobtitle)
return (jobtitle in blacklisted)
//Logic check for if you can open the job
/datum/computer_file/program/card_mod/proc/can_open_job(datum/job/job)
if(job)
if(!job_blacklisted(job.title))
if((job.total_positions <= GLOB.player_list.len * (max_relative_positions / 100)))
var/delta = (world.time / 10) - GLOB.time_last_changed_position
if((change_position_cooldown < delta) || (opened_positions[job.title] < 0))
return 1
return -2
return 0
return 0
//Logic check for if you can close the job
/datum/computer_file/program/card_mod/proc/can_close_job(datum/job/job)
if(job)
if(!job_blacklisted(job.title))
if(job.total_positions > job.current_positions)
var/delta = (world.time / 10) - GLOB.time_last_changed_position
if((change_position_cooldown < delta) || (opened_positions[job.title] > 0))
return 1
return -2
return 0
return 0
/datum/computer_file/program/card_mod/proc/format_jobs(list/jobs)
var/obj/item/computer_hardware/card_slot/card_slot = computer.all_components[MC_CARD]
var/obj/item/card/id/id_card = card_slot.stored_card
var/list/formatted = list()
for(var/job in jobs)
formatted.Add(list(list(
"display_name" = replacetext(job, "&nbsp", " "),
"target_rank" = id_card && id_card.assignment ? id_card.assignment : "Unassigned",
"job" = job)))
if(length(region_access))
minor = TRUE
authenticated = TRUE
update_static_data(user)
return TRUE
return formatted
@@ -0,0 +1,74 @@
/datum/computer_file/program/shipping
filename = "shipping"
filedesc = "Nanotrasen Shipping Scanner"
program_icon_state = "shipping"
extended_desc = "A combination printer/scanner app that enables modular computers to print barcodes for easy scanning and shipping."
network_destination = "ship scanner"
size = 6
tgui_id = "NtosShipping"
ui_x = 450
ui_y = 350
///Account used for creating barcodes.
var/datum/bank_account/payments_acc
///The amount which the tagger will recieve for the sale.
var/percent_cut = 20
/datum/computer_file/program/shipping/ui_data(mob/user)
var/list/data = get_header_data()
var/obj/item/computer_hardware/card_slot/card_slot = computer.all_components[MC_CARD]
var/obj/item/computer_hardware/printer/printer = computer.all_components[MC_PRINT]
var/obj/item/card/id/id_card = card_slot ? card_slot.stored_card : null
data["has_id_slot"] = !!card_slot
data["has_printer"] = !!printer
data["paperamt"] = printer ? "[printer.stored_paper] / [printer.max_paper]" : null
data["card_owner"] = card_slot && card_slot.stored_card ? id_card.registered_name : "No Card Inserted."
data["current_user"] = payments_acc ? payments_acc.account_holder : null
data["barcode_split"] = percent_cut
return data
/datum/computer_file/program/shipping/ui_act(action, list/params)
if(..())
return TRUE
if(!computer)
return
// Get components
var/obj/item/computer_hardware/card_slot/card_slot = computer.all_components[MC_CARD]
var/obj/item/computer_hardware/printer/printer = computer.all_components[MC_PRINT]
var/obj/item/card/id/id_card = card_slot ? card_slot.stored_card : null
if(!card_slot || !printer) //We need both to successfully use this app.
return
switch(action)
if("ejectid")
if(id_card)
card_slot.try_eject(TRUE, usr)
if("selectid")
if(!id_card)
return
if(!id_card.registered_account)
playsound(get_turf(ui_host()), 'sound/machines/buzz-sigh.ogg', 50, TRUE, -1)
return
payments_acc = id_card.registered_account
playsound(get_turf(ui_host()), 'sound/machines/ping.ogg', 50, TRUE, -1)
if("resetid")
payments_acc = null
if("setsplit")
var/potential_cut = input("How much would you like to payout to the registered card?","Percentage Profit") as num|null
percent_cut = potential_cut ? clamp(round(potential_cut, 1), 1, 50) : 20
if("print")
if(!printer)
to_chat(usr, "<span class='notice'>Hardware error: A printer is required to print barcodes.</span>")
return
if(printer.stored_paper <= 0)
to_chat(usr, "<span class='notice'>Hardware error: Printer is out of paper.</span>")
return
if(!payments_acc)
to_chat(usr, "<span class='notice'>Software error: Please set a current user first.</span>")
return
var/obj/item/barcode/barcode = new /obj/item/barcode(get_turf(ui_host()))
barcode.payments_acc = payments_acc
barcode.percent_cut = percent_cut
printer.stored_paper--
to_chat(usr, "<span class='notice'>The computer prints out a barcode.</span>")
@@ -14,7 +14,7 @@
ui_y = 630
available_on_ntnet = 0
requires_ntnet = 0
tgui_id = "ntos_configuration"
tgui_id = "NtosConfiguration"
var/obj/item/modular_computer/movable = null
@@ -0,0 +1,50 @@
/datum/computer_file/program/crew_manifest
filename = "crewmani"
filedesc = "Crew Manifest"
program_icon_state = "id"
extended_desc = "Program for viewing and printing the current crew manifest"
transfer_access = ACCESS_HEADS
requires_ntnet = FALSE
size = 4
tgui_id = "NtosCrewManifest"
ui_x = 400
ui_y = 480
/datum/computer_file/program/crew_manifest/ui_static_data(mob/user)
var/list/data = list()
data["manifest"] = GLOB.data_core.get_manifest()
return data
/datum/computer_file/program/crew_manifest/ui_data(mob/user)
var/list/data = get_header_data()
var/obj/item/computer_hardware/printer/printer
if(computer)
printer = computer.all_components[MC_PRINT]
if(computer)
data["have_printer"] = !!printer
else
data["have_printer"] = FALSE
return data
/datum/computer_file/program/crew_manifest/ui_act(action, params, datum/tgui/ui)
if(..())
return
var/obj/item/computer_hardware/printer/printer
if(computer)
printer = computer.all_components[MC_PRINT]
switch(action)
if("PRG_print")
if(computer && printer) //This option should never be called if there is no printer
var/contents = {"<h4>Crew Manifest</h4>
<br>
[GLOB.data_core ? GLOB.data_core.get_manifest_html(0) : ""]
"}
if(!printer.print_text(contents,text("crew manifest ([])", station_time_timestamp())))
to_chat(usr, "<span class='notice'>Hardware error: Printer was unable to print the file. It may be out of paper.</span>")
return
else
computer.visible_message("<span class='notice'>\The [computer] prints out a paper.</span>")
@@ -4,10 +4,10 @@
extended_desc = "This program allows management of files."
program_icon_state = "generic"
size = 8
requires_ntnet = 0
available_on_ntnet = 0
undeletable = 1
tgui_id = "ntos_file_manager"
requires_ntnet = FALSE
available_on_ntnet = FALSE
undeletable = TRUE
tgui_id = "NtosFileManager"
var/open_file
var/error
@@ -0,0 +1,141 @@
/datum/computer_file/program/job_management
filename = "job_manage"
filedesc = "Job Manager"
program_icon_state = "id"
extended_desc = "Program for viewing and changing job slot avalibility."
transfer_access = ACCESS_HEADS
requires_ntnet = 0
size = 4
tgui_id = "NtosJobManager"
ui_x = 400
ui_y = 620
var/change_position_cooldown = 30
//Jobs you cannot open new positions for
var/list/blacklisted = list(
"AI",
"Assistant",
"Cyborg",
"Captain",
"Head of Personnel",
"Head of Security",
"Chief Engineer",
"Research Director",
"Chief Medical Officer")
//The scaling factor of max total positions in relation to the total amount of people on board the station in %
var/max_relative_positions = 30 //30%: Seems reasonable, limit of 6 @ 20 players
//This is used to keep track of opened positions for jobs to allow instant closing
//Assoc array: "JobName" = (int)<Opened Positions>
var/list/opened_positions = list()
/datum/computer_file/program/job_management/New()
..()
change_position_cooldown = CONFIG_GET(number/id_console_jobslot_delay)
/datum/computer_file/program/job_management/proc/can_open_job(datum/job/job)
if(!(job?.title in blacklisted))
if((job.total_positions <= length(GLOB.player_list) * (max_relative_positions / 100)))
var/delta = (world.time / 10) - GLOB.time_last_changed_position
if((change_position_cooldown < delta) || (opened_positions[job.title] < 0))
return TRUE
return FALSE
/datum/computer_file/program/job_management/proc/can_close_job(datum/job/job)
if(!(job?.title in blacklisted))
if(job.total_positions > length(GLOB.player_list) * (max_relative_positions / 100))
var/delta = (world.time / 10) - GLOB.time_last_changed_position
if((change_position_cooldown < delta) || (opened_positions[job.title] > 0))
return TRUE
return FALSE
/datum/computer_file/program/job_management/ui_act(action, params, datum/tgui/ui)
if(..())
return
var/authed = FALSE
var/mob/user = usr
var/obj/item/card/id/user_id = user.get_idcard()
if(user_id)
if(ACCESS_CHANGE_IDS in user_id.access)
authed = TRUE
if(!authed)
return
switch(action)
if("PRG_open_job")
var/edit_job_target = params["target"]
var/datum/job/j = SSjob.GetJob(edit_job_target)
if(!j || !can_open_job(j))
return
if(opened_positions[edit_job_target] >= 0)
GLOB.time_last_changed_position = world.time / 10
j.total_positions++
opened_positions[edit_job_target]++
playsound(computer, 'sound/machines/terminal_prompt_confirm.ogg', 50, FALSE)
return TRUE
if("PRG_close_job")
var/edit_job_target = params["target"]
var/datum/job/j = SSjob.GetJob(edit_job_target)
if(!j || !can_close_job(j))
return
//Allow instant closing without cooldown if a position has been opened before
if(opened_positions[edit_job_target] <= 0)
GLOB.time_last_changed_position = world.time / 10
j.total_positions--
opened_positions[edit_job_target]--
playsound(computer, 'sound/machines/terminal_prompt_confirm.ogg', 50, FALSE)
return TRUE
if("PRG_priority")
if(length(SSjob.prioritized_jobs) >= 5)
return
var/priority_target = params["target"]
var/datum/job/j = SSjob.GetJob(priority_target)
if(!j)
return
if(j.total_positions <= j.current_positions)
return
if(j in SSjob.prioritized_jobs)
SSjob.prioritized_jobs -= j
else
SSjob.prioritized_jobs += j
playsound(computer, 'sound/machines/terminal_prompt_confirm.ogg', 50, FALSE)
return TRUE
/datum/computer_file/program/job_management/ui_data(mob/user)
var/list/data = get_header_data()
var/authed = FALSE
var/obj/item/card/id/user_id = user.get_idcard(FALSE)
if(user_id)
if(ACCESS_CHANGE_IDS in user_id.access)
authed = TRUE
data["authed"] = authed
var/list/pos = list()
for(var/j in SSjob.occupations)
var/datum/job/job = j
if(job.title in blacklisted)
continue
pos += list(list(
"title" = job.title,
"current" = job.current_positions,
"total" = job.total_positions,
"status_open" = authed ? can_open_job(job) : FALSE,
"status_close" = authed ? can_close_job(job) : FALSE,
))
data["slots"] = pos
var/delta = round(change_position_cooldown - ((world.time / 10) - GLOB.time_last_changed_position), 1)
data["cooldown"] = delta < 0 ? 0 : delta
var/list/priority = list()
for(var/j in SSjob.prioritized_jobs)
var/datum/job/job = j
priority += job.title
data["prioritized"] = priority
return data
@@ -10,7 +10,9 @@
requires_ntnet_feature = NTNET_SOFTWAREDOWNLOAD
available_on_ntnet = 0
ui_header = "downloader_finished.gif"
tgui_id = "ntos_net_downloader"
tgui_id = "NtosNetDownloader"
ui_x = 480
ui_y = 735
var/datum/computer_file/program/downloaded_file = null
var/hacked_download = 0
@@ -168,4 +170,4 @@
/datum/computer_file/program/ntnetdownload/kill_program(forced)
abort_file_download()
return ..(forced)
return ..(forced)
@@ -6,8 +6,8 @@
size = 12
requires_ntnet = 1
required_access = ACCESS_NETWORK //NETWORK CONTROL IS A MORE SECURE PROGRAM.
available_on_ntnet = 1
tgui_id = "ntos_net_monitor"
available_on_ntnet = TRUE
tgui_id = "NtosNetMonitor"
/datum/computer_file/program/ntnetmonitor/ui_act(action, params)
if(..())
@@ -78,4 +78,4 @@
data["ntnetlogs"] += list(list("entry" = i))
data["ntnetmaxlogs"] = SSnetworks.station_network.setting_maxlogcount
return data
return data
@@ -9,7 +9,7 @@
network_destination = "NTNRC server"
ui_header = "ntnrc_idle.gif"
available_on_ntnet = 1
tgui_id = "ntos_net_chat"
tgui_id = "NtosNetChat"
ui_x = 900
ui_y = 675
@@ -11,8 +11,7 @@
requires_ntnet = 0
network_destination = "power monitoring system"
size = 9
tgui_id = "ntos_power_monitor"
ui_style = "ntos"
tgui_id = "NtosPowerMonitor"
ui_x = 550
ui_y = 700

Some files were not shown because too many files have changed in this diff Show More