diff --git a/code/__HELPERS/game.dm b/code/__HELPERS/game.dm index 082d473010d..98ce4af1ec8 100644 --- a/code/__HELPERS/game.dm +++ b/code/__HELPERS/game.dm @@ -137,7 +137,7 @@ if(sight_check && !isInSight(A, O)) continue L |= M - //log_to_dd("[recursion_limit] = [M] - [get_turf(M)] - ([M.x], [M.y], [M.z])") + //log_world("[recursion_limit] = [M] - [get_turf(M)] - ([M.x], [M.y], [M.z])") else if(include_radio && istype(A, /obj/item/device/radio)) if(sight_check && !isInSight(A, O)) @@ -167,7 +167,7 @@ var/mob/M = A if(M.client || include_clientless) hear += M - //log_to_dd("Start = [M] - [get_turf(M)] - ([M.x], [M.y], [M.z])") + //log_world("Start = [M] - [get_turf(M)] - ([M.x], [M.y], [M.z])") else if(istype(A, /obj/item/device/radio)) hear += A diff --git a/code/__HELPERS/lists.dm b/code/__HELPERS/lists.dm index 799f94feebb..071c1afa202 100644 --- a/code/__HELPERS/lists.dm +++ b/code/__HELPERS/lists.dm @@ -416,7 +416,7 @@ //Don't use this on lists larger than half a dozen or so /proc/insertion_sort_numeric_list_ascending(var/list/L) - //log_to_dd("ascending len input: [L.len]") + //log_world("ascending len input: [L.len]") var/list/out = list(pop(L)) for(var/entry in L) if(isnum(entry)) @@ -429,13 +429,13 @@ if(!success) out.Add(entry) - //log_to_dd(" output: [out.len]") + //log_world(" output: [out.len]") return out /proc/insertion_sort_numeric_list_descending(var/list/L) - //log_to_dd("descending len input: [L.len]") + //log_world("descending len input: [L.len]") var/list/out = insertion_sort_numeric_list_ascending(L) - //log_to_dd(" output: [out.len]") + //log_world(" output: [out.len]") return reverselist(out) //Copies a list, and all lists inside it recusively diff --git a/code/__HELPERS/logging.dm b/code/__HELPERS/logging.dm deleted file mode 100644 index b31e3a40c88..00000000000 --- a/code/__HELPERS/logging.dm +++ /dev/null @@ -1,131 +0,0 @@ -//print an error message to world.log - -// On Linux/Unix systems the line endings are LF, on windows it's CRLF, admins that don't use notepad++ -// will get logs that are one big line if the system is Linux and they are using notepad. This solves it by adding CR to every line ending -// in the logs. ascii character 13 = CR - -/var/global/log_end= world.system_type == UNIX ? ascii2text(13) : "" - - -/proc/error(msg) - log_to_dd("## ERROR: [msg]") - -#define WARNING(MSG) warning("[MSG] in [__FILE__] at line [__LINE__] src: [src] usr: [usr].") -//print a warning message to world.log -/proc/warning(msg) - log_to_dd("## WARNING: [msg]") - -//print a testing-mode debug message to world.log and world -#ifdef TESTING -#define testing(msg) log_to_dd("## TESTING: [msg]"); to_chat(world, "## TESTING: [msg]") -#else -#define testing(msg) -#endif - -/proc/log_admin(text) - admin_log.Add(text) - if(config.log_admin) - diary << "\[[time_stamp()]]ADMIN: [text]" - - -/proc/log_debug(text) - if(config.log_debug) - diary << "\[[time_stamp()]]DEBUG: [text]" - - for(var/client/C in admins) - if(check_rights(R_DEBUG, 0, C.mob) && (C.prefs.toggles & CHAT_DEBUGLOGS)) - to_chat(C, "DEBUG: [text]") - - -/proc/log_game(text) - if(config.log_game) - diary << "\[[time_stamp()]]GAME: [text]" - -/proc/log_vote(text) - if(config.log_vote) - diary << "\[[time_stamp()]]VOTE: [text]" - -/proc/log_access(text) - if(config.log_access) - diary << "\[[time_stamp()]]ACCESS: [text]" - -/proc/log_say(text) - if(config.log_say) - diary << "\[[time_stamp()]]SAY: [text]" - -/proc/log_robot(text) - if(config.log_say) - diary << "\[[time_stamp()]]ROBOT: [text]" - -/proc/log_ooc(text) - if(config.log_ooc) - diary << "\[[time_stamp()]]OOC: [text]" - -/proc/log_whisper(text) - if(config.log_whisper) - diary << "\[[time_stamp()]]WHISPER: [text]" - -/proc/log_emote(text) - if(config.log_emote) - diary << "\[[time_stamp()]]EMOTE: [text]" - -/proc/log_attack(text) - if(config.log_attack) - diary << "\[[time_stamp()]]ATTACK: [text]" //Seperate attack logs? Why? - -/proc/log_adminsay(text) - if(config.log_adminchat) - diary << "\[[time_stamp()]]ADMINSAY: [text]" - -/proc/log_adminwarn(text) - if(config.log_adminwarn) - diary << "\[[time_stamp()]]ADMINWARN: [text]" - -/proc/log_pda(text) - if(config.log_pda) - diary << "\[[time_stamp()]]PDA: [text][log_end]" - -/proc/log_chat(text) - if (config.log_pda) - diary << "\[[time_stamp()]]CHAT: [text]" - -/proc/log_misc(text) - diary << "\[[time_stamp()]]MISC: [text][log_end]" - -/proc/log_to_dd(text) - world.log << text - if(config && config.log_world_output) - diary << "\[[time_stamp()]]DD_OUTPUT: [text][log_end]" - -/** - * Standardized method for tracking startup times. - */ -/proc/log_startup_progress(var/message) - to_chat(world, "[message]") - log_to_dd(message) - -// A logging proc that only outputs after setup is done, to -// help devs test initialization stuff that happens a lot -/proc/log_after_setup(var/message) - if(ticker && ticker.current_state > GAME_STATE_SETTING_UP) - to_chat(world, "[message]") - log_to_dd(message) - -// Helper procs for building detailed log lines - -/proc/datum_info_line(var/datum/d) - if(!istype(d)) - return - if(!istype(d, /mob)) - return "[d] ([d.type])" - var/mob/m = d - return "[m] ([m.ckey]) ([m.type])" - -/proc/atom_loc_line(var/atom/a) - if(!istype(a)) - return - var/turf/t = get_turf(a) - if(istype(t)) - return "[a.loc] ([t.x],[t.y],[t.z]) ([a.loc.type])" - else if(a.loc) - return "[a.loc] (0,0,0) ([a.loc.type])" diff --git a/code/__HELPERS/mobs.dm b/code/__HELPERS/mobs.dm index 94b7a9b4255..7f7b9715907 100644 --- a/code/__HELPERS/mobs.dm +++ b/code/__HELPERS/mobs.dm @@ -243,30 +243,28 @@ proc/age2agedescription(age) Proc for attack log creation, because really why not 1 argument is the actor 2 argument is the target of action -3 is the description of action(like punched, throwed, or any other verb) -4 is the tool with which the action was made(usually item) -5 is additional information, anything that needs to be added -6 is whether the attack should be logged to the log file and shown to admins +3 is the full description of the action +4 is whether or not to message admins +This is always put in the attack log. */ -proc/add_logs(mob/user, mob/target, what_done, var/object=null, var/addition=null, var/admin=1, var/print_attack_log = 1)//print_attack_log notifies admins with attack logs on - var/list/ignore=list("shaked", "CPRed", "grabbed", "disarmed") - if(!user) +/proc/add_attack_logs(mob/user, mob/target, what_done, admin_notify = TRUE) + if(islist(target)) // Multi-victim adding + var/list/targets = target + for(var/mob/M in targets) + add_attack_logs(user, M, what_done, admin_notify) return - if(ismob(user)) - user.create_attack_log("Has [what_done] [key_name(target)][object ? " with [object]" : " "][addition]") - if(ismob(target)) - target.create_attack_log("Has been [what_done] by [key_name(user)][object ? " with [object]" : " "][addition]") - if(admin) - log_attack("[key_name(user)] [what_done] [key_name(target)][object ? " with [object]" : " "][addition]") - if(istype(target) && (target.key)) - if(what_done in ignore) - return - if(target == user) - return - if(!print_attack_log) - return - msg_admin_attack("[key_name_admin(user)] [what_done] [key_name_admin(target)][object ? " with [object]" : " "][addition]") + + var/user_str = key_name(user) + var/target_str = key_name(target) + + if(istype(user)) + user.create_attack_log("Attacked [target_str]: [what_done]") + if(istype(target)) + target.create_attack_log("Attacked by [user_str]: [what_done]") + log_attack(user_str, target_str, what_done) + if(admin_notify) + msg_admin_attack("[key_name_admin(user)] vs [key_name_admin(target)]: [what_done]") /proc/do_mob(var/mob/user, var/mob/target, var/time = 30, var/uninterruptible = 0, progress = 1, datum/callback/extra_checks = null) if(!user || !target) diff --git a/code/__HELPERS/time.dm b/code/__HELPERS/time.dm index 57adb01c2cb..b47e60275e8 100644 --- a/code/__HELPERS/time.dm +++ b/code/__HELPERS/time.dm @@ -42,9 +42,12 @@ /proc/worldtime2text() return gameTimestamp("hh:mm:ss", world.time) -/proc/time_stamp(format = "hh:mm:ss", show_ds) - var/time_string = time2text(world.timeofday, format) - return show_ds ? "[time_string]:[world.timeofday % 10]" : time_string +// This is ISO-8601 +// If anything that uses this proc shouldn't be ISO-8601, change that thing, not this proc. This is important for logging. +/proc/time_stamp() + var/date_portion = time2text(world.timeofday, "YYYY-MM-DD") + var/time_portion = time2text(world.timeofday, "hh:mm:ss") + return "[date_portion]T[time_portion]" /proc/gameTimestamp(format = "hh:mm:ss", wtime=null) if(!wtime) diff --git a/code/__helpers/_logging.dm b/code/__helpers/_logging.dm new file mode 100644 index 00000000000..cbc514d7232 --- /dev/null +++ b/code/__helpers/_logging.dm @@ -0,0 +1,185 @@ +//location of the rust-g library +#define RUST_G "rust_g" + +// On Linux/Unix systems the line endings are LF, on windows it's CRLF, admins that don't use notepad++ +// will get logs that are one big line if the system is Linux and they are using notepad. This solves it by adding CR to every line ending +// in the logs. ascii character 13 = CR + +/var/global/log_end = world.system_type == UNIX ? ascii2text(13) : "" + +#define DIRECT_OUTPUT(A, B) A << B +#define SEND_IMAGE(target, image) DIRECT_OUTPUT(target, image) +#define SEND_SOUND(target, sound) DIRECT_OUTPUT(target, sound) +#define SEND_TEXT(target, text) DIRECT_OUTPUT(target, text) +#define WRITE_FILE(file, text) DIRECT_OUTPUT(file, text) +#define WRITE_LOG(log, text) call(RUST_G, "log_write")(log, text) + +/proc/error(msg) + log_world("## ERROR: [msg]") + +//print a warning message to world.log +#define WARNING(MSG) warning("[MSG] in [__FILE__] at line [__LINE__] src: [src] usr: [usr].") +/proc/warning(msg) + log_world("## WARNING: [msg]") + +//print a testing-mode debug message to world.log and world +#ifdef TESTING +#define testing(msg) log_world("## TESTING: [msg]"); to_chat(world, "## TESTING: [msg]") +#else +#define testing(msg) +#endif + +/proc/log_admin(text) + admin_log.Add(text) + if(config.log_admin) + WRITE_LOG(GLOB.world_game_log, "ADMIN: [text][log_end]") + +/proc/log_debug(text) + if(config.log_debug) + WRITE_LOG(GLOB.world_game_log, "DEBUG: [text][log_end]") + + for(var/client/C in admins) + if(check_rights(R_DEBUG, 0, C.mob) && (C.prefs.toggles & CHAT_DEBUGLOGS)) + to_chat(C, "DEBUG: [text]") + +/proc/log_game(text) + if(config.log_game) + WRITE_LOG(GLOB.world_game_log, "GAME: [text][log_end]") + +/proc/log_vote(text) + if(config.log_vote) + WRITE_LOG(GLOB.world_game_log, "VOTE: [text][log_end]") + +/proc/log_access_in(client/new_client) + if(config.log_access) + var/message = "[key_name(new_client)] - IP:[new_client.address] - CID:[new_client.computer_id] - BYOND v[new_client.byond_version]" + WRITE_LOG(GLOB.world_game_log, "ACCESS IN: [message][log_end]") + +/proc/log_access_out(mob/last_mob) + if(config.log_access) + var/message = "[key_name(last_mob)] - IP:[last_mob.lastKnownIP] - CID:[last_mob.computer_id] - BYOND Logged Out" + WRITE_LOG(GLOB.world_game_log, "ACCESS OUT: [message][log_end]") + +/proc/log_say(text, mob/speaker) + if(config.log_say) + WRITE_LOG(GLOB.world_game_log, "SAY: [speaker.simple_info_line()]: [html_decode(text)][log_end]") + +/proc/log_whisper(text, mob/speaker) + if(config.log_whisper) + WRITE_LOG(GLOB.world_game_log, "WHISPER: [speaker.simple_info_line()]: [html_decode(text)][log_end]") + +/proc/log_ooc(text, client/user) + if(config.log_ooc) + WRITE_LOG(GLOB.world_game_log, "OOC: [user.simple_info_line()]: [html_decode(text)][log_end]") + +/proc/log_aooc(text, client/user) + if(config.log_ooc) + WRITE_LOG(GLOB.world_game_log, "AOOC: [user.simple_info_line()]: [html_decode(text)][log_end]") + +/proc/log_looc(text, client/user) + if(config.log_ooc) + WRITE_LOG(GLOB.world_game_log, "LOOC: [user.simple_info_line()]: [html_decode(text)][log_end]") + +/proc/log_emote(text, mob/speaker) + if(config.log_emote) + WRITE_LOG(GLOB.world_game_log, "EMOTE: [speaker.simple_info_line()]: [html_decode(text)][log_end]") + +/proc/log_attack(attacker, defender, message) + if(config.log_attack) + WRITE_LOG(GLOB.world_game_log, "ATTACK: [attacker] against [defender]: [message][log_end]") //Seperate attack logs? Why? + +/proc/log_adminsay(text, mob/speaker) + if(config.log_adminchat) + WRITE_LOG(GLOB.world_game_log, "ADMINSAY: [speaker.simple_info_line()]: [html_decode(text)][log_end]") + +/proc/log_mentorsay(text, mob/speaker) + if(config.log_adminchat) + WRITE_LOG(GLOB.world_game_log, "MENTORSAY: [speaker.simple_info_line()]: [html_decode(text)][log_end]") + +/proc/log_ghostsay(text, mob/speaker) + if(config.log_say) + WRITE_LOG(GLOB.world_game_log, "DEADCHAT: [speaker.simple_info_line()]: [html_decode(text)][log_end]") + +/proc/log_ghostemote(text, mob/speaker) + if(config.log_emote) + WRITE_LOG(GLOB.world_game_log, "DEADEMOTE: [speaker.simple_info_line()]: [html_decode(text)][log_end]") + +/proc/log_adminwarn(text) + if(config.log_adminwarn) + WRITE_LOG(GLOB.world_game_log, "ADMINWARN: [html_decode(text)][log_end]") + +/proc/log_pda(text, mob/speaker) + if(config.log_pda) + WRITE_LOG(GLOB.world_game_log, "PDA: [speaker.simple_info_line()]: [html_decode(text)][log_end]") + +/proc/log_chat(text, mob/speaker) + if(config.log_pda) + WRITE_LOG(GLOB.world_game_log, "CHAT: [speaker.simple_info_line()] [html_decode(text)][log_end]") + +/proc/log_misc(text) + WRITE_LOG(GLOB.world_game_log, "MISC: [text][log_end]") + +/proc/log_world(text) + SEND_TEXT(world.log, text) + if(config && config.log_world_output) + WRITE_LOG(GLOB.world_game_log, "WORLD: [html_decode(text)][log_end]") + +/proc/log_runtime_txt(text) // different from /tg/'s log_runtime because our error handler has a log_runtime proc already that does other stuff + GLOB.world_runtime_log << text + +/proc/log_config(text) + WRITE_LOG(GLOB.config_error_log, text) + SEND_TEXT(world.log, text) + +/proc/log_href(text) + WRITE_LOG(GLOB.world_href_log, "HREF: [html_decode(text)]") + +/** + * Standardized method for tracking startup times. + */ +/proc/log_startup_progress(var/message) + to_chat(world, "[message]") + log_world(message) + +// A logging proc that only outputs after setup is done, to +// help devs test initialization stuff that happens a lot +/proc/log_after_setup(var/message) + if(ticker && ticker.current_state > GAME_STATE_SETTING_UP) + to_chat(world, "[message]") + log_world(message) + +/* For logging round startup. */ +/proc/start_log(log) + WRITE_LOG(log, "Starting up.\n-------------------------") + +/* Close open log handles. This should be called as late as possible, and no logging should hapen after. */ +/proc/shutdown_logging() + call(RUST_G, "log_close_all")() + +// Helper procs for building detailed log lines + +/proc/datum_info_line(var/datum/d) + if(!istype(d)) + return + if(!istype(d, /mob)) + return "[d] ([d.type])" + var/mob/m = d + return "[m] ([m.ckey]) ([m.type])" + +/proc/atom_loc_line(var/atom/a) + if(!istype(a)) + return + var/turf/t = get_turf(a) + if(istype(t)) + return "[a.loc] ([t.x],[t.y],[t.z]) ([a.loc.type])" + else if(a.loc) + return "[a.loc] (0,0,0) ([a.loc.type])" + +/mob/proc/simple_info_line() + return "[key_name(src)] ([x],[y],[z])" + +/client/proc/simple_info_line() + return "[key_name(src)] ([mob.x],[mob.y],[mob.z])" + +//this is only used here (for now) +#undef RUST_G \ No newline at end of file diff --git a/code/_globalvars/logging.dm b/code/_globalvars/logging.dm index e4223fcee55..f96e83cb7a1 100644 --- a/code/_globalvars/logging.dm +++ b/code/_globalvars/logging.dm @@ -1,6 +1,13 @@ -var/diary = null -var/diaryofmeanpeople = null -var/href_logfile = null +GLOBAL_VAR(log_directory) +GLOBAL_PROTECT(log_directory) +GLOBAL_VAR(world_game_log) +GLOBAL_PROTECT(world_game_log) +GLOBAL_VAR(config_error_log) +GLOBAL_PROTECT(config_error_log) +GLOBAL_VAR(world_runtime_log) +GLOBAL_PROTECT(world_runtime_log) +GLOBAL_VAR(world_href_log) +GLOBAL_PROTECT(world_href_log) var/list/jobMax = list() var/list/bombers = list( ) @@ -13,4 +20,4 @@ var/list/IClog = list() var/list/OOClog = list() var/list/adminlog = list() -var/list/investigate_log_subjects = list("notes", "watchlist", "hrefs") +var/list/investigate_log_subjects = list("notes", "watchlist", "hrefs") \ No newline at end of file diff --git a/code/_onclick/item_attack.dm b/code/_onclick/item_attack.dm index e03ee6ee606..ab794b23b18 100644 --- a/code/_onclick/item_attack.dm +++ b/code/_onclick/item_attack.dm @@ -66,7 +66,7 @@ user.do_attack_animation(M) M.attacked_by(src, user, def_zone) - add_logs(user, M, "attacked", name, "(INTENT: [uppertext(user.a_intent)]) (DAMTYPE: [uppertext(damtype)])", print_attack_log = (force > 0))//print it if stuff deals damage + add_attack_logs(user, M, "attacked with [name] (INTENT: [uppertext(user.a_intent)]) (DAMTYPE: [uppertext(damtype)])", admin_notify = (force > 0)) add_fingerprint(user) diff --git a/code/_onclick/rig.dm b/code/_onclick/rig.dm index 215428d1d48..4c22d986e5f 100644 --- a/code/_onclick/rig.dm +++ b/code/_onclick/rig.dm @@ -69,7 +69,7 @@ if(istype(rig) && !rig.offline && rig.selected_module) if(src != rig.wearer) if(rig.ai_can_move_suit(src, check_user_module = 1)) - message_admins("[key_name_admin(src, include_name = 1)] is trying to force \the [key_name_admin(rig.wearer, include_name = 1)] to use a hardsuit module.") + message_admins("[key_name_admin(src)] is trying to force \the [key_name_admin(rig.wearer)] to use a hardsuit module.") else return 0 rig.selected_module.engage(A, alert_ai) diff --git a/code/controllers/ProcessScheduler/core/process.dm b/code/controllers/ProcessScheduler/core/process.dm index 9e777d07ea3..134eaec96a6 100644 --- a/code/controllers/ProcessScheduler/core/process.dm +++ b/code/controllers/ProcessScheduler/core/process.dm @@ -386,9 +386,9 @@ if(istype(thrower, /atom)) var/atom/A = thrower ptext += " ([A]) ([A.x],[A.y],[A.z])" - log_to_dd("\[[time_stamp()]\] Process [name] caught exception[ptext]: [etext]") + log_world("\[[time_stamp()]\] Process [name] caught exception[ptext]: [etext]") if(exceptions[eid] >= 10) - log_to_dd("This exception will now be ignored for ten minutes.") + log_world("This exception will now be ignored for ten minutes.") spawn(6000) exceptions[eid] = 0 diff --git a/code/controllers/configuration.dm b/code/controllers/configuration.dm index 7750a40074f..b71531ee20f 100644 --- a/code/controllers/configuration.dm +++ b/code/controllers/configuration.dm @@ -55,7 +55,6 @@ var/guest_jobban = 1 var/usewhitelist = 0 var/mods_are_mentors = 0 - var/kick_inactive = 0 //force disconnect for inactive players var/load_jobs_from_txt = 0 var/ToRban = 0 var/automute_on = 0 //enables automuting/spam prevention @@ -209,7 +208,6 @@ if(initial(M.config_tag)) if(!(initial(M.config_tag) in modes)) // ensure each mode is added only once - diary << "Adding game mode [initial(M.name)] ([initial(M.config_tag)]) to configuration." src.modes += initial(M.config_tag) src.mode_names[initial(M.config_tag)] = initial(M.name) src.probabilities[initial(M.config_tag)] = initial(M.probability) @@ -423,16 +421,13 @@ if(prob_name in config.modes) config.probabilities[prob_name] = text2num(prob_value) else - diary << "Unknown game mode probability configuration definition: [prob_name]." + log_config("Unknown game mode probability configuration definition: [prob_name].") else - diary << "Incorrect probability configuration definition: [prob_name] [prob_value]." + log_config("Incorrect probability configuration definition: [prob_name] [prob_value].") if("allow_random_events") config.allow_random_events = 1 - if("kick_inactive") - config.kick_inactive = 1 - if("load_jobs_from_txt") load_jobs_from_txt = 1 @@ -618,12 +613,10 @@ if("disable_high_pop_mc_mode_amount") config.disable_high_pop_mc_mode_amount = text2num(value) else - diary << "Unknown setting in configuration: '[name]'" + log_config("Unknown setting in configuration: '[name]'") else if(type == "game_options") - if(!value) - diary << "Unknown value for setting [name] in [filename]." value = text2num(value) switch(name) @@ -684,7 +677,7 @@ if("enable_night_shifts") config.enable_night_shifts = TRUE else - diary << "Unknown setting in configuration: '[name]'" + log_config("Unknown setting in configuration: '[name]'") /datum/configuration/proc/loadsql(filename) // -- TLE var/list/Lines = file2list(filename) @@ -729,10 +722,10 @@ if("db_version") db_version = text2num(value) else - diary << "Unknown setting in configuration: '[name]'" + log_config("Unknown setting in configuration: '[name]'") if(config.sql_enabled && db_version != SQL_VERSION) config.sql_enabled = 0 - diary << "WARNING: DB_CONFIG DEFINITION MISMATCH!" + log_config("WARNING: DB_CONFIG DEFINITION MISMATCH!") spawn(60) if(ticker.current_state == GAME_STATE_PREGAME) going = 0 diff --git a/code/controllers/globals.dm b/code/controllers/globals.dm index ab92ca49be7..62b83100fb4 100644 --- a/code/controllers/globals.dm +++ b/code/controllers/globals.dm @@ -16,8 +16,6 @@ GLOBAL_REAL(GLOB, /datum/controller/global_vars) gvars_datum_in_built_vars = exclude_these.vars + list("gvars_datum_protected_varlist", "gvars_datum_in_built_vars", "gvars_datum_init_order") qdel(exclude_these) - log_to_dd("[vars.len - gvars_datum_in_built_vars.len] global variables") - Initialize() /datum/controller/global_vars/Destroy(force) @@ -60,7 +58,7 @@ GLOBAL_REAL(GLOB, /datum/controller/global_vars) var/list/expected_global_procs = vars - gvars_datum_in_built_vars for(var/I in global_procs) expected_global_procs -= replacetext("[I]", "InitGlobal", "") - log_to_dd("Missing procs: [expected_global_procs.Join(", ")]") + log_world("Missing procs: [expected_global_procs.Join(", ")]") for(var/I in global_procs) var/start_tick = world.time call(src, I)() diff --git a/code/controllers/master.dm b/code/controllers/master.dm index 28395717f08..ddde5460cef 100644 --- a/code/controllers/master.dm +++ b/code/controllers/master.dm @@ -63,6 +63,8 @@ GLOBAL_REAL(Master, /datum/controller/master) = new /datum/controller/master/New() makeDatumRefLists() + //temporary file used to record errors with loading config, moved to log directory once logging is set up + GLOB.config_error_log = GLOB.world_game_log = GLOB.world_runtime_log = "data/logs/config_error.log" load_configuration() // Highlander-style: there can only be one! Kill off the old and replace it with the new. @@ -96,9 +98,9 @@ GLOBAL_REAL(Master, /datum/controller/master) = new sortTim(subsystems, /proc/cmp_subsystem_init) reverseRange(subsystems) for(var/datum/controller/subsystem/ss in subsystems) - log_to_dd("Shutting down [ss.name] subsystem...") + log_world("Shutting down [ss.name] subsystem...") ss.Shutdown() - log_to_dd("Shutdown complete") + log_world("Shutdown complete") // Returns 1 if we created a new mc, 0 if we couldn't due to a recent restart, // -1 if we encountered a runtime trying to recreate it @@ -133,7 +135,7 @@ GLOBAL_REAL(Master, /datum/controller/master) = new msg += "\t [varname] = [D]([D.type])\n" else msg += "\t [varname] = [varval]\n" - log_to_dd(msg) + log_world(msg) var/datum/controller/subsystem/BadBoy = Master.last_type_processed var/FireHim = FALSE @@ -149,7 +151,7 @@ GLOBAL_REAL(Master, /datum/controller/master) = new BadBoy.flags |= SS_NO_FIRE if(msg) to_chat(admins, "[msg]") - log_to_dd(msg) + log_world(msg) if(istype(Master.subsystems)) if(FireHim) @@ -191,7 +193,7 @@ GLOBAL_REAL(Master, /datum/controller/master) = new var/msg = "Initializations complete within [time] second[time == 1 ? "" : "s"]!" to_chat(world, "[msg]") - log_to_dd(msg) + log_world(msg) if(!current_runlevel) SetRunLevel(1) @@ -347,7 +349,7 @@ GLOBAL_REAL(Master, /datum/controller/master) = new if(CheckQueue(subsystems_to_check) <= 0) if(!SoftReset(tickersubsystems, runlevel_sorted_subsystems)) - log_to_dd("MC: SoftReset() failed, crashing") + log_world("MC: SoftReset() failed, crashing") return if(!error_level) iteration++ @@ -359,7 +361,7 @@ GLOBAL_REAL(Master, /datum/controller/master) = new if(queue_head) if(RunQueue() <= 0) if(!SoftReset(tickersubsystems, runlevel_sorted_subsystems)) - log_to_dd("MC: SoftReset() failed, crashing") + log_world("MC: SoftReset() failed, crashing") return if(!error_level) iteration++ @@ -538,9 +540,9 @@ GLOBAL_REAL(Master, /datum/controller/master) = new // called if any mc's queue procs runtime or exit improperly. /datum/controller/master/proc/SoftReset(list/ticker_SS, list/runlevel_SS) . = 0 - log_to_dd("MC: SoftReset called, resetting MC queue state.") + log_world("MC: SoftReset called, resetting MC queue state.") if(!istype(subsystems) || !istype(ticker_SS) || !istype(runlevel_SS)) - log_to_dd("MC: SoftReset: Bad list contents: '[subsystems]' '[ticker_SS]' '[runlevel_SS]'") + log_world("MC: SoftReset: Bad list contents: '[subsystems]' '[ticker_SS]' '[runlevel_SS]'") return var/subsystemstocheck = subsystems + ticker_SS for(var/I in runlevel_SS) @@ -554,26 +556,26 @@ GLOBAL_REAL(Master, /datum/controller/master) = new ticker_SS -= list(SS) for(var/I in runlevel_SS) I -= list(SS) - log_to_dd("MC: SoftReset: Found bad entry in subsystem list, '[SS]'") + log_world("MC: SoftReset: Found bad entry in subsystem list, '[SS]'") continue if(SS.queue_next && !istype(SS.queue_next)) - log_to_dd("MC: SoftReset: Found bad data in subsystem queue, queue_next = '[SS.queue_next]'") + log_world("MC: SoftReset: Found bad data in subsystem queue, queue_next = '[SS.queue_next]'") SS.queue_next = null if(SS.queue_prev && !istype(SS.queue_prev)) - log_to_dd("MC: SoftReset: Found bad data in subsystem queue, queue_prev = '[SS.queue_prev]'") + log_world("MC: SoftReset: Found bad data in subsystem queue, queue_prev = '[SS.queue_prev]'") SS.queue_prev = null SS.queued_priority = 0 SS.queued_time = 0 SS.state = SS_IDLE if(queue_head && !istype(queue_head)) - log_to_dd("MC: SoftReset: Found bad data in subsystem queue, queue_head = '[queue_head]'") + log_world("MC: SoftReset: Found bad data in subsystem queue, queue_head = '[queue_head]'") queue_head = null if(queue_tail && !istype(queue_tail)) - log_to_dd("MC: SoftReset: Found bad data in subsystem queue, queue_tail = '[queue_tail]'") + log_world("MC: SoftReset: Found bad data in subsystem queue, queue_tail = '[queue_tail]'") queue_tail = null queue_priority_count = 0 queue_priority_count_bg = 0 - log_to_dd("MC: SoftReset: Finished.") + log_world("MC: SoftReset: Finished.") . = 1 diff --git a/code/controllers/subsystem.dm b/code/controllers/subsystem.dm index a78750bf8d0..4b1d59fa82e 100644 --- a/code/controllers/subsystem.dm +++ b/code/controllers/subsystem.dm @@ -162,7 +162,7 @@ var/time = (REALTIMEOFDAY - start_timeofday) / 10 var/msg = "Initialized [name] subsystem within [time] second[time == 1 ? "" : "s"]!" to_chat(world, "[msg]") - log_to_dd(msg) + log_world(msg) return time //hook for printing stats to the "MC" statuspanel for admins to see performance and related stats etc. diff --git a/code/datums/datumvars.dm b/code/datums/datumvars.dm index 8e86a4eb5ed..9526a3e671a 100644 --- a/code/datums/datumvars.dm +++ b/code/datums/datumvars.dm @@ -1260,7 +1260,7 @@ if(prompt != "Yes") return L.Cut(index, index+1) - log_to_dd("### ListVarEdit by [src]: /list's contents: REMOVED=[html_encode("[variable]")]") + log_world("### ListVarEdit by [src]: /list's contents: REMOVED=[html_encode("[variable]")]") log_admin("[key_name(src)] modified list's contents: REMOVED=[variable]") message_admins("[key_name_admin(src)] modified list's contents: REMOVED=[variable]") return TRUE @@ -1281,7 +1281,7 @@ return TRUE uniqueList_inplace(L) - log_to_dd("### ListVarEdit by [src]: /list contents: CLEAR DUPES") + log_world("### ListVarEdit by [src]: /list contents: CLEAR DUPES") log_admin("[key_name(src)] modified list's contents: CLEAR DUPES") message_admins("[key_name_admin(src)] modified list's contents: CLEAR DUPES") return TRUE @@ -1293,7 +1293,7 @@ return TRUE listclearnulls(L) - log_to_dd("### ListVarEdit by [src]: /list contents: CLEAR NULLS") + log_world("### ListVarEdit by [src]: /list contents: CLEAR NULLS") log_admin("[key_name(src)] modified list's contents: CLEAR NULLS") message_admins("[key_name_admin(src)] modified list's contents: CLEAR NULLS") return TRUE @@ -1308,7 +1308,7 @@ return TRUE L.len = value["value"] - log_to_dd("### ListVarEdit by [src]: /list len: [L.len]") + log_world("### ListVarEdit by [src]: /list len: [L.len]") log_admin("[key_name(src)] modified list's len: [L.len]") message_admins("[key_name_admin(src)] modified list's len: [L.len]") return TRUE @@ -1320,7 +1320,7 @@ return TRUE shuffle_inplace(L) - log_to_dd("### ListVarEdit by [src]: /list contents: SHUFFLE") + log_world("### ListVarEdit by [src]: /list contents: SHUFFLE") log_admin("[key_name(src)] modified list's contents: SHUFFLE") message_admins("[key_name_admin(src)] modified list's contents: SHUFFLE") return TRUE diff --git a/code/datums/mind.dm b/code/datums/mind.dm index 970d7c5cb95..79f6e9193d6 100644 --- a/code/datums/mind.dm +++ b/code/datums/mind.dm @@ -1537,7 +1537,7 @@ jumpsuit.color = team_color H.update_inv_w_uniform(0,0) - add_logs(missionary, current, "converted", addition = "for [convert_duration/600] minutes") + add_attack_logs(missionary, current, "Converted to a zealot for [convert_duration/600] minutes") addtimer(src, "remove_zealot", convert_duration, FALSE, jumpsuit) //deconverts after the timer expires return 1 @@ -1546,7 +1546,7 @@ if(!zealot_master) //if they aren't a zealot, we can't remove their zealot status, obviously. don't bother with the rest so we don't confuse them with the messages return ticker.mode.remove_traitor_mind(src) - add_logs(zealot_master, current, "lost control of", addition = "as their zealot master") + add_attack_logs(zealot_master, current, "Lost control of zealot") zealot_master = null if(jumpsuit) diff --git a/code/datums/spell.dm b/code/datums/spell.dm index 7afdc1b91d9..e44c331e556 100644 --- a/code/datums/spell.dm +++ b/code/datums/spell.dm @@ -218,7 +218,7 @@ var/list/spells = typesof(/obj/effect/proc_holder/spell) //needed for the badmin before_cast(targets) invocation() if(user && user.ckey) - user.create_attack_log("[user.real_name] ([user.ckey]) cast the spell [name].") + user.create_attack_log("[key_name(user)] cast the spell [name].") spawn(0) if(charge_type == "recharge" && recharge) start_recharge() diff --git a/code/datums/spells/summonitem.dm b/code/datums/spells/summonitem.dm index 7524e7f31d6..e99a9356312 100644 --- a/code/datums/spells/summonitem.dm +++ b/code/datums/spells/summonitem.dm @@ -76,7 +76,7 @@ var/obj/item/brain/B = new /obj/item/brain(target.loc) B.transfer_identity(C) C.death() - add_logs(target, C, "magically debrained", addition="INTENT: [uppertext(target.a_intent)]")*/ + add_attack_logs(target, C, "Magically debrained INTENT: [uppertext(target.a_intent)]")*/ if(C.stomach_contents && item_to_retrive in C.stomach_contents) C.stomach_contents -= item_to_retrive for(var/X in C.bodyparts) diff --git a/code/defines/procs/admin.dm b/code/defines/procs/admin.dm index 2bc6b59e1d0..ceb6df18dcb 100644 --- a/code/defines/procs/admin.dm +++ b/code/defines/procs/admin.dm @@ -1,9 +1,14 @@ -/proc/key_name(var/whom, var/include_link = null, var/include_name = 1, var/type = null) +// Always return "Something/(Something)", even if it's an error message. +/proc/key_name(whom, include_link = FALSE, type = null) + if(include_link != FALSE && include_link != TRUE) + log_runtime(EXCEPTION("Key_name was called with an incorrect include_link [include_link]")) + var/mob/M var/client/C var/key - if(!whom) return "*null*" + if(!whom) + return "INVALID/(INVALID)" if(istype(whom, /client)) C = whom M = C.mob @@ -12,21 +17,29 @@ M = whom C = M.client key = M.key + else if(istype(whom, /datum/mind)) + var/datum/mind/D = whom + key = D.key + M = D.current + if(D.current) + C = D.current.client else if(istype(whom, /datum)) var/datum/D = whom - return "*invalid:[D.type]*" + return "INVALID/([D.type])" + else if(istext(whom)) + return "AUTOMATED/([whom])" else - return "*invalid*" + return "INVALID/(INVALID)" . = "" if(key) - if(C && C.holder && C.holder.fakekey && !include_name) + if(C && C.holder && C.holder.fakekey) if(include_link) . += "" . += "Administrator" else - if(include_link) + if(include_link && C) . += "" . += key @@ -34,23 +47,26 @@ if(C) . += "" else . += " (DC)" else - . += "*no key*" + . += "INVALID" - if(include_name && M) + var/name = "INVALID" + if(M) if(M.real_name) - . += "/([M.real_name])" + name = M.real_name else if(M.name) - . += "/([M.name])" + name = M.name + + . += "/([name])" return . -/proc/key_name_admin(var/whom, var/include_name = 1) - var/message = "[key_name(whom, 1, include_name)](?)[isAntag(whom) ? "(A)" : ""][isLivingSSD(whom) ? "(SSD!)" : ""] ([admin_jump_link(whom)])" +/proc/key_name_admin(whom) + var/message = "[key_name(whom, 1)](?)[isAntag(whom) ? "(A)" : ""][isLivingSSD(whom) ? "(SSD!)" : ""] ([admin_jump_link(whom)])" return message -/proc/key_name_mentor(var/whom, var/include_name = 1) +/proc/key_name_mentor(whom) // Same as key_name_admin, but does not include (?) or (A) for antags. - var/message = "[key_name(whom, 1, include_name)] [isLivingSSD(whom) ? "(SSD!)" : ""] ([admin_jump_link(whom)])" + var/message = "[key_name(whom, 1)] [isLivingSSD(whom) ? "(SSD!)" : ""] ([admin_jump_link(whom)])" return message diff --git a/code/defines/procs/announce.dm b/code/defines/procs/announce.dm index 5b9f85bc95c..660237350d3 100644 --- a/code/defines/procs/announce.dm +++ b/code/defines/procs/announce.dm @@ -169,7 +169,7 @@ /datum/announcement/proc/Log(message as text, message_title as text) if(log) - log_say("[key_name(usr)] has made \a [announcement_type]: [message_title] - [message] - [announcer]") + log_game("[key_name(usr)] has made \a [announcement_type]: [message_title] - [message] - [announcer]") message_admins("[key_name_admin(usr)] has made \a [announcement_type].", 1) /proc/GetNameAndAssignmentFromId(var/obj/item/card/id/I) diff --git a/code/game/dna/genes/goon_powers.dm b/code/game/dna/genes/goon_powers.dm index 1bca3ab3edc..6fbc30883ca 100644 --- a/code/game/dna/genes/goon_powers.dm +++ b/code/game/dna/genes/goon_powers.dm @@ -166,13 +166,11 @@ if(H.internal) H.visible_message("[user] sprays a cloud of fine ice crystals, engulfing [H]!", "[user] sprays a cloud of fine ice crystals over your [H.head]'s visor.") - log_admin("[key_name(user)] has used cryokinesis on [key_name(C)] while wearing internals and a suit") - msg_admin_attack("[key_name_admin(user)] has cast cryokinesis on [key_name_admin(C)]") + add_attack_logs(user, C, "Cryokinesis") else H.visible_message("[user] sprays a cloud of fine ice crystals engulfing, [H]!", "[user] sprays a cloud of fine ice crystals cover your [H.head]'s visor and make it into your air vents!.") - log_admin("[key_name(user)] has used cryokinesis on [key_name(C)]") - msg_admin_attack("[key_name_admin(user)] has cast cryokinesis on [key_name_admin(C)]") + add_attack_logs(user, C, "Cryokinesis") H.bodytemperature = max(0, H.bodytemperature - 50) H.adjustFireLoss(5) if(!handle_suit) @@ -181,8 +179,8 @@ C.ExtinguishMob() C.visible_message("[user] sprays a cloud of fine ice crystals, engulfing [C]!") - log_admin("[key_name(user)] has used cryokinesis on [key_name(C)] without internals or a suit") - msg_admin_attack("[key_name_admin(user)] has cast cryokinesis on [key_name_admin(C)]") + log_attack(user, C, "Used cryokinesis on a victim without internals or a suit") + msg_admin_attack("[key_name_admin(user)] has cast cryokinesis on [key_name_admin(C)] (NO SUIT)") //playsound(user.loc, 'bamf.ogg', 50, 0) diff --git a/code/game/dna/genes/vg_powers.dm b/code/game/dna/genes/vg_powers.dm index 43a4a07955a..bfd75f486e0 100644 --- a/code/game/dna/genes/vg_powers.dm +++ b/code/game/dna/genes/vg_powers.dm @@ -233,7 +233,7 @@ say = pencode_to_html(say, usr, format = 0, fields = 0) for(var/mob/living/target in targets) - log_say("Project Mind: [key_name(user)]->[key_name(target)]: [say]") + log_say("(TPATH to [key_name(target)]) [say]", user) if(REMOTE_TALK in target.mutations) target.show_message("You hear [user.real_name]'s voice: [say]") else diff --git a/code/game/gamemodes/blob/blob.dm b/code/game/gamemodes/blob/blob.dm index f36e763a4a0..0bcd942b7a0 100644 --- a/code/game/gamemodes/blob/blob.dm +++ b/code/game/gamemodes/blob/blob.dm @@ -44,7 +44,7 @@ var/list/blob_nodes = list() infected_crew += blob blob.special_role = SPECIAL_ROLE_BLOB blob.restricted_roles = restricted_jobs - log_game("[blob.key] (ckey) has been selected as a Blob") + log_game("[key_name(blob)] has been selected as a Blob") possible_blobs -= blob if(!infected_crew.len) @@ -66,7 +66,7 @@ var/list/blob_nodes = list() return 0 infected_crew += blobmind blobmind.special_role = SPECIAL_ROLE_BLOB - log_game("[blob.key] (ckey) has been selected as a Blob") + log_game("[key_name(blob)] has been selected as a Blob") greet_blob(blobmind) to_chat(blob, "You feel very tired and bloated! You don't have long before you burst!") spawn(600) diff --git a/code/game/gamemodes/blob/overmind.dm b/code/game/gamemodes/blob/overmind.dm index 2af2a53a939..5da84fbc460 100644 --- a/code/game/gamemodes/blob/overmind.dm +++ b/code/game/gamemodes/blob/overmind.dm @@ -88,7 +88,7 @@ blob_talk(message) /mob/camera/blob/proc/blob_talk(message) - log_say("[key_name(src)] : [message]") + log_say("(BLOB) [message]", src) message = trim(copytext(sanitize(message), 1, MAX_MESSAGE_LEN)) diff --git a/code/game/gamemodes/changeling/powers/tiny_prick.dm b/code/game/gamemodes/changeling/powers/tiny_prick.dm index e972af4ce23..c344897c624 100644 --- a/code/game/gamemodes/changeling/powers/tiny_prick.dm +++ b/code/game/gamemodes/changeling/powers/tiny_prick.dm @@ -57,7 +57,7 @@ to_chat(user, "We stealthily sting [target.name].") if(target.mind && target.mind.changeling) to_chat(target, "You feel a tiny prick.") - add_logs(user, target, "unsuccessfully stung") + add_attack_logs(user, target, "Unsuccessful sting (changeling)") return 1 @@ -100,7 +100,7 @@ return TRUE /obj/effect/proc_holder/changeling/sting/transformation/sting_action(var/mob/user, var/mob/target) - add_logs(user, target, "stung", object="transformation sting", addition=" new identity is [selected_dna.real_name]") + add_attack_logs(user, target, "Transformation sting (changeling) (new identity is [selected_dna.real_name])") var/datum/dna/NewDNA = selected_dna if(issmall(target)) to_chat(user, "Our genes cry out as we sting [target.name]!") @@ -135,7 +135,7 @@ obj/effect/proc_holder/changeling/sting/extract_dna return user.mind.changeling.can_absorb_dna(user, target) /obj/effect/proc_holder/changeling/sting/extract_dna/sting_action(var/mob/user, var/mob/living/carbon/human/target) - add_logs(user, target, "stung", object="extraction sting") + add_attack_logs(user, target, "Extraction sting (changeling)") if(!(user.mind.changeling.has_dna(target.dna))) user.mind.changeling.absorb_dna(target, user) feedback_add_details("changeling_powers","ED") @@ -150,7 +150,7 @@ obj/effect/proc_holder/changeling/sting/mute dna_cost = 2 /obj/effect/proc_holder/changeling/sting/mute/sting_action(var/mob/user, var/mob/living/carbon/target) - add_logs(user, target, "stung", object="mute sting") + add_attack_logs(user, target, "Mute sting (changeling)") target.AdjustSilence(30) feedback_add_details("changeling_powers","MS") return 1 @@ -164,7 +164,7 @@ obj/effect/proc_holder/changeling/sting/blind dna_cost = 1 /obj/effect/proc_holder/changeling/sting/blind/sting_action(var/mob/living/user, var/mob/living/target) - add_logs(user, target, "stung", object="blind sting") + add_attack_logs(user, target, "Blind sting (changeling)") to_chat(target, "Your eyes burn horrifically!") target.BecomeNearsighted() target.EyeBlind(20) @@ -181,7 +181,7 @@ obj/effect/proc_holder/changeling/sting/LSD dna_cost = 1 /obj/effect/proc_holder/changeling/sting/LSD/sting_action(var/mob/user, var/mob/living/carbon/target) - add_logs(user, target, "stung", object="LSD sting") + add_attack_logs(user, target, "LSD sting (changeling)") spawn(rand(300,600)) if(target) target.Hallucinate(400) @@ -197,7 +197,7 @@ obj/effect/proc_holder/changeling/sting/cryo //Enable when mob cooling is fixed dna_cost = 2 /obj/effect/proc_holder/changeling/sting/cryo/sting_action(var/mob/user, var/mob/target) - add_logs(user, target, "stung", object="cryo sting") + add_attack_logs(user, target, "Cryo sting (changeling)") if(target.reagents) target.reagents.add_reagent("frostoil", 30) target.reagents.add_reagent("ice", 30) diff --git a/code/game/gamemodes/cult/cult_comms.dm b/code/game/gamemodes/cult/cult_comms.dm index bfe25eba5d5..c854693c86e 100644 --- a/code/game/gamemodes/cult/cult_comms.dm +++ b/code/game/gamemodes/cult/cult_comms.dm @@ -36,4 +36,4 @@ else if(M in dead_mob_list) to_chat(M, " (F) [my_message] ") - log_say("[user.real_name]/[user.key] : [message]") \ No newline at end of file + log_say("(CULT) [message]") \ No newline at end of file diff --git a/code/game/gamemodes/cult/ritual.dm b/code/game/gamemodes/cult/ritual.dm index 45d187965da..19f9f57e9e7 100644 --- a/code/game/gamemodes/cult/ritual.dm +++ b/code/game/gamemodes/cult/ritual.dm @@ -63,7 +63,7 @@ var/holy2unholy = M.reagents.get_reagent_amount("holywater") M.reagents.del_reagent("holywater") M.reagents.add_reagent("unholywater",holy2unholy) - add_logs(user, M, "smacked", src, " removing the holy water from them") + add_attack_logs(user, M, "Hit with [src], removing the holy water from them") return M.take_organ_damage(0, 15) //Used to be a random between 5 and 20 playsound(M, 'sound/weapons/sear.ogg', 50, 1) @@ -71,7 +71,7 @@ "[user] strikes you with the tome, searing your flesh!") flick("tome_attack", src) user.do_attack_animation(M) - add_logs(user, M, "smacked", src) + add_attack_logs(user, M, "Hit with [src]") /obj/item/tome/attack_self(mob/user) if(!iscultist(user)) diff --git a/code/game/gamemodes/cult/runes.dm b/code/game/gamemodes/cult/runes.dm index 4f8cf56254e..3713ebab6c7 100644 --- a/code/game/gamemodes/cult/runes.dm +++ b/code/game/gamemodes/cult/runes.dm @@ -536,15 +536,15 @@ var/list/teleport_runes = list() /obj/effect/rune/narsie/attackby(obj/I, mob/user, params) //Since the narsie rune takes a long time to make, add logging to removal. if((istype(I, /obj/item/tome) && iscultist(user))) - user.visible_message("[user.name] begins erasing the [src]...", "You begin erasing the [src]...") + user.visible_message("[user] begins erasing the [src]...", "You begin erasing the [src]...") if(do_after(user, 50, target = src)) //Prevents accidental erasures. - log_game("Summon Narsie rune erased by [user.mind.key] (ckey) with a tome") + log_game("Summon Narsie rune erased by [key_name(user)] with a tome") message_admins("[key_name_admin(user)] erased a Narsie rune with a tome") ..() return else if(istype(I, /obj/item/nullrod)) //Begone foul magiks. You cannot hinder me. - log_game("Summon Narsie rune erased by [user.mind.key] (ckey) using a null rod") + log_game("Summon Narsie rune erased by [key_name(user)] using a null rod") message_admins("[key_name_admin(user)] erased a Narsie rune with a null rod") ..() return @@ -576,13 +576,13 @@ var/list/teleport_runes = list() if((istype(I, /obj/item/tome) && iscultist(user))) user.visible_message("[user.name] begins erasing the [src]...", "You begin erasing the [src]...") if(do_after(user, 50, target = src)) //Prevents accidental erasures. - log_game("Summon demon rune erased by [user.mind.key] (ckey) with a tome") + log_game("Summon demon rune erased by [key_name(user)] with a tome") message_admins("[key_name_admin(user)] erased a demon rune with a tome") ..() return else if(istype(I, /obj/item/nullrod)) //Begone foul magiks. You cannot hinder me. - log_game("Summon demon rune erased by [user.mind.key] (ckey) using a null rod") + log_game("Summon demon rune erased by [key_name(user)] using a null rod") message_admins("[key_name_admin(user)] erased a demon rune with a null rod") ..() return @@ -594,12 +594,12 @@ var/list/teleport_runes = list() var/mob/living/user = invokers[1] var/datum/game_mode/cult/cult_mode = ticker.mode if(!(CULT_SLAUGHTER in cult_mode.objectives)) - message_admins("[usr.real_name]([user.ckey]) tried to summon demons when the objective was wrong") + message_admins("[key_name_admin(user)] tried to summon demons when the objective was wrong") burn_invokers(invokers) log_game("Summon Demons rune failed - improper objective") return if(!is_station_level(user.z)) - message_admins("[user.real_name]([user.ckey]) tried to summon demons off station") + message_admins("[key_name_admin(user)] tried to summon demons off station") burn_invokers(invokers) log_game("Summon demons rune failed - off station Z level") return diff --git a/code/game/gamemodes/cult/talisman.dm b/code/game/gamemodes/cult/talisman.dm index 4f0cf071eaa..910d73b3261 100644 --- a/code/game/gamemodes/cult/talisman.dm +++ b/code/game/gamemodes/cult/talisman.dm @@ -249,7 +249,7 @@ target.visible_message("[target]'s holy weapon absorbs the talisman's light!", \ "Your holy weapon absorbs the blinding light!") else - add_logs(user, target, "stunned", addition="with a talisman") + add_attack_logs(user, target, "Stunned with a talisman") target.Weaken(10) target.Stun(10) target.flash_eyes(1,1) @@ -393,7 +393,7 @@ C.handcuffed = new /obj/item/restraints/handcuffs/energy/cult/used(C) C.update_handcuffed() to_chat(user, "You shackle [C].") - add_logs(user, C, "handcuffed") + add_attack_logs(user, C, "Handcuffed (shackle talisman)") uses-- else to_chat(user, "[C] is already bound.") diff --git a/code/game/gamemodes/miniantags/abduction/abduction.dm b/code/game/gamemodes/miniantags/abduction/abduction.dm index 9c83493e187..dc38849c445 100644 --- a/code/game/gamemodes/miniantags/abduction/abduction.dm +++ b/code/game/gamemodes/miniantags/abduction/abduction.dm @@ -76,11 +76,11 @@ scientist.assigned_role = "MODE" scientist.special_role = SPECIAL_ROLE_ABDUCTOR_SCIENTIST - log_game("[scientist.key] (ckey) has been selected as an abductor team [team_number] scientist.") + log_game("[key_name(scientist)] has been selected as an abductor team [team_number] scientist.") agent.assigned_role = "MODE" agent.special_role = SPECIAL_ROLE_ABDUCTOR_AGENT - log_game("[agent.key] (ckey) has been selected as an abductor team [team_number] agent.") + log_game("[key_name(agent)] has been selected as an abductor team [team_number] agent.") abductors |= agent abductors |= scientist diff --git a/code/game/gamemodes/miniantags/abduction/abduction_gear.dm b/code/game/gamemodes/miniantags/abduction/abduction_gear.dm index ac0acc56c1c..4500647e362 100644 --- a/code/game/gamemodes/miniantags/abduction/abduction_gear.dm +++ b/code/game/gamemodes/miniantags/abduction/abduction_gear.dm @@ -391,7 +391,7 @@ Congratulations! You are now trained for invasive xenobiology research!"} var/mob/living/carbon/human/H = L H.forcesay(hit_appends) - add_logs(user, L, "stunned") + add_attack_logs(user, L, "Stunned with [src]") /obj/item/abductor_baton/proc/SleepAttack(mob/living/L,mob/living/user) if(L.stunned || L.sleeping) @@ -399,7 +399,7 @@ Congratulations! You are now trained for invasive xenobiology research!"} "You suddenly feel very drowsy!") playsound(loc, 'sound/weapons/Egloves.ogg', 50, 1, -1) L.Sleeping(60) - add_logs(user, L, "put to sleep") + add_attack_logs(user, L, "Put to sleep with [src]") else L.AdjustDrowsy(1) to_chat(user, "Sleep inducement works fully only on stunned specimens! ") @@ -419,7 +419,7 @@ Congratulations! You are now trained for invasive xenobiology research!"} C.handcuffed = new /obj/item/restraints/handcuffs/energy/used(C) C.update_handcuffed() to_chat(user, "You handcuff [C].") - add_logs(user, C, "handcuffed") + add_attack_logs(user, C, "Handcuffed ([src])") else to_chat(user, "You fail to handcuff [C].") diff --git a/code/game/gamemodes/miniantags/borer/borer.dm b/code/game/gamemodes/miniantags/borer/borer.dm index 5851023fce9..e9a830e7ed6 100644 --- a/code/game/gamemodes/miniantags/borer/borer.dm +++ b/code/game/gamemodes/miniantags/borer/borer.dm @@ -15,7 +15,7 @@ message = trim(sanitize(copytext(message, 1, MAX_MESSAGE_LEN))) if(!message) return - log_say("[key_name(src)] : [message]") + log_say(message, src) if(stat == DEAD) return say_dead(message) var/mob/living/simple_animal/borer/B = loc @@ -179,7 +179,7 @@ var/say_string = (docile) ? "slurs" :"states" if(host) to_chat(host, "[truename] [say_string]: [input]") - log_say("Borer Communication: [key_name(src)] -> [key_name(host)] : [input]") + log_say("(BORER to [key_name(host)]) [input]", src) for(var/M in dead_mob_list) if(isobserver(M)) to_chat(M, "Borer Communication from [truename] ([ghost_follow_link(src, ghost=M)]): [input]") @@ -214,7 +214,7 @@ return to_chat(B, "[src] says: [input]") - log_say("Borer Communication: [key_name(src)] -> [key_name(B)] : [input]") + log_say("(BORER to [key_name(B)]) [input]", src) for(var/M in dead_mob_list) if(isobserver(M)) @@ -236,7 +236,7 @@ return to_chat(CB, "[B.truename] says: [input]") - log_say("Borer Communication: [key_name(B)] -> [key_name(CB)] : [input]") + log_say("(BORER to [key_name(CB)]) [input]", B) for(var/M in dead_mob_list) if(isobserver(M)) @@ -436,7 +436,7 @@ to_chat(src, "You squirt a measure of [R.name] from your reservoirs into [host]'s bloodstream.") host.reagents.add_reagent(C.chemname, C.quantity) chemicals -= C.chemuse - log_game("[src]/([src.ckey]) has injected [R.name] into their host [host]/([host.ckey])") + log_game("[key_name(src)] has injected [R.name] into their host [host]/([host.ckey])") // This is used because we use a static set of datums to determine what chems are available, // instead of a table or something. Thus, when we instance it, we can safely delete it @@ -625,8 +625,7 @@ to_chat(src, "You plunge your probosci deep into the cortex of the host brain, interfacing directly with their nervous system.") to_chat(host, "You feel a strange shifting sensation behind your eyes as an alien consciousness displaces yours.") var/borer_key = src.key - host.create_attack_log("[key_name(src)] has assumed control of [key_name(host)]") - msg_admin_attack("[key_name_admin(src)] has assumed control of [key_name_admin(host)]") + add_attack_logs(src, host, "Assumed control of (borer)") // host -> brain var/h2b_id = host.computer_id var/h2b_ip= host.lastKnownIP @@ -763,8 +762,7 @@ host.med_hud_set_status() if(host_brain) - host.create_attack_log("[host_brain.name] ([host_brain.ckey]) has taken control back from [name] ([host.ckey])") - msg_admin_attack("[host_brain.name] ([host_brain.ckey]) has taken control back from [name] ([host.ckey]) (JMP)") + add_attack_logs(host, src, "Took control back (borer)") // host -> self var/h2s_id = host.computer_id var/h2s_ip= host.lastKnownIP diff --git a/code/game/gamemodes/miniantags/guardian/guardian.dm b/code/game/gamemodes/miniantags/guardian/guardian.dm index 3b2f106d02b..822bfc9ce29 100644 --- a/code/game/gamemodes/miniantags/guardian/guardian.dm +++ b/code/game/gamemodes/miniantags/guardian/guardian.dm @@ -165,7 +165,7 @@ for(var/mob/M in mob_list) if(M == summoner) to_chat(M, "[src]: [input]") - log_say("Guardian Communication: [key_name(src)] -> [key_name(M)] : [input]") + log_say("(GUARDIAN to [key_name(M)]) [input]", src) else if(M in dead_mob_list) to_chat(M, "Guardian Communication from [src] ([ghost_follow_link(src, ghost=M)]): [input]") to_chat(src, "[src]: [input]") @@ -186,7 +186,7 @@ var/mob/living/simple_animal/hostile/guardian/G = M if(G.summoner == src) to_chat(G, "[src]: [input]") - log_say("Guardian Communication: [key_name(src)] -> [key_name(G)] : [input]") + log_say("(GUARDIAN to [key_name(G)]) [input]", src) else if(M in dead_mob_list) to_chat(M, "Guardian Communication from [src] ([ghost_follow_link(src, ghost=M)]): [input]") diff --git a/code/game/gamemodes/miniantags/revenant/revenant.dm b/code/game/gamemodes/miniantags/revenant/revenant.dm index 12a5c988106..49380c57863 100644 --- a/code/game/gamemodes/miniantags/revenant/revenant.dm +++ b/code/game/gamemodes/miniantags/revenant/revenant.dm @@ -96,7 +96,7 @@ /mob/living/simple_animal/revenant/say(message) if(!message) return - log_say("[key_name(src)] : [message]") + log_say(message, src) var/rendered = "[src] says, \"[message]\"" for(var/mob/M in mob_list) if(istype(M, /mob/living/simple_animal/revenant)) diff --git a/code/game/gamemodes/miniantags/revenant/revenant_abilities.dm b/code/game/gamemodes/miniantags/revenant/revenant_abilities.dm index f982d335fde..32d51b579c4 100644 --- a/code/game/gamemodes/miniantags/revenant/revenant_abilities.dm +++ b/code/game/gamemodes/miniantags/revenant/revenant_abilities.dm @@ -132,7 +132,7 @@ if(!msg) charge_counter = charge_max return - log_say("RevenantTransmit: [key_name(user)]->[key_name(M)] : [msg]") + log_say("(REVENANT to [key_name(M)]) [msg]", user) to_chat(user, "You transmit to [M]: [msg]") to_chat(M, "An alien voice resonates from all around... [msg]") diff --git a/code/game/gamemodes/miniantags/slaughter/slaughter.dm b/code/game/gamemodes/miniantags/slaughter/slaughter.dm index 3c0523daa3c..42827d27f59 100644 --- a/code/game/gamemodes/miniantags/slaughter/slaughter.dm +++ b/code/game/gamemodes/miniantags/slaughter/slaughter.dm @@ -217,7 +217,7 @@ var/msg = stripped_input(usr, "What do you wish to tell [choice]?", null, "") if(!(msg)) return - log_say("Slaughter Demon Transmit: [key_name(usr)]->[key_name(choice)]: [msg]") + log_say("(SLAUGHTER to [key_name(choice)]) [msg]", usr) to_chat(usr, "You whisper to [choice]: [msg]") to_chat(choice, "Suddenly a strange, demonic voice resonates in your head... [msg]") for(var/mob/dead/observer/G in player_list) diff --git a/code/game/gamemodes/revolution/revolution.dm b/code/game/gamemodes/revolution/revolution.dm index 556b7f50e5b..25f70144dec 100644 --- a/code/game/gamemodes/revolution/revolution.dm +++ b/code/game/gamemodes/revolution/revolution.dm @@ -68,7 +68,7 @@ update_rev_icons_removed(trotsky) for(var/datum/mind/rev_mind in head_revolutionaries) - log_game("[rev_mind.key] (ckey) has been selected as a head rev") + log_game("[key_name(rev_mind)] has been selected as a head rev") for(var/datum/mind/head_mind in heads) mark_for_death(rev_mind, head_mind) @@ -195,7 +195,7 @@ var/datum/mind/stalin = pick(promotable_revs) revolutionaries -= stalin head_revolutionaries += stalin - log_game("[stalin.key] (ckey) has been promoted to a head rev") + log_game("[key_name(stalin)] has been promoted to a head rev") equip_revolutionary(stalin.current) forge_revolutionary_objectives(stalin) greet_revolutionary(stalin) diff --git a/code/game/gamemodes/shadowling/shadowling.dm b/code/game/gamemodes/shadowling/shadowling.dm index 76129be2d71..ed8603360fe 100644 --- a/code/game/gamemodes/shadowling/shadowling.dm +++ b/code/game/gamemodes/shadowling/shadowling.dm @@ -107,7 +107,7 @@ Made by Xhuis /datum/game_mode/shadowling/post_setup() for(var/datum/mind/shadow in shadows) - log_game("[shadow.key] (ckey) has been selected as a Shadowling.") + log_game("[key_name(shadow)] has been selected as a Shadowling.") sleep(10) to_chat(shadow.current, "
") to_chat(shadow.current, "You are a shadowling!") diff --git a/code/game/gamemodes/vampire/vampire.dm b/code/game/gamemodes/vampire/vampire.dm index 781d417929f..c2431f17318 100644 --- a/code/game/gamemodes/vampire/vampire.dm +++ b/code/game/gamemodes/vampire/vampire.dm @@ -279,9 +279,7 @@ You are weak to holy things and starlight. Don't go into space and avoid the Cha to_chat(owner, "[owner.wear_mask] prevents you from biting [H]!") draining = null return - owner.create_attack_log("Bit [H] ([H.ckey]) in the neck and draining their blood") - H.create_attack_log("Has been bit in the neck by [owner] ([owner.ckey])") - log_attack("[owner] ([owner.ckey]) bit [H] ([H.ckey]) in the neck") + add_attack_logs(owner, H, "vampirebit & is draining their blood.", FALSE) owner.visible_message("[owner] grabs [H]'s neck harshly and sinks in their fangs!", "You sink your fangs into [H] and begin to drain their blood.", "You hear a soft puncture and a wet sucking noise.") if(!iscarbon(owner)) H.LAssailant = null diff --git a/code/game/gamemodes/vampire/vampire_powers.dm b/code/game/gamemodes/vampire/vampire_powers.dm index 8d0aa8de772..e9a249d8412 100644 --- a/code/game/gamemodes/vampire/vampire_powers.dm +++ b/code/game/gamemodes/vampire/vampire_powers.dm @@ -347,7 +347,7 @@ H.mind.special_role = SPECIAL_ROLE_VAMPIRE_THRALL to_chat(H, "You have been Enthralled by [user]. Follow their every command.") to_chat(user, "You have successfully Enthralled [H]. If they refuse to do as you say just adminhelp.") - add_logs(user, H, "vampire-thralled") + add_attack_logs(user, H, "Vampire-thralled") /obj/effect/proc_holder/spell/vampire/self/cloak diff --git a/code/game/gamemodes/wizard/soulstone.dm b/code/game/gamemodes/wizard/soulstone.dm index b2d18a9bc30..22cb882af5c 100644 --- a/code/game/gamemodes/wizard/soulstone.dm +++ b/code/game/gamemodes/wizard/soulstone.dm @@ -117,10 +117,7 @@ if(spent)//checking one more time against shenanigans return - M.create_attack_log("Has had their soul captured with [src.name] by [key_name(user)]") - user.create_attack_log("Used the [src.name] to capture the soul of [key_name(M)]") - log_attack("[key_name(user)] used the [src.name] to capture the soul of [key_name(M)]") - + add_attack_logs(user, M, "Stolestone'd with [name]") transfer_soul("VICTIM", M, user) return diff --git a/code/game/gamemodes/wizard/spellbook.dm b/code/game/gamemodes/wizard/spellbook.dm index cbe9a9f0989..fdd1cc9f40a 100644 --- a/code/game/gamemodes/wizard/spellbook.dm +++ b/code/game/gamemodes/wizard/spellbook.dm @@ -703,7 +703,7 @@ else user.mind.AddSpell(S) to_chat(user, "you rapidly read through the arcane book. Suddenly you realize you understand [spellname]!") - user.create_attack_log("[user.real_name] ([user.ckey]) learned the spell [spellname] ([S]).") + user.create_attack_log("[key_name(user)] learned the spell [spellname] ([S]).") onlearned(user) diff --git a/code/game/gamemodes/wizard/wizard.dm b/code/game/gamemodes/wizard/wizard.dm index 9eb6bf97dd2..44b1bd1997d 100644 --- a/code/game/gamemodes/wizard/wizard.dm +++ b/code/game/gamemodes/wizard/wizard.dm @@ -44,7 +44,7 @@ /datum/game_mode/wizard/post_setup() for(var/datum/mind/wizard in wizards) - log_game("[wizard.key] (ckey) has been selected as a Wizard") + log_game("[key_name(wizard)] has been selected as a Wizard") forge_wizard_objectives(wizard) //learn_basic_spells(wizard.current) equip_wizard(wizard.current) diff --git a/code/game/jobs/whitelist.dm b/code/game/jobs/whitelist.dm index 049903b475e..a09eaed6c02 100644 --- a/code/game/jobs/whitelist.dm +++ b/code/game/jobs/whitelist.dm @@ -56,7 +56,7 @@ var/list/whitelist = list() /proc/load_alienwhitelist() var/text = file2text("config/alienwhitelist.txt") if(!text) - diary << "Failed to load config/alienwhitelist.txt\n" + log_config("Failed to load config/alienwhitelist.txt\n") else alien_whitelist = splittext(text, "\n") diff --git a/code/game/machinery/atmoalter/canister.dm b/code/game/machinery/atmoalter/canister.dm index 858ac8cf303..9324262bb30 100644 --- a/code/game/machinery/atmoalter/canister.dm +++ b/code/game/machinery/atmoalter/canister.dm @@ -437,14 +437,14 @@ update_flag var/logmsg if(valve_open) if(holding) - logmsg = "Valve was closed by [usr] ([usr.ckey]), stopping the transfer into the [holding]
" + logmsg = "Valve was closed by [key_name(usr)], stopping the transfer into the [holding]
" else - logmsg = "Valve was closed by [usr] ([usr.ckey]), stopping the transfer into the air
" + logmsg = "Valve was closed by [key_name(usr)], stopping the transfer into the air
" else if(holding) - logmsg = "Valve was opened by [usr] ([usr.ckey]), starting the transfer into the [holding]
" + logmsg = "Valve was opened by [key_name(usr)], starting the transfer into the [holding]
" else - logmsg = "Valve was opened by [usr] ([usr.ckey]), starting the transfer into the air
" + logmsg = "Valve was opened by [key_name(usr)], starting the transfer into the air
" if(air_contents.toxins > 0) message_admins("[key_name_admin(usr)] opened a canister that contains plasma in [get_area(src)]! (JMP)") log_admin("[key_name(usr)] opened a canister that contains plasma at [get_area(src)]: [x], [y], [z]") @@ -460,7 +460,7 @@ update_flag if(holding) if(valve_open) valve_open = 0 - release_log += "Valve was closed by [usr] ([usr.ckey]), stopping the transfer into the [holding]
" + release_log += "Valve was closed by [key_name(usr)], stopping the transfer into the [holding]
" holding.loc = loc holding = null diff --git a/code/game/machinery/computer/communications.dm b/code/game/machinery/computer/communications.dm index 21acc1252d2..8e2783fe0ae 100644 --- a/code/game/machinery/computer/communications.dm +++ b/code/game/machinery/computer/communications.dm @@ -237,7 +237,7 @@ return Nuke_request(input, usr) to_chat(usr, "Request sent.") - log_say("[key_name(usr)] has requested the nuclear codes from Centcomm") + log_game("[key_name(usr)] has requested the nuclear codes from Centcomm") priority_announcement.Announce("The codes for the on-station nuclear self-destruct have been requested by [usr]. Confirmation or denial of this request will be sent shortly.", "Nuclear Self Destruct Codes Requested",'sound/AI/commandreport.ogg') centcomm_message_cooldown = 1 spawn(6000)//10 minute cooldown @@ -257,7 +257,7 @@ Centcomm_announce(input, usr) print_centcom_report(input, station_time_timestamp() + " Captain's Message") to_chat(usr, "Message transmitted.") - log_say("[key_name(usr)] has made a Centcomm announcement: [input]") + log_game("[key_name(usr)] has made a Centcomm announcement: [input]") centcomm_message_cooldown = 1 spawn(6000)//10 minute cooldown centcomm_message_cooldown = 0 @@ -276,7 +276,7 @@ return Syndicate_announce(input, usr) to_chat(usr, "Message transmitted.") - log_say("[key_name(usr)] has made a Syndicate announcement: [input]") + log_game("[key_name(usr)] has made a Syndicate announcement: [input]") centcomm_message_cooldown = 1 spawn(6000)//10 minute cooldown centcomm_message_cooldown = 0 diff --git a/code/game/machinery/computer/honkputer.dm b/code/game/machinery/computer/honkputer.dm index e9b8e09799a..0d6b16d421b 100644 --- a/code/game/machinery/computer/honkputer.dm +++ b/code/game/machinery/computer/honkputer.dm @@ -53,7 +53,7 @@ return HONK_announce(input, usr) to_chat(usr, "Message transmitted.") - log_say("[key_name(usr)] has made a HONKplanet announcement: [input]") + log_game("[key_name(usr)] has made a HONKplanet announcement: [input]") message_cooldown = 1 spawn(6000)//10 minute cooldown message_cooldown = 0 diff --git a/code/game/machinery/computer/message.dm b/code/game/machinery/computer/message.dm index a4ed47099f4..8fdbc68377b 100644 --- a/code/game/machinery/computer/message.dm +++ b/code/game/machinery/computer/message.dm @@ -494,7 +494,7 @@ if(isnull(PDARec)) src.linkedServer.send_pda_message("[customrecepient.owner]", "[customsender]","[custommessage]") recipient_messenger.notify("Message from [customsender] ([customjob]), \"[custommessage]\" (Reply)") - log_pda("[usr] (PDA: [customsender]) sent \"[custommessage]\" to [customrecepient.owner]") + log_pda("(PDA: [customsender]) sent \"[custommessage]\" to [customrecepient.owner]", usr) //Sender is faking as someone who exists else src.linkedServer.send_pda_message("[customrecepient.owner]", "[PDARec.owner]","[custommessage]") @@ -504,7 +504,7 @@ recipient_messenger.conversations.Add("\ref[PDARec]") recipient_messenger.notify("Message from [PDARec.owner] ([customjob]), \"[custommessage]\" (Reply)") - log_pda("[usr] (PDA: [PDARec.owner]) sent \"[custommessage]\" to [customrecepient.owner]") + log_pda("(PDA: [PDARec.owner]) sent \"[custommessage]\" to [customrecepient.owner]", usr) //Finally.. ResetMessage() diff --git a/code/game/machinery/poolcontroller.dm b/code/game/machinery/poolcontroller.dm index 661a814c6fb..9ce963d7a03 100644 --- a/code/game/machinery/poolcontroller.dm +++ b/code/game/machinery/poolcontroller.dm @@ -100,10 +100,7 @@ if(drownee.losebreath > 20) //You've probably got bigger problems than drowning at this point, so we won't add to it until you get that under control. return - if(isLivingSSD(drownee)) - add_logs(src, drownee, "drowned", null, null, 0, 1) // Notify admins, since the person is SSD - else - add_logs(src, drownee, "drowned", null, null, 0, 0) // Do not notify admins. + add_attack_logs(src, drownee, "Drowned", isLivingSSD(drownee)) if(drownee.stat) //Mob is in critical. drownee.AdjustLoseBreath(3, bound_lower = 0, bound_upper = 20) drownee.visible_message("\The [drownee] appears to be drowning!","You're quickly drowning!") //inform them that they are fucked. diff --git a/code/game/machinery/telecomms/broadcaster.dm b/code/game/machinery/telecomms/broadcaster.dm index af013849f45..82df914f68d 100644 --- a/code/game/machinery/telecomms/broadcaster.dm +++ b/code/game/machinery/telecomms/broadcaster.dm @@ -639,6 +639,6 @@ var/message_delay = 0 // To make sure restarting the recentmessages list is kept if(do_sleep) sleep(rand(10,25)) - //log_to_dd("Level: [signal.data["level"]] - Done: [signal.data["done"]]") + //log_world("Level: [signal.data["level"]] - Done: [signal.data["done"]]") return signal diff --git a/code/game/machinery/telecomms/telecomunications.dm b/code/game/machinery/telecomms/telecomunications.dm index b3b00adc57b..05e1694b3d3 100644 --- a/code/game/machinery/telecomms/telecomunications.dm +++ b/code/game/machinery/telecomms/telecomunications.dm @@ -547,8 +547,8 @@ var/global/list/obj/machinery/telecomms/telecomms_list = list() /obj/machinery/telecomms/server/proc/admin_log(var/mob/mob) var/msg="[key_name(mob)] has compiled a script to server [src]:" - diary << msg - diary << rawcode + log_game("NTSL: [msg]") + log_game("NTSL: [rawcode]") src.investigate_log("[msg]
[rawcode]", "ntsl") if(length(rawcode)) // Let's not bother the admins for empty code. message_admins("[key_name_admin(mob)] has compiled and uploaded a NTSL script to [src.id] (JMP)") diff --git a/code/game/mecha/equipment/tools/medical_tools.dm b/code/game/mecha/equipment/tools/medical_tools.dm index 409987530a7..5f3483d2ce4 100644 --- a/code/game/mecha/equipment/tools/medical_tools.dm +++ b/code/game/mecha/equipment/tools/medical_tools.dm @@ -197,7 +197,7 @@ if(to_inject && patient.reagents.get_reagent_amount(R.id) + to_inject <= inject_amount*2) occupant_message("Injecting [patient] with [to_inject] units of [R.name].") log_message("Injecting [patient] with [to_inject] units of [R.name].") - add_logs(chassis.occupant, patient, "injected", "[name] ([R] - [to_inject] units)") + add_attack_logs(chassis.occupant, patient, "Injected with [name] containing [R], transferred [to_inject] units") SG.reagents.trans_id_to(patient,R.id,to_inject) update_equip_info() return @@ -333,12 +333,12 @@ for(var/datum/reagent/A in mechsyringe.reagents.reagent_list) R += A.id + " (" R += num2text(A.volume) + ")," + add_attack_logs(originaloccupant, M, "Shot with [src] containing [R], transferred [mechsyringe.reagents.total_volume] units") mechsyringe.icon_state = initial(mechsyringe.icon_state) mechsyringe.icon = initial(mechsyringe.icon) mechsyringe.reagents.reaction(M, INGEST) mechsyringe.reagents.trans_to(M, mechsyringe.reagents.total_volume) M.take_organ_damage(2) - add_logs(originaloccupant, M, "shot", "syringegun") break else if(mechsyringe.loc == trg) mechsyringe.icon_state = initial(mechsyringe.icon_state) diff --git a/code/game/mecha/equipment/tools/mining_tools.dm b/code/game/mecha/equipment/tools/mining_tools.dm index d89d6bd0bd4..f39dedcc772 100644 --- a/code/game/mecha/equipment/tools/mining_tools.dm +++ b/code/game/mecha/equipment/tools/mining_tools.dm @@ -86,7 +86,7 @@ /obj/item/mecha_parts/mecha_equipment/drill/proc/drill_mob(mob/living/target, mob/user, var/drill_damage=80) target.visible_message("[chassis] drills [target] with [src].", \ "[chassis] drills [target] with [src].") - add_logs(user, target, "attacked", "[name]", "(INTENT: [uppertext(user.a_intent)]) (DAMTYPE: [uppertext(damtype)])") + add_attack_logs(user, target, "DRILLED with [src] (INTENT: [uppertext(user.a_intent)]) (DAMTYPE: [uppertext(damtype)])") if(target.stat == DEAD && target.butcher_results) target.harvest(chassis) // Butcher the mob with our drill. else diff --git a/code/game/mecha/equipment/tools/other_tools.dm b/code/game/mecha/equipment/tools/other_tools.dm index 2e9c75510f4..501b41be4cb 100644 --- a/code/game/mecha/equipment/tools/other_tools.dm +++ b/code/game/mecha/equipment/tools/other_tools.dm @@ -125,7 +125,7 @@ step_away(A,target) sleep(2) var/turf/T = get_turf(target) - log_game("[chassis.occupant.ckey]([chassis.occupant]) used a Gravitational Catapult in ([T.x],[T.y],[T.z])") + log_game("[key_name(chassis.occupant)] used a Gravitational Catapult in ([T.x],[T.y],[T.z])") return 1 diff --git a/code/game/mecha/equipment/tools/work_tools.dm b/code/game/mecha/equipment/tools/work_tools.dm index c4a52416a4a..866cb7580f6 100644 --- a/code/game/mecha/equipment/tools/work_tools.dm +++ b/code/game/mecha/equipment/tools/work_tools.dm @@ -60,7 +60,7 @@ target.visible_message("[chassis] squeezes [target].", \ "[chassis] squeezes [target].",\ "You hear something crack.") - add_logs(chassis.occupant, M, "attacked", "[name]", "(INTENT: [uppertext(chassis.occupant.a_intent)]) (DAMTYE: [uppertext(damtype)])") + add_attack_logs(chassis.occupant, M, "Squeezed with [src] (INTENT: [uppertext(chassis.occupant.a_intent)]) (DAMTYE: [uppertext(damtype)])") start_cooldown() else step_away(M,chassis) diff --git a/code/game/mecha/equipment/weapons/weapons.dm b/code/game/mecha/equipment/weapons/weapons.dm index df66ea13952..1e362a91972 100644 --- a/code/game/mecha/equipment/weapons/weapons.dm +++ b/code/game/mecha/equipment/weapons/weapons.dm @@ -60,7 +60,7 @@ set_ready_state(0) log_message("Fired from [name], targeting [target].") var/turf/T = get_turf(src) - msg_admin_attack("[key_name_admin(chassis.occupant)] fired a [src] in ([T.x], [T.y], [T.z] - JMP)") + msg_admin_attack("[key_name_admin(chassis.occupant)] fired a [src] in ([T.x], [T.y], [T.z] - [ADMIN_JMP(T)])") log_game("[key_name(chassis.occupant)] fired a [src] in [T.x], [T.y], [T.z]") do_after_cooldown() return @@ -159,16 +159,13 @@ if(ismob(A)) var/mob/M = A if(istype(firer, /mob)) - M.create_attack_log("[firer]/[firer.ckey] shot [M]/[M.ckey] with a [src]") - firer.create_attack_log("[firer]/[firer.ckey] shot [M]/[M.ckey] with a [src]") - log_attack("[firer] ([firer.ckey]) shot [M] ([M.ckey]) with a [src]") + add_attack_logs(firer, M, "Mecha-shot with [src]") if(!iscarbon(firer)) M.LAssailant = null else M.LAssailant = firer else - M.create_attack_log("UNKNOWN SUBJECT (No longer exists) shot [M]/[M.ckey] with a [src]") - log_attack("UNKNOWN shot [M] ([M.ckey]) with a [src]") + add_attack_logs(null, M, "Mecha-shot with [src]") if(life <= 0) qdel(src) return @@ -239,7 +236,7 @@ chassis.use_power(energy_drain) log_message("Honked from [name]. HONK!") var/turf/T = get_turf(src) - msg_admin_attack("[key_name_admin(chassis.occupant)] used a Mecha Honker in ([T.x], [T.y], [T.z] - JMP)") + msg_admin_attack("[key_name_admin(chassis.occupant)] used a Mecha Honker in ([T.x], [T.y], [T.z] - [ADMIN_JMP(T)])") log_game("[key_name(chassis.occupant)] used a Mecha Honker in [T.x], [T.y], [T.z]") do_after_cooldown() return @@ -353,7 +350,7 @@ projectiles-- log_message("Fired from [name], targeting [target].") var/turf/T = get_turf(src) - msg_admin_attack("[key_name_admin(chassis.occupant)] fired a [src] in ([T.x], [T.y], [T.z] - JMP)") + msg_admin_attack("[key_name_admin(chassis.occupant)] fired a [src] in ([T.x], [T.y], [T.z] - [ADMIN_JMP(T)])") log_game("[key_name(chassis.occupant)] fired a [src] in [T.x], [T.y], [T.z]") do_after_cooldown() return diff --git a/code/game/mecha/mecha.dm b/code/game/mecha/mecha.dm index 3f55ca70d10..3ba3221cd83 100644 --- a/code/game/mecha/mecha.dm +++ b/code/game/mecha/mecha.dm @@ -233,7 +233,7 @@ M.occupant_message("You hit [src].") visible_message("[src] has been hit by [M.name].") take_damage(M.force, damtype) - add_logs(M.occupant, src, "attacked", object=M, addition="(INTENT: [uppertext(M.occupant.a_intent)]) (DAMTYPE: [uppertext(M.damtype)])") + add_attack_logs(M.occupant, src, "Mecha-attacked with [M] (INTENT: [uppertext(M.occupant.a_intent)]) (DAMTYPE: [uppertext(M.damtype)])") return /obj/mecha/proc/range_action(atom/target) diff --git a/code/game/objects/explosion.dm b/code/game/objects/explosion.dm index 66d7f315580..8adb61dec93 100644 --- a/code/game/objects/explosion.dm +++ b/code/game/objects/explosion.dm @@ -150,7 +150,8 @@ */ var/took = stop_watch(watch) //You need to press the DebugGame verb to see these now....they were getting annoying and we've collected a fair bit of data. Just -test- changes to explosion code using this please so we can compare - if(Debug2) log_to_dd("## DEBUG: Explosion([x0],[y0],[z0])(d[devastation_range],h[heavy_impact_range],l[light_impact_range]): Took [took] seconds.") + if(Debug2) + log_world("## DEBUG: Explosion([x0],[y0],[z0])(d[devastation_range],h[heavy_impact_range],l[light_impact_range]): Took [took] seconds.") //Machines which report explosions. for(var/i,i<=doppler_arrays.len,i++) diff --git a/code/game/objects/items.dm b/code/game/objects/items.dm index 4ebe130d666..2f900532324 100644 --- a/code/game/objects/items.dm +++ b/code/game/objects/items.dm @@ -456,7 +456,7 @@ var/global/image/fire_overlay = image("icon" = 'icons/goonstation/effects/fire.d "You stab yourself in the eyes with [src]!" \ ) - add_logs(user, M, "attacked", "[name]", "(INTENT: [uppertext(user.a_intent)])") + add_attack_logs(user, M, "Eye-stabbed with [src] (INTENT: [uppertext(user.a_intent)])") if(istype(H)) var/obj/item/organ/internal/eyes/eyes = H.get_int_organ(/obj/item/organ/internal/eyes) diff --git a/code/game/objects/items/devices/aicard.dm b/code/game/objects/items/devices/aicard.dm index 88e2a7d86e5..d8c9b50c402 100644 --- a/code/game/objects/items/devices/aicard.dm +++ b/code/game/objects/items/devices/aicard.dm @@ -17,7 +17,7 @@ var/mob/living/silicon/ai/AI = locate(/mob/living/silicon/ai) in src if(AI) //AI is on the card, implies user wants to upload it. target.transfer_ai(AI_TRANS_FROM_CARD, user, AI, src) - add_logs(user, AI, "carded", object="[name]") + add_attack_logs(user, AI, "Carded with [src]") else //No AI on the card, therefore the user wants to download one. target.transfer_ai(AI_TRANS_TO_CARD, user, null, src) update_state() //Whatever happened, update the card's state (icon, name) to match. @@ -84,6 +84,7 @@ var/confirm = alert("Are you sure you want to wipe this card's memory? This cannot be undone once started.", "Confirm Wipe", "Yes", "No") if(confirm == "Yes" && (CanUseTopic(user, state) == STATUS_INTERACTIVE)) msg_admin_attack("[key_name_admin(user)] wiped [key_name_admin(AI)] with \the [src].") + log_attack(user, AI, "Wiped with [src].") flush = 1 AI.suiciding = 1 to_chat(AI, "Your core files are being wiped!") diff --git a/code/game/objects/items/devices/flash.dm b/code/game/objects/items/devices/flash.dm index cd11af32712..8c555e621eb 100644 --- a/code/game/objects/items/devices/flash.dm +++ b/code/game/objects/items/devices/flash.dm @@ -81,7 +81,7 @@ /obj/item/device/flash/proc/flash_carbon(var/mob/living/carbon/M, var/mob/user = null, var/power = 5, targeted = 1) - add_logs(user, M, "flashed", object="[src.name]") + add_attack_logs(user, M, "Flashed with [src]") if(user && targeted) if(M.weakeyes) M.Weaken(3) //quick weaken bypasses eye protection but has no eye flash @@ -121,10 +121,10 @@ if(R.module) // Perhaps they didn't choose a module yet for(var/obj/item/borg/combat/shield/S in R.module.modules) if(R.activated(S)) - add_logs(user, M, "flashed", object="[src.name]") + add_attack_logs(user, M, "Flashed with [src]") user.visible_message("[user] tries to overloads [M]'s sensors with the [src.name], but is blocked by [M]'s shield!", "You try to overload [M]'s sensors with the [src.name], but are blocked by their shield!") return 1 - add_logs(user, M, "flashed", object="[src.name]") + add_attack_logs(user, M, "Flashed with [src]") if(M.flash_eyes(affect_silicon = 1)) M.Weaken(rand(5,10)) user.visible_message("[user] overloads [M]'s sensors with the [src.name]!", "You overload [M]'s sensors with the [src.name]!") diff --git a/code/game/objects/items/devices/flashlight.dm b/code/game/objects/items/devices/flashlight.dm index 8a82d3cd73a..db8d647453a 100644 --- a/code/game/objects/items/devices/flashlight.dm +++ b/code/game/objects/items/devices/flashlight.dm @@ -278,7 +278,7 @@ obj/item/device/flashlight/lamp/bananalamp "[user] blinks \the [src] at \the [A].") if(ismob(A)) var/mob/M = A - add_logs(user, M, "attacked", object="EMP-light") + add_attack_logs(user, M, "Hit with EMP-light") to_chat(user, "[src] now has [emp_cur_charges] charge\s.") A.emp_act(1) else diff --git a/code/game/objects/items/devices/laserpointer.dm b/code/game/objects/items/devices/laserpointer.dm index 48381b17ec1..3215aae841e 100644 --- a/code/game/objects/items/devices/laserpointer.dm +++ b/code/game/objects/items/devices/laserpointer.dm @@ -99,7 +99,7 @@ if(iscarbon(target)) var/mob/living/carbon/C = target if(user.zone_sel.selecting == "eyes") - add_logs(user, C, "shone in the eyes", object="laser pointer") + add_attack_logs(user, C, "Shone a laser in the eyes with [src]") var/severity = 1 if(prob(33)) @@ -125,9 +125,7 @@ to_chat(S, "Your sensors were overloaded by a laser!") outmsg = "You overload [S] by shining [src] at their sensors." - S.create_attack_log("Has had a laser pointer shone in their eyes by [user.name] ([user.ckey])") - user.create_attack_log("Shone a laser pointer in the eyes of [S.name] ([S.ckey])") - log_attack("[user.name] ([user.ckey]) Shone a laser pointer in the eyes of [S.name] ([S.ckey])") + add_attack_logs(user, S, "shone [src] in their eyes") else outmsg = "You fail to overload [S] by shining [src] at their sensors." @@ -138,8 +136,8 @@ C.emp_act(1) outmsg = "You hit the lens of [C] with [src], temporarily disabling the camera!" - log_admin("\[[time_stamp()]\] [user.name] ([user.ckey]) EMPd a camera with a laser pointer") - user.create_attack_log("[user.name] ([user.ckey]) EMPd a camera with a laser pointer") + log_admin("[key_name(user)] EMPd a camera with a laser pointer") + user.create_attack_log("[key_name(user)] EMPd a camera with a laser pointer") else outmsg = "You missed the lens of [C] with [src]." diff --git a/code/game/objects/items/devices/traitordevices.dm b/code/game/objects/items/devices/traitordevices.dm index 6b48dea1910..002c3968dff 100644 --- a/code/game/objects/items/devices/traitordevices.dm +++ b/code/game/objects/items/devices/traitordevices.dm @@ -47,7 +47,7 @@ effective or pretty fucking useless. for(var/mob/living/carbon/human/M in oview(7, user)) if(prob(50)) M.Weaken(rand(4,7)) - add_logs(user, M, "stunned", src) + add_attack_logs(user, M, "Stunned with [src]") to_chat(M, "You feel a tremendous, paralyzing wave flood your mind.") else to_chat(M, "You feel a sudden, electric jolt travel through your head.") @@ -90,7 +90,7 @@ effective or pretty fucking useless. /obj/item/device/rad_laser/attack(mob/living/M, mob/living/user) if(!used) - add_logs(user, M, "irradiated", src) + add_attack_logs(user, M, "Irradiated by [src]") user.visible_message("[user] has analyzed [M]'s vitals.") var/cooldown = round(max(100,(((intensity*8)-(wavelength/2))+(intensity*2))*10)) used = 1 diff --git a/code/game/objects/items/robot/robot_items.dm b/code/game/objects/items/robot/robot_items.dm index 9d0f39285bc..bdc7e6df6cc 100644 --- a/code/game/objects/items/robot/robot_items.dm +++ b/code/game/objects/items/robot/robot_items.dm @@ -29,8 +29,7 @@ "[user] has prodded you with [src]!") playsound(loc, 'sound/weapons/Egloves.ogg', 50, 1, -1) - - add_logs(user, M, "stunned", src, "(INTENT: [uppertext(user.a_intent)])") + add_attack_logs(user, M, "Stunned with [src] (INTENT: [uppertext(user.a_intent)])") /obj/item/borg/overdrive name = "Overdrive" diff --git a/code/game/objects/items/weapons/defib.dm b/code/game/objects/items/weapons/defib.dm index 3557c5d57ee..762b2151b9c 100644 --- a/code/game/objects/items/weapons/defib.dm +++ b/code/game/objects/items/weapons/defib.dm @@ -333,7 +333,7 @@ H.emote("gasp") if(!H.undergoing_cardiac_arrest() && (prob(10) || defib.combat)) // Your heart explodes. H.set_heartattack(TRUE) - add_logs(user, M, "stunned", object="defibrillator") + add_attack_logs(user, M, "Stunned with [src]") defib.deductcharge(revivecost) cooldown = 1 busy = 0 @@ -411,7 +411,7 @@ if(tplus > tloss) H.setBrainLoss( max(0, min(99, ((tlimit - tplus) / tlimit * 100)))) defib.deductcharge(revivecost) - add_logs(user, M, "revived", object="defibrillator") + add_attack_logs(user, M, "Revived with [src]") else if(tplus > tlimit|| !H.get_int_organ(/obj/item/organ/internal/heart)) user.visible_message("[defib] buzzes: Resuscitation failed - Heart tissue damage beyond point of no return for defibrillation.") @@ -473,7 +473,7 @@ H.set_heartattack(TRUE) playsound(get_turf(src), 'sound/machines/defib_zap.ogg', 50, 1, -1) H.emote("gasp") - add_logs(user, M, "stunned", object="defibrillator") + add_attack_logs(user, M, "Stunned with [src]") if(isrobot(user)) var/mob/living/silicon/robot/R = user R.cell.use(revivecost) @@ -529,7 +529,7 @@ if(isrobot(user)) var/mob/living/silicon/robot/R = user R.cell.use(revivecost) - add_logs(user, M, "revived", object="defibrillator") + add_attack_logs(user, M, "Revived with [src]") else if(tplus > tlimit) user.visible_message("[user] buzzes: Resuscitation failed - Heart tissue damage beyond point of no return for defibrillation.") diff --git a/code/game/objects/items/weapons/dna_injector.dm b/code/game/objects/items/weapons/dna_injector.dm index a473b8d6b20..d120fb4e1cd 100644 --- a/code/game/objects/items/weapons/dna_injector.dm +++ b/code/game/objects/items/weapons/dna_injector.dm @@ -119,35 +119,19 @@ if(!user.IsAdvancedToolUser()) return 0 - M.create_attack_log("Has been injected with [name] by [user.name] ([user.ckey])") - user.create_attack_log("Used the [name] to inject [M.name] ([M.ckey])") - log_attack("[user.name] ([user.ckey]) used the [name] to inject [M.name] ([M.ckey])") - - if(!iscarbon(user)) - M.LAssailant = null - else - M.LAssailant = user + var/attack_log = "injected with the Isolated [name]" if(buf.types & DNA2_BUF_SE) - if(block) if(GetState() && block == MONKEYBLOCK && ishuman(M)) + attack_log = "injected with the Isolated [name] (MONKEY)" message_admins("[key_name_admin(user)] injected [key_name_admin(M)] with the Isolated [name] (MONKEY)") - log_attack("[key_name(user)] injected [key_name(M)] with the Isolated [name] (MONKEY)") - log_game("[key_name_admin(user)] injected [key_name_admin(M)] with the Isolated [name] (MONKEY)") - else - log_attack("[key_name(user)] injected [key_name(M)] with the Isolated [name]") else if(GetState(MONKEYBLOCK) && ishuman(M)) + attack_log = "injected with the Isolated [name] (MONKEY)" message_admins("[key_name_admin(user)] injected [key_name_admin(M)] with the Isolated [name] (MONKEY)") - log_attack("[key_name(user)] injected [key_name(M)] with the Isolated [name] (MONKEY)") - log_game("[key_name_admin(user)] injected [key_name_admin(M)] with the Isolated [name] (MONKEY)") - else - log_attack("[key_name(user)] injected [key_name(M)] with the Isolated [name]") - else - log_attack("[key_name(user)] injected [key_name(M)] with the [name]") if(M != user) M.visible_message("[user] is trying to inject [M] with [src]!", "[user] is trying to inject [M] with [src]!") @@ -155,10 +139,15 @@ return M.visible_message("[user] injects [M] with the syringe with [src]!", \ "[user] injects [M] with the syringe with [src]!") - else to_chat(user, "You inject yourself with [src].") + add_attack_logs(user, M, attack_log, FALSE) + if(!iscarbon(user)) + M.LAssailant = null + else + M.LAssailant = user + inject(M, user) used = 1 icon_state = "dnainjector0" diff --git a/code/game/objects/items/weapons/dnascrambler.dm b/code/game/objects/items/weapons/dnascrambler.dm index 53ceac58fdd..cd1d79ae683 100644 --- a/code/game/objects/items/weapons/dnascrambler.dm +++ b/code/game/objects/items/weapons/dnascrambler.dm @@ -51,9 +51,7 @@ H.dna.ResetUIFrom(H) target.update_icons() - log_attack("[key_name(user)] injected [key_name(target)] with the [name]") - log_game("[key_name_admin(user)] injected [key_name_admin(target)] with the [name]") - + add_attack_logs(user, target, "injected with [src]") used = 1 update_icon() name = "used " + name diff --git a/code/game/objects/items/weapons/explosives.dm b/code/game/objects/items/weapons/explosives.dm index d1e47f34bca..56f49853b10 100644 --- a/code/game/objects/items/weapons/explosives.dm +++ b/code/game/objects/items/weapons/explosives.dm @@ -89,7 +89,7 @@ /obj/item/grenade/plastic/suicide_act(mob/user) message_admins("[key_name_admin(user)](?) (FLW) suicided with [src.name] at ([user.x],[user.y],[user.z] - JMP)",0,1) - message_admins("[key_name(user)] suicided with [name] at ([user.x],[user.y],[user.z])") + log_game("[key_name(user)] suicided with [name] at ([user.x],[user.y],[user.z])") user.visible_message("[user] activates the [name] and holds it above \his head! It looks like \he's going out with a bang!") var/message_say = "FOR NO RAISIN!" if(user.mind) diff --git a/code/game/objects/items/weapons/flamethrower.dm b/code/game/objects/items/weapons/flamethrower.dm index d27bce20313..9a872257e3f 100644 --- a/code/game/objects/items/weapons/flamethrower.dm +++ b/code/game/objects/items/weapons/flamethrower.dm @@ -65,7 +65,7 @@ var/turf/target_turf = get_turf(target) if(target_turf) var/turflist = getline(user, target_turf) - add_logs(user, target, "flamethrowered", addition="at [target.x],[target.y],[target.z]") + add_attack_logs(user, target, "Flamethrowered at [target.x],[target.y],[target.z]") flame_turf(turflist) /obj/item/flamethrower/attackby(obj/item/W as obj, mob/user as mob, params) diff --git a/code/game/objects/items/weapons/handcuffs.dm b/code/game/objects/items/weapons/handcuffs.dm index 5a099274915..070e058b2d0 100644 --- a/code/game/objects/items/weapons/handcuffs.dm +++ b/code/game/objects/items/weapons/handcuffs.dm @@ -46,7 +46,7 @@ else feedback_add_details("handcuffs","H") - add_logs(user, C, "handcuffed", src) + add_attack_logs(user, C, "Handcuffed ([src])") else to_chat(user, "You fail to handcuff [C].") @@ -183,7 +183,7 @@ C.handcuffed = new /obj/item/restraints/handcuffs/cable/zipties/used(C) C.update_handcuffed() to_chat(user, "You handcuff [C].") - add_logs(user, C, "ziptie-cuffed") + add_attack_logs(user, C, "Handcuffed (ziptie-cuffed)") else to_chat(user, "You fail to handcuff [C].") diff --git a/code/game/objects/items/weapons/implants/implant.dm b/code/game/objects/items/weapons/implants/implant.dm index 94d476b6470..9a7c3f0e27c 100644 --- a/code/game/objects/items/weapons/implants/implant.dm +++ b/code/game/objects/items/weapons/implants/implant.dm @@ -54,7 +54,7 @@ H.sec_hud_set_implants() if(user) - add_logs(user, source, "implanted", object="[name]") + add_attack_logs(user, source, "Implanted with [src]") return 1 diff --git a/code/game/objects/items/weapons/implants/implant_traitor.dm b/code/game/objects/items/weapons/implants/implant_traitor.dm index fa7192f4f56..68ef65664c7 100644 --- a/code/game/objects/items/weapons/implants/implant_traitor.dm +++ b/code/game/objects/items/weapons/implants/implant_traitor.dm @@ -74,7 +74,7 @@ slaved.add_serv_hud(user.mind, "master") //handles master servent icons slaved.add_serv_hud(H.mind, "mindslave") - log_admin("[ckey(user.key)] has mind-slaved [ckey(H.key)].") + log_admin("[key_name(user)] has mind-slaved [key_name(H)].") activated = 1 if(jobban_isbanned(M, ROLE_SYNDICATE)) ticker.mode.replace_jobbanned_player(M, ROLE_SYNDICATE) diff --git a/code/game/objects/items/weapons/pneumaticCannon.dm b/code/game/objects/items/weapons/pneumaticCannon.dm index 55515dc0947..84b8d55a915 100644 --- a/code/game/objects/items/weapons/pneumaticCannon.dm +++ b/code/game/objects/items/weapons/pneumaticCannon.dm @@ -114,7 +114,7 @@ if(!discharge) user.visible_message("[user] fires \the [src]!", \ "You fire \the [src]!") - add_logs(user, target, "fired at", src) + add_attack_logs(user, target, "Fired [src]") playsound(src.loc, 'sound/weapons/sonic_jackhammer.ogg', 50, 1) for(var/obj/item/ITD in loadedItems) //Item To Discharge spawn(0) diff --git a/code/game/objects/items/weapons/powerfist.dm b/code/game/objects/items/weapons/powerfist.dm index 0af3018268c..7b6dfeb3a75 100644 --- a/code/game/objects/items/weapons/powerfist.dm +++ b/code/game/objects/items/weapons/powerfist.dm @@ -93,6 +93,6 @@ target.throw_at(throw_target, 5 * fisto_setting, 0.2) - add_logs(user, target, "power fisted", src) + add_attack_logs(user, target, "POWER FISTED with [src]") user.changeNext_move(CLICK_CD_MELEE * click_delay) diff --git a/code/game/objects/items/weapons/storage/bible.dm b/code/game/objects/items/weapons/storage/bible.dm index deb1fc489c2..4d56e2a22ad 100644 --- a/code/game/objects/items/weapons/storage/bible.dm +++ b/code/game/objects/items/weapons/storage/bible.dm @@ -38,16 +38,11 @@ return /obj/item/storage/bible/attack(mob/living/M as mob, mob/living/user as mob) - var/chaplain = 0 if(user.mind && (user.mind.assigned_role == "Chaplain")) chaplain = 1 - - M.create_attack_log("Has been attacked with [src.name] by [user.name] ([user.ckey])") - user.create_attack_log("Used the [src.name] to attack [M.name] ([M.ckey])") - log_attack("[user.name] ([user.ckey]) attacked [M.name] ([M.ckey]) with [src.name] (INTENT: [uppertext(user.a_intent)])") - + add_attack_logs(user, M, "Hit with [src]") if(!iscarbon(user)) M.LAssailant = null else diff --git a/code/game/objects/items/weapons/stunbaton.dm b/code/game/objects/items/weapons/stunbaton.dm index ce8ed6ad167..95598a0ed23 100644 --- a/code/game/objects/items/weapons/stunbaton.dm +++ b/code/game/objects/items/weapons/stunbaton.dm @@ -160,7 +160,7 @@ var/mob/living/carbon/human/H = L H.forcesay(hit_appends) - add_logs(user, L, "stunned", object="stunbaton") + add_attack_logs(user, L, "Stunned with [src]") /obj/item/melee/baton/emp_act(severity) if(bcell) diff --git a/code/game/objects/items/weapons/swords_axes_etc.dm b/code/game/objects/items/weapons/swords_axes_etc.dm index 55fa8177e15..3fc4b4b7717 100644 --- a/code/game/objects/items/weapons/swords_axes_etc.dm +++ b/code/game/objects/items/weapons/swords_axes_etc.dm @@ -55,8 +55,8 @@ return 0 playsound(get_turf(src), 'sound/effects/woodhit.ogg', 75, 1, -1) target.Weaken(3) - add_logs(user, target, "stunned", object="[src]") - src.add_fingerprint(user) + add_attack_logs(user, target, "Stunned with [src]") + add_fingerprint(user) target.visible_message("[user] has knocked down [target] with \the [src]!", \ "[user] has knocked down [target] with \the [src]!") if(!iscarbon(user)) diff --git a/code/game/objects/items/weapons/tanks/watertank.dm b/code/game/objects/items/weapons/tanks/watertank.dm index 6f773d329ca..64a5c95f5c0 100644 --- a/code/game/objects/items/weapons/tanks/watertank.dm +++ b/code/game/objects/items/weapons/tanks/watertank.dm @@ -286,7 +286,7 @@ nanofrost_cooldown = 1 R.remove_any(50) var/obj/effect/nanofrost_container/A = new /obj/effect/nanofrost_container(get_turf(src)) - log_game("[user.ckey] ([user.name]) used Nanofrost at [get_area(user)] ([user.x], [user.y], [user.z]).") + log_game("[key_name(user)] used Nanofrost at [get_area(user)] ([user.x], [user.y], [user.z]).") playsound(src,'sound/items/syringeproj.ogg',40,1) for(var/a=0, a<5, a++) step_towards(A, target) diff --git a/code/game/objects/structures/morgue.dm b/code/game/objects/structures/morgue.dm index 49235504200..3e5d3386e0a 100644 --- a/code/game/objects/structures/morgue.dm +++ b/code/game/objects/structures/morgue.dm @@ -368,9 +368,7 @@ if(M.stat!=2) M.emote("scream") if(istype(user)) - M.create_attack_log("Has been cremated by [user.name] ([user.ckey])") - user.create_attack_log("Cremated [M.name] ([M.ckey])") - log_attack("[user.name] ([user.ckey]) cremated [M.name] ([M.ckey])") + add_attack_logs(user, M, "Cremated") M.death(1) if(QDELETED(M)) continue // Re-check for mobs that delete themselves on death diff --git a/code/game/objects/structures/spirit_board.dm b/code/game/objects/structures/spirit_board.dm index 253f93dc7ae..b6f66350f1f 100644 --- a/code/game/objects/structures/spirit_board.dm +++ b/code/game/objects/structures/spirit_board.dm @@ -33,7 +33,7 @@ notify_ghosts("Someone has begun playing with a [src.name] in [get_area(src)]!", source = src) planchette = input("Choose the letter.", "Seance!") in list("A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z") - add_logs(M, src, "picked a letter on", addition="which was \"[planchette]\".") + add_attack_logs(M, src, "Picked a letter on [src] which was \"[planchette]\".") cooldown = world.time lastuser = M.ckey diff --git a/code/game/objects/structures/tables_racks.dm b/code/game/objects/structures/tables_racks.dm index 9737b6fe0da..002bbb566d6 100644 --- a/code/game/objects/structures/tables_racks.dm +++ b/code/game/objects/structures/tables_racks.dm @@ -190,7 +190,7 @@ G.affecting.Weaken(2) G.affecting.visible_message("[G.assailant] pushes [G.affecting] onto [src].", \ "[G.assailant] pushes [G.affecting] onto [src].") - add_logs(G.assailant, G.affecting, "pushed onto a table") + add_attack_logs(G.assailant, G.affecting, "Pushed onto a table") qdel(I) return 1 qdel(I) diff --git a/code/game/verbs/ooc.dm b/code/game/verbs/ooc.dm index cd68b0ec3b0..29d5e41b716 100644 --- a/code/game/verbs/ooc.dm +++ b/code/game/verbs/ooc.dm @@ -40,7 +40,7 @@ var/global/admin_ooc_colour = "#b82e00" message_admins("[key_name_admin(src)] has attempted to advertise in OOC: [msg]") return - log_ooc("[mob.name]/[key] : [msg]") + log_ooc(msg, src) var/display_colour = normal_ooc_colour if(holder && !holder.fakekey) @@ -187,7 +187,7 @@ var/global/admin_ooc_colour = "#b82e00" message_admins("[key_name_admin(src)] has attempted to advertise in LOOC: [msg]") return - log_ooc("(LOCAL) [mob.name]/[key] : [msg]") + log_looc(msg, src) var/mob/source = mob.get_looc_source() var/list/heard = get_mobs_in_view(7, source) diff --git a/code/game/world.dm b/code/game/world.dm new file mode 100644 index 00000000000..f7cf1a758b7 --- /dev/null +++ b/code/game/world.dm @@ -0,0 +1,494 @@ +#define RECOMMENDED_VERSION 510 + +var/global/list/map_transition_config = MAP_TRANSITION_CONFIG + +/world/New() + SetupLogs() + log_world("World loaded at [time_stamp()]") + log_world("[GLOB.vars.len - GLOB.gvars_datum_in_built_vars.len] global variables") + + if(byond_version < RECOMMENDED_VERSION) + log_world("Your server's byond version does not meet the recommended requirements for this code. Please update BYOND") + + if(config && config.server_name != null && config.server_suffix && world.port > 0) + // dumb and hardcoded but I don't care~ + config.server_name += " #[(world.port % 1000) / 100]" + + GLOB.timezoneOffset = text2num(time2text(0, "hh")) * 36000 + + callHook("startup") + + src.update_status() + + . = ..() + + // Create robolimbs for chargen. + populate_robolimb_list() + + space_manager.initialize() //Before the MC starts up + + Master.Initialize(10, FALSE) + + processScheduler = new + master_controller = new /datum/controller/game_controller() + spawn(1) + processScheduler.deferSetupFor(/datum/controller/process/ticker) + processScheduler.setup() + + master_controller.setup() + + if(using_map && using_map.name) + map_name = "[using_map.name]" + else + map_name = "Unknown" + + + if(config && config.server_name) + name = "[config.server_name]: [station_name()]" + else + name = station_name() + + +#undef RECOMMENDED_VERSION + + return + +//world/Topic(href, href_list[]) +// to_chat(world, "Received a Topic() call!") +// to_chat(world, "[href]") +// for(var/a in href_list) +// to_chat(world, "[a]") +// if(href_list["hello"]) +// to_chat(world, "Hello world!") +// return "Hello world!" +// to_chat(world, "End of Topic() call.") +// ..() + +var/world_topic_spam_protect_ip = "0.0.0.0" +var/world_topic_spam_protect_time = world.timeofday + +/world/Topic(T, addr, master, key) + log_debug("WORLD/TOPIC: \"[T]\", from:[addr], master:[master], key:[key]") + + var/list/input = params2list(T) + var/key_valid = (config.comms_password && input["key"] == config.comms_password) //no password means no comms, not any password + + if("ping" in input) + var/x = 1 + for(var/client/C) + x++ + return x + + else if("players" in input) + var/n = 0 + for(var/mob/M in player_list) + if(M.client) + n++ + return n + + else if("status" in input) + var/list/s = list() + var/list/admins = list() + s["version"] = game_version + s["mode"] = master_mode + s["respawn"] = config ? abandon_allowed : 0 + s["enter"] = enter_allowed + s["vote"] = config.allow_vote_mode + s["ai"] = config.allow_ai + s["host"] = host ? host : null + s["players"] = list() + s["roundtime"] = worldtime2text() + s["stationtime"] = station_time_timestamp() + s["oldstationtime"] = classic_worldtime2text() // more "consistent" indication of the round's running time + s["listed"] = "Public" + if(!hub_password) + s["listed"] = "Invisible" + var/player_count = 0 + var/admin_count = 0 + + for(var/client/C in clients) + if(C.holder) + if(C.holder.fakekey) + continue //so stealthmins aren't revealed by the hub + admin_count++ + admins += list(list(C.key, C.holder.rank)) + s["player[player_count]"] = C.key + player_count++ + s["players"] = player_count + s["admins"] = admin_count + s["map_name"] = map_name ? map_name : "Unknown" + + if(key_valid) + if(ticker && ticker.mode) + s["real_mode"] = ticker.mode.name + + s["security_level"] = get_security_level() + s["ticker_state"] = ticker.current_state + + if(shuttle_master && shuttle_master.emergency) + // Shuttle status, see /__DEFINES/stat.dm + s["shuttle_mode"] = shuttle_master.emergency.mode + // Shuttle timer, in seconds + s["shuttle_timer"] = shuttle_master.emergency.timeLeft() + + for(var/i in 1 to admins.len) + var/list/A = admins[i] + s["admin[i - 1]"] = A[1] + s["adminrank[i - 1]"] = A[2] + + return list2params(s) + + else if("manifest" in input) + var/list/positions = list() + var/list/set_names = list( + "heads" = command_positions, + "sec" = security_positions, + "eng" = engineering_positions, + "med" = medical_positions, + "sci" = science_positions, + "car" = supply_positions, + "srv" = service_positions, + "civ" = civilian_positions, + "bot" = nonhuman_positions + ) + + for(var/datum/data/record/t in data_core.general) + var/name = t.fields["name"] + var/rank = t.fields["rank"] + var/real_rank = t.fields["real_rank"] + + var/department = 0 + for(var/k in set_names) + if(real_rank in set_names[k]) + if(!positions[k]) + positions[k] = list() + positions[k][name] = rank + department = 1 + if(!department) + if(!positions["misc"]) + positions["misc"] = list() + positions["misc"][name] = rank + + return json_encode(positions) + + else if("adminmsg" in input) + /* + We got an adminmsg from IRC bot lets split the input then validate the input. + expected output: + 1. adminmsg = ckey of person the message is to + 2. msg = contents of message, parems2list requires + 3. validatationkey = the key the bot has, it should match the gameservers commspassword in it's configuration. + 4. sender = the ircnick that send the message. + */ + if(!key_valid) + return keySpamProtect(addr) + + var/client/C + + for(var/client/K in clients) + if(K.ckey == input["adminmsg"]) + C = K + break + if(!C) + return "No client with that name on server" + + var/message = "IRC-Admin PM from [C.holder ? "IRC-" + input["sender"] : "Administrator"]: [input["msg"]]" + var/amessage = "IRC-Admin PM from IRC-[input["sender"]] to [key_name(C)] : [input["msg"]]" + + C.received_irc_pm = world.time + C.irc_admin = input["sender"] + + C << 'sound/effects/adminhelp.ogg' + to_chat(C, message) + + for(var/client/A in admins) + if(A != C) + to_chat(A, amessage) + + return "Message Successful" + + else if("notes" in input) + /* + We got a request for notes from the IRC Bot + expected output: + 1. notes = ckey of person the notes lookup is for + 2. validationkey = the key the bot has, it should match the gameservers commspassword in it's configuration. + */ + if(!key_valid) + return keySpamProtect(addr) + + return show_player_info_irc(input["notes"]) + + else if("announce" in input) + if(config.comms_password) + if(input["key"] != config.comms_password) + return "Bad Key" + else + for(var/client/C in clients) + to_chat(C, "PR: [input["announce"]]") + + else if("kick" in input) + /* + We have a kick request over coms. + Only needed portion is the ckey + */ + if(!key_valid) + return keySpamProtect(addr) + + var/client/C + + for(var/client/K in clients) + if(K.ckey == input["kick"]) + C = K + break + if(!C) + return "No client with that name on server" + + del(C) + + return "Kick Successful" + + else if("setlog" in input) + if(!key_valid) + return keySpamProtect(addr) + + SetupLogs() + + return "Logs set to current date" + + else if("setlist" in input) + if(!key_valid) + return keySpamProtect(addr) + if(input["req"] == "public") + hub_password = hub_password_base + update_status() + return "Set listed status to public." + else + hub_password = "" + update_status() + return "Set listed status to invisible." + +/proc/keySpamProtect(var/addr) + if(world_topic_spam_protect_ip == addr && abs(world_topic_spam_protect_time - world.time) < 50) + spawn(50) + world_topic_spam_protect_time = world.time + return "Bad Key (Throttled)" + + world_topic_spam_protect_time = world.time + world_topic_spam_protect_ip = addr + return "Bad Key" + +/world/Reboot(var/reason, var/feedback_c, var/feedback_r, var/time) + if(reason == 1) //special reboot, do none of the normal stuff + if(usr) + message_admins("[key_name_admin(usr)] has requested an immediate world restart via client side debugging tools") + log_admin("[key_name(usr)] has requested an immediate world restart via client side debugging tools") + spawn(0) + to_chat(world, "Rebooting world immediately due to host request") + shutdown_logging() // Past this point, no logging procs can be used, at risk of data loss. + if(config && config.shutdown_on_reboot) + sleep(0) + if(shutdown_shell_command) + shell(shutdown_shell_command) + del(world) + return + else + return ..(1) + + var/delay + if(!isnull(time)) + delay = max(0,time) + else + delay = ticker.restart_timeout + if(ticker.delay_end) + to_chat(world, "An admin has delayed the round end.") + return + to_chat(world, "Rebooting world in [delay/10] [delay > 10 ? "seconds" : "second"]. [reason]") + + var/round_end_sound = pick(round_end_sounds) + var/sound_length = round_end_sounds[round_end_sound] + if(delay > sound_length) // If there's time, play the round-end sound before rebooting + spawn(delay - sound_length) + if(!ticker.delay_end) + world << round_end_sound + sleep(delay) + if(blackbox) + blackbox.save_all_data_to_sql() + if(ticker.delay_end) + to_chat(world, "Reboot was cancelled by an admin.") + return + feedback_set_details("[feedback_c]","[feedback_r]") + log_game("Rebooting world. [reason]") + //kick_clients_in_lobby("The round came to an end with you in the lobby.", 1) + + processScheduler.stop() + shutdown_logging() // Past this point, no logging procs can be used, at risk of data loss. + + if(config && config.shutdown_on_reboot) + sleep(0) + if(shutdown_shell_command) + shell(shutdown_shell_command) + del(world) + return + else + for(var/client/C in clients) + if(config.server) //if you set a server location in config.txt, it sends you there instead of trying to reconnect to the same world address. -- NeoFite + C << link("byond://[config.server]") + ..(0) + + +/hook/startup/proc/loadMode() + world.load_mode() + return 1 + +/world/proc/load_mode() + var/list/Lines = file2list("data/mode.txt") + if(Lines.len) + if(Lines[1]) + master_mode = Lines[1] + log_game("Saved mode is '[master_mode]'") + +/world/proc/save_mode(var/the_mode) + var/F = file("data/mode.txt") + fdel(F) + F << the_mode + +/hook/startup/proc/loadMOTD() + world.load_motd() + return 1 + +/world/proc/load_motd() + join_motd = file2text("config/motd.txt") + + +/proc/load_configuration() + config = new /datum/configuration() + config.load("config/config.txt") + config.load("config/game_options.txt","game_options") + config.loadsql("config/dbconfig.txt") + config.loadoverflowwhitelist("config/ofwhitelist.txt") + // apply some settings from config.. + +/world/proc/update_status() + var/s = "" + + if(config && config.server_name) + s += "[config.server_name] — " + + s += "[station_name()]"; + s += " (" + s += "" //Change this to wherever you want the hub to link to. + s += "[game_version]" + s += "" + s += ")" + s += "
The Perfect Mix of RP & Action
" + + + + + var/list/features = list() + + if(ticker) + if(master_mode) + features += master_mode + else + features += "STARTING" + + if(!enter_allowed) + features += "closed" + + features += abandon_allowed ? "respawn" : "no respawn" + + if(config && config.allow_vote_mode) + features += "vote" + + if(config && config.allow_ai) + features += "AI allowed" + + var/n = 0 + for(var/mob/M in player_list) + if(M.client) + n++ + + if(n > 1) + features += "~[n] players" + else if(n > 0) + features += "~[n] player" + + /* + is there a reason for this? the byond site shows 'hosted by X' when there is a proper host already. + if(host) + features += "hosted by [host]" + */ + +// if(!host && config && config.hostedby) +// features += "hosted by [config.hostedby]" + + if(features) + s += ": [jointext(features, ", ")]" + + /* does this help? I do not know */ + if(src.status != s) + src.status = s + +#define FAILED_DB_CONNECTION_CUTOFF 5 +var/failed_db_connections = 0 +var/failed_old_db_connections = 0 + +/world/proc/SetupLogs() + GLOB.log_directory = "data/logs/[time2text(world.realtime, "YYYY/MM-Month/DD-Day")]" + GLOB.world_game_log = "[GLOB.log_directory]/game.log" + GLOB.world_href_log = "[GLOB.log_directory]/hrefs.log" + GLOB.world_runtime_log = "[GLOB.log_directory]/runtime.log" + start_log(GLOB.world_game_log) + start_log(GLOB.world_href_log) + start_log(GLOB.world_runtime_log) + + if(fexists(GLOB.config_error_log)) + fcopy(GLOB.config_error_log, "[GLOB.log_directory]/config_error.log") + fdel(GLOB.config_error_log) + + +/hook/startup/proc/connectDB() + if(!setup_database_connection()) + log_world("Your server failed to establish a connection with the feedback database.") + else + log_world("Feedback database connection established.") + return 1 + +/proc/setup_database_connection() + + if(failed_db_connections > FAILED_DB_CONNECTION_CUTOFF) //If it failed to establish a connection more than 5 times in a row, don't bother attempting to conenct anymore. + return 0 + + if(!dbcon) + dbcon = new() + + var/user = sqlfdbklogin + var/pass = sqlfdbkpass + var/db = sqlfdbkdb + var/address = sqladdress + var/port = sqlport + + dbcon.Connect("dbi:mysql:[db]:[address]:[port]","[user]","[pass]") + . = dbcon.IsConnected() + if( . ) + failed_db_connections = 0 //If this connection succeeded, reset the failed connections counter. + else + failed_db_connections++ //If it failed, increase the failed connections counter. + log_world(dbcon.ErrorMsg()) + + return . + +//This proc ensures that the connection to the feedback database (global variable dbcon) is established +proc/establish_db_connection() + if(failed_db_connections > FAILED_DB_CONNECTION_CUTOFF) + return 0 + + if(!dbcon || !dbcon.IsConnected()) + return setup_database_connection() + else + return 1 + +#undef FAILED_DB_CONNECTION_CUTOFF + diff --git a/code/modules/admin/IsBanned.dm b/code/modules/admin/IsBanned.dm index 4015c2fda1c..b97993d5327 100644 --- a/code/modules/admin/IsBanned.dm +++ b/code/modules/admin/IsBanned.dm @@ -1,11 +1,11 @@ //Blocks an attempt to connect before even creating our client datum thing. world/IsBanned(key,address,computer_id) if(!key || !address || !computer_id) - log_access("Failed Login (invalid data): [key] [address]-[computer_id]") + log_adminwarn("Failed Login (invalid data): [key] [address]-[computer_id]") return list("reason"="invalid login data", "desc"="Error: Could not check ban status, please try again. Error message: Your computer provided invalid or blank information to the server on connection (BYOND Username, IP, and Computer ID). Provided information for reference: Username: '[key]' IP: '[address]' Computer ID: '[computer_id]'. If you continue to get this error, please restart byond or contact byond support.") if(text2num(computer_id) == 2147483647) //this cid causes stickybans to go haywire - log_access("Failed Login (invalid cid): [key] [address]-[computer_id]") + log_adminwarn("Failed Login (invalid cid): [key] [address]-[computer_id]") return list("reason"="invalid login data", "desc"="Error: Could not check ban status, Please try again. Error message: Your computer provided an invalid Computer ID.") var/admin = 0 var/ckey = ckey(key) @@ -16,13 +16,13 @@ world/IsBanned(key,address,computer_id) //Guest Checking if(!guests_allowed && IsGuestKey(key)) - log_access("Failed Login: [key] [computer_id] [address] - Guests not allowed") + log_adminwarn("Failed Login: [key] [computer_id] [address] - Guests not allowed") // message_admins("Failed Login: [key] - Guests not allowed") return list("reason"="guest", "desc"="\nReason: Guests not allowed. Please sign in with a BYOND account.") //check if the IP address is a known Tor node if(config.ToRban && ToRban_isbanned(address)) - log_access("Failed Login: [key] [computer_id] [address] - Banned: Tor") + log_adminwarn("Failed Login: [key] [computer_id] [address] - Banned: Tor") message_admins("Failed Login: [key] - Banned: Tor") //ban their computer_id and ckey for posterity AddBan(ckey(key), computer_id, "Use of Tor", "Automated Ban", 0, 0) @@ -41,14 +41,13 @@ world/IsBanned(key,address,computer_id) message_admins("The admin [key] has been allowed to bypass a matching ban on [.["key"]]") addclientmessage(ckey,"You have been allowed to bypass a matching ban on [.["key"]].") else - log_access("Failed Login: [key] [computer_id] [address] - Banned [.["reason"]]") + log_adminwarn("Failed Login: [key] [computer_id] [address] - Banned [.["reason"]]") return . else var/ckeytext = ckey(key) if(!establish_db_connection()) - log_to_dd("Ban database connection failure. Key [ckeytext] not checked") - diary << "Ban database connection failure. Key [ckeytext] not checked" + log_world("Ban database connection failure. Key [ckeytext] not checked") return var/ipquery = "" @@ -100,7 +99,7 @@ world/IsBanned(key,address,computer_id) . = list("reason"="[bantype]", "desc"="[desc]") - log_access("Failed Login: [key] [computer_id] [address] - Banned [.["reason"]]") + log_adminwarn("Failed Login: [key] [computer_id] [address] - Banned [.["reason"]]") return . . = ..() //default pager ban stuff @@ -114,6 +113,6 @@ world/IsBanned(key,address,computer_id) addclientmessage(ckey,"You have been allowed to bypass a matching host/sticky ban.") return null else - log_access("Failed Login: [key] [computer_id] [address] - Banned [.["message"]]") + log_adminwarn("Failed Login: [key] [computer_id] [address] - Banned [.["message"]]") return . diff --git a/code/modules/admin/ToRban.dm b/code/modules/admin/ToRban.dm index 77e49877259..05af7c15cf5 100644 --- a/code/modules/admin/ToRban.dm +++ b/code/modules/admin/ToRban.dm @@ -22,7 +22,7 @@ /proc/ToRban_update() spawn(0) - diary << "Downloading updated ToR data..." + log_world("Downloading updated ToR data...") var/http[] = world.Export("http://exitlist.torproject.org/exit-addresses") var/list/rawlist = file2list(http["CONTENT"]) @@ -36,11 +36,11 @@ if(!cleaned) continue F[cleaned] << 1 to_chat(F["last_update"], world.realtime) - diary << "ToR data updated!" + log_world("ToR data updated!") if(usr) to_chat(usr, "ToRban updated.") return 1 - diary << "ToR data update aborted: no data." + log_world("ToR data update aborted: no data.") return 0 /client/proc/ToRban(task in list("update","toggle","show","remove","remove all","find")) diff --git a/code/modules/admin/admin.dm b/code/modules/admin/admin.dm index ce5ac02b85a..b155ddc13dd 100644 --- a/code/modules/admin/admin.dm +++ b/code/modules/admin/admin.dm @@ -4,14 +4,12 @@ var/global/nologevent = 0 //////////////////////////////// /proc/message_admins(var/msg) msg = "ADMIN LOG: [msg]" - log_adminwarn(msg) for(var/client/C in admins) if(R_ADMIN & C.holder.rights) if(C.prefs && !(C.prefs.toggles & CHAT_NO_ADMINLOGS)) to_chat(C, msg) /proc/msg_admin_attack(var/text) //Toggleable Attack Messages - log_attack(text) if(!nologevent) var/rendered = "ATTACK: [text]" for(var/client/C in admins) @@ -866,13 +864,13 @@ var/global/nologevent = 0 for(var/mob/living/silicon/S in mob_list) ai_number++ if(isAI(S)) - to_chat(usr, "AI [key_name(S, usr)]'s laws:") + to_chat(usr, "AI [key_name(S, TRUE)]'s laws:") else if(isrobot(S)) var/mob/living/silicon/robot/R = S - to_chat(usr, "CYBORG [key_name(S, usr)]'s [R.connected_ai?"(Slaved to: [R.connected_ai])":"(Independent)"] laws:") + to_chat(usr, "CYBORG [key_name(S, TRUE)]'s [R.connected_ai?"(Slaved to: [R.connected_ai])":"(Independent)"] laws:") else if(ispAI(S)) var/mob/living/silicon/pai/P = S - to_chat(usr, "pAI [key_name(S, usr)]'s laws:") + to_chat(usr, "pAI [key_name(S, TRUE)]'s laws:") to_chat(usr, "[P.pai_law0]") if(P.pai_laws) to_chat(usr, "[P.pai_laws]") diff --git a/code/modules/admin/admin_investigate.dm b/code/modules/admin/admin_investigate.dm index 3eb12b11e68..4623a46d7d1 100644 --- a/code/modules/admin/admin_investigate.dm +++ b/code/modules/admin/admin_investigate.dm @@ -40,8 +40,8 @@ if("hrefs") //persistant logs and stuff if(config && config.log_hrefs) - if(href_logfile) - src << browse(href_logfile,"window=investigate[subject];size=800x300") + if(GLOB.world_href_log) + src << browse(file(GLOB.world_href_log), "window=investigate[subject];size=800x300") else to_chat(src, "Error: admin_investigate: No href logfile found.") return diff --git a/code/modules/admin/admin_ranks.dm b/code/modules/admin/admin_ranks.dm index 7b5c4073293..45e85a847fe 100644 --- a/code/modules/admin/admin_ranks.dm +++ b/code/modules/admin/admin_ranks.dm @@ -104,8 +104,7 @@ var/list/admin_ranks = list() //list of all ranks with associated rights establish_db_connection() if(!dbcon.IsConnected()) - log_to_dd("Failed to connect to database in load_admins(). Reverting to legacy system.") - diary << "Failed to connect to database in load_admins(). Reverting to legacy system." + log_world("Failed to connect to database in load_admins(). Reverting to legacy system.") config.admin_legacy_system = 1 load_admins() return @@ -124,8 +123,7 @@ var/list/admin_ranks = list() //list of all ranks with associated rights //find the client for a ckey if they are connected and associate them with the new admin datum D.associate(directory[ckey]) if(!admin_datums) - log_to_dd("The database query in load_admins() resulted in no admins being added to the list. Reverting to legacy system.") - diary << "The database query in load_admins() resulted in no admins being added to the list. Reverting to legacy system." + log_world("The database query in load_admins() resulted in no admins being added to the list. Reverting to legacy system.") config.admin_legacy_system = 1 load_admins() return diff --git a/code/modules/admin/admin_verbs.dm b/code/modules/admin/admin_verbs.dm index e3889ebf1bd..43652f0784d 100644 --- a/code/modules/admin/admin_verbs.dm +++ b/code/modules/admin/admin_verbs.dm @@ -19,17 +19,13 @@ var/list/admin_verbs_admin = list( /client/proc/resetcolorooc, /*allows us to set a reset our ooc color*/ /client/proc/admin_ghost, /*allows us to ghost/reenter body at will*/ /client/proc/toggle_view_range, /*changes how far we can see*/ - /datum/admins/proc/view_txt_log, /*shows the server log (diary) for today*/ - /datum/admins/proc/view_atk_log, /*shows the server combat-log, doesn't do anything presently*/ /client/proc/cmd_admin_pm_context, /*right-click adminPM interface*/ /client/proc/cmd_admin_pm_panel, /*admin-pm list*/ /client/proc/cmd_admin_pm_by_key_panel, /*admin-pm list by key*/ /client/proc/cmd_admin_subtle_message, /*send an message to somebody as a 'voice in their head'*/ /client/proc/cmd_admin_delete, /*delete an instance/object/mob/etc*/ /client/proc/cmd_admin_check_contents, /*displays the contents of an instance*/ - /client/proc/giveruntimelog, /*allows us to give access to runtime logs to somebody*/ - /client/proc/getruntimelog, /*allows us to access runtime logs to somebody*/ - /client/proc/getserverlog, /*allows us to fetch server logs (diary) for other days*/ + /client/proc/getserverlogs, /*allows us to fetch server logs (diary) for other days*/ /client/proc/jumptocoord, /*we ghost and jump to a coordinate*/ /client/proc/Getmob, /*teleports a mob to our location*/ /client/proc/Getkey, /*teleports a mob with a certain ckey to our location*/ diff --git a/code/modules/admin/banappearance.dm b/code/modules/admin/banappearance.dm index 06deaa1c461..ff461c0f333 100644 --- a/code/modules/admin/banappearance.dm +++ b/code/modules/admin/banappearance.dm @@ -52,8 +52,7 @@ DEBUG log_admin("appearance_keylist was empty") else if(!establish_db_connection()) - log_to_dd("Database connection failed. Reverting to the legacy ban system.") - diary << "Database connection failed. Reverting to the legacy ban system." + log_world("Database connection failed. Reverting to the legacy ban system.") config.ban_legacy_system = 1 appearance_loadbanfile() return diff --git a/code/modules/admin/banjob.dm b/code/modules/admin/banjob.dm index 6dd7930b120..920bb933f32 100644 --- a/code/modules/admin/banjob.dm +++ b/code/modules/admin/banjob.dm @@ -78,8 +78,7 @@ DEBUG log_runtime(EXCEPTION("Skipping malformed job ban: [s]")) else if(!establish_db_connection()) - log_to_dd("Database connection failed. Reverting to the legacy ban system.") - diary << "Database connection failed. Reverting to the legacy ban system." + log_world("Database connection failed. Reverting to the legacy ban system.") config.ban_legacy_system = 1 jobban_loadbanfile() return diff --git a/code/modules/admin/verbs/adminhelp.dm b/code/modules/admin/verbs/adminhelp.dm index 9c0564a6bf1..c38b42ad9b5 100644 --- a/code/modules/admin/verbs/adminhelp.dm +++ b/code/modules/admin/verbs/adminhelp.dm @@ -109,7 +109,7 @@ var/list/adminhelp_ignored_words = list("unknown","the","a","an","of","monkey"," switch(selected_type) if("Mentorhelp") - msg = "[selected_type]: [key_name(src, 1, 1, selected_type)] (?) (PP) (VV) (SM) ([admin_jump_link(mob)]) (CA) (REJT) [ai_found ? " (CL)" : ""] (TAKE) : [msg]" + msg = "[selected_type]: [key_name(src, TRUE, selected_type)] (?) (PP) (VV) (SM) ([admin_jump_link(mob)]) (CA) (REJT) [ai_found ? " (CL)" : ""] (TAKE) : [msg]" for(var/client/X in mentorholders + modholders + adminholders) if(X.prefs.sound & SOUND_ADMINHELP) X << 'sound/effects/adminhelp.ogg' @@ -123,7 +123,7 @@ var/list/adminhelp_ignored_words = list("unknown","the","a","an","of","monkey"," T.addResponse(usr.client, msg) else ticketNum = globAdminTicketHolder.getTicketCounter() // ticketNum is the ticket ready to be assigned. - msg = "[selected_type]: [key_name(src, 1, 1, selected_type)] (?) (PP) (VV) (SM) ([admin_jump_link(mob)]) (CA) (TICKET) [ai_found ? " (CL)" : ""](TAKE) : [msg]" + msg = "[selected_type]: [key_name(src, TRUE, selected_type)] (?) (PP) (VV) (SM) ([admin_jump_link(mob)]) (CA) (TICKET) [ai_found ? " (CL)" : ""](TAKE) : [msg]" //Open a new adminticket and inform the user. globAdminTicketHolder.newTicket(src, prunedmsg, msg) for(var/client/X in modholders + adminholders) diff --git a/code/modules/admin/verbs/adminpm.dm b/code/modules/admin/verbs/adminpm.dm index 4c045e193c8..474b9795b59 100644 --- a/code/modules/admin/verbs/adminpm.dm +++ b/code/modules/admin/verbs/adminpm.dm @@ -88,7 +88,7 @@ //get message text, limit it's length.and clean/escape html if(!msg) - msg = input(src,"Message:", "Private message to [key_name(C, 0, 0)]") as text|null + msg = input(src,"Message:", "Private message to [key_name(C, 0)]") as text|null if(!msg) return @@ -152,9 +152,9 @@ var/emoji_msg = "[msg]" - recieve_message = "[type] from-[recieve_pm_type][key_name(src, C, C.holder ? 1 : 0, type)]: [emoji_msg]" + recieve_message = "[type] from-[recieve_pm_type][key_name(src, TRUE, type)]: [emoji_msg]" to_chat(C, recieve_message) - to_chat(src, "[send_pm_type][type] to-[key_name(C, src, holder ? 1 : 0, type)]: [emoji_msg]") + to_chat(src, "[send_pm_type][type] to-[key_name(C, TRUE, type)]: [emoji_msg]") /*if(holder && !C.holder) C.last_pm_recieved = world.time @@ -175,13 +175,13 @@ switch(type) if("Mentorhelp") if(check_rights(R_ADMIN|R_MOD|R_MENTOR, 0, X.mob)) - to_chat(X, "[type]: [key_name(src, X, 0, type)]->[key_name(C, X, 0, type)]: [emoji_msg]") + to_chat(X, "[type]: [key_name(src, TRUE, type)]->[key_name(C, TRUE, type)]: [emoji_msg]") if("Adminhelp") if(check_rights(R_ADMIN|R_MOD, 0, X.mob)) - to_chat(X, "[type]: [key_name(src, X, 0, type)]->[key_name(C, X, 0, type)]: [emoji_msg]") + to_chat(X, "[type]: [key_name(src, TRUE, type)]->[key_name(C, TRUE, type)]: [emoji_msg]") else if(check_rights(R_ADMIN|R_MOD, 0, X.mob)) - to_chat(X, "[type]: [key_name(src, X, 0, type)]->[key_name(C, X, 0, type)]: [emoji_msg]") + to_chat(X, "[type]: [key_name(src, TRUE, type)]->[key_name(C, TRUE, type)]: [emoji_msg]") //Check if the mob being PM'd has any open admin tickets. var/tickets = list() @@ -226,4 +226,4 @@ if(X == src) continue if(check_rights(R_ADMIN|R_MOD|R_MENTOR, 0, X.mob)) - to_chat(X, "PM: [key_name(src, X, 0)]->IRC-Admins: [msg]") + to_chat(X, "PM: [key_name(src, TRUE, 0)]->IRC-Admins: [msg]") diff --git a/code/modules/admin/verbs/adminsay.dm b/code/modules/admin/verbs/adminsay.dm index cbcacc43006..f091e49f60e 100644 --- a/code/modules/admin/verbs/adminsay.dm +++ b/code/modules/admin/verbs/adminsay.dm @@ -7,7 +7,7 @@ msg = sanitize(copytext(msg, 1, MAX_MESSAGE_LEN)) if(!msg) return - log_admin("[key_name(src)] : [msg]") + log_adminsay(msg, src) if(check_rights(R_ADMIN,0)) for(var/client/C in admins) @@ -25,7 +25,7 @@ return msg = sanitize(copytext(msg, 1, MAX_MESSAGE_LEN)) - log_admin("MENTOR: [key_name(src)] : [msg]") + log_mentorsay(msg, src) if(!msg) return diff --git a/code/modules/admin/verbs/antag-ooc.dm b/code/modules/admin/verbs/antag-ooc.dm index cc33f7948f4..2e0c044c424 100644 --- a/code/modules/admin/verbs/antag-ooc.dm +++ b/code/modules/admin/verbs/antag-ooc.dm @@ -17,4 +17,4 @@ to_chat(M, "AOOC: [display_name]: [msg]") - log_ooc("(ANTAG) [key] : [msg]") + log_aooc(msg, src) diff --git a/code/modules/admin/verbs/freeze.dm b/code/modules/admin/verbs/freeze.dm index 523fe5cb302..9439c63e861 100644 --- a/code/modules/admin/verbs/freeze.dm +++ b/code/modules/admin/verbs/freeze.dm @@ -118,7 +118,7 @@ var/global/list/frozen_mob_list = list() M.addVerb(/obj/mecha/verb/eject) to_chat(M.occupant, "You have been unfrozen by [key]") message_admins("[key_name_admin(usr)] unfroze [key_name(M.occupant)] in a [M.name]") - log_admin("[key_name(usr)] unfroze [M.occupant.name]/[M.occupant.ckey] in a [M.name]") + log_admin("[key_name(usr)] unfroze [key_name(M.occupant)] in a [M.name]") else message_admins("[key_name_admin(usr)] unfroze an empty [M.name]") log_admin("[key_name(usr)] unfroze an empty [M.name]") diff --git a/code/modules/admin/verbs/getlogs.dm b/code/modules/admin/verbs/getlogs.dm index 48507a55352..22c6d778733 100644 --- a/code/modules/admin/verbs/getlogs.dm +++ b/code/modules/admin/verbs/getlogs.dm @@ -14,56 +14,11 @@ */ -//This proc allows Game Masters to grant a client access to the .getruntimelog verb -//Permissions expire at the end of each round. -//Runtimes can be used to meta or spot game-crashing exploits so it's advised to only grant coders that -//you trust access. Also, it may be wise to ensure that they are not going to play in the current round. -/client/proc/giveruntimelog() - set name = ".giveruntimelog" - set desc = "Give somebody access to any session logfiles saved to the /log/runtime/ folder." - set category = null - - if(!src.holder) - to_chat(src, "Only Admins may use this command.") - return - - var/client/target = input(src,"Choose somebody to grant access to the server's runtime logs (permissions expire at the end of each round):","Grant Permissions",null) as null|anything in clients - if(!istype(target,/client)) - to_chat(src, "Error: giveruntimelog(): Client not found.") - return - - target.verbs |= /client/proc/getruntimelog - to_chat(target, "You have been granted access to runtime logs. Please use them responsibly or risk being banned.") - return - - -//This proc allows download of runtime logs saved within the data/logs/ folder by dreamdeamon. -//It works similarly to show-server-log. -/client/proc/getruntimelog() - set name = ".getruntimelog" - set desc = "Retrieve any session logfiles saved by dreamdeamon." - set category = null - - var/path = browse_files("data/logs/runtime/") - if(!path) - return - - if(file_spam_check()) - return - - message_admins("[key_name_admin(src)] accessed file: [path]") - src << ftp(file(path)) - - to_chat(src, "Attempting to send file, this may take a fair few minutes if the file is very large.") - return - - //This proc allows download of past server logs saved within the data/logs/ folder. -//It works similarly to show-server-log. -/client/proc/getserverlog() - set name = ".getserverlog" - set desc = "Fetch logfiles from data/logs" - set category = null +/client/proc/getserverlogs() + set name = "Get Server Logs" + set desc = "View/retrieve logfiles." + set category = "Admin" var/path = browse_files("data/logs/") if(!path) @@ -73,44 +28,14 @@ return message_admins("[key_name_admin(src)] accessed file: [path]") - src << ftp(file(path)) - - to_chat(src, "Attempting to send file, this may take a fair few minutes if the file is very large.") - return - - -//Other log stuff put here for the sake of organisation - -//Shows today's server log -/datum/admins/proc/view_txt_log() - set category = "Admin" - set name = "Show Server Log" - set desc = "Shows today's server log." - - var/path = "data/logs/[time2text(world.realtime,"YYYY/MM-Month/DD-Day")].log" - if( fexists(path) ) - src << ftp(file(path)) - - else - to_chat(src, "Error: view_txt_log(): File not found/Invalid path([path]).") - return - feedback_add_details("admin_verb","VTL") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! - return - -//Shows today's attack log -/datum/admins/proc/view_atk_log() - set category = "Admin" - set name = "Show Server Attack Log" - set desc = "Shows today's server attack log." - - var/path = "data/logs/[time2text(world.realtime,"YYYY/MM-Month/DD-Day")] Attack.log" - if( fexists(path) ) - src << ftp(file(path)) - - else - to_chat(src, "Error: view_atk_log(): File not found/Invalid path([path]).") - return - usr << run(file(path)) - - feedback_add_details("admin_verb","SSAL") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! - return + switch(alert("View (in game), Open (in your system's text editor), or Download?", path, "View", "Open", "Download")) + if ("View") + src << browse("
[html_encode(file2text(file(path)))]
", list2params(list("window" = "viewfile.[path]"))) + if ("Open") + src << run(file(path)) + if ("Download") + src << ftp(file(path)) + else + return + to_chat(src, "Attempting to send [path], this may take a fair few minutes if the file is very large.") + return \ No newline at end of file diff --git a/code/modules/admin/verbs/massmodvar.dm b/code/modules/admin/verbs/massmodvar.dm index 084057498bb..b26a27b3aa6 100644 --- a/code/modules/admin/verbs/massmodvar.dm +++ b/code/modules/admin/verbs/massmodvar.dm @@ -201,7 +201,7 @@ if(rejected) to_chat(src, "[rejected] out of [count] objects rejected your edit") - log_to_dd("### MassVarEdit by [src]: [O.type] (A/R [accepted]/[rejected]) [variable]=[html_encode("[O.vars[variable]]")]([list2params(value)])") + log_world("### MassVarEdit by [src]: [O.type] (A/R [accepted]/[rejected]) [variable]=[html_encode("[O.vars[variable]]")]([list2params(value)])") log_admin("[key_name(src)] mass modified [original_name]'s [variable] to [O.vars[variable]] ([accepted] objects modified)") message_admins("[key_name_admin(src)] mass modified [original_name]'s [variable] to [O.vars[variable]] ([accepted] objects modified)") diff --git a/code/modules/admin/verbs/modifyvariables.dm b/code/modules/admin/verbs/modifyvariables.dm index 55ce03d8988..dfca07426c5 100644 --- a/code/modules/admin/verbs/modifyvariables.dm +++ b/code/modules/admin/verbs/modifyvariables.dm @@ -342,7 +342,7 @@ var/list/VVpixelmovement = list("step_x", "step_y", "step_size", "bound_height", if(!O.vv_edit_var(objectvar, L)) to_chat(src, "Your edit was rejected by the object.") return - log_to_dd("### ListVarEdit by [src]: [(O ? O.type : "/list")] [objectvar]: ADDED=[var_value]") + log_world("### ListVarEdit by [src]: [(O ? O.type : "/list")] [objectvar]: ADDED=[var_value]") log_admin("[key_name(src)] modified [original_name]'s [objectvar]: ADDED=[var_value]") message_admins("[key_name_admin(src)] modified [original_name]'s [objectvar]: ADDED=[var_value]") @@ -385,7 +385,7 @@ var/list/VVpixelmovement = list("step_x", "step_y", "step_size", "bound_height", if(!O.vv_edit_var(objectvar, L)) to_chat(src, "Your edit was rejected by the object.") return - log_to_dd("### ListVarEdit by [src]: [O.type] [objectvar]: CLEAR NULLS") + log_world("### ListVarEdit by [src]: [O.type] [objectvar]: CLEAR NULLS") log_admin("[key_name(src)] modified [original_name]'s [objectvar]: CLEAR NULLS") message_admins("[key_name_admin(src)] modified [original_name]'s list [objectvar]: CLEAR NULLS") return @@ -395,7 +395,7 @@ var/list/VVpixelmovement = list("step_x", "step_y", "step_size", "bound_height", if(!O.vv_edit_var(objectvar, L)) to_chat(src, "Your edit was rejected by the object.") return - log_to_dd("### ListVarEdit by [src]: [O.type] [objectvar]: CLEAR DUPES") + log_world("### ListVarEdit by [src]: [O.type] [objectvar]: CLEAR DUPES") log_admin("[key_name(src)] modified [original_name]'s [objectvar]: CLEAR DUPES") message_admins("[key_name_admin(src)] modified [original_name]'s list [objectvar]: CLEAR DUPES") return @@ -405,7 +405,7 @@ var/list/VVpixelmovement = list("step_x", "step_y", "step_size", "bound_height", if(!O.vv_edit_var(objectvar, L)) to_chat(src, "Your edit was rejected by the object.") return - log_to_dd("### ListVarEdit by [src]: [O.type] [objectvar]: SHUFFLE") + log_world("### ListVarEdit by [src]: [O.type] [objectvar]: SHUFFLE") log_admin("[key_name(src)] modified [original_name]'s [objectvar]: SHUFFLE") message_admins("[key_name_admin(src)] modified [original_name]'s list [objectvar]: SHUFFLE") return @@ -482,7 +482,7 @@ var/list/VVpixelmovement = list("step_x", "step_y", "step_size", "bound_height", if(!O.vv_edit_var(objectvar, L)) to_chat(src, "Your edit was rejected by the object.") return - log_to_dd("### ListVarEdit by [src]: [O.type] [objectvar]: REMOVED=[html_encode("[original_var]")]") + log_world("### ListVarEdit by [src]: [O.type] [objectvar]: REMOVED=[html_encode("[original_var]")]") log_admin("[key_name(src)] modified [original_name]'s [objectvar]: REMOVED=[original_var]") message_admins("[key_name_admin(src)] modified [original_name]'s [objectvar]: REMOVED=[original_var]") return @@ -501,7 +501,7 @@ var/list/VVpixelmovement = list("step_x", "step_y", "step_size", "bound_height", if(!O.vv_edit_var(objectvar, L)) to_chat(src, "Your edit was rejected by the object.") return - log_to_dd("### ListVarEdit by [src]: [(O ? O.type : "/list")] [objectvar]: [original_var]=[new_var]") + log_world("### ListVarEdit by [src]: [(O ? O.type : "/list")] [objectvar]: [original_var]=[new_var]") log_admin("[key_name(src)] modified [original_name]'s [objectvar]: [original_var]=[new_var]") message_admins("[key_name_admin(src)] modified [original_name]'s varlist [objectvar]: [original_var]=[new_var]") @@ -612,7 +612,7 @@ var/list/VVpixelmovement = list("step_x", "step_y", "step_size", "bound_height", if(!O.vv_edit_var(variable, var_new)) to_chat(src, "Your edit was rejected by the object.") return - log_to_dd("### VarEdit by [src]: [O.type] [variable]=[html_encode("[var_new]")]") + log_world("### VarEdit by [src]: [O.type] [variable]=[html_encode("[var_new]")]") log_admin("[key_name(src)] modified [original_name]'s [variable] to [var_new]") var/msg = "[key_name_admin(src)] modified [original_name]'s [variable] to [var_new]" message_admins(msg) diff --git a/code/modules/assembly/bomb.dm b/code/modules/assembly/bomb.dm index 3f52862536d..9b230e6e742 100644 --- a/code/modules/assembly/bomb.dm +++ b/code/modules/assembly/bomb.dm @@ -47,6 +47,7 @@ status = 1 bombers += "[key_name(user)] welded a single tank bomb. Temperature: [bombtank.air_contents.temperature-T0C]" msg_admin_attack("[key_name_admin(user)] welded a single tank bomb. Temperature: [bombtank.air_contents.temperature-T0C]") + log_game("[key_name(user)] welded a single tank bomb. Temperature: [bombtank.air_contents.temperature - T0C]") to_chat(user, "A pressure hole has been bored to [bombtank] valve. \The [bombtank] can now be ignited.") else status = 0 diff --git a/code/modules/awaymissions/maploader/swapmaps.dm b/code/modules/awaymissions/maploader/swapmaps.dm index bff9df153ef..bdb15581b61 100644 --- a/code/modules/awaymissions/maploader/swapmaps.dm +++ b/code/modules/awaymissions/maploader/swapmaps.dm @@ -584,7 +584,7 @@ proc/SwapMaps_CreateFromTemplate(template_id) else if(swapmaps_mode!=SWAPMAPS_TEXT && fexists("map_[template_id].txt")) text=1 else - log_to_dd("SwapMaps error in SwapMaps_CreateFromTemplate(): map_[template_id] file not found.") + log_world("SwapMaps error in SwapMaps_CreateFromTemplate(): map_[template_id] file not found.") return if(text) S=new @@ -611,7 +611,7 @@ proc/SwapMaps_LoadChunk(chunk_id,turf/locorner) else if(swapmaps_mode!=SWAPMAPS_TEXT && fexists("map_[chunk_id].txt")) text=1 else - log_to_dd("SwapMaps error in SwapMaps_LoadChunk(): map_[chunk_id] file not found.") + log_world("SwapMaps error in SwapMaps_LoadChunk(): map_[chunk_id] file not found.") return if(text) S=new @@ -629,9 +629,9 @@ proc/SwapMaps_LoadChunk(chunk_id,turf/locorner) proc/SwapMaps_SaveChunk(chunk_id,turf/corner1,turf/corner2) if(!corner1 || !corner2) - log_to_dd("SwapMaps error in SwapMaps_SaveChunk():") - if(!corner1) log_to_dd(" corner1 turf is null") - if(!corner2) log_to_dd(" corner2 turf is null") + log_world("SwapMaps error in SwapMaps_SaveChunk():") + if(!corner1) log_world(" corner1 turf is null") + if(!corner2) log_world(" corner2 turf is null") return var/swapmap/M=new M.id=chunk_id @@ -658,7 +658,7 @@ proc/SwapMaps_GetSize(id) else if(swapmaps_mode!=SWAPMAPS_TEXT && fexists("map_[id].txt")) text=1 else - log_to_dd("SwapMaps error in SwapMaps_GetSize(): map_[id] file not found.") + log_world("SwapMaps error in SwapMaps_GetSize(): map_[id] file not found.") return if(text) S=new diff --git a/code/modules/awaymissions/zlevel.dm b/code/modules/awaymissions/zlevel.dm index f946c63e76c..65220b0b754 100644 --- a/code/modules/awaymissions/zlevel.dm +++ b/code/modules/awaymissions/zlevel.dm @@ -57,7 +57,7 @@ var/global/list/potentialRandomZlevels = generateMapList(filename = "config/away maploader.load_map(file, z_offset = zlev) late_setup_level(block(locate(1, 1, zlev), locate(world.maxx, world.maxy, zlev))) space_manager.remove_dirt(zlev) - log_to_dd(" Away mission loaded: [map]") + log_world(" Away mission loaded: [map]") for(var/obj/effect/landmark/L in landmarks_list) if(L.name != "awaystart") @@ -88,7 +88,7 @@ var/global/list/potentialRandomZlevels = generateMapList(filename = "config/away maploader.load_map(file, z_offset = zlev) late_setup_level(block(locate(1, 1, zlev), locate(world.maxx, world.maxy, zlev))) space_manager.remove_dirt(zlev) - log_to_dd(" Away mission loaded: [map]") + log_world(" Away mission loaded: [map]") //map_transition_config.Add(AWAY_MISSION_LIST) @@ -168,7 +168,7 @@ var/global/list/potentialRandomZlevels = generateMapList(filename = "config/away if(!valid) continue - log_to_dd(" Ruin \"[ruin.name]\" loaded in [stop_watch(watch)]s at ([T.x], [T.y], [T.z]).") + log_world(" Ruin \"[ruin.name]\" loaded in [stop_watch(watch)]s at ([T.x], [T.y], [T.z]).") var/obj/effect/ruin_loader/R = new /obj/effect/ruin_loader(T) R.Load(ruins,ruin) @@ -179,7 +179,7 @@ var/global/list/potentialRandomZlevels = generateMapList(filename = "config/away if(initialbudget == budget) //Kill me - log_to_dd(" No ruins loaded.") + log_world(" No ruins loaded.") /obj/effect/ruin_loader diff --git a/code/modules/client/client procs.dm b/code/modules/client/client procs.dm index 9b30cc9e599..838670221ad 100644 --- a/code/modules/client/client procs.dm +++ b/code/modules/client/client procs.dm @@ -65,7 +65,7 @@ //search the href for script injection if( findtext(href,"[time2text(world.timeofday,"hh:mm")] [src] (usr:[usr]) || [hsrc ? "[hsrc] " : ""][href]
") + if(config && config.log_hrefs) + log_href("[src] (usr:[usr]\[[COORD(usr)]\]) : [hsrc ? "[hsrc] " : ""][href]") if(href_list["karmashop"]) if(config.disable_karma) @@ -559,7 +559,7 @@ //Log all the alts if(related_accounts_cid.len) - log_access("Alts: [key_name(src)]:[jointext(related_accounts_cid, " - ")]") + log_admin("[key_name(src)] alts:[jointext(related_accounts_cid, " - ")]") var/watchreason = check_watchlist(ckey) @@ -668,7 +668,7 @@ cidcheck_failedckeys[ckey] = TRUE note_randomizer_user() - log_access("Failed Login: [key] [computer_id] [address] - CID randomizer confirmed (oldcid: [oldcid])") + log_adminwarn("Failed Login: [key] [computer_id] [address] - CID randomizer confirmed (oldcid: [oldcid])") del(src) return TRUE @@ -710,7 +710,7 @@ /client/proc/cid_check_reconnect() var/token = md5("[rand(0,9999)][world.time][rand(0,9999)][ckey][rand(0,9999)][address][rand(0,9999)][computer_id][rand(0,9999)]") . = token - log_access("Failed Login: [key] [computer_id] [address] - CID randomizer check") + log_adminwarn("Failed Login: [key] [computer_id] [address] - CID randomizer check") var/url = winget(src, null, "url") //special javascript to make them reconnect under a new window. src << browse("\ diff --git a/code/modules/detective_work/detective_work.dm b/code/modules/detective_work/detective_work.dm index cc53bacc956..69ee566124e 100644 --- a/code/modules/detective_work/detective_work.dm +++ b/code/modules/detective_work/detective_work.dm @@ -17,19 +17,19 @@ atom/proc/add_fibers(mob/living/carbon/human/M) if(M.wear_suit) fibertext = "Material from \a [M.wear_suit]." if(prob(10*item_multiplier) && !(fibertext in suit_fibers) && M.wear_suit.can_leave_fibers) - //log_to_dd("Added fibertext: [fibertext]") + //log_world("Added fibertext: [fibertext]") suit_fibers += fibertext if(!(M.wear_suit.body_parts_covered & UPPER_TORSO)) if(M.w_uniform) fibertext = "Fibers from \a [M.w_uniform]." if(prob(12*item_multiplier) && !(fibertext in suit_fibers) && M.w_uniform.can_leave_fibers) //Wearing a suit means less of the uniform exposed. - //log_to_dd("Added fibertext: [fibertext]") + //log_world("Added fibertext: [fibertext]") suit_fibers += fibertext if(!(M.wear_suit.body_parts_covered & HANDS)) if(M.gloves) fibertext = "Material from a pair of [M.gloves.name]." if(prob(20*item_multiplier) && !(fibertext in suit_fibers) && M.gloves.can_leave_fibers) - //log_to_dd("Added fibertext: [fibertext]") + //log_world("Added fibertext: [fibertext]") suit_fibers += fibertext else if(M.w_uniform) fibertext = "Fibers from \a [M.w_uniform]." @@ -39,10 +39,10 @@ atom/proc/add_fibers(mob/living/carbon/human/M) if(M.gloves) fibertext = "Material from a pair of [M.gloves.name]." if(prob(20*item_multiplier) && !(fibertext in suit_fibers) && M.gloves.can_leave_fibers) - //log_to_dd("Added fibertext: [fibertext]") + //log_world("Added fibertext: [fibertext]") suit_fibers += "Material from a pair of [M.gloves.name]." else if(M.gloves) fibertext = "Material from a pair of [M.gloves.name]." if(prob(20*item_multiplier) && !(fibertext in suit_fibers) && M.gloves.can_leave_fibers) - //log_to_dd("Added fibertext: [fibertext]") + //log_world("Added fibertext: [fibertext]") suit_fibers += "Material from a pair of [M.gloves.name]." diff --git a/code/modules/error_handler/error_handler.dm b/code/modules/error_handler/error_handler.dm index 430ac0fccb1..a527367ee2b 100644 --- a/code/modules/error_handler/error_handler.dm +++ b/code/modules/error_handler/error_handler.dm @@ -8,7 +8,7 @@ var/total_runtimes_skipped = 0 #ifdef DEBUG /world/Error(var/exception/e, var/datum/e_src) if(!istype(e)) // Something threw an unusual exception - log_to_dd("\[[time_stamp()]] Uncaught exception: [e]") + log_world("\[[time_stamp()]] Uncaught exception: [e]") return ..() if(!error_last_seen) // A runtime is occurring too early in start-up initialization return ..() @@ -39,7 +39,7 @@ var/total_runtimes_skipped = 0 var/skipcount = abs(error_cooldown[erroruid]) - 1 error_cooldown[erroruid] = 0 if(skipcount > 0) - log_to_dd("\[[time_stamp()]] Skipped [skipcount] runtimes in [e.file],[e.line].") + log_world("\[[time_stamp()]] Skipped [skipcount] runtimes in [e.file],[e.line].") error_cache.logError(e, skipCount = skipcount) error_last_seen[erroruid] = world.time error_cooldown[erroruid] = cooldown @@ -95,12 +95,13 @@ var/total_runtimes_skipped = 0 desclines += " (This error will now be silenced for [ERROR_SILENCE_TIME / 600] minutes)" // Now to actually output the error info... - log_to_dd("\[[time_stamp()]] Runtime in [e.file],[e.line]: [e]") + log_world("\[[time_stamp()]] Runtime in [e.file],[e.line]: [e]") + log_runtime_txt("\[[time_stamp()]] Runtime in [e.file],[e.line]: [e]") for(var/line in desclines) - log_to_dd(line) + log_world(line) + log_runtime_txt(line) if(error_cache) error_cache.logError(e, desclines, e_src = e_src) - #endif /proc/log_runtime(exception/e, datum/e_src, extra_info) diff --git a/code/modules/food_and_drinks/drinks/drinks/bottle.dm b/code/modules/food_and_drinks/drinks/drinks/bottle.dm index ec79d13890c..a7274c53f4e 100644 --- a/code/modules/food_and_drinks/drinks/drinks/bottle.dm +++ b/code/modules/food_and_drinks/drinks/drinks/bottle.dm @@ -106,7 +106,7 @@ "[target] hits \himself with a bottle of [name][head_attack_message]!") //Attack logs - add_logs(user, target, "attacked", src) + add_attack_logs(user, target, "Hit with [src]") //The reagents in the bottle splash all over the target, thanks for the idea Nodrak SplashReagents(target) diff --git a/code/modules/food_and_drinks/food/condiment.dm b/code/modules/food_and_drinks/food/condiment.dm index b589e0eec24..f9ec698f196 100644 --- a/code/modules/food_and_drinks/food/condiment.dm +++ b/code/modules/food_and_drinks/food/condiment.dm @@ -47,7 +47,7 @@ if(!reagents || !reagents.total_volume) return // The condiment might be empty after the delay. user.visible_message("[user] feeds [M] from [src].") - add_logs(user, M, "fed", reagentlist(src)) + add_attack_logs(user, M, "Fed [src] containing [reagentlist(src)]") var/fraction = min(10/reagents.total_volume, 1) reagents.reaction(M, INGEST, fraction) diff --git a/code/modules/food_and_drinks/kitchen_machinery/deep_fryer.dm b/code/modules/food_and_drinks/kitchen_machinery/deep_fryer.dm index 13f100b6a3d..b4a787ea4c8 100644 --- a/code/modules/food_and_drinks/kitchen_machinery/deep_fryer.dm +++ b/code/modules/food_and_drinks/kitchen_machinery/deep_fryer.dm @@ -59,7 +59,7 @@ user.changeNext_move(CLICK_CD_MELEE) C.apply_damage(25, BURN, "head") //25 fire damage and disfigurement because your face was just deep fried! head.disfigure("burn") - add_logs(user, G.affecting, "deep-fried", addition="'s face") + add_attack_logs(user, G.affecting, "Deep-fried with [src]") qdel(G) //Removes the grip so the person MIGHT have a small chance to run the fuck away and to prevent rapid dunks. return 0 return 0 diff --git a/code/modules/food_and_drinks/kitchen_machinery/gibber.dm b/code/modules/food_and_drinks/kitchen_machinery/gibber.dm index 7c3a6407808..0c2af905a74 100644 --- a/code/modules/food_and_drinks/kitchen_machinery/gibber.dm +++ b/code/modules/food_and_drinks/kitchen_machinery/gibber.dm @@ -221,7 +221,8 @@ return if(UserOverride) - msg_admin_attack("[key_name_admin(occupant)] was gibbed by an autogibber (\the [src]) (JMP)") + msg_admin_attack("[key_name_admin(occupant)] was gibbed by an autogibber (\the [src]) [ADMIN_JMP(src)]") + log_game("[key_name(occupant)] was gibbed by an autogibber ([src]) (X:[x] Y:[y] Z:[z])") if(operating) return @@ -259,11 +260,7 @@ new /obj/effect/decal/cleanable/blood/gibs(src) if(!UserOverride) - occupant.create_attack_log("Was gibbed by [key_name(user)]") //One shall not simply gib a mob unnoticed!) - user.create_attack_log("Gibbed [key_name(occupant)]") - - if(occupant.ckey) - msg_admin_attack("[key_name_admin(user)] gibbed [key_name_admin(occupant)]") + add_attack_logs(user, occupant, "Gibbed in [src]", !!occupant.ckey) if(!iscarbon(user)) occupant.LAssailant = null @@ -275,7 +272,7 @@ occupant.emote("scream") playsound(get_turf(src), 'sound/goonstation/effects/gib.ogg', 50, 1) - victims += "\[[time_stamp()]\] [occupant.name] ([occupant.ckey]) killed by [UserOverride ? "Autogibbing" : "[user] ([user.ckey])"]" //have to do this before ghostizing + victims += "\[[time_stamp()]\] [key_name(occupant)] killed by [UserOverride ? "Autogibbing" : "[key_name(user)]"]" //have to do this before ghostizing occupant.death(1) occupant.ghostize() diff --git a/code/modules/food_and_drinks/kitchen_machinery/grill_new.dm b/code/modules/food_and_drinks/kitchen_machinery/grill_new.dm index 7d926053cdc..c1b2612533d 100644 --- a/code/modules/food_and_drinks/kitchen_machinery/grill_new.dm +++ b/code/modules/food_and_drinks/kitchen_machinery/grill_new.dm @@ -55,7 +55,7 @@ C.emote("scream") user.changeNext_move(CLICK_CD_MELEE) C.adjustFireLoss(30) - add_logs(user, G.affecting, "burned", src) + add_attack_logs(user, G.affecting, "Burned with [src]") qdel(G) //Removes the grip to prevent rapid sears and give you a chance to run return 0 return 0 \ No newline at end of file diff --git a/code/modules/food_and_drinks/kitchen_machinery/oven_new.dm b/code/modules/food_and_drinks/kitchen_machinery/oven_new.dm index cde9a0ed27e..4904a2a5d5f 100644 --- a/code/modules/food_and_drinks/kitchen_machinery/oven_new.dm +++ b/code/modules/food_and_drinks/kitchen_machinery/oven_new.dm @@ -61,7 +61,7 @@ C.apply_damage(5, BURN, "head") //5 fire damage, 15 brute damage, and weakening because your head was just in a hot oven with the door bashing into your neck! C.apply_damage(15, BRUTE, "head") C.Weaken(2) - add_logs(user, G.affecting, "smashed", addition="'s head on [src]") + add_attack_logs(user, G.affecting, "Smashed with [src]") qdel(G) //Removes the grip to prevent rapid bashes. With the weaken, you PROBABLY can't run unless they are slow to grab you again... return 0 return 0 diff --git a/code/modules/hydroponics/grown/nettle.dm b/code/modules/hydroponics/grown/nettle.dm index 1147932692c..c65c9dcf618 100644 --- a/code/modules/hydroponics/grown/nettle.dm +++ b/code/modules/hydroponics/grown/nettle.dm @@ -104,7 +104,7 @@ ..() if(isliving(M)) to_chat(M, "You are stunned by the powerful acid of the Deathnettle!") - add_logs(user, M, "attacked", src) + add_attack_logs(user, M, "Hit with [src]") M.AdjustEyeBlurry(force/7) if(prob(20)) diff --git a/code/modules/hydroponics/hydroponics.dm b/code/modules/hydroponics/hydroponics.dm index 3bb535eeb07..416c712f2f7 100644 --- a/code/modules/hydroponics/hydroponics.dm +++ b/code/modules/hydroponics/hydroponics.dm @@ -799,7 +799,7 @@ else if(istype(O, /obj/item/seeds) && !istype(O, /obj/item/seeds/sample)) if(!myseed) if(istype(O, /obj/item/seeds/kudzu)) - investigate_log("had Kudzu planted in it by [user.ckey]([user]) at ([x],[y],[z])","kudzu") + investigate_log("had Kudzu planted in it by [key_name(user)] at ([x],[y],[z])","kudzu") user.unEquip(O) to_chat(user, "You plant [O].") dead = 0 diff --git a/code/modules/karma/karma.dm b/code/modules/karma/karma.dm index b5cdbe0154f..e9265c15b4a 100644 --- a/code/modules/karma/karma.dm +++ b/code/modules/karma/karma.dm @@ -136,7 +136,7 @@ var/list/karma_spenders = list() var/special_role = "None" var/assigned_role = "None" - var/karma_diary = file("data/logs/karma_[time2text(world.realtime, "YYYY/MM-Month/DD-Day")].log") + var/karma_diary = file("[GLOB.log_directory]/karma.log") if(M.mind) if(M.mind.special_role) special_role = M.mind.special_role diff --git a/code/modules/library/computers/base.dm b/code/modules/library/computers/base.dm index c955f91a6a0..5bb8019cd58 100644 --- a/code/modules/library/computers/base.dm +++ b/code/modules/library/computers/base.dm @@ -50,7 +50,7 @@ var/DBQuery/_query = dbcon.NewQuery(sql) _query.Execute() if(_query.ErrorMsg()) - log_to_dd(_query.ErrorMsg()) + log_world(_query.ErrorMsg()) var/list/results = list() while(_query.NextRow()) diff --git a/code/modules/library/computers/checkout.dm b/code/modules/library/computers/checkout.dm index 4d060f274a5..0f0774aa1f4 100644 --- a/code/modules/library/computers/checkout.dm +++ b/code/modules/library/computers/checkout.dm @@ -263,7 +263,7 @@ if(!response) to_chat(usr, query.ErrorMsg()) return - log_admin("LIBRARY: [usr.name]/[usr.key] has deleted \"[target.title]\", by [target.author] ([target.ckey])!") + log_admin("LIBRARY: [key_name(usr)] has deleted \"[target.title]\", by [target.author] ([target.ckey])!") message_admins("[key_name_admin(usr)] has deleted \"[target.title]\", by [target.author] ([target.ckey])!") src.updateUsrDialog() return @@ -283,7 +283,7 @@ if(affected==0) to_chat(usr, "Unable to find any matching rows.") return - log_admin("LIBRARY: [usr.name]/[usr.key] has deleted [affected] books written by [tckey]!") + log_admin("LIBRARY: [key_name(usr)] has deleted [affected] books written by [tckey]!") message_admins("[key_name_admin(usr)] has deleted [affected] books written by [tckey]!") src.updateUsrDialog() return diff --git a/code/modules/martial_arts/brawling.dm b/code/modules/martial_arts/brawling.dm index a3f512bfb0d..9f9fa5236b2 100644 --- a/code/modules/martial_arts/brawling.dm +++ b/code/modules/martial_arts/brawling.dm @@ -19,7 +19,7 @@ if(!damage) playsound(D.loc, 'sound/weapons/punchmiss.ogg', 25, 1, -1) D.visible_message("[A] has attempted to hit [D] with a [atk_verb]!") - add_logs(A, D, "attempted to hit", atk_verb) + add_attack_logs(A, D, "Melee attacked with [src] (miss/block)") return 0 @@ -32,7 +32,7 @@ "[A] has hit [D] with a [atk_verb]!") D.apply_damage(damage, STAMINA, affecting, armor_block) - add_logs(A, D, "punched") + add_attack_logs(A, D, "Melee attacked with [src]") if(D.getStaminaLoss() > 50) var/knockout_prob = D.getStaminaLoss() + rand(-15,15) if((D.stat != DEAD) && prob(knockout_prob)) @@ -61,7 +61,7 @@ return 1 /datum/martial_art/drunk_brawling/harm_act(var/mob/living/carbon/human/A, var/mob/living/carbon/human/D) - add_logs(A, D, "punched") + add_attack_logs(A, D, "Melee attacked with [src]") A.do_attack_animation(D) var/atk_verb = pick("jab","uppercut","overhand punch","drunken right hook","drunken left hook") diff --git a/code/modules/martial_arts/krav_maga.dm b/code/modules/martial_arts/krav_maga.dm index 1a3bba05140..d17d1b30495 100644 --- a/code/modules/martial_arts/krav_maga.dm +++ b/code/modules/martial_arts/krav_maga.dm @@ -108,7 +108,7 @@ datum/martial_art/krav_maga/grab_act(var/mob/living/carbon/human/A, var/mob/livi /datum/martial_art/krav_maga/harm_act(var/mob/living/carbon/human/A, var/mob/living/carbon/human/D) if(check_streak(A,D)) return 1 - add_logs(A, D, "punched") + add_attack_logs(A, D, "Melee attacked with [src]") A.do_attack_animation(D) var/picked_hit_type = pick("punches", "kicks") var/bonus_damage = 10 diff --git a/code/modules/martial_arts/martial.dm b/code/modules/martial_arts/martial.dm index 12eecb6300c..29c6044e386 100644 --- a/code/modules/martial_arts/martial.dm +++ b/code/modules/martial_arts/martial.dm @@ -55,7 +55,7 @@ D.apply_damage(damage, BRUTE, affecting, armor_block) - add_logs(A, D, "punched") + add_attack_logs(A, D, "Melee attacked with [src]") if((D.stat != DEAD) && damage >= A.species.punchstunthreshold) D.visible_message("[A] has weakened [D]!!", \ diff --git a/code/modules/martial_arts/mimejutsu.dm b/code/modules/martial_arts/mimejutsu.dm index 23a1585efdb..4d8edbf7236 100644 --- a/code/modules/martial_arts/mimejutsu.dm +++ b/code/modules/martial_arts/mimejutsu.dm @@ -38,7 +38,7 @@ playsound(get_turf(A), 'sound/weapons/thudswoosh.ogg', 50, 1, -1) D.apply_damage(damage, STAMINA, affecting, armor_block) - add_logs(A, D, "mimechucked") + add_attack_logs(A, D, "Melee attacked with [src] (mimechuck)") return 1 return basic_hit(A,D) diff --git a/code/modules/martial_arts/wrestleing.dm b/code/modules/martial_arts/wrestleing.dm index 07c5d62d12b..e9dfd9c02a8 100644 --- a/code/modules/martial_arts/wrestleing.dm +++ b/code/modules/martial_arts/wrestleing.dm @@ -28,7 +28,7 @@ var/armor_block = D.run_armor_check(null, "melee") D.apply_damage(30, BRUTE, null, armor_block) D.apply_effect(6, WEAKEN, armor_block) - add_logs(A, D, "suplexed") + add_attack_logs(A, D, "Melee attacked with [src] (SUPLEX)") A.SpinAnimation(10,1) diff --git a/code/modules/mining/equipment_locker.dm b/code/modules/mining/equipment_locker.dm index 87a8465dcc1..9306eec9829 100644 --- a/code/modules/mining/equipment_locker.dm +++ b/code/modules/mining/equipment_locker.dm @@ -682,7 +682,7 @@ playsound(src,'sound/weapons/resonator_blast.ogg',50,1) if(creator) for(var/mob/living/L in src.loc) - add_logs(creator, L, "used a resonator field on", object="resonator") + add_attack_logs(creator, L, "Resonance field'ed") to_chat(L, "The [src.name] ruptured with you in it!") L.adjustBruteLoss(resonance_damage) else diff --git a/code/modules/mining/lavaland/loot/hierophant_loot.dm b/code/modules/mining/lavaland/loot/hierophant_loot.dm index 052887d15af..62d72d4a0a9 100644 --- a/code/modules/mining/lavaland/loot/hierophant_loot.dm +++ b/code/modules/mining/lavaland/loot/hierophant_loot.dm @@ -28,7 +28,7 @@ if(proximity_flag) spawn(0) aoe_burst(T, user) - add_logs(user, target, "fired 3x3 blast at", src) + add_attack_logs(user, target, "Fired 3x3 blast at [src]") else if(ismineralturf(target) && get_dist(user, target) < 6) //target is minerals, we can hit it(even if we can't see it) spawn(0) @@ -39,11 +39,11 @@ if(isliving(target) && chaser_timer <= world.time) //living and chasers off cooldown? fire one! chaser_timer = world.time + chaser_cooldown new /obj/effect/temp_visual/hierophant/chaser(get_turf(user), user, target, 1.5, friendly_fire_check) - add_logs(user, target, "fired a chaser at", src) + add_attack_logs(user, target, "Fired a chaser at [src]") else spawn(0) cardinal_blasts(T, user) //otherwise, just do cardinal blast - add_logs(user, target, "fired cardinal blast at", src) + add_attack_logs(user, target, "Fired cardinal blast at [src]") else to_chat(user, "That target is out of range!") //too far away @@ -109,7 +109,7 @@ to_chat(user, "The rune is blocked by something, preventing teleportation!") user.update_action_buttons_icon() return - add_logs(user, rune, "teleported self from ([source.x],[source.y],[source.z]) to") + add_attack_logs(user, rune, "Teleported self from ([source.x],[source.y],[source.z]) to ([T.x],[T.y],[T.z])") new /obj/effect/temp_visual/hierophant/telegraph/teleport(T, user) new /obj/effect/temp_visual/hierophant/telegraph/teleport(source, user) for(var/t in RANGE_TURFS(1, T)) @@ -150,7 +150,7 @@ return M.visible_message("[M] fades in!") if(user != M) - add_logs(user, M, "teleported", null, "from ([source.x],[source.y],[source.z])") + add_attack_logs(user, M, "Teleported from ([source.x],[source.y],[source.z])") /obj/item/hierophant_staff/proc/cardinal_blasts(turf/T, mob/living/user) //fire cardinal cross blasts with a delay if(!T) diff --git a/code/modules/mob/dead/observer/say.dm b/code/modules/mob/dead/observer/say.dm index 82e8c620192..b780ac0d381 100644 --- a/code/modules/mob/dead/observer/say.dm +++ b/code/modules/mob/dead/observer/say.dm @@ -4,7 +4,7 @@ if(!message) return - log_say("Ghost/[src.key] : [message]") + log_ghostsay(message, src) if(src.client) if(src.client.prefs.muted & MUTE_DEADCHAT) @@ -26,7 +26,7 @@ if(act != "me") return - log_emote("Ghost/[src.key] : [message]") + log_ghostemote(message, src) if(src.client) if(src.client.prefs.muted & MUTE_DEADCHAT) diff --git a/code/modules/mob/emote.dm b/code/modules/mob/emote.dm index 6f81d13e816..623f5b6b353 100644 --- a/code/modules/mob/emote.dm +++ b/code/modules/mob/emote.dm @@ -46,7 +46,7 @@ if(message) - log_emote("[name]/[key] : [message]") + log_emote(message, src) //Hearing gasp and such every five seconds is not good emotes were not global for a reason. // Maybe some people are okay with that. @@ -94,7 +94,6 @@ O.show_message(message, m_type) /mob/proc/emote_dead(var/message) - if(client.prefs.muted & MUTE_DEADCHAT) to_chat(src, "You cannot send deadchat emotes (muted).") return @@ -122,8 +121,6 @@ if(message) - log_emote("Ghost/[src.key] : [message]") - for(var/mob/M in player_list) if(istype(M, /mob/new_player)) continue diff --git a/code/modules/mob/language.dm b/code/modules/mob/language.dm index 6d6558463e1..dc2e8ee7106 100644 --- a/code/modules/mob/language.dm +++ b/code/modules/mob/language.dm @@ -99,7 +99,7 @@ if(!check_can_speak(speaker)) return FALSE - log_say("[key_name(speaker)]: ([name]) [message]") + log_say("([name]-HIVE) [message]", speaker) if(!speaker_mask) speaker_mask = speaker.name @@ -553,14 +553,13 @@ var/drone_only /datum/language/binary/broadcast(mob/living/speaker, message, speaker_mask) - if(!speaker.binarycheck()) return if(!message) return - log_robot("[key_name(speaker)] : [message]") + log_say("(ROBOT) [message]", speaker) var/message_start = "[name], [speaker.name]" var/message_body = "[speaker.say_quote(message)],\"[message]\"
" diff --git a/code/modules/mob/living/carbon/alien/alien_defenses.dm b/code/modules/mob/living/carbon/alien/alien_defenses.dm index fef2e469848..5934987f8a4 100644 --- a/code/modules/mob/living/carbon/alien/alien_defenses.dm +++ b/code/modules/mob/living/carbon/alien/alien_defenses.dm @@ -35,7 +35,7 @@ In all, this is a lot like the monkey code. /N visible_message("[M.name] bites [src]!", \ "[M.name] bites [src]!") adjustBruteLoss(damage) - add_logs(M, src, "attacked", admin=0, print_attack_log = 0) + add_attack_logs(M, src, "Alien attack", FALSE) updatehealth() else to_chat(M, "[name] is too injured for that.") diff --git a/code/modules/mob/living/carbon/alien/humanoid/alien_powers.dm b/code/modules/mob/living/carbon/alien/humanoid/alien_powers.dm index 4292f101eb5..a2527317eec 100644 --- a/code/modules/mob/living/carbon/alien/humanoid/alien_powers.dm +++ b/code/modules/mob/living/carbon/alien/humanoid/alien_powers.dm @@ -43,7 +43,7 @@ Doesn't work on other aliens/AI.*/ adjustPlasma(-10) var/msg = sanitize(input("Message:", "Alien Whisper") as text|null) if(msg) - log_say("Alien Whisper: [key_name(src)]->[key_name(M)]: [msg]") + log_say("(AWHISPER to [key_name(M)]) [msg]", src) to_chat(M, "You hear a strange, alien voice in your head...[msg]") to_chat(src, "You said: [msg] to [M]") for(var/mob/dead/observer/G in player_list) diff --git a/code/modules/mob/living/carbon/alien/larva/emote.dm b/code/modules/mob/living/carbon/alien/larva/emote.dm index d3140e4a969..82ebcf943f6 100644 --- a/code/modules/mob/living/carbon/alien/larva/emote.dm +++ b/code/modules/mob/living/carbon/alien/larva/emote.dm @@ -114,7 +114,7 @@ else to_chat(src, text("Invalid Emote: []", act)) if((message && src.stat == 0)) - log_emote("[name]/[key] : [message]") + log_emote(message, src) if(m_type & 1) for(var/mob/O in viewers(src, null)) O.show_message(message, m_type) diff --git a/code/modules/mob/living/carbon/alien/larva/larva.dm b/code/modules/mob/living/carbon/alien/larva/larva.dm index 305f8ad45a9..2d638dd0db1 100644 --- a/code/modules/mob/living/carbon/alien/larva/larva.dm +++ b/code/modules/mob/living/carbon/alien/larva/larva.dm @@ -84,7 +84,7 @@ "[M] [M.attacktext] [src]!") var/damage = rand(M.melee_damage_lower, M.melee_damage_upper) adjustBruteLoss(damage) - add_logs(M, src, "attacked", admin=0, print_attack_log = 0) + add_attack_logs(M, src, "Animal attacked", FALSE) updatehealth() diff --git a/code/modules/mob/living/carbon/carbon.dm b/code/modules/mob/living/carbon/carbon.dm index 7a885fd1823..7cdebe4502c 100644 --- a/code/modules/mob/living/carbon/carbon.dm +++ b/code/modules/mob/living/carbon/carbon.dm @@ -564,7 +564,7 @@ var/list/ventcrawl_machinery = list(/obj/machinery/atmospherics/unary/vent_pump, var/start_T_descriptor = "tile at [start_T.x], [start_T.y], [start_T.z] in area [get_area(start_T)]" var/end_T_descriptor = "tile at [end_T.x], [end_T.y], [end_T.z] in area [get_area(end_T)]" - add_logs(src, throwable_mob, "thrown", addition="from [start_T_descriptor] with the target [end_T_descriptor]") + add_attack_logs(src, throwable_mob, "Thrown from [start_T_descriptor] with the target [end_T_descriptor]") else if(!(I.flags & ABSTRACT)) //can't throw abstract items thrown_thing = I @@ -1018,9 +1018,7 @@ var/list/ventcrawl_machinery = list(/obj/machinery/atmospherics/unary/vent_pump, return 1 /mob/living/carbon/proc/forceFedAttackLog(var/obj/item/reagent_containers/food/toEat, mob/user) - create_attack_log("Has been fed [toEat.name] by [user.name] ([user.ckey]) Reagents: [toEat.reagentlist(toEat)]") - user.create_attack_log("Fed [toEat.name] to [name] ([ckey]) Reagents: [toEat.reagentlist(toEat)]") - log_attack("[user.name] ([user.ckey]) fed [name] ([ckey]) with [toEat.name] Reagents: [toEat.reagentlist(toEat)] (INTENT: [uppertext(user.a_intent)])") + add_attack_logs(user, src, "Fed [toEat]. Reagents: [toEat.reagentlist(toEat)]") if(!iscarbon(user)) LAssailant = null else diff --git a/code/modules/mob/living/carbon/human/death.dm b/code/modules/mob/living/carbon/human/death.dm index 514fd2fe83f..84b4608b233 100644 --- a/code/modules/mob/living/carbon/human/death.dm +++ b/code/modules/mob/living/carbon/human/death.dm @@ -111,7 +111,7 @@ if(ishuman(LAssailant)) var/mob/living/carbon/human/H=LAssailant if(H.mind) - H.mind.kills += "[name] ([ckey])" + H.mind.kills += "[key_name(src)]" if(!gibbed) update_canmove() @@ -121,7 +121,7 @@ med_hud_set_status() if(mind) mind.store_memory("Time of death: [station_time_timestamp("hh:mm:ss", timeofdeath)]", 0) if(ticker && ticker.mode) -// log_to_dd("k") +// log_world("k") sql_report_death(src) ticker.mode.check_win() //Calls the rounds wincheck, mainly for wizard, malf, and changeling now diff --git a/code/modules/mob/living/carbon/human/emote.dm b/code/modules/mob/living/carbon/human/emote.dm index c10b9a67036..97ff899abe6 100644 --- a/code/modules/mob/living/carbon/human/emote.dm +++ b/code/modules/mob/living/carbon/human/emote.dm @@ -898,7 +898,7 @@ to_chat(src, "Unusable emote '[act]'. Say *help for a list.") if(message) //Humans are special fucking snowflakes and have 800 lines of emotes, they get to handle their own emotes, not call the parent. - log_emote("[name]/[key] : [message]") + log_emote(message, src) //Hearing gasp and such every five seconds is not good emotes were not global for a reason. // Maybe some people are okay with that. diff --git a/code/modules/mob/living/carbon/human/human.dm b/code/modules/mob/living/carbon/human/human.dm index 6f8abb96bd2..f41479cd392 100644 --- a/code/modules/mob/living/carbon/human/human.dm +++ b/code/modules/mob/living/carbon/human/human.dm @@ -315,7 +315,7 @@ M.do_attack_animation(src) visible_message("[M] [M.attacktext] [src]!", \ "[M] [M.attacktext] [src]!") - add_logs(M, src, "attacked") + add_attack_logs(M, src, "Animal attacked") var/damage = rand(M.melee_damage_lower, M.melee_damage_upper) if(check_shields(damage, "the [M.name]", null, MELEE_ATTACK, M.armour_penetration)) return 0 @@ -753,12 +753,12 @@ unEquip(pocket_item) if(thief_mode) usr.put_in_hands(pocket_item) - add_logs(usr, src, "stripped", addition="of [pocket_item]", print_attack_log = isLivingSSD(src)) + add_attack_logs(usr, src, "Stripped of [pocket_item]", isLivingSSD(src)) else if(place_item) usr.unEquip(place_item) equip_to_slot_if_possible(place_item, pocket_id, 0, 1) - add_logs(usr, src, "equipped", addition="with [pocket_item]", print_attack_log = isLivingSSD(src)) + add_attack_logs(usr, src, "Equipped with [pocket_item]", isLivingSSD(src)) // Update strip window if(usr.machine == src && in_range(src, usr)) @@ -767,7 +767,7 @@ // Display a warning if the user mocks up if they don't have pickpocket gloves. if(!thief_mode) to_chat(src, "You feel your [pocket_side] pocket being fumbled with!") - add_logs(usr, src, "attempted to strip", addition="of [pocket_item]", print_attack_log = isLivingSSD(src)) + add_attack_logs(usr, src, "Attempted strip of [pocket_item]", isLivingSSD(src)) if(href_list["set_sensor"]) if(istype(w_uniform, /obj/item/clothing/under)) @@ -782,7 +782,7 @@ "You have dislodged everything from [src]'s headpocket!") var/obj/item/organ/internal/headpocket/C = get_int_organ(/obj/item/organ/internal/headpocket) C.empty_contents() - add_logs(usr, src, "stripped", addition="of headpocket items", print_attack_log=isLivingSSD(src)) + add_attack_logs(usr, src, "Stripped of headpocket items", isLivingSSD(src)) if(href_list["strip_accessory"]) if(istype(w_uniform, /obj/item/clothing/under)) diff --git a/code/modules/mob/living/carbon/human/human_attackhand.dm b/code/modules/mob/living/carbon/human/human_attackhand.dm index 99fbc4f1326..57be152295b 100644 --- a/code/modules/mob/living/carbon/human/human_attackhand.dm +++ b/code/modules/mob/living/carbon/human/human_attackhand.dm @@ -19,38 +19,13 @@ ..() if((M != src) && M.a_intent != INTENT_HELP && check_shields(0, M.name, attack_type = UNARMED_ATTACK)) - add_logs(M, src, "attempted to touch") + add_attack_logs(M, src, "Melee attacked with fists (miss/block)") visible_message("[M] attempted to touch [src]!") return 0 - if(istype(M.gloves , /obj/item/clothing/gloves/boxing/hologlove)) - - var/damage = rand(0, 9) - if(!damage) - playsound(loc, 'sound/weapons/punchmiss.ogg', 25, 1, -1) - visible_message("[M] has attempted to punch [src]!") - return 0 - var/obj/item/organ/external/affecting = get_organ(ran_zone(M.zone_sel.selecting)) - var/armor_block = run_armor_check(affecting, "melee") - - if(HULK in M.mutations) - damage += 5 - Weaken(4) - - playsound(loc, "punch", 25, 1, -1) - - visible_message("[M] has punched [src]!") - - apply_damage(damage, STAMINA, affecting, armor_block) - if(damage >= 9) - visible_message("[M] has weakened [src]!") - apply_effect(4, WEAKEN, armor_block) - - return - var/datum/martial_art/attacker_style = M.martial_art - species.handle_attack_hand(src,M) + species.handle_attack_hand(src, M) switch(M.a_intent) if(INTENT_HELP) @@ -63,11 +38,11 @@ if(S.next_step(M, src)) return 1 help_shake_act(M) - add_logs(M, src, "shaked") + add_attack_logs(M, src, "Shaked") return 1 if(health >= config.health_threshold_crit) help_shake_act(M) - add_logs(M, src, "shaked") + add_attack_logs(M, src, "Shaked") return 1 if(!H.check_has_mouth()) to_chat(H, "You don't have a mouth, you cannot perform CPR!") @@ -94,7 +69,7 @@ to_chat(src, "You feel a breath of fresh air enter your lungs. It feels good.") to_chat(M, "Repeat at least every 7 seconds.") - add_logs(M, src, "CPRed") + add_attack_logs(M, src, "CPRed", FALSE) return 1 else to_chat(M, "You need to stay still while performing CPR!") @@ -123,8 +98,7 @@ return //we're good to suck the blood, blaah M.mind.vampire.handle_bloodsucking(src) - add_logs(M, src, "vampirebit") - msg_admin_attack("[key_name_admin(M)] vampirebit [key_name_admin(src)]") + add_attack_logs(M, src, "vampirebit") return //end vampire codes if(attacker_style && attacker_style.harm_act(H, src)) @@ -133,7 +107,7 @@ var/datum/unarmed_attack/attack = M.species.unarmed M.do_attack_animation(src) - add_logs(M, src, "[pick(attack.attack_verb)]ed") + add_attack_logs(M, src, "Melee attacked with fists") if(!iscarbon(M)) LAssailant = null @@ -172,7 +146,7 @@ if(attacker_style && attacker_style.disarm_act(H, src)) return 1 else - add_logs(M, src, "disarmed") + add_attack_logs(M, src, "Disarmed") if(w_uniform) w_uniform.add_fingerprint(M) @@ -182,14 +156,11 @@ apply_effect(2, WEAKEN, run_armor_check(affecting, "melee")) playsound(loc, 'sound/weapons/thudswoosh.ogg', 50, 1, -1) visible_message("[M] has pushed [src]!") - M.create_attack_log("Pushed [src.name] ([src.ckey])") - src.create_attack_log("Has been pushed by [M.name] ([M.ckey])") + add_attack_logs(M, src, "Pushed over") if(!iscarbon(M)) LAssailant = null else LAssailant = M - - log_attack("[M.name] ([M.ckey]) pushed [src.name] ([src.ckey])") return var/talked = 0 // BubbleWrap diff --git a/code/modules/mob/living/carbon/human/human_defense.dm b/code/modules/mob/living/carbon/human/human_defense.dm index 6d9c594ec6a..f01ab117448 100644 --- a/code/modules/mob/living/carbon/human/human_defense.dm +++ b/code/modules/mob/living/carbon/human/human_defense.dm @@ -191,9 +191,7 @@ emp_act --meatleft to_chat(user, "You hack off a chunk of meat from [name]") if(!meatleft) - create_attack_log("Was chopped up into meat by [key_name(user)]") - user.create_attack_log("Chopped up [key_name(src)] into meat") - msg_admin_attack("[key_name_admin(user)] chopped up [key_name_admin(src)] into meat") + add_attack_logs(user, src, "Chopped up into meat") if(!iscarbon(user)) LAssailant = null else @@ -371,10 +369,7 @@ emp_act visible_message("[src] has been hit by [M.name].", \ "[src] has been hit by [M.name].") - create_attack_log("Has been attacked by \the [M] controlled by [key_name(M.occupant)] (INTENT: [uppertext(M.occupant.a_intent)])") - M.occupant.create_attack_log("Attacked [src] with \the [M] (INTENT: [uppertext(M.occupant.a_intent)])") - msg_admin_attack("[key_name_admin(M.occupant)] attacked [key_name_admin(src)] with \the [M] (INTENT: [uppertext(M.occupant.a_intent)])") - + add_attack_logs(M.occupant, src, "Mecha-meleed with [M]") else ..() diff --git a/code/modules/mob/living/carbon/human/species/apollo.dm b/code/modules/mob/living/carbon/human/species/apollo.dm index 95d473bf0ff..f1ca3294017 100644 --- a/code/modules/mob/living/carbon/human/species/apollo.dm +++ b/code/modules/mob/living/carbon/human/species/apollo.dm @@ -78,9 +78,7 @@ head_organ.h_style = "Bald" H.update_hair() - M.create_attack_log("removed antennae [H.name] ([H.ckey])") - H.create_attack_log("Has had their antennae removed by [M.name] ([M.ckey])") - msg_admin_attack("[key_name(M)] removed [key_name(H)]'s antennae") + add_attack_logs(M, H, "Antennae removed") return 0 /datum/species/nucleation diff --git a/code/modules/mob/living/carbon/slime/slime.dm b/code/modules/mob/living/carbon/slime/slime.dm index 63df9a3c484..5fa5a09c441 100644 --- a/code/modules/mob/living/carbon/slime/slime.dm +++ b/code/modules/mob/living/carbon/slime/slime.dm @@ -237,9 +237,8 @@ playsound(loc, M.attack_sound, 50, 1, 1) visible_message("[M] [M.attacktext] [src]!", \ "[M] [M.attacktext] [src]!") - M.create_attack_log("attacked [src.name] ([src.ckey])") - src.create_attack_log("was attacked by [M.name] ([M.ckey])") var/damage = rand(M.melee_damage_lower, M.melee_damage_upper) + add_attack_logs(src, M, "Slime'd for [damage] damage") attacked += 10 adjustBruteLoss(damage) updatehealth() diff --git a/code/modules/mob/living/living.dm b/code/modules/mob/living/living.dm index efd09cd4b0d..964dba89a47 100644 --- a/code/modules/mob/living/living.dm +++ b/code/modules/mob/living/living.dm @@ -816,7 +816,7 @@ who.unEquip(what) if(silent) put_in_hands(what) - add_logs(src, who, "stripped", addition="of [what]", print_attack_log = isLivingSSD(who)) + add_attack_logs(src, who, "Stripped of [what]", isLivingSSD(who)) // The src mob is trying to place an item on someone // Override if a certain mob should be behave differently when placing items (can't, for example) @@ -835,7 +835,7 @@ if(what && Adjacent(who)) unEquip(what) who.equip_to_slot_if_possible(what, where, 0, 1) - add_logs(src, who, "equipped", what, print_attack_log = isLivingSSD(who)) + add_attack_logs(src, who, "Equipped [what]", isLivingSSD(who)) /mob/living/singularity_act() diff --git a/code/modules/mob/living/living_defense.dm b/code/modules/mob/living/living_defense.dm index d335dffe917..d1eeafa6b19 100644 --- a/code/modules/mob/living/living_defense.dm +++ b/code/modules/mob/living/living_defense.dm @@ -98,7 +98,7 @@ var/armor = run_armor_check(zone, "melee", "Your armor has protected your [parse_zone(zone)].", "Your armor has softened hit to your [parse_zone(zone)].", I.armour_penetration) apply_damage(I.throwforce, dtype, zone, armor, is_sharp(I), I) if(I.thrownby) - add_logs(I.thrownby, src, "hit", I) + add_attack_logs(I.thrownby, src, "Hit with thrown [I]") else return 1 else @@ -126,14 +126,10 @@ M.occupant_message("You hit [src].") visible_message("[src] has been hit by [M.name].", \ "[src] has been hit by [M.name].") - create_attack_log("Has been attacked by \the [M] controlled by [key_name(M.occupant)] (INTENT: [uppertext(M.occupant.a_intent)])") - M.occupant.create_attack_log("Attacked [src] with \the [M] (INTENT: [uppertext(M.occupant.a_intent)])") - msg_admin_attack("[key_name_admin(M.occupant)] attacked [key_name_admin(src)] with \the [M] (INTENT: [uppertext(M.occupant.a_intent)])") - + add_attack_logs(M.occupant, src, "Mecha-meleed with [M]") else - step_away(src,M) - add_logs(M.occupant, src, "pushed", object=M, admin=0, print_attack_log = 0) + add_attack_logs(M.occupant, src, "Mecha-pushed with [M]", FALSE) M.occupant_message("You push [src] out of the way.") visible_message("[M] pushes [src] out of the way.") return @@ -244,7 +240,7 @@ to_chat(user, "You already grabbed [src].") return - add_logs(user, src, "grabbed", addition="passively") + add_attack_logs(user, src, "Grabbed passively") var/obj/item/grab/G = new /obj/item/grab(user, src) if(buckled) diff --git a/code/modules/mob/living/say.dm b/code/modules/mob/living/say.dm index ac2ad648c70..b2755e2b7d8 100644 --- a/code/modules/mob/living/say.dm +++ b/code/modules/mob/living/say.dm @@ -286,7 +286,7 @@ proc/get_radio_key_from_channel(var/channel) //Log of what we've said, plain message, no spans or junk say_log += message - log_say("[name]/[key] : [message]") + log_say(message, src) return 1 /mob/living/proc/say_signlang(var/message, var/verb="gestures", var/datum/language/language) @@ -313,7 +313,7 @@ proc/get_radio_key_from_channel(var/channel) return 1 if(act && type && message) //parent call - log_emote("[name]/[key] : [message]") + log_emote(message, src) for(var/mob/M in dead_mob_list) if(!M.client || istype(M, /mob/new_player)) @@ -485,7 +485,7 @@ proc/get_radio_key_from_channel(var/channel) for(var/mob/M in watching) M.show_message(rendered, 2) - log_whisper("[name]/[key] : [message]") + log_whisper(message, src) return 1 /mob/living/speech_bubble(var/bubble_state = "",var/bubble_loc = src, var/list/bubble_recipients = list()) diff --git a/code/modules/mob/living/silicon/ai/ai.dm b/code/modules/mob/living/silicon/ai/ai.dm index c7e8308df44..1579085c6ad 100644 --- a/code/modules/mob/living/silicon/ai/ai.dm +++ b/code/modules/mob/living/silicon/ai/ai.dm @@ -725,7 +725,7 @@ var/list/ai_verbs_default = list( if(M.attack_sound) playsound(loc, M.attack_sound, 50, 1, 1) visible_message("[M] [M.attacktext] [src]!") - add_logs(M, src, "attacked", admin=0, print_attack_log = 0) + add_attack_logs(M, src, "Animal attacked", FALSE) var/damage = rand(M.melee_damage_lower, M.melee_damage_upper) switch(M.melee_damage_type) if(BRUTE) diff --git a/code/modules/mob/living/silicon/pai/pai.dm b/code/modules/mob/living/silicon/pai/pai.dm index 3af95f62b37..25781717e08 100644 --- a/code/modules/mob/living/silicon/pai/pai.dm +++ b/code/modules/mob/living/silicon/pai/pai.dm @@ -237,9 +237,8 @@ playsound(loc, M.attack_sound, 50, 1, 1) for(var/mob/O in viewers(src, null)) O.show_message("[M] [M.attacktext] [src]!", 1) - M.create_attack_log("attacked [name] ([ckey])") - create_attack_log("was attacked by [M.name] ([M.ckey])") var/damage = rand(M.melee_damage_lower, M.melee_damage_upper) + add_attack_logs(M, src, "Animal attacked for [damage] damage") adjustBruteLoss(damage) updatehealth() diff --git a/code/modules/mob/living/silicon/robot/robot.dm b/code/modules/mob/living/silicon/robot/robot.dm index a8f89f300e6..0b0872e663b 100644 --- a/code/modules/mob/living/silicon/robot/robot.dm +++ b/code/modules/mob/living/silicon/robot/robot.dm @@ -913,7 +913,7 @@ var/list/robot_verbs_default = list( if(M.attack_sound) playsound(loc, M.attack_sound, 50, 1, 1) visible_message("[M] [M.attacktext] [src]!") - add_logs(M, src, "attacked", admin=0, print_attack_log = 0) + add_attack_logs(M, src, "Animal attacked", FALSE) var/damage = rand(M.melee_damage_lower, M.melee_damage_upper) switch(M.melee_damage_type) if(BRUTE) diff --git a/code/modules/mob/living/silicon/say.dm b/code/modules/mob/living/silicon/say.dm index 7f25a743fc7..0de811224dc 100644 --- a/code/modules/mob/living/silicon/say.dm +++ b/code/modules/mob/living/silicon/say.dm @@ -1,5 +1,5 @@ /mob/living/silicon/handle_message_mode(message_mode, message, verb, speaking, used_radios, alt_name) - log_say("[key_name(src)] : [message]") + log_say(message, src) if(..()) return 1 @@ -67,8 +67,7 @@ //For holopads only. Usable by AI. /mob/living/silicon/ai/proc/holopad_talk(var/message, verb, datum/language/speaking) - - log_say("[key_name(src)] : [message]") + log_say("(HPAD) [message]", src) message = trim(message) @@ -108,9 +107,6 @@ return 1 /mob/living/silicon/ai/proc/holopad_emote(var/message) //This is called when the AI uses the 'me' verb while using a holopad. - - log_emote("[key_name(src)] : [message]") - message = trim(message) if(!message) @@ -123,6 +119,8 @@ for(var/mob/M in viewers(T.loc)) M.show_message(rendered, 2) + + log_emote("(HPAD) [message]", src) else //This shouldn't occur, but better safe then sorry. to_chat(src, "No holopad connected.") return diff --git a/code/modules/mob/living/simple_animal/bot/bot.dm b/code/modules/mob/living/simple_animal/bot/bot.dm index f893560ec60..ae8cecb8eb2 100644 --- a/code/modules/mob/living/simple_animal/bot/bot.dm +++ b/code/modules/mob/living/simple_animal/bot/bot.dm @@ -219,7 +219,7 @@ turn_on() //The bot automatically turns on when emagged, unless recently hit with EMP. to_chat(src, "(#$*#$^^( OVERRIDE DETECTED") show_laws() - add_logs(user, src, "emagged") + add_attack_logs(user, src, "Emagged") return else //Bot is unlocked, but the maint panel has not been opened with a screwdriver yet. to_chat(user, "You need to open maintenance panel first!") @@ -273,7 +273,7 @@ return apply_damage(M.melee_damage_upper, BRUTE) visible_message("[M] has [M.attacktext] [src]!") - add_logs(M, src, "attacked", admin=0, print_attack_log = 0) + add_attack_logs(M, src, "Animal attacked", FALSE) if(prob(10)) new /obj/effect/decal/cleanable/blood/oil(loc) @@ -333,7 +333,7 @@ bot_name = name name = paicard.pai.name faction = user.faction - add_logs(user, paicard.pai, "uploaded to [src.bot_name],") + add_attack_logs(user, paicard.pai, "Uploaded to [src.bot_name]") else to_chat(user, "[W] is inactive.") else @@ -865,7 +865,7 @@ Pass a positive integer as an argument to override a bot's default speed. to_chat(usr, "[text_hack]") show_laws() bot_reset() - add_logs(usr, src, "hacked") + add_attack_logs(usr, src, "Hacked") else if(!hacked) to_chat(usr, "[text_dehack_fail]") else @@ -874,7 +874,7 @@ Pass a positive integer as an argument to override a bot's default speed. to_chat(usr, "[text_dehack]") show_laws() bot_reset() - add_logs(usr, src, "dehacked") + add_attack_logs(usr, src, "Dehacked") if("ejectpai") if(paicard && (!locked || issilicon(usr) || usr.can_admin_interact())) to_chat(usr, "You eject [paicard] from [bot_name]") @@ -946,9 +946,9 @@ Pass a positive integer as an argument to override a bot's default speed. key = null paicard.forceMove(loc) if(user) - add_logs(user, paicard.pai, "ejected from [src.bot_name],") + add_attack_logs(user, paicard.pai, "Ejected from [src.bot_name],") else - add_logs(src, paicard.pai, "ejected") + add_attack_logs(src, paicard.pai, "Ejected") if(announce) to_chat(paicard.pai, "You feel your control fade as [paicard] ejects from [bot_name].") paicard = null diff --git a/code/modules/mob/living/simple_animal/bot/ed209bot.dm b/code/modules/mob/living/simple_animal/bot/ed209bot.dm index 2a0c333ed21..864898902b7 100644 --- a/code/modules/mob/living/simple_animal/bot/ed209bot.dm +++ b/code/modules/mob/living/simple_animal/bot/ed209bot.dm @@ -550,7 +550,7 @@ Auto Patrol[]"}, C.Weaken(5) C.stuttering = 5 C.Stun(5) - add_logs(src, C, "stunned") + add_attack_logs(src, C, "Stunned by [src]") if(declare_arrests) var/area/location = get_area(src) speak("[arrest_type ? "Detaining" : "Arresting"] level [threat] scumbag [C] in [location].", radio_channel) diff --git a/code/modules/mob/living/simple_animal/bot/mulebot.dm b/code/modules/mob/living/simple_animal/bot/mulebot.dm index bdfd446e4f7..cb449e3f047 100644 --- a/code/modules/mob/living/simple_animal/bot/mulebot.dm +++ b/code/modules/mob/living/simple_animal/bot/mulebot.dm @@ -684,7 +684,7 @@ visible_message("[src] bumps into [M]!") else if(!paicard) - add_logs(src, M, "knocked down") + add_attack_logs(src, M, "Knocked down") visible_message("[src] knocks over [M]!") M.stop_pulling() M.Stun(8) @@ -692,7 +692,7 @@ return ..() /mob/living/simple_animal/bot/mulebot/proc/RunOver(mob/living/carbon/human/H) - add_logs(src, H, "run over", null, "(DAMTYPE: [uppertext(BRUTE)])") + add_attack_logs(src, H, "Run over (DAMTYPE: [uppertext(BRUTE)])") H.visible_message("[src] drives over [H]!", \ "[src] drives over you!") playsound(loc, 'sound/effects/splat.ogg', 50, 1) diff --git a/code/modules/mob/living/simple_animal/bot/secbot.dm b/code/modules/mob/living/simple_animal/bot/secbot.dm index c2f967aee2c..032c5df9ce8 100644 --- a/code/modules/mob/living/simple_animal/bot/secbot.dm +++ b/code/modules/mob/living/simple_animal/bot/secbot.dm @@ -260,7 +260,7 @@ Auto Patrol: []"}, C.Weaken(5) C.stuttering = 5 C.Stun(5) - add_logs(src, C, "stunned") + add_attack_logs(src, C, "Stunned by [src]") if(declare_arrests) var/area/location = get_area(src) speak("[arrest_type ? "Detaining" : "Arresting"] level [threat] scumbag [C] in [location].", radio_channel) diff --git a/code/modules/mob/living/simple_animal/friendly/spiderbot.dm b/code/modules/mob/living/simple_animal/friendly/spiderbot.dm index ab736a0746a..fd92b27764c 100644 --- a/code/modules/mob/living/simple_animal/friendly/spiderbot.dm +++ b/code/modules/mob/living/simple_animal/friendly/spiderbot.dm @@ -137,7 +137,7 @@ to_chat(user, "You short out the security protocols and rewrite [src]'s internal memory.") to_chat(src, "You have been emagged; you are now completely loyal to [user] and their every order!") emagged_master = user.name - add_logs(user, src, "emagged") + add_attack_logs(user, src, "Emagged") maxHealth = 60 health = 60 melee_damage_lower = 15 diff --git a/code/modules/mob/living/simple_animal/hostile/megafauna/hierophant.dm b/code/modules/mob/living/simple_animal/hostile/megafauna/hierophant.dm index a0f3c4d7ad3..c5526b37cc8 100644 --- a/code/modules/mob/living/simple_animal/hostile/megafauna/hierophant.dm +++ b/code/modules/mob/living/simple_animal/hostile/megafauna/hierophant.dm @@ -547,7 +547,7 @@ Difficulty: Hard L.apply_damage(damage, BURN, limb_to_hit, armor) if(ismegafauna(L) || istype(L, /mob/living/simple_animal/hostile/asteroid)) L.adjustBruteLoss(damage) - add_logs(caster, L, "struck with a [name]") + add_attack_logs(caster, L, "Struck with a [name]") for(var/obj/mecha/M in T.contents - hit_things) //and mechs. hit_things += M if(M.occupant) diff --git a/code/modules/mob/living/simple_animal/simple_animal.dm b/code/modules/mob/living/simple_animal/simple_animal.dm index 89326550c25..a4eba013f94 100644 --- a/code/modules/mob/living/simple_animal/simple_animal.dm +++ b/code/modules/mob/living/simple_animal/simple_animal.dm @@ -273,7 +273,7 @@ playsound(loc, M.attack_sound, 50, 1, 1) visible_message("\The [M] [M.attacktext] [src]!", \ "\The [M] [M.attacktext] [src]!") - add_logs(M, src, "attacked", admin=0, print_attack_log = 0) + add_attack_logs(M, src, "Animal attacked") var/damage = rand(M.melee_damage_lower, M.melee_damage_upper) attack_threshold_check(damage,M.melee_damage_type) diff --git a/code/modules/mob/living/stat_states.dm b/code/modules/mob/living/stat_states.dm index 812eeaa0821..3decff7596e 100644 --- a/code/modules/mob/living/stat_states.dm +++ b/code/modules/mob/living/stat_states.dm @@ -6,7 +6,8 @@ return 0 else if(stat == UNCONSCIOUS) return 0 - add_logs(src, null, "fallen unconscious at [atom_loc_line(get_turf(src))]", admin=0, print_attack_log = 0) + create_attack_log("Fallen unconscious at [atom_loc_line(get_turf(src))]") + log_game("[key_name(src)] fell unconscious at [atom_loc_line(get_turf(src))]") stat = UNCONSCIOUS if(updating) // update_blind_effects() @@ -19,7 +20,8 @@ return 0 else if(stat == CONSCIOUS) return 0 - add_logs(src, null, "woken up at [atom_loc_line(get_turf(src))]", admin=0, print_attack_log = 0) + create_attack_log("Woken up at [atom_loc_line(get_turf(src))]") + log_game("[key_name(src)] woke up at [atom_loc_line(get_turf(src))]") stat = CONSCIOUS if(updating) // update_blind_effects() @@ -40,7 +42,8 @@ return 0 if(!can_be_revived()) return 0 - add_logs(src, null, "came back to life at [atom_loc_line(get_turf(src))]", admin=0, print_attack_log = 0) + create_attack_log("Came back to life at [atom_loc_line(get_turf(src))]") + log_game("[key_name(src)] came back to life at [atom_loc_line(get_turf(src))]") stat = CONSCIOUS dead_mob_list -= src living_mob_list += src diff --git a/code/modules/mob/login.dm b/code/modules/mob/login.dm index 27197474c00..63b248ffd41 100644 --- a/code/modules/mob/login.dm +++ b/code/modules/mob/login.dm @@ -3,7 +3,7 @@ //Multikey checks and logging lastKnownIP = client.address computer_id = client.computer_id - log_access("Login: [key_name(src)] from [lastKnownIP ? lastKnownIP : "localhost"]-[computer_id] || BYOND v[client.byond_version]") + log_access_in(client) if(config.log_access) for(var/mob/M in player_list) if(M == src) continue @@ -19,10 +19,10 @@ if(matches) if(M.client) message_admins("Notice: [key_name_admin(src)] has the same [matches] as [key_name_admin(M)].", 1) - log_access("Notice: [key_name(src)] has the same [matches] as [key_name(M)].") + log_adminwarn("Notice: [key_name(src)] has the same [matches] as [key_name(M)].") else message_admins("Notice: [key_name_admin(src)] has the same [matches] as [key_name_admin(M)] (no longer logged in). ", 1) - log_access("Notice: [key_name(src)] has the same [matches] as [key_name(M)] (no longer logged in).") + log_adminwarn("Notice: [key_name(src)] has the same [matches] as [key_name(M)] (no longer logged in).") /mob/Login() player_list |= src diff --git a/code/modules/mob/logout.dm b/code/modules/mob/logout.dm index 1909c67f0ec..a0f8594e870 100644 --- a/code/modules/mob/logout.dm +++ b/code/modules/mob/logout.dm @@ -2,7 +2,7 @@ SSnanoui.user_logout(src) // this is used to clean up (remove) this user's Nano UIs unset_machine() player_list -= src - log_access("Logout: [key_name(src)]") + log_access_out(src) // `holder` is nil'd out by now, so we check the `admin_datums` array directly //Only report this stuff if we are currently playing. if(admin_datums[ckey] && ticker && ticker.current_state == GAME_STATE_PLAYING) diff --git a/code/modules/mob/mob_grab.dm b/code/modules/mob/mob_grab.dm index 4f91672769b..72513f57de2 100644 --- a/code/modules/mob/mob_grab.dm +++ b/code/modules/mob/mob_grab.dm @@ -272,9 +272,7 @@ state = GRAB_NECK icon_state = "grabbed+1" assailant.setDir(get_dir(assailant, affecting)) - affecting.create_attack_log("Has had their neck grabbed by [assailant.name] ([assailant.ckey])") - assailant.create_attack_log("Grabbed the neck of [affecting.name] ([affecting.ckey])") - log_attack("[assailant.name] ([assailant.ckey]) grabbed the neck of [affecting.name] ([affecting.ckey])") + add_attack_logs(assailant, affecting, "Neck grabbed") if(!iscarbon(assailant)) affecting.LAssailant = null else @@ -288,9 +286,7 @@ state = GRAB_KILL assailant.visible_message("[assailant] has tightened \his grip on [affecting]'s neck!") - affecting.create_attack_log("Has been strangled (kill intent) by [assailant.name] ([assailant.ckey])") - assailant.create_attack_log("Strangled (kill intent) [affecting.name] ([affecting.ckey])") - msg_admin_attack("[key_name(assailant)] strangled (kill intent) [key_name(affecting)]") + add_attack_logs(assailant, affecting, "Strangled") assailant.next_move = world.time + 10 if(!affecting.get_organ_slot("breathing_tube")) @@ -342,9 +338,7 @@ damage += hat.force * 3 affecting.apply_damage(damage*rand(90, 110)/100, BRUTE, "head", affected.run_armor_check(affecting, "melee")) playsound(assailant.loc, "swing_hit", 25, 1, -1) - assailant.create_attack_log("Headbutted [affecting.name] ([affecting.ckey])") - affecting.create_attack_log("Headbutted by [assailant.name] ([assailant.ckey])") - msg_admin_attack("[key_name(assailant)] has headbutted [key_name(affecting)]") + add_attack_logs(assailant, affecting, "Headbutted") return /*if(last_hit_zone == "eyes") @@ -361,9 +355,7 @@ return assailant.visible_message("[assailant] presses \his fingers into [affecting]'s eyes!") to_chat(affecting, "You feel immense pain as digits are being pressed into your eyes!") - assailant.create_attack_log("Pressed fingers into the eyes of [affecting.name] ([affecting.ckey])") - affecting.create_attack_log("Had fingers pressed into their eyes by [assailant.name] ([assailant.ckey])") - msg_admin_attack("[key_name(assailant)] has pressed his fingers into [key_name(affecting)]'s eyes.") + add_attack_logs(assailant, affecting, "Eye-fucked with their fingers") var/obj/item/organ/internal/eyes/eyes = affected.get_int_organ(/obj/item/organ/internal/eyes) eyes.damage += rand(3,4) if(eyes.damage >= eyes.min_broken_damage) @@ -400,9 +392,7 @@ user.visible_message("[user] devours \the [affecting]!") if(affecting.mind) - affecting.create_attack_log("Has been devoured by [attacker.name] ([attacker.ckey])") - attacker.create_attack_log("Devoured [affecting.name] ([affecting.ckey])") - msg_admin_attack("[key_name(attacker)] devoured [key_name(affecting)]") + add_attack_logs(attacker, affecting, "Devoured") affecting.loc = user attacker.stomach_contents.Add(affecting) diff --git a/code/modules/mob/new_player/new_player.dm b/code/modules/mob/new_player/new_player.dm index d28a34f1bc3..bf6526c856e 100644 --- a/code/modules/mob/new_player/new_player.dm +++ b/code/modules/mob/new_player/new_player.dm @@ -36,7 +36,7 @@ if(antags && antags.len) if(!skip_antag) output += "

Global Antag Candidancy" else output += "

Global Antag Candidancy" - output += "
You are [skip_antag ? "ineligable" : "eligable"] for all antag roles.

" + output += "
You are [skip_antag ? "ineligible" : "eligible"] for all antag roles.

" else output += "

View the Crew Manifest

" output += "

Join Game!

" diff --git a/code/modules/modular_computers/file_system/programs/command/comms.dm b/code/modules/modular_computers/file_system/programs/command/comms.dm index 5f89eddecef..a3e1809528f 100644 --- a/code/modules/modular_computers/file_system/programs/command/comms.dm +++ b/code/modules/modular_computers/file_system/programs/command/comms.dm @@ -331,7 +331,7 @@ return 1 Nuke_request(input, usr) to_chat(usr, "Request sent.") - log_say("[key_name(usr)] has requested the nuclear codes from Centcomm") + log_game("[key_name(usr)] has requested the nuclear codes from Centcomm") priority_announcement.Announce("The codes for the on-station nuclear self-destruct have been requested by [usr]. Confirmation or denial of this request will be sent shortly.", "Nuclear Self Destruct Codes Requested",'sound/AI/commandreport.ogg') centcomm_message_cooldown = 1 spawn(6000)//10 minute cooldown @@ -350,7 +350,7 @@ return 1 Centcomm_announce(input, usr) to_chat(usr, "Message transmitted.") - log_say("[key_name(usr)] has made a Centcomm announcement: [input]") + log_game("[key_name(usr)] has made a Centcomm announcement: [input]") centcomm_message_cooldown = 1 spawn(6000)//10 minute cooldown centcomm_message_cooldown = 0 @@ -369,7 +369,7 @@ return 1 Syndicate_announce(input, usr) to_chat(usr, "Message transmitted.") - log_say("[key_name(usr)] has made a Syndicate announcement: [input]") + log_game("[key_name(usr)] has made a Syndicate announcement: [input]") centcomm_message_cooldown = 1 spawn(6000)//10 minute cooldown centcomm_message_cooldown = 0 diff --git a/code/modules/modular_computers/file_system/programs/generic/ntnrc_client.dm b/code/modules/modular_computers/file_system/programs/generic/ntnrc_client.dm index de272f490e5..19b3fe80ffe 100644 --- a/code/modules/modular_computers/file_system/programs/generic/ntnrc_client.dm +++ b/code/modules/modular_computers/file_system/programs/generic/ntnrc_client.dm @@ -103,7 +103,7 @@ if(!message || !channel) return channel.add_message(message, username) - log_chat("[user]/([user.ckey]) as [username] sent to [channel.title]: [message]") + log_chat("[username] sent to [channel.title]: [message]", user) if("PRG_joinchannel") . = 1 diff --git a/code/modules/nano/nanomapgen.dm b/code/modules/nano/nanomapgen.dm index 710083cb158..10bf8f288a6 100644 --- a/code/modules/nano/nanomapgen.dm +++ b/code/modules/nano/nanomapgen.dm @@ -50,11 +50,11 @@ var/icon/Tile = icon(file("nano/mapbase1024.png")) if(Tile.Width() != NANOMAP_MAX_ICON_DIMENSION || Tile.Height() != NANOMAP_MAX_ICON_DIMENSION) - log_to_dd("NanoMapGen: ERROR: BASE IMAGE DIMENSIONS ARE NOT [NANOMAP_MAX_ICON_DIMENSION]x[NANOMAP_MAX_ICON_DIMENSION]") + log_world("NanoMapGen: ERROR: BASE IMAGE DIMENSIONS ARE NOT [NANOMAP_MAX_ICON_DIMENSION]x[NANOMAP_MAX_ICON_DIMENSION]") sleep(3) return NANOMAP_TERMINALERR - log_to_dd("NanoMapGen: GENERATE MAP ([startX],[startY],[currentZ]) to ([endX],[endY],[currentZ])") + log_world("NanoMapGen: GENERATE MAP ([startX],[startY],[currentZ]) to ([endX],[endY],[currentZ])") to_chat(usr, "NanoMapGen: GENERATE MAP ([startX],[startY],[currentZ]) to ([endX],[endY],[currentZ])") var/count = 0; @@ -71,16 +71,16 @@ count++ if(count % 8000 == 0) - log_to_dd("NanoMapGen: [count] tiles done") + log_world("NanoMapGen: [count] tiles done") sleep(1) var/mapFilename = "nanomap_z[currentZ]-new.png" - log_to_dd("NanoMapGen: sending [mapFilename] to client") + log_world("NanoMapGen: sending [mapFilename] to client") usr << browse(Tile, "window=picture;file=[mapFilename];display=0") - log_to_dd("NanoMapGen: Done.") + log_world("NanoMapGen: Done.") to_chat(usr, "NanoMapGen: Done. File [mapFilename] uploaded to your cache.") diff --git a/code/modules/paperwork/paper.dm b/code/modules/paperwork/paper.dm index 42519a4d049..db3f7cddce7 100644 --- a/code/modules/paperwork/paper.dm +++ b/code/modules/paperwork/paper.dm @@ -669,5 +669,5 @@ if(!istype(G) || G.transfer_prints) H.reagents.add_reagent(contact_poison, contact_poison_volume) contact_poison = null - add_logs(user, src, "picked up [src], the paper poisoned by [contact_poison_poisoner]") + add_attack_logs(src, user, "Picked up [src], the paper poisoned by [contact_poison_poisoner]") ..() diff --git a/code/modules/paperwork/pen.dm b/code/modules/paperwork/pen.dm index 3ddd478eed3..b4446f67e0e 100644 --- a/code/modules/paperwork/pen.dm +++ b/code/modules/paperwork/pen.dm @@ -114,7 +114,7 @@ // to_chat(M, "You feel a tiny prick!") . = 1 - add_logs(user, M, "stabbed", object="[name]") + add_attack_logs(user, M, "Stabbed with [src]") else . = ..() @@ -201,7 +201,7 @@ P.contact_poison = "amanitin" P.contact_poison_volume = 15 P.contact_poison_poisoner = user.name - add_logs(user, P, "used poison pen on") + add_attack_logs(user, P, "Poison pen'ed") to_chat(user, "You apply the poison to [P].") else to_chat(user, "[src] clicks. It seems to be depleted.") diff --git a/code/modules/pda/messenger.dm b/code/modules/pda/messenger.dm index b048b1c054c..bfc74a3b8ec 100644 --- a/code/modules/pda/messenger.dm +++ b/code/modules/pda/messenger.dm @@ -180,7 +180,7 @@ SSnanoui.update_user_uis(U, P) // Update the sending user's PDA UI so that they can see the new message PM.notify("Message from [pda.owner] ([pda.ownjob]), \"[t]\" (Reply)") - log_pda("[usr] (PDA: [src.name]) sent \"[t]\" to [P.name]") + log_pda("(PDA: [src.name]) sent \"[t]\" to [P.name]", usr) else to_chat(U, "ERROR: Messaging server is not responding.") diff --git a/code/modules/power/power.dm b/code/modules/power/power.dm index 6e3eeccb8d5..fd5946b7dc4 100644 --- a/code/modules/power/power.dm +++ b/code/modules/power/power.dm @@ -254,7 +254,7 @@ //remove the old powernet and replace it with a new one throughout the network. /proc/propagate_network(var/obj/O, var/datum/powernet/PN) - //log_to_dd("propagating new network") + //log_world("propagating new network") var/list/worklist = list() var/list/found_machines = list() var/index = 1 diff --git a/code/modules/power/singularity/emitter.dm b/code/modules/power/singularity/emitter.dm index 0b01d2da51e..ea4c290d045 100644 --- a/code/modules/power/singularity/emitter.dm +++ b/code/modules/power/singularity/emitter.dm @@ -120,7 +120,7 @@ if(radio_controller) radio_controller.remove_object(src, frequency) radio_connection = null - msg_admin_attack("Emitter deleted at ([x],[y],[z] - JMP)",0,1) + msg_admin_attack("Emitter deleted at ([x],[y],[z] - [ADMIN_JMP(src)])", 0, 1) log_game("Emitter deleted at ([x],[y],[z])") investigate_log("deleted at ([x],[y],[z])","singulo") return ..() diff --git a/code/modules/power/singularity/particle_accelerator/particle_control.dm b/code/modules/power/singularity/particle_accelerator/particle_control.dm index c59e7734f37..b8570de2c78 100644 --- a/code/modules/power/singularity/particle_accelerator/particle_control.dm +++ b/code/modules/power/singularity/particle_accelerator/particle_control.dm @@ -227,9 +227,9 @@ active = !active investigate_log("turned [active?"ON":"OFF"] by [usr ? usr.key : "outside forces"]","singulo") if(active) - msg_admin_attack("PA Control Computer turned ON by [key_name(usr, usr.client)](?) in ([x],[y],[z] - JMP)",0,1) - log_game("PA Control Computer turned ON by [usr.ckey]([usr]) in ([x],[y],[z])") - use_log += text("\[[time_stamp()]\] [usr.name] ([usr.ckey]) has turned on the PA Control Computer.") + msg_admin_attack("PA Control Computer turned ON by [key_name_admin(usr)]",0,1) + log_game("PA Control Computer turned ON by [key_name(usr)] in ([x],[y],[z])") + use_log += text("\[[time_stamp()]\] [key_name(usr)] has turned on the PA Control Computer.") if(active) use_power = 2 for(var/obj/structure/particle_accelerator/part in connected_parts) diff --git a/code/modules/projectiles/guns/dartgun.dm b/code/modules/projectiles/guns/dartgun.dm index da8e7ad77c6..5ae089d5522 100644 --- a/code/modules/projectiles/guns/dartgun.dm +++ b/code/modules/projectiles/guns/dartgun.dm @@ -173,19 +173,12 @@ R += A.id + " (" R += num2text(A.volume) + ")," if(istype(M, /mob)) - M.create_attack_log("[user]/[user.ckey] shot [M]/[M.ckey] with a dartgun ([R])") - user.create_attack_log("[user]/[user.ckey] shot [M]/[M.ckey] with a dartgun ([R])") - if(M.ckey) - msg_admin_attack("[key_name_admin(user)] shot [M] ([M.ckey]) with a dartgun ([R]).") if(!iscarbon(user)) M.LAssailant = null else M.LAssailant = user - else - M.create_attack_log("UNKNOWN SUBJECT (No longer exists) shot [key_name_admin(M)] with a dartgun ([R])") - msg_admin_attack("UNKNOWN shot [key_name(M)] with a dartgun ([R]) (JMP)") - + add_attack_logs(user, M, "Shot with dartgun containing [R]", !!M.ckey) if(D.reagents) D.reagents.trans_to(M, 15) to_chat(M, "You feel a slight prick.") diff --git a/code/modules/projectiles/guns/magic/wand.dm b/code/modules/projectiles/guns/magic/wand.dm index 5f6e7dcf3b1..1a8e5e45946 100644 --- a/code/modules/projectiles/guns/magic/wand.dm +++ b/code/modules/projectiles/guns/magic/wand.dm @@ -50,7 +50,7 @@ /obj/item/gun/magic/wand/proc/zap_self(mob/living/user) user.visible_message("[user] zaps \himself with [src].") playsound(user, fire_sound, 50, 1) - user.create_attack_log("[user]/[user.ckey] zapped \himself with a [src]") + user.create_attack_log("[key_name(user)] zapped \himself with a [src]") ///////////////////////////////////// //WAND OF DEATH diff --git a/code/modules/projectiles/projectile.dm b/code/modules/projectiles/projectile.dm index 22d7d04784d..a378e291e7c 100644 --- a/code/modules/projectiles/projectile.dm +++ b/code/modules/projectiles/projectile.dm @@ -120,7 +120,7 @@ reagent_note += R.id + " (" reagent_note += num2text(R.volume) + ") " if(!log_override && firer && original) - add_logs(firer, L, "shot", src, reagent_note) + add_attack_logs(firer, L, "Shot with a [type] (potentially containing [reagent_note])") return L.apply_effects(stun, weaken, paralyze, irradiate, slur, stutter, eyeblur, drowsy, blocked, stamina, jitter) /obj/item/projectile/proc/get_splatter_blockage(var/turf/step_over, var/atom/target, var/splatter_dir, var/target_loca) //Check whether the place we want to splatter blood is blocked (i.e. by windows). diff --git a/code/modules/projectiles/projectile/magic.dm b/code/modules/projectiles/projectile/magic.dm index 506263cbc22..e6e77548ced 100644 --- a/code/modules/projectiles/projectile/magic.dm +++ b/code/modules/projectiles/projectile/magic.dm @@ -244,7 +244,7 @@ proc/wabbajack(mob/living/M) else return - M.create_attack_log("[M.real_name] ([M.ckey]) became [new_mob.real_name].") + M.create_attack_log("[key_name(M)] became [new_mob.real_name].") new_mob.attack_log = M.attack_log new_mob.a_intent = INTENT_HARM diff --git a/code/modules/reagents/chemistry/reagents/medicine.dm b/code/modules/reagents/chemistry/reagents/medicine.dm index 970ff077762..ada22d5b139 100644 --- a/code/modules/reagents/chemistry/reagents/medicine.dm +++ b/code/modules/reagents/chemistry/reagents/medicine.dm @@ -666,7 +666,7 @@ M.update_revive() M.stat = UNCONSCIOUS - add_logs(M, M, "revived", object="strange reagent") //Yes, the logs say you revived yourself. + add_attack_logs(M, M, "Revived with strange reagent") //Yes, the logs say you revived yourself. ..() /datum/reagent/medicine/mannitol diff --git a/code/modules/reagents/reagent_containers/borghydro.dm b/code/modules/reagents/reagent_containers/borghydro.dm index d8828865660..057a339649c 100644 --- a/code/modules/reagents/reagent_containers/borghydro.dm +++ b/code/modules/reagents/reagent_containers/borghydro.dm @@ -84,13 +84,9 @@ if(M.reagents) var/datum/reagent/injected = chemical_reagents_list[reagent_ids[mode]] var/contained = injected.name - M.create_attack_log("Has been injected with [name] by [key_name(user)]. Reagents: [contained]") - user.create_attack_log("Used the [name] to inject [key_name(M)]. Reagents: [contained]") - if(M.ckey) - msg_admin_attack("[key_name_admin(user)] injected [key_name_admin(M)] with [name]. Reagents: [contained] (INTENT: [uppertext(user.a_intent)])") - M.LAssailant = user - var/trans = R.trans_to(M, amount_per_transfer_from_this) + add_attack_logs(M, user, "Injected with [name] containing [contained], transfered [trans] units", !!M.ckey) + M.LAssailant = user to_chat(user, "[trans] units injected. [R.total_volume] units remaining.") return diff --git a/code/modules/reagents/reagent_containers/dropper.dm b/code/modules/reagents/reagent_containers/dropper.dm index 5a9552046b3..6198313bf88 100644 --- a/code/modules/reagents/reagent_containers/dropper.dm +++ b/code/modules/reagents/reagent_containers/dropper.dm @@ -61,7 +61,7 @@ for(var/datum/reagent/R in reagents.reagent_list) injected += R.name var/contained = english_list(injected) - add_logs(user, C, "dripped", src, "([contained])") + add_attack_logs(user, C, "Dripped with [src] containing ([contained]), transfering [to_transfer]") to_transfer = reagents.trans_to(C, amount_per_transfer_from_this) to_chat(user, "You transfer [to_transfer] units of the solution.") diff --git a/code/modules/reagents/reagent_containers/glass_containers.dm b/code/modules/reagents/reagent_containers/glass_containers.dm index 64e9f75fb02..004efd57657 100644 --- a/code/modules/reagents/reagent_containers/glass_containers.dm +++ b/code/modules/reagents/reagent_containers/glass_containers.dm @@ -82,10 +82,7 @@ for(var/datum/reagent/R in reagents.reagent_list) injected += R.name var/contained = english_list(injected) - M.create_attack_log("Has been splashed with [name] by [key_name(user)]. Reagents: [contained]") - user.create_attack_log("Used the [name] to splash [key_name(M)]. Reagents: [contained]") - if(M.ckey) - msg_admin_attack("[key_name_admin(user)] splashed [key_name_admin(M)] with [name]. Reagents: [contained] (INTENT: [uppertext(user.a_intent)])") + add_attack_logs(M, user, "Splashed with [name] containing [contained]", !!M.ckey) if(!iscarbon(user)) M.LAssailant = null else diff --git a/code/modules/reagents/reagent_containers/hypospray.dm b/code/modules/reagents/reagent_containers/hypospray.dm index 64d853fa9bf..feee1bab8b4 100644 --- a/code/modules/reagents/reagent_containers/hypospray.dm +++ b/code/modules/reagents/reagent_containers/hypospray.dm @@ -37,7 +37,7 @@ var/contained = english_list(injected) - add_logs(user, M, "injected", src, "([contained])") + add_attack_logs(user, M, "Injected with [src] containing ([contained])") return TRUE diff --git a/code/modules/reagents/reagent_containers/syringes.dm b/code/modules/reagents/reagent_containers/syringes.dm index 71156d8c1a5..38478abd0e7 100644 --- a/code/modules/reagents/reagent_containers/syringes.dm +++ b/code/modules/reagents/reagent_containers/syringes.dm @@ -145,10 +145,7 @@ rinject += R.name var/contained = english_list(rinject) - if(L != user) - add_logs(user, L, "injected", src, addition="which had [contained]") - else - log_attack("[user.name] ([user.ckey]) injected [L.name] ([L.ckey]) with [src.name], which had [contained] (INTENT: [uppertext(user.a_intent)])") + add_attack_logs(user, L, "Injected with [name] containing [contained], transfered [amount_per_transfer_from_this] units") var/fraction = min(amount_per_transfer_from_this/reagents.total_volume, 1) reagents.reaction(L, INGEST, fraction) diff --git a/code/modules/recycling/disposal.dm b/code/modules/recycling/disposal.dm index f36b1765d18..6cc51c09c28 100644 --- a/code/modules/recycling/disposal.dm +++ b/code/modules/recycling/disposal.dm @@ -133,10 +133,7 @@ for(var/mob/C in viewers(src)) C.show_message("[GM.name] has been placed in the [src] by [user].", 3) qdel(G) - usr.create_attack_log("Has placed [key_name(GM)] in disposals.") - GM.create_attack_log("Has been placed in disposals by [key_name(user)]") - if(GM.ckey) - msg_admin_attack("[key_name_admin(user)] placed [key_name_admin(GM)] in a disposals unit. (JMP)") + add_attack_logs(usr, GM, "Disposal'ed", !!GM.ckey) return if(!I) @@ -182,10 +179,7 @@ msg = "[user.name] stuffs [target.name] into the [src]!" to_chat(user, "You stuff [target.name] into the [src]!") - user.create_attack_log("Has placed [key_name(target)] in disposals.") - target.create_attack_log("Has been placed in disposals by [key_name(user)]") - if(target.ckey) - msg_admin_attack("[key_name_admin(user)] placed [key_name_admin(target)] in a disposals unit") + add_attack_logs(user, target, "Disposal'ed", !!target.ckey) else return target.forceMove(src) diff --git a/code/modules/research/xenobiology/xenobiology.dm b/code/modules/research/xenobiology/xenobiology.dm index 22eb9058087..73fe73180c4 100644 --- a/code/modules/research/xenobiology/xenobiology.dm +++ b/code/modules/research/xenobiology/xenobiology.dm @@ -437,7 +437,7 @@ G.change_gender(pick(MALE,FEMALE)) G.loc = src.loc G.key = ghost.key - add_logs(user, G, "summoned", null, "as a golem") + add_attack_logs(user, G, "Summoned as a golem") to_chat(G, "You are an adamantine golem. You move slowly, but are highly resistant to heat and cold as well as blunt trauma. You are unable to wear clothes, but can still use most tools. Serve [user], and assist them in completing their goals at any cost.") qdel(src) diff --git a/code/modules/surgery/dental_implant.dm b/code/modules/surgery/dental_implant.dm index e86b47f104f..5f2b071591f 100644 --- a/code/modules/surgery/dental_implant.dm +++ b/code/modules/surgery/dental_implant.dm @@ -49,7 +49,7 @@ if(!..()) return to_chat(owner, "You grit your teeth and burst the implanted [target]!") - add_logs(owner, null, "swallowed an implanted pill", target) + add_attack_logs(owner, owner, "Swallowed implanted [target]") if(target.reagents.total_volume) target.reagents.reaction(owner, INGEST) target.reagents.trans_to(owner, target.reagents.total_volume) diff --git a/code/modules/surgery/generic.dm b/code/modules/surgery/generic.dm index c746baf19de..ce6465124e3 100644 --- a/code/modules/surgery/generic.dm +++ b/code/modules/surgery/generic.dm @@ -227,7 +227,7 @@ user.visible_message(" [user] amputates [target]'s [affected.name] at the [affected.amputation_point] with \the [tool].", \ " You amputate [target]'s [affected.name] with \the [tool].") - add_logs(user, target, "surgically removed [affected.name] from", addition="INTENT: [uppertext(user.a_intent)]")//log it + add_attack_logs(user, target, "Surgically removed [affected.name]. INTENT: [uppertext(user.a_intent)]")//log it var/atom/movable/thing = affected.droplimb(1,DROPLIMB_SHARP) if(istype(thing,/obj/item)) diff --git a/code/modules/surgery/organs/organ.dm b/code/modules/surgery/organs/organ.dm index 337d2dbfe9d..c6bf7ca01f1 100644 --- a/code/modules/surgery/organs/organ.dm +++ b/code/modules/surgery/organs/organ.dm @@ -306,10 +306,7 @@ processing_objects |= src if(owner && vital && is_primary_organ()) // I'd do another check for species or whatever so that you couldn't "kill" an IPC by removing a human head from them, but it doesn't matter since they'll come right back from the dead - if(user) - user.create_attack_log(" removed a vital organ ([src]) from [key_name(owner)] (INTENT: [uppertext(user.a_intent)])") - owner.create_attack_log(" had a vital organ ([src]) removed by [key_name(user)] (INTENT: [uppertext(user.a_intent)])") - msg_admin_attack("[key_name_admin(user)] removed a vital organ ([src]) from [key_name_admin(owner)]") + add_attack_logs(user, owner, "Removed vital organ ([src])", !!user) owner.death() owner = null return src diff --git a/code/modules/surgery/organs_internal.dm b/code/modules/surgery/organs_internal.dm index 354700a4913..1af925c3166 100644 --- a/code/modules/surgery/organs_internal.dm +++ b/code/modules/surgery/organs_internal.dm @@ -276,14 +276,14 @@ if(target_zone == "head" && B && B.host == target) user.visible_message("[user] successfully extracts [B] from [target]'s [parse_zone(target_zone)]!", "You successfully extract [B] from [target]'s [parse_zone(target_zone)].") - add_logs(user, target, "surgically removed [B] from", addition="INTENT: [uppertext(user.a_intent)]") + add_attack_logs(user, target, "Surgically removed [B]. INTENT: [uppertext(user.a_intent)]") B.leave_host() return FALSE if(I && I.owner == target) user.visible_message(" [user] has separated and extracts [target]'s [I] with [tool].", " You have separated and extracted [target]'s [I] with [tool].") - add_logs(user, target, "surgically removed [I.name] from", addition="INTENT: [uppertext(user.a_intent)]") + add_attack_logs(user, target, "Surgically removed [I.name]. INTENT: [uppertext(user.a_intent)]") spread_germs_to_organ(I, user, tool) var/obj/item/thing = I.remove(target) if(!istype(thing)) diff --git a/code/modules/surgery/robotics.dm b/code/modules/surgery/robotics.dm index 84408dfa617..cd0f452e8e8 100644 --- a/code/modules/surgery/robotics.dm +++ b/code/modules/surgery/robotics.dm @@ -455,7 +455,7 @@ user.visible_message(" [user] has decoupled [target]'s [I] with \the [tool]." , \ " You have decoupled [target]'s [I] with \the [tool].") - add_logs(user, target, "surgically removed [I.name] from", addition="INTENT: [uppertext(user.a_intent)]") + add_attack_logs(user, target, "Surgically removed [I.name]. INTENT: [uppertext(user.a_intent)]") spread_germs_to_organ(I, user) var/obj/item/thing = I.remove(target) if(!istype(thing)) @@ -531,7 +531,7 @@ " You have decoupled [target]'s [affected.name] with \the [tool].") - add_logs(user, target, "surgically removed [affected.name] from", addition="INTENT: [uppertext(user.a_intent)]")//log it + add_attack_logs(user, target, "Surgically removed [affected.name] from. INTENT: [uppertext(user.a_intent)]")//log it var/atom/movable/thing = affected.droplimb(1,DROPLIMB_SHARP) if(istype(thing,/obj/item)) diff --git a/code/world.dm b/code/world.dm index 48c48debef5..8e8d2176172 100644 --- a/code/world.dm +++ b/code/world.dm @@ -1,11 +1,5 @@ -var/global/datum/global_init/init = new () - -/* - Pre-map initialization stuff should go here. -*/ -/datum/global_init/New() - setLog() - del(src) +// This file is just for the necessary /world definition +// Try looking in game/world.dm /world mob = /mob/new_player @@ -13,515 +7,3 @@ var/global/datum/global_init/init = new () area = /area/space view = "15x15" cache_lifespan = 0 //stops player uploaded stuff from being kept in the rsc past the current session - - -#define RECOMMENDED_VERSION 510 - -var/global/list/map_transition_config = MAP_TRANSITION_CONFIG - -/world/New() - diary << "\n\nStarting up. [time2text(world.timeofday, "hh:mm.ss")]\n---------------------" - diaryofmeanpeople << "\n\nStarting up. [time2text(world.timeofday, "hh:mm.ss")]\n---------------------" - if(byond_version < RECOMMENDED_VERSION) - log_to_dd("Your server's byond version does not meet the recommended requirements for this code. Please update BYOND") - - if(config && config.log_runtimes) - log = file("data/logs/runtime/[time2text(world.realtime,"YYYY-MM-DD-(hh-mm-ss)")]-runtime.log") - - if(config && config.server_name != null && config.server_suffix && world.port > 0) - // dumb and hardcoded but I don't care~ - config.server_name += " #[(world.port % 1000) / 100]" - - GLOB.timezoneOffset = text2num(time2text(0, "hh")) * 36000 - - - callHook("startup") - - src.update_status() - - . = ..() - - // Create robolimbs for chargen. - populate_robolimb_list() - - space_manager.initialize() //Before the MC starts up - - Master.Initialize(10, FALSE) - - processScheduler = new - master_controller = new /datum/controller/game_controller() - spawn(1) - processScheduler.deferSetupFor(/datum/controller/process/ticker) - processScheduler.setup() - - master_controller.setup() - - if(using_map && using_map.name) - map_name = "[using_map.name]" - else - map_name = "Unknown" - - - if(config && config.server_name) - name = "[config.server_name]: [station_name()]" - else - name = station_name() - - -#undef RECOMMENDED_VERSION - - return - -//world/Topic(href, href_list[]) -// to_chat(world, "Received a Topic() call!") -// to_chat(world, "[href]") -// for(var/a in href_list) -// to_chat(world, "[a]") -// if(href_list["hello"]) -// to_chat(world, "Hello world!") -// return "Hello world!" -// to_chat(world, "End of Topic() call.") -// ..() - -var/world_topic_spam_protect_ip = "0.0.0.0" -var/world_topic_spam_protect_time = world.timeofday - -/world/Topic(T, addr, master, key) - diary << "TOPIC: \"[T]\", from:[addr], master:[master], key:[key]" - - var/list/input = params2list(T) - var/key_valid = (config.comms_password && input["key"] == config.comms_password) //no password means no comms, not any password - - if("ping" in input) - var/x = 1 - for(var/client/C) - x++ - return x - - else if("players" in input) - var/n = 0 - for(var/mob/M in player_list) - if(M.client) - n++ - return n - - else if("status" in input) - var/list/s = list() - var/list/admins = list() - s["version"] = game_version - s["mode"] = master_mode - s["respawn"] = config ? abandon_allowed : 0 - s["enter"] = enter_allowed - s["vote"] = config.allow_vote_mode - s["ai"] = config.allow_ai - s["host"] = host ? host : null - s["players"] = list() - s["roundtime"] = worldtime2text() - s["stationtime"] = station_time_timestamp() - s["oldstationtime"] = classic_worldtime2text() // more "consistent" indication of the round's running time - s["listed"] = "Public" - if(!hub_password) - s["listed"] = "Invisible" - var/player_count = 0 - var/admin_count = 0 - - for(var/client/C in clients) - if(C.holder) - if(C.holder.fakekey) - continue //so stealthmins aren't revealed by the hub - admin_count++ - admins += list(list(C.key, C.holder.rank)) - s["player[player_count]"] = C.key - player_count++ - s["players"] = player_count - s["admins"] = admin_count - s["map_name"] = map_name ? map_name : "Unknown" - - if(key_valid) - if(ticker && ticker.mode) - s["real_mode"] = ticker.mode.name - - s["security_level"] = get_security_level() - s["ticker_state"] = ticker.current_state - - if(shuttle_master && shuttle_master.emergency) - // Shuttle status, see /__DEFINES/stat.dm - s["shuttle_mode"] = shuttle_master.emergency.mode - // Shuttle timer, in seconds - s["shuttle_timer"] = shuttle_master.emergency.timeLeft() - - for(var/i in 1 to admins.len) - var/list/A = admins[i] - s["admin[i - 1]"] = A[1] - s["adminrank[i - 1]"] = A[2] - - return list2params(s) - - else if("manifest" in input) - var/list/positions = list() - var/list/set_names = list( - "heads" = command_positions, - "sec" = security_positions, - "eng" = engineering_positions, - "med" = medical_positions, - "sci" = science_positions, - "car" = supply_positions, - "srv" = service_positions, - "civ" = civilian_positions, - "bot" = nonhuman_positions - ) - - for(var/datum/data/record/t in data_core.general) - var/name = t.fields["name"] - var/rank = t.fields["rank"] - var/real_rank = t.fields["real_rank"] - - var/department = 0 - for(var/k in set_names) - if(real_rank in set_names[k]) - if(!positions[k]) - positions[k] = list() - positions[k][name] = rank - department = 1 - if(!department) - if(!positions["misc"]) - positions["misc"] = list() - positions["misc"][name] = rank - - return json_encode(positions) - - else if("adminmsg" in input) - /* - We got an adminmsg from IRC bot lets split the input then validate the input. - expected output: - 1. adminmsg = ckey of person the message is to - 2. msg = contents of message, parems2list requires - 3. validatationkey = the key the bot has, it should match the gameservers commspassword in it's configuration. - 4. sender = the ircnick that send the message. - */ - if(!key_valid) - return keySpamProtect(addr) - - var/client/C - - for(var/client/K in clients) - if(K.ckey == input["adminmsg"]) - C = K - break - if(!C) - return "No client with that name on server" - - var/message = "IRC-Admin PM from [C.holder ? "IRC-" + input["sender"] : "Administrator"]: [input["msg"]]" - var/amessage = "IRC-Admin PM from IRC-[input["sender"]] to [key_name(C)] : [input["msg"]]" - - C.received_irc_pm = world.time - C.irc_admin = input["sender"] - - C << 'sound/effects/adminhelp.ogg' - to_chat(C, message) - - for(var/client/A in admins) - if(A != C) - to_chat(A, amessage) - - return "Message Successful" - - else if("notes" in input) - /* - We got a request for notes from the IRC Bot - expected output: - 1. notes = ckey of person the notes lookup is for - 2. validationkey = the key the bot has, it should match the gameservers commspassword in it's configuration. - */ - if(!key_valid) - return keySpamProtect(addr) - - return show_player_info_irc(input["notes"]) - - else if("announce" in input) - if(config.comms_password) - if(input["key"] != config.comms_password) - return "Bad Key" - else - for(var/client/C in clients) - to_chat(C, "PR: [input["announce"]]") - - else if("kick" in input) - /* - We have a kick request over coms. - Only needed portion is the ckey - */ - if(!key_valid) - return keySpamProtect(addr) - - var/client/C - - for(var/client/K in clients) - if(K.ckey == input["kick"]) - C = K - break - if(!C) - return "No client with that name on server" - - del(C) - - return "Kick Successful" - - else if("setlog" in input) - if(!key_valid) - return keySpamProtect(addr) - - setLog() - - return "Logs set to current date" - - else if("setlist" in input) - if(!key_valid) - return keySpamProtect(addr) - if(input["req"] == "public") - hub_password = hub_password_base - update_status() - return "Set listed status to public." - else - hub_password = "" - update_status() - return "Set listed status to invisible." - -/proc/keySpamProtect(var/addr) - if(world_topic_spam_protect_ip == addr && abs(world_topic_spam_protect_time - world.time) < 50) - spawn(50) - world_topic_spam_protect_time = world.time - return "Bad Key (Throttled)" - - world_topic_spam_protect_time = world.time - world_topic_spam_protect_ip = addr - return "Bad Key" - -/world/Reboot(var/reason, var/feedback_c, var/feedback_r, var/time) - if(reason == 1) //special reboot, do none of the normal stuff - if(usr) - message_admins("[key_name_admin(usr)] has requested an immediate world restart via client side debugging tools") - log_admin("[key_name(usr)] has requested an immediate world restart via client side debugging tools") - spawn(0) - to_chat(world, "Rebooting world immediately due to host request") - if(config && config.shutdown_on_reboot) - sleep(0) - if(shutdown_shell_command) - shell(shutdown_shell_command) - del(world) - return - else - return ..(1) - - var/delay - if(!isnull(time)) - delay = max(0,time) - else - delay = ticker.restart_timeout - if(ticker.delay_end) - to_chat(world, "An admin has delayed the round end.") - return - to_chat(world, "Rebooting world in [delay/10] [delay > 10 ? "seconds" : "second"]. [reason]") - - var/round_end_sound = pick(round_end_sounds) - var/sound_length = round_end_sounds[round_end_sound] - if(delay > sound_length) // If there's time, play the round-end sound before rebooting - spawn(delay - sound_length) - if(!ticker.delay_end) - world << round_end_sound - sleep(delay) - if(blackbox) - blackbox.save_all_data_to_sql() - if(ticker.delay_end) - to_chat(world, "Reboot was cancelled by an admin.") - return - feedback_set_details("[feedback_c]","[feedback_r]") - log_game("Rebooting world. [reason]") - //kick_clients_in_lobby("The round came to an end with you in the lobby.", 1) - - processScheduler.stop() - - if(config && config.shutdown_on_reboot) - sleep(0) - if(shutdown_shell_command) - shell(shutdown_shell_command) - del(world) - return - else - for(var/client/C in clients) - if(config.server) //if you set a server location in config.txt, it sends you there instead of trying to reconnect to the same world address. -- NeoFite - C << link("byond://[config.server]") - ..(0) - -#define INACTIVITY_KICK 6000 //10 minutes in ticks (approx.) -/world/proc/KickInactiveClients() - var/tmp/sleep_check = 0 // buffer for checking elapsed ticks - var/tmp/work_length = 2 // number of ticks to run before yielding cpu - var/tmp/sleep_length = 5 // number of ticks to yield - var/waiting=1 - - sleep_check = world.timeofday - - while(waiting) - waiting = 0 - sleep(INACTIVITY_KICK) - for(var/client/C in clients) - if(C.holder) return - if(C.is_afk(INACTIVITY_KICK)) - if(!istype(C.mob, /mob/dead)) - log_access("AFK: [key_name(C)]") - to_chat(C, "You have been inactive for more than 10 minutes and have been disconnected.") - del(C) - if( ((world.timeofday - sleep_check) > work_length) || ((world.timeofday - sleep_check) < 0) ) - sleep(sleep_length) - sleep_check = world.timeofday - waiting++ -//#undef INACTIVITY_KICK - -/hook/startup/proc/loadMode() - world.load_mode() - return 1 - -/world/proc/load_mode() - var/list/Lines = file2list("data/mode.txt") - if(Lines.len) - if(Lines[1]) - master_mode = Lines[1] - diary << "Saved mode is '[master_mode]'" - -/world/proc/save_mode(var/the_mode) - var/F = file("data/mode.txt") - fdel(F) - F << the_mode - -/hook/startup/proc/loadMOTD() - world.load_motd() - return 1 - -/world/proc/load_motd() - join_motd = file2text("config/motd.txt") - - -/proc/load_configuration() - config = new /datum/configuration() - config.load("config/config.txt") - config.load("config/game_options.txt","game_options") - config.loadsql("config/dbconfig.txt") - config.loadoverflowwhitelist("config/ofwhitelist.txt") - // apply some settings from config.. - -/world/proc/update_status() - var/s = "" - - if(config && config.server_name) - s += "[config.server_name] — " - - s += "[station_name()]"; - s += " (" - s += "" //Change this to wherever you want the hub to link to. - s += "[game_version]" - s += "" - s += ")" - s += "
The Perfect Mix of RP & Action
" - - - - - var/list/features = list() - - if(ticker) - if(master_mode) - features += master_mode - else - features += "STARTING" - - if(!enter_allowed) - features += "closed" - - features += abandon_allowed ? "respawn" : "no respawn" - - if(config && config.allow_vote_mode) - features += "vote" - - if(config && config.allow_ai) - features += "AI allowed" - - var/n = 0 - for(var/mob/M in player_list) - if(M.client) - n++ - - if(n > 1) - features += "~[n] players" - else if(n > 0) - features += "~[n] player" - - /* - is there a reason for this? the byond site shows 'hosted by X' when there is a proper host already. - if(host) - features += "hosted by [host]" - */ - -// if(!host && config && config.hostedby) -// features += "hosted by [config.hostedby]" - - if(features) - s += ": [jointext(features, ", ")]" - - /* does this help? I do not know */ - if(src.status != s) - src.status = s - -#define FAILED_DB_CONNECTION_CUTOFF 5 -var/failed_db_connections = 0 -var/failed_old_db_connections = 0 - -/proc/setLog() - var/date_string = time2text(world.realtime, "YYYY/MM-Month/DD-Day") - href_logfile = file("data/logs/[date_string] hrefs.htm") - diary = file("data/logs/[date_string].log") - diaryofmeanpeople = file("data/logs/[date_string] Attack.log") - -/hook/startup/proc/connectDB() - if(!setup_database_connection()) - log_to_dd("Your server failed to establish a connection with the feedback database.") - else - log_to_dd("Feedback database connection established.") - return 1 - -/proc/setup_database_connection() - - if(failed_db_connections > FAILED_DB_CONNECTION_CUTOFF) //If it failed to establish a connection more than 5 times in a row, don't bother attempting to conenct anymore. - return 0 - - if(!dbcon) - dbcon = new() - - var/user = sqlfdbklogin - var/pass = sqlfdbkpass - var/db = sqlfdbkdb - var/address = sqladdress - var/port = sqlport - - dbcon.Connect("dbi:mysql:[db]:[address]:[port]","[user]","[pass]") - . = dbcon.IsConnected() - if( . ) - failed_db_connections = 0 //If this connection succeeded, reset the failed connections counter. - else - failed_db_connections++ //If it failed, increase the failed connections counter. - log_to_dd(dbcon.ErrorMsg()) - - return . - -//This proc ensures that the connection to the feedback database (global variable dbcon) is established -proc/establish_db_connection() - if(failed_db_connections > FAILED_DB_CONNECTION_CUTOFF) - return 0 - - if(!dbcon || !dbcon.IsConnected()) - return setup_database_connection() - else - return 1 - -#undef FAILED_DB_CONNECTION_CUTOFF - diff --git a/config/example/config.txt b/config/example/config.txt index 95ec5292021..d0eb704ea07 100644 --- a/config/example/config.txt +++ b/config/example/config.txt @@ -62,16 +62,13 @@ LOG_PDA LOG_RUNTIME ## log world.log messages -# LOG_WORLD_OUTPUT +LOG_WORLD_OUTPUT ## log all Topic() calls (for use by coders in tracking down Topic issues) # LOG_HREFS ## log admin warning messages -##LOG_ADMINWARN ## Also duplicates a bunch of other messages. - -## disconnect players who did nothing during 15 minutes -KICK_INACTIVE +LOG_ADMINWARN ## probablities for game modes chosen in "secret" and "random" modes ## diff --git a/manuals.dm b/manuals.dm deleted file mode 100644 index 6be7958d294..00000000000 --- a/manuals.dm +++ /dev/null @@ -1,2563 +0,0 @@ -/*********************MANUALS (BOOKS)***********************/ - -//Oh god what the fuck I am not good at computer -/obj/item/book/manual - icon = 'icons/obj/library.dmi' - due_date = 0 // Game time in 1/10th seconds - unique = 1 // 0 - Normal book, 1 - Should not be treated as normal book, unable to be copied, unable to be modified - - -/obj/item/book/manual/engineering_construction - name = "Station Repairs and Construction" - icon_state ="bookEngineering" - author = "Engineering Encyclopedia" // Who wrote the thing, can be changed by pen or PC. It is not automatically assigned - title = "Station Repairs and Construction" - dat = {" - - - - - - - - - - - "} - -/obj/item/book/manual/engineering_particle_accelerator - name = "Particle Accelerator User's Guide" - icon_state ="bookParticleAccelerator" - author = "Engineering Encyclopedia" // Who wrote the thing, can be changed by pen or PC. It is not automatically assigned - title = "Particle Accelerator User's Guide" -//big pile of shit below. - - dat = {" - - - - - -

Experienced user's guide

- -

Setting up

- -
    -
  1. Wrench all pieces to the floor
  2. -
  3. Add wires to all the pieces
  4. -
  5. Close all the panels with your screwdriver
  6. -
- -

Use

- -
    -
  1. Open the control panel
  2. -
  3. Set the speed to 2
  4. -
  5. Start firing at the singularity generator
  6. -
  7. When the singularity reaches a large enough size so it starts moving on it's own set the speed down to 0, but don't shut it off
  8. -
  9. Remember to wear a radiation suit when working with this machine... we did tell you that at the start, right?
  10. -
- - - "} - - -/obj/item/book/manual/supermatter_engine - name = "Supermatter Engine User's Guide" - icon_state = "bookParticleAccelerator" //TEMP FIXME - author = "Waleed Asad" - title = "Supermatter Engine User's Guide" - - dat = {"Engineering notes on single-stage Supermatter engine,
- -Waleed Asad
- - A word of caution, do not enter the engine room, for any reason, without radiation protection and mesons on. The status of the engine may be unpredictable even when you believe it is .off.. This is an important level of personal protection.

- - The engine has two basic modes of functionality. He has observed that it is capable of both a safe level of operation and a modified, high output mode.

- -
Notes on starting the basic function mode, dubbed .Heat-Primary Mode..


- - 1. Prepare collector arrays. This is done standard to any text on their function by wrenching them down, filling six plasma tanks with a plasma canister, and inserting the tank into the collectors one by one. Finally, initialize each collector.

- - 2. Prepare gas system. Before introducing any gas to the Supermatter engine room, it is important to remember the small but vital steps to preparing this section. First, set the input gas pump and output gas flow pump to 4500, or maximum flow. Second, switch the digital switching valve into the .up. position, in order to circulate the gas back toward the coolers and collectors.

- - 3. Apply N2 gas. Retrieve the two N2 canisters from storage and bring them to the engine room. Attach one of them to the input section of the engine gas system located next to the collectors. Keep it attached until the N2 pressure is low enough to turn the canister light red. Replace it with the second canister to keep N2 pressure at optimal levels.

- - 4. Begin primary emitter burst series. This means firing a single emitter for its first four shots. It is important to move to this step quickly. The onboard SMES units may not have enough power to run the emitters if left alone too long on-station. This engine can produce enough power on its own to run the entire station, ignoring the SMES units completely, and is wired to do so.

- - 5. Switch SMES units to primary settings. Maximize input and set the devices to automatically charge, additionally turn their outputs on if they are off unless power is to be saved (Which can be useful in case of later failures.)

- - 6. Begin secondary emitter burst series. Before firing the emitter again, check the power in the line with a multimeter (Do not forget electrical gloves.) The engine is running at high efficiency when the value exceeds 200,000 power units.

- - 7. Maintain engine power. When power in the lines gets low, add an additional emitter burst series to bring power to normal levels.


- - - -
The second mode for running the engine uses a gas mix to produce a reaction within the Supermatter. This mode requires CE or Atmospheric help to setup. This has been dubbed the .O2-Reaction Mode..


- - THIS MODE CAN CAUSE A RUNAWAY REACTION, LEADING TO CATASTROPHIC FAILURE IF NOT MAINTAINED. NEVER FORGET ABOUT THE ENGINE IN THIS MODE.

- - Additionally, this mode can be used for what is called a .Cold Start.. If the station has no power in the SMES to run the emitters, using this mode will allow enough power output to run them, and quickly reach an acceptable level of power output.

- - 1. Prepare collector arrays. This is done standard to any text on their function by wrenching them down, filling six plasma tanks with a plasma canister, and inserting the tank into the collectors one by one. Finally, initialize each collector.

- - 2. Prepare gas system. Before introducing any gas to the Supermatter engine room, it is important to remember the small but vital steps to preparing this section. First, set the input gas pump and output gas flow pump to 4500, or maximum flow. Second, switch the digital switching valve into the .up. position, in order to circulate the gas back toward the coolers and collectors.

- - 3. Modify the engine room filters. Unlike the Heat-Primary Mode, it is important to change the filters attached to the gas system to stop filtering O2, and start filtering Carbon Molecules. O2-Reaction Mode produces far more plasma than Heat-Primary, therefor filtering it off is essential.

- - 4. Switch SMES units to primary settings. Maximize input and set the devices to automatically charge, additionally turn their outputs on if they are off unless power is to be saved (Which can be useful in case of later failures.) If you check the power in the system lines at this point you will find that it is constantly going up. Indeed, with just the addition of O2 to the Supermatter, it will begin outputting power.

- - 5. Begin primary emitter burst series. Fire a single emitter for a series of four pulses, or a single series, and turn it off. Do not over power the Supermatter. The reaction is self sustaining and propagating. As long as O2 is in the chamber, it will continue outputting MORE power.

- - 6. Maintain follow up operations. Remember to check the temp of the core gas and switch to the Heat-Primary function, or vent the core room when problems begin if required.

- - Notes on Supermatter Reaction Function and Drawbacks-

- - After several hours of observation an interesting phenomenon was witnessed. The Supermatter undergoes a constant self-sustaining reaction when given an extremely high O2 concentration. Anything about 80% or higher typically will cause this reaction. The Supermatter will continue to react whenever this gas mix is in the same room as the Supermatter.

- - To understand why O2-Reaction mode is dangerous, the core principle of the Supermatter must be understood. The Supermatter emits three things when .not safe,. that is any time it is giving off power. These things are:

- - *Radiation (which is converted into power by the collectors,)
- *Heat (which is removed via the gas exchange system and coolers,)
- *External gas (in the form of plasma and O2.)
- - When in Heat-Primary mode, far more heat and plasma are produced than radiation. In O2-Reaction mode, very little heat and only moderate amounts of plasma are produced, however HUGE amounts of energy leaving the Supermatter is in the form of radiation.

- - The O2-Reaction engine mode has a single drawback which has been eluded to more than once so far and that is very simple. The engine room will continue to grow hotter as the constant reaction continues. Eventually, there will be what he calls the .critical gas mix.. This is the point at which the constant adding of plasma to the mix of air around the Supermatter changes the gas concentration to below the tolerance. When this happens, two things occur. First, the Supermatter switches to its primary mode of operation where in huge amounts of heat are produced by the engine rather than low amounts with high power output. Second, an uncontrollable increase in heat within the Supermatter chamber will occur. This will lead to a spark-up, igniting the plasma in the Supermatter chamber, wildly increasing both pressure and temperature.

- - While the O2-Reaction mode is dangerous, it does produce heavy amounts of energy. Consider using this mode only in short amounts to fill the SMES, and switch back later in the shift to keep things flowing normally.

- - - Notes on Supermatter Containment and Emergency Procedures-

- - While a constant vigil on the Supermatter is not required, regular checkups are important. Verify the temp of gas leaving the Supermatter chamber for unsafe levels, and ensure that the plasma in the chamber is at a safe concentration. Of course, also make sure the chamber is not on fire. A fire in the core chamber is very difficult to put out. As any Toxin scientist can tell you, even low amounts of plasma can burn at very high temperatures. This burning creates a huge increase in pressure and more importantly, temperature of the crystal itself.

- - The Supermatter is strong, but not invincible. When the Supermatter is heated too much, its crystal structure will attempt to liquify. The change in atomic structure of the Supermatter leads to a single reaction, a massive explosion. The computer chip attached to the Supermatter core will warn the station when stability is threatened. It will then offer a second warning, when things have become dangerously close to total destruction of the core.

- - Located both within the supermatter monitoring room and engine room is the vent control button. This button allows the Core Vent Controls to be accessed, venting the room to space. Remember however, that this process takes time. If a fire is raging, and the pressure is higher than fathomable, it will take a great deal of time to vent the room. Also located in the supermatter monitoring room is the emergency core eject button. A new core can be ordered from cargo. It is often not worth the lives of the crew to hold on to it, not to mention the structural damage. However, if by some mistake the Supermatter is pushed off or removed from the mass ejector it sits on, manual reposition will be required. Which is very dangerous and often leads to death.

- - The Supermatter is extremely dangerous. More dangerous than people give it credit for. It can destroy you in an instant, without hesitation, reducing you to a pile of dust. When working closely with Supermatter it is.. suggested to get a genetic backup and do not wear any items of value to you. The Supermatter core can be pulled if grabbed properly by the base, but pushing is not possible.


- - - In Closing-

- - Remember that the Supermatter is dangerous, and the core is dangerous still. Venting the core room is always an option if you are even remotely worried, utilizing Atmospherics to properly ready the room once more for core function. It is always a good idea to check up regularly on the temperature of gas leaving the chamber, as well as the power in the system lines. Lastly, once again remember, never touch the Supermatter with anything. Ever.

- - -Waleed Asad, Senior Engine Technician."} - -/obj/item/book/manual/engineering_hacking - name = "Hacking" - icon_state ="bookHacking" - author = "Engineering Encyclopedia" // Who wrote the thing, can be changed by pen or PC. It is not automatically assigned - title = "Hacking" -//big pile of shit below. - - dat = {" - - - - - - - - - - - "} - -/obj/item/book/manual/engineering_singularity_safety - name = "Singularity Safety in Special Circumstances" - icon_state ="bookEngineeringSingularitySafety" - author = "Engineering Encyclopedia" // Who wrote the thing, can be changed by pen or PC. It is not automatically assigned - title = "Singularity Safety in Special Circumstances" -//big pile of shit below. - - dat = {" - - - - -

Singularity Safety in Special Circumstances

- -

Power outage

- - A power problem has made the entire station loose power? Could be station-wide wiring problems or syndicate power sinks. In any case follow these steps: -

- Step one: PANIC!
- Step two: Get your ass over to engineering! QUICKLY!!!
- Step three: Get to the Area Power Controller which controls the power to the emitters.
- Step four: Swipe it with your ID card - if it doesn't unlock, continue with step 15.
- Step five: Open the console and disengage the cover lock.
- Step six: Pry open the APC with a Crowbar.
- Step seven: Take out the empty power cell.
- Step eight: Put in the new, full power cell - if you don't have one, continue with step 15.
- Step nine: Quickly put on a Radiation suit.
- Step ten: Check if the singularity field generators withstood the down-time - if they didn't, continue with step 15.
- Step eleven: Since disaster was averted you now have to ensure it doesn't repeat. If it was a powersink which caused it and if the engineering apc is wired to the same powernet, which the powersink is on, you have to remove the piece of wire which links the apc to the powernet. If it wasn't a powersink which caused it, then skip to step 14.
- Step twelve: Grab your crowbar and pry away the tile closest to the APC.
- Step thirteen: Use the wirecutters to cut the wire which is conecting the grid to the terminal.
- Step fourteen: Go to the bar and tell the guys how you saved them all. Stop reading this guide here.
- Step fifteen: GET THE FUCK OUT OF THERE!!!
-

- -

Shields get damaged

- - Step one: GET THE FUCK OUT OF THERE!!! FORGET THE WOMEN AND CHILDREN, SAVE YOURSELF!!!
- - - "} - -/obj/item/book/manual/hydroponics_pod_people - name = "The Human Harvest - From seed to market" - icon_state ="bookHydroponicsPodPeople" - author = "Farmer John" - title = "The Human Harvest - From seed to market" - dat = {" - - - - -

Growing Humans

- - Why would you want to grow humans? Well I'm expecting most readers to be in the slave trade, but a few might actually - want to revive fallen comrades. Growing pod people is easy, but prone to disaster. -

-

    -
  1. Find a dead person who is in need of cloning.
  2. -
  3. Take a blood sample with a syringe.
  4. -
  5. Inject a seed pack with the blood sample.
  6. -
  7. Plant the seeds.
  8. -
  9. Tend to the plants water and nutrition levels until it is time to harvest the cloned human.
  10. -
-

- It really is that easy! Good luck! - - - - "} - -/obj/item/book/manual/medical_cloning - name = "Cloning techniques of the 26th century" - icon_state ="bookCloning" - author = "Medical Journal, volume 3" // Who wrote the thing, can be changed by pen or PC. It is not automatically assigned - title = "Cloning techniques of the 26th century" -//big pile of shit below. - - dat = {" - - - - - -

How to Clone People

- So thereÂ’s 50 dead people lying on the floor, chairs are spinning like no tomorrow and you havenÂ’t the foggiest idea of what to do? Not to worry! This guide is intended to teach you how to clone people and how to do it right, in a simple step-by-step process! If at any point of the guide you have a mental meltdown, genetics probably isnÂ’t for you and you should get a job-change as soon as possible before youÂ’re sued for malpractice. - -
    -
  1. Acquire body
  2. -
  3. Strip body
  4. -
  5. Put body in cloning machine
  6. -
  7. Scan body
  8. -
  9. Clone body
  10. -
  11. Get clean Structurel Enzymes for the body
  12. -
  13. Put body in morgue
  14. -
  15. Await cloned body
  16. -
  17. Use the clean SW injector
  18. -
  19. Give person clothes back
  20. -
  21. Send person on their way
  22. -
- -

Step 1: Acquire body

- This is pretty much vital for the process because without a body, you cannot clone it. Usually, bodies will be brought to you, so you do not need to worry so much about this step. If you already have a body, great! Move on to the next step. - -

Step 2: Strip body

- The cloning machine does not like abiotic items. What this means is you canÂ’t clone anyone if theyÂ’re wearing clothes, so take all of it off. If itÂ’s just one person, itÂ’s courteous to put their possessions in the closet. If you have about seven people awaiting cloning, just leave the piles where they are, but donÂ’t mix them around and for GodÂ’s sake donÂ’t let people in to steal them. - -

Step 3: Put body in cloning machine

- Grab the body and then put it inside the DNA modifier. If you cannot do this, then you messed up at Step 2. Go back and check you took EVERYTHING off - a commonly missed item is their headset. - -

Step 4: Scan body

- Go onto the computer and scan the body by pressing ‘Scan - ’. If you’re successful, they will be added to the records (note that this can be done at any time, even with living people, so that they can be cloned without a body in the event that they are lying dead on port solars and didn‘t turn on their suit sensors)! If not, and it says “Error: Mental interface failure.”, then they have left their bodily confines and are one with the spirits. If this happens, just shout at them to get back in their body, click ‘Refresh‘ and try scanning them again. If there’s no success, threaten them with gibbing. Still no success? Skip over to Step 7 and don‘t continue after it, as you have an unresponsive body and it cannot be cloned. If you got “Error: Unable to locate valid genetic data.“, you are trying to clone a monkey - start over. - -

Step 5: Clone body

- Now that the body has a record, click ’View Records’, click the subject’s name, and then click ‘Clone’ to start the cloning process. Congratulations! You’re halfway there. Remember not to ‘Eject’ the cloning pod as this will kill the developing clone and you’ll have to start the process again. - -

Step 6: Get clean SEs for body

- Cloning is a finicky and unreliable process. Whilst it will most certainly bring someone back from the dead, they can have any number of nasty disabilities given to them during the cloning process! For this reason, you need to prepare a clean, defect-free Structural Enzyme (SE) injection for when they’re done. If you’re a competent Geneticist, you will already have one ready on your working computer. If, for any reason, you do not, then eject the body from the DNA modifier (NOT THE CLONING POD) and take it next door to the Genetics research room. Put the body in one of those DNA modifiers and then go onto the console. Go into View/Edit/Transfer Buffer, find an open slot and click “SE“ to save it. Then click ‘Injector’ to get the SEs in syringe form. Put this in your pocket or something for when the body is done. - -

Step 7: Put body in morgue

- Now that the cloning process has been initiated and you have some clean Structural Enzymes, you no longer need the body! Drag it to the morgue and tell the Chef over the radio that they have some fresh meat waiting for them in there. To put a body in a morgue bed, simply open the tray, grab the body, put it on the open tray, then close the tray again. Use one of the nearby pens to label the bed “CHEF MEAT” in order to avoid confusion. - -

Step 8: Await cloned body

- Now go back to the lab and wait for your patient to be cloned. It wonÂ’t be long now, I promise. - -

Step 9: Use the clean SE injector on person

- Has your body been cloned yet? Great! As soon as the guy pops out, grab your injector and jab it in them. Once youÂ’ve injected them, they now have clean Structural Enzymes and their defects, if any, will disappear in a short while. - -

Step 10: Give person clothes back

- Obviously the person will be naked after they have been cloned. Provided you werenÂ’t an irresponsible little shit, you should have protected their possessions from thieves and should be able to give them back to the patient. No matter how cruel you are, itÂ’s simply against protocol to force your patients to walk outside naked. - -

Step 11: Send person on their way

- Give the patient one last check-over - make sure they donÂ’t still have any defects and that they have all their possessions. Ask them how they died, if they know, so that you can report any foul play over the radio. Once youÂ’re done, your patient is ready to go back to work! Chances are they do not have Medbay access, so you should let them out of Genetics and the Medbay main entrance. - -

If youÂ’ve gotten this far, congratulations! You have mastered the art of cloning. Now, the real problem is how to resurrect yourself after that traitor had his way with you for cloning his target. - - - - - - "} - - -/obj/item/book/manual/ripley_build_and_repair - name = "APLU \"Ripley\" Construction and Operation Manual" - icon_state ="book" - author = "Weyland-Yutani Corp" // Who wrote the thing, can be changed by pen or PC. It is not automatically assigned - title = "APLU \"Ripley\" Construction and Operation Manual" -//big pile of shit below. - - dat = {" - - - - -

- Weyland-Yutani - Building Better Worlds -

Autonomous Power Loader Unit \"Ripley\"

-
-

Specifications:

-
    -
  • Class: Autonomous Power Loader
  • -
  • Scope: Logistics and Construction
  • -
  • Weight: 820kg (without operator and with empty cargo compartment)
  • -
  • Height: 2.5m
  • -
  • Width: 1.8m
  • -
  • Top speed: 5km/hour
  • -
  • Operation in vacuum/hostile environment: Possible -
  • Airtank Volume: 500liters
  • -
  • Devices: -
      -
    • Hydraulic Clamp
    • -
    • High-speed Drill
    • -
    -
  • -
  • Propulsion Device: Powercell-powered electro-hydraulic system.
  • -
  • Powercell capacity: Varies.
  • -
- -

Construction:

-
    -
  1. Connect all exosuit parts to the chassis frame
  2. -
  3. Connect all hydraulic fittings and tighten them up with a wrench
  4. -
  5. Adjust the servohydraulics with a screwdriver
  6. -
  7. Wire the chassis. (Cable is not included.)
  8. -
  9. Use the wirecutters to remove the excess cable if needed.
  10. -
  11. Install the central control module (Not included. Use supplied datadisk to create one).
  12. -
  13. Secure the mainboard with a screwdriver.
  14. -
  15. Install the peripherals control module (Not included. Use supplied datadisk to create one).
  16. -
  17. Secure the peripherals control module with a screwdriver
  18. -
  19. Install the internal armor plating (Not included due to Nanotrasen regulations. Can be made using 5 metal sheets.)
  20. -
  21. Secure the internal armor plating with a wrench
  22. -
  23. Weld the internal armor plating to the chassis
  24. -
  25. Install the external reinforced armor plating (Not included due to Nanotrasen regulations. Can be made using 5 reinforced metal sheets.)
  26. -
  27. Secure the external reinforced armor plating with a wrench
  28. -
  29. Weld the external reinforced armor plating to the chassis
  30. -
  31. -
  32. Additional Information:
  33. -
  34. The firefighting variation is made in a similar fashion.
  35. -
  36. A firesuit must be connected to the Firefighter chassis for heat shielding.
  37. -
  38. Internal armor is plasteel for additional strength.
  39. -
  40. External armor must be installed in 2 parts, totaling 10 sheets.
  41. -
  42. Completed mech is more resiliant against fire, and is a bit more durable overall
  43. -
  44. Nanotrasen is determined to the safety of its investments employees.
  45. -
- - - -

Operation

- Coming soon... - "} - -/obj/item/book/manual/experimentor - name = "Mentoring your Experiments" - icon_state = "rdbook" - author = "Dr. H.P. Kritz" - title = "Mentoring your Experiments" - dat = {" - - - - -

THE E.X.P.E.R.I-MENTOR

- The Enhanced Xenobiological Period Extraction (and) Restoration Instructor is a machine designed to discover the secrets behind every item in existence. - With advanced technology, it can process 99.95% of items, and discover their uses and secrets. - The E.X.P.E.R.I-MENTOR is a Research apparatus that takes items, and through a process of elimination, it allows you to deduce new technological designs from them. - Due to the volatile nature of the E.X.P.E.R.I-MENTOR, there is a slight chance for malfunction, potentially causing irreparable damage to you or your environment. - However, upgrading the apparatus has proven to decrease the chances of undesirable, potentially life-threatening outcomes. - Please note that the E.X.P.E.R.I-MENTOR uses a state-of-the-art random generator, which has a larger entropy than the observable universe, - therefore it can generate wildly different results each day, therefore it is highly suggested to re-scan objects of interests frequently (e.g. each shift). - -

BASIC PROCESS

- The usage of the E.X.P.E.R.I-MENTOR is quite simple: -
    -
  1. Find an item with a technological background
  2. -
  3. Insert the item into the E.X.P.E.R.I-MENTOR
  4. -
  5. Cycle through each processing method of the device.
  6. -
  7. Stand back, even in case of a successful experiment, as the machine might produce undesired behaviour.
  8. -
- -

ADVANCED USAGE

- The E.X.P.E.R.I-MENTOR has a variety of uses, beyond menial research work. The different results can be used to combat localised events, or even to get special items. - - The E.X.P.E.R.I-MENTOR's OBLITERATE function has the added use of transferring the destroyed item's material into a linked lathe. - - The IRRADIATE function can be used to transform items into other items, resulting in potential upgrades (or downgrades). - - Users should remember to always wear appropriate protection when using the machine, because malfunction can occur at any moment! - -

EVENTS

-

GLOBAL (happens at any time):

-
    -
  1. DETECTION MALFUNCTION - The machine's onboard sensors have malfunctioned, causing it to redefine the item's experiment type. - Produces the message: The E.X.P.E.R.I-MENTOR's onboard detection system has malfunctioned!
  2. - -
  3. IANIZATION - The machine's onboard corgi-filter has malfunctioned, causing it to produce a corgi from.. somewhere. - Produces the message: The E.X.P.E.R.I-MENTOR melts the banana, ian-izing the air around it!
  4. - -
  5. RUNTIME ERROR - The machine's onboard C4T-P processor has encountered a critical error, causing it to produce a cat from.. somewhere. - Produces the message: The E.X.P.E.R.I-MENTOR encounters a run-time error!
  6. - -
  7. B100DG0D.EXE - The machine has encountered an unknown subroutine, which has been injected into it's runtime. It upgrades the held item! - Produces the message: The E.X.P.E.R.I-MENTOR improves the banana, drawing the life essence of those nearby!
  8. - -
  9. POWERSINK - The machine's PSU has tripped the charging mechanism! It consumes massive amounts of power! - Produces the message: The E.X.P.E.R.I-MENTOR begins to smoke and hiss, shaking violently!
  10. -
-

FAIL:

- This event is produced when the item mismatches the selected experiment. - Produces a random message similar to: "the Banana rumbles, and shakes, the experiment was a failure!" - -

POKE:

-
    -
  1. WILD ARMS - The machine's gryoscopic processors malfunction, causing it to lash out at nearby people with it's arms. - Produces the message: The E.X.P.E.R.I-MENTOR malfunctions and destroys the banana, lashing it's arms out at nearby people!
  2. - -
  3. MISTYPE - The machine's interface has been garbled, and it switches to OBLITERATE. - Produces the message: The E.X.P.E.R.I-MENTOR malfunctions!
  4. - -
  5. THROW - The machine's spatial recognition device has shifted several meters across the room, causing it to try and repostion the item there. - Produces the message: The E.X.P.E.R.I-MENTOR malfunctions, throwing the banana!
  6. -
-

IRRADIATE:

-
    -
  1. RADIATION LEAK - The machine's shield has failed, resulting in a toxic radiation leak. - Produces the message: The E.X.P.E.R.I-MENTOR malfunctions, melting the banana and leaking radiation!
  2. - -
  3. RADIATION DUMP - The machine's recycling and containment functions have failed, resulting in a dump of toxic waste around it - Produces the message: The E.X.P.E.R.I-MENTOR malfunctions, spewing toxic waste!
  4. - -
  5. MUTATION - The machine's radio-isotope level meter has malfunctioned, causing it over-irradiate the item, making it transform. - Produces the message: The E.X.P.E.R.I-MENTOR malfunctions, transforming the banana!
  6. -
-

GAS:

-
    -
  1. TOXIN LEAK - The machine's filtering and vent systems have failed, resulting in a cloud of toxic gas being expelled. - Produces the message: The E.X.P.E.R.I-MENTOR destroys the banana, leaking dangerous gas!
  2. - -
  3. GAS LEAK - The machine's vent systems have failed, resulting in a cloud of harmless, but obscuring gas. - Produces the message: The E.X.P.E.R.I-MENTOR malfunctions, spewing harmless gas!
  4. - -
  5. ELECTROMAGNETIC IONS - The machine's electrolytic scanners have failed, causing a dangerous Electromagnetic reaction. - Produces the message: The E.X.P.E.R.I-MENTOR melts the banana, ionizing the air around it!
  6. -
-

HEAT:

-
    -
  1. TOASTER - The machine's heating coils have come into contact with the machine's gas storage, causing a large, sudden blast of flame. - Produces the message: The E.X.P.E.R.I-MENTOR malfunctions, melting the banana and releasing a burst of flame!
  2. - -
  3. SAUNA - The machine's vent loop has sprung a leak, resulting in a large amount of superheated air being dumped around it. - Produces the message: The E.X.P.E.R.I-MENTOR malfunctions, melting the banana and leaking hot air!
  4. - -
  5. EMERGENCY VENT - The machine's temperature gauge has malfunctioned, resulting in it attempting to cool the area around it, but instead, dumping a cloud of steam. - Produces the message: The E.X.P.E.R.I-MENTOR malfunctions, activating it's emergency coolant systems!
  6. -
-

COLD:

-
    -
  1. FREEZER - The machine's cooling loop has sprung a leak, resulting in a cloud of super-cooled liquid being blasted into the air. - Produces the message: The E.X.P.E.R.I-MENTOR malfunctions, shattering the banana and releasing a dangerous cloud of coolant!
  2. - -
  3. FRIDGE - The machine's cooling loop has been exposed to the outside air, resulting in a large decrease in temperature. - Produces the message: The E.X.P.E.R.I-MENTOR malfunctions, shattering the banana and leaking cold air!
  4. - -
  5. SNOWSTORM - The machine's cooling loop has come into contact with the heating coils, resulting in a sudden blast of cool air. - Produces the message: The E.X.P.E.R.I-MENTOR malfunctions, releasing a flurry of chilly air as the banana pops out!
  6. -
-

OBLITERATE:

-
    -
  1. IMPLOSION - The machine's pressure leveller has malfunctioned, causing it to pierce the space-time momentarily, making everything in the area fly towards it. - Produces the message: The E.X.P.E.R.I-MENTOR's crusher goes way too many levels too high, crushing right through space-time!
  2. - -
  3. DISTORTION - The machine's pressure leveller has completely disabled, resulting in a momentary space-time distortion, causing everything to fly around. - Produces the message: The E.X.P.E.R.I-MENTOR's crusher goes one level too high, crushing right into space-time!
  4. -
- - - "} - -/obj/item/book/manual/research_and_development - name = "Research and Development 101" - icon_state = "rdbook" - author = "Dr. L. Ight" - title = "Research and Development 101" - dat = {" - - - - - - -

Science For Dummies

- So you want to further SCIENCE? Good man/woman/thing! However, SCIENCE is a complicated process even though it's quite easy. For the most part, it's a three step process: -
    -
  1. 1) Deconstruct items in the Destructive Analyzer to advance technology or improve the design.
  2. -
  3. 2) Build unlocked designs in the Protolathe and Circuit Imprinter
  4. -
  5. 3) Repeat!
  6. -
- - Those are the basic steps to furthing science. What do you do science with, however? Well, you have four major tools: R&D Console, the Destructive Analyzer, the Protolathe, and the Circuit Imprinter. - -

The R&D Console

- The R&D console is the cornerstone of any research lab. It is the central system from which the Destructive Analyzer, Protolathe, and Circuit Imprinter (your R&D systems) are controled. More on those systems in their own sections. On its own, the R&D console acts as a database for all your technological gains and new devices you discover. So long as the R&D console remains intact, you'll retain all that SCIENCE you've discovered. Protect it though, because if it gets damaged, you'll lose your data! In addition to this important purpose, the R&D console has a disk menu that lets you transfer data from the database onto disk or from the disk into the database. It also has a settings menu that lets you re-sync with nearby R&D devices (if they've become disconnected), lock the console from the unworthy, upload the data to all other R&D consoles in the network (all R&D consoles are networked by default), connect/disconnect from the network, and purge all data from the database. - NOTE: The technology list screen, circuit imprinter, and protolathe menus are accessible by non-scientists. This is intended to allow 'public' systems for the plebians to utilize some new devices. - -

Destructive Analyzer

- This is the source of all technology. Whenever you put a handheld object in it, it analyzes it and determines what sort of technological advancements you can discover from it. If the technology of the object is equal or higher then your current knowledge, you can destroy the object to further those sciences. Some devices (notably, some devices made from the protolathe and circuit imprinter) aren't 100% reliable when you first discover them. If these devices break down, you can put them into the Destructive Analyzer and improve their reliability rather then futher science. If their reliability is high enough ,it'll also advance their related technologies. - -

Circuit Imprinter

- This machine, along with the Protolathe, is used to actually produce new devices. The Circuit Imprinter takes glass and various chemicals (depends on the design) to produce new circuit boards to build new machines or computers. It can even be used to print AI modules. - -

Protolathe

- This machine is an advanced form of the Autolathe that produce non-circuit designs. Unlike the Autolathe, it can use processed metal, glass, solid plasma, silver, gold, and diamonds along with a variety of chemicals to produce devices. The downside is that, again, not all devices you make are 100% reliable when you first discover them. - -

Reliability and You

- As it has been stated, many devices when they're first discovered do not have a 100% reliablity when you first discover them. Instead, the reliablity of the device is dependent upon a base reliability value, whatever improvements to the design you've discovered through the Destructive Analyzer, and any advancements you've made with the device's source technologies. To be able to improve the reliability of a device, you have to use the device until it breaks beyond repair. Once that happens, you can analyze it in a Destructive Analyzer. Once the device reachs a certain minimum reliability, you'll gain tech advancements from it. - -

Building a Better Machine

- Many machines produces from circuit boards and inserted into a machine frame require a variety of parts to construct. These are parts like capacitors, batteries, matter bins, and so forth. As your knowledge of science improves, more advanced versions are unlocked. If you use these parts when constructing something, its attributes may be improved. For example, if you use an advanced matter bin when constructing an autolathe (rather then a regular one), it'll hold more materials. Experiment around with stock parts of various qualities to see how they affect the end results! Be warned, however: Tier 3 and higher stock parts don't have 100% reliability and their low reliability may affect the reliability of the end machine. - - - "} - - -/obj/item/book/manual/robotics_cyborgs - name = "Cyborgs for Dummies" - icon_state = "borgbook" - author = "XISC" - title = "Cyborgs for Dummies" - dat = {" - - - - - -

Cyborgs for Dummies

- -

Chapters

- -
    -
  1. Cyborg Related Equipment
  2. -
  3. Cyborg Modules
  4. -
  5. Cyborg Construction
  6. -
  7. Cyborg Maintenance
  8. -
  9. Cyborg Repairs
  10. -
  11. In Case of Emergency
  12. -
- - -

Cyborg Related Equipment

- -

Exosuit Fabricator

- The Exosuit Fabricator is the most important piece of equipment related to cyborgs. It allows the construction of the core cyborg parts. Without these machines, cyborgs can not be built. It seems that they may also benefit from advanced research techniques. - -

Cyborg Recharging Station

- This useful piece of equipment will suck power out of the power systems to charge a cyborg's power cell back up to full charge. - -

Robotics Control Console

- This useful piece of equipment can be used to immobolize or destroy a cyborg. A word of warning: Cyborgs are expensive pieces of equipment, do not destroy them without good reason, or Nanotrasen may see to it that it never happens again. - - -

Cyborg Modules

- When a cyborg is created it picks out of an array of modules to designate its purpose. There are 6 different cyborg modules. - -

Standard Cyborg

- The standard cyborg module is a multi-purpose cyborg. It is equipped with various modules, allowing it to do basic tasks.
A Standard Cyborg comes with: -
    -
  • Crowbar
  • -
  • Stun Baton
  • -
  • Health Analyzer
  • -
  • Fire Extinguisher
  • -
- -

Engineering Cyborg

- The Engineering cyborg module comes equipped with various engineering-related tools to help with engineering-related tasks.
An Engineering Cyborg comes with: -
    -
  • A basic set of engineering tools
  • -
  • Metal Synthesizer
  • -
  • Reinforced Glass Synthesizer
  • -
  • An RCD
  • -
  • Wire Synthesizer
  • -
  • Fire Extinguisher
  • -
  • Built-in Optical Meson Scanners
  • -
- -

Mining Cyborg

- The Mining Cyborg module comes equipped with the latest in mining equipment. They are efficient at mining due to no need for oxygen, but their power cells limit their time in the mines.
A Mining Cyborg comes with: -
    -
  • Jackhammer
  • -
  • Shovel
  • -
  • Mining Satchel
  • -
  • Built-in Optical Meson Scanners
  • -
- -

Security Cyborg

- The Security Cyborg module is equipped with effective security measures used to apprehend and arrest criminals without harming them a bit.
A Security Cyborg comes with: -
    -
  • Stun Baton
  • -
  • Handcuffs
  • -
  • Taser
  • -
- -

Janitor Cyborg

- The Janitor Cyborg module is equipped with various cleaning-facilitating devices.
A Janitor Cyborg comes with: -
    -
  • Mop
  • -
  • Hand Bucket
  • -
  • Cleaning Spray Synthesizer and Spray Nozzle
  • -
- -

Service Cyborg

- The service cyborg module comes ready to serve your human needs. It includes various entertainment and refreshment devices. Occasionally some service cyborgs may have been referred to as "Bros"
A Service Cyborg comes with: -
    -
  • Shaker
  • -
  • Industrail Dropper
  • -
  • Platter
  • -
  • Beer Synthesizer
  • -
  • Zippo Lighter
  • -
  • Rapid-Service-Fabricator (Produces various entertainment and refreshment objects)
  • -
  • Pen
  • -
- -

Cyborg Construction

- Cyborg construction is a rather easy process, requiring a decent amount of metal and a few other supplies.
The required materials to make a cyborg are: -
    -
  • Metal
  • -
  • Two Flashes
  • -
  • One Power Cell (Preferrably rated to 15000w)
  • -
  • Some electrical wires
  • -
  • One Human Brain
  • -
  • One Man-Machine Interface
  • -
- Once you have acquired the materials, you can start on construction of your cyborg.
To construct a cyborg, follow the steps below: -
    -
  1. Start the Exosuit Fabricators constructing all of the cyborg parts
  2. -
  3. While the parts are being constructed, take your human brain, and place it inside the Man-Machine Interface
  4. -
  5. Once you have a Robot Head, place your two flashes inside the eye sockets
  6. -
  7. Once you have your Robot Chest, wire the Robot chest, then insert the power cell
  8. -
  9. Attach all of the Robot parts to the Robot frame
  10. -
  11. Insert the Man-Machine Interface (With the Brain inside) Into the Robot Body
  12. -
  13. Congratulations! You have a new cyborg!
  14. -
- -

Cyborg Maintenance

- Occasionally Cyborgs may require maintenance of a couple types, this could include replacing a power cell with a charged one, or possibly maintaining the cyborg's internal wiring. - -

Replacing a Power Cell

- Replacing a Power cell is a common type of maintenance for cyborgs. It usually involves replacing the cell with a fully charged one, or upgrading the cell with a larger capacity cell.
The steps to replace a cell are follows: -
    -
  1. Unlock the Cyborg's Interface by swiping your ID on it
  2. -
  3. Open the Cyborg's outer panel using a crowbar
  4. -
  5. Remove the old power cell
  6. -
  7. Insert the new power cell
  8. -
  9. Close the Cyborg's outer panel using a crowbar
  10. -
  11. Lock the Cyborg's Interface by swiping your ID on it, this will prevent non-qualified personnel from attempting to remove the power cell
  12. -
- -

Exposing the Internal Wiring

- Exposing the internal wiring of a cyborg is fairly easy to do, and is mainly used for cyborg repairs.
You can easily expose the internal wiring by following the steps below: -
    -
  1. Follow Steps 1 - 3 of "Replacing a Cyborg's Power Cell"
  2. -
  3. Open the cyborg's internal wiring panel by using a screwdriver to unsecure the panel
  4. -
- To re-seal the cyborg's internal wiring: -
    -
  1. Use a screwdriver to secure the cyborg's internal panel
  2. -
  3. Follow steps 4 - 6 of "Replacing a Cyborg's Power Cell" to close up the cyborg
  4. -
- -

Cyborg Repairs

- Occasionally a Cyborg may become damaged. This could be in the form of impact damage from a heavy or fast-travelling object, or it could be heat damage from high temperatures, or even lasers or Electromagnetic Pulses (EMPs). - -

Dents

- If a cyborg becomes damaged due to impact from heavy or fast-moving objects, it will become dented. Sure, a dent may not seem like much, but it can compromise the structural integrity of the cyborg, possibly causing a critical failure. - Dents in a cyborg's frame are rather easy to repair, all you need is to apply a welding tool to the dented area, and the high-tech cyborg frame will repair the dent under the heat of the welder. - -

Excessive Heat Damage

- If a cyborg becomes damaged due to excessive heat, it is likely that the internal wires will have been damaged. You must replace those wires to ensure that the cyborg remains functioning properly.
To replace the internal wiring follow the steps below: -
    -
  1. Unlock the Cyborg's Interface by swiping your ID
  2. -
  3. Open the Cyborg's External Panel using a crowbar
  4. -
  5. Remove the Cyborg's Power Cell
  6. -
  7. Using a screwdriver, expose the internal wiring or the Cyborg
  8. -
  9. Replace the damaged wires inside the cyborg
  10. -
  11. Secure the internal wiring cover using a screwdriver
  12. -
  13. Insert the Cyborg's Power Cell
  14. -
  15. Close the Cyborg's External Panel using a crowbar
  16. -
  17. Lock the Cyborg's Interface by swiping your ID
  18. -
- These repair tasks may seem difficult, but are essential to keep your cyborgs running at peak efficiency. - -

In Case of Emergency

- In case of emergency, there are a few steps you can take. - -

"Rogue" Cyborgs

- If the cyborgs seem to become "rogue", they may have non-standard laws. In this case, use extreme caution. - To repair the situation, follow these steps: -
    -
  1. Locate the nearest robotics console
  2. -
  3. Determine which cyborgs are "Rogue"
  4. -
  5. Press the lockdown button to immobolize the cyborg
  6. -
  7. Locate the cyborg
  8. -
  9. Expose the cyborg's internal wiring
  10. -
  11. Check to make sure the LawSync and AI Sync lights are lit
  12. -
  13. If they are not lit, pulse the LawSync wire using a multitool to enable the cyborg's Law Sync
  14. -
  15. Proceed to a cyborg upload console. Nanotrasen usually places these in the same location as AI uplaod consoles.
  16. -
  17. Use a "Reset" upload moduleto reset the cyborg's laws
  18. -
  19. Proceed to a Robotics Control console
  20. -
  21. Remove the lockdown on the cyborg
  22. -
- -

As a last resort

- If all else fails in a case of cyborg-related emergency. There may be only one option. Using a Robotics Control console, you may have to remotely detonate the cyborg. -

WARNING:

Do not detonate a borg without an explicit reason for doing so. Cyborgs are expensive pieces of Nanotrasen equipment, and you may be punished for detonating them without reason. - - - - "} - -/obj/item/book/manual/security_space_law - name = "Space Law" - desc = "A set of Nanotrasen guidelines for keeping law and order on their space stations." - icon_state = "bookSpaceLaw" - author = "Nanotrasen" - title = "Space Law" - dat = {" - - - - - - - - - - "} - -/obj/item/book/manual/security_space_law/black - name = "Space Law - Limited Edition" - desc = "A leather-bound, immaculately-written copy of JUSTICE." - icon_state = "bookSpaceLawblack" - title = "Space Law - Limited Edition" - -/obj/item/book/manual/engineering_guide - name = "Engineering Textbook" - icon_state ="bookEngineering2" - author = "Engineering Encyclopedia" - title = "Engineering Textbook" - dat = {" - - - - - - - - - - "} - - -/obj/item/book/manual/chef_recipes - name = "Chef Recipes" - icon_state = "cooked_book" - author = "Victoria Ponsonby" - title = "Chef Recipes" - dat = {" - - - - - -

Food for Dummies

- Here is a guide on basic food recipes and also how to not poison your customers accidentally. - -

Basics:

- Knead an egg and some flour to make dough. Bake that to make a bun or flatten and cut it. - -

Burger:

- Put a bun and some meat into the microwave and turn it on. Then wait. - -

Bread:

- Put some dough and an egg into the microwave and then wait. - -

Waffles:

- Add two lumps of dough and 10u of sugar to the microwave and then wait. - -

Popcorn:

- Add 1 corn to the microwave and wait. - -

Meat Steak:

- Put a slice of meat, 1 unit of salt and 1 unit of pepper into the microwave and wait. - -

Meat Pie:

- Put a flattened piece of dough and some meat into the microwave and wait. - -

Boiled Spaghetti:

- Put the spaghetti (processed flour) and 5 units of water into the microwave and wait. - -

Donuts:

- Add some dough and 5 units of sugar to the microwave and wait. - -

Fries:

- Add one potato to the processor, then bake them in the microwave. - - - - - "} - -/obj/item/book/manual/barman_recipes - name = "Barman Recipes" - icon_state = "barbook" - author = "Sir John Rose" - title = "Barman Recipes" - dat = {" - - - - - -

Drinks for dummies

- Heres a guide for some basic drinks. - -

Manly Dorf:

- Mix ale and beer into a glass. - -

Grog:

- Mix rum and water into a glass. - -

Black Russian:

- Mix vodka and kahlua into a glass. - -

Irish Cream:

- Mix cream and whiskey into a glass. - -

Screwdriver:

- Mix vodka and orange juice into a glass. - -

Cafe Latte:

- Mix milk and coffee into a glass. - -

Mead:

- Mix Enzyme, water and sugar into a glass. - -

Gin Tonic:

- Mix gin and tonic into a glass. - -

Classic Martini:

- Mix vermouth and gin into a glass. - - - - - "} - - -/obj/item/book/manual/detective - name = "The Film Noir: Proper Procedures for Investigations" - icon_state ="bookDetective" - author = "Nanotrasen" - title = "The Film Noir: Proper Procedures for Investigations" - dat = {" - - - - -

Detective Work

- - Between your bouts of self-narration, and drinking whiskey on the rocks, you might get a case or two to solve.
- To have the best chance to solve your case, follow these directions: -

-

    -
  1. Go to the crime scene.
  2. -
  3. Take your scanner and scan EVERYTHING (Yes, the doors, the tables, even the dog.)
  4. -
  5. Once you are reasonably certain you have every scrap of evidence you can use, find all possible entry points and scan them, too.
  6. -
  7. Return to your office.
  8. -
  9. Using your forensic scanning computer, scan your Scanner to upload all of your evidence into the database.
  10. -
  11. Browse through the resulting dossiers, looking for the one that either has the most complete set of prints, or the most suspicious items handled.
  12. -
  13. If you have 80% or more of the print (The print is displayed) go to step 10, otherwise continue to step 8.
  14. -
  15. Look for clues from the suit fibres you found on your perp, and go about looking for more evidence with this new information, scanning as you go.
  16. -
  17. Try to get a fingerprint card of your perp, as if used in the computer, the prints will be completed on their dossier.
  18. -
  19. Assuming you have enough of a print to see it, grab the biggest complete piece of the print and search the security records for it.
  20. -
  21. Since you now have both your dossier and the name of the person, print both out as evidence, and get security to nab your baddie.
  22. -
  23. Give yourself a pat on the back and a bottle of the ships finest vodka, you did it!.
  24. -
-

- It really is that easy! Good luck! - - - "} - -/obj/item/book/manual/nuclear - name = "Fission Mailed: Nuclear Sabotage 101" - icon_state ="bookNuclear" - author = "Syndicate" - title = "Fission Mailed: Nuclear Sabotage 101" - dat = {" - Nuclear Explosives 101:
- Hello and thank you for choosing the Syndicate for your nuclear information needs.
- Today's crash course will deal with the operation of a Fusion Class Nanotrasen made Nuclear Device.
- First and foremost, DO NOT TOUCH ANYTHING UNTIL THE BOMB IS IN PLACE.
- Pressing any button on the compacted bomb will cause it to extend and bolt itself into place.
- If this is done to unbolt it one must completely log in which at this time may not be possible.
- To make the nuclear device functional:
-

  • Place the nuclear device in the designated detonation zone.
  • -
  • Extend and anchor the nuclear device from its interface.
  • -
  • Insert the nuclear authorisation disk into slot.
  • -
  • Type numeric authorisation code into the keypad. This should have been provided. Note: If you make a mistake press R to reset the device. -
  • Press the E button to log onto the device.
  • - You now have activated the device. To deactivate the buttons at anytime for example when you've already prepped the bomb for detonation remove the auth disk OR press the R on the keypad.
    - Now the bomb CAN ONLY be detonated using the timer. Manual detonation is not an option.
    - Note: Nanotrasen is a pain in the neck.
    - Toggle off the SAFETY.
    - Note: You wouldn't believe how many Syndicate Operatives with doctorates have forgotten this step.
    - So use the - - and + + to set a det time between 5 seconds and 10 minutes.
    - Then press the timer toggle button to start the countdown.
    - Now remove the auth. disk so that the buttons deactivate.
    - Note: THE BOMB IS STILL SET AND WILL DETONATE
    - Now before you remove the disk if you need to move the bomb you can:
    - Toggle off the anchor, move it, and re-anchor.

    - Good luck. Remember the order:
    - Disk, Code, Safety, Timer, Disk, RUN!
    - Intelligence Analysts believe that normal Nanotrasen procedure is for the Captain to secure the nuclear authorisation disk.
    - Good luck! - "} - -/obj/item/book/manual/atmospipes - name = "Pipes and You: Getting To Know Your Scary Tools" - icon_state = "pipingbook" - author = "Maria Crash, Senior Atmospherics Technician" - title = "Pipes and You: Getting To Know Your Scary Tools" - dat = {" - - - - - - -

    Contents

    -
      -
    1. Author's Forward
    2. -
    3. Basic Piping
    4. -
    5. Insulated Pipes
    6. -
    7. Atmospherics Devices
    8. -
    9. Heat Exchange Systems
    10. -
    11. Final Checks
    12. -
    -

    - -

    HOW TO NOT SUCK QUITE SO HARD AT ATMOSPHERICS


    - Or: What the fuck does a "passive gate" do?

    - - Alright. It has come to my attention that a variety of people are unsure of what a "pipe" is and what it does. - Apparently there is an unnatural fear of these arcane devices and their "gases". Spooky, spooky. So, - this will tell you what every device constructable by an ordinary pipe dispenser within atmospherics actually does. - You are not going to learn what to do with them to be the super best person ever, or how to play guitar with passive gates, - or something like that. Just what stuff does.

    - - -

    Basic Pipes


    - The boring ones.
    - TMost ordinary pipes are pretty straightforward. They hold gas. If gas is moving in a direction for some reason, gas will flow in that direction. - That's about it. Even so, here's all of your wonderful pipe options.
    - -
  • Straight pipes: They're pipes. One-meter sections. Straight line. Pretty simple. Just about every pipe and device is based around this - standard one-meter size, so most things will take up as much space as one of these.
  • -
  • Bent pipes: Pipes with a 90 degree bend at the half-meter mark. My goodness.
  • -
  • Pipe manifolds: Pipes that are essentially a "T" shape, allowing you to connect three things at one point.
  • -
  • 4-way manifold: A four-way junction.
  • -
  • Pipe cap: Caps off the end of a pipe. Open ends don't actually vent air, because of the way the pipes are assembled, so, uh. Use them to decorate your house or something.
  • -
  • Manual Valve: A valve that will block off airflow when turned. Can't be used by the AI or cyborgs, because they don't have hands.
  • -
  • Manual T-Valve: Like a manual valve, but at the center of a manifold instead of a straight pipe.


  • - -

    Insulated Pipes


    - Special Public Service Announcement.
    - Our regular pipes are already insulated. These are completely worthless. Punch anyone who uses them.

    - -

    Devices:


    - They actually do something.
    - This is usually where people get frightened,
    afraid, and start calling on their gods and/or cowering in fear. Yes, I can see you doing that right now. - Stop it. It's unbecoming. Most of these are fairly straightforward.
    - -
  • Gas Pump: Take a wild guess. It moves gas in the direction it's pointing (marked by the red line on one end). It moves it based on pressure, the maximum output being 4500 kPa (kilopascals). - Ordinary atmospheric pressure, for comparison, is 101.3 kPa, and the minimum pressure of room-temperature pure oxygen needed to not suffocate in a matter of minutes is 16 kPa - (though 18 is preferred using internals, for various reasons).
  • -
  • Volume pump: This pump goes based on volume, instead of pressure, and the possible maximum pressure it can create in the pipe on the recieving end is double the gas pump because of this, - clocking in at an incredible 9000 kPa. If a pipe with this is destroyed or damaged, and this pressure of gas escapes, it can be incredibly dangerous depending on the size of the pipe filled. - Don't hook this to the distribution loop, or you will make babies cry and the Chief Engineer brutally beat you.
  • -
  • Passive gate: This is essentially a cap on the pressure of gas allowed to flow in a specific direction. - When turned on, instead of actively pumping gas, it measures the pressure flowing through it, and whatever pressure you set is the maximum: it'll cap after that. - In addition, it only lets gas flow one way. The direction the gas flows is opposite the red handle on it, which is confusing to people used to the red stripe on pumps pointing the way.
  • -
  • Unary vent: The basic vent used in rooms. It pumps gas into the room, but can't suck it back out. Controlled by the room's air alarm system.
  • -
  • Scrubber: The other half of room equipment. Filters air, and can suck it in entirely in what's called a "panic siphon". Actvating a panic siphon without very good reason will kill someone. Don't do it.
  • -
  • Meter: A little box with some gagues and numbers. Fasten it to any pipe or manifold, and it'll read you the pressure in it. Very useful.
  • -
  • Gas mixer: Two sides are input, one side is output. Mixes the gases pumped into it at the ratio defined. The side perpendicular to the other two is "node 2", for reference. - Can output this gas at pressures from 0-4500 kPa.
  • -
  • Gas filter: Essentially the opposite of a gas mixer. One side is input. The other two sides are output. One gas type will be filtered into the perpendicular output pipe, - the rest will continue out the other side. Can also output from 0-4500 kPa.
  • - -

    Heat Exchange Systems


    - Will not set you on fire.
    - These systems are used to transfer heat only between two pipes. They will not move gases or any other element, but will equalize the temperature (eventually). Note that because of how gases work (remember: pv=nRt), - a higher temperature will raise pressure, and a lower one will lower temperature.
    - -
  • Pipe: This is a pipe that will exchange heat with the surrounding atmosphere. Place in fire for superheating. Place in space for supercooling.
  • -
  • Bent Pipe: Take a wild guess.
  • -
  • Junction:Junction:The point where you connect your normal pipes to heat exchange pipes. Not necessary for heat exchangers, but necessary for H/E pipes/bent pipes.
  • -
  • Heat Exchanger: These funky-looking bits attach to an open pipe end. Put another heat exchanger directly across from it, and you can transfer heat across two pipes without having to have the gases touch. - This normally shouldn't exchange with the ambient air, despite being totally exposed. Just don't ask questions...

  • - - - That's about it for pipes. Go forth, armed with this knowledge, and try not to break, burn down, or kill anything. Please.
    - - - - "} - -/obj/item/book/manual/evaguide - name = "EVA Gear and You: Not Spending All Day Inside" - icon_state = "evabook" - author = "Maria Crash, Senior Atmospherics Technician" - title = "EVA Gear and You: Not Spending All Day Inside" - dat = {" - - - - - - -

    Contents

    -
      -
    1. A forward on using EVA gear
    2. -
    3. Donning a Civilian Suits
    4. -
    5. Putting on a Hardsuit
    6. -
    7. Final Checks
    8. -
    -

    - -

    EVA Gear and You: Not Spending All Day Inside


    - Or: How not to suffocate because there's a hole in your shoes

    - - EVA gear. Wonderful to use. It's useful for mining, engineering, and occasionally just surviving, if things are that bad. Most people have EVA training, - but apparently there are some on a space station who don't. This guide should give you a basic idea of how to use this gear, safely. It's split into two sections: - Civilian suits and hardsuits.

    - -

    Civilian Suits


    - The bulkiest things this side of Alpha Centauri
    - These suits are the grey ones that are stored in EVA. They're the more simple to get on, but are also a lot bulkier, and provide less protection from environmental hazards such as radiaion or physical impact. - As Medical, Engineering, Security, and Mining all have hardsuits of their own, these don't see much use, but knowing how to put them on is quite useful anyways.

    - - First, take the suit. It should be in three pieces: A top, a bottom,
    and a helmet. Put the bottom on first, shoes and the like will fit in it. If you have magnetic boots, however, - put them on on top of the suit's feet. Next, get the top on, as you would a shirt. It can be somewhat awkward putting these pieces on, due to the makeup of the suit, - but to an extent they will adjust to you. You can then find the snaps and seals around the waist, where the two pieces meet. Fasten these, and double-check their tightness. - The red indicators around the waist of the lower half will turn green when this is done correctly. Next, put on whatever breathing apparatus you're using, be it a gas mask or a breath mask. Make sure the oxygen tube is fastened into it. - Put on the helmet now, straight forward, and make sure the tube goes into the small opening specifically for internals. Again, fasten seals around the neck, a small indicator light in the inside of the helmet should go from red to off when all is fastened. - There is a small slot on the side of the suit where an emergency oxygen tank or extended emergency oxygen tank will fit, - but it is reccomended to have a full-sized tank on your back for EVA.

    - -

    Hardsuits


    - Heavy, uncomfortable, still the best option.
    - These suits come in Engineering, Mining, and the Armory. There's also a couple Medical Hardsuits in EVA. These provide a lot more protection than the standard suits.

    - - Similarly to the other suits, these are split into three parts. Fastening the pant and top are mostly the same as the other spacesuits, with the exception that these are a bit heavier, - though not as bulky. The helmet goes on differently, with the air tube feeing into the suit and out a hole near the left shoulder, while the helmet goes on turned ninety degrees counter-clockwise, - and then is screwed in for one and a quarter full rotations clockwise, leaving the faceplate directly in front of you. There is a small button on the right side of the helmet that activates the helmet light. - The tanks that fasten onto the side slot are emergency tanks, as
    well as full-sized oxygen tanks, leaving your back free for a backpack or satchel.

    - -

    FINAL CHECKS:


    -
  • Are all seals fastened correctly?
  • -
  • Do you either have shoes on under the suit, or magnetic boots on over it?
  • -
  • Do you have a mask on and internals on the suit or your back?
  • -
  • Do you have a way to communicate with the station in case something goes wrong?
  • -
  • Do you have a second person watching if this is a training session?

  • - - If you don't have any further issues, go out and do whatever is necessary.
    - - - - "} - -/obj/item/book/manual/faxes - name = "A Guide to Faxes" - desc = "A NanoTrasen-approved guide to writing faxes" - icon_state = "book6" - author = "NanoTrasen" - title = "A Guide to Faxes" - dat = {" - - - - - - - - -

    Contents

    -
      -
    1. What's a Fax?
    2. -
    3. When to Fax?
    4. -
    5. How to Fax?
    6. -
    -

    - -

    What's a Fax?


    -
  • Faxes are your main method of communicating with the NAS Trurl, better known as Central Command.
  • -
  • Faxes allow personnel on the station to maintain open lines of communication with the NAS Trurl, allowing for vital information to flow both ways.
  • -
  • Being written communications, proper grammar, syntax and typography is required, in addition to a signature and, if applicable, a stamp. Failure to sign faxes will lead to an automatic rejection.
  • -
  • We at NanoTrasen provide Fax Machines to every Head of Staff, in addition to the Magistrate, NanoTrasen Representative, and Internal Affairs Agents.
  • -
  • This means that we trust the recipients of these fax machines to only use them in the proper circumstances (see When to Fax?).
  • - -

    When to Fax?


    -
  • While it is up to the discretion of each individual person to decide when to fax Central Command, there are some simple guidelines on when to do this.
  • -
  • Firstly, any situation that can reasonably be solved on-site, should be handled on-site. Knowledge of Standard Operating Procedure is mandatory for everyone with access to a fax machine.
  • -
  • Resolving issues on-site not only leads to more expedient problem-solving, it also frees up company resources and provides valuable work experience for all parties involved.
  • -
  • This means that you should work with the Heads of Staff concerning personnel and workplace issues, and attempt to resolve situations with them. If, for whatever reason, the relevent Head of Staff is not available or receptive, consider speaking with the Captain and/or NanoTrasen Representative.
  • -
  • If, for whatever reason, these issues cannot be solved on-site, either due to incompetence or just plain refusal to cooperate, faxing Central Command becomes a viable option.
  • -
  • Secondly, station status reports should be sent occasionally, but never at the start of the shift. Remember, we assign personnel to the station. We do not need a repeat of what we just signed off on.
  • -
  • Thirdly, staff/departmental evaluations are always welcome, especially in cases of noticeable (in)competence. Just as a brilliant coworker can be rewarded, an incompetent one can be punished.
  • -
  • Fourthly, do not issue faxes asking for sentences. You have an entire Security department and an associated Detective, not to mention on-site Space Law manuals.
  • -
  • Lastly, please pay attention to context. If the station is facing a massive emergency, such as a Class 7-10 Blob Organism, most, if not all, non-relevant faxes will be duly ignored.
  • - -

    How to Fax?


    -
  • Sending a fax is simple. Simply insert your ID into the fax machine, then log in.
  • -
  • Once logged in, insert a piece of paper and select the destination from the provided list. Remember, you can rename your fax from within the fax machine's menu.
  • -
  • You can send faxes to any other fax machine on the station, which can be a very useful tool when you need to issue broad communications to all of the Heads of Staff.
  • -
  • To send a fax to Central Command, simply select the correct destination, and send the fax. Keep in mind, the communication arrays need to recharge after sending a fax to Central Command, so make sure you sent everything you need.
  • -
  • Lastly, paper bundles can also be faxed as a single item, so feel free to bundle up all relevant documentation and send it in at once.
  • - -
    - - - - "} - -/obj/item/book/manual/sop_science - name = "Science Standard Operating Procedures" - desc = "A set of guidelines aiming at the safe conduct of all scientific activities." - icon_state = "book6" - author = "Nanotrasen" - title = "Science Standard Operating Procedures" - dat = {" - - - - - - - - -

    Contents

    -
      -
    1. Foreword
    2. -
    3. Research Director
    4. -
    5. Roboticist
    6. -
    7. Scientist
    8. -
    9. Geneticist
    10. -
    11. Exotic Implants
    12. -
    -

    - -

    FOREWORD


    - Job SOP should not be a considered a checklist of conditions to fire someone over, and should not be rigidly followed to the letter in detriment of circumstances and context. - As always, SOP can be malleable if the situation so requires, and the decision to punish a crewmember for breaching it ultimately falls onto the relevant Head of Staff, - for Department Members, or Captain, for the Head of Staff.

    - -

    Research Director


    - Code Green -
      -
    1. The Research Director must make sure Research is being done. Research must be completed by the end of the shift, assuming Science is provided the materials for it by Supply;
    2. -
    3. The Research Director is permitted to carry a telescopic baton;
    4. -
    5. The Research Director is permitted to carry their Reactive Teleport Armour on their person. However, it is highly recommended they keep it inactive unless necessary, for personal safety;
    6. -
    7. The Research Director is not permitted to authorize the construction of AI Units without the Captain's approval. An exception is made if the station was not provided with an AI Unit, or a previous AI Unit had to be destroyed.
    8. -
    9. The Research Director is not permitted to authorize Anomalous Artifacts to be brought onto the station prior to full testing and cataloguing;
    10. -
    11. The Research Director must keep the Communications Decryption Key on their person at all times, or at least somewhere safe and out of reach;
    12. -
    13. The Research Director is permitted to add beneficial scripts to Telecommunications;
    14. -
    15. The Research Director is permitted to change the AI Unit's lawset, provided they receive general approval from the Captain and another Head of Staff. If there are no other Heads of Staff available, Captain approval will suffice;
    16. -
    17. The Research Director must work with Robotics to make sure all Cyborgs remain slaved to the station's AI Unit, except in such a situation where the AI Unit has been subverted or is malfunctioning.
    18. -

    - - Code Blue -
      -
    1. All Guidelines carry over from Code Green
    2. -

    - - Code Red -
      -
    1. Guidelines 1, 3, 4, 6, 7, 8 and 9 carry over from Code Green;
    2. -
    3. In addition to the a telescopic baton, the Research Director is permitted to carry a single weapon created in the Protolathe, provided they receive authorization from the Head of Security. Exception is made during extreme emergencies, such as Nuclear Operatives or Blob Organisms.
    4. -

    -

    - -

    Roboticist


    - Code Green -
      -
    1. The Roboticist is not permitted to construct Combat Mechs without express permission from the Captain and/or Head of Security. This refers to the Durand, Gygax and Phazon. If permitted, the Mechs is to be delivered to the Armory for storage. The Research Director is placed under the same restrictions;
    2. -
    3. The Roboticist is freely permitted to construct Utility Mechs, along with any assorted Utility Equipment. This refers to Ripleys (to be handed to Mining), Firefighting Ripleys (to be handed to Atmospherics) and the Odysseus Medical Mech (to be handed to Medical). The HONK Mech is not to be constructed without full approval by the Research Director and Captain;
    4. -
    5. The Roboticist is freely permitted to construct Cyborgs and all assorted equipment;
    6. -
    7. The Roboticist is not permitted to transfer personnel MMIs into Cyborgs without express written consent from the person in question. The consent form should be kept safe;
    8. -
    9. The Roboticist is not permitted to construct AI Units without express consent from the Captain;
    10. -
    11. The Roboticist must place a Tracking Beacon on all constructed Mechs;
    12. -
    13. The Roboticist must work together with the Research Director to make sure all Cyborgs remain slaved to the station's AI Unit, except in such a situation where the AI Unit has been subverted or is malfunctioning;
    14. -
    15. The Roboticist must DNA-Lock all parked Mechs prior to delivery. DNA-Lock must be removed when the Mech is delivered to its final destination
    16. -

    - - Code Blue -
      -
    1. Guidelines 2, 3, 4, 5, 6, 7 and 8 carry over from Code Green;
    2. -
    3. The Roboticist is permitted to construct Combat Mechs without prior consent, but must deliver them to the Armory for storage. Failure to comply will result in the Combat Mech being destroyed. Exception is made for extreme emergencies, such as a Blob Organism or Nuclear Operatives, where the Roboticist may pilot the Mech themselves. However, even in these circumstances, the Mech must be delivered to the Armory after the emergency is over. The Research Director is placed under the same restrictions;
    4. -

    - - Code Red -
      -
    1. Guidelines 3, 4, 5, 6, 7, 8 and 9 carry over from Code Green;
    2. -
    3. All Guidelines carry over from Code Blue.
    4. -

    -

    - -

    Scientist


    - Code Green -
      -
    1. Scientists are not permitted to bring Grenades outside of Science;
    2. -
    3. Scientists are not permitted to bring Toxins Bombs outside of Science. Exception is made if the Toxins Bomb is handed to Mining, as it can be useful for mining operations;
    4. -
    5. While not mandatory, it is highly recommended that Scientists give a prior warning before a Toxins Test. This must be done via the Common Communication Channel, with at least ten (10) seconds between the warning and detonation;
    6. -
    7. Scientists are not permitted to use Telescience equipment to acquire objects, items or personnel they do not have access to;
    8. -
    9. Scientists are, however, permitted to use Telescience equipment to recover dead personnel, provided Medical cannot reach them;
    10. -
    11. Scientists must, at all times, keep live slimes and Golden Extract-based lifeforms inside Xenobiology pens, except when transporting them to new cells. Peaceful Golden Extract lifeforms may be released with the express permission of the Research Director. In addition, injecting plasma into Golden Extract is strictly forbidden;
    12. -
    13. Scientists are not permitted to bring Anomalous Artifacts aboard the station without express verbal consent from the Research Director. Regular Xenoarchaeological artifacts are permitted;
    14. -
    15. Scientists are not permitted to construct the Portable Wormhole Generator without express permission from the Research Director. In addition, Scientists are not to hand out Weapon Lockboxes to any non-Security or non-Command personnel without express permission from the Head of Security;
    16. -

    - - Code Blue -
      -
    1. Guidelines 3, 4, 5, 6, 7 and 9 carry over from Code Green;
    2. -
    3. Scientists are permitted to bring Grenades outside of Science, but only for delivery to the Armory;
    4. -
    5. Scientists are permitted to bring Toxins Bombs outside of Science, but only for delivery to the Armory. In addition, the Mining exception still applies
    6. -

    - - Code Red -
      -
    1. Guidelines, 3, 4, 5, 6, 7 and 9 carry over from Code Green;
    2. -
    3. All Guidelines carry over from Code Blue.
    4. -

    -

    - -

    Geneticist


    - Code Green -
      -
    1. The Geneticist is not permitted to ignore Cloning, and must provide Clean SE Injectors when required, as well as humanized animals if required for Surgery. In addition, the Geneticist must make sure that Cloning is stocked with Biomass;
    2. -
    3. The Geneticist is permitted to test Genetic Powers on themselves. However, they are not to utilize these powers on any crewmembers, nor abuse them to obtain items/personnel outside their access;
    4. -
    5. The Geneticist is permitted to grant Genetic Powers to Command Staff at their discretion, provided prior permission is requested and granted. All staff must be warned of the full effects of the SE Injector. The Geneticist is not, however, obligated to grant powers, unless the Research Director issues a direct order;
    6. -
    7. The Geneticist is not permitted to grant Powers to non-Command Staff without express verbal consent from the Research Director. Both the Chief Medical Officer and the Research Director maintain full authority to forcefully remove these Powers if they are abused;
    8. -
    9. The Geneticist must place all discarded humanized animals in the Morgue. It is recommended that said discarded humanized animals be directed to the Crematorium;
    10. -
    11. The Geneticist is not permitted to provide body doubles, unless the Research Director approves it. In addition, Security is to be notified of all doubles;
    12. -
    13. The Geneticist is not permitted to alter personnel's UI Status, unless it has been previously tampered with by hostile elements, or permission is given;
    14. -
    15. The Geneticist is not permitted to use sentient humanoids as test subjects unless the sentient humanoid has granted their permission, on paper.
    16. -

    - - Code Blue -
      -
    1. All Guidelines carry over from Code Green
    2. -

    - - Code Red -
      -
    1. All Guidelines carry over from Code Green. In regards to Guideline 4, the Geneticist is now permitted to grant Powers to Security personnel, under the same conditions as detailed in Guideline 3.
    2. -

    -

    - -

    Exotic Implants


    - Exotic Implants refer to Xeno Organs, Cybernetic Implants or any such exotic materials.
    -
      -
    1. General utility implants (such as Welding Shield, Nutriment or Reviver) are unregulated, and may be handed out freely;
    2. -
    3. X-Ray Vision and Thermal Vision implants may be handed out freely, but may have their implantation vetoed by the Chief Medical Officer and/or Research Director (see below);
    4. -
    5. Medical HUDs must be approved by the Chief Medical Officer before implantation, and Security HUDs require express permission from the Head of Security or Warden;
    6. -
    7. Combat-capable Implants (such as the CNS Rebooter or Anti-Drop) are not be handed out without express permission from the Head of Security;
    8. -
    9. Cybernetic Implantation should be performed in Surgery or any such sterilized environment, to reduce the risk of internal infection. If no Surgeons or Doctors are available, the Roboticist can fill in;
    10. -
    11. The Chief Medical Officer and Research Director have the power to veto any Cybernetic Implantation or Xeno Organ Implantation if they believe it threatens the stability of the station or crew. Only the Captain may override this veto;
    12. -
    13. Xeno Organs may be harvested at will, but may not be implanted without express permission from the Chief Medical Officer. Egg-Laying Organs from Xenomorph Lifeforms are strictly forbidden;
    14. -
    15. Failure to follow these Guidelines makes the offending party liable to having their Exotic Implants forcefully removed.
    16. -

    - - - - "} - -/obj/item/book/manual/sop_medical - name = "Medical Standard Operating Procedures" - desc = "A set of guidelines aiming at the safe conduct of all medical activities." - icon_state = "book7" - author = "Nanotrasen" - title = "Medical Standard Operating Procedures" - dat = {" - - - - - - - - -

    Contents

    -
      -
    1. Foreword
    2. -
    3. Chief Medical Officer
    4. -
    5. Medical Doctor
    6. -
    7. Chemist
    8. -
    9. Geneticist
    10. -
    11. Virologist
    12. -
    13. Paramedic
    14. -
    15. Psychologist
    16. -
    17. Surgery
    18. -
    19. Viral Outbreak Procedures
    20. -
    21. Coroner Procedures
    22. -
    23. Exotic Implants
    24. -
    -

    - -

    FOREWORD


    - Job SOP should not be a considered a checklist of conditions to fire someone over, and should not be rigidly followed to the letter in detriment of circumstances and context. - As always, SOP can be malleable if the situation so requires, and the decision to punish a crewmember for breaching it ultimately falls onto the relevant Head of Staff, - for Department Members, or Captain, for the Head of Staff.

    - -

    Chief Medical Officer


    -
      -
    1. The Chief Medical Officer is permitted to carry a regular Defibrillator or a Compact Defibrillator on their person at all times;
    2. -
    3. The Chief Medical Officer is permitted to carry a telescopic baton. In case Genetic Powers need to be forcefully removed, they are cleared to carry a Syringe Gun;
    4. -
    5. The Chief Medical Officer is not permitted to allow the creation of poisonous or explosive mixtures in Chemistry without express consent from the Captain or, failing that, the presence of a clear and urgent danger to the integrity of the station, except of course in situations where Chemical Implants are required;
    6. -
    7. The Chief Medical Officer is not permitted to allow the release of any virus without a full list of its symptoms, as well as the creation of a vial of antibodies, to be kept in a secure location. The virus may not have any harmful symptoms whatsoever, though neutral/harmless symptoms are permitted;
    8. -
    9. The Chief Medical Officer must make sure that any cloneable corpses are, in fact, cloned.
    10. -
    -

    - -

    Medical Doctor


    -
      -
    1. Though not mandatory, it is recommended that Doctors wear Sterile Masks and Latex/Nitrile gloves when handling patients. This Guideline becomes mandatory during Viral Outbreaks;
    2. -
    3. Nurses should focus on helping Medical Doctors and Surgeons in whatever they require, and tending to patients that require light care. If necessary, they can stand in for regular Medical Doctor duties;
    4. -
    5. Surgeons are expected to fulfill the duties of regular Medical Doctors if there are no active Surgical Procedures undergoing;
    6. -
    7. Medical Doctors must ensure there is at least one (1) Defibrillator available for use, at all times, next to or near the Cryotubes;
    8. -
    9. Medical Doctors must maintain the entirety of Medbay in an hygienic state. This includes, but is not limited to, cleaning organic residue, fluids and corpses;
    10. -
    11. Medical Doctors must place all corpses inside body bags. If there is an assigned Coroner, the Morgue Trays must be correctly tagged;
    12. -
    13. Medical Doctors must, together with Geneticists and Chemists, make sure that Cloning is stocked with Biomass. In addition, Medical Doctors must make sure that the Morgue does not contain cloneable corpses;
    14. -
    15. Medical Doctors must certify that all cloned personnel are put in the Cryotubes after Cloning, and receive either a dose of Mutadone or a Clean SE Injector, in addition to Mannitol. An exception is made if the Cloning Pod was fully upgraded by Science;
    16. -
    17. Medical Doctors are not permitted to leave Medbay to perform recreational activities if there are unattended patients requiring treatment;
    18. -
    19. Medical Doctors must stabilize patients before delivering them to Surgery. If the patient presents Internal Bleeding, they are to be rushed to Surgery post haste.
    20. - -
    -

    - -

    Chemist


    -
      -
    1. The Chemist is not permitted to experiment with explosive mixtures;
    2. -
    3. The Chemist is not permitted to experiment with poisonous mixtures and/or narcotics;
    4. -
    5. The Chemist is not permitted to experiment with Life or other Omnizine-derived mixtures apart from Omnizine or Strange Reagent;
    6. -
    7. The Chemist is not permitted to produce alcoholic beverages;
    8. -
    9. Chemists must, together with Geneticists and Medical Doctors, make sure that Cloning is stocked with Biomass;
    10. -
    11. The Chemist must ensure that the Medical Fridge is stocked with at least enough medication to handle Brute, Burn, Respiratory, Toxic and Brain damage. Failure to follow this Guideline within thirty (30) minutes is to be considered a breach of Standard Operating Procedure
    12. -
    13. The Chemist is not allowed to leave Chemistry unattended if the Medical Fridge is devoid of Medication, except in such a case as Chemistry is unusable or if Fungus needs to be collected
    14. -
    -

    - -

    Geneticist


    - Code Green -
      -
    1. The Geneticist is not permitted to ignore Cloning, and must provide Clean SE Injectors when required, as well as humanized animals if required for Surgery. In addition, the Geneticist must make sure that Cloning is stocked with Biomass;
    2. -
    3. The Geneticist is permitted to test Genetic Powers on themselves. However, they are not to utilize these powers on any crewmembers, nor abuse them to obtain items/personnel outside their access;
    4. -
    5. The Geneticist is permitted to grant Genetic Powers to Command Staff at their discretion, provided prior permission is requested and granted. All staff must be warned of the full effects of the SE Injector. The Geneticist is not, however, obligated to grant powers, unless the Research Director issues a direct order;
    6. -
    7. The Geneticist is not permitted to grant Powers to non-Command Staff without express verbal consent from the Research Director. Both the Chief Medical Officer and the Research Director maintain full authority to forcefully remove these Powers if they are abused;
    8. -
    9. The Geneticist must place all discarded humanized animals in the Morgue. It is recommended that said discarded humanized animals be directed to the Crematorium;
    10. -
    11. The Geneticist is not permitted to provide body doubles, unless the Research Director approves it. In addition, Security is to be notified of all doubles;
    12. -
    13. The Geneticist is not permitted to alter personnel's UI Status, unless it has been previously tampered with by hostile elements, or permission is given;
    14. -
    15. The Geneticist is not permitted to use sentient humanoids as test subjects unless the sentient humanoid has granted their permission, on paper.
    16. -

    - - Code Blue -
      -
    1. All Guidelines carry over from Code Green
    2. -

    - - Code Red -
      -
    1. All Guidelines carry over from Code Green. In regards to Guideline 4, the Geneticist is now permitted to grant Powers to Security personnel, under the same conditions as detailed in Guideline 3.
    2. -

    -

    - -

    Virologist


    -
      -
    1. The Virologist must always wear adequate protection (such as a Biosuit and Internals for Airborne Viruses) when handling infected personnel and Test Animals. Exception is made for IPC Virologists, for obvious reasons;
    2. -
    3. The Virologist must only test viral samples on the provided Test Animals. Said Test Animals are to be maintained inside their pen, and disposed of via Virology's Disposals Chutes if dead, to prevent possible contamination. In addition, the Virologist may not, under any circumstances whatsoever, leave Virology while infected by a Viral Pathogen that spreads by Contact or Airborne means, unless permitted by the Chief Medical Officer;
    4. -
    5. The Virologist may not, under any circumstance whatsoever, release an active virus without prior consent from Chief Medical Officer. Contact and/or Airborne viruses may only be released with consent from the Chief Medical officer and Captain. In the event a Contact and/or Airborne virus is released, the crew must be informed, and Vaccines should be ready for any personnel that choose to opt out of being infected;
    6. -
    7. The Virologist must ensure that all Viral Samples are kept on their person at all times, or at the very least in a secure location (such as the Virology Fridge);
    8. -
    9. The Virologist must work together with Medical Staff, especially Chemistry, if there is a cure that requires manufacturing;
    10. -
    11. In the event of a lethal Viral Outbreak, the Virologist must work together with the Chief Medical Officer and/or Chemists and/or Bartender to produce a cure. Failure to keep casualties down to, at most, 25% of the station's crew is to be considered a breach of Standard Operating Procedure for everyone involved.
    12. -
    -

    - -

    Paramedic


    -
      -
    1. The Paramedic is not permitted to perform Field Surgery unless there are no available Medical Doctors or the Operating Rooms are unusable;
    2. -
    3. The Paramedic is permitted to perform Surgical Procedures inside an Operating Room. However, Doctors/Surgeons should take precedence;
    4. -
    5. The Paramedic is fully permitted to carry a Defibrillator on their person at all times, provided they leave at least one (1) Defibrillator for use in Medbay;
    6. -
    7. The Paramedic must stabilize all patients before bringing them to the Medical Bay. If the patient presents with Internal Bleeding, they are to be rushed to Surgery post haste;
    8. -
    9. In such a case as a patient is found dead, and cannot be brought back via Defibrillation, the Paramedic must ensure that said patient is brought to Cloning, and Medbay is notified;
    10. -
    11. The Paramedic must carry, at all times, enough materials to provide for adequate first aid of all Major Injury Types (Brute, Burn, Toxic, Respiratory and Brain)
    12. -
    -

    - -

    Psychologist


    -
      -
    1. The Psychologist may perform a full psychological evaluation on anyone, along with any potential treatment, provided the person in question seeks them out;
    2. -
    3. The Psychologist may not force someone to receive therapy if the person does not want it. Exception is made for violent criminals, if the Head of Security or Magistrate orders it;
    4. -
    5. The Psychologist is not permitted to administer any medication without consent from their patient;
    6. -
    7. The Psychologist is not permitted to muzzle or straightjacket anyone without express permission from the Chief Medical Officer or Head of Security. An exception is made for violent and/or out of control patients;
    8. -
    9. The Psychologist may recommend a patient's demotion if they find their psychological condition to be unfit;
    10. -
    11. The Psychologist may request to consult prisoners in Permanent Imprisonment. This must happen inside the Brig, preferably inside the Permabrig, and only with Warden and/or Head of Security authorization. This should be done under the supervision of a member of Security with Permabrig access
    12. -
    -

    - -

    Surgery


    -
      -
    1. Attending Surgeon must use Latex/Nitrile gloves in order to prevent infection. Though not mandatory, a Sterile Mask is recommended;
    2. -
    3. Attending Surgeon is to keep the Operating Room in an hygienic condition at all times, again, to prevent infection;
    4. -
    5. Attending Surgeon is to wash his/her hands between different patients, again, to prevent infection;
    6. -
    7. Attending Surgeon is to use either Anesthetics or Sedatives (for species that cannot breathe Anesthetics) during Surgical Procedures. Exception is made if the patient requests otherwise;
    8. -
    9. Attending Surgeon is not to remove any legal Implants (such as Mindshield or Tracking Implants) from the patient, unless requested by Security;
    10. -
    11. If a patient requests that a lost limb be replaced with an organic, rather than mechanical, substitute, said limb must be harvested from a compatible humanized Test Animal (such as Monkeys for Humans, or Farwas for Tajarans). Exception is made if the patient deliberately requests otherwise;
    12. -
    13. Attending Surgeon is not to bring any of the Surgical Tools outside of their respective Operating Room, and must in fact ensure the Operating Room maintains its proper inventory. This includes ensuring that the Anesthetics Equipment be kept inside the OR
    14. -
    -

    - -

    Viral Outbreak Procedures


    - Definition: A Viral Outbreak is defined as a situation where a Viral Pathogen has infected a significant portion of the crew (>10%) -
      -
    1. All Medbay personnel are to contribute in fighting the outbreak if there are no other critical patients requiring assistance. Eliminating the Viral Threat becomes number one priority;
    2. -
    3. Personnel are to be informed of known symptoms, and directed to Medbay immediately if they are suffering from them;
    4. -
    5. All infected personnel are to be confined to either an Isolated Room, or Virology;
    6. -
    7. A blood sample is to be taken from an infected person, for study;
    8. -
    9. If any infected personnel attempt to leave containment, Medbay Quarantine is to be initiated immediately, and only lifted when more patients need to be admitted, or the Viral Outbreak is over;
    10. -
    11. A single infected person may volunteer to receive a dose of Radium in order to develop Antibodies. Radium must not be administered without consent. Otherwise, animal testing is to be conducted in order to obtain Antibodies;
    12. -
    13. Once Antibodies are produced, they are to be diluted, then handed out to all infected personnel. Injecting infected personnel with Radium after Antibodies have been extracted is forbidden. In the event of a large enough crisis, directly injecting blood with the relevant Antibodies is permissible;
    14. -
    15. Viral Pathogen should be cataloged and analyzed, in case any stray cases remained untreated;
    16. -
    17. Cured personnel should have a sample of their blood removed for the purpose of creating antibodies, until there are no infected personnel left;
    18. -
    19. In case the Viral Pathogen leads to fluid leakage, cleaning these fluids is to be considered top priority;
    20. -
    21. Once the Viral Outbreak is over, all personnel are to return to regular duties.
    22. -
    -

    - -

    Coroner Procedures


    -
      -
    1. For the sake of hygiene, the Coroner should wear a Sterile Mask when handling corpses;
    2. -
    3. The Coroner must inject/apply Formaldehyde to all corpses, and place them in body bags;
    4. -
    5. The Coroner must perform a full autopsy on all corpses, and keep a record of it, in written format. If foul play is suspected, Security must be contacted;
    6. -
    7. The Coroner must correctly tag the Morgue Trays in order to identify the corpse within, as well as Cause of Death;
    8. -
    9. The Coroner must ensure Security-based DNR Notices (such as executed personnel, for instance) are respected;
    10. -
    11. The Coroner must ensure that every ID from unclonable bodies is delivered to either the relevant Head of Staff, or the Head of Personnel. This applies to any Medbay personnel placing a body in the Morgue
    12. -
    -

    - -

    Exotic Implants


    - Exotic Implants refer to Xeno Organs, Cybernetic Implants or any such exotic materials.
    -
      -
    1. General utility implants (such as Welding Shield, Nutriment or Reviver) are unregulated, and may be handed out freely;
    2. -
    3. X-Ray Vision and Thermal Vision implants may be handed out freely, but may have their implantation vetoed by the Chief Medical Officer and/or Research Director (see below);
    4. -
    5. Medical HUDs must be approved by the Chief Medical Officer before implantation, and Security HUDs require express permission from the Head of Security or Warden;
    6. -
    7. Combat-capable Implants (such as the CNS Rebooter or Anti-Drop) are not be handed out without express permission from the Head of Security;
    8. -
    9. Cybernetic Implantation should be performed in Surgery or any such sterilized environment, to reduce the risk of internal infection. If no Surgeons or Doctors are available, the Roboticist can fill in;
    10. -
    11. The Chief Medical Officer and Research Director have the power to veto any Cybernetic Implantation or Xeno Organ Implantation if they believe it threatens the stability of the station or crew. Only the Captain may override this veto;
    12. -
    13. Xeno Organs may be harvested at will, but may not be implanted without express permission from the Chief Medical Officer. Egg-Laying Organs from Xenomorph Lifeforms are strictly forbidden;
    14. -
    15. Failure to follow these Guidelines makes the offending party liable to having their Exotic Implants forcefully removed.
    16. -

    - - - - "} - -/obj/item/book/manual/sop_engineering - name = "Engineering Standard Operating Procedures" - desc = "A set of guidelines aiming at the safe conduct of all engineering activities." - icon_state = "book3" - author = "Nanotrasen" - title = "Engineering Standard Operating Procedures" - dat = {" - - - - - - - - -

    Contents

    -
      -
    1. Foreword
    2. -
    3. Chief Engineer
    4. -
    5. Station Engineer
    6. -
    7. Atmospherics Technician
    8. -
    9. Mechanic
    10. -
    -

    - -

    FOREWORD


    - Job SOP should not be a considered a checklist of conditions to fire someone over, and should not be rigidly followed to the letter in detriment of circumstances and context. - As always, SOP can be malleable if the situation so requires, and the decision to punish a crewmember for breaching it ultimately falls onto the relevant Head of Staff, - for Department Members, or Captain, for the Head of Staff.

    - -

    Chief Engineer


    -
      -
    1. The Chief Engineer must make sure that the Gravitational Singularity Engine and/or Tesla Engine and/or Solar Panels are fully set up and wired before any further action is taken by themselves or their team;
    2. -
    3. The Chief Engineer, along with the Research Director, is responsible for maintaining the integrity of Telecommunications. The Chief Engineer may not upload malicious scripts or in any way hinder the proper functionality of Telecommunications, and must diagnose and repair any issues that arise;
    4. -
    5. The Chief Engineer is not to authorize the ordering of a Supermatter Shard before any power source is fully set up;
    6. -
    7. The Chief Engineer is bound to the same rules regarding the axe as Atmospheric Technicians;
    8. -
    9. The Chief Engineer is permitted to carry a telescopic baton and a flash;
    10. -
    11. The Chief Engineer is responsible for maintaining the integrity of the Gravitational Singularity Engine and/or the Supermatter Engine and/or the Tesla Engine. Neglecting this duty is grounds for termination should the Engine malfunction;
    12. -
    13. The Chief Engineer is responsible for maintaining the integrity of the Cyberiad's Atmospherics System. Failure to maintain this integrity is grounds for termination;
    14. -
    15. The Chief Engineer may declare an area "Condemned", if it is damaged to the point where repairs cannot reasonably be completed within an acceptable frame of time;
    16. -
    17. The Chief Engineer is permitted to grant Building Permits to crewmembers, but must keep the Station Blueprints in a safe location at all times.
    18. -
    -

    - -

    Station Engineer


    -
      -
    1. Engineers must properly activate and wire the Gravitational Singularity Engine and/or Tesla Engine and/or the Solar Panels at the start of the shift, before any other actions are undertaken;
    2. -
    3. Engineers are responsible for maintaining the integrity of the Gravitational Singularity Engine and/or the Supermatter Engine and/or the Tesla Engine. Neglecting this duty is grounds for termination should the Engine malfunction;
    4. -
    5. Engineers are not permitted to construct additional power sources (Supermatter Engines, additional Tesla Engines, additional Gravitational Singularity Engines or additional Solar Panels) until at least one (1) power source is correctly wired and set up;
    6. -
    7. Engineers are permitted to carry out solo reconstruction/rebuilding/personal projects if there is no damage to the station that requires fixing;
    8. -
    9. Engineers must periodically check on the Gravitational Singularity Engine, if it is the chosen method of power generation, in intervals of, at most, thirty (30) minutes. While the Tesla Engine is not as prone to malfunction, this action should still be undertaken for it;
    10. -
    11. Engineers must constantly monitor the Supermatter Engine, if it is the chosen method of power generation, if it is currently active (ie, under Emitter Fire). This is not negotiable;
    12. -
    13. Engineers must respond promptly to breaches, regardless of size. Failure to report within fifteen (15) minutes will be considered a breach of Standard Operating Procedure, unless there are no spare Engineers to report or an Atmospheric Technician has arrived on scene first. All Hazard Zones must be cordoned off with Engineering Tape, for the sake of everyone else;
    14. -
    15. Engineers are permitted to hack doors to gain unauthorized access to locations if said locations happen to require urgent repairs;
    16. -
    17. Engineers are to maintain the integrity of the Cyberiad's Power Network. In addition, hotwiring the Gravitational Singularity Engine, Supermatter Engine or Tesla Engine is strictly forbidden;
    18. -
    19. Engineers must ensure there is at least one (1) engineering hardsuit available on the station at all times, unless there is an emergency that requires the use of all suits.
    20. -
    -

    - -

    Atmospherics Technician


    -
      -
    1. Atmospheric Technicians are permitted to completely repipe the Atmospherics Piping Setup, provided they do not pump harmful gases into anywhere except the Turbine;
    2. -
    3. Atmospheric Technicians are not permitted to create volatile mixes using Plasma and Oxygen, nor are they permitted to create any potentially harmful mixes with Carbon Dioxide and/or Nitrous Oxide. An exception is made when working with the Turbine;
    4. -
    5. Atmospheric Technicians are permitted to cool Plasma and store it for later use in Radiation Collectors. Likewise, they are permitted to cool Nitrogen or Carbon Dioxide and store it for use as coolant for the Supermatter Engine;
    6. -
    7. Atmospheric Technicians are not permitted to take the axe out of its case unless there is an immediate and urgent threat to their life or urgent access to crisis locations is necessary. The axe must be returned to the case afterwards, and the case locked;
    8. -
    9. Atmospheric Technicians are not permitted to tamper with the default values on Air Alarms. They are, however, permitted to create small, acclimatized rooms for species that require special atmospheric conditions (such as Plasmamen and Vox), provided they receive express permission from the Chief Engineer;
    10. -
    11. Atmospheric Technicians must periodically check on the Central Alarms Computer, in periods of, at most, thirty (30) minutes;
    12. -
    13. Atmospheric Technicians must respond promptly to piping and station breaches. Failure to report within fifteen (15) minutes will be considered a breach of Standard Operating Procedure, unless there are no spare Atmospheric Technicians to report, or an Engineer has arrived on scene first. All Hazard Zones must be cordoned off with Engineering Tape, for the sake of everyone else
    14. -
    -

    - -

    Mechanic


    -
      -
    1. The Mechanic is not permitted to fit any weaponry onto constructed Space Pods without express permission by the Head of Security;
    2. -
    3. The Mechanic is permitted to construct Space Pods for any crewmember that requests one, provided the Pods do not have any weaponry. Anyone possessing a Pod is to follow Mechanic SOP, Civilians included;
    4. -
    5. The Mechanic is not permitted to enter the Security Pod Bay, unless the Security Pod Pilot or Head of Security permit it;
    6. -
    7. The Mechanic is not permitted to bring any Space Pod into the actual station
    8. -
    -

    - - - - "} - -/obj/item/book/manual/sop_service - name = "Service Standard Operating Procedures" - desc = "A set of guidelines aiming at the safe conduct of all service activities." - icon_state = "book4" - author = "Nanotrasen" - title = "Service Standard Operating Procedures" - dat = {" - - - - - - - - -

    Contents

    -
      -
    1. Foreword
    2. -
    3. Chef
    4. -
    5. Bartender
    6. -
    7. Botanist
    8. -
    9. Clown
    10. -
    11. Mime
    12. -
    13. Chaplain
    14. -
    15. Janitor
    16. -
    17. Barber
    18. -
    19. Librarian
    20. -
    -

    - -

    FOREWORD


    - Job SOP should not be a considered a checklist of conditions to fire someone over, and should not be rigidly followed to the letter in detriment of circumstances and context. - As always, SOP can be malleable if the situation so requires, and the decision to punish a crewmember for breaching it ultimately falls onto the relevant Head of Staff, - for Department Members, or Captain, for the Head of Staff.

    - -

    Chef


    -
      -
    1. The Chef is not permitted to use the corpses of deceased personnel for meat unless given specific permission from the Chief Medical Officer. Exception is made for changelings and any other executed personnel not slated for Borgifications;
    2. -
    3. The Chef is permitted to use Ambrosia and other such light narcotics in the production of food;
    4. -
    5. The Chef must produce at least three (3) dishes of any food within twenty (20) minutes. Failure to do so is to be considered a breach of Standard Operating Procedure;
    6. -
    7. The Chef is not permitted to leave the kitchen unattended for longer than fifteen (15) minutes if there is no food available for consumption. Exception is made if there are no ingredients, or if the Kitchen is unusable/a hazard zone
    8. -
    -

    - -

    Bartender


    -
      -
    1. The Bartender is not permitted to carry their shotgun outside the bar. However, they may obtain permission from the Head of Security to shorten the barrel for easier transportation. Shortening the barrel without authorization is grounds for confiscation of the Bartender's shotgun;
    2. -
    3. The Bartender is permitted to use their shotgun on unruly bar patrons in order to throw them out if they are being disruptive. They are not, however, permitted to apply lethal, or near-lethal force;
    4. -
    5. The Bartender is exempt from legal ramifications when dutifully removing unruly (ie, overtly hostile) patrons from the Bar, provided, of course, they followed Guideline 2;
    6. -
    7. The Bartender is not permitted to possess regular (ie, lethal) shotgun ammunition. Only beanbag slugs are permitted. Exception is made during major emergencies, such as Nuclear Operatives or Blob Organisms;
    8. -
    9. The Bartender has full permission to forcefully throw out anyone who climbs over the bar counter without permission, up to and including personnel who may have access to the side windoor. They are not, however, permitted to do so if the person in question uses the door, or is on an active investigation;
    10. -
    11. The Bartender is permitted to ask for monetary payment in exchange for drinks
    12. -
    -

    - -

    Botanist


    -
      -
    1. Botanists are permitted to grow narcotics, presuming they do not distribute it;
    2. -
    3. Botanists must provide the Chef with adequate Botanical Supplies, per the Chef's request;
    4. -
    5. Botanists are not permitted to cause unregulated plantlife to spread outside of Hydroponics or other such designated locations;
    6. -
    7. Botanists are not permitted to hand out (spatially) unstable Botanical Supplies to non-Hydroponics personnel;
    8. -
    9. Botanists are not permitted to harvest Amanitin or other such plant/fungi-derived poisons, unless specifically requested by the Head of Security and/or Captain.
    10. -
    -

    - -

    Clown


    -
      -
    1. The Clown is permitted to, and freely exempt from any consequences of, slipping literally anyone, assuming it does not interfere with active Security duty, or in any way endangers other personnel (such as slipping a Paramedic who's dragging a wounded person to Medbay);
    2. -
    3. The Clown is not permitted to remove their Clown Shoes or Clown Mask. Exception is made if removing them is truly necessary for the sake of their clowning performance (such as being a satire of bad clowns);
    4. -
    5. The Clown is not permitted to hold anything but water in their Sunflower;
    6. -
    7. The Clown is not permitted to use Space Lube on anything. Exception is made during major emergencies involving hostile humanoids, whereby use of Space Lube may be condoned to help the crew;
    8. -
    9. The Clown must legitimately attempt to be funny and/or entertaining at least once every fifteen (15) minutes. A simple pun will suffice. Continuously slipping people for no reason does not constitute humour. The joke is supposed to be funny for everyone;
    10. -
    11. The Clown is permitted to, and freely exempt from any consequences of, performing any harmless prank that does not directly conflict with the above Guidelines
    12. -
    -
    -

    - -

    Mime


    -
      -
    1. The Mime is not permitted to talk, under any circumstance whatsoever. A Mime who breaks the Vow of Silence is to be stripped of their rank post haste;
    2. -
    3. The Mime is permitted to use written words to communicate, either via paper or PDA, but are discouraged from automatically resorting to it when miming will suffice;
    4. -
    5. The Mime must actually mime something at least once every thirty (30) minutes. Standing against an invisible wall will suffice.
    6. -
    -

    - -

    Chaplain


    -
      -
    1. The Chaplain is not permitted to execute Bible Healing without consent, unless the person in question is in Critical Condition and there are no doctors, as doing so incurs the risk of causing brain damage;
    2. -
    3. The Chaplain may not draw the Null Rod or Holy Sword on any personnel. Using these items on any personnel is grounds to have these items confiscated, unless there is a clear and present danger to their life;
    4. -
    5. The Chaplain may not actively discriminate against any personnel on the grounds that it is a religious tenet of their particular faith;
    6. -
    7. The Chaplain may not perform funerals for any personnel that have since been cloned;
    8. -
    9. The Chaplain may, however, freely conduct funerals for non-cloneable personnel. All funerals must be concluded with the use of the Mass Driver or Crematorium.
    10. -
    -

    - -

    Janitor


    -
      -
    1. The Janitor must promptly respond to any call from the crew for them to clean. Failure to respond within fifteen (15) minutes is to be considered a breach of Standard Operating Procedure;
    2. -
    3. If the Janitor's work leaves any surface slippery, they are to place wet floor signs, either physical or holographic. During major crises, such as Nuclear Operatives or Blob Organisms, the Janitor is to refrain from creating any slippery surfaces whatsoever;
    4. -
    5. The Janitor is not to use Cleaning Foam Grenades as pranking implements. Cleaning Foam Grenades are to be used to clean large surfaces at once, only;
    6. -
    7. During Viral Outbreaks, the Janitors must don their Biosuit, and focus on cleaning any biological waste, until such a point as the Viral Pathogen is deemed eliminated;
    8. -
    9. The Janitor may not deploy bear traps anywhere, unless there are actually large wild animals on the station.
    10. -
    -

    - -

    Barber


    -
      -
    1. The Barber may not give unsolicited haircuts/dye jobs to any personnel;
    2. -
    3. The Barber must perform haircuts/dye jobs as per the request of personnel, and not from personal taste
    4. -
    -

    - -

    Librarian


    -
      -
    1. The Librarian is to keep at least one (1) shelf stocked with books for the station's personnel;
    2. -
    3. The Librarian is permitted to conduct journalism on any part of the station. However, they are not entitled to participation in trials, and must receive authorization from the Head of Security or Magistrate.
    4. -
    -

    - - - - "} - -/obj/item/book/manual/sop_supply - name = "Supply Standard Operating Procedures" - desc = "A set of guidelines aiming at the safe conduct of all supply activities." - icon_state = "book1" - author = "Nanotrasen" - title = "Supply Standard Operating Procedures" - dat = {" - - - - - - - - -

    Contents

    -
      -
    1. Foreword
    2. -
    3. Quarter Master
    4. -
    5. Cargo Technician
    6. -
    7. Shaft Miner
    8. -
    -

    - -

    FOREWORD


    - Job SOP should not be a considered a checklist of conditions to fire someone over, and should not be rigidly followed to the letter in detriment of circumstances and context. - As always, SOP can be malleable if the situation so requires, and the decision to punish a crewmember for breaching it ultimately falls onto the relevant Head of Staff, - for Department Members, or Captain, for the Head of Staff.

    - -

    Quarter Master


    -
      -
    1. The Quartermaster must ensure that every approved order is delivered within 15 minutes of having been placed and approved;
    2. -
    3. In the event of a major crisis, such as Nuclear Operatives or a Blob Organism, expediency is to be favored over paperwork, as excessive bureaucracy may be detrimental to the well-being of the station;
    4. -
    5. The Quartermaster is permitted to hack the Autolathe, or to have a Cargo Tech do so, assuming they do not produce illegal materials;
    6. -
    7. The Quartermaster is not permitted to authorize the ordering of Security equipment and/or gear without express permission from the Head of Security and/or Captain. An exception is made during extreme emergencies, such as Nuclear Operatives or a Blob Organism, where said equipment is to be delivered to Security, post haste;
    8. -
    9. The Quartermaster must ensure at least one copy of every Order Form (ie, the forms produced by the Requests Console) is kept inside Cargo. The same applies for Cargo Technicians;
    10. -
    11. The Quartermaster is not permitted to produce .357 speedloaders for the Detective without express permission from the Head of Security;
    12. -
    13. The Quartermaster is not to keep any illegal items that are flushed down Disposals, and must deliver them to Security. The same applies for Cargo Technicians and Shaft Miners;
    14. -
    15. The Quartermaster is not permitted to hack the MULE Delivery Bots so that they may ride them, or that they may go faster. The same applies for Cargo Technicians and Shaft Miners;
    16. -
    17. The Quartermaster is permitted to authorize non-departmental orders (such as a Medical Doctor asking for Insulated Gloves) without express permission from the respective Head of Staff (in this example, the Chief Engineer), utilizing their best judgement, although they may still request a stamped form. However, any breach of Standard Operating Procedure and/or Space Law that results from said order will also implicate the Quartermaster;
    18. -
    19. The Quartermaster is not permitted to authorize a Supermatter Crate without express permission from the Chief Engineer.
    20. -
    -

    - -

    Cargo Technician


    -
      -
    1. Cargo Technicians are bound to the same rules as the Quartermaster regarding restricted crates (see above);
    2. -
    3. Cargo Technicians are not permitted to order items for sole personal use without express consent from the Quartermaster. Exception is made if there are more than 500 Supply Requisition Points available and no outstanding orders. Cargo Technicians may not deplete the entire stock of Requisition Points with this;
    4. -
    5. Cargo Technicians are not permitted to order non-essential items (such as cats, or clothing) without express consent from the Quartermaster;
    6. -
    7. Cargo Technicians are not permitted to force and/or break open locked crates. The same applies to the Quartermaster. Exception is made for Abandoned Crates found by Mining;
    8. -
    9. Cargo Technicians are not permitted to authorize non-departmental orders (such as a Medical Doctor asking for Insulated Gloves) without express permission from the Quartermaster;
    10. -
    11. Cargo Technicians must ensure that every approved order is delivered within 15 minutes of having been placed and approved;
    12. -
    13. Cargo Technicians must send back all crates that have been ordered, with accompanying stamped manifest inside the crate;
    14. -
    15. Cargo Technicians should ensure that a single Department does not fully drain the Ore Redemption Machine, as it can be utilized by multiple Departments;
    16. -
    17. Cargo Technicians are not permitted to ask for money in exchange for legal orders. The same applies to the Quartermaster;
    18. -
    19. Cargo Technicians are not permitted to trade items and/or favors in exchange for items with regular personnel without express consent from the Quartermaster.
    20. -
    -

    - -

    Shaft Miner


    -
      -
    1. Shaft Miners are not permitted to bring Gibtonite aboard the station;
    2. -
    3. Shaft Miners must deliver at least 1000 Points of mined material to the Ore Redemption Machine within one (1) hour;
    4. -
    5. Shaft Miners are not permitted to hoard materials. All mined materials are to be left in the Ore Redemption Machine;
    6. -
    7. Shaft Miners are not permitted to throw people into manufactured wormholes, nor are they permitted to trick people into using Bluespace Crystals, or throwing Bluespace Crystals at anyone;
    8. -
    9. Shaft Miners are not permitted to mine their way into the Labor Camp;
    10. -
    11. Should Shaft Miners encounter Xenomorph lifeforms, they are to report to Medbay immediately
    12. -
    -

    - - - - "} - -/obj/item/book/manual/sop_security - name = "Security Standard Operating Procedures" - desc = "A set of guidelines aiming at the safe conduct of all security activities." - icon_state = "book2" - author = "Nanotrasen" - title = "Security Standard Operating Procedures" - dat = {" - - - - - - - - -

    Contents

    -
      -
    1. Foreword
    2. -
    3. Head of Security
    4. -
    5. Security Officer
    6. -
    7. Warden
    8. -
    9. Detective
    10. -
    11. Security Pod Pilot
    12. -
    13. Brig Physician
    14. -
    -

    - -

    FOREWORD


    - Job SOP should not be a considered a checklist of conditions to fire someone over, and should not be rigidly followed to the letter in detriment of circumstances and context. - As always, SOP can be malleable if the situation so requires, and the decision to punish a crewmember for breaching it ultimately falls onto the relevant Head of Staff, - for Department Members, or Captain, for the Head of Staff.

    - -

    Head of Security


    - Code Green -
      -
    1. The Head of Security is permitted to carry out arrests under the same conditions as their Security Officers;
    2. -
    3. The Head of Security is permitted to carry a taser, a flash, a flashbang, a stunbaton and a can of pepperspray. While permitted to carry their unique Energy Gun, they are discouraged from doing so for safety concerns, and should keep it on Stun/Disable;
    4. -
    5. The Head of Security is not obligated to provide a trial, but is encouraged to allow legal representation should the suspect request it. This only applies to Capital Crimes;
    6. -
    7. The Head of Security may not, under any circumstance, overrule a Magistrate, unless their decisions are blatantly breaking Standard Operating Procedure and/or Space Law, in which case Central Command is to be contacted as well;
    8. -
    9. The Head of Security must follow the same guidelines as the Warden for Armory equipment, portable flashers and deployable barriers;
    10. -
    11. The Head of Security is not permitted to collect equipment from the Armory to carry on their person;
    12. -
    13. The Head of Security is permitted to either use their regular coat, or armored trenchcoat;
    14. -
    15. The Head of Security is permitted to wear their unique gas mask;
    16. -
    17. The Head of Security may not overrule established sentences, unless further evidence is brought to light or the prisoner in question attempts to escape
    18. -

    - - Code Blue -
      -
    1. All Guidelines carry over from Code Green. In regards to Guideline 2, the Head of Security is now encouraged to carry their unique Energy Gun
    2. -

    - - Code Red -
      -
    1. Guidelines 1, 3, 4, 5, 7, 8 and 9 are carried over from Code Green;
    2. -
    3. The Head of Security is permitted to take whatever equipment they require from the Armory, provided they leave enough equipment for the rest of the Security force;
    4. -
    5. The Head of Security is required to produce a Station Announcement regarding the nature of the confirmed threat that caused Code Red;
    6. -
    7. Lethal Force is permitted if the target is confirmed to be guilty of Capital Crimes and actively, and aggressively, resists arrest
    8. -

    -

    - -

    Security Officer


    - Code Green -
      -
    1. Security Officers are required to state the reasons behind an arrest before any further action is taken. Exception is made if the suspect refuses to stop;
    2. -
    3. Security Officers must attempt to bring all suspects or witnesses to the Brig without handcuffing or incapacitating them. Should the suspect not cooperate, the officer may proceed as usual;
    4. -
    5. No weapons are to be unholstered until the suspect attempts to run away or becomes actively hostile;
    6. -
    7. Security Officers are permitted to carry a taser, a flash, a flashbang, a stunbaton and a can of pepperspray;
    8. -
    9. Security Officers may not demand access to the interior of other Departments during regular patrols. However, asking for access from the Head of Personnel is still acceptable;
    10. -
    11. Security officers are not permitted to have weapons drawn during regular patrols;
    12. -
    13. Security officers are permitted to conduct searches, provided there is reasonable evidence/suspicion that the person in question has committed a crime. Any further searches require a warrant from the Head of Security, Captain or Magistrate;
    14. -
    15. Lethal Force is not authorized unless there is a clear and immediate threat to the station's integrity or the Officer's life
    16. -

    - - Code Blue -
      -
    1. Guidelines 1, 2, 4 and 8 are carried over from Code Green;
    2. -
    3. Security Officers are permitted to carry around any weapons or equipment available in the Armory, at the Warden's discretion, but never more than one at a time. Exception is made for severe emergencies, such as Blob Organisms or Nuclear Operatives;
    4. -
    5. Security Officers are permitted to carry weapons in hand during regular patrols, although this is not advised;
    6. -
    7. Security Officers are permitted to present weapons during arrests;
    8. -
    9. Security Officers may demand entry to specific Departments during regular patrols;
    10. -
    11. Security Officers may randomly search crewmembers, but are not allowed to apply any degree of force unless said crewmember acts overtly hostile. Crew who refuse to be searched may be stunned and cuffed for the search;
    12. -
    13. Security Officers are permitted to leave prisoners bucklecuffed should they act hostile.
    14. -

    - - Code Red -
      -
    1. Guidelines 2, 3, 4, 5, 6 and 7 are carried over from Code Blue;
    2. -
    3. Security Officers may arrest crewmembers with no stated reason if there is evidence they are involved in criminal activities;
    4. -
    5. Security Officers may forcefully relocate crewmembers to their respective Departments if necessary;
    6. -
    7. Lethal Force is permitted if the target is confirmed to be guilty of Capital Crimes and actively, and aggressively, resists arrest.
    8. -

    -

    - -

    Warden


    - Code Green -
      -
    1. The Warden may not perform arrests if there are Security Officers active;
    2. -
    3. The Warden must conduct a thorough search of every prisoner's belongings, including pockets, PDA slots, any coat pockets and suit storage slots;
    4. -
    5. The Warden is not obligated to provide a trial, but is encouraged to allow legal representation should the suspect request it. This only applies to Capital Crimes;
    6. -
    7. The Warden may not hand out any weapons or armour from the Armory, except for extra tasers. Hardsuits may be issued if emergency E.V.A action is required. Exception is made if there is an immediate threat that requires attention, such as Nuclear Operatives, or rioters;
    8. -
    9. The Warden is permitted to carry a taser, a flash, a stunbaton, a flashbang and a can of pepperspray;
    10. -
    11. The Warden may not place the portable flashers within the Brig;
    12. -
    13. The Warden may not place the deployable barriers within the Brig;
    14. -
    15. The Warden must read to every prisoner the crimes they are sentenced to;
    16. -
    17. The Warden is not permitted to leave prisoners bucklecuffed to their beds. An exception is made if the prisoners acts overtly hostile or attempts to breach the cell in order to escape.
    18. -

    - - Code Blue -
      -
    1. Guidelines 1, 2, 3, 5 and 8 are carried over from Code Green;
    2. -
    3. The Warden is permitted to hand out all equipment from the Armory. Energy and Laser guns are only to be handed out with Head of Security or Captain's approval, as they present a lethal risk, or if there is an immediate threat, such as Blob Organisms or Nuclear Operatives;
    4. -
    5. The Warden is permitted to place the portable flashers inside the Brig;
    6. -
    7. The Warden is permitted to place the deployable barriers inside the Brig
    8. -

    - - Code Red -
      -
    1. Guidelines 2, 3, 5 and 8 are carried over from Code Green;
    2. -
    3. Guidelines 3 and 4 are carried over from Code Blue. In addition, the Warden may also carry any weapon from the Armory, but never more than one at a time;
    4. -
    5. The Warden is permitted to distribute any weapon or piece of equipment in the Armory. This includes whatever Research has provided;
    6. -
    7. The Warden is permitted to carry out arrests freely;
    8. -
    9. Lethal Force is permitted if the target is confirmed to be guilty of Capital Crimes and actively, and aggressively, resists arrest.
    10. -

    -

    - -

    Detective


    - Code Green -
      -
    1. The Detective may not perform arrests or searches unless given specific permission by the Head of Security or Warden. Exception is made if there are no active Officers or Warden;
    2. -
    3. The Detective may not intentionally go around Security officers to perform arrests. If Officers are available, arrests may only be performed if there is an immediate violent threat to the Detective or anyone around them;
    4. -
    5. The Detective may not unholster their revolver unless a clear and present danger to their life is present;
    6. -
    7. The Detective may carry their revolver, along with spare ammunition;
    8. -
    9. The Detective may carry their telescopic baton;
    10. -
    11. Should the Detective be assaulted by a crewmember, they must use the issued Telescopic Baton to apprehend them. Using the revolver is permitted only if the crewmember attempts to escape and there are no Officers available for backup;
    12. -
    13. The Detective may not search anyone in the Brig without permission from the Warden or Head of Security;
    14. -
    15. The Detective is not permitted to modify their revolver to chamber lethal rounds, under any circumstance;
    16. -
    17. The Detective must compile all evidence gathered into organized dossiers, and have at least one copy available at all times.
    18. -

    - - Code Blue -
      -
    1. Guidelines 4, 5, and 9 are carried over from Code Green;
    2. -
    3. If sufficient forensic evidence is collected, and there are no Security Officers available at the time, the Detective is permitted to carry out arrests if a prior warning is given via Security Comms;
    4. -
    5. The Detective is obligated to inform the suspect of the crimes they are accused;
    6. -
    7. The Detective may search any suspect in the Brig;
    8. -
    9. The Detective may pull aside any suspect for an interrogation, provided they receive authorization from the Head of Security or the Warden;
    10. -
    11. The Detective may unholster their revolver whenever they deem it necessary, though it is recommended they do so sparsely
    12. -
    13. Lethal Force is not permitted, unless there is a clear and immediate danger to the Detective's life
    14. -

    - - Code Red -
      -
    1. Guidelines 4, 5 and 9 carry over from Code Green;
    2. -
    3. Guidelines 2, 3, 4, 5, 6 and 7 carry over from Code Blue;
    4. -
    5. The Detective may freely discharge his revolver when handling confirmed threats;
    6. -
    7. Lethal Force is permitted if the target is confirmed to be guilty of Capital Crimes and actively, and aggressively, resists arrest.
    8. -

    -

    - -

    Security Pod Pilot


    - Code Green -
      -
    1. The Security Pod Pilot is permitted to carry out arrests under the same conditions as a Security Officer;
    2. -
    3. The Security Pod Pilot is permitted to carry a taser, a flash, a stunbaton, a flashbang and a can of pepperspray;
    4. -
    5. The Security Pod Pilot is not permitted to bring the Security Pod inside the station, except for designated Pod Bays;
    6. -
    7. The Security Pod Pilot is not permitted to swap the Security Pod's weapon systems to the Laser Module unless a lethal threat, such as Space Carp or Attack Drones, is present;
    8. -
    9. The Security Pod Pilot is not permitted to use the Laser Module during arrests, and must switch to the Disabler Module;
    10. -
    11. The Security Pod Pilot must carry around a spare set of tools and energy cell, for their own sake;
    12. -
    13. The Security Pod Pilot may immediately, and without warning, conduct arrests on individuals attempting to perform E.V.A actions near the AI Satellite. Exception is made if the AI Unit is malfunctioning;
    14. -
    15. The Security Pod Pilot is not permitted to explore the area surrounding the station, and must therefore be confined to the immediate orbital area of the NSS Cyberiad, the NXS Klapaucius (the Telecomms Satellite) and the Mining/Research Asteroid. Exception is made if the Head of Security permits otherwise.
    16. -

    - - Code Blue -
      -
    1. Guidelines 1, 2, 7 and 8 are carried over from Code Green. In regards to Guideline 2, Pod Pilots are now also permitted to carry around Bulletproof Armour or Riot Gear;
    2. -
    3. Pod Pilots are permitted to carry weapons in hand during regular patrols;
    4. -
    5. Pod Pilots are permitted to present weapons during arrests;
    6. -
    7. Pod Pilots may demand entry to specific Departments during regular patrols;
    8. -
    9. Pod Pilots may randomly search crewmembers, but are not allowed to apply any degree of force unless said crewmember acts overtly hostile;;
    10. -
    11. Pod Pilots are permitted to leave prisoners bucklecuffed should they act hostile.
    12. -

    - - Code Red -
      -
    1. Guidelines 1, 2, 7 and 8 carry over from Code Green;
    2. -
    3. All Guidelines carry over from Code Blue;
    4. -
    5. The Security Pod Pilot is permitted to carry any weapon from the Armory, but never more than one at a time. Exception is made for severe emergencies, such as Blob Organisms or Nuclear Operatives;
    6. -
    7. The Security Pod Pilot is permitted to bring the Security Pod inside the station in extreme emergencies;
    8. -
    9. The Security Pod Pilot is permitted to permanently install the Laser Module onto the Security Pod;
    10. -
    11. Lethal Force is permitted if the target is confirmed to be guilty of Capital Crimes and actively, and aggressively, resists arrest.
    12. -

    -

    - -

    Brig Physician


    - Code Green -
      -
    1. The Brig Physician may not, under any circumstance, arrest anyone;
    2. -
    3. The Brig Physician may not, under any circumstance, interfere with Security's duties;
    4. -
    5. The Brig Physician may not, under any circumstance, directly alter a sentence, or attempt to contest one with Security personnel. Contacting a Magistrate/IAA/NT Representative is still acceptable;
    6. -
    7. The Brig Physician must wait until someone is brigged and their timer starts before bringing them to the Brig Medbay. Exception is made if the Head of Security or Warden allows it, or there is a problem that requires immediate medical aid to prevent death;
    8. -
    9. The Brig Physician may not stop a timer if a prisoner is brought into the Brig Medbay for treatment. The timer is to continue while they are treated. If the timer runs out during medical treatment, the prisoner is to be released;
    10. -
    11. The Brig Physician may not restrain a prisoner unless they are actively hostile;
    12. -
    13. The Brig Physician is permitted to carry a flash and a can of pepperspray;
    14. -
    15. The Brig Physician must maintain the Brig Medbay, himself and all treated prisoners in a hygienic condition. Should the need arise, this extends to the rest of the Brig as well;
    16. -
    17. The Brig Physician must escort all prisoners requiring surgery to Medbay personally, and make sure that they are returned to the Brig before being released. The Brig Physician may also choose to construct a smaller surgery room inside the Brig Medbay.
    18. -

    - - Code Blue -
      -
    1. All Guidelines carry over from Code Green;
    2. -
    3. Additional equipment may be provided by the Warden for self-defense;
    4. -

    - - Code Red -
      -
    1. All guidelines carry over from Code Green;
    2. -
    3. All guidelines carry over from Code Blue.
    4. -

    -

    - - - - - "} - -/obj/item/book/manual/sop_legal - name = "Legal Standard Operating Procedures" - desc = "A set of guidelines aiming at the safe conduct of all legal activities." - icon_state = "book1" - author = "Nanotrasen" - title = "Legal Standard Operating Procedures" - dat = {" - - - - - - - - -

    Contents

    -
      -
    1. Punishments
    2. -
    3. Brigging
    4. -
    5. Permabrigging
    6. -
    7. Execution: General
    8. -
    9. Execution: Electric Chair
    10. -
    11. Execution: Lethal Injection
    12. -
    13. Execution:Firing Squad
    14. -
    -

    - -

    Punishments


    - These are the procedures for standard punishments, and should be followed unless an emergency makes them unable to be followed.

    - -

    Brigging


    -
      -
    1. No prisoner is to be held for longer than ten (10) minutes in Processing if no evidence against them is readily available. Should the ten (10) minutes expire without any evidence of any crimes coming to light, the prisoner is to be released. Otherwise, proceed with the following guidelines:
    2. -
    3. The prisoner is to be cuffed, and brought to their cell.
    4. -
    5. The prisoner is to be stripped of all belongings, save for their uniform, headset, ID, PDA and shoes. Vox are to retain their internals, plasmamen are to retain internals and their suit.
    6. -
    7. The prisoner is then to be uncuffed. If they are a violent risk, they may be bucklecuffed, flashed, then have their cuffs removed.
    8. -
    9. The timer for the cell is to be set, and the charges declared.
    10. -
    11. Prisoners attempting to break the windows of the cell are to be flashed and their timers reset.
    12. -
    13. Removal of the prisoner's headset may ONLY occur if the prisoner is using the headset to encourage further crimes or co-ordinate an escape attempt.
    14. -
    -

    - -

    Permabrigging


    -
      -
    1. Prisoner must be cuffed, and their ID must be terminated.
    2. -
    3. Prisoner must be stripped of all belongings, except for his/her headset and ID Card. Said belongings must be placed in one of the lockers next to the Interrogation Room.
    4. -
    5. Prisoner must be clothed in a Prison Uniform and Orange Shoes.
    6. -
    7. Prisoner must be brought to the Permabrig area, and the doors behind closed properly.
    8. -
    9. Prisoner must be bucklecuffed to one of the beds.
    10. -
    11. Prisoner must have his cuffs removed, then be flashed or stunned, and the cuffs recovered.
    12. -
    13. All Security agents must then leave the Permabrig.
    14. -
    15. In the case of an attempted escape or riot, the Nitrous Oxide control is to be used.
    16. -
    -

    - -

    Execution: General


    -
      -
    1. Prisoner must be cuffed, and their ID must be terminated.
    2. -
    3. Prisoner must be stripped of all belongings, except for his/her headset and ID Card. Said belongings must be placed in one of the lockers next to the Interrogation Room.
    4. -
    5. Prisoner must be clothed in a Prison Uniform and Orange Shoes.
    6. -
    7. Prisoner must be brought to the Prisoner Transfer room.
    8. -
    9. A Chaplain may be present if requested, and allowed by the HoS.
    10. -
    11. It is advised, but not required, to have a Brig Physician or other medical personell in attendance to verify death.
    12. -
    13. Authorization must be given by the Captain and/or Magistrate. Without authorization, executions are murder.
    14. -
    15. Though not obligatory, it is recommended that all executed prisoners be considered for borgification post-execution.
    16. -
    -

    - -

    Execution: Electric Chair


    -
      -
    1. Prisoner must be bucklecuffed to the electric chair.
    2. -
    3. Prisoner must be allowed his/her final words, after which the chair will be activated.
    4. -
    5. Prisoner's pulse is to be checked to confirm death.
    6. -
    7. Prisoner must then be borged, fired into space via mass driver, cremated, or placed in the morgue with a DNR Notice, at the discretion of the Magistrate, Captain or Head of Security.
    8. -
    -

    - -

    Execution: Lethal Injection


    -
      -
    1. Prisoner must be bucklecuffed to the electric chair or bed.
    2. -
    3. Prisoner must be allowed his/her final words, after which the injection will be applied.
    4. -
    5. Prisoner's pulse is to be checked to confirm death.
    6. -
    7. Prisoner must then be borged, fired into space via mass driver, cremated, or placed in the morgue with a DNR Notice, at the discretion of the Magistrate, Captain or Head of Security.
    8. -
    -

    - -

    Execution: Firing Squad


    -
      -
    1. Prisoner must be brought to the Firing Range.
    2. -
    3. Prisoner must be bucklecuffed to a chair.
    4. -
    5. Prisoner must be allowed his/her final words, after which authorised security personell are to open fire with any of the following: Energy Gun, Advanced Energy Gun, Laser Gun, Revolver, Shotgun, or any ranged weapon manufactured by Research.
    6. -
    7. Prisoner's pulse is to be checked to confirm death.
    8. -
    9. Prisoner must then be borged, fired into space via mass driver, cremated, or placed in the morgue with a DNR Notice, at the discretion of the Magistrate, Captain or Head of Security.
    10. -
    -

    - - - - "} - -/obj/item/book/manual/sop_general - name = "Standard Operating Procedures" - desc = "A set of guidelines aiming at the safe conduct of all station activities." - icon_state = "book1" - author = "Nanotrasen" - title = "Standard Operating Procedures" - dat = {" - - - - - - - - -

    Contents

    -
      -
    1. FOREWORD
    2. -
    3. Code Green
    4. -
    5. Code Blue
    6. -
    7. Code Red
    8. -
    9. Code Gamma
    10. -
    11. Hiring Policies
    12. -
    13. Firing Policies
    14. -
    15. Causes for Demotion and Dismissal
    16. -
    17. Situational SoP
    18. -
    19. Evacuation
    20. -
    21. Viral Outbreak Procedures
    22. -
    23. Fire and Environmental Hazards
    24. -
    25. Meteor Storm
    26. -
    27. Singularity Containment Failure
    28. -
    -

    - -

    FOREWORD


    - Job SOP should not be a considered a checklist of conditions to fire someone over, and should not be rigidly followed to the letter in detriment of circumstances and context. - As always, SOP can be malleable if the situation so requires, and the decision to punish a crewmember for breaching it ultimately falls onto the relevant Head of Staff, - for Department Members, or Captain, for the Head of Staff.

    - - -

    Code Green


    - All clear.
    - Default operating level. No immediate or clear threat to the station. All departments may carry out work as normal. - This alert level can be set at the Communications Console with a Captain level ID.
    - All threats to the station have passed. All weapons need to be holstered and privacy laws are once again fully enforced.
    -
    - Security:
    -
      -
    • Weapons worn by security/headstaff are to be holstered, except in emergencies.
    • -
    • Security must respect the privacy of crew members and no unauthorized searches are allowed. Searches of any kind may only be done with a signed warrant by the Head of Security or higher, or if there's evidence of criminal activity.
    • -
    -
    - Locations:
    -
      -
    • Secure areas are recommended to be left unbolted. This includes EVA, Teleporter, AI Upload, Engineering Secure Storage, and Tech Storage.
    • -
    -
    - Crew:
    -
      -
    • Crew members may freely walk in the hallways
    • -
    • Suit sensors are not mandatory.
    • -
    -

    - -

    Code Blue


    - There is a suspected threat.
    - Raised alert level. Suspected threat to the station. Issued by Central Command, the Captain, or a Head of Staff vote. This alert level can be set at the Communications Console with a Captain level ID.
    - Security staff may have weapons visible, random searches are permitted.
    -
    - Security:
    -
      -
    • Security may have weapons visible, but not drawn unless needed.
    • -
    • Energy guns, laser guns and riot gear are allowed to be given out to security personnel with clearance from the Warden or HoS.
    • -
    • Body Armour and helmets are recommended but not mandatory.
    • -
    • Random body and workplace searches are allowed without warrant.
    • -
    -
    - Locations:
    -
      -
    • Secure areas may be bolted down. This includes EVA, Teleporter, AI Upload, Engineering Secure Storage, and Tech Storage.
    • -
    -
    - Crew:
    -
      -
    • Employees are recommended to comply with all security requests.
    • -
    • Suit sensors are mandatory, but coordinate positions are not required.
    • -
    -

    - -

    Code Red


    - There is a confirmed threat.
    - Maximum alert level. Confirmed threat to the station or severe damage. Issued by Central Command, the Captain, or a Head of Staff vote. This alert level can only be set via the Keycard Authentication Devices in each Heads of Staff office and by swiping two Heads of Staff ID cards simultaneously.
    - Security staff to be on high alert, random searches are permitted and recommended.
    -
    - Security:
    -
      -
    • Security may have weapons drawn at all times.
    • -
    • Body Armour and helmets are mandatory. Riot gear is also recommended for appropriate situations.
    • -
    • Random body and workplace searches are allowed and recommended.
    • -
    -
    - Locations:
    -
      -
    • Secure areas are recommended to be bolted.
    • -
    -
    - Crew:
    -
      -
    • Suit sensors and coordinate positions are mandatory.
    • -
    • All crew members must remain in their departments.
    • -
    • Employees are required to comply with all security requests.
    • -
    • Emergency Response Team may be authorised. All crew are to comply with their direction.
    • -
    -

    - -

    Code Gamma


    - Extremely hostile threat onboard the station.
    - GAMMA Security level has been set by Centcom.
    - Security is to have weapons at hand at all time, random searches are permitted and Martial Law is declared.
    -
    - Security:
    -
      -
    • Security may have weapons drawn at all times.
    • -
    • Body Armour and helmets are mandatory. Riot gear is also recommended for appropriate situations.
    • -
    • Random body and workplace searches are allowed and recommended.
    • -
    • GAMMA Armory unlocked for security personnel.
    • -
    -
    - Locations:
    -
      -
    • Secure areas are to be bolted.
    • -
    -
    - Crew:
    -
      -
    • Employees are required to comply with all security requests.
    • -
    • All civilians are to seek their nearest head for transportation to a safe location.
    • -
    • All personnel are required to defend the station and help security with dealing with the threat. All crew must follow direct orders from Security Personell or Head of Staff.
    • -
    -

    - -

    Hiring Policies


    -
      -
    • Authorisation from the relevant Department Head is required to be hired into a Department. If none exists, the HoP or Captain's authorisation is required.
    • -
    • Promotion to a Department Head requires authorisation from the Captain or Acting Captain.
    • -
    • CentComm Authorisation is required for hiring the following: Blueshield, Security Pod Pilot, Magistrate, Brig Physician, Nanotrasen Representative, Mechanic.
    • -
    • If no Department Head has yet been sent, any promotion to said position is on a temporary basis until one arrives.
    • -
    • All Security personnel are to be mindshield implanted.
    • -
    -

    - -

    Firing Policies


    -
      -
    • If a crew is to be dismissed, their ID is to be terminated.
    • -
    • Demotion may be to any rank lower than their current. Assistant or Janitor are recommended for punishments.
    • -
    • Demotion or Dismissal must be authorised by the relevant department head, or Captain.
    • -
    • Demotion or Dismissal must have due cause.
    • -
    -

    - -

    Causes for Demotion and Dismissal


    -
      -
    • A medium or higher crime may be grounds for dismissal, at the department head's discretion.
    • -
    • A Capital Crime requires dismissal.
    • -
    • Any crew shown not to have the skills or knowledge necessary for the position should be dismissed.
    • -
    • Failure to follow SoP may be grounds for dismissal, at the Department Head's discretion.
    • -
    • Failure to follow SoP causing harm to crew requires dismissal, and brig time.
    • -
    • Refusal to follow reasonable and legal orders from relevant department head is grounds for dismissal. Their status as reasonable and legal is to be judged by the HoP or Captain.
    • -
    • A crew member creating an abusive and hostile work environment may be dismissed or demoted. This is to be judged by the Department Head and HoP.
    • -
    • Demotion or dismissal may be in person, or declared on a radio channel. If demoted or dismissed, an employee is required to attend the HoP office to hand in their ID, and to leave all items as part of their job at their workplace.
    • -
    • Reasonable time is to be allowed for the fired persons to obtain a new set of clothing from the locker room.
    • -
    • Failure or refusal to hand in any items, ID, etc, of their previous job, is to be considered theft.
    • -
    -

    - -

    Situational SoP


    - The following situations have specific SoP. Failure to follow these may result in demotion/dismissal, or detaining by security if failure to follow them presents a significant risk. -

    - -

    Evacuation


    -
      -
    • All personnel are required to assist with evacuation. All crew must be evacuated, regardless of conscious state.
    • -
    • A Capital Crime requires dismissal.
    • -
    • All prisoners are to be brought to the secure area of the escape shuttle, unless doing so would cause unnecessary risk for crew.
    • -
    • Bodies are to be brought back to Central Command for processing.
    • -
    • AI units may be brought to Central Command on portable card devices (Intelicards) if structural failure is likely.
    • -
    • Shortening time to shuttle launch may be authorised if a clear threat to life, limb, or shuttle integrity is present.
    • -
    -

    - -

    Viral Outbreak Procedures


    - Definition: A Viral Outbreak is defined as a situation where a Viral Pathogen has infected a significant portion of the crew (>10%) -
      -
    1. All Medbay personnel are to contribute in fighting the outbreak if there are no other critical patients requiring assistance. Eliminating the Viral Threat becomes number one priority;
    2. -
    3. Personnel are to be informed of known symptoms, and directed to Medbay immediately if they are suffering from them;
    4. -
    5. All infected personnel are to be confined to either an Isolated Room, or Virology;
    6. -
    7. A blood sample is to be taken from an infected person, for study;
    8. -
    9. If any infected personnel attempt to leave containment, Medbay Quarantine is to be initiated immediately, and only lifted when more patients need to be admitted, or the Viral Outbreak is over;
    10. -
    11. A single infected person may volunteer to receive a dose of Radium in order to develop Antibodies. Radium must not be administered without consent. Otherwise, animal testing is to be conducted in order to obtain Antibodies;
    12. -
    13. Once Antibodies are produced, they are to be diluted, then handed out to all infected personnel. Injecting infected personnel with Radium after Antibodies have been extracted is forbidden. In the event of a large enough crisis, directly injecting blood with the relevant Antibodies is permissible;
    14. -
    15. Viral Pathogen should be cataloged and analyzed, in case any stray cases remained untreated;
    16. -
    17. Cured personnel should have a sample of their blood removed for the purpose of creating antibodies, until there are no infected personnel left;
    18. -
    19. In case the Viral Pathogen leads to fluid leakage, cleaning these fluids is to be considered top priority;
    20. -
    21. Once the Viral Outbreak is over, all personnel are to return to regular duties.
    22. -
    -

    - -

    Evacuation


    -
      -
    • Immediate evacuation of all untrained personnel.
    • -
    • Fire alarms to be used to control hazard.
    • -
    • Atmospheric Technicians are to remove hazard.
    • -
    -

    - -

    Meteor Storm


    -
      -
    • All crew to move to central parts of the station.
    • -
    • Damage is to be repaired by engineering personnel after the threat has passed.
    • -
    • Personel that are doing EVA maintenance should seek shelter immediately.
    • -
    -

    - -

    Singularity Containment Failure


    -
      -
    • Observation of Singularity movement.
    • -
    • Evacuation to be called if deemed a major threat to station integrity.
    • -
    • Demotion of Chief Engineer and reparation of Engine if no threat manifests.
    • -
    -

    - - - - - "} - -/obj/item/book/manual/sop_command - name = "Command Standard Operating Procedures" - desc = "A set of guidelines aiming at the safe conduct of all Command activities." - icon_state = "book4" - author = "Nanotrasen" - title = "Command Standard Operating Procedures" - dat = {" - - - - - - - - -

    Contents

    -
      -
    1. Foreword
    2. -
    3. Captain
    4. -
    5. Head of Personnel
    6. -
    7. NanoTrasen Representative
    8. -
    9. Blueshield Officer
    10. -
    11. AI
    12. -
    -

    - -

    FOREWORD


    - Job SOP should not be a considered a checklist of conditions to fire someone over, and should not be rigidly followed to the letter in detriment of circumstances and context. - As always, SOP can be malleable if the situation so requires, and the decision to punish a crewmember for breaching it ultimately falls onto the relevant Head of Staff, - for Department Members, or Captain, for the Head of Staff.

    - -

    Captain


    -
      -
    1. The Captain is not permitted to perform regular Security Duty. However, they may still assist Security if they are understaffed, or if they see a crime being committed. However, the Captain is not permitted to take items from the Armory under normal circumstances, unless authorized by the Head of Security. In addition, the Captain may not requisition weaponry for themselves from Cargo and/or Science, unless there's an immediate threat to station and/or crew;
    2. -
    3. If a Department lacks a Head of Staff, the Captain should make reasonable efforts to appoint an Acting Head of Staff, if there are available personnel to fill the position;
    4. -
    5. The Captain is to ensure that Space Law is being correctly applied. This should be done in cooperation with the Head of Security;
    6. -
    7. The Captain is not to leave the NSS Cyberiad unless given specific permission by Central Command, or it happens to be the end of the shift. This includes via space or via the Gateway. To do so is to be considered abandoning their posts and is grounds for termination;
    8. -
    9. The Captain must keep the Nuclear Authentication Disk on their person at all times or, failing that, in the possession of the Head of Security or Blueshield;
    10. -
    11. The Captain is to attempt to resolve every issue that arises in Command locally before contacting Central Command;
    12. -
    13. The Captain is not permitted to carry their Antique Laser Gun or Space Armor unless there's an immediate emergency that requires attending to;
    14. -
    15. The Captain, despite being in charge of the Cyberiad, is not independent from NanoTrasen. Any attempts to disregard general company policy are to be considered an instant condition for contract termination;
    16. -
    17. The Captain may only promote personnel to a Acting Head of Staff position if there is no assigned Head of Staff associated with the Department. Said Acting Head of Staff must be a member of the Department they are to lead. See below for more information on Chain of Command;
    18. -
    19. The Captain may not fire any Head of Staff without reasonable justification (ie, incompetency, criminal activity, or otherwise any action that endangers/compromises the station and/or crew). The Captain may not fire any Central Command VIPs (ie, Blueshield, Magistrate, NanoTrasen Representative) without permission from Central Command, unless they are blatantly acting against the well-being and safety of the crew and station.
    20. -

    - -

    Head of Personnel


    -
      -
    1. The Head of Personnel may not transfer any personnel to another Department without authorization from the relevant Head of Staff. If no Head of Staff is available, the Head of Personnel may make a judgement call. This does not apply to Security, which always requires authorization from the Head of Security, or Genetics, which requires both Chief Medical Officer and Research Director approval. If there is no Head of Security active, no transfers are allowed to Security without authorization from the Captain;
    2. -
    3. The Head of Personnel may not give any personnel increased access without authorization from the relevant Head of Staff. This includes the Head of Personnel. In addition, the Head of Personnel may only give Captain-Level access to someone if they are the Acting Captain. This access is to be removed when a proper Captain arrives on the station;
    4. -
    5. The Head of Personnel may not increase any Job Openings unless the relevant Head of Staff approves;
    6. -
    7. The Head of Personnel may not fire any personnel without authorization from the relevant Head of Staff, unless other conditions apply (see Space Law and General Standard Operating Procedure);
    8. -
    9. The Head of Personnel may not promote any personnel to the following Jobs without authorization from Central Command: Barber, Brig Physician, NanoTrasen Representative, Blueshield, Security Pod Pilot, Mechanic and Magistrate; (This is due to them being karma locked. Do not promote people to these positions without approval from the Administrators);
    10. -
    11. The Head of Personnel is free to utilize paperwork at their discretion. However, during major station emergencies, expediency should take precedence over bureaucracy;
    12. -
    13. The Head of Personnel may not leave their office unmanned if there are personnel waiting in line. Failure to respond to personnel with a legitimate request within ten (10) minutes, either via radio or in person, is to be considered a breach of Standard Operating Procedure;
    14. -
    15. Despite nominally being in charge of Supply, the Head of Personnel should allow the Quartermaster to run the Department, unless they prove themselves to be incompetent/dangerous;
    16. -
    17. The Head of Personnel is bound to the same rules regarding ordering Cargo Crates as the Quartermaster and Cargo Technicians. In addition, the Head of Personnel may not order unneeded, non-essential items against the wishes of Cargo;
    18. -
    19. The Head of Personnel is not permitted to perform Security duty. The Head of Personnel is permitted to carry an Energy Gun, for self-defence only.
    20. -

    - -

    NanoTrasen Representative


    -
      -
    1. The NanoTrasen Representative is to ensure that every Department is following Standard Operating Procedure, up to and including the respective Head of Staff. If a Head of Staff is not available for a Department, the NanoTrasen Representative must ensure that the Captain appoints an Acting Head of Staff for said Department;
    2. -
    3. The NanoTrasen Representative must attempt to resolve any breach of Standard Operating Procedure locally before contacting Central Command. This is an imperative: Standard Operating Procedure should always be followed unless there is a very good reason not to;
    4. -
    5. The NanoTrasen Representative must, together with the Magistrate and Head of Security, ensure that Space Law is being followed and correctly applied;
    6. -
    7. The NanoTrasen Representative may not threaten the use of a fax in order to gain leverage over any personnel, up to and including Command. In addition they may not threaten to fire, or have Central Command, fire anyone, unless they actually possess a demotion note;
    8. -
    9. The NanoTrasen Representative is permitted to carry their Stun-Cane, or a Telescopic Baton if the Stun-Cane is lost.
    10. -

    - -

    Blueshield Officer


    -
      -
    1. The Blueshield may not conduct arrests under the same conditions as Security. However, they may apprehend any personnel that trespass on a Head of Staff Office or Command Area, any personnel that steal from those locations, or any personnel that steal from and/or injure any Head of Staff or Central Command VIP. However, all apprehended personnel are to be processed by Security personnel;
    2. -
    3. The Blueshield is to put the lives of Command over those of any other personnel, the Blueshield included. Their continued well-being is the Blueshield's top priority. This includes applying basic first aid and making sure they are revived if killed;
    4. -
    5. The Blueshield is to protect the lives of Command personnel, not follow their orders to a fault. The Blueshield is not to interfere with legal demotions or arrests. To do so is to place themselves under the Special Modifier Aiding and Abetting;
    6. -
    7. The Blueshield is not to apply Lethal Force unless there is a clear and present danger to their life, or to the life of a member of Command, and the assailant cannot be non-lethally detained.
    8. -

    - -

    AI


    - The following are procedures for AI Maintenance:
    -
      -
    1. Only the Captain or Research Director may enter the AI Upload to perform Law Changes (see below), and only the Captain, Research Director or Chief Engineer may enter the AI Core to perform a Carding (see below);
    2. -
    3. No Law Changes are to be performed without approval from the Captain and Research Director. The only Lawsets to be used are those provided by NanoTrasen. Failure to legally perform a Law Change is to be considered Sabotage. Command must be informed prior to the Law Change, and all objections must be taken into consideration. If the number of Command personnel opposing the Law Change is greater than the number of Command personnel in favour, the Law Change is not to be done. If the Law Change is performed, the crew is to be immediately informed of the new Law(s);
    4. -
    5. The AI may not be Carded unless it it clearly malfunctioning or subverted. However, any member of Command may card it if the AI agrees to it, either at the end of the shift, or due to external circumstances (such as massive damage to the AI Satellite);
    6. -
    7. The AI Upload and Minisat Antechamber Turrets are to be kept on Non-Lethal in Code Green and Code Blue. The AI Core Turrets are to be kept on Lethal at all times. If a legal Law Change or Carding is occurring, the Turrets are to be disabled;
    8. -
    9. If the AI Unit is not malfunctioning or subverted, any attempt at performing an illegal Carding or Law Change is to be responded to with non-lethal force. If the illegal attempts persist, and the perpetrator is demonstrably hostile, lethal force from Command/Security is permitted;
    10. -
    11. Freeform Laws are only to be added if absolutely necessary due to external circumstances (such as major station emergencies). Adding unnecessary Freeform Laws is not permitted. Exception is made if the AI Unit and majority of Command agree to the Freeform Law that is proposed;
    12. -
    13. Any use of the "Purge" Module is to be followed by the upload of a NanoTrasen-approved Lawset immediately. AI Units must be bound to a Lawset at all times.
    14. -

    - - - - "} \ No newline at end of file diff --git a/paradise.dme b/paradise.dme index 3ef86b2687f..83f25b5c819 100644 --- a/paradise.dme +++ b/paradise.dme @@ -60,6 +60,7 @@ #include "code\__DEFINES\typeids.dm" #include "code\__DEFINES\vv.dm" #include "code\__DEFINES\zlevel.dm" +#include "code\__HELPERS\_logging.dm" #include "code\__HELPERS\_string_lists.dm" #include "code\__HELPERS\AnimationLibrary.dm" #include "code\__HELPERS\cmp.dm" @@ -71,7 +72,6 @@ #include "code\__HELPERS\icon_smoothing.dm" #include "code\__HELPERS\icons.dm" #include "code\__HELPERS\lists.dm" -#include "code\__HELPERS\logging.dm" #include "code\__HELPERS\maths.dm" #include "code\__HELPERS\matrices.dm" #include "code\__HELPERS\mobs.dm" @@ -384,6 +384,7 @@ #include "code\game\shuttle_engines.dm" #include "code\game\skincmd.dm" #include "code\game\sound.dm" +#include "code\game\world.dm" #include "code\game\area\ai_monitored.dm" #include "code\game\area\areas.dm" #include "code\game\area\Dynamic areas.dm" diff --git a/rust_g.dll b/rust_g.dll new file mode 100644 index 00000000000..80d09ac19ca Binary files /dev/null and b/rust_g.dll differ diff --git a/tgstation.dme b/tgstation.dme new file mode 120000 index 00000000000..abc8cf17220 --- /dev/null +++ b/tgstation.dme @@ -0,0 +1 @@ +paradise.dme \ No newline at end of file