diff --git a/baystation12.dme b/baystation12.dme
index 510ef39501b..12abeb3abb4 100644
--- a/baystation12.dme
+++ b/baystation12.dme
@@ -1460,6 +1460,7 @@
#include "code\modules\random_map\random_map.dm"
#include "code\modules\reagents\Chemistry-Colours.dm"
#include "code\modules\reagents\Chemistry-Holder.dm"
+#include "code\modules\reagents\Chemistry-Logging.dm"
#include "code\modules\reagents\Chemistry-Machinery.dm"
#include "code\modules\reagents\Chemistry-Metabolism.dm"
#include "code\modules\reagents\Chemistry-Readme.dm"
diff --git a/code/modules/admin/admin_verbs.dm b/code/modules/admin/admin_verbs.dm
index 9655ba5bcec..625a63a29e7 100644
--- a/code/modules/admin/admin_verbs.dm
+++ b/code/modules/admin/admin_verbs.dm
@@ -83,10 +83,12 @@ var/list/admin_verbs_admin = list(
/client/proc/allow_character_respawn, /* Allows a ghost to respawn */
/client/proc/event_manager_panel,
/client/proc/empty_ai_core_toggle_latejoin,
+ /client/proc/empty_ai_core_toggle_latejoin,
/client/proc/aooc,
/client/proc/change_human_appearance_admin, /* Allows an admin to change the basic appearance of human-based mobs */
/client/proc/change_human_appearance_self, /* Allows the human-based mob itself change its basic appearance */
- /client/proc/change_security_level
+ /client/proc/change_security_level,
+ /client/proc/view_chemical_reaction_logs
)
var/list/admin_verbs_ban = list(
/client/proc/unban_panel,
diff --git a/code/modules/mob/dead/observer/observer.dm b/code/modules/mob/dead/observer/observer.dm
index 176e837f946..84a3e6b2c30 100644
--- a/code/modules/mob/dead/observer/observer.dm
+++ b/code/modules/mob/dead/observer/observer.dm
@@ -566,7 +566,7 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
toggle_visibility(1)
else
user.visible_message ( \
- "[user] just tried to smash his book into that ghost! It's not very effective.", \
+ "[user] just tried to smash \his book into that ghost! It's not very effective.", \
"You get the feeling that the ghost can't become any more visible." \
)
diff --git a/code/modules/reagents/Chemistry-Logging.dm b/code/modules/reagents/Chemistry-Logging.dm
new file mode 100644
index 00000000000..1432b18a2e8
--- /dev/null
+++ b/code/modules/reagents/Chemistry-Logging.dm
@@ -0,0 +1,28 @@
+
+/var/list/chemical_reaction_logs = list()
+
+/proc/log_chemical_reaction(atom/A, datum/chemical_reaction/R, multiplier)
+ if(!A || !R)
+ return
+
+ var/turf/T = get_turf(A)
+ var/logstr = "[usr ? key_name(usr) : "EVENT"] mixed [R.name] ([R.result]) (x[multiplier]) in \the [A] at [T ? "[T.x],[T.y],[T.z]" : "*null*"]"
+
+ chemical_reaction_logs += "\[[time_stamp()]\] [logstr]"
+
+ if(R.log_is_important)
+ message_admins(logstr)
+ log_admin(logstr)
+
+/client/proc/view_chemical_reaction_logs()
+ set name = "Show Chemical Reactions"
+ set category = "Admin"
+
+ if(!check_rights(R_ADMIN))
+ return
+
+ var/html = ""
+ for(var/entry in chemical_reaction_logs)
+ html += "[entry]
"
+
+ usr << browse(html, "window=chemlogs")
diff --git a/code/modules/reagents/Chemistry-Recipes.dm b/code/modules/reagents/Chemistry-Recipes.dm
index 6da341198db..677ffb910ab 100644
--- a/code/modules/reagents/Chemistry-Recipes.dm
+++ b/code/modules/reagents/Chemistry-Recipes.dm
@@ -9,6 +9,7 @@
var/result_amount = 0
var/mix_message = "The solution begins to bubble."
+ var/log_is_important = 0 // If this reaction should be considered important for logging. Important recipes message admins when mixed, non-important ones just log to file.
/datum/chemical_reaction/proc/can_happen(var/datum/reagents/holder)
return 1
@@ -146,6 +147,7 @@
result = "kelotane"
required_reagents = list("silicon" = 1, "carbon" = 1)
result_amount = 2
+ log_is_important = 1
/datum/chemical_reaction/peridaxon
name = "Peridaxon"
@@ -392,6 +394,7 @@
result = "coolant"
required_reagents = list("tungsten" = 1, "oxygen" = 1, "water" = 1)
result_amount = 3
+ log_is_important = 1
/datum/chemical_reaction/rezadone
name = "Rezadone"
diff --git a/code/world.dm b/code/world.dm
index fb9aabdc544..9adfe9968a5 100644
--- a/code/world.dm
+++ b/code/world.dm
@@ -102,7 +102,8 @@ var/world_topic_spam_protect_time = world.timeofday
n++
return n
- else if (T == "status")
+ else if (copytext(T,1,7) == "status")
+ var/input[] = params2list(T)
var/list/s = list()
s["version"] = game_version
s["mode"] = master_mode
@@ -111,21 +112,37 @@ var/world_topic_spam_protect_time = world.timeofday
s["vote"] = config.allow_vote_mode
s["ai"] = config.allow_ai
s["host"] = host ? host : null
- s["players"] = list()
s["stationtime"] = worldtime2text()
- var/n = 0
- var/admins = 0
- for(var/client/C in clients)
- if(C.holder)
- if(C.holder.fakekey)
- continue //so stealthmins aren't revealed by the hub
- admins++
- s["player[n]"] = C.key
- n++
- s["players"] = n
+ if(input["status"] == "2")
+ var/list/players = list()
+ var/list/admins = list()
- s["admins"] = admins
+ for(var/client/C in clients)
+ if(C.holder)
+ if(C.holder.fakekey)
+ continue
+ admins[C.key] = C.holder.rank
+ players += C.key
+
+ s["players"] = players.len
+ s["playerlist"] = list2params(players)
+ s["admins"] = admins.len
+ s["adminlist"] = list2params(admins)
+ else
+ var/n = 0
+ var/admins = 0
+
+ for(var/client/C in clients)
+ if(C.holder)
+ if(C.holder.fakekey)
+ continue //so stealthmins aren't revealed by the hub
+ admins++
+ s["player[n]"] = C.key
+ n++
+
+ s["players"] = n
+ s["admins"] = admins
return list2params(s)