Merge remote-tracking branch 'refs/remotes/ParadiseSS13/master' into wizloadouts

This commit is contained in:
datlo
2020-03-22 12:32:54 +01:00
68 changed files with 600 additions and 149 deletions
@@ -0,0 +1,13 @@
name: 'Merge Conflict Detection'
on:
push:
branches:
- master
jobs:
triage:
runs-on: ubuntu-latest
steps:
- uses: mschilde/auto-label-merge-conflicts@master
with:
CONFLICT_LABEL_NAME: 'Merge Conflict'
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
@@ -1789,7 +1789,6 @@
/area/ruin/unpowered/syndicate_lava_base/cargo)
"ed" = (
/obj/structure/table,
/obj/item/paper_bin,
/obj/item/pen,
/obj/effect/decal/cleanable/dirt,
/obj/effect/decal/cleanable/dirt,
@@ -1803,6 +1802,7 @@
/obj/effect/turf_decal/tile/neutral{
dir = 8
},
/obj/item/paper_bin/syndicate,
/turf/simulated/floor/plasteel/dark,
/area/ruin/unpowered/syndicate_lava_base/cargo)
"ef" = (
@@ -1898,7 +1898,6 @@
"ep" = (
/obj/structure/table/reinforced,
/obj/effect/decal/cleanable/dirt,
/obj/item/paper_bin,
/obj/item/pen,
/obj/machinery/atmospherics/pipe/simple/hidden/supply,
/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers,
@@ -1912,6 +1911,7 @@
/obj/effect/turf_decal/tile/neutral{
dir = 8
},
/obj/item/paper_bin/syndicate,
/turf/simulated/floor/plasteel/dark,
/area/ruin/unpowered/syndicate_lava_base/testlab)
"eq" = (
@@ -6790,8 +6790,8 @@
/area/ruin/unpowered/syndicate_lava_base/telecomms)
"ov" = (
/obj/structure/table/reinforced,
/obj/item/paper_bin,
/obj/item/pen,
/obj/item/paper_bin/syndicate,
/turf/simulated/floor/plasteel/dark,
/area/ruin/unpowered/syndicate_lava_base/telecomms)
"ox" = (
+11 -38
View File
@@ -1619,15 +1619,12 @@
/area/security/range)
"adH" = (
/obj/structure/table/wood,
/obj/item/paper_bin{
pixel_x = -3;
pixel_y = 7
},
/obj/item/pen/multi,
/obj/machinery/light{
dir = 1;
on = 1
},
/obj/item/paper_bin/nanotrasen,
/turf/simulated/floor/plasteel{
icon_state = "dark"
},
@@ -16077,16 +16074,13 @@
/area/lawoffice)
"aAI" = (
/obj/structure/table/reinforced,
/obj/item/paper_bin{
pixel_x = -3;
pixel_y = 7
},
/obj/item/pen,
/obj/machinery/alarm{
dir = 8;
pixel_x = 25;
pixel_y = 0
},
/obj/item/paper_bin/nanotrasen,
/turf/simulated/floor/plasteel{
tag = "icon-cult";
icon_state = "cult";
@@ -16863,11 +16857,8 @@
/area/magistrateoffice)
"aCj" = (
/obj/structure/table/reinforced,
/obj/item/paper_bin{
pixel_x = -3;
pixel_y = 7
},
/obj/item/stamp/magistrate,
/obj/item/paper_bin/nanotrasen,
/turf/simulated/floor/carpet,
/area/magistrateoffice)
"aCk" = (
@@ -21875,11 +21866,8 @@
/area/maintenance/fpmaint2)
"aMO" = (
/obj/structure/table/reinforced,
/obj/item/paper_bin{
pixel_x = -3;
pixel_y = 7
},
/obj/item/pen,
/obj/item/paper_bin/nanotrasen,
/turf/simulated/floor/plasteel{
tag = "icon-cult";
icon_state = "cult";
@@ -27795,16 +27783,13 @@
/obj/item/folder/yellow,
/obj/item/stamp/ce,
/obj/item/book/manual/sop_engineering,
/obj/item/paper_bin{
pixel_x = -3;
pixel_y = 7
},
/obj/item/storage/fancy/cigarettes,
/obj/item/lighter/zippo,
/obj/item/pen/multi,
/obj/item/enginepicker{
layer = 3.1
},
/obj/item/paper_bin/nanotrasen,
/turf/simulated/floor/plasteel{
dir = 8;
icon_state = "neutralfull"
@@ -43355,12 +43340,9 @@
},
/area/hallway/primary/central/west)
"bCG" = (
/obj/item/paper_bin{
pixel_x = -3;
pixel_y = 7
},
/obj/item/pen,
/obj/structure/table/wood,
/obj/item/paper_bin/nanotrasen,
/turf/simulated/floor/carpet,
/area/bridge/meeting_room)
"bCH" = (
@@ -47113,10 +47095,6 @@
/area/shuttle/constructionsite)
"bJN" = (
/obj/structure/table/wood,
/obj/item/paper_bin{
pixel_x = -3;
pixel_y = 10
},
/obj/item/pen/multi/fountain,
/obj/machinery/door_control{
id = "captainofficedoor";
@@ -47129,6 +47107,7 @@
/obj/item/radio/intercom{
pixel_x = -28
},
/obj/item/paper_bin/nanotrasen,
/turf/simulated/floor/wood,
/area/crew_quarters/captain)
"bJO" = (
@@ -50576,15 +50555,12 @@
},
/area/toxins/lab)
"bPE" = (
/obj/item/paper_bin{
pixel_x = 1;
pixel_y = 9
},
/obj/structure/table/glass,
/obj/item/pen/multi,
/obj/item/book/manual/sop_science{
pixel_y = -14
},
/obj/item/paper_bin/nanotrasen,
/turf/simulated/floor/plasteel{
dir = 2;
icon_state = "cafeteria";
@@ -54151,10 +54127,6 @@
/area/hallway/primary/central/se)
"bVy" = (
/obj/structure/table,
/obj/item/paper_bin{
pixel_x = -3;
pixel_y = 7
},
/obj/item/pen/multi,
/obj/item/pen/multi,
/obj/item/megaphone,
@@ -55112,6 +55084,7 @@
/obj/item/book/manual/sop_service,
/obj/item/book/manual/sop_supply,
/obj/item/book/manual/sop_command,
/obj/item/paper_bin/nanotrasen,
/turf/simulated/floor/plasteel,
/area/crew_quarters/heads)
"bXa" = (
@@ -60880,7 +60853,6 @@
/area/medical/cmo)
"cfW" = (
/obj/structure/table/glass,
/obj/item/paper_bin,
/obj/item/pen/multi,
/obj/item/folder/white{
pixel_y = 7
@@ -60890,6 +60862,7 @@
pixel_x = 32;
pixel_y = 0
},
/obj/item/paper_bin/nanotrasen,
/turf/simulated/floor/plasteel{
dir = 4;
icon_state = "darkblue"
@@ -67468,12 +67441,12 @@
/area/blueshield)
"cqS" = (
/obj/structure/table/wood,
/obj/item/paper_bin,
/obj/item/flashlight/lamp/green{
pixel_x = -5;
pixel_y = 12
},
/obj/item/paper/ntrep,
/obj/item/paper_bin/nanotrasen,
/turf/simulated/floor/carpet,
/area/ntrep)
"cqT" = (
-10
View File
@@ -6,16 +6,6 @@
// atmospherics devices.
//--------------------------------------------
#define PIPE_COLOR_GREY "#ffffff" //yes white is grey
#define PIPE_COLOR_RED "#ff0000"
#define PIPE_COLOR_BLUE "#0000ff"
#define PIPE_COLOR_CYAN "#00ffff"
#define PIPE_COLOR_GREEN "#00ff00"
#define PIPE_COLOR_YELLOW "#ffcc00"
#define PIPE_COLOR_PURPLE "#5c1ec0"
GLOBAL_LIST_INIT(pipe_colors, list("grey" = PIPE_COLOR_GREY, "red" = PIPE_COLOR_RED, "blue" = PIPE_COLOR_BLUE, "cyan" = PIPE_COLOR_CYAN, "green" = PIPE_COLOR_GREEN, "yellow" = PIPE_COLOR_YELLOW, "purple" = PIPE_COLOR_PURPLE))
/proc/pipe_color_lookup(var/color)
for(var/C in GLOB.pipe_colors)
if(color == GLOB.pipe_colors[C])
+9
View File
@@ -99,3 +99,12 @@
#define COLOR_ASSEMBLY_LBLUE "#5D99BE"
#define COLOR_ASSEMBLY_BLUE "#38559E"
#define COLOR_ASSEMBLY_PURPLE "#6F6192"
// Pipe colours
#define PIPE_COLOR_GREY "#ffffff" //yes white is grey
#define PIPE_COLOR_RED "#ff0000"
#define PIPE_COLOR_BLUE "#0000ff"
#define PIPE_COLOR_CYAN "#00ffff"
#define PIPE_COLOR_GREEN "#00ff00"
#define PIPE_COLOR_YELLOW "#ffcc00"
#define PIPE_COLOR_PURPLE "#5c1ec0"
+6
View File
@@ -0,0 +1,6 @@
#define ATTACK_LOG "Attack"
#define DEFENSE_LOG "Defense"
#define CONVERSION_LOG "Conversion"
#define SAY_LOG "Say"
#define EMOTE_LOG "Emote"
#define MISC_LOG "Misc"
+61 -27
View File
@@ -274,7 +274,7 @@ Proc for attack log creation, because really why not
This is always put in the attack log.
*/
/proc/add_attack_logs(mob/user, mob/target, what_done, custom_level)
/proc/add_attack_logs(atom/user, target, what_done, custom_level)
if(islist(target)) // Multi-victim adding
var/list/targets = target
for(var/mob/M in targets)
@@ -282,24 +282,33 @@ This is always put in the attack log.
return
var/user_str = key_name_log(user) + COORD(user)
var/target_str = key_name_log(target) + COORD(target)
if(istype(user))
user.create_attack_log("<font color='red'>Attacked [target_str]: [what_done]</font>")
if(istype(target))
target.create_attack_log("<font color='orange'>Attacked by [user_str]: [what_done]</font>")
var/target_str
if(isatom(target))
var/atom/AT = target
target_str = key_name_log(AT) + COORD(AT)
else
target_str = target
var/mob/MU = user
var/mob/MT = target
if(istype(MU))
MU.create_log(ATTACK_LOG, what_done, target, get_turf(user))
MU.create_attack_log("<font color='red'>Attacked [target_str]: [what_done]</font>")
if(istype(MT))
MT.create_log(DEFENSE_LOG, what_done, user, get_turf(MT))
MT.create_attack_log("<font color='orange'>Attacked by [user_str]: [what_done]</font>")
log_attack(user_str, target_str, what_done)
var/loglevel = ATKLOG_MOST
if(!isnull(custom_level))
loglevel = custom_level
else if(istype(target))
if(istype(user) && !user.ckey && !target.ckey) // Attacks between NPCs are only shown to admins with ATKLOG_ALL
loglevel = ATKLOG_ALL
else if(!user.ckey || !target.ckey || (user.ckey == target.ckey)) // Player v NPC combat is de-prioritized. Also no self-harm, nobody cares
loglevel = ATKLOG_ALMOSTALL
else if(istype(MT))
if(istype(MU))
if(!MU.ckey && !MT.ckey) // Attacks between NPCs are only shown to admins with ATKLOG_ALL
loglevel = ATKLOG_ALL
else if(!MU.ckey || !MT.ckey || (MU.ckey == MT.ckey)) // Player v NPC combat is de-prioritized. Also no self-harm, nobody cares
loglevel = ATKLOG_ALMOSTALL
else
var/area/A = get_area(target)
var/area/A = get_area(MT)
if(A && A.hide_attacklogs)
loglevel = ATKLOG_ALMOSTALL
if(isLivingSSD(target)) // Attacks on SSDs are shown to admins with any log level except ATKLOG_NONE. Overrides custom level
@@ -346,24 +355,35 @@ This is always put in the attack log.
if(progress)
qdel(progbar)
/proc/do_after(mob/user, delay, needhand = 1, atom/target = null, progress = 1, datum/callback/extra_checks = null)
/* Use this proc when you want to have code under it execute after a delay, and ensure certain conditions are met during that delay...
* Such as the user not being interrupted via getting stunned or by moving off the tile they're currently on.
*
* Example usage:
*
* if(do_after(user, 50, target = sometarget, extra_checks = list(callback_check1, callback_check2)))
* do_stuff()
*
* This will create progress bar that lasts for 5 seconds. If the user doesn't move or otherwise do something that would cause the checks to fail in those 5 seconds, do_stuff() would execute.
* The Proc returns TRUE upon success (the progress bar reached the end), or FALSE upon failure (the user moved or some other check failed)
*/
/proc/do_after(mob/user, delay, needhand = 1, atom/target = null, progress = 1, list/extra_checks = list(), use_default_checks = TRUE)
if(!user)
return 0
return FALSE
var/atom/Tloc = null
if(target)
Tloc = target.loc
var/atom/Uloc = user.loc
var/drifting = 0
var/drifting = FALSE
if(!user.Process_Spacemove(0) && user.inertia_dir)
drifting = 1
drifting = TRUE
var/holding = user.get_active_hand()
var/holdingnull = 1 //User's hand started out empty, check for an empty hand
var/holdingnull = TRUE //User's hand started out empty, check for an empty hand
if(holding)
holdingnull = 0 //Users hand started holding something, check to see if it's still holding that
holdingnull = FALSE //Users hand started holding something, check to see if it's still holding that
var/datum/progressbar/progbar
if(progress)
@@ -371,22 +391,29 @@ This is always put in the attack log.
var/endtime = world.time + delay
var/starttime = world.time
. = 1
. = TRUE
// By default, checks for weakness and stunned get added to the extra_checks list.
// Setting `use_default_checks` to FALSE means that you don't want the do_after to check for these statuses, or that you will be supplying your own checks.
if(use_default_checks)
extra_checks += CALLBACK(user, /mob.proc/IsWeakened)
extra_checks += CALLBACK(user, /mob.proc/IsStunned)
while(world.time < endtime)
sleep(1)
if(progress)
progbar.update(world.time - starttime)
if(drifting && !user.inertia_dir)
drifting = 0
drifting = FALSE
Uloc = user.loc
if(!user || user.stat || user.IsWeakened() || user.stunned || (!drifting && user.loc != Uloc)|| (extra_checks && !extra_checks.Invoke()))
. = 0
if(!user || user.stat || (!drifting && user.loc != Uloc) || check_for_true_callbacks(extra_checks))
. = FALSE
break
if(Tloc && (!target || Tloc != target.loc))
. = 0
. = FALSE
break
if(needhand)
@@ -394,14 +421,21 @@ This is always put in the attack log.
//i.e the hand is used to pull some item/tool out of the construction
if(!holdingnull)
if(!holding)
. = 0
. = FALSE
break
if(user.get_active_hand() != holding)
. = 0
. = FALSE
break
if(progress)
qdel(progbar)
// Upon any of the callbacks in the list returning TRUE, the proc will return TRUE.
/proc/check_for_true_callbacks(list/extra_checks)
for(var/datum/callback/CB in extra_checks)
if(CB.Invoke())
return TRUE
return FALSE
#define DOAFTERONCE_MAGIC "Magic~~"
GLOBAL_LIST_INIT(do_after_once_tracker, list())
/proc/do_after_once(mob/user, delay, needhand = 1, atom/target = null, progress = 1, attempt_cancel_message = "Attempt cancelled.")
@@ -414,7 +448,7 @@ GLOBAL_LIST_INIT(do_after_once_tracker, list())
to_chat(user, "<span class='warning'>[attempt_cancel_message]</span>")
return FALSE
GLOB.do_after_once_tracker[cache_key] = TRUE
. = do_after(user, delay, needhand, target, progress, extra_checks = CALLBACK(GLOBAL_PROC, .proc/do_after_once_checks, cache_key))
. = do_after(user, delay, needhand, target, progress, extra_checks = list(CALLBACK(GLOBAL_PROC, .proc/do_after_once_checks, cache_key)))
GLOB.do_after_once_tracker[cache_key] = FALSE
/proc/do_after_once_checks(cache_key)
+15 -1
View File
@@ -50,10 +50,24 @@
return "[date_portion]T[time_portion]"
/proc/gameTimestamp(format = "hh:mm:ss", wtime=null)
if(!wtime)
if(wtime == null)
wtime = world.time
return time2text(wtime - GLOB.timezoneOffset, format)
// max hh:mm:ss supported
/proc/timeStampToNum(timestamp)
var/list/splits = text2numlist(timestamp, ":")
. = 0
var/split_len = length(splits)
for(var/i = 1 to length(splits))
switch(split_len - i)
if(2)
. += splits[i] HOURS
if(1)
. += splits[i] MINUTES
if(0)
. += splits[i] SECONDS
/* This is used for displaying the "station time" equivelent of a world.time value
Calling it with no args will give you the current time, but you can specify a world.time-based value as an argument
- You can use this, for example, to do "This will expire at [station_time_at(world.time + 500)]" to display a "station time" expiration date
+10 -3
View File
@@ -1895,8 +1895,15 @@ GLOBAL_DATUM_INIT(dview_mob, /mob/dview, new)
#undef DELTA_CALC
// This proc gets a list of all "points of interest" (poi's) that can be used by admins to track valuable mobs or atoms (such as the nuke disk).
/proc/getpois(mobs_only=0,skip_mindless=0)
/*
* This proc gets a list of all "points of interest" (poi's) that can be used by admins to track valuable mobs or atoms (such as the nuke disk).
* @param mobs_only if set to TRUE it won't include locations to the returned list
* @param skip_mindless if set to TRUE it will skip mindless mobs
* @param force_include_bots if set to TRUE it will include bots even if skip_mindless is set to TRUE
* @param force_include_cameras if set to TRUE it will include camera eyes even if skip_mindless is set to TRUE
* @return returns a list with the found points of interest
*/
/proc/getpois(mobs_only = FALSE, skip_mindless = FALSE, force_include_bots = FALSE, force_include_cameras = FALSE)
var/list/mobs = sortmobs()
var/list/names = list()
var/list/pois = list()
@@ -1904,7 +1911,7 @@ GLOBAL_DATUM_INIT(dview_mob, /mob/dview, new)
for(var/mob/M in mobs)
if(skip_mindless && (!M.mind && !M.ckey))
if(!isbot(M) && !istype(M, /mob/camera/))
if(!(force_include_bots && isbot(M)) && !(force_include_cameras && istype(M, /mob/camera)))
continue
if(M.client && M.client.holder && M.client.holder.fakekey) //stealthmins
continue
+1
View File
@@ -100,3 +100,4 @@ GLOBAL_DATUM_INIT(dbcon, /DBConnection, new) //Feedback database (New database)
GLOBAL_PROTECT(dbcon)
GLOBAL_LIST_EMPTY(ability_verbs) // Create-level abilities
GLOBAL_LIST_INIT(pipe_colors, list("grey" = PIPE_COLOR_GREY, "red" = PIPE_COLOR_RED, "blue" = PIPE_COLOR_BLUE, "cyan" = PIPE_COLOR_CYAN, "green" = PIPE_COLOR_GREEN, "yellow" = PIPE_COLOR_YELLOW, "purple" = PIPE_COLOR_PURPLE))
+1 -1
View File
@@ -31,7 +31,7 @@
/datum/proc/vv_get_var(var_name)
switch(var_name)
if("attack_log", "debug_log")
if("attack_log_old", "debug_log")
return debug_variable(var_name, vars[var_name], 0, src, sanitize = FALSE)
if("vars")
return debug_variable(var_name, list(), 0, src)
+37
View File
@@ -0,0 +1,37 @@
/datum/log_record
var/log_type // Type of log
var/raw_time // When did this happen?
var/what // What happened
var/who // Who did it
var/target // Who/what was targeted (can be a string)
var/turf/where // Where did it happen
/datum/log_record/New(_log_type, _who, _what, _target, _where, _raw_time)
log_type = _log_type
who = get_subject_text(_who)
what = _what
target = get_subject_text(_target)
if(!_where)
_where = get_turf(_who)
where = _where
if(!_raw_time)
_raw_time = world.time
raw_time = _raw_time
/datum/log_record/proc/get_subject_text(subject)
if(ismob(subject) || isclient(subject) || istype(subject, /datum/mind))
return key_name_admin(subject)
if(isatom(subject))
var/atom/A = subject
return A.name
if(istype(subject, /datum))
var/datum/D = subject
return D.type
return subject
/proc/compare_log_record(datum/log_record/A, datum/log_record/B)
var/time_diff = A.raw_time - B.raw_time
if(!time_diff) // Same time
return cmp_text_asc(A.log_type, B.log_type)
return time_diff
+232
View File
@@ -0,0 +1,232 @@
#define ALL_LOGS list(ATTACK_LOG, DEFENSE_LOG, CONVERSION_LOG, SAY_LOG, EMOTE_LOG, MISC_LOG)
/datum/log_viewer
var/time_from = 0
var/time_to = 4 HOURS // 4 Hours should be enough. INFINITY would screw the UI up
var/list/selected_mobs = list() // The mobs in question
var/list/selected_log_types = list() // The log types being searched for
var/list/log_records = list() // Found and sorted records
/datum/log_viewer/proc/clear_all()
selected_mobs.Cut()
selected_log_types.Cut()
time_from = initial(time_from)
time_to = initial(time_to)
log_records.Cut()
return
/datum/log_viewer/proc/search()
log_records.Cut() // Empty the old results
var/list/invalid_mobs = list()
for(var/i in selected_mobs)
var/mob/M = i
if(!M || QDELETED(M))
invalid_mobs |= M
continue
for(var/log_type in selected_log_types)
var/list/logs = M.logs[log_type]
var/len_logs = length(logs)
if(len_logs)
var/start_index = get_earliest_log_index(logs)
if(!start_index) // No log found that matches the starting time criteria
continue
var/end_index = get_latest_log_index(logs)
if(!end_index) // No log found that matches the end time criteria
continue
log_records.Add(logs.Copy(start_index, end_index + 1))
if(invalid_mobs.len)
to_chat(usr, "<span class='warning'>The search criteria contained invalid mobs. They have been removed from the criteria.</span>")
for(var/i in invalid_mobs)
selected_mobs -= i // Cleanup
log_records = sortTim(log_records, /proc/compare_log_record)
/** Binary search like implementation to find the earliest log
* Returns the index of the earliest log using the time_from value for the given list of logs.
* It will return 0 if no log after time_from is found
*/
/datum/log_viewer/proc/get_earliest_log_index(list/logs)
if(!time_from)
return 1
var/start = 1
var/end = length(logs)
var/mid
do
mid = round_down((end + start) / 2)
var/datum/log_record/L = logs[mid]
if(L.raw_time >= time_from)
end = mid
else
start = mid
while(end - start > 1)
var/datum/log_record/L = logs[end]
if(L.raw_time >= time_from) // Check if there is atleast one valid log
return end
return 0
/** Binary search like implementation to find the latest log
* Returns the index of the latest log using the time_to value (1 second is added to prevent rounding weirdness) for the given list of logs.
* It will return 0 if no log before time_to + 10 is found
*/
/datum/log_viewer/proc/get_latest_log_index(list/logs)
if(world.time < time_to)
return length(logs)
var/end = length(logs)
var/start = 1
var/mid
var/max_time = time_to + 10
do
mid = round((end + start) / 2 + 0.5)
var/datum/log_record/L = logs[mid]
if(L.raw_time >= max_time)
end = mid
else
start = mid
while(end - start > 1)
var/datum/log_record/L = logs[start]
if(L.raw_time < max_time) // Check if there is atleast one valid log
return start
return 0
/datum/log_viewer/proc/add_mob(mob/user, mob/M)
if(!M || !user)
return
selected_mobs |= M
show_ui(user)
/datum/log_viewer/proc/show_ui(mob/user)
var/all_log_types = ALL_LOGS
var/trStyleTop = "border-top:2px solid; border-bottom:2px solid; padding-top: 5px; padding-bottom: 5px;"
var/trStyle = "border-top:1px solid; border-bottom:1px solid; padding-top: 5px; padding-bottom: 5px;"
var/dat
dat += "<head><style>.adminticket{border:2px solid} td{border:1px solid grey;} th{border:1px solid grey;} span{float:left;width:150px;}</style></head>"
dat += "<div style='height:15vh'>"
dat += "<span>Time Search Range:</span> <a href='?src=[UID()];start_time=1'>[gameTimestamp(wtime = time_from)]</a>"
dat += " To: <a href='?src=[UID()];end_time=1'>[gameTimestamp(wtime = time_to)]</a>"
dat += "<BR>"
dat += "<span>Mobs being used:</span>"
for(var/i in selected_mobs)
var/mob/M = i
dat += "<a href='?src=[UID()];remove_mob=\ref[M]'>[M.name]</a>"
dat += "<a href='?src=[UID()];add_mob=1'>Add Mob</a>"
dat += "<a href='?src=[UID()];clear_mobs=1'>Clear All Mobs</a>"
dat += "<BR>"
dat += "<span>Log Types:</span>"
for(var/i in all_log_types)
var/log_type = i
var/enabled = (log_type in selected_log_types)
var/text
var/style
if(enabled)
text = "<b>[log_type]</b>"
style = "background: [get_logtype_color(i)]"
else
text = log_type
dat += "<a href='?src=[UID()];toggle_log_type=[log_type]' style='[style]'>[text]</a>"
dat += "<BR>"
dat += "<a href='?src=[UID()];clear_all=1'>Clear All Settings</a>"
dat += "<a href='?src=[UID()];search=1'>Search</a>"
dat += "</div>"
// Search results
var/tdStyleTime = "width:80px; text-align:center;"
var/tdStyleType = "width:80px; text-align:center;"
var/tdStyleWho = "width:300px; text-align:center;"
var/tdStyleWhere = "width:150px; text-align:center;"
dat += "<div style='overflow-y: auto; max-height:76vh;'>"
dat += "<table style='width:100%; border: 1px solid;'>"
dat += "<tr style='[trStyleTop]'><th style='[tdStyleTime]'>When</th><th style='[tdStyleType]'>Type</th><th style='[tdStyleWho]'>Who</th><th>What</th><th>Target</th><th style='[tdStyleWhere]'>Where</th></tr>"
for(var/i in log_records)
var/datum/log_record/L = i
var/time = gameTimestamp(wtime = L.raw_time - 9.99) // The time rounds up for some reason. Will result in weird filtering results
dat +="<tr style='[trStyle]'><td style='[tdStyleTime]'>[time]</td><td style='[tdStyleType]background: [get_logtype_color(L.log_type)]'>[L.log_type]</td>\
<td style='[tdStyleWho]'>[L.who]</td><td style='background: [get_logtype_color(L.log_type)];'>[L.what]</td>\
<td style='[tdStyleWho]'>[L.target]</td><td style='[tdStyleWhere]'>[ADMIN_COORDJMP(L.where)]</td></tr>"
dat += "</table>"
dat += "</div>"
var/datum/browser/popup = new(user, "Log viewer", "Log viewer", 1400, 600)
popup.set_content(dat)
popup.open()
/datum/log_viewer/Topic(href, href_list)
if(href_list["start_time"])
var/input = input(usr, "hh:mm:ss", "Start time", "00:00:00") as text|null
if(!input)
return
var/res = timeStampToNum(input)
if(res < 0)
to_chat(usr, "<span class='warning'>'[input]' is an invalid input value.</span>")
return
time_from = res
show_ui(usr)
return
if(href_list["end_time"])
var/input = input(usr, "hh:mm:ss", "End time", "04:00:00") as text|null
if(!input)
return
var/res = timeStampToNum(input)
if(res < 0)
to_chat(usr, "<span class='warning'>'[input]' is an invalid input value.</span>")
return
time_to = res
show_ui(usr)
return
if(href_list["search"])
search(usr)
show_ui(usr)
return
if(href_list["clear_all"])
clear_all(usr)
show_ui(usr)
return
if(href_list["clear_mobs"])
selected_mobs.Cut()
show_ui(usr)
return
if(href_list["add_mob"])
var/list/mobs = getpois(TRUE, TRUE)
var/datum/async_input/A = input_autocomplete_async(usr, "Please, select a mob: ", mobs)
A.on_close(CALLBACK(src, .proc/add_mob, usr))
return
if(href_list["remove_mob"])
var/mob/M = locate(href_list["remove_mob"])
if(M)
selected_mobs -= M
show_ui(usr)
return
if(href_list["toggle_log_type"])
var/log_type = href_list["toggle_log_type"]
if(log_type in selected_log_types)
selected_log_types -= log_type
else
selected_log_types += log_type
show_ui(usr)
return
/datum/log_viewer/proc/get_logtype_color(log_type)
switch(log_type)
if(ATTACK_LOG)
return "darkred"
if(DEFENSE_LOG)
return "chocolate"
if(CONVERSION_LOG)
return "indigo"
if(SAY_LOG)
return "teal"
if(EMOTE_LOG)
return "deepskyblue"
if(MISC_LOG)
return "gray"
return "slategray"
+8
View File
@@ -105,6 +105,14 @@
current.mind = null
leave_all_huds() //leave all the huds in the old body, so it won't get huds if somebody else enters it
for(var/log_type in current.logs) // Copy the old logs
var/list/logs = current.logs[log_type]
if(new_character.logs[log_type])
new_character.logs[log_type] += logs.Copy() // Append the old ones
new_character.logs[log_type] = sortTim(new_character.logs[log_type], /proc/compare_log_record) // Sort them on time
else
new_character.logs[log_type] = logs.Copy() // Just copy them
SSnanoui.user_transferred(current, new_character)
if(new_character.mind) //remove any mind currently in our new body's mind variable
+1 -1
View File
@@ -241,7 +241,7 @@ GLOBAL_LIST_INIT(spells, typesof(/obj/effect/proc_holder/spell))
before_cast(targets)
invocation()
if(user && user.ckey)
user.create_attack_log("<font color='red'>[key_name(user)] cast the spell [name].</font>")
add_attack_logs(user, null, "cast the spell [name]")
spawn(0)
if(charge_type == "recharge" && recharge)
start_recharge()
+2 -1
View File
@@ -141,6 +141,7 @@
else
user.mind.AddSpell(S)
to_chat(user, "<span class='notice'>You flip through the pages. Your understanding of the boundaries of reality increases. You can cast [spellname]!</span>")
user.create_log(MISC_LOG, "learned the spell [spellname] ([S])")
user.create_attack_log("<font color='orange'>[key_name(user)] learned the spell [spellname] ([S]).</font>")
onlearned(user)
@@ -164,4 +165,4 @@
/obj/item/spellbook/oneuse/mime/greaterwall
spell = /obj/effect/proc_holder/spell/targeted/forcewall/mime
spellname = "Invisible Greater Wall"
desc = "It contains illustrations of the great walls of human history."
desc = "It contains illustrations of the great walls of human history."
@@ -12,7 +12,7 @@ GLOBAL_LIST_EMPTY(sting_paths)
return
var/datum/changeling/changeling = usr.mind.changeling
if(!GLOB.sting_paths)
if(!GLOB.sting_paths || !GLOB.sting_paths.len)
GLOB.sting_paths = init_subtypes(/datum/action/changeling)
var/dat = create_menu(changeling)
+1
View File
@@ -189,6 +189,7 @@ GLOBAL_LIST_EMPTY(all_cults)
C.Grant(cult_mind.current)
SEND_SOUND(cult_mind.current, 'sound/ambience/antag/bloodcult.ogg')
cult_mind.current.create_attack_log("<span class='danger'>Has been converted to the cult!</span>")
cult_mind.current.create_log(CONVERSION_LOG, "converted to the cult")
if(jobban_isbanned(cult_mind.current, ROLE_CULTIST) || jobban_isbanned(cult_mind.current, ROLE_SYNDICATE))
replace_jobbanned_player(cult_mind.current, ROLE_CULTIST)
update_cult_icons_added(cult_mind)
@@ -267,6 +267,7 @@
SSticker.mode.abductors -= abductor_mind
abductor_mind.special_role = null
abductor_mind.current.create_attack_log("<span class='danger'>No longer abductor</span>")
abductor_mind.current.create_log(CONVERSION_LOG, "No longer abductor")
if(issilicon(abductor_mind.current))
to_chat(abductor_mind.current, "<span class='userdanger'>You have been turned into a robot! You are no longer an abductor.</span>")
else
@@ -281,4 +282,4 @@
/datum/game_mode/proc/update_abductor_icons_removed(datum/mind/alien_mind)
var/datum/atom_hud/antag/hud = GLOB.huds[ANTAG_HUD_ABDUCTOR]
hud.leave_hud(alien_mind.current)
set_antag_hud(alien_mind.current, null)
set_antag_hud(alien_mind.current, null)
+1
View File
@@ -68,6 +68,7 @@ proc/issyndicate(mob/living/M as mob)
for(var/datum/objective/nuclear/O in operative_mind.objectives)
operative_mind.objectives -= O
operative_mind.current.create_attack_log("<span class='danger'>No longer nuclear operative</span>")
operative_mind.current.create_log(CONVERSION_LOG, "No longer nuclear operative")
if(issilicon(operative_mind.current))
to_chat(operative_mind.current, "<span class='userdanger'>You have been turned into a robot! You are no longer a Syndicate operative.</span>")
else
+2 -1
View File
@@ -244,6 +244,7 @@
rev_mind.current.Stun(5)
to_chat(rev_mind.current, "<span class='danger'><FONT size = 3> You are now a revolutionary! Help your cause. Do not harm your fellow freedom fighters. You can identify your comrades by the red \"R\" icons, and your leaders by the blue \"R\" icons. Help them kill the heads to win the revolution!</FONT></span>")
rev_mind.current.create_attack_log("<font color='red'>Has been converted to the revolution!</font>")
rev_mind.current.create_log(CONVERSION_LOG, "converted to the revolution")
rev_mind.special_role = SPECIAL_ROLE_REV
update_rev_icons_added(rev_mind)
if(jobban_isbanned(rev_mind.current, ROLE_REV) || jobban_isbanned(rev_mind.current, ROLE_SYNDICATE))
@@ -262,7 +263,7 @@
revolutionaries -= rev_mind
rev_mind.special_role = null
rev_mind.current.create_attack_log("<font color='red'>Has renounced the revolution!</font>")
rev_mind.current.create_log(CONVERSION_LOG, "renounced the revolution")
if(beingborged)
to_chat(rev_mind.current, "<span class='danger'><FONT size = 3>The frame's firmware detects and deletes your neural reprogramming! You remember nothing[remove_head ? "." : " but the name of the one who flashed you."]</FONT></span>")
message_admins("[key_name_admin(rev_mind.current)] [ADMIN_QUE(rev_mind.current,"?")] ([ADMIN_FLW(rev_mind.current,"FLW")]) has been borged while being a [remove_head ? "leader" : " member"] of the revolution.")
@@ -158,6 +158,7 @@ Made by Xhuis
new_thrall_mind.special_role = SPECIAL_ROLE_SHADOWLING_THRALL
update_shadow_icons_added(new_thrall_mind)
new_thrall_mind.current.create_attack_log("<span class='danger'>Became a thrall</span>")
new_thrall_mind.current.create_log(CONVERSION_LOG, "Became a thrall")
new_thrall_mind.current.add_language("Shadowling Hivemind")
new_thrall_mind.AddSpell(new /obj/effect/proc_holder/spell/targeted/lesser_shadow_walk(null))
new_thrall_mind.AddSpell(new /obj/effect/proc_holder/spell/targeted/shadow_vision/thrall(null))
@@ -179,6 +180,7 @@ Made by Xhuis
return 0 //If there is no mind, the mind isn't a thrall, or the mind's mob isn't alive, return
shadowling_thralls.Remove(thrall_mind)
thrall_mind.current.create_attack_log("<span class='danger'>Dethralled</span>")
thrall_mind.current.create_log(CONVERSION_LOG, "Dethralled")
thrall_mind.special_role = null
update_shadow_icons_removed(thrall_mind)
for(var/obj/effect/proc_holder/spell/S in thrall_mind.spell_list)
@@ -236,6 +238,7 @@ Made by Xhuis
update_shadow_icons_removed(ling_mind)
shadows.Remove(ling_mind)
ling_mind.current.create_attack_log("<span class='danger'>Deshadowlinged</span>")
ling_mind.current.create_log(CONVERSION_LOG, "Deshadowlinged")
ling_mind.special_role = null
for(var/obj/effect/proc_holder/spell/S in ling_mind.spell_list)
ling_mind.RemoveSpell(S)
+1
View File
@@ -348,6 +348,7 @@ You are weak to holy things and starlight. Don't go into space and avoid the Cha
SSticker.mode.vampires -= vampire_mind
vampire_mind.special_role = null
vampire_mind.current.create_attack_log("<span class='danger'>De-vampired</span>")
vampire_mind.current.create_log(CONVERSION_LOG, "De-vampired")
if(vampire_mind.vampire)
vampire_mind.vampire.remove_vampire_powers()
QDEL_NULL(vampire_mind.vampire)
+3 -1
View File
@@ -109,6 +109,7 @@ GLOBAL_VAR_INIT(summon_magic_triggered, FALSE)
H.mind.add_antag_datum(/datum/antagonist/survivalist/guns)
H.create_attack_log("<font color='red'>was made into a survivalist, and trusts no one!</font>")
H.create_log(CONVERSION_LOG, "was made into a survivalist")
var/gun_type = pick(GLOB.summoned_guns)
var/obj/item/gun/G = new gun_type(get_turf(H))
@@ -130,6 +131,7 @@ GLOBAL_VAR_INIT(summon_magic_triggered, FALSE)
H.mind.add_antag_datum(/datum/antagonist/survivalist/magic)
H.create_attack_log("<font color='red'>was made into a survivalist, and trusts no one!</font>")
H.create_log(CONVERSION_LOG, "was made into a survivalist")
var/magic_type = pick(GLOB.summoned_magic)
var/lucky = FALSE
@@ -166,4 +168,4 @@ GLOBAL_VAR_INIT(summon_magic_triggered, FALSE)
if(summon_type == SUMMON_MAGIC)
give_magic(H)
else
give_guns(H)
give_guns(H)
+1 -4
View File
@@ -69,9 +69,6 @@
to_chat(user, "<span class='cultlarge'>\"Come now, do not capture your fellow's soul.\"</span>")
return ..()
M.create_attack_log("<font color='orange'>Has had their soul captured with [src.name] by [key_name(user)]</font>")
user.create_attack_log("<font color='red'>Used the [src.name] to capture the soul of [key_name(M)]</font>")
if(optional)
if(!M.ckey)
to_chat(user, "<span class='warning'>They have no soul!</span>")
@@ -353,7 +350,7 @@
/obj/item/soulstone/proc/get_shade_type()
return /mob/living/simple_animal/shade/cult
/obj/item/soulstone/anybody/get_shade_type()
return /mob/living/simple_animal/shade
+1
View File
@@ -891,6 +891,7 @@
else
user.mind.AddSpell(S)
to_chat(user, "<span class='notice'>you rapidly read through the arcane book. Suddenly you realize you understand [spellname]!</span>")
user.create_log(MISC_LOG, "learned the spell [spellname] ([S])")
user.create_attack_log("<font color='orange'>[key_name(user)] learned the spell [spellname] ([S]).</font>")
onlearned(user)
+1
View File
@@ -59,6 +59,7 @@
SSticker.mode.wizards -= wizard_mind
wizard_mind.special_role = null
wizard_mind.current.create_attack_log("<span class='danger'>De-wizarded</span>")
wizard_mind.current.create_log(CONVERSION_LOG, "De-wizarded")
wizard_mind.current.spellremove(wizard_mind.current)
wizard_mind.current.faction = list("Station")
if(issilicon(wizard_mind.current))
+13 -5
View File
@@ -425,6 +425,7 @@
var/AN = ""
var/open = ""
var/infected = ""
var/dead = ""
var/robot = ""
var/imp = ""
var/bled = ""
@@ -439,6 +440,8 @@
splint = "Splinted:"
if(e.status & ORGAN_BROKEN)
AN = "[e.broken_description]:"
if(e.status & ORGAN_DEAD)
dead = "DEAD:"
if(e.is_robotic())
robot = "Robotic:"
if(e.open)
@@ -454,9 +457,9 @@
infected = "Acute Infection:"
if(INFECTION_LEVEL_TWO + 200 to INFECTION_LEVEL_TWO + 300)
infected = "Acute Infection+:"
if(INFECTION_LEVEL_TWO + 300 to INFECTION_LEVEL_TWO + 400)
if(INFECTION_LEVEL_TWO + 300 to INFECTION_LEVEL_TWO + 399)
infected = "Acute Infection++:"
if(INFECTION_LEVEL_THREE to INFINITY)
if(INFECTION_LEVEL_TWO + 400 to INFINITY)
infected = "Septic:"
var/unknown_body = 0
@@ -467,11 +470,14 @@
imp += "Unknown body present:"
if(!AN && !open && !infected & !imp)
AN = "None:"
dat += "<td>[e.name]</td><td>[e.burn_dam]</td><td>[e.brute_dam]</td><td>[robot][bled][AN][splint][open][infected][imp][internal_bleeding][lung_ruptured]</td>"
dat += "<td>[e.name]</td><td>[e.burn_dam]</td><td>[e.brute_dam]</td><td>[robot][bled][AN][splint][open][infected][imp][internal_bleeding][lung_ruptured][dead]</td>"
dat += "</tr>"
for(var/obj/item/organ/internal/i in occupant.internal_organs)
var/mech = i.desc
var/infection = "None"
var/dead = ""
if(i.status & ORGAN_DEAD)
dead = "DEAD:"
switch(i.germ_level)
if(1 to INFECTION_LEVEL_ONE + 200)
infection = "Mild Infection:"
@@ -483,11 +489,13 @@
infection = "Acute Infection:"
if(INFECTION_LEVEL_TWO + 200 to INFECTION_LEVEL_TWO + 300)
infection = "Acute Infection+:"
if(INFECTION_LEVEL_TWO + 300 to INFINITY)
if(INFECTION_LEVEL_TWO + 300 to INFECTION_LEVEL_TWO + 399)
infection = "Acute Infection++:"
if(INFECTION_LEVEL_TWO + 400 to INFINITY)
infection = "Septic:"
dat += "<tr>"
dat += "<td>[i.name]</td><td>N/A</td><td>[i.damage]</td><td>[infection]:[mech]</td><td></td>"
dat += "<td>[i.name]</td><td>N/A</td><td>[i.damage]</td><td>[infection]:[mech][dead]</td><td></td>"
dat += "</tr>"
dat += "</table>"
if(occupant.disabilities & BLIND)
+15 -13
View File
@@ -358,35 +358,37 @@
return
if(scan_brain && !can_brainscan())
return
if((isnull(subject)) || (!(ishuman(subject))) || (!subject.dna) || (NO_SCAN in subject.dna.species.species_traits))
scantemp = "<span class=\"bad\">Error: Unable to locate valid genetic data.</span>"
SSnanoui.update_uis(src)
return
if(isnull(subject) || (!(ishuman(subject))) || (!subject.dna))
if(isalien(subject))
scantemp = "<span class=\"bad\">Error: Xenomorphs are not scannable.</span>"
SSnanoui.update_uis(src)
return
// can add more conditions for specific non-human messages here
else
scantemp = "<span class=\"bad\">Error: Subject species is not scannable.</span>"
SSnanoui.update_uis(src)
return
if(subject.get_int_organ(/obj/item/organ/internal/brain))
var/obj/item/organ/internal/brain/Brn = subject.get_int_organ(/obj/item/organ/internal/brain)
if(istype(Brn))
if(NO_SCAN in Brn.dna.species.species_traits)
scantemp = "<span class=\"bad\">Error: Subject's brain is incompatible.</span>"
scantemp = "<span class=\"bad\">Error: [subject.dna.species.name_plural] are not scannable.</span>"
SSnanoui.update_uis(src)
return
if(!subject.get_int_organ(/obj/item/organ/internal/brain))
scantemp = "<span class=\"bad\">Error: No signs of intelligence detected.</span>"
scantemp = "<span class=\"bad\">Error: No brain detected in subject.</span>"
SSnanoui.update_uis(src)
return
if(subject.suiciding)
scantemp = "<span class=\"bad\">Error: Subject's brain is not responding to scanning stimuli.</span>"
scantemp = "<span class=\"bad\">Error: Subject has committed suicide and is not scannable.</span>"
SSnanoui.update_uis(src)
return
if((!subject.ckey) || (!subject.client))
scantemp = "<span class=\"bad\">Error: Mental interface failure.</span>"
scantemp = "<span class=\"bad\">Error: Subject's brain is not responding. Further attempts after a short delay may succeed.</span>"
SSnanoui.update_uis(src)
return
if((NOCLONE in subject.mutations) && src.scanner.scan_level < 2)
scantemp = "<span class=\"bad\">Error: Mental interface failure.</span>"
SSnanoui.update_uis(src)
return
if(scan_brain && !subject.get_int_organ(/obj/item/organ/internal/brain))
scantemp = "<span class=\"bad\">Error: No brain found.</span>"
scantemp = "<span class=\"bad\">Error: Subject has incompatible genetic mutations.</span>"
SSnanoui.update_uis(src)
return
if(!isnull(find_record(subject.ckey)))
+5 -2
View File
@@ -276,6 +276,7 @@ About the new airlock wires panel:
if(usr)
shockedby += text("\[[time_stamp()]\] - [usr](ckey:[usr.ckey])")
usr.create_attack_log("<font color='red'>Electrified the [name] at [x] [y] [z]</font>")
add_attack_logs(usr, src, "Electrified")
else
shockedby += text("\[[time_stamp()]\] - EMP)")
message = "The door is now electrified [duration == -1 ? "permanently" : "for [duration] second\s"]."
@@ -763,6 +764,7 @@ About the new airlock wires panel:
else if(activate) //electrify door for 30 seconds
shockedby += text("\[[time_stamp()]\][usr](ckey:[usr.ckey])")
usr.create_attack_log("<font color='red'>Electrified the [name] at [x] [y] [z]</font>")
add_attack_logs(usr, src, "Electrified")
to_chat(usr, "The door is now electrified for thirty seconds.")
electrify(30)
if("electrify_permanently")
@@ -774,6 +776,7 @@ About the new airlock wires panel:
else if(activate)
shockedby += text("\[[time_stamp()]\][usr](ckey:[usr.ckey])")
usr.create_attack_log("<font color='red'>Electrified the [name] at [x] [y] [z]</font>")
add_attack_logs(usr, src, "Electrified")
to_chat(usr, "The door is now electrified.")
electrify(-1)
if("open")
@@ -1000,7 +1003,7 @@ About the new airlock wires panel:
"<span class='notice'>You begin [welded ? "unwelding":"welding"] the airlock...</span>", \
"<span class='italics'>You hear welding.</span>")
if(I.use_tool(src, user, 40, volume = I.tool_volume, extra_checks = CALLBACK(src, .proc/weld_checks, I, user)))
if(I.use_tool(src, user, 40, volume = I.tool_volume, extra_checks = list(CALLBACK(src, .proc/weld_checks, I, user))))
if(!density && !welded)
return
welded = !welded
@@ -1011,7 +1014,7 @@ About the new airlock wires panel:
user.visible_message("[user] is welding the airlock.", \
"<span class='notice'>You begin repairing the airlock...</span>", \
"<span class='italics'>You hear welding.</span>")
if(I.use_tool(src, user, 40, volume = I.tool_volume, extra_checks = CALLBACK(src, .proc/weld_checks, I, user)))
if(I.use_tool(src, user, 40, volume = I.tool_volume, extra_checks = list(CALLBACK(src, .proc/weld_checks, I, user))))
obj_integrity = max_integrity
stat &= ~BROKEN
user.visible_message("[user.name] has repaired [src].", \
+1
View File
@@ -559,6 +559,7 @@
animal_damage = user.obj_damage
animal_damage = min(animal_damage, 20*user.environment_smash)
user.create_attack_log("<font color='red'>attacked [name]</font>")
add_attack_logs(user, src, "Attacked")
attack_generic(user, animal_damage, user.melee_damage_type, "melee", play_soundeffect)
return TRUE
@@ -138,6 +138,7 @@
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")
add_attack_logs(user, C, "EMPd with [src]")
else
outmsg = "<span class='info'>You missed the lens of [C] with [src].</span>"
@@ -16,11 +16,11 @@
var/datum/callback/tool_check = CALLBACK(src, .proc/tool_check_callback, user, target, amount, extra_checks)
if(ismob(target))
if(!do_mob(user, target, delay, extra_checks=tool_check))
if(!do_mob(user, target, delay, extra_checks = list(tool_check)))
return
else
if(!do_after(user, delay, target=target, extra_checks=tool_check))
if(!do_after(user, delay, target=target, extra_checks = list(tool_check)))
return
else
// Invoke the extra checks once, just in case.
+5 -5
View File
@@ -254,7 +254,7 @@ GLOBAL_LIST_INIT(wcCommon, pick(list("#379963", "#0d8395", "#58b5c3", "#49e46e",
if(!can_be_reached(user))
return
to_chat(user, "<span class='notice'>You begin to lever the window [state == WINDOW_OUT_OF_FRAME ? "into":"out of"] the frame...</span>")
if(!I.use_tool(src, user, decon_speed, volume = I.tool_volume, extra_checks = CALLBACK(src, .proc/check_state_and_anchored, state, anchored)))
if(!I.use_tool(src, user, decon_speed, volume = I.tool_volume, extra_checks = list(CALLBACK(src, .proc/check_state_and_anchored, state, anchored))))
return
state = (state == WINDOW_OUT_OF_FRAME ? WINDOW_IN_FRAME : WINDOW_OUT_OF_FRAME)
to_chat(user, "<span class='notice'>You pry the window [state == WINDOW_IN_FRAME ? "into":"out of"] the frame.</span>")
@@ -268,20 +268,20 @@ GLOBAL_LIST_INIT(wcCommon, pick(list("#379963", "#0d8395", "#58b5c3", "#49e46e",
if(reinf)
if(state == WINDOW_SCREWED_TO_FRAME || state == WINDOW_IN_FRAME)
to_chat(user, "<span class='notice'>You begin to [state == WINDOW_SCREWED_TO_FRAME ? "unscrew the window from":"screw the window to"] the frame...</span>")
if(!I.use_tool(src, user, decon_speed, volume = I.tool_volume, extra_checks = CALLBACK(src, .proc/check_state_and_anchored, state, anchored)))
if(!I.use_tool(src, user, decon_speed, volume = I.tool_volume, extra_checks = list(CALLBACK(src, .proc/check_state_and_anchored, state, anchored))))
return
state = (state == WINDOW_IN_FRAME ? WINDOW_SCREWED_TO_FRAME : WINDOW_IN_FRAME)
to_chat(user, "<span class='notice'>You [state == WINDOW_IN_FRAME ? "unfasten the window from":"fasten the window to"] the frame.</span>")
else if(state == WINDOW_OUT_OF_FRAME)
to_chat(user, "<span class='notice'>You begin to [anchored ? "unscrew the frame from":"screw the frame to"] the floor...</span>")
if(!I.use_tool(src, user, decon_speed, volume = I.tool_volume, extra_checks = CALLBACK(src, .proc/check_state_and_anchored, state, anchored)))
if(!I.use_tool(src, user, decon_speed, volume = I.tool_volume, extra_checks = list(CALLBACK(src, .proc/check_state_and_anchored, state, anchored))))
return
anchored = !anchored
update_nearby_icons()
to_chat(user, "<span class='notice'>You [anchored ? "fasten the frame to":"unfasten the frame from"] the floor.</span>")
else //if we're not reinforced, we don't need to check or update state
to_chat(user, "<span class='notice'>You begin to [anchored ? "unscrew the window from":"screw the window to"] the floor...</span>")
if(!I.use_tool(src, user, decon_speed, volume = I.tool_volume, extra_checks = CALLBACK(src, .proc/check_anchored, anchored)))
if(!I.use_tool(src, user, decon_speed, volume = I.tool_volume, extra_checks = list(CALLBACK(src, .proc/check_anchored, anchored))))
return
anchored = !anchored
air_update_turf(TRUE)
@@ -297,7 +297,7 @@ GLOBAL_LIST_INIT(wcCommon, pick(list("#379963", "#0d8395", "#58b5c3", "#49e46e",
if(!can_be_reached(user))
return
TOOL_ATTEMPT_DISMANTLE_MESSAGE
if(!I.use_tool(src, user, decon_speed, volume = I.tool_volume, extra_checks = CALLBACK(src, .proc/check_state_and_anchored, state, anchored)))
if(!I.use_tool(src, user, decon_speed, volume = I.tool_volume, extra_checks = list(CALLBACK(src, .proc/check_state_and_anchored, state, anchored))))
return
var/obj/item/stack/sheet/G = new glass_type(user.loc, glass_amount)
G.add_fingerprint(user)
+1
View File
@@ -26,6 +26,7 @@ GLOBAL_LIST_INIT(admin_verbs_admin, list(
/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/cmd_admin_open_logging_view,
/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*/
+9 -3
View File
@@ -2196,9 +2196,15 @@
var/reply_to = locate(href_list["replyto"])
var/destination
var/notify
var/obj/item/paper/P = new /obj/item/paper(null) //hopefully the null loc won't cause trouble for us
var/obj/item/paper/P
var/use_letterheard = alert("Use letterhead? If so, do not add your own header or a footer. Type and format only your actual message.",,"Nanotrasen","Syndicate", "No")
switch(use_letterheard)
if("Nanotrasen")
P = new /obj/item/paper/central_command(null)
if("Syndicate")
P = new /obj/item/paper/syndicate(null)
if("No")
P = new /obj/item/paper(null)
if(!fax)
var/list/departmentoptions = GLOB.alldepartments + GLOB.hidden_departments + "All Departments"
destination = input(usr, "To which department?", "Choose a department", "") as null|anything in departmentoptions
+10
View File
@@ -0,0 +1,10 @@
GLOBAL_LIST_INIT(open_logging_views, list())
/client/proc/cmd_admin_open_logging_view()
set category = "Admin"
set name = "Open Logging View"
set desc = "Opens the detailed logging viewer"
if(!GLOB.open_logging_views[usr.client.ckey])
GLOB.open_logging_views[usr.client.ckey] = new /datum/log_viewer()
GLOB.open_logging_views[usr.client.ckey].show_ui(usr)
+1 -1
View File
@@ -885,7 +885,7 @@ Traitors and the like can also be revived with the previous role mostly intact.
return
to_chat(usr, text("<span class='danger'>Attack Log for []</span>", mob))
for(var/t in M.attack_log)
for(var/t in M.attack_log_old)
to_chat(usr, t)
feedback_add_details("admin_verb","ATTL") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
+2 -1
View File
@@ -195,7 +195,8 @@ GLOBAL_LIST_EMPTY(asset_datums)
"large_stamp-rep.png" = 'icons/paper_icons/large_stamp-rep.png',
"large_stamp-magistrate.png"= 'icons/paper_icons/large_stamp-magistrate.png',
"talisman.png" = 'icons/paper_icons/talisman.png',
"ntlogo.png" = 'icons/paper_icons/ntlogo.png'
"ntlogo.png" = 'icons/paper_icons/ntlogo.png',
"syndielogo.png" ='icons/paper_icons/syndielogo.png'
)
/datum/asset/simple/chess
@@ -285,6 +285,7 @@
else //this looks ugly but it's better than a copy-pasted startgibbing proc override
occupant.create_attack_log("Was gibbed by <b>an autogibber (\the [src])</b>")
add_attack_logs(src, occupant, "gibbed")
occupant.emote("scream")
playsound(get_turf(src), 'sound/goonstation/effects/gib.ogg', 50, 1)
+4 -3
View File
@@ -53,7 +53,8 @@ GLOBAL_VAR_INIT(observer_default_invisibility, INVISIBILITY_OBSERVER)
var/turf/T
if(ismob(body))
T = get_turf(body) //Where is the body located?
attack_log = body.attack_log //preserve our attack logs by copying them to our ghost
attack_log_old = body.attack_log_old //preserve our attack logs by copying them to our ghost
logs = body.logs.Copy()
var/mutable_appearance/MA = copy_appearance(body)
if(body.mind && body.mind.name)
@@ -431,7 +432,7 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
set name = "Orbit" // "Haunt"
set desc = "Follow and orbit a mob."
var/list/mobs = getpois(skip_mindless=1)
var/list/mobs = getpois(FALSE, TRUE, TRUE, TRUE)
var/datum/async_input/A = input_autocomplete_async(usr, "Please, select a mob: ", mobs)
A.on_close(CALLBACK(src, .proc/ManualFollow))
@@ -506,7 +507,7 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
set desc = "Teleport to a mob"
if(isobserver(usr)) //Make sure they're an observer!
var/list/dest = getpois(mobs_only=1) //Fill list, prompt user with list
var/list/dest = getpois(mobs_only=TRUE) //Fill list, prompt user with list
var/datum/async_input/A = input_autocomplete_async(usr, "Enter a mob name: ", dest)
A.on_close(CALLBACK(src, .proc/jump_to_mob))
+1
View File
@@ -59,6 +59,7 @@
var/mob/living/L = src
L.say_log += "EMOTE: [input]" //say log too so it is easier on admins instead of having to merge the two with timestamps etc
L.emote_log += input //emote only log if an admin wants to search just for emotes they don't have to sift through the say
create_log(EMOTE_LOG, input) // TODO after #13047: Include the channel
// Hearing gasp and such every five seconds is not good emotes were not global for a reason.
// Maybe some people are okay with that.
for(var/mob/M in GLOB.player_list)
@@ -146,11 +146,13 @@
return
var/limb_select = input(H, "Choose a limb to regrow", "Limb Regrowth") as null|anything in missing_limbs
if(!limb_select) // If the user hit cancel on the popup, return
return
var/chosen_limb = missing_limbs[limb_select]
H.visible_message("<span class='notice'>[H] begins to hold still and concentrate on [H.p_their()] missing [limb_select]...</span>", "<span class='notice'>You begin to focus on regrowing your missing [limb_select]... (This will take [round(SLIMEPERSON_REGROWTHDELAY/10)] seconds, and you must hold still.)</span>")
if(do_after(H, SLIMEPERSON_REGROWTHDELAY, needhand = 0, target = H))
if(H.incapacitated())
if(do_after(H, SLIMEPERSON_REGROWTHDELAY, FALSE, H, extra_checks = list(CALLBACK(H, /mob.proc/IsStunned)), use_default_checks = FALSE)) // Override the check for weakness, only check for stunned
if(H.incapacitated(ignore_lying = TRUE, extra_checks = list(CALLBACK(H, /mob.proc/IsStunned)), use_default_checks = FALSE)) // Override the check for weakness, only check for stunned
to_chat(H, "<span class='warning'>You cannot regenerate missing limbs in your current state.</span>")
return
@@ -196,4 +198,4 @@
#undef SLIMEPERSON_HUNGERCOST
#undef SLIMEPERSON_MINHUNGER
#undef SLIMEPERSON_REGROWTHDELAY
#undef SLIMEPERSON_REGROWTHDELAY
+1
View File
@@ -247,6 +247,7 @@
set hidden = 1
if(InCritical())
create_attack_log("[src] has ["succumbed to death"] with [round(health, 0.1)] points of health!")
create_log(MISC_LOG, "has succumbed to death with [round(health, 0.1)] points of health")
adjustOxyLoss(health - HEALTH_THRESHOLD_DEAD)
// super check for weird mobs, including ones that adjust hp
// we don't want to go overboard and gib them, though
+2
View File
@@ -276,6 +276,7 @@ proc/get_radio_key_from_channel(var/channel)
//Log of what we've said, plain message, no spans or junk
say_log += message
create_log(SAY_LOG, message) // TODO after #13047: Include the channel
log_say(message, src)
return 1
@@ -361,6 +362,7 @@ proc/get_radio_key_from_channel(var/channel)
say_log += "whisper: [message]"
log_whisper(message, src)
create_log(SAY_LOG, "WHISPER: [message]")
var/message_range = 1
var/eavesdropping_range = 2
var/watching_range = 5
@@ -30,6 +30,7 @@
to_chat(ghost, "<span class='ghostalert'>Your cyborg shell has been repaired, re-enter if you want to continue!</span> (Verbs -> Ghost -> Re-enter corpse)")
ghost << sound('sound/effects/genetics.ogg')
create_attack_log("revived, trigger reason: [reason]")
create_log(MISC_LOG, "revived, trigger reason: [reason]")
// diag_hud_set_status()
// diag_hud_set_health()
// update_health_hud()
+4 -1
View File
@@ -7,6 +7,7 @@
else if(stat == UNCONSCIOUS)
return 0
create_attack_log("<font color='red'>Fallen unconscious at [atom_loc_line(get_turf(src))]</font>")
add_attack_logs(src, null, "Fallen unconscious")
log_game("[key_name(src)] fell unconscious at [atom_loc_line(get_turf(src))]")
stat = UNCONSCIOUS
if(updating)
@@ -22,6 +23,7 @@
else if(stat == CONSCIOUS)
return 0
create_attack_log("<font color='red'>Woken up at [atom_loc_line(get_turf(src))]</font>")
add_attack_logs(src, null, "Woken up")
log_game("[key_name(src)] woke up at [atom_loc_line(get_turf(src))]")
stat = CONSCIOUS
if(updating)
@@ -45,6 +47,7 @@
if(!can_be_revived())
return 0
create_attack_log("<font color='red'>Came back to life at [atom_loc_line(get_turf(src))]</font>")
add_attack_logs(src, null, "Came back to life")
log_game("[key_name(src)] came back to life at [atom_loc_line(get_turf(src))]")
stat = CONSCIOUS
GLOB.dead_mob_list -= src
@@ -73,4 +76,4 @@
return 1
/mob/living/proc/check_death_method()
return TRUE
return TRUE
+8 -2
View File
@@ -65,8 +65,14 @@
return !(IsWeakened() || paralysis || stat || (status_flags & FAKEDEATH))
// Whether the mob is capable of actions or not
/mob/living/incapacitated(ignore_restraints = FALSE, ignore_grab = FALSE, ignore_lying = FALSE)
if(stat || paralysis || stunned || IsWeakened() || (!ignore_restraints && restrained()) || (!ignore_lying && lying))
/mob/living/incapacitated(ignore_restraints = FALSE, ignore_grab = FALSE, ignore_lying = FALSE, list/extra_checks = list(), use_default_checks = TRUE)
// By default, checks for weakness and stunned get added to the extra_checks list.
// Setting `use_default_checks` to FALSE means that you don't want it checking for these statuses or you are supplying your own checks.
if(use_default_checks)
extra_checks += CALLBACK(src, /mob.proc/IsWeakened)
extra_checks += CALLBACK(src, /mob.proc/IsStunned)
if(stat || paralysis || (!ignore_restraints && restrained()) || (!ignore_lying && lying) || check_for_true_callbacks(extra_checks))
return TRUE
// wonderful proc names, I know - used to check whether the blur overlay
+1
View File
@@ -5,6 +5,7 @@
computer_id = client.computer_id
log_access_in(client)
create_attack_log("<font color='red'>Logged in at [atom_loc_line(get_turf(src))]</font>")
create_log(MISC_LOG, "Logged in")
if(config.log_access)
for(var/mob/M in GLOB.player_list)
if(M == src) continue
+1
View File
@@ -4,6 +4,7 @@
GLOB.player_list -= src
log_access_out(src)
create_attack_log("<font color='red'>Logged out at [atom_loc_line(get_turf(src))]</font>")
create_log(MISC_LOG, "Logged out")
// `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(GLOB.admin_datums[ckey] && SSticker && SSticker.current_state == GAME_STATE_PLAYING)
+10 -3
View File
@@ -22,6 +22,7 @@
for(var/datum/alternate_appearance/AA in viewing_alternate_appearances)
AA.viewers -= src
viewing_alternate_appearances = null
logs.Cut()
..()
return QDEL_HINT_HARDDEL
@@ -1257,14 +1258,20 @@ GLOBAL_LIST_INIT(slot_equipment_priority, list( \
return list() //must return list or IGNORE_ACCESS
/mob/proc/create_attack_log(text, collapse = TRUE)
LAZYINITLIST(attack_log)
create_log_in_list(attack_log, text, collapse, last_log)
LAZYINITLIST(attack_log_old)
create_log_in_list(attack_log_old, text, collapse, last_log)
last_log = world.timeofday
/mob/proc/create_debug_log(text, collapse = TRUE)
LAZYINITLIST(debug_log)
create_log_in_list(debug_log, text, collapse, world.timeofday)
/mob/proc/create_log(log_type, what, target = null, turf/where = get_turf(src))
LAZYINITLIST(logs[log_type])
var/list/log_list = logs[log_type]
var/datum/log_record/record = new(log_type, src, what, target, where, world.time)
log_list.Add(record)
/proc/create_log_in_list(list/target, text, collapse = TRUE, last_log)//forgive me code gods for this shitcode proc
//this proc enables lovely stuff like an attack log that looks like this: "[18:20:29-18:20:45]21x John Smith attacked Andrew Jackson with a crowbar."
//That makes the logs easier to read, but because all of this is stored in strings, weird things have to be used to get it all out.
@@ -1406,4 +1413,4 @@ GLOBAL_LIST_INIT(slot_equipment_priority, list( \
///Force set the mob nutrition
/mob/proc/set_nutrition(change)
nutrition = max(0, change)
nutrition = max(0, change)
+5 -2
View File
@@ -33,8 +33,11 @@
var/computer_id = null
var/lastattacker = null
var/lastattacked = null
var/list/attack_log = list( )
var/list/attack_log_old = list( )
var/list/debug_log = null
var/list/logs = list() // Logs for each log type defined in __DEFINES/logs.dm
var/last_log = 0
var/obj/machinery/machine = null
var/other_mobs = null
@@ -208,4 +211,4 @@
var/list/tkgrabbed_objects = list() // Assoc list of items to TK grabs
var/forced_look = null // This can either be a numerical direction or a soft object reference (UID). It makes the mob always face towards the selected thing.
var/registered_z
var/registered_z
+1 -1
View File
@@ -1,5 +1,5 @@
#define ILLEGAL_CHARACTERS_LIST list("<" = "", ">" = "", "^" = "", \
#define ILLEGAL_CHARACTERS_LIST list("<" = "", ">" = "", \
"\[" = "", "]" = "", "{" = "", "}" = "")
/mob/proc/say()
+3
View File
@@ -173,6 +173,9 @@
/mob/proc/Stun()
return
/mob/proc/IsStunned()
return stunned
/mob/proc/SetStunned()
return
+21 -2
View File
@@ -21,7 +21,9 @@
max_integrity = 50
attack_verb = list("bapped")
dog_fashion = /datum/dog_fashion/head
var/header //Above the main body, displayed at the top
var/info //What's actually written on the paper.
var/footer //The bottom stuff before the stamp but after the body
var/info_links //A different version of the paper which includes html links at fields and EOF
var/stamps //The (text for the) stamps on the paper.
var/fields //Amount of user created fields
@@ -76,9 +78,9 @@
var/data
var/stars = (!user.say_understands(null, GLOB.all_languages["Galactic Common"]) && !forceshow) || forcestars
if(stars) //assuming all paper is written in common is better than hardcoded type checks
data = "[stars(info)][stamps]"
data = "[header][stars(info)][footer][stamps]"
else
data = "<div id='markdown'>[infolinks ? info_links : info]</div>[stamps]"
data = "[header]<div id='markdown'>[infolinks ? info_links : info]</div>[footer][stamps]"
if(view)
var/datum/browser/popup = new(user, "Paper[UID()]", , paper_width, paper_height)
popup.stylesheets = list()
@@ -587,6 +589,23 @@
/obj/item/paper/crumpled
name = "paper scrap"
icon_state = "scrap"
/obj/item/paper/syndicate
name = "paper"
header = "<p><img style='display: block; margin-left: auto; margin-right: auto;' src='syndielogo.png' width='220' height='135' /></p><hr />"
info = ""
/obj/item/paper/nanotrasen
name = "paper"
header = "<p><img style='display: block; margin-left: auto; margin-right: auto;' src='ntlogo.png' width='220' height='135' /></p><hr />"
info = ""
/obj/item/paper/central_command
name = "paper"
header ="<p><img style='display: block; margin-left: auto; margin-right: auto;' src='ntlogo.png' alt='' width='220' height='135' /></p><hr /><h3 style='text-align: center;font-family: Verdana;'><b> Nanotrasen Central Command</h3><p style='text-align: center;font-family:Verdana;'>Official Expedited Memorandum</p></b><hr />"
info = ""
footer = "<hr /><p style='font-family:Verdana;'><em>Failure to adhere appropriately to orders that may be contained herein is in violation of Space Law, and punishments may be administered appropriately upon return to Central Command.</em><br /><em>The recipient(s) of this memorandum acknowledge by reading it that they are liable for any and all damages to crew or station that may arise from ignoring suggestions or advice given herein.</em></p>"
/obj/item/paper/crumpled/update_icon()
return
+16 -2
View File
@@ -10,7 +10,8 @@
pressure_resistance = 8
var/amount = 30 //How much paper is in the bin.
var/list/papers = list() //List of papers put in the bin for reference.
var/letterhead_type
/obj/item/paper_bin/fire_act(datum/gas_mixture/air, exposed_temperature, exposed_volume, global_overlay = TRUE)
if(amount)
amount = 0
@@ -71,7 +72,10 @@
P = papers[papers.len]
papers.Remove(P)
else
P = new /obj/item/paper
if(letterhead_type && alert("Choose a style",,"Letterhead","Blank")=="Letterhead")
P = new letterhead_type
else
P = new /obj/item/paper
if(SSholiday.holidays && SSholiday.holidays[APRIL_FOOLS])
if(prob(30))
P.info = "<font face=\"[P.crayonfont]\" color=\"red\"><b>HONK HONK HONK HONK HONK HONK HONK<br>HOOOOOOOOOOOOOOOOOOOOOONK<br>APRIL FOOLS</b></font>"
@@ -139,3 +143,13 @@
add_fingerprint(user)
return
/obj/item/paper_bin/nanotrasen
name = "nanotrasen paper bin"
letterhead_type = /obj/item/paper/nanotrasen
/obj/item/paper_bin/syndicate
name = "syndicate paper bin"
letterhead_type = /obj/item/paper/syndicate
+2
View File
@@ -187,7 +187,9 @@
/obj/machinery/photocopier/proc/copy(var/obj/item/paper/copy)
var/obj/item/paper/c = new /obj/item/paper (loc)
c.header = copy.header
c.info = copy.info
c.footer = copy.footer
c.name = copy.name // -- Doohl
c.fields = copy.fields
c.stamps = copy.stamps
@@ -51,6 +51,7 @@
user.visible_message("<span class='danger'>[user] zaps [user.p_them()]self with [src].</span>")
playsound(user, fire_sound, 50, 1)
user.create_attack_log("<b>[key_name(user)]</b> zapped [user.p_them()]self with a <b>[src]</b>")
add_attack_logs(null, user, "zapped [user.p_them()]self with a [src]")
/////////////////////////////////////
//WAND OF DEATH
+4 -2
View File
@@ -263,12 +263,14 @@
return
M.create_attack_log("<font color='orange'>[key_name(M)] became [new_mob.real_name].</font>")
new_mob.attack_log = M.attack_log
add_attack_logs(null, M, "became [new_mob.real_name]")
new_mob.a_intent = INTENT_HARM
if(M.mind)
M.mind.transfer_to(new_mob)
else
new_mob.attack_log_old = M.attack_log_old.Copy()
new_mob.logs = M.logs.Copy()
new_mob.key = M.key
to_chat(new_mob, "<B>Your form morphs into that of a [randomize].</B>")
@@ -344,4 +346,4 @@
to_chat(target, "<span class='notice'>You get splatted by [src].</span>")
M.Weaken(slip_weaken)
M.Stun(slip_stun)
. = ..()
. = ..()
+9 -3
View File
@@ -16,7 +16,7 @@
. = ..()
if(. && obj_integrity > 0)
if(tank_volume && (damage_flag == "bullet" || damage_flag == "laser"))
boom()
boom(FALSE, TRUE)
/obj/structure/reagent_dispensers/attackby(obj/item/I, mob/user, params)
if(I.is_refillable())
@@ -43,7 +43,7 @@
/obj/structure/reagent_dispensers/deconstruct(disassembled = TRUE)
if(!(flags & NODECONSTRUCT))
if(!disassembled)
boom()
boom(FALSE, TRUE)
else
qdel(src)
@@ -85,15 +85,19 @@
if(!QDELETED(src)) //wasn't deleted by the projectile's effects.
if(!P.nodamage && ((P.damage_type == BURN) || (P.damage_type == BRUTE)))
message_admins("[key_name_admin(P.firer)] triggered a fueltank explosion with [P.name] at [COORD(loc)] ")
add_attack_logs(P.firer, src, "shot with [P.name]")
log_game("[key_name(P.firer)] triggered a fueltank explosion with [P.name] at [COORD(loc)]")
investigate_log("[key_name(P.firer)] triggered a fueltank explosion with [P.name] at [COORD(loc)]", INVESTIGATE_BOMB)
boom()
/obj/structure/reagent_dispensers/fueltank/boom(rigtrigger = FALSE) // Prevent case where someone who rigged the tank is blamed for the explosion when the rig isn't what triggered the explosion
/obj/structure/reagent_dispensers/fueltank/boom(rigtrigger = FALSE, log_attack = FALSE) // Prevent case where someone who rigged the tank is blamed for the explosion when the rig isn't what triggered the explosion
if(rigtrigger) // If the explosion is triggered by an assembly holder
message_admins("A fueltank, last rigged by [lastrigger], was triggered at [COORD(loc)]") // Then admin is informed of the last person who rigged the fuel tank
log_game("A fueltank, last rigged by [lastrigger], triggered at [COORD(loc)]")
add_attack_logs(lastrigger, src, "rigged fuel tank exploded")
investigate_log("A fueltank, last rigged by [lastrigger], triggered at [COORD(loc)]", INVESTIGATE_BOMB)
if(log_attack)
add_attack_logs(usr, src, "blew up", ATKLOG_FEW)
if(reagents)
reagents.set_reagent_temp(1000) //uh-oh
qdel(src)
@@ -140,6 +144,7 @@
if(istype(H.a_left, /obj/item/assembly/igniter) || istype(H.a_right, /obj/item/assembly/igniter))
msg_admin_attack("[key_name_admin(user)] rigged [src.name] with [I.name] for explosion (<A HREF='?_src_=holder;adminplayerobservecoodjump=1;X=[x];Y=[y];Z=[z]'>JMP</a>)", ATKLOG_FEW)
log_game("[key_name(user)] rigged [src.name] with [I.name] for explosion at [COORD(loc)]")
add_attack_logs(user, src, "rigged fuel tank")
investigate_log("[key_name(user)] rigged [src.name] with [I.name] for explosion at [COORD(loc)]", INVESTIGATE_BOMB)
lastrigger = "[key_name(user)]"
@@ -163,6 +168,7 @@ obj/structure/reagent_dispensers/fueltank/welder_act(mob/user, obj/item/I)
user.visible_message("<span class='danger'>[user] catastrophically fails at refilling [user.p_their()] [I]!</span>", "<span class='userdanger'>That was stupid of you.</span>")
message_admins("[key_name_admin(user)] triggered a fueltank explosion at [COORD(loc)]")
log_game("[key_name(user)] triggered a fueltank explosion at [COORD(loc)]")
add_attack_logs(user, src, "hit with lit welder")
investigate_log("[key_name(user)] triggered a fueltank explosion at [COORD(loc)]", INVESTIGATE_BOMB)
boom()
else
@@ -221,6 +221,7 @@
user.visible_message("<span class='notice'>[user] wraps [target].</span>")
user.create_attack_log("<font color='blue'>Has used [name] on [target]</font>")
add_attack_logs(user, target, "used [name]")
if(amount <= 0 && !src.loc) //if we used our last wrapping paper, drop a cardboard tube
new /obj/item/c_tube( get_turf(user) )
+1
View File
@@ -216,6 +216,7 @@
deal_damage(damage)
visible_message("<span class='danger'>[user]</span> [user.attacktext] [src]!")
user.create_attack_log("<font color='red'>attacked [src.name]</font>")
add_attack_logs(user, src, "attacked")
return TRUE
/obj/spacepod/attack_alien(mob/user)
+1
View File
@@ -243,6 +243,7 @@
qdel(src)
src.visible_message("<span class='danger'>[M] has [M.attacktext] [src]!</span>")
M.create_attack_log("<font color='red'>attacked [src.name]</font>")
add_attack_logs(M, src, "attacked")
/obj/tram/bullet_act(var/obj/item/projectile/proj)
if(prob(proj.damage))
Binary file not shown.

Before

Width:  |  Height:  |  Size: 148 KiB

After

Width:  |  Height:  |  Size: 149 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 148 KiB

After

Width:  |  Height:  |  Size: 149 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.8 KiB

After

Width:  |  Height:  |  Size: 6.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.6 KiB

+4
View File
@@ -46,6 +46,7 @@
#include "code\__DEFINES\language.dm"
#include "code\__DEFINES\layers.dm"
#include "code\__DEFINES\lighting.dm"
#include "code\__DEFINES\logs.dm"
#include "code\__DEFINES\machines.dm"
#include "code\__DEFINES\math.dm"
#include "code\__DEFINES\MC.dm"
@@ -263,6 +264,8 @@
#include "code\datums\gas_mixture.dm"
#include "code\datums\holocall.dm"
#include "code\datums\hud.dm"
#include "code\datums\log_record.dm"
#include "code\datums\log_viewer.dm"
#include "code\datums\mind.dm"
#include "code\datums\mixed.dm"
#include "code\datums\mutable_appearance.dm"
@@ -1214,6 +1217,7 @@
#include "code\modules\admin\verbs\gimmick_team.dm"
#include "code\modules\admin\verbs\honksquad.dm"
#include "code\modules\admin\verbs\infiltratorteam_syndicate.dm"
#include "code\modules\admin\verbs\logging_view.dm"
#include "code\modules\admin\verbs\map_template_loadverb.dm"
#include "code\modules\admin\verbs\mapping.dm"
#include "code\modules\admin\verbs\massmodvar.dm"