diff --git a/baystation12.dme b/baystation12.dme
index 94a938770d..370edab842 100644
--- a/baystation12.dme
+++ b/baystation12.dme
@@ -211,7 +211,6 @@
#include "code\defines\gases.dm"
#include "code\defines\obj.dm"
#include "code\defines\obj\weapon.dm"
-#include "code\defines\procs\admin.dm"
#include "code\defines\procs\announce.dm"
#include "code\defines\procs\AStar.dm"
#include "code\defines\procs\dbcore.dm"
@@ -815,6 +814,7 @@
#include "code\js\byjax.dm"
#include "code\js\menus.dm"
#include "code\modules\admin\admin.dm"
+#include "code\modules\admin\admin_attack_log.dm"
#include "code\modules\admin\admin_investigate.dm"
#include "code\modules\admin\admin_memo.dm"
#include "code\modules\admin\admin_ranks.dm"
diff --git a/code/_helpers/logging.dm b/code/_helpers/logging.dm
index 50f55703d3..d5d0f58685 100644
--- a/code/_helpers/logging.dm
+++ b/code/_helpers/logging.dm
@@ -93,3 +93,60 @@
if(dir & DOWN) comps += "DOWN"
return english_list(comps, nothing_text="0", and_text="|", comma_text="|")
+
+//more or less a logging utility
+/proc/key_name(var/whom, var/include_link = null, var/include_name = 1, var/highlight_special_characters = 1)
+ var/mob/M
+ var/client/C
+ var/key
+
+ if(!whom) return "*null*"
+ if(istype(whom, /client))
+ C = whom
+ M = C.mob
+ key = C.key
+ else if(ismob(whom))
+ M = whom
+ C = M.client
+ key = M.key
+ else if(istype(whom, /datum))
+ var/datum/D = whom
+ return "*invalid:[D.type]*"
+ else
+ return "*invalid*"
+
+ . = ""
+
+ if(key)
+ if(include_link && C)
+ . += ""
+
+ if(C && C.holder && C.holder.fakekey && !include_name)
+ . += "Administrator"
+ else
+ . += key
+
+ if(include_link)
+ if(C) . += ""
+ else . += " (DC)"
+ else
+ . += "*no key*"
+
+ if(include_name && M)
+ var/name
+
+ if(M.real_name)
+ name = M.real_name
+ else if(M.name)
+ name = M.name
+
+
+ if(include_link && is_special_character(M) && highlight_special_characters)
+ . += "/([name])" //Orange
+ else
+ . += "/([name])"
+
+ return .
+
+/proc/key_name_admin(var/whom, var/include_name = 1)
+ return key_name(whom, 1, include_name)
diff --git a/code/_helpers/unsorted.dm b/code/_helpers/unsorted.dm
index 29d55e629f..e44a60ebc2 100644
--- a/code/_helpers/unsorted.dm
+++ b/code/_helpers/unsorted.dm
@@ -479,64 +479,6 @@ Turf and target are seperate in case you want to teleport some distance from a t
if(M < 0)
return -M
-
-/proc/key_name(var/whom, var/include_link = null, var/include_name = 1, var/highlight_special_characters = 1)
- var/mob/M
- var/client/C
- var/key
-
- if(!whom) return "*null*"
- if(istype(whom, /client))
- C = whom
- M = C.mob
- key = C.key
- else if(ismob(whom))
- M = whom
- C = M.client
- key = M.key
- else if(istype(whom, /datum))
- var/datum/D = whom
- return "*invalid:[D.type]*"
- else
- return "*invalid*"
-
- . = ""
-
- if(key)
- if(include_link && C)
- . += ""
-
- if(C && C.holder && C.holder.fakekey && !include_name)
- . += "Administrator"
- else
- . += key
-
- if(include_link)
- if(C) . += ""
- else . += " (DC)"
- else
- . += "*no key*"
-
- if(include_name && M)
- var/name
-
- if(M.real_name)
- name = M.real_name
- else if(M.name)
- name = M.name
-
-
- if(include_link && is_special_character(M) && highlight_special_characters)
- . += "/([name])" //Orange
- else
- . += "/([name])"
-
- return .
-
-/proc/key_name_admin(var/whom, var/include_name = 1)
- return key_name(whom, 1, include_name)
-
-
// returns the turf located at the map edge in the specified direction relative to A
// used for mass driver
/proc/get_edge_target_turf(var/atom/A, var/direction)
diff --git a/code/game/gamemodes/malfunction/newmalf_ability_trees/HELPERS.dm b/code/game/gamemodes/malfunction/newmalf_ability_trees/HELPERS.dm
index 1be9d0330f..f757ed5e9e 100644
--- a/code/game/gamemodes/malfunction/newmalf_ability_trees/HELPERS.dm
+++ b/code/game/gamemodes/malfunction/newmalf_ability_trees/HELPERS.dm
@@ -65,7 +65,7 @@
set desc = "Opens help window with overview of available hardware, software and other important information."
var/mob/living/silicon/ai/user = usr
- var/help = file2text("ingame_manuals/malf_ai.html")
+ var/help = file2text('ingame_manuals/malf_ai.html')
if(!help)
help = "Error loading help (file /ingame_manuals/malf_ai.html is probably missing). Please report this to server administration staff."
diff --git a/code/game/objects/effects/effect_system.dm b/code/game/objects/effects/effect_system.dm
index b38a0f1551..ec3881cdbe 100644
--- a/code/game/objects/effects/effect_system.dm
+++ b/code/game/objects/effects/effect_system.dm
@@ -487,28 +487,34 @@ steam.start() -- spawns the effect
M.Weaken(rand(1,5))
return
else
- var/devastation = -1
+ var/devst = -1
var/heavy = -1
var/light = -1
var/flash = -1
- // Clamp all values to max_explosion_range
+ // Clamp all values to fractions of max_explosion_range, following the same pattern as for tank transfer bombs
if (round(amount/12) > 0)
- devastation = min (max_explosion_range, devastation + round(amount/12))
+ devst = devst + amount/12
if (round(amount/6) > 0)
- heavy = min (max_explosion_range, heavy + round(amount/6))
+ heavy = heavy + amount/6
if (round(amount/3) > 0)
- light = min (max_explosion_range, light + round(amount/3))
+ light = light + amount/3
- if (flash && flashing_factor)
- flash += (round(amount/4) * flashing_factor)
+ if (flashing && flashing_factor)
+ flash = (amount/4) * flashing_factor
for(var/mob/M in viewers(8, location))
M << "The solution violently explodes."
- explosion(location, devastation, heavy, light, flash)
+ explosion(
+ location,
+ round(min(devst, BOMBCAP_DVSTN_RADIUS)),
+ round(min(heavy, BOMBCAP_HEAVY_RADIUS)),
+ round(min(light, BOMBCAP_LIGHT_RADIUS)),
+ round(min(flash, BOMBCAP_FLASH_RADIUS))
+ )
proc/holder_damage(var/atom/holder)
if(holder)
diff --git a/code/game/objects/explosion.dm b/code/game/objects/explosion.dm
index 58c053aa66..6ad69f099b 100644
--- a/code/game/objects/explosion.dm
+++ b/code/game/objects/explosion.dm
@@ -16,16 +16,16 @@ proc/explosion(turf/epicenter, devastation_range, heavy_impact_range, light_impa
explosion_rec(epicenter, power)
return
+ var/start = world.timeofday
+ epicenter = get_turf(epicenter)
+ if(!epicenter) return
+
///// Z-Level Stuff
if(z_transfer && (devastation_range > 0 || heavy_impact_range > 0))
//transfer the explosion in both directions
explosion_z_transfer(epicenter, devastation_range, heavy_impact_range, light_impact_range, flash_range)
///// Z-Level Stuff
- var/start = world.timeofday
- epicenter = get_turf(epicenter)
- if(!epicenter) return
-
var/max_range = max(devastation_range, heavy_impact_range, light_impact_range, flash_range)
//playsound(epicenter, 'sound/effects/explosionfar.ogg', 100, 1, round(devastation_range*2,1) )
//playsound(epicenter, "explosion", 100, 1, round(devastation_range,1) )
diff --git a/code/game/objects/items/devices/aicard.dm b/code/game/objects/items/devices/aicard.dm
index a6a51386d5..e4d1c57a0d 100644
--- a/code/game/objects/items/devices/aicard.dm
+++ b/code/game/objects/items/devices/aicard.dm
@@ -91,7 +91,7 @@
/obj/item/device/aicard/proc/grab_ai(var/mob/living/silicon/ai/ai, var/mob/living/user)
if(!ai.client)
- user << "ERROR: [name] data core is offline. Unable to download."
+ user << "ERROR: AI [ai.name] is offline. Unable to download."
return 0
if(carded_ai)
@@ -112,7 +112,6 @@
ai.cancel_camera()
ai.control_disabled = 1
ai.aiRestorePowerRoutine = 0
- ai.aiRadio.disabledAi = 1
carded_ai = ai
if(ai.client)
diff --git a/code/game/objects/items/weapons/material/material_weapons.dm b/code/game/objects/items/weapons/material/material_weapons.dm
index fe33163dba..6ff156b27f 100644
--- a/code/game/objects/items/weapons/material/material_weapons.dm
+++ b/code/game/objects/items/weapons/material/material_weapons.dm
@@ -23,6 +23,15 @@
if(!material_key)
material_key = default_material
set_material(material_key)
+ if(!material)
+ qdel(src)
+ return
+
+ matter = material.get_matter()
+ if(matter.len)
+ for(var/material_type in matter)
+ if(!isnull(matter[material_type]))
+ matter[material_type] *= force_divisor // May require a new var instead.
/obj/item/weapon/material/proc/update_force()
if(edge || sharp)
diff --git a/code/game/objects/items/weapons/tanks/tanks.dm b/code/game/objects/items/weapons/tanks/tanks.dm
index 86effc923c..8c5b1de026 100644
--- a/code/game/objects/items/weapons/tanks/tanks.dm
+++ b/code/game/objects/items/weapons/tanks/tanks.dm
@@ -268,19 +268,22 @@
if(!istype(src.loc,/obj/item/device/transfer_valve))
message_admins("Explosive tank rupture! last key to touch the tank was [src.fingerprintslast].")
log_game("Explosive tank rupture! last key to touch the tank was [src.fingerprintslast].")
- //world << "[x],[y] tank is exploding: [pressure] kPa"
+
//Give the gas a chance to build up more pressure through reacting
air_contents.react()
air_contents.react()
air_contents.react()
+
pressure = air_contents.return_pressure()
var/range = (pressure-TANK_FRAGMENT_PRESSURE)/TANK_FRAGMENT_SCALE
- range = min(range, max_explosion_range) // was 8 - - - Changed to a configurable define -- TLE
- var/turf/epicenter = get_turf(loc)
- //world << "Exploding Pressure: [pressure] kPa, intensity: [range]"
-
- explosion(epicenter, round(range*0.25), round(range*0.5), round(range), round(range*1.5))
+ explosion(
+ get_turf(loc),
+ round(min(BOMBCAP_DVSTN_RADIUS, range*0.25)),
+ round(min(BOMBCAP_HEAVY_RADIUS, range*0.50)),
+ round(min(BOMBCAP_LIGHT_RADIUS, range*1.00)),
+ round(min(BOMBCAP_FLASH_RADIUS, range*1.50)),
+ )
qdel(src)
else if(pressure > TANK_RUPTURE_PRESSURE)
diff --git a/code/modules/admin/admin.dm b/code/modules/admin/admin.dm
index d27359acfc..5e486c195a 100644
--- a/code/modules/admin/admin.dm
+++ b/code/modules/admin/admin.dm
@@ -20,6 +20,10 @@ var/global/floorIsLava = 0
var/msg = rendered
C << msg
+proc/admin_notice(var/message, var/rights)
+ for(var/mob/M in mob_list)
+ if(check_rights(rights, 0, M))
+ M << message
///////////////////////////////////////////////////////////////////////////////////////////////Panels
diff --git a/code/defines/procs/admin.dm b/code/modules/admin/admin_attack_log.dm
similarity index 76%
rename from code/defines/procs/admin.dm
rename to code/modules/admin/admin_attack_log.dm
index bf16c5267d..72e85e1d94 100644
--- a/code/defines/procs/admin.dm
+++ b/code/modules/admin/admin_attack_log.dm
@@ -1,7 +1,6 @@
-proc/admin_notice(var/message, var/rights)
- for(var/mob/M in mob_list)
- if(check_rights(rights, 0, M))
- M << message
+/mob/var/lastattacker = null
+/mob/var/lastattacked = null
+/mob/var/attack_log = list( )
proc/log_and_message_admins(var/message as text, var/mob/user = usr)
log_admin(user ? "[key_name(user)] [message]" : "EVENT [message]")
@@ -23,10 +22,12 @@ proc/admin_log_and_message_admins(var/message as text)
message_admins(usr ? "[key_name_admin(usr)] [message]" : "EVENT [message]", 1)
proc/admin_attack_log(var/mob/attacker, var/mob/victim, var/attacker_message, var/victim_message, var/admin_message)
- victim.attack_log += text("\[[time_stamp()]\] [key_name(attacker)] - [victim_message]")
- attacker.attack_log += text("\[[time_stamp()]\] [key_name(victim)] - [attacker_message]")
+ if(victim)
+ victim.attack_log += text("\[[time_stamp()]\] [key_name(attacker)] - [victim_message]")
+ if(attacker)
+ attacker.attack_log += text("\[[time_stamp()]\] [key_name(victim)] - [attacker_message]")
- msg_admin_attack("[key_name(attacker)] [admin_message] [key_name(victim)] (INTENT: [uppertext(attacker.a_intent)]) (JMP)")
+ msg_admin_attack("[key_name(attacker)] [admin_message] [key_name(victim)] (INTENT: [attacker? uppertext(attacker.a_intent) : "N/A"]) (JMP)")
proc/admin_attacker_log_many_victims(var/mob/attacker, var/list/mob/victims, var/attacker_message, var/victim_message, var/admin_message)
if(!victims || !victims.len)
diff --git a/code/modules/materials/material_sheets.dm b/code/modules/materials/material_sheets.dm
index 8a5f584b4f..c41b6fc449 100644
--- a/code/modules/materials/material_sheets.dm
+++ b/code/modules/materials/material_sheets.dm
@@ -38,13 +38,7 @@
if(material.conductive)
flags |= CONDUCT
- if(!islist(matter))
- matter = list()
- if(material.composite_material)
- for(var/material_string in material.composite_material)
- matter[material_string] = material.composite_material[material_string]
- else
- matter[material.name] = SHEET_MATERIAL_AMOUNT
+ matter = material.get_matter()
return 1
/obj/item/stack/material/transfer_to(obj/item/stack/S, var/tamount=null, var/type_verified)
diff --git a/code/modules/materials/materials.dm b/code/modules/materials/materials.dm
index 3f4a4c04ee..08c22538c0 100644
--- a/code/modules/materials/materials.dm
+++ b/code/modules/materials/materials.dm
@@ -103,6 +103,16 @@ var/list/name_to_material
/material/proc/get_blunt_damage()
return weight //todo
+// Return the matter comprising this material.
+/material/proc/get_matter()
+ var/list/temp_matter = list()
+ if(islist(composite_material))
+ for(var/material_string in composite_material)
+ temp_matter[material_string] = composite_material[material_string]
+ else if(stack_per_sheet)
+ temp_matter[name] = stack_per_sheet
+ return temp_matter
+
// As above.
/material/proc/get_edge_damage()
return hardness //todo
@@ -386,6 +396,7 @@ var/list/name_to_material
name = "cardboard"
stack_type = /obj/item/stack/material/cardboard
flags = MATERIAL_BRITTLE
+ integrity = 10
icon_base = "solid"
icon_reinf = "reinf_over"
icon_colour = "#AAAAAA"
diff --git a/code/modules/mob/dead/observer/observer.dm b/code/modules/mob/dead/observer/observer.dm
index c8d5651b29..2c338bcfe7 100644
--- a/code/modules/mob/dead/observer/observer.dm
+++ b/code/modules/mob/dead/observer/observer.dm
@@ -670,9 +670,9 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
client.images -= ghostimage //remove ourself
mob/dead/observer/MayRespawn(var/feedback = 0)
- if(!client || !mind)
+ if(!client)
return 0
- if(mind.current && mind.current.stat != DEAD)
+ if(mind && mind.current && mind.current.stat != DEAD)
if(feedback)
src << "Your non-dead body prevent you from respawning."
return 0
diff --git a/code/modules/mob/living/carbon/human/life.dm b/code/modules/mob/living/carbon/human/life.dm
index e1abecc16b..80adfdc4f2 100644
--- a/code/modules/mob/living/carbon/human/life.dm
+++ b/code/modules/mob/living/carbon/human/life.dm
@@ -1483,7 +1483,7 @@
return
if(shock_stage == 10)
- src << ""+pick("It hurts so much!", "You really need some painkillers..", "Dear god, the pain!")
+ src << "[pick("It hurts so much", "You really need some painkillers", "Dear god, the pain")]!"
if(shock_stage >= 30)
if(shock_stage == 30) emote("me",1,"is having trouble keeping their eyes open.")
@@ -1491,22 +1491,22 @@
stuttering = max(stuttering, 5)
if(shock_stage == 40)
- src << ""+pick("The pain is excrutiating!", "Please, just end the pain!", "Your whole body is going numb!")
+ src << "[pick("The pain is excruciating", "Please, just end the pain", "Your whole body is going numb")]!"
if (shock_stage >= 60)
if(shock_stage == 60) emote("me",1,"'s body becomes limp.")
if (prob(2))
- src << ""+pick("The pain is excrutiating!", "Please, just end the pain!", "Your whole body is going numb!")
+ src << "[pick("The pain is excruciating", "Please, just end the pain", "Your whole body is going numb")]!"
Weaken(20)
if(shock_stage >= 80)
if (prob(5))
- src << ""+pick("The pain is excrutiating!", "Please, just end the pain!", "Your whole body is going numb!")
+ src << "[pick("The pain is excruciating", "Please, just end the pain", "Your whole body is going numb")]!"
Weaken(20)
if(shock_stage >= 120)
if (prob(2))
- src << ""+pick("You black out!", "You feel like you could die any moment now.", "You're about to lose consciousness.")
+ src << "[pick("You black out", "You feel like you could die any moment now", "You're about to lose consciousness")]!"
Paralyse(5)
if(shock_stage == 150)
diff --git a/code/modules/mob/mob_defines.dm b/code/modules/mob/mob_defines.dm
index 897c5181da..109e29f036 100644
--- a/code/modules/mob/mob_defines.dm
+++ b/code/modules/mob/mob_defines.dm
@@ -48,9 +48,6 @@
var/use_me = 1 //Allows all mobs to use the me verb by default, will have to manually specify they cannot
var/damageoverlaytemp = 0
var/computer_id = null
- var/lastattacker = null
- var/lastattacked = null
- var/attack_log = list( )
var/already_placed = 0.0
var/obj/machinery/machine = null
var/other_mobs = null
diff --git a/code/modules/organs/organ_icon.dm b/code/modules/organs/organ_icon.dm
index 281cd0c016..bc9a47e25f 100644
--- a/code/modules/organs/organ_icon.dm
+++ b/code/modules/organs/organ_icon.dm
@@ -47,7 +47,9 @@ var/global/list/limb_icon_cache = list()
..()
overlays.Cut()
- if(species.has_organ["eyes"])
+ if(!owner || !owner.species)
+ return
+ if(owner.species.has_organ["eyes"])
var/obj/item/organ/eyes/eyes = owner.internal_organs_by_name["eyes"]
if(species.eyes)
var/icon/eyes_icon = new/icon('icons/mob/human_face.dmi', species.eyes)
diff --git a/code/modules/projectiles/gun.dm b/code/modules/projectiles/gun.dm
index 9e57640963..3f791e8e9f 100644
--- a/code/modules/projectiles/gun.dm
+++ b/code/modules/projectiles/gun.dm
@@ -206,6 +206,9 @@
if(user.client) user.client.move_delay = world.time + _move_delay
next_fire_time = world.time + _fire_delay
+ if(muzzle_flash)
+ set_light(0)
+
//obtains the next projectile to fire
/obj/item/weapon/gun/proc/consume_next_projectile()
return null
@@ -247,10 +250,7 @@
)
if(muzzle_flash)
- var/turf/T_user = get_turf(user)
- var/turf/T_target = get_turf(target)
- var/obj/effect/effect/smoke/illumination/I = new /obj/effect/effect/smoke/illumination(get_step(T_user, get_dir(T_user,T_target)), brightness=muzzle_flash, lifetime=8)
- I.alpha = 0
+ set_light(muzzle_flash)
if(recoil)
spawn()
diff --git a/code/modules/projectiles/guns/launcher/syringe_gun.dm b/code/modules/projectiles/guns/launcher/syringe_gun.dm
index 5dac7d4c9c..8acbcce8b2 100644
--- a/code/modules/projectiles/guns/launcher/syringe_gun.dm
+++ b/code/modules/projectiles/guns/launcher/syringe_gun.dm
@@ -50,9 +50,11 @@
if(speed >= 10 && isliving(hit_atom))
var/mob/living/L = hit_atom
//unfortuately we don't know where the dart will actually hit, since that's done by the parent.
- if(L.can_inject())
- if(syringe.reagents)
- syringe.reagents.trans_to_mob(L, 15, CHEM_BLOOD)
+ if(L.can_inject() && syringe.reagents)
+ var/reagent_log = syringe.reagents.get_reagents()
+ syringe.reagents.trans_to_mob(L, 15, CHEM_BLOOD)
+ admin_inject_log(thrower, L, src, reagent_log, 15, violent=1)
+
syringe.break_syringe(iscarbon(hit_atom)? hit_atom : null)
syringe.update_icon()
diff --git a/code/modules/reagents/Chemistry-Holder.dm b/code/modules/reagents/Chemistry-Holder.dm
index 84c8affc94..f785408392 100644
--- a/code/modules/reagents/Chemistry-Holder.dm
+++ b/code/modules/reagents/Chemistry-Holder.dm
@@ -218,12 +218,10 @@
return 0
/datum/reagents/proc/get_reagents()
- var/res = ""
+ . = list()
for(var/datum/reagent/current in reagent_list)
- if (res != "") res += ","
- res += "[current.id]([current.volume])"
-
- return res
+ . += "[current.id] ([current.volume])"
+ return english_list(., "EMPTY", "", ", ", ", ")
/* Holder-to-holder and similar procs */
diff --git a/code/modules/supermatter/supermatter.dm b/code/modules/supermatter/supermatter.dm
index c08f85b298..6adda4b4b6 100644
--- a/code/modules/supermatter/supermatter.dm
+++ b/code/modules/supermatter/supermatter.dm
@@ -103,7 +103,8 @@
grav_pulling = 1
exploded = 1
for(var/mob/living/mob in living_mob_list)
- if(loc.z == mob.loc.z)
+ var/turf/T = get_turf(mob)
+ if(T && (loc.z == T.z))
if(istype(mob, /mob/living/carbon/human))
//Hilariously enough, running into a closet should make you get hit the hardest.
var/mob/living/carbon/human/H = mob