Updates modular computers, begins work on shuttle stuff.

This commit is contained in:
Artur
2020-04-23 15:06:35 +03:00
parent 0b34e20f56
commit a8aa2e2014
29 changed files with 535 additions and 1091 deletions

View File

@@ -42,6 +42,7 @@
var/synchronizer_coeff = -1 //makes the mutation hurt the user less var/synchronizer_coeff = -1 //makes the mutation hurt the user less
var/power_coeff = -1 //boosts mutation strength var/power_coeff = -1 //boosts mutation strength
var/energy_coeff = -1 //lowers mutation cooldown var/energy_coeff = -1 //lowers mutation cooldown
var/list/valid_chrom_list = list() //List of strings of valid chromosomes this mutation can accept.
/datum/mutation/human/New(class_ = MUT_OTHER, timer, datum/mutation/human/copymut) /datum/mutation/human/New(class_ = MUT_OTHER, timer, datum/mutation/human/copymut)
. = ..() . = ..()
@@ -166,6 +167,7 @@
energy_coeff = HM.energy_coeff energy_coeff = HM.energy_coeff
mutadone_proof = HM.mutadone_proof mutadone_proof = HM.mutadone_proof
can_chromosome = HM.can_chromosome can_chromosome = HM.can_chromosome
valid_chrom_list = HM.valid_chrom_list
/datum/mutation/human/proc/remove_chromosome() /datum/mutation/human/proc/remove_chromosome()
stabilizer_coeff = initial(stabilizer_coeff) stabilizer_coeff = initial(stabilizer_coeff)

View File

@@ -825,6 +825,9 @@
/atom/proc/GenerateTag() /atom/proc/GenerateTag()
return return
/atom/proc/connect_to_shuttle(obj/docking_port/mobile/port, obj/docking_port/stationary/dock, idnum, override=FALSE)
return
// Generic logging helper // Generic logging helper
/atom/proc/log_message(message, message_type, color=null, log_globally=TRUE) /atom/proc/log_message(message, message_type, color=null, log_globally=TRUE)
if(!log_globally) if(!log_globally)

View File

@@ -0,0 +1,31 @@
/obj/item/stack/arcadeticket
name = "arcade tickets"
desc = "Wow! With enough of these, you could buy a bike! ...Pssh, yeah right."
singular_name = "arcade ticket"
icon_state = "arcade-ticket"
item_state = "tickets"
w_class = WEIGHT_CLASS_TINY
max_amount = 30
/obj/item/stack/arcadeticket/Initialize(mapload, new_amount, merge = TRUE)
. = ..()
update_icon()
/obj/item/stack/arcadeticket/update_icon()
var/amount = get_amount()
if((amount >= 12) && (amount > 0))
icon_state = "arcade-ticket_4"
else if((amount >= 6) && (amount > 0))
icon_state = "arcade-ticket_3"
else if((amount >= 2) && (amount > 0))
icon_state = "arcade-ticket_2"
else
icon_state = "arcade-ticket"
/obj/item/stack/arcadeticket/proc/pay_tickets()
amount -= 2
if (amount == 0)
qdel(src)
/obj/item/stack/arcadeticket/thirty
amount = 30

View File

@@ -14,12 +14,14 @@
/datum/syndicate_contract/proc/generate(blacklist) /datum/syndicate_contract/proc/generate(blacklist)
contract.find_target(null, blacklist) contract.find_target(null, blacklist)
var/datum/data/record/record = find_record("name", contract.target.name, GLOB.data_core.general) var/datum/data/record/record
if(contract.target)
record = find_record("name", contract.target.name, GLOB.data_core.general)
if(record) if(record)
target_rank = record.fields["rank"] target_rank = record.fields["rank"]
else else
target_rank = "Unknown" target_rank = "Unknown"
if (payout_type == CONTRACT_PAYOUT_LARGE) if(payout_type == CONTRACT_PAYOUT_LARGE)
contract.payout_bonus = rand(9,13) contract.payout_bonus = rand(9,13)
else if(payout_type == CONTRACT_PAYOUT_MEDIUM) else if(payout_type == CONTRACT_PAYOUT_MEDIUM)
contract.payout_bonus = rand(6,8) contract.payout_bonus = rand(6,8)

View File

@@ -147,7 +147,8 @@
"json2.min.js" = 'code/modules/goonchat/browserassets/js/json2.min.js', "json2.min.js" = 'code/modules/goonchat/browserassets/js/json2.min.js',
"browserOutput.js" = 'code/modules/goonchat/browserassets/js/browserOutput.js', "browserOutput.js" = 'code/modules/goonchat/browserassets/js/browserOutput.js',
"browserOutput.css" = 'code/modules/goonchat/browserassets/css/browserOutput.css', "browserOutput.css" = 'code/modules/goonchat/browserassets/css/browserOutput.css',
"browserOutput_white.css" = 'code/modules/goonchat/browserassets/css/browserOutput_white.css', "browserOutput_dark.css" = 'code/modules/goonchat/browserassets/css/browserOutput_dark.css',
"browserOutput_light.css" = 'code/modules/goonchat/browserassets/css/browserOutput_light.css'
) )
/datum/asset/simple/fontawesome /datum/asset/simple/fontawesome
@@ -200,35 +201,27 @@
"boss4.gif" = 'icons/UI_Icons/Arcade/boss4.gif', "boss4.gif" = 'icons/UI_Icons/Arcade/boss4.gif',
"boss5.gif" = 'icons/UI_Icons/Arcade/boss5.gif', "boss5.gif" = 'icons/UI_Icons/Arcade/boss5.gif',
"boss6.gif" = 'icons/UI_Icons/Arcade/boss6.gif', "boss6.gif" = 'icons/UI_Icons/Arcade/boss6.gif',
)
/datum/asset/spritesheet/simple/achievements
name ="achievements"
assets = list(
"default" = 'icons/UI_Icons/Achievements/default.png',
"basemisc" = 'icons/UI_Icons/Achievements/basemisc.png',
"baseboss" = 'icons/UI_Icons/Achievements/baseboss.png',
"baseskill" = 'icons/UI_Icons/Achievements/baseskill.png',
"bbgum" = 'icons/UI_Icons/Achievements/Boss/bbgum.png',
"colossus" = 'icons/UI_Icons/Achievements/Boss/colossus.png',
"hierophant" = 'icons/UI_Icons/Achievements/Boss/hierophant.png',
"legion" = 'icons/UI_Icons/Achievements/Boss/legion.png',
"miner" = 'icons/UI_Icons/Achievements/Boss/miner.png',
"swarmer" = 'icons/UI_Icons/Achievements/Boss/swarmer.png',
"tendril" = 'icons/UI_Icons/Achievements/Boss/tendril.png',
"featofstrength" = 'icons/UI_Icons/Achievements/Misc/featofstrength.png',
"helbital" = 'icons/UI_Icons/Achievements/Misc/helbital.png',
"jackpot" = 'icons/UI_Icons/Achievements/Misc/jackpot.png',
"meteors" = 'icons/UI_Icons/Achievements/Misc/meteors.png',
"timewaste" = 'icons/UI_Icons/Achievements/Misc/timewaste.png',
"upgrade" = 'icons/UI_Icons/Achievements/Misc/upgrade.png',
"clownking" = 'icons/UI_Icons/Achievements/Misc/clownking.png',
"clownthanks" = 'icons/UI_Icons/Achievements/Misc/clownthanks.png',
"rule8" = 'icons/UI_Icons/Achievements/Misc/rule8.png',
"snail" = 'icons/UI_Icons/Achievements/Misc/snail.png',
"mining" = 'icons/UI_Icons/Achievements/Skills/mining.png',
) )
/datum/asset/spritesheet/simple/minesweeper
name = "minesweeper"
assets = list(
"1" = 'icons/misc/minesweeper_tiles/one.png',
"2" = 'icons/misc/minesweeper_tiles/two.png',
"3" = 'icons/misc/minesweeper_tiles/three.png',
"4" = 'icons/misc/minesweeper_tiles/four.png',
"5" = 'icons/misc/minesweeper_tiles/five.png',
"6" = 'icons/misc/minesweeper_tiles/six.png',
"7" = 'icons/misc/minesweeper_tiles/seven.png',
"8" = 'icons/misc/minesweeper_tiles/eight.png',
"empty" = 'icons/misc/minesweeper_tiles/empty.png',
"flag" = 'icons/misc/minesweeper_tiles/flag.png',
"hidden" = 'icons/misc/minesweeper_tiles/hidden.png',
"mine" = 'icons/misc/minesweeper_tiles/mine.png',
"minehit" = 'icons/misc/minesweeper_tiles/minehit.png'
)
/datum/asset/spritesheet/simple/pills /datum/asset/spritesheet/simple/pills
name ="pills" name ="pills"
assets = list( assets = list(

View File

@@ -85,3 +85,4 @@
var/obj/item/computer_hardware/hard_drive/hard_drive = cpu.all_components[MC_HDD] var/obj/item/computer_hardware/hard_drive/hard_drive = cpu.all_components[MC_HDD]
hard_drive.store_file(new/datum/computer_file/program/chatclient()) hard_drive.store_file(new/datum/computer_file/program/chatclient())
hard_drive.store_file(new/datum/computer_file/program/nttransfer()) hard_drive.store_file(new/datum/computer_file/program/nttransfer())
hard_drive.store_file(new/datum/computer_file/program/arcade())

View File

@@ -1,26 +1,43 @@
// /program/ files are executable programs that do things. // /program/ files are executable programs that do things.
/datum/computer_file/program /datum/computer_file/program
filetype = "PRG" filetype = "PRG"
filename = "UnknownProgram" // File name. FILE NAME MUST BE UNIQUE IF YOU WANT THE PROGRAM TO BE DOWNLOADABLE FROM NTNET! /// File name. FILE NAME MUST BE UNIQUE IF YOU WANT THE PROGRAM TO BE DOWNLOADABLE FROM NTNET!
var/required_access = null // List of required accesses to *run* the program. filename = "UnknownProgram"
var/transfer_access = null // List of required access to download or file host the program /// List of required accesses to *run* the program.
var/program_state = PROGRAM_STATE_KILLED// PROGRAM_STATE_KILLED or PROGRAM_STATE_BACKGROUND or PROGRAM_STATE_ACTIVE - specifies whether this program is running. var/required_access = null
var/obj/item/modular_computer/computer // Device that runs this program. /// List of required access to download or file host the program
var/filedesc = "Unknown Program" // User-friendly name of this program. var/transfer_access = null
var/extended_desc = "N/A" // Short description of this program's function. /// PROGRAM_STATE_KILLED or PROGRAM_STATE_BACKGROUND or PROGRAM_STATE_ACTIVE - specifies whether this program is running.
var/program_icon_state = null // Program-specific screen icon state var/program_state = PROGRAM_STATE_KILLED
var/requires_ntnet = 0 // Set to 1 for program to require nonstop NTNet connection to run. If NTNet connection is lost program crashes. /// Device that runs this program.
var/requires_ntnet_feature = 0 // Optional, if above is set to 1 checks for specific function of NTNet (currently NTNET_SOFTWAREDOWNLOAD, NTNET_PEERTOPEER, NTNET_SYSTEMCONTROL and NTNET_COMMUNICATION) var/obj/item/modular_computer/computer
var/ntnet_status = 1 // NTNet status, updated every tick by computer running this program. Don't use this for checks if NTNet works, computers do that. Use this for calculations, etc. /// User-friendly name of this program.
var/usage_flags = PROGRAM_ALL // Bitflags (PROGRAM_CONSOLE, PROGRAM_LAPTOP, PROGRAM_TABLET combination) or PROGRAM_ALL var/filedesc = "Unknown Program"
var/network_destination = null // Optional string that describes what NTNet server/system this program connects to. Used in default logging. /// Short description of this program's function.
var/available_on_ntnet = 1 // Whether the program can be downloaded from NTNet. Set to 0 to disable. var/extended_desc = "N/A"
var/available_on_syndinet = 0 // Whether the program can be downloaded from SyndiNet (accessible via emagging the computer). Set to 1 to enable. /// Program-specific screen icon state
var/tgui_id // ID of TGUI interface var/program_icon_state = null
var/ui_style // ID of custom TGUI style (optional) /// Set to 1 for program to require nonstop NTNet connection to run. If NTNet connection is lost program crashes.
var/ui_x = 575 // Default size of TGUI window, in pixels var/requires_ntnet = FALSE
/// Optional, if above is set to 1 checks for specific function of NTNet (currently NTNET_SOFTWAREDOWNLOAD, NTNET_PEERTOPEER, NTNET_SYSTEMCONTROL and NTNET_COMMUNICATION)
var/requires_ntnet_feature = 0
/// NTNet status, updated every tick by computer running this program. Don't use this for checks if NTNet works, computers do that. Use this for calculations, etc.
var/ntnet_status = 1
/// Bitflags (PROGRAM_CONSOLE, PROGRAM_LAPTOP, PROGRAM_TABLET combination) or PROGRAM_ALL
var/usage_flags = PROGRAM_ALL
/// Optional string that describes what NTNet server/system this program connects to. Used in default logging.
var/network_destination = null
/// Whether the program can be downloaded from NTNet. Set to 0 to disable.
var/available_on_ntnet = 1
/// Whether the program can be downloaded from SyndiNet (accessible via emagging the computer). Set to 1 to enable.
var/available_on_syndinet = 0
/// ID of TGUI interface
var/tgui_id
/// Default size of TGUI window, in pixels
var/ui_x = 575
var/ui_y = 700 var/ui_y = 700
var/ui_header = null // Example: "something.gif" - a header image that will be rendered in computer's UI when this program is running at background. Images are taken from /icons/program_icons. Be careful not to use too large images! /// Example: "something.gif" - a header image that will be rendered in computer's UI when this program is running at background. Images are taken from /icons/program_icons. Be careful not to use too large images!
var/ui_header = null
/datum/computer_file/program/New(obj/item/modular_computer/comp = null) /datum/computer_file/program/New(obj/item/modular_computer/comp = null)
..() ..()
@@ -50,23 +67,23 @@
/datum/computer_file/program/proc/generate_network_log(text) /datum/computer_file/program/proc/generate_network_log(text)
if(computer) if(computer)
return computer.add_log(text) return computer.add_log(text)
return 0 return FALSE
/datum/computer_file/program/proc/is_supported_by_hardware(hardware_flag = 0, loud = 0, mob/user = null) /datum/computer_file/program/proc/is_supported_by_hardware(hardware_flag = 0, loud = 0, mob/user = null)
if(!(hardware_flag & usage_flags)) if(!(hardware_flag & usage_flags))
if(loud && computer && user) if(loud && computer && user)
to_chat(user, "<span class='danger'>\The [computer] flashes an \"Hardware Error - Incompatible software\" warning.</span>") to_chat(user, "<span class='danger'>\The [computer] flashes an \"Hardware Error - Incompatible software\" warning.</span>")
return 0 return FALSE
return 1 return TRUE
/datum/computer_file/program/proc/get_signal(specific_action = 0) /datum/computer_file/program/proc/get_signal(specific_action = 0)
if(computer) if(computer)
return computer.get_ntnet_status(specific_action) return computer.get_ntnet_status(specific_action)
return 0 return FALSE
// Called by Process() on device that runs us, once every tick. // Called by Process() on device that runs us, once every tick.
/datum/computer_file/program/proc/process_tick() /datum/computer_file/program/proc/process_tick()
return 1 return TRUE
// Check if the user can run program. Only humans can operate computer. Automatically called in run_program() // Check if the user can run program. Only humans can operate computer. Automatically called in run_program()
// User has to wear their ID for ID Scan to work. // User has to wear their ID for ID Scan to work.
@@ -87,7 +104,7 @@
if(IsAdminGhost(user)) if(IsAdminGhost(user))
return TRUE return TRUE
if(computer && computer.hasSiliconAccessInArea(user)) if(issilicon(user))
return TRUE return TRUE
if(ishuman(user)) if(ishuman(user))
@@ -98,6 +115,7 @@
D = card_slot.GetID() D = card_slot.GetID()
var/mob/living/carbon/human/h = user var/mob/living/carbon/human/h = user
var/obj/item/card/id/I = h.get_idcard(TRUE) var/obj/item/card/id/I = h.get_idcard(TRUE)
if(!I && !D) if(!I && !D)
if(loud) if(loud)
to_chat(user, "<span class='danger'>\The [computer] flashes an \"RFID Error - Unable to scan ID\" warning.</span>") to_chat(user, "<span class='danger'>\The [computer] flashes an \"RFID Error - Unable to scan ID\" warning.</span>")
@@ -123,7 +141,7 @@
// This is performed on program startup. May be overridden to add extra logic. Remember to include ..() call. Return 1 on success, 0 on failure. // This is performed on program startup. May be overridden to add extra logic. Remember to include ..() call. Return 1 on success, 0 on failure.
// When implementing new program based device, use this to run the program. // When implementing new program based device, use this to run the program.
/datum/computer_file/program/proc/run_program(mob/living/user) /datum/computer_file/program/proc/run_program(mob/living/user)
if(can_run(user, 1)) if(can_run(user, TRUE))
if(requires_ntnet && network_destination) if(requires_ntnet && network_destination)
generate_network_log("Connection opened to [network_destination].") generate_network_log("Connection opened to [network_destination].")
program_state = PROGRAM_STATE_ACTIVE program_state = PROGRAM_STATE_ACTIVE
@@ -145,10 +163,6 @@
assets.send(user) assets.send(user)
ui = new(user, src, ui_key, tgui_id, filedesc, ui_x, ui_y, state = state) ui = new(user, src, ui_key, tgui_id, filedesc, ui_x, ui_y, state = state)
if(ui_style)
ui.set_style(ui_style)
ui.set_autoupdate(state = 1)
ui.open() ui.open()
// CONVENTIONS, READ THIS WHEN CREATING NEW PROGRAM AND OVERRIDING THIS PROC: // CONVENTIONS, READ THIS WHEN CREATING NEW PROGRAM AND OVERRIDING THIS PROC:
@@ -156,7 +170,7 @@
// Calls beginning with "PRG_" are reserved for programs handling. // Calls beginning with "PRG_" are reserved for programs handling.
// Calls beginning with "PC_" are reserved for computer handling (by whatever runs the program) // Calls beginning with "PC_" are reserved for computer handling (by whatever runs the program)
// ALWAYS INCLUDE PARENT CALL ..() OR DIE IN FIRE. // ALWAYS INCLUDE PARENT CALL ..() OR DIE IN FIRE.
/datum/computer_file/program/ui_act(action,params,datum/tgui/ui) /datum/computer_file/program/ui_act(action,list/params,datum/tgui/ui)
if(..()) if(..())
return TRUE return TRUE
if(computer) if(computer)

View File

@@ -4,14 +4,14 @@
program_icon_state = "generic" program_icon_state = "generic"
extended_desc = "This program is capable of reconstructing damaged AI systems. Requires direct AI connection via intellicard slot." extended_desc = "This program is capable of reconstructing damaged AI systems. Requires direct AI connection via intellicard slot."
size = 12 size = 12
requires_ntnet = 0 requires_ntnet = FALSE
usage_flags = PROGRAM_CONSOLE usage_flags = PROGRAM_CONSOLE | PROGRAM_LAPTOP
transfer_access = ACCESS_HEADS transfer_access = ACCESS_HEADS
available_on_ntnet = TRUE available_on_ntnet = TRUE
tgui_id = "NtosAiRestorer" tgui_id = "NtosAiRestorer"
ui_x = 370 ui_x = 370
ui_y = 400 ui_y = 400
/// Variable dictating if we are in the process of restoring the AI in the inserted intellicard
var/restoring = FALSE var/restoring = FALSE
/datum/computer_file/program/aidiag/proc/get_ai(cardcheck) /datum/computer_file/program/aidiag/proc/get_ai(cardcheck)
@@ -30,11 +30,11 @@
if(ai_slot.stored_card.AI) if(ai_slot.stored_card.AI)
return ai_slot.stored_card.AI return ai_slot.stored_card.AI
return null return
/datum/computer_file/program/aidiag/ui_act(action, params) /datum/computer_file/program/aidiag/ui_act(action, params)
if(..()) if(..())
return TRUE return
var/mob/living/silicon/ai/A = get_ai() var/mob/living/silicon/ai/A = get_ai()
if(!A) if(!A)
@@ -44,6 +44,7 @@
if("PRG_beginReconstruction") if("PRG_beginReconstruction")
if(A && A.health < 100) if(A && A.health < 100)
restoring = TRUE restoring = TRUE
A.notify_ghost_cloning("Your core files are being restored!", source = computer)
return TRUE return TRUE
if("PRG_eject") if("PRG_eject")
if(computer.all_components[MC_AI]) if(computer.all_components[MC_AI])
@@ -53,7 +54,7 @@
return TRUE return TRUE
/datum/computer_file/program/aidiag/process_tick() /datum/computer_file/program/aidiag/process_tick()
..() . = ..()
if(!restoring) //Put the check here so we don't check for an ai all the time if(!restoring) //Put the check here so we don't check for an ai all the time
return return
var/obj/item/aicard/cardhold = get_ai(2) var/obj/item/aicard/cardhold = get_ai(2)
@@ -73,13 +74,13 @@
restoring = FALSE restoring = FALSE
return return
ai_slot.locked =TRUE ai_slot.locked =TRUE
A.adjustOxyLoss(-1, 0) A.adjustOxyLoss(-5, 0)
A.adjustFireLoss(-1, 0) A.adjustFireLoss(-5, 0)
A.adjustToxLoss(-1, 0) A.adjustToxLoss(-5, 0)
A.adjustBruteLoss(-1, 0) A.adjustBruteLoss(-5, 0)
A.updatehealth() A.updatehealth()
if(A.health >= 0 && A.stat == DEAD) if(A.health >= 0 && A.stat == DEAD)
A.revive() A.revive(full_heal = FALSE, admin_revive = FALSE)
// Finished restoring // Finished restoring
if(A.health >= 100) if(A.health >= 100)
ai_slot.locked = FALSE ai_slot.locked = FALSE
@@ -90,14 +91,14 @@
/datum/computer_file/program/aidiag/ui_data(mob/user) /datum/computer_file/program/aidiag/ui_data(mob/user)
var/list/data = get_header_data() var/list/data = get_header_data()
var/mob/living/silicon/ai/AI var/mob/living/silicon/ai/AI = get_ai()
// A shortcut for getting the AI stored inside the computer. The program already does necessary checks.
AI = get_ai()
var/obj/item/aicard/aicard = get_ai(2) var/obj/item/aicard/aicard = get_ai(2)
data["ejectable"] = TRUE
data["AI_present"] = FALSE
data["error"] = null
if(!aicard) if(!aicard)
data["nocard"] = TRUE
data["error"] = "Please insert an intelliCard." data["error"] = "Please insert an intelliCard."
else else
if(!AI) if(!AI)
@@ -107,15 +108,15 @@
if(cardhold.flush) if(cardhold.flush)
data["error"] = "Flush in progress" data["error"] = "Flush in progress"
else else
data["AI_present"] = TRUE
data["name"] = AI.name data["name"] = AI.name
data["restoring"] = restoring data["restoring"] = restoring
data["laws"] = AI.laws.get_law_list(include_zeroth = 1)
data["health"] = (AI.health + 100) / 2 data["health"] = (AI.health + 100) / 2
data["isDead"] = AI.stat == DEAD data["isDead"] = AI.stat == DEAD
data["ai_laws"] = AI.laws.get_law_list(include_zeroth = 1) data["laws"] = AI.laws.get_law_list(include_zeroth = 1)
return data return data
/datum/computer_file/program/aidiag/kill_program(forced) /datum/computer_file/program/aidiag/kill_program(forced)
restoring = FALSE restoring = FALSE
return ..(forced) return ..()

View File

@@ -72,15 +72,23 @@
/datum/computer_file/program/alarm_monitor/proc/cancelAlarm(class, area/A, obj/origin) /datum/computer_file/program/alarm_monitor/proc/cancelAlarm(class, area/A, obj/origin)
var/list/L = alarms[class] var/list/L = alarms[class]
var/cleared = 0 var/cleared = 0
var/arealevelalarm = FALSE // set to TRUE for alarms that set/clear whole areas
if (class=="Fire")
arealevelalarm = TRUE
for (var/I in L) for (var/I in L)
if (I == A.name) if (I == A.name)
var/list/alarm = L[I] if (!arealevelalarm) // the traditional behaviour
var/list/srcs = alarm[3] var/list/alarm = L[I]
if (origin in srcs) var/list/srcs = alarm[3]
srcs -= origin if (origin in srcs)
if (srcs.len == 0) srcs -= origin
if (srcs.len == 0)
cleared = 1
L -= I
else
L -= I // wipe the instances entirely
cleared = 1 cleared = 1
L -= I
update_alarm_display() update_alarm_display()
return !cleared return !cleared

View File

@@ -12,15 +12,16 @@
ui_x = 500 ui_x = 500
ui_y = 600 ui_y = 600
var/error = "" var/error = ""
var/page = CONTRACT_UPLINK_PAGE_CONTRACTS var/info_screen = TRUE
var/assigned = FALSE var/assigned = FALSE
var/first_load = TRUE
/datum/computer_file/program/contract_uplink/run_program(var/mob/living/user) /datum/computer_file/program/contract_uplink/run_program(var/mob/living/user)
. = ..(user) . = ..(user)
/datum/computer_file/program/contract_uplink/ui_act(action, params) /datum/computer_file/program/contract_uplink/ui_act(action, params)
if(..()) if(..())
return 1 return TRUE
var/mob/living/user = usr var/mob/living/user = usr
var/obj/item/computer_hardware/hard_drive/small/syndicate/hard_drive = computer.all_components[MC_HDD] var/obj/item/computer_hardware/hard_drive/small/syndicate/hard_drive = computer.all_components[MC_HDD]
switch(action) switch(action)
@@ -30,27 +31,32 @@
hard_drive.traitor_data.contractor_hub.assigned_contracts[contract_id].status = CONTRACT_STATUS_ACTIVE hard_drive.traitor_data.contractor_hub.assigned_contracts[contract_id].status = CONTRACT_STATUS_ACTIVE
hard_drive.traitor_data.contractor_hub.current_contract = hard_drive.traitor_data.contractor_hub.assigned_contracts[contract_id] hard_drive.traitor_data.contractor_hub.current_contract = hard_drive.traitor_data.contractor_hub.assigned_contracts[contract_id]
program_icon_state = "single_contract" program_icon_state = "single_contract"
return 1 return TRUE
if("PRG_login") if("PRG_login")
var/datum/antagonist/traitor/traitor_data = user.mind.has_antag_datum(/datum/antagonist/traitor) var/datum/antagonist/traitor/traitor_data = user.mind.has_antag_datum(/datum/antagonist/traitor)
if(traitor_data) // Bake their data right into the hard drive, or we don't allow non-antags gaining access to unused contract system. We also create their contracts at this point.
if(!traitor_data.contractor_hub) // Only play greet sound, and handle contractor hub when assigning for the first time. // Bake their data right into the hard drive, or we don't allow non-antags gaining access to an unused
// contract system.
// We also create their contracts at this point.
if(traitor_data)
// Only play greet sound, and handle contractor hub when assigning for the first time.
if(!traitor_data.contractor_hub)
user.playsound_local(user, 'sound/effects/contractstartup.ogg', 100, FALSE)
traitor_data.contractor_hub = new traitor_data.contractor_hub = new
traitor_data.contractor_hub.create_hub_items() traitor_data.contractor_hub.create_hub_items()
user.playsound_local(user, 'sound/effects/contractstartup.ogg', 100, 0) // Stops any topic exploits such as logging in multiple times on a single system.
// Stops any topic exploits such as logging in multiple times on a single system.
if(!assigned) if(!assigned)
traitor_data.contractor_hub.create_contracts(traitor_data.owner) traitor_data.contractor_hub.create_contracts(traitor_data.owner)
hard_drive.traitor_data = traitor_data hard_drive.traitor_data = traitor_data
program_icon_state = "contracts" program_icon_state = "contracts"
assigned = TRUE assigned = TRUE
else else
error = "Incorrect login details." error = "UNAUTHORIZED USER"
return 1 return TRUE
if("PRG_call_extraction") if("PRG_call_extraction")
if(hard_drive.traitor_data.contractor_hub.current_contract.status != CONTRACT_STATUS_EXTRACTING) if(hard_drive.traitor_data.contractor_hub.current_contract.status != CONTRACT_STATUS_EXTRACTING)
if(hard_drive.traitor_data.contractor_hub.current_contract.handle_extraction(user)) if(hard_drive.traitor_data.contractor_hub.current_contract.handle_extraction(user))
user.playsound_local(user, 'sound/effects/confirmdropoff.ogg', 100, 1) user.playsound_local(user, 'sound/effects/confirmdropoff.ogg', 100, TRUE)
hard_drive.traitor_data.contractor_hub.current_contract.status = CONTRACT_STATUS_EXTRACTING hard_drive.traitor_data.contractor_hub.current_contract.status = CONTRACT_STATUS_EXTRACTING
program_icon_state = "extracted" program_icon_state = "extracted"
else else
@@ -58,17 +64,18 @@
error = "Either both you or your target aren't at the dropoff location, or the pod hasn't got a valid place to land. Clear space, or make sure you're both inside." error = "Either both you or your target aren't at the dropoff location, or the pod hasn't got a valid place to land. Clear space, or make sure you're both inside."
else else
user.playsound_local(user, 'sound/machines/uplinkerror.ogg', 50) user.playsound_local(user, 'sound/machines/uplinkerror.ogg', 50)
error = "Already extracting... Place the target into the pod. If the pod was destroyed, you will need to cancel this contract." error = "Already extracting... Place the target into the pod. If the pod was destroyed, this contract is no longer possible."
return 1 return TRUE
if("PRG_contract_abort") if("PRG_contract_abort")
var/contract_id = hard_drive.traitor_data.contractor_hub.current_contract.id var/contract_id = hard_drive.traitor_data.contractor_hub.current_contract.id
hard_drive.traitor_data.contractor_hub.current_contract = null hard_drive.traitor_data.contractor_hub.current_contract = null
hard_drive.traitor_data.contractor_hub.assigned_contracts[contract_id].status = CONTRACT_STATUS_ABORTED hard_drive.traitor_data.contractor_hub.assigned_contracts[contract_id].status = CONTRACT_STATUS_ABORTED
program_icon_state = "contracts" program_icon_state = "contracts"
return 1 return TRUE
if("PRG_redeem_TC") if("PRG_redeem_TC")
if(hard_drive.traitor_data.contractor_hub.contract_TC_to_redeem) if(hard_drive.traitor_data.contractor_hub.contract_TC_to_redeem)
var/obj/item/stack/telecrystal/crystals = new /obj/item/stack/telecrystal(get_turf(user), hard_drive.traitor_data.contractor_hub.contract_TC_to_redeem) var/obj/item/stack/telecrystal/crystals = new /obj/item/stack/telecrystal(get_turf(user),
hard_drive.traitor_data.contractor_hub.contract_TC_to_redeem)
if(ishuman(user)) if(ishuman(user))
var/mob/living/carbon/human/H = user var/mob/living/carbon/human/H = user
if(H.put_in_hands(crystals)) if(H.put_in_hands(crystals))
@@ -77,22 +84,23 @@
to_chat(user, "<span class='notice'>Your payment materializes onto the floor.</span>") to_chat(user, "<span class='notice'>Your payment materializes onto the floor.</span>")
hard_drive.traitor_data.contractor_hub.contract_TC_payed_out += hard_drive.traitor_data.contractor_hub.contract_TC_to_redeem hard_drive.traitor_data.contractor_hub.contract_TC_payed_out += hard_drive.traitor_data.contractor_hub.contract_TC_to_redeem
hard_drive.traitor_data.contractor_hub.contract_TC_to_redeem = 0 hard_drive.traitor_data.contractor_hub.contract_TC_to_redeem = 0
return 1 return TRUE
else else
user.playsound_local(user, 'sound/machines/uplinkerror.ogg', 50) user.playsound_local(user, 'sound/machines/uplinkerror.ogg', 50)
return 1 return TRUE
if("PRG_clear_error") if("PRG_clear_error")
error = "" error = ""
if("PRG_contractor_hub") return TRUE
page = CONTRACT_UPLINK_PAGE_HUB if("PRG_set_first_load_finished")
program_icon_state = "store" first_load = FALSE
if("PRG_hub_back") return TRUE
page = CONTRACT_UPLINK_PAGE_CONTRACTS if("PRG_toggle_info")
program_icon_state = "contracts" info_screen = !info_screen
return TRUE
if("buy_hub") if("buy_hub")
if(hard_drive.traitor_data.owner.current == user) if(hard_drive.traitor_data.owner.current == user)
var/item = params["item"] var/item = params["item"]
for (var/datum/contractor_item/hub_item in hard_drive.traitor_data.contractor_hub.hub_items) for(var/datum/contractor_item/hub_item in hard_drive.traitor_data.contractor_hub.hub_items)
if (hub_item.name == item) if (hub_item.name == item)
hub_item.handle_purchase(hard_drive.traitor_data.contractor_hub, user) hub_item.handle_purchase(hard_drive.traitor_data.contractor_hub, user)
else else
@@ -103,21 +111,28 @@
var/obj/item/computer_hardware/hard_drive/small/syndicate/hard_drive = computer.all_components[MC_HDD] var/obj/item/computer_hardware/hard_drive/small/syndicate/hard_drive = computer.all_components[MC_HDD]
var/screen_to_be = null var/screen_to_be = null
data["first_load"] = first_load
if(hard_drive && hard_drive.traitor_data != null) if(hard_drive && hard_drive.traitor_data != null)
var/datum/antagonist/traitor/traitor_data = hard_drive.traitor_data var/datum/antagonist/traitor/traitor_data = hard_drive.traitor_data
error = "" data += get_header_data()
data = get_header_data()
if(traitor_data.contractor_hub.current_contract) if(traitor_data.contractor_hub.current_contract)
data["ongoing_contract"] = TRUE data["ongoing_contract"] = TRUE
screen_to_be = "single_contract" screen_to_be = "single_contract"
if(traitor_data.contractor_hub.current_contract.status == CONTRACT_STATUS_EXTRACTING) if(traitor_data.contractor_hub.current_contract.status == CONTRACT_STATUS_EXTRACTING)
data["extraction_enroute"] = TRUE data["extraction_enroute"] = TRUE
screen_to_be = "extracted" screen_to_be = "extracted"
else
data["extraction_enroute"] = FALSE
else
data["ongoing_contract"] = FALSE
data["extraction_enroute"] = FALSE
data["logged_in"] = TRUE data["logged_in"] = TRUE
data["station_name"] = GLOB.station_name data["station_name"] = GLOB.station_name
data["redeemable_tc"] = traitor_data.contractor_hub.contract_TC_to_redeem data["redeemable_tc"] = traitor_data.contractor_hub.contract_TC_to_redeem
data["earned_tc"] = traitor_data.contractor_hub.contract_TC_payed_out
data["contracts_completed"] = traitor_data.contractor_hub.contracts_completed
data["contract_rep"] = traitor_data.contractor_hub.contract_rep data["contract_rep"] = traitor_data.contractor_hub.contract_rep
data["page"] = page data["info_screen"] = info_screen
data["error"] = error data["error"] = error
for(var/datum/contractor_item/hub_item in traitor_data.contractor_hub.hub_items) for(var/datum/contractor_item/hub_item in traitor_data.contractor_hub.hub_items)
data["contractor_hub_items"] += list(list( data["contractor_hub_items"] += list(list(
@@ -135,7 +150,8 @@
"payout_bonus" = contract.contract.payout_bonus, "payout_bonus" = contract.contract.payout_bonus,
"dropoff" = contract.contract.dropoff, "dropoff" = contract.contract.dropoff,
"id" = contract.id, "id" = contract.id,
"status" = contract.status "status" = contract.status,
"message" = contract.wanted_message
)) ))
var/direction var/direction
@@ -154,14 +170,8 @@
else else
direction = "???" direction = "???"
data["dropoff_direction"] = direction data["dropoff_direction"] = direction
if (page == CONTRACT_UPLINK_PAGE_HUB)
screen_to_be = "store"
if (!screen_to_be)
screen_to_be = "contracts"
else else
data["logged_in"] = FALSE data["logged_in"] = FALSE
if (!screen_to_be)
screen_to_be = "assign"
program_icon_state = screen_to_be program_icon_state = screen_to_be
update_computer_icon() update_computer_icon()
return data return data

View File

@@ -36,61 +36,52 @@
if(target) if(target)
target.dos_sources.Remove(src) target.dos_sources.Remove(src)
target = null target = null
executed = 0 executed = FALSE
..() ..()
/datum/computer_file/program/ntnet_dos/ui_act(action, params) /datum/computer_file/program/ntnet_dos/ui_act(action, params)
if(..()) if(..())
return 1 return
switch(action) switch(action)
if("PRG_target_relay") if("PRG_target_relay")
for(var/obj/machinery/ntnet_relay/R in SSnetworks.station_network.relays) for(var/obj/machinery/ntnet_relay/R in SSnetworks.station_network.relays)
if("[R.uid]" == params["targid"]) if("[R.uid]" == params["targid"])
target = R target = R
return 1 break
return TRUE
if("PRG_reset") if("PRG_reset")
if(target) if(target)
target.dos_sources.Remove(src) target.dos_sources.Remove(src)
target = null target = null
executed = 0 executed = FALSE
error = "" error = ""
return 1 return TRUE
if("PRG_execute") if("PRG_execute")
if(target) if(target)
executed = 1 executed = TRUE
target.dos_sources.Add(src) target.dos_sources.Add(src)
if(SSnetworks.station_network.intrusion_detection_enabled) if(SSnetworks.station_network.intrusion_detection_enabled)
var/obj/item/computer_hardware/network_card/network_card = computer.all_components[MC_NET] var/obj/item/computer_hardware/network_card/network_card = computer.all_components[MC_NET]
SSnetworks.station_network.add_log("IDS WARNING - Excess traffic flood targeting relay [target.uid] detected from device: [network_card.get_network_tag()]") SSnetworks.station_network.add_log("IDS WARNING - Excess traffic flood targeting relay [target.uid] detected from device: [network_card.get_network_tag()]")
SSnetworks.station_network.intrusion_detection_alarm = 1 SSnetworks.station_network.intrusion_detection_alarm = TRUE
return 1 return TRUE
/datum/computer_file/program/ntnet_dos/ui_data(mob/user) /datum/computer_file/program/ntnet_dos/ui_data(mob/user)
if(!SSnetworks.station_network) if(!SSnetworks.station_network)
return return
var/list/data = list() var/list/data = get_header_data()
data = get_header_data() data["error"] = error
if(target && executed)
if(error) data["target"] = TRUE
data["error"] = error
else if(target && executed)
data["target"] = 1
data["speed"] = dos_speed data["speed"] = dos_speed
// This is mostly visual, generate some strings of 1s and 0s data["overload"] = target.dos_overload
// Probability of 1 is equal of completion percentage of DoS attack on this relay. data["capacity"] = target.dos_capacity
// Combined with UI updates this adds quite nice effect to the UI
var/percentage = target.dos_overload * 100 / target.dos_capacity
data["dos_strings"] = list()
for(var/j, j<10, j++)
var/string = ""
for(var/i, i<20, i++)
string = "[string][prob(percentage)]"
data["dos_strings"] += list(list("nums" = string))
else else
data["target"] = FALSE
data["relays"] = list() data["relays"] = list()
for(var/obj/machinery/ntnet_relay/R in SSnetworks.station_network.relays) for(var/obj/machinery/ntnet_relay/R in SSnetworks.station_network.relays)
data["relays"] += list(list("id" = R.uid)) data["relays"] += list(list("id" = R.uid))

View File

@@ -21,7 +21,7 @@
/datum/computer_file/program/revelation/proc/activate() /datum/computer_file/program/revelation/proc/activate()
if(computer) if(computer)
computer.visible_message("<span class='notice'>\The [computer]'s screen brightly flashes and loud electrical buzzing is heard.</span>") computer.visible_message("<span class='notice'>\The [computer]'s screen brightly flashes and loud electrical buzzing is heard.</span>")
computer.enabled = 0 computer.enabled = FALSE
computer.update_icon() computer.update_icon()
var/obj/item/computer_hardware/hard_drive/hard_drive = computer.all_components[MC_HDD] var/obj/item/computer_hardware/hard_drive/hard_drive = computer.all_components[MC_HDD]
var/obj/item/computer_hardware/battery/battery_module = computer.all_components[MC_CELL] var/obj/item/computer_hardware/battery/battery_module = computer.all_components[MC_CELL]
@@ -43,18 +43,20 @@
/datum/computer_file/program/revelation/ui_act(action, params) /datum/computer_file/program/revelation/ui_act(action, params)
if(..()) if(..())
return 1 return
switch(action) switch(action)
if("PRG_arm") if("PRG_arm")
armed = !armed armed = !armed
return TRUE
if("PRG_activate") if("PRG_activate")
activate() activate()
return TRUE
if("PRG_obfuscate") if("PRG_obfuscate")
var/mob/living/user = usr var/newname = params["new_name"]
var/newname = sanitize(input(user, "Enter new program name: "))
if(!newname) if(!newname)
return return
filedesc = newname filedesc = newname
return TRUE
/datum/computer_file/program/revelation/clone() /datum/computer_file/program/revelation/clone()

View File

@@ -1,3 +1,11 @@
#define CARDCON_DEPARTMENT_SERVICE "Service"
#define CARDCON_DEPARTMENT_SECURITY "Security"
#define CARDCON_DEPARTMENT_MEDICAL "Medical"
#define CARDCON_DEPARTMENT_SUPPLY "Supply"
#define CARDCON_DEPARTMENT_SCIENCE "Science"
#define CARDCON_DEPARTMENT_ENGINEERING "Engineering"
#define CARDCON_DEPARTMENT_COMMAND "Command"
/datum/computer_file/program/card_mod /datum/computer_file/program/card_mod
filename = "cardmod" filename = "cardmod"
filedesc = "ID Card Modification" filedesc = "ID Card Modification"
@@ -85,11 +93,11 @@
update_static_data(user) update_static_data(user)
return TRUE return TRUE
return formatted return FALSE
/datum/computer_file/program/card_mod/ui_act(action, params) /datum/computer_file/program/card_mod/ui_act(action, params)
if(..()) if(..())
return 1 return TRUE
var/obj/item/computer_hardware/card_slot/card_slot var/obj/item/computer_hardware/card_slot/card_slot
var/obj/item/computer_hardware/printer/printer var/obj/item/computer_hardware/printer/printer
@@ -99,192 +107,220 @@
if(!card_slot) if(!card_slot)
return return
var/obj/item/card/id/user_id_card = null
var/mob/user = usr var/mob/user = usr
var/obj/item/card/id/user_id_card = user.get_idcard(FALSE)
var/obj/item/card/id/id_card = card_slot.stored_card var/obj/item/card/id/id_card = card_slot.stored_card
var/obj/item/card/id/auth_card = card_slot.stored_card2
if(auth_card)
user_id_card = auth_card
else
if(ishuman(user))
var/mob/living/carbon/human/h = user
user_id_card = h.get_idcard(TRUE)
switch(action) switch(action)
if("PRG_switchm") if("PRG_authenticate")
if(params["target"] == "mod") if(!computer || !user_id_card)
mod_mode = 1 playsound(computer, 'sound/machines/terminal_prompt_deny.ogg', 50, FALSE)
else if (params["target"] == "manifest") return
mod_mode = 0 if(authenticate(user, user_id_card))
else if (params["target"] == "manage") playsound(computer, 'sound/machines/terminal_on.ogg', 50, FALSE)
mod_mode = 2 return TRUE
if("PRG_togglea") if("PRG_logout")
if(show_assignments) authenticated = FALSE
show_assignments = 0 playsound(computer, 'sound/machines/terminal_off.ogg', 50, FALSE)
else return TRUE
show_assignments = 1
if("PRG_print") if("PRG_print")
if(computer && printer) //This option should never be called if there is no printer if(!computer || !printer)
if(mod_mode) return
if(authorized()) if(!authenticated)
var/contents = {"<h4>Access Report</h4> return
<u>Prepared By:</u> [user_id_card && user_id_card.registered_name ? user_id_card.registered_name : "Unknown"]<br> var/contents = {"<h4>Access Report</h4>
<u>For:</u> [id_card.registered_name ? id_card.registered_name : "Unregistered"]<br> <u>Prepared By:</u> [user_id_card && user_id_card.registered_name ? user_id_card.registered_name : "Unknown"]<br>
<hr> <u>For:</u> [id_card.registered_name ? id_card.registered_name : "Unregistered"]<br>
<u>Assignment:</u> [id_card.assignment]<br> <hr>
<u>Access:</u><br> <u>Assignment:</u> [id_card.assignment]<br>
"} <u>Access:</u><br>
"}
var/known_access_rights = get_all_accesses() var/known_access_rights = get_all_accesses()
for(var/A in id_card.access) for(var/A in id_card.access)
if(A in known_access_rights) if(A in known_access_rights)
contents += " [get_access_desc(A)]" contents += " [get_access_desc(A)]"
if(!printer.print_text(contents,"access report")) if(!printer.print_text(contents,"access report"))
to_chat(usr, "<span class='notice'>Hardware error: Printer was unable to print the file. It may be out of paper.</span>") to_chat(usr, "<span class='notice'>Hardware error: Printer was unable to print the file. It may be out of paper.</span>")
return return
else
computer.visible_message("<span class='notice'>\The [computer] prints out paper.</span>")
else
var/contents = {"<h4>Crew Manifest</h4>
<br>
[GLOB.data_core ? GLOB.data_core.get_manifest(0) : ""]
"}
if(!printer.print_text(contents,text("crew manifest ([])", STATION_TIME_TIMESTAMP("hh:mm:ss", world.time))))
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 paper.</span>")
if("PRG_eject")
if(computer && card_slot)
var/select = params["target"]
switch(select)
if("id")
if(id_card)
GLOB.data_core.manifest_modify(id_card.registered_name, id_card.assignment)
card_slot.try_eject(1, user)
else
var/obj/item/I = usr.get_active_held_item()
if (istype(I, /obj/item/card/id))
if(!usr.transferItemToLoc(I, computer))
return
card_slot.stored_card = I
if("auth")
if(auth_card)
if(id_card)
GLOB.data_core.manifest_modify(id_card.registered_name, id_card.assignment)
head_subordinates = null
region_access = null
authenticated = 0
minor = 0
card_slot.try_eject(2, user)
else
var/obj/item/I = usr.get_active_held_item()
if (istype(I, /obj/item/card/id))
if(!usr.transferItemToLoc(I, computer))
return
card_slot.stored_card2 = I
if("PRG_terminate")
if(computer && ((id_card.assignment in head_subordinates) || id_card.assignment == "Assistant"))
id_card.assignment = "Unassigned"
remove_nt_access(id_card)
if("PRG_edit")
if(computer && authorized())
if(params["name"])
var/temp_name = reject_bad_name(input("Enter name.", "Name", id_card.registered_name))
if(temp_name)
id_card.registered_name = temp_name
else
computer.visible_message("<span class='notice'>[computer] buzzes rudely.</span>")
//else if(params["account"])
// var/account_num = text2num(input("Enter account number.", "Account", id_card.associated_account_number))
// id_card.associated_account_number = account_num
if("PRG_assign")
if(computer && authorized() && id_card)
var/t1 = params["assign_target"]
if(t1 == "Custom")
var/temp_t = reject_bad_text(input("Enter a custom job assignment.","Assignment", id_card.assignment), 45)
//let custom jobs function as an impromptu alt title, mainly for sechuds
if(temp_t)
id_card.assignment = temp_t
else
var/list/access = list()
if(is_centcom)
access = get_centcom_access(t1)
else
var/datum/job/jobdatum
for(var/jobtype in typesof(/datum/job))
var/datum/job/J = new jobtype
if(ckey(J.title) == ckey(t1))
jobdatum = J
break
if(!jobdatum)
to_chat(usr, "<span class='warning'>No log exists for this job: [t1]</span>")
return
access = jobdatum.get_access()
remove_nt_access(id_card)
apply_access(id_card, access)
id_card.assignment = t1
if("PRG_access")
if(params["allowed"] && computer && authorized())
var/access_type = text2num(params["access_target"])
var/access_allowed = text2num(params["allowed"])
if(access_type in (is_centcom ? get_all_centcom_access() : get_all_accesses()))
id_card.access -= access_type
if(!access_allowed)
id_card.access += access_type
if("PRG_open_job")
var/edit_job_target = params["target"]
var/datum/job/j = SSjob.GetJob(edit_job_target)
if(!j)
return 0
if(can_open_job(j) != 1)
return 0
if(opened_positions[edit_job_target] >= 0)
GLOB.time_last_changed_position = world.time / 10
j.total_positions++
opened_positions[edit_job_target]++
if("PRG_close_job")
var/edit_job_target = params["target"]
var/datum/job/j = SSjob.GetJob(edit_job_target)
if(!j)
return 0
if(can_close_job(j) != 1)
return 0
//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]--
if("PRG_regsel")
if(!reg_ids)
reg_ids = list()
var/regsel = text2num(params["region"])
if(regsel in reg_ids)
reg_ids -= regsel
else else
reg_ids += regsel playsound(computer, 'sound/machines/terminal_on.ogg', 50, FALSE)
computer.visible_message("<span class='notice'>\The [computer] prints out a paper.</span>")
return TRUE
if("PRG_eject")
if(!computer || !card_slot)
return
if(id_card)
GLOB.data_core.manifest_modify(id_card.registered_name, id_card.assignment)
card_slot.try_eject(TRUE, user)
else
var/obj/item/I = user.get_active_held_item()
if(istype(I, /obj/item/card/id))
if(!user.transferItemToLoc(I, computer))
return
card_slot.stored_card = I
playsound(computer, 'sound/machines/terminal_insert_disc.ogg', 50, FALSE)
return TRUE
if("PRG_terminate")
if(!computer || !authenticated)
return
if(minor)
if(!(id_card.assignment in head_subordinates) && id_card.assignment != "Assistant")
return
if(id_card) id_card.access -= get_all_centcom_access() + get_all_accesses()
id_card.name = text("[id_card.registered_name]'s ID Card ([id_card.assignment])") id_card.assignment = "Unassigned"
id_card.update_label()
playsound(computer, 'sound/machines/terminal_prompt_deny.ogg', 50, FALSE)
return TRUE
if("PRG_edit")
if(!computer || !authenticated || !id_card)
return
var/new_name = params["name"]
if(!new_name)
return
id_card.registered_name = new_name
id_card.update_label()
playsound(computer, "terminal_type", 50, FALSE)
return TRUE
if("PRG_assign")
if(!computer || !authenticated || !id_card)
return
var/target = params["assign_target"]
if(!target)
return
return 1 if(target == "Custom")
var/custom_name = params["custom_name"]
if(custom_name)
id_card.assignment = custom_name
id_card.update_label()
else
if(minor && !(target in head_subordinates))
return
var/list/new_access = list()
if(is_centcom)
new_access = get_centcom_access(target)
else
var/datum/job/job
for(var/jobtype in subtypesof(/datum/job))
var/datum/job/J = new jobtype
if(J.title == target)
job = J
break
if(!job)
to_chat(user, "<span class='warning'>No class exists for this job: [target]</span>")
return
new_access = job.get_access()
id_card.access -= get_all_centcom_access() + get_all_accesses()
id_card.access |= new_access
id_card.assignment = target
id_card.update_label()
playsound(computer, 'sound/machines/terminal_prompt_confirm.ogg', 50, FALSE)
return TRUE
if("PRG_access")
if(!computer || !authenticated)
return
var/access_type = text2num(params["access_target"])
if(access_type in (is_centcom ? get_all_centcom_access() : get_all_accesses()))
if(access_type in id_card.access)
id_card.access -= access_type
else
id_card.access |= access_type
playsound(computer, "terminal_type", 50, FALSE)
return TRUE
if("PRG_grantall")
if(!computer || !authenticated || minor)
return
id_card.access |= (is_centcom ? get_all_centcom_access() : get_all_accesses())
playsound(computer, 'sound/machines/terminal_prompt_confirm.ogg', 50, FALSE)
return TRUE
if("PRG_denyall")
if(!computer || !authenticated || minor)
return
id_card.access.Cut()
playsound(computer, 'sound/machines/terminal_prompt_deny.ogg', 50, FALSE)
return TRUE
if("PRG_grantregion")
if(!computer || !authenticated)
return
var/region = text2num(params["region"])
if(isnull(region))
return
id_card.access |= get_region_accesses(region)
playsound(computer, 'sound/machines/terminal_prompt_confirm.ogg', 50, FALSE)
return TRUE
if("PRG_denyregion")
if(!computer || !authenticated)
return
var/region = text2num(params["region"])
if(isnull(region))
return
id_card.access -= get_region_accesses(region)
playsound(computer, 'sound/machines/terminal_prompt_deny.ogg', 50, FALSE)
return TRUE
/datum/computer_file/program/card_mod/proc/remove_nt_access(obj/item/card/id/id_card)
id_card.access -= get_all_accesses()
id_card.access -= get_all_centcom_access()
/datum/computer_file/program/card_mod/proc/apply_access(obj/item/card/id/id_card, list/accesses)
id_card.access |= accesses /datum/computer_file/program/card_mod/ui_static_data(mob/user)
var/list/data = list()
data["station_name"] = station_name()
data["centcom_access"] = is_centcom
data["minor"] = target_dept || minor ? TRUE : FALSE
var/list/departments = target_dept
if(is_centcom)
departments = list("CentCom" = get_all_centcom_jobs())
else if(isnull(departments))
departments = list(
CARDCON_DEPARTMENT_COMMAND = list("Captain"),//lol
CARDCON_DEPARTMENT_ENGINEERING = GLOB.engineering_positions,
CARDCON_DEPARTMENT_MEDICAL = GLOB.medical_positions,
CARDCON_DEPARTMENT_SCIENCE = GLOB.science_positions,
CARDCON_DEPARTMENT_SECURITY = GLOB.security_positions,
CARDCON_DEPARTMENT_SUPPLY = GLOB.supply_positions,
CARDCON_DEPARTMENT_SERVICE = GLOB.service_positions
)
data["jobs"] = list()
for(var/department in departments)
var/list/job_list = departments[department]
var/list/department_jobs = list()
for(var/job in job_list)
if(minor && !(job in head_subordinates))
continue
department_jobs += list(list(
"display_name" = replacetext(job, "&nbsp", " "),
"job" = job
))
if(length(department_jobs))
data["jobs"][department] = department_jobs
var/list/regions = list()
for(var/i in 1 to 7)
if((minor || target_dept) && !(i in region_access))
continue
var/list/accesses = list()
for(var/access in get_region_accesses(i))
if (get_access_desc(access))
accesses += list(list(
"desc" = replacetext(get_access_desc(access), "&nbsp", " "),
"ref" = access,
))
regions += list(list(
"name" = get_region_accesses_name(i),
"regid" = i,
"accesses" = accesses
))
data["regions"] = regions
return data
/datum/computer_file/program/card_mod/ui_data(mob/user) /datum/computer_file/program/card_mod/ui_data(mob/user)
var/list/data = get_header_data() var/list/data = get_header_data()
var/obj/item/computer_hardware/card_slot/card_slot var/obj/item/computer_hardware/card_slot/card_slot
@@ -294,181 +330,34 @@
card_slot = computer.all_components[MC_CARD] card_slot = computer.all_components[MC_CARD]
printer = computer.all_components[MC_PRINT] printer = computer.all_components[MC_PRINT]
data["mmode"] = mod_mode
var/authed = 0
if(computer)
if(card_slot)
var/obj/item/card/id/auth_card = card_slot.stored_card2
data["auth_name"] = auth_card ? strip_html_simple(auth_card.name) : "-----"
authed = authorized()
if(mod_mode == 2)
data["slots"] = list()
var/list/pos = list()
for(var/datum/job/job in SSjob.occupations)
if(job.title in blacklisted)
continue
var/list/status_open = build_manage(job,1)
var/list/status_close = build_manage(job,0)
pos.Add(list(list(
"title" = job.title,
"current" = job.current_positions,
"total" = job.total_positions,
"status_open" = (authed && !minor) ? status_open["enable"]: 0,
"status_close" = (authed && !minor) ? status_close["enable"] : 0,
"desc_open" = status_open["desc"],
"desc_close" = status_close["desc"])))
data["slots"] = pos
data["src"] = "[REF(src)]"
data["station_name"] = station_name() data["station_name"] = station_name()
if(!mod_mode)
data["manifest"] = list()
var/list/crew = list()
for(var/datum/data/record/t in sortRecord(GLOB.data_core.general))
crew.Add(list(list(
"name" = t.fields["name"],
"rank" = t.fields["rank"])))
data["manifest"] = crew
data["assignments"] = show_assignments
if(computer) if(computer)
data["have_id_slot"] = !!card_slot data["have_id_slot"] = !!card_slot
data["have_printer"] = !!printer data["have_printer"] = !!printer
if(!card_slot && mod_mode == 1)
mod_mode = 0 //We can't modify IDs when there is no card reader
else else
data["have_id_slot"] = 0 data["have_id_slot"] = FALSE
data["have_printer"] = 0 data["have_printer"] = FALSE
data["centcom_access"] = is_centcom data["authenticated"] = authenticated
data["authenticated"] = authed
if(mod_mode == 1 && computer)
if(card_slot)
var/obj/item/card/id/id_card = card_slot.stored_card
data["has_id"] = !!id_card
data["id_rank"] = id_card && id_card.assignment ? html_encode(id_card.assignment) : "Unassigned"
data["id_owner"] = id_card && id_card.registered_name ? html_encode(id_card.registered_name) : "-----"
data["id_name"] = id_card ? strip_html_simple(id_card.name) : "-----"
if(show_assignments)
data["engineering_jobs"] = format_jobs(GLOB.engineering_positions)
data["medical_jobs"] = format_jobs(GLOB.medical_positions)
data["science_jobs"] = format_jobs(GLOB.science_positions)
data["security_jobs"] = format_jobs(GLOB.security_positions)
data["cargo_jobs"] = format_jobs(GLOB.supply_positions)
data["civilian_jobs"] = format_jobs(GLOB.civilian_positions)
data["centcom_jobs"] = format_jobs(get_all_centcom_jobs())
if(card_slot.stored_card)
var/obj/item/card/id/id_card = card_slot.stored_card
if(is_centcom)
var/list/all_centcom_access = list()
for(var/access in get_all_centcom_access())
all_centcom_access.Add(list(list(
"desc" = replacetext(get_centcom_access_desc(access), "&nbsp", " "),
"ref" = access,
"allowed" = (access in id_card.access) ? 1 : 0)))
data["all_centcom_access"] = all_centcom_access
else
var/list/regions = list()
for(var/i = 1; i <= 7; i++)
if((minor || target_dept) && !(i in region_access))
continue
var/list/accesses = list()
if(i in reg_ids)
for(var/access in get_region_accesses(i))
if (get_access_desc(access))
accesses.Add(list(list(
"desc" = replacetext(get_access_desc(access), "&nbsp", " "),
"ref" = access,
"allowed" = (access in id_card.access) ? 1 : 0)))
regions.Add(list(list(
"name" = get_region_accesses_name(i),
"regid" = i,
"selected" = (i in reg_ids) ? 1 : null,
"accesses" = accesses)))
data["regions"] = regions
data["minor"] = target_dept || minor ? 1 : 0
if(computer)
var/obj/item/card/id/id_card = card_slot.stored_card
data["has_id"] = !!id_card
data["id_name"] = id_card ? id_card.name : "-----"
if(id_card)
data["id_rank"] = id_card.assignment ? id_card.assignment : "Unassigned"
data["id_owner"] = id_card.registered_name ? id_card.registered_name : "-----"
data["access_on_card"] = id_card.access
return data return data
/datum/computer_file/program/card_mod/proc/build_manage(datum/job,open = FALSE)
var/out = "Denied"
var/can_change= 0
if(open)
can_change = can_open_job(job)
else
can_change = can_close_job(job)
var/enable = 0
if(can_change == 1)
out = "[open ? "Open Position" : "Close Position"]"
enable = 1
else if(can_change == -2)
var/time_to_wait = round(change_position_cooldown - ((world.time / 10) - GLOB.time_last_changed_position), 1)
var/mins = round(time_to_wait / 60)
var/seconds = time_to_wait - (60*mins)
out = "Cooldown ongoing: [mins]:[(seconds < 10) ? "0[seconds]" : "[seconds]"]"
else
out = "Denied"
return list("enable" = enable, "desc" = out) #undef CARDCON_DEPARTMENT_SERVICE
#undef CARDCON_DEPARTMENT_SECURITY
#undef CARDCON_DEPARTMENT_MEDICAL
/datum/computer_file/program/card_mod/proc/authorized() #undef CARDCON_DEPARTMENT_SCIENCE
if(!authenticated && computer) #undef CARDCON_DEPARTMENT_SUPPLY
var/obj/item/computer_hardware/card_slot/card_slot = computer.all_components[MC_CARD] #undef CARDCON_DEPARTMENT_ENGINEERING
if(card_slot) #undef CARDCON_DEPARTMENT_COMMAND
var/obj/item/card/id/auth_card = card_slot.stored_card2
if(auth_card)
region_access = list()
if(ACCESS_CHANGE_IDS in auth_card.GetAccess())
minor = 0
authenticated = 1
return 1
else
if((ACCESS_HOP in auth_card.access) && ((target_dept==1) || !target_dept))
region_access |= 1
region_access |= 6
get_subordinates("Head of Personnel")
if((ACCESS_HOS in auth_card.access) && ((target_dept==2) || !target_dept))
region_access |= 2
get_subordinates("Head of Security")
if((ACCESS_CMO in auth_card.access) && ((target_dept==3) || !target_dept))
region_access |= 3
get_subordinates("Chief Medical Officer")
if((ACCESS_RD in auth_card.access) && ((target_dept==4) || !target_dept))
region_access |= 4
get_subordinates("Research Director")
if((ACCESS_CE in auth_card.access) && ((target_dept==5) || !target_dept))
region_access |= 5
get_subordinates("Chief Engineer")
if(region_access.len)
minor = 1
authenticated = 1
return 1
else
return authenticated
/datum/computer_file/program/card_mod/proc/get_subordinates(rank)
head_subordinates = list()
for(var/datum/job/job in SSjob.occupations)
if(rank in job.department_head)
head_subordinates += job.title

View File

@@ -14,176 +14,57 @@
/datum/computer_file/program/filemanager/ui_act(action, params) /datum/computer_file/program/filemanager/ui_act(action, params)
if(..()) if(..())
return 1 return
var/obj/item/computer_hardware/hard_drive/HDD = computer.all_components[MC_HDD] var/obj/item/computer_hardware/hard_drive/HDD = computer.all_components[MC_HDD]
var/obj/item/computer_hardware/hard_drive/RHDD = computer.all_components[MC_SDD] var/obj/item/computer_hardware/hard_drive/RHDD = computer.all_components[MC_SDD]
var/obj/item/computer_hardware/printer/printer = computer.all_components[MC_PRINT]
switch(action) switch(action)
if("PRG_openfile")
. = 1
open_file = params["name"]
if("PRG_newtextfile")
. = 1
var/newname = stripped_input(usr, "Enter file name or leave blank to cancel:", "File rename", max_length=50)
if(!newname)
return 1
if(!HDD)
return 1
var/datum/computer_file/data/F = new/datum/computer_file/data()
F.filename = newname
F.filetype = "TXT"
HDD.store_file(F)
if("PRG_deletefile") if("PRG_deletefile")
. = 1
if(!HDD) if(!HDD)
return 1 return
var/datum/computer_file/file = HDD.find_file_by_name(params["name"]) var/datum/computer_file/file = HDD.find_file_by_name(params["name"])
if(!file || file.undeletable) if(!file || file.undeletable)
return 1 return
HDD.remove_file(file) HDD.remove_file(file)
return TRUE
if("PRG_usbdeletefile") if("PRG_usbdeletefile")
. = 1
if(!RHDD) if(!RHDD)
return 1 return
var/datum/computer_file/file = RHDD.find_file_by_name(params["name"]) var/datum/computer_file/file = RHDD.find_file_by_name(params["name"])
if(!file || file.undeletable) if(!file || file.undeletable)
return 1
RHDD.remove_file(file)
if("PRG_closefile")
. = 1
open_file = null
error = null
if("PRG_clone")
. = 1
if(!HDD)
return 1
var/datum/computer_file/F = HDD.find_file_by_name(params["name"])
if(!F || !istype(F))
return 1
var/datum/computer_file/C = F.clone(1)
HDD.store_file(C)
if("PRG_rename")
. = 1
if(!HDD)
return 1
var/datum/computer_file/file = HDD.find_file_by_name(params["name"])
if(!file || !istype(file))
return 1
var/newname = stripped_input(usr, "Enter new file name:", "File rename", file.filename, max_length=50)
if(file && newname)
file.filename = newname
if("PRG_edit")
. = 1
if(!open_file)
return 1
if(!HDD)
return 1
var/datum/computer_file/data/F = HDD.find_file_by_name(open_file)
if(!F || !istype(F))
return 1
if(F.do_not_edit && (alert("WARNING: This file is not compatible with editor. Editing it may result in permanently corrupted formatting or damaged data consistency. Edit anyway?", "Incompatible File", "No", "Yes") == "No"))
return 1
// 16384 is the limit for file length in characters. Currently, papers have value of 2048 so this is 8 times as long, since we can't edit parts of the file independently.
var/newtext = stripped_multiline_input(usr, "Editing file [open_file]. You may use most tags used in paper formatting:", "Text Editor", html_decode(F.stored_data), 16384, TRUE)
if(!newtext)
return return
if(F) RHDD.remove_file(file)
var/datum/computer_file/data/backup = F.clone() return TRUE
HDD.remove_file(F) if("PRG_rename")
F.stored_data = newtext
F.calculate_size()
// We can't store the updated file, it's probably too large. Print an error and restore backed up version.
// This is mostly intended to prevent people from losing texts they spent lot of time working on due to running out of space.
// They will be able to copy-paste the text from error screen and store it in notepad or something.
if(!HDD.store_file(F))
error = "I/O error: Unable to overwrite file. Hard drive is probably full. You may want to backup your changes before closing this window:<br><br>[F.stored_data]<br><br>"
HDD.store_file(backup)
if("PRG_printfile")
. = 1
if(!open_file)
return 1
if(!HDD) if(!HDD)
return 1 return
var/datum/computer_file/data/F = HDD.find_file_by_name(open_file) var/datum/computer_file/file = HDD.find_file_by_name(params["name"])
if(!F || !istype(F)) if(!file)
return 1 return
if(!printer) var/newname = params["new_name"]
error = "Missing Hardware: Your computer does not have required hardware to complete this operation." if(!newname)
return 1 return
if(!printer.print_text("<font face=\"[(computer.obj_flags & EMAGGED) ? CRAYON_FONT : PRINTER_FONT]\">" + prepare_printjob(F.stored_data) + "</font>", open_file)) file.filename = newname
error = "Hardware error: Printer was unable to print the file. It may be out of paper." return TRUE
return 1
if("PRG_copytousb") if("PRG_copytousb")
. = 1
if(!HDD || !RHDD) if(!HDD || !RHDD)
return 1 return
var/datum/computer_file/F = HDD.find_file_by_name(params["name"]) var/datum/computer_file/F = HDD.find_file_by_name(params["name"])
if(!F || !istype(F)) if(!F)
return 1 return
var/datum/computer_file/C = F.clone(0) var/datum/computer_file/C = F.clone(FALSE)
RHDD.store_file(C) RHDD.store_file(C)
return TRUE
if("PRG_copyfromusb") if("PRG_copyfromusb")
. = 1
if(!HDD || !RHDD) if(!HDD || !RHDD)
return 1 return
var/datum/computer_file/F = RHDD.find_file_by_name(params["name"]) var/datum/computer_file/F = RHDD.find_file_by_name(params["name"])
if(!F || !istype(F)) if(!F || !istype(F))
return 1 return
var/datum/computer_file/C = F.clone(0) var/datum/computer_file/C = F.clone(FALSE)
HDD.store_file(C) HDD.store_file(C)
return TRUE
/datum/computer_file/program/filemanager/proc/parse_tags(t)
t = replacetext(t, "\[center\]", "<center>")
t = replacetext(t, "\[/center\]", "</center>")
t = replacetext(t, "\[br\]", "<BR>")
t = replacetext(t, "\n", "<BR>")
t = replacetext(t, "\[b\]", "<B>")
t = replacetext(t, "\[/b\]", "</B>")
t = replacetext(t, "\[i\]", "<I>")
t = replacetext(t, "\[/i\]", "</I>")
t = replacetext(t, "\[u\]", "<U>")
t = replacetext(t, "\[/u\]", "</U>")
t = replacetext(t, "\[time\]", "[STATION_TIME_TIMESTAMP("hh:mm:ss", world.time)]")
t = replacetext(t, "\[date\]", "[time2text(world.realtime, "MMM DD")] [GLOB.year_integer]")
t = replacetext(t, "\[large\]", "<font size=\"4\">")
t = replacetext(t, "\[/large\]", "</font>")
t = replacetext(t, "\[h1\]", "<H1>")
t = replacetext(t, "\[/h1\]", "</H1>")
t = replacetext(t, "\[h2\]", "<H2>")
t = replacetext(t, "\[/h2\]", "</H2>")
t = replacetext(t, "\[h3\]", "<H3>")
t = replacetext(t, "\[/h3\]", "</H3>")
t = replacetext(t, "\[*\]", "<li>")
t = replacetext(t, "\[hr\]", "<HR>")
t = replacetext(t, "\[small\]", "<font size = \"1\">")
t = replacetext(t, "\[/small\]", "</font>")
t = replacetext(t, "\[list\]", "<ul>")
t = replacetext(t, "\[/list\]", "</ul>")
t = replacetext(t, "\[table\]", "<table border=1 cellspacing=0 cellpadding=3 style='border: 1px solid black;'>")
t = replacetext(t, "\[/table\]", "</td></tr></table>")
t = replacetext(t, "\[grid\]", "<table>")
t = replacetext(t, "\[/grid\]", "</td></tr></table>")
t = replacetext(t, "\[row\]", "</td><tr>")
t = replacetext(t, "\[tr\]", "</td><tr>")
t = replacetext(t, "\[td\]", "<td>")
t = replacetext(t, "\[cell\]", "<td>")
t = replacetext(t, "\[tab\]", "&nbsp;&nbsp;&nbsp;&nbsp;")
t = parsemarkdown_basic(t)
return t
/datum/computer_file/program/filemanager/proc/prepare_printjob(t) // Additional stuff to parse if we want to print it and make a happy Head of Personnel. Forms FTW.
t = replacetext(t, "\[field\]", "<span class=\"paper_field\"></span>")
t = replacetext(t, "\[sign\]", "<span class=\"paper_field\"></span>")
t = parse_tags(t)
t = replacetext(t, regex("(?:%s(?:ign)|%f(?:ield))(?=\\s|$)", "ig"), "<span class=\"paper_field\"></span>")
return t
/datum/computer_file/program/filemanager/ui_data(mob/user) /datum/computer_file/program/filemanager/ui_data(mob/user)
var/list/data = get_header_data() var/list/data = get_header_data()
@@ -192,41 +73,28 @@
var/obj/item/computer_hardware/hard_drive/portable/RHDD = computer.all_components[MC_SDD] var/obj/item/computer_hardware/hard_drive/portable/RHDD = computer.all_components[MC_SDD]
if(error) if(error)
data["error"] = error data["error"] = error
if(open_file) if(!computer || !HDD)
var/datum/computer_file/data/file data["error"] = "I/O ERROR: Unable to access hard drive."
if(!computer || !HDD)
data["error"] = "I/O ERROR: Unable to access hard drive."
else
file = HDD.find_file_by_name(open_file)
if(!istype(file))
data["error"] = "I/O ERROR: Unable to open file."
else
data["filedata"] = parse_tags(file.stored_data)
data["filename"] = "[file.filename].[file.filetype]"
else else
if(!computer || !HDD) var/list/files = list()
data["error"] = "I/O ERROR: Unable to access hard drive." for(var/datum/computer_file/F in HDD.stored_files)
else files += list(list(
var/list/files[0] "name" = F.filename,
for(var/datum/computer_file/F in HDD.stored_files) "type" = F.filetype,
files.Add(list(list( "size" = F.size,
"undeletable" = F.undeletable
))
data["files"] = files
if(RHDD)
data["usbconnected"] = TRUE
var/list/usbfiles = list()
for(var/datum/computer_file/F in RHDD.stored_files)
usbfiles += list(list(
"name" = F.filename, "name" = F.filename,
"type" = F.filetype, "type" = F.filetype,
"size" = F.size, "size" = F.size,
"undeletable" = F.undeletable "undeletable" = F.undeletable
))) ))
data["files"] = files data["usbfiles"] = usbfiles
if(RHDD)
data["usbconnected"] = 1
var/list/usbfiles[0]
for(var/datum/computer_file/F in RHDD.stored_files)
usbfiles.Add(list(list(
"name" = F.filename,
"type" = F.filetype,
"size" = F.size,
"undeletable" = F.undeletable
)))
data["usbfiles"] = usbfiles
return data return data

View File

@@ -115,49 +115,50 @@
var/list/data = get_header_data() var/list/data = get_header_data()
// This IF cuts on data transferred to client, so i guess it's worth it. data["downloading"] = !!downloaded_file
if(downloaderror) // Download errored. Wait until user resets the program. data["error"] = downloaderror || FALSE
data["error"] = downloaderror
else if(downloaded_file) // Download running. Wait please.. // Download running. Wait please..
if(downloaded_file)
data["downloadname"] = downloaded_file.filename data["downloadname"] = downloaded_file.filename
data["downloaddesc"] = downloaded_file.filedesc data["downloaddesc"] = downloaded_file.filedesc
data["downloadsize"] = downloaded_file.size data["downloadsize"] = downloaded_file.size
data["downloadspeed"] = download_netspeed data["downloadspeed"] = download_netspeed
data["downloadcompletion"] = round(download_completion, 0.1) data["downloadcompletion"] = round(download_completion, 0.1)
else // No download running, pick file.
var/obj/item/computer_hardware/hard_drive/hard_drive = my_computer.all_components[MC_HDD] var/obj/item/computer_hardware/hard_drive/hard_drive = my_computer.all_components[MC_HDD]
data["disk_size"] = hard_drive.max_capacity data["disk_size"] = hard_drive.max_capacity
data["disk_used"] = hard_drive.used_capacity data["disk_used"] = hard_drive.used_capacity
var/list/all_entries[0] var/list/all_entries[0]
for(var/A in SSnetworks.station_network.available_station_software) for(var/A in SSnetworks.station_network.available_station_software)
var/datum/computer_file/program/P = A var/datum/computer_file/program/P = A
// Only those programs our user can run will show in the list // Only those programs our user can run will show in the list
if(!P.can_run(user,transfer = 1) || hard_drive.find_file_by_name(P.filename)) if(!P.can_run(user,transfer = 1) || hard_drive.find_file_by_name(P.filename))
continue continue
all_entries.Add(list(list( all_entries.Add(list(list(
"filename" = P.filename, "filename" = P.filename,
"filedesc" = P.filedesc, "filedesc" = P.filedesc,
"fileinfo" = P.extended_desc, "fileinfo" = P.extended_desc,
"compatibility" = check_compatibility(P), "compatibility" = check_compatibility(P),
"size" = P.size "size" = P.size,
))) )))
data["hackedavailable"] = 0 data["hackedavailable"] = FALSE
if(computer.obj_flags & EMAGGED) // If we are running on emagged computer we have access to some "bonus" software if(computer.obj_flags & EMAGGED) // If we are running on emagged computer we have access to some "bonus" software
var/list/hacked_programs[0] var/list/hacked_programs[0]
for(var/S in SSnetworks.station_network.available_antag_software) for(var/S in SSnetworks.station_network.available_antag_software)
var/datum/computer_file/program/P = S var/datum/computer_file/program/P = S
if(hard_drive.find_file_by_name(P.filename)) if(hard_drive.find_file_by_name(P.filename))
continue continue
data["hackedavailable"] = 1 data["hackedavailable"] = TRUE
hacked_programs.Add(list(list( hacked_programs.Add(list(list(
"filename" = P.filename, "filename" = P.filename,
"filedesc" = P.filedesc, "filedesc" = P.filedesc,
"fileinfo" = P.extended_desc, "fileinfo" = P.extended_desc,
"size" = P.size "size" = P.size,
))) )))
data["hacked_programs"] = hacked_programs data["hacked_programs"] = hacked_programs
data["downloadable_programs"] = all_entries data["downloadable_programs"] = all_entries
return data return data

View File

@@ -4,58 +4,48 @@
program_icon_state = "comm_monitor" program_icon_state = "comm_monitor"
extended_desc = "This program monitors stationwide NTNet network, provides access to logging systems, and allows for configuration changes" extended_desc = "This program monitors stationwide NTNet network, provides access to logging systems, and allows for configuration changes"
size = 12 size = 12
requires_ntnet = 1 requires_ntnet = TRUE
required_access = ACCESS_NETWORK //NETWORK CONTROL IS A MORE SECURE PROGRAM. required_access = ACCESS_NETWORK //NETWORK CONTROL IS A MORE SECURE PROGRAM.
available_on_ntnet = TRUE available_on_ntnet = TRUE
tgui_id = "NtosNetMonitor" tgui_id = "NtosNetMonitor"
/datum/computer_file/program/ntnetmonitor/ui_act(action, params) /datum/computer_file/program/ntnetmonitor/ui_act(action, params)
if(..()) if(..())
return 1 return
switch(action) switch(action)
if("resetIDS") if("resetIDS")
. = 1
if(SSnetworks.station_network) if(SSnetworks.station_network)
SSnetworks.station_network.resetIDS() SSnetworks.station_network.resetIDS()
return 1 return TRUE
if("toggleIDS") if("toggleIDS")
. = 1
if(SSnetworks.station_network) if(SSnetworks.station_network)
SSnetworks.station_network.toggleIDS() SSnetworks.station_network.toggleIDS()
return 1 return TRUE
if("toggleWireless") if("toggleWireless")
. = 1
if(!SSnetworks.station_network) if(!SSnetworks.station_network)
return 1 return
// NTNet is disabled. Enabling can be done without user prompt // NTNet is disabled. Enabling can be done without user prompt
if(SSnetworks.station_network.setting_disabled) if(SSnetworks.station_network.setting_disabled)
SSnetworks.station_network.setting_disabled = 0 SSnetworks.station_network.setting_disabled = FALSE
return 1 return TRUE
// NTNet is enabled and user is about to shut it down. Let's ask them if they really want to do it, as wirelessly connected computers won't connect without NTNet being enabled (which may prevent people from turning it back on) SSnetworks.station_network.setting_disabled = TRUE
var/mob/user = usr return TRUE
if(!user)
return 1
var/response = alert(user, "Really disable NTNet wireless? If your computer is connected wirelessly you won't be able to turn it back on! This will affect all connected wireless devices.", "NTNet shutdown", "Yes", "No")
if(response == "Yes")
SSnetworks.station_network.setting_disabled = 1
return 1
if("purgelogs") if("purgelogs")
. = 1
if(SSnetworks.station_network) if(SSnetworks.station_network)
SSnetworks.station_network.purge_logs() SSnetworks.station_network.purge_logs()
return TRUE
if("updatemaxlogs") if("updatemaxlogs")
. = 1 var/logcount = params["new_number"]
var/mob/user = usr
var/logcount = text2num(input(user,"Enter amount of logs to keep in memory ([MIN_NTNET_LOGS]-[MAX_NTNET_LOGS]):"))
if(SSnetworks.station_network) if(SSnetworks.station_network)
SSnetworks.station_network.update_max_log_count(logcount) SSnetworks.station_network.update_max_log_count(logcount)
return TRUE
if("toggle_function") if("toggle_function")
. = 1
if(!SSnetworks.station_network) if(!SSnetworks.station_network)
return 1 return
SSnetworks.station_network.toggle_function(text2num(params["id"])) SSnetworks.station_network.toggle_function(text2num(params["id"]))
return TRUE
/datum/computer_file/program/ntnetmonitor/ui_data(mob/user) /datum/computer_file/program/ntnetmonitor/ui_data(mob/user)
if(!SSnetworks.station_network) if(!SSnetworks.station_network)
@@ -73,6 +63,8 @@
data["config_systemcontrol"] = SSnetworks.station_network.setting_systemcontrol data["config_systemcontrol"] = SSnetworks.station_network.setting_systemcontrol
data["ntnetlogs"] = list() data["ntnetlogs"] = list()
data["minlogs"] = MIN_NTNET_LOGS
data["maxlogs"] = MAX_NTNET_LOGS
for(var/i in SSnetworks.station_network.logs) for(var/i in SSnetworks.station_network.logs)
data["ntnetlogs"] += list(list("entry" = i)) data["ntnetlogs"] += list(list("entry" = i))

View File

@@ -81,13 +81,13 @@
if(air.total_moles()) if(air.total_moles())
for(var/gasid in air.gases) for(var/gasid in air.gases)
gasdata.Add(list(list( gasdata.Add(list(list(
"name"= GLOB.meta_gas_names[gasid], "name"= air.gases[gasid][GAS_META][META_GAS_NAME],
"amount" = round(100*air.gases[gasid]/air.total_moles(),0.01)))) "amount" = round(100*air.gases[gasid][MOLES]/air.total_moles(),0.01))))
else else
for(var/gasid in air.gases) for(var/gasid in air.gases)
gasdata.Add(list(list( gasdata.Add(list(list(
"name"= GLOB.meta_gas_names[gasid], "name"= air.gases[gasid][GAS_META][META_GAS_NAME],
"amount" = 0))) "amount" = 0)))
data["gases"] = gasdata data["gases"] = gasdata

View File

@@ -167,6 +167,7 @@
// So drones can teach borgs and AI dronespeak. For best effect, combine with mother drone lawset. // So drones can teach borgs and AI dronespeak. For best effect, combine with mother drone lawset.
/obj/item/dronespeak_manual /obj/item/dronespeak_manual
name = "dronespeak manual" name = "dronespeak manual"
desc = "The book's cover reads: \"Understanding Dronespeak - An exercise in futility.\"" desc = "The book's cover reads: \"Understanding Dronespeak - An exercise in futility.\""
@@ -180,7 +181,7 @@
to_chat(user, "<span class='boldannounce'>You start skimming through [src], but you already know dronespeak.</span>") to_chat(user, "<span class='boldannounce'>You start skimming through [src], but you already know dronespeak.</span>")
else else
to_chat(user, "<span class='boldannounce'>You start skimming through [src], and suddenly the drone chittering makes sense.</span>") to_chat(user, "<span class='boldannounce'>You start skimming through [src], and suddenly the drone chittering makes sense.</span>")
user.grant_language(/datum/language/drone, TRUE, TRUE, LANGUAGE_MIND) user.grant_language(/datum/language/drone, TRUE, TRUE)
return return
if(user.has_language(/datum/language/drone)) if(user.has_language(/datum/language/drone))
@@ -201,7 +202,7 @@
M.visible_message("<span class='danger'>[user] beats [M] over the head with [src]!</span>", "<span class='userdanger'>[user] beats you over the head with [src]!</span>", "<span class='hear'>You hear smacking.</span>") M.visible_message("<span class='danger'>[user] beats [M] over the head with [src]!</span>", "<span class='userdanger'>[user] beats you over the head with [src]!</span>", "<span class='hear'>You hear smacking.</span>")
else else
M.visible_message("<span class='notice'>[user] teaches [M] by beating [M.p_them()] over the head with [src]!</span>", "<span class='boldnotice'>As [user] hits you with [src], chitters resonate in your mind.</span>", "<span class='hear'>You hear smacking.</span>") M.visible_message("<span class='notice'>[user] teaches [M] by beating [M.p_them()] over the head with [src]!</span>", "<span class='boldnotice'>As [user] hits you with [src], chitters resonate in your mind.</span>", "<span class='hear'>You hear smacking.</span>")
M.grant_language(/datum/language/drone, TRUE, TRUE, LANGUAGE_MIND) M.grant_language(/datum/language/drone, TRUE, TRUE)
return return
/obj/structure/fluff/oldturret /obj/structure/fluff/oldturret

View File

@@ -105,10 +105,10 @@ GLOBAL_DATUM_INIT(keycard_events, /datum/events, new)
message_admins("[ADMIN_LOOKUPFLW(triggerer)] triggered and [ADMIN_LOOKUPFLW(confirmer)] confirmed event [event]") message_admins("[ADMIN_LOOKUPFLW(triggerer)] triggered and [ADMIN_LOOKUPFLW(confirmer)] confirmed event [event]")
var/area/A1 = get_area(triggerer) var/area/A1 = get_area(triggerer)
deadchat_broadcast(" triggered [event] at <span class='name'>[A1.name]</span>.", "<span class='name'>[triggerer]</span>", triggerer, message_type=DEADCHAT_ANNOUNCEMENT) deadchat_broadcast(" triggered [event] at <span class='name'>[A1.name]</span>.", "<span class='name'>[triggerer]</span>", triggerer)
var/area/A2 = get_area(confirmer) var/area/A2 = get_area(confirmer)
deadchat_broadcast(" confirmed [event] at <span class='name'>[A2.name]</span>.", "<span class='name'>[confirmer]</span>", confirmer, message_type=DEADCHAT_ANNOUNCEMENT) deadchat_broadcast(" confirmed [event] at <span class='name'>[A2.name]</span>.", "<span class='name'>[confirmer]</span>", confirmer)
switch(event) switch(event)
if(KEYCARD_RED_ALERT) if(KEYCARD_RED_ALERT)
set_security_level(SEC_LEVEL_RED) set_security_level(SEC_LEVEL_RED)

View File

@@ -5,369 +5,3 @@
Two roads diverged in a wood, and I,\n\ Two roads diverged in a wood, and I,\n\
I took the one less traveled by,\n\ I took the one less traveled by,\n\
And that has made all the difference." And that has made all the difference."
icon = 'icons/obj/machines/shuttle_manipulator.dmi'
icon_state = "holograph_on"
density = TRUE
// UI state variables
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
/obj/machinery/shuttle_manipulator/Initialize()
. = ..()
update_icon()
SSshuttle.manipulator = src
/obj/machinery/shuttle_manipulator/Destroy(force)
if(!force)
. = QDEL_HINT_LETMELIVE
else
SSshuttle.manipulator = null
. = ..()
/obj/machinery/shuttle_manipulator/update_overlays()
. = ..()
var/mutable_appearance/hologram_projection = mutable_appearance(icon, "hologram_on")
hologram_projection.pixel_y = 22
var/mutable_appearance/hologram_ship = mutable_appearance(icon, "hologram_whiteship")
hologram_ship.pixel_y = 27
. += hologram_projection
. += hologram_ship
/obj/machinery/shuttle_manipulator/can_interact(mob/user)
// Only admins can use this, but they can use it from anywhere
return user.client && check_rights_for(user.client, R_ADMIN)
/obj/machinery/shuttle_manipulator/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, "shuttle_manipulator", name, 800, 600, master_ui, state)
ui.open()
/proc/shuttlemode2str(mode)
switch(mode)
if(SHUTTLE_IDLE)
. = "idle"
if(SHUTTLE_IGNITING)
. = "engines charging"
if(SHUTTLE_RECALL)
. = "recalled"
if(SHUTTLE_CALL)
. = "called"
if(SHUTTLE_DOCKED)
. = "docked"
if(SHUTTLE_STRANDED)
. = "stranded"
if(SHUTTLE_ESCAPE)
. = "escape"
if(SHUTTLE_ENDGAME)
. = "endgame"
if(!.)
CRASH("shuttlemode2str(): invalid mode [mode]")
/obj/machinery/shuttle_manipulator/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 SSshuttle.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(shuttlemode2str(M.mode))
L["status"] = M.getDbgStatusText()
if(M == existing_shuttle)
data["existing_shuttle"] = L
data["shuttles"] += list(L)
return data
/obj/machinery/shuttle_manipulator/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 = SSshuttle.getShuttle(S.port_id)
selected = S
. = TRUE
if("jump_to")
if(params["type"] == "mobile")
for(var/i in SSshuttle.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 SSshuttle.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 SSshuttle.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 == SSshuttle.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]")
update_icon()
/obj/machinery/shuttle_manipulator/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
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)
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
/obj/machinery/shuttle_manipulator/proc/load_template(datum/map_template/shuttle/S)
. = FALSE
// load shuttle template, centred at shuttle import landmark,
var/turf/landmark_turf = get_turf(locate(/obj/effect/landmark/shuttle_import) in GLOB.landmarks_list)
S.load(landmark_turf, centered = TRUE, register = FALSE)
var/affected = S.get_affected_turfs(landmark_turf, centered=TRUE)
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.on_bought()
return TRUE
/obj/machinery/shuttle_manipulator/proc/unload_preview()
if(preview_shuttle)
preview_shuttle.jumpToNullSpace()
preview_shuttle = null
/obj/docking_port/mobile/proc/admin_fly_shuttle(mob/user)
var/list/options = list()
for(var/port in SSshuttle.stationary)
if (istype(port, /obj/docking_port/stationary/transit))
continue // please don't do this
var/obj/docking_port/stationary/S = port
if (canDock(S) == SHUTTLE_CAN_DOCK)
options[S.name || S.id] = S
options += "--------"
options += "Infinite Transit"
options += "Delete Shuttle"
options += "Into The Sunset (delete & greentext 'escape')"
var/selection = input(user, "Select where to fly [name || id]:", "Fly Shuttle") as null|anything in options
if(!selection)
return
switch(selection)
if("Infinite Transit")
destination = null
mode = SHUTTLE_IGNITING
setTimer(ignitionTime)
if("Delete Shuttle")
if(alert(user, "Really delete [name || id]?", "Delete Shuttle", "Cancel", "Really!") != "Really!")
return
jumpToNullSpace()
if("Into The Sunset (delete & greentext 'escape')")
if(alert(user, "Really delete [name || id] and greentext escape objectives?", "Delete Shuttle", "Cancel", "Really!") != "Really!")
return
intoTheSunset()
else
if(options[selection])
request(options[selection])
/obj/docking_port/mobile/emergency/admin_fly_shuttle(mob/user)
return // use the existing verbs for this
/obj/docking_port/mobile/arrivals/admin_fly_shuttle(mob/user)
switch(alert(user, "Would you like to fly the arrivals shuttle once or change its destination?", "Fly Shuttle", "Fly", "Retarget", "Cancel"))
if("Cancel")
return
if("Fly")
return ..()
var/list/options = list()
for(var/port in SSshuttle.stationary)
if (istype(port, /obj/docking_port/stationary/transit))
continue // please don't do this
var/obj/docking_port/stationary/S = port
if (canDock(S) == SHUTTLE_CAN_DOCK)
options[S.name || S.id] = S
var/selection = input(user, "Select the new arrivals destination:", "Fly Shuttle") as null|anything in options
if(!selection)
return
target_dock = options[selection]
if(!QDELETED(target_dock))
destination = target_dock

View File

@@ -194,10 +194,10 @@
roundstart_template = SSmapping.shuttle_templates[sid] roundstart_template = SSmapping.shuttle_templates[sid]
if(!roundstart_template) if(!roundstart_template)
CRASH("Invalid path ([roundstart_template]) passed to docking port.") CRASH("Invalid path ([sid]/[roundstart_template]) passed to docking port.")
if(roundstart_template) if(roundstart_template)
SSshuttle.manipulator.action_load(roundstart_template, src) SSshuttle.action_load(roundstart_template, src)
//returns first-found touching shuttleport //returns first-found touching shuttleport
/obj/docking_port/stationary/get_docked() /obj/docking_port/stationary/get_docked()

View File

@@ -111,7 +111,7 @@
return UI_DISABLED return UI_DISABLED
return UI_CLOSE // Otherwise, we got nothing. return UI_CLOSE // Otherwise, we got nothing.
/mob/living/carbon/human/shared_living_ui_distance(atom/movable/src_object) /mob/living/carbon/human/shared_living_ui_distance(atom/movable/src_object, viewcheck = TRUE)
if(dna.check_mutation(TK) && tkMaxRangeCheck(src, src_object)) if(dna.check_mutation(TK) && tkMaxRangeCheck(src, src_object))
return UI_INTERACTIVE return UI_INTERACTIVE
return ..() return ..()

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 922 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 568 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

View File

@@ -1050,6 +1050,7 @@
#include "code\game\objects\items\stacks\rods.dm" #include "code\game\objects\items\stacks\rods.dm"
#include "code\game\objects\items\stacks\stack.dm" #include "code\game\objects\items\stacks\stack.dm"
#include "code\game\objects\items\stacks\telecrystal.dm" #include "code\game\objects\items\stacks\telecrystal.dm"
#include "code\game\objects\items\stacks\tickets.dm"
#include "code\game\objects\items\stacks\wrap.dm" #include "code\game\objects\items\stacks\wrap.dm"
#include "code\game\objects\items\stacks\sheets\glass.dm" #include "code\game\objects\items\stacks\sheets\glass.dm"
#include "code\game\objects\items\stacks\sheets\leather.dm" #include "code\game\objects\items\stacks\sheets\leather.dm"