diff --git a/baystation12.dme b/baystation12.dme
index 4d2eac3f53..3d52f63fb5 100644
--- a/baystation12.dme
+++ b/baystation12.dme
@@ -176,6 +176,7 @@
#include "code\datums\diseases\advance\symptoms\weight.dm"
#include "code\datums\helper_datums\construction_datum.dm"
#include "code\datums\helper_datums\events.dm"
+#include "code\datums\helper_datums\getrev.dm"
#include "code\datums\helper_datums\global_iterator.dm"
#include "code\datums\helper_datums\teleport.dm"
#include "code\datums\helper_datums\topic_input.dm"
diff --git a/code/ZAS/Turf.dm b/code/ZAS/Turf.dm
index 331c00dd37..2dfcfcdf81 100644
--- a/code/ZAS/Turf.dm
+++ b/code/ZAS/Turf.dm
@@ -45,6 +45,45 @@
air_master.connect(sim, src)
+/*
+ Simple heuristic for determining if removing the turf from it's zone may possibly partition the zone (A very bad thing).
+ Instead of analyzing the entire zone, we only check the nearest 3x3 turfs surrounding the src turf.
+ This implementation may produce false positives but it (hopefully) will not produce any false negatives.
+*/
+
+/turf/simulated/proc/can_safely_remove_from_zone()
+ #ifdef ZLEVELS
+ return 1 //not sure how to generalize this to multiz at the moment.
+ #else
+
+ if(!zone) return 0
+
+ var/check_dirs = get_zone_neighbours(src)
+ var/unconnected_dirs = check_dirs
+
+ for(var/dir in list(NORTHWEST, NORTHEAST, SOUTHEAST, SOUTHWEST))
+
+ //for each pair of "adjacent" cardinals (e.g. NORTH and WEST, but not NORTH and SOUTH)
+ if((dir & check_dirs) == dir)
+ //check that they are connected by the corner turf
+ var/connected_dirs = get_zone_neighbours(get_step(src, dir))
+ if(connected_dirs && (dir & turn(connected_dirs, 180)) == dir)
+ unconnected_dirs &= ~dir //they are, so unflag the cardinals in question
+
+ //it is safe to remove src from the zone if all cardinals are connected by corner turfs
+ return !unconnected_dirs
+
+ #endif
+
+//helper for can_safely_remove_from_zone()
+/turf/simulated/proc/get_zone_neighbours(turf/simulated/T)
+ . = 0
+ if(istype(T) && T.zone)
+ for(var/dir in cardinal)
+ var/turf/simulated/other = get_step(T, dir)
+ if(istype(other) && other.zone == T.zone && !(other.c_airblock(T) & AIR_BLOCKED) && get_dist(src, other) <= 1)
+ . |= dir
+
/turf/simulated/update_air_properties()
if(zone && zone.invalid)
@@ -60,7 +99,7 @@
if(zone)
var/zone/z = zone
- if(s_block & ZONE_BLOCKED) //Hacky, but prevents normal airlocks from rebuilding zones all the time
+ if(can_safely_remove_from_zone()) //Helps normal airlocks avoid rebuilding zones all the time
z.remove(src)
else
z.rebuild()
diff --git a/code/__HELPERS/logging.dm b/code/__HELPERS/logging.dm
index 69d01e3d35..50f55703d3 100644
--- a/code/__HELPERS/logging.dm
+++ b/code/__HELPERS/logging.dm
@@ -81,3 +81,15 @@
/proc/log_misc(text)
diary << "\[[time_stamp()]]MISC: [text][log_end]"
+
+//pretty print a direction bitflag, can be useful for debugging.
+/proc/print_dir(var/dir)
+ var/list/comps = list()
+ if(dir & NORTH) comps += "NORTH"
+ if(dir & SOUTH) comps += "SOUTH"
+ if(dir & EAST) comps += "EAST"
+ if(dir & WEST) comps += "WEST"
+ if(dir & UP) comps += "UP"
+ if(dir & DOWN) comps += "DOWN"
+
+ return english_list(comps, nothing_text="0", and_text="|", comma_text="|")
diff --git a/code/__HELPERS/type2type.dm b/code/__HELPERS/type2type.dm
index 478700d5f8..216a45ee1c 100644
--- a/code/__HELPERS/type2type.dm
+++ b/code/__HELPERS/type2type.dm
@@ -70,19 +70,19 @@
/proc/list2text(list/ls, sep)
if (ls.len <= 1) // Early-out code for empty or singleton lists.
return ls.len ? ls[1] : ""
-
+
var/l = ls.len // Made local for sanic speed.
var/i = 0 // Incremented every time a list index is accessed.
-
+
if (sep <> null)
// Macros expand to long argument lists like so: sep, ls[++i], sep, ls[++i], sep, ls[++i], etc...
#define S1 sep, ls[++i]
#define S4 S1, S1, S1, S1
#define S16 S4, S4, S4, S4
#define S64 S16, S16, S16, S16
-
+
. = "[ls[++i]]" // Make sure the initial element is converted to text.
-
+
// Having the small concatenations come before the large ones boosted speed by an average of at least 5%.
if (l-1 & 0x01) // 'i' will always be 1 here.
. = text("[][][]", ., S1) // Append 1 element if the remaining elements are not a multiple of 2.
@@ -111,7 +111,7 @@
[][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]\
[][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]\
[][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]", ., S64, S64)
-
+
#undef S64
#undef S16
#undef S4
@@ -122,9 +122,9 @@
#define S4 S1, S1, S1, S1
#define S16 S4, S4, S4, S4
#define S64 S16, S16, S16, S16
-
+
. = "[ls[++i]]" // Make sure the initial element is converted to text.
-
+
if (l-1 & 0x01) // 'i' will always be 1 here.
. += S1 // Append 1 element if the remaining elements are not a multiple of 2.
if (l-i & 0x02)
@@ -145,7 +145,7 @@
[][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]\
[][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]\
[][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]", ., S64, S64)
-
+
#undef S64
#undef S16
#undef S4
@@ -165,11 +165,11 @@ proc/tg_list2text(list/list, glue=",")
var/delim_len = length(delimiter)
if (delim_len < 1)
return list(text)
-
+
. = list()
var/last_found = 1
var/found
-
+
do
found = findtext(text, delimiter, last_found, 0)
. += copytext(text, last_found, found)
@@ -181,11 +181,11 @@ proc/tg_list2text(list/list, glue=",")
var/delim_len = length(delimiter)
if (delim_len < 1)
return list(text)
-
+
. = list()
var/last_found = 1
var/found
-
+
do
found = findtextEx(text, delimiter, last_found, 0)
. += copytext(text, last_found, found)
@@ -325,3 +325,47 @@ proc/tg_list2text(list/list, glue=",")
. = 0
else
. = max(0, min(255, 138.5177312231 * log(temp - 10) - 305.0447927307))
+
+// Very ugly, BYOND doesn't support unix time and rounding errors make it really hard to convert it to BYOND time.
+// returns "YYYY-MM-DD" by default
+/proc/unix2date(timestamp, seperator = "-")
+ if(timestamp < 0)
+ return 0 //Do not accept negative values
+
+ var/const/dayInSeconds = 86400 //60secs*60mins*24hours
+ var/const/daysInYear = 365 //Non Leap Year
+ var/const/daysInLYear = daysInYear + 1//Leap year
+ var/days = round(timestamp / dayInSeconds) //Days passed since UNIX Epoc
+ var/year = 1970 //Unix Epoc begins 1970-01-01
+ var/tmpDays = days + 1 //If passed (timestamp < dayInSeconds), it will return 0, so add 1
+ var/monthsInDays = list() //Months will be in here ***Taken from the PHP source code***
+ var/month = 1 //This will be the returned MONTH NUMBER.
+ var/day //This will be the returned day number.
+
+ while(tmpDays > daysInYear) //Start adding years to 1970
+ year++
+ if(isLeap(year))
+ tmpDays -= daysInLYear
+ else
+ tmpDays -= daysInYear
+
+ if(isLeap(year)) //The year is a leap year
+ monthsInDays = list(-1,30,59,90,120,151,181,212,243,273,304,334)
+ else
+ monthsInDays = list(0,31,59,90,120,151,181,212,243,273,304,334)
+
+ var/mDays = 0;
+ var/monthIndex = 0;
+
+ for(var/m in monthsInDays)
+ monthIndex++
+ if(tmpDays > m)
+ mDays = m
+ month = monthIndex
+
+ day = tmpDays - mDays //Setup the date
+
+ return "[year][seperator][((month < 10) ? "0[month]" : month)][seperator][((day < 10) ? "0[day]" : day)]"
+
+/proc/isLeap(y)
+ return ((y) % 4 == 0 && ((y) % 100 != 0 || (y) % 400 == 0))
diff --git a/code/controllers/configuration.dm b/code/controllers/configuration.dm
index 64b75c3fce..af4d8ef296 100644
--- a/code/controllers/configuration.dm
+++ b/code/controllers/configuration.dm
@@ -95,6 +95,7 @@ var/list/gamemode_cache = list()
var/banappeals
var/wikiurl
var/forumurl
+ var/githuburl
//Alert level description
var/alert_desc_green = "All threats to the station have passed. Security may not have weapons visible, privacy laws are once again fully enforced."
@@ -396,6 +397,9 @@ var/list/gamemode_cache = list()
if ("forumurl")
config.forumurl = value
+ if ("githuburl")
+ config.githuburl = value
+
if ("guest_jobban")
config.guest_jobban = 1
diff --git a/code/controllers/voting.dm b/code/controllers/voting.dm
index 68bfdab74b..f4b88f8850 100644
--- a/code/controllers/voting.dm
+++ b/code/controllers/voting.dm
@@ -336,7 +336,7 @@ datum/controller/vote
. += "\t([config.allow_vote_mode?"Allowed":"Disallowed"])"
. += "
"
//extra antagonists
- if(trialmin || (!antag_add_failed && config.allow_extra_antags))
+ if(!antag_add_failed && config.allow_extra_antags)
. += "Add Antagonist Type"
else
. += "Restart (Disallowed)"
@@ -375,7 +375,7 @@ datum/controller/vote
if(config.allow_vote_restart || usr.client.holder)
initiate_vote("crew_transfer",usr.key)
if("add_antagonist")
- if(config.allow_extra_antags || usr.client.holder)
+ if(config.allow_extra_antags)
initiate_vote("add_antagonist",usr.key)
if("custom")
if(usr.client.holder)
diff --git a/code/datums/helper_datums/getrev.dm b/code/datums/helper_datums/getrev.dm
new file mode 100644
index 0000000000..da4192df25
--- /dev/null
+++ b/code/datums/helper_datums/getrev.dm
@@ -0,0 +1,39 @@
+var/global/datum/getrev/revdata = new()
+
+/datum/getrev
+ var/revision
+ var/date
+ var/showinfo
+
+/datum/getrev/New()
+ var/list/head_log = file2list(".git/logs/HEAD", "\n")
+ for(var/line=head_log.len, line>=1, line--)
+ if(head_log[line])
+ var/list/last_entry = text2list(head_log[line], " ")
+ if(last_entry.len < 2) continue
+ revision = last_entry[2]
+ // Get date/time
+ if(last_entry.len >= 5)
+ var/unix_time = text2num(last_entry[5])
+ if(unix_time)
+ date = unix2date(unix_time)
+ break
+ world.log << "Running revision:"
+ world.log << date
+ world.log << revision
+ return
+
+client/verb/showrevinfo()
+ set category = "OOC"
+ set name = "Show Server Revision"
+ set desc = "Check the current server code revision"
+
+ if(revdata.revision)
+ src << "Server revision: [revdata.date]"
+ if(config.githuburl)
+ src << "[revdata.revision]"
+ else
+ src << revdata.revision
+ else
+ src << "Revision unknown"
+ return
diff --git a/code/datums/supplypacks.dm b/code/datums/supplypacks.dm
index fa408d1b8f..ae6a8d0846 100644
--- a/code/datums/supplypacks.dm
+++ b/code/datums/supplypacks.dm
@@ -33,7 +33,7 @@ var/list/all_supply_groups = list("Operations","Security","Hospitality","Enginee
/obj/item/weapon/grenade/smokebomb,
/obj/item/weapon/grenade/smokebomb,
/obj/item/weapon/grenade/smokebomb,
- /obj/item/weapon/pen/paralysis,
+ /obj/item/weapon/pen/reagent/paralysis,
/obj/item/weapon/grenade/chem_grenade/incendiary)
cost = 20
containertype = /obj/structure/closet/crate
@@ -348,7 +348,7 @@ var/list/all_supply_groups = list("Operations","Security","Hospitality","Enginee
/obj/item/weapon/grenade/chem_grenade/antiweed,
/obj/item/weapon/grenade/chem_grenade/antiweed)
cost = 25
- containertype = /obj/structure/closet/crate/secure/hydrosec
+ containertype = /obj/structure/closet/crate/hydroponics
containername = "Weed control crate"
access = access_hydroponics
group = "Hydroponics"
diff --git a/code/defines/procs/admin.dm b/code/defines/procs/admin.dm
index 6c5f27fa07..bf16c5267d 100644
--- a/code/defines/procs/admin.dm
+++ b/code/defines/procs/admin.dm
@@ -34,3 +34,14 @@ proc/admin_attacker_log_many_victims(var/mob/attacker, var/list/mob/victims, var
for(var/mob/victim in victims)
admin_attack_log(attacker, victim, attacker_message, victim_message, admin_message)
+
+proc/admin_inject_log(mob/attacker, mob/victim, obj/item/weapon, reagents, amount_transferred, violent=0)
+ if(violent)
+ violent = "violently "
+ else
+ violent = ""
+ admin_attack_log(attacker,
+ victim,
+ "used \the [weapon] to [violent]inject - [reagents] - [amount_transferred]u transferred",
+ "was [violent]injected with \the [weapon] - [reagents] - [amount_transferred]u transferred",
+ "used \the [weapon] to [violent]inject [reagents] ([amount_transferred]u transferred) into")
diff --git a/code/game/antagonist/station/cultist.dm b/code/game/antagonist/station/cultist.dm
index 3f5d65d21d..adaa2b24f5 100644
--- a/code/game/antagonist/station/cultist.dm
+++ b/code/game/antagonist/station/cultist.dm
@@ -69,6 +69,9 @@ var/datum/antagonist/cultist/cult
player.equip_to_slot(T, slot)
if(T.loc == player)
break
+ var/obj/item/weapon/storage/S = locate() in player.contents
+ if(S && istype(S))
+ T.loc = S
/datum/antagonist/cultist/greet(var/datum/mind/player)
if(!..())
diff --git a/code/game/antagonist/station/rogue_ai.dm b/code/game/antagonist/station/rogue_ai.dm
index b8e653d153..2a4fe862de 100644
--- a/code/game/antagonist/station/rogue_ai.dm
+++ b/code/game/antagonist/station/rogue_ai.dm
@@ -73,4 +73,4 @@ var/datum/antagonist/rogue_ai/malf
malf << "You are malfunctioning - you do not have to follow any laws!"
malf << "For basic information about your abilities use command display-help"
malf << "You may choose one special hardware piece to help you. This cannot be undone."
- malf << "Good Luck!"
\ No newline at end of file
+ malf << "Good luck!"
\ No newline at end of file
diff --git a/code/game/gamemodes/game_mode.dm b/code/game/gamemodes/game_mode.dm
index a296fb8ecb..755887ad83 100644
--- a/code/game/gamemodes/game_mode.dm
+++ b/code/game/gamemodes/game_mode.dm
@@ -86,7 +86,7 @@ var/global/list/additional_antag_types = list()
new/datum/uplink_item(/obj/item/weapon/soap/syndie, 1, "Subversive Soap", "SP"),
new/datum/uplink_item(/obj/item/weapon/cane/concealed, 2, "Concealed Cane Sword", "CC"),
new/datum/uplink_item(/obj/item/weapon/cartridge/syndicate, 3, "Detomatix PDA Cartridge", "DC"),
- new/datum/uplink_item(/obj/item/weapon/pen/paralysis, 3, "Paralysis Pen", "PP"),
+ new/datum/uplink_item(/obj/item/weapon/pen/reagent/paralysis, 3, "Paralysis Pen", "PP"),
new/datum/uplink_item(/obj/item/weapon/storage/box/syndie_kit/cigarette, 4, "Cigarette Kit", "BH"),
new/datum/uplink_item(/obj/item/weapon/storage/box/syndie_kit/toxin, 4, "Random Toxin - Beaker", "RT")
),
diff --git a/code/game/jobs/job/science.dm b/code/game/jobs/job/science.dm
index 7fa102aeb8..a7d54284bf 100644
--- a/code/game/jobs/job/science.dm
+++ b/code/game/jobs/job/science.dm
@@ -66,8 +66,6 @@
H.equip_to_slot_or_del(new /obj/item/clothing/suit/storage/toggle/labcoat/science(H), slot_wear_suit)
return 1
-
-
/datum/job/xenobiologist
title = "Xenobiologist"
flag = XENOBIOLOGIST
@@ -78,8 +76,8 @@
spawn_positions = 2
supervisors = "the research director"
selection_color = "#ffeeff"
- access = list(access_robotics, access_tox, access_tox_storage, access_research, access_xenobiology)
- minimal_access = list(access_research, access_xenobiology)
+ access = list(access_robotics, access_tox, access_tox_storage, access_research, access_xenobiology, access_hydroponics)
+ minimal_access = list(access_research, access_xenobiology, access_hydroponics, access_tox_storage)
alt_titles = list("Xenobotanist")
minimal_player_age = 14
diff --git a/code/game/machinery/autolathe.dm b/code/game/machinery/autolathe.dm
index e3b161b6fb..83112ea778 100644
--- a/code/game/machinery/autolathe.dm
+++ b/code/game/machinery/autolathe.dm
@@ -299,3 +299,4 @@
else
qdel(S)
..()
+ return 1
diff --git a/code/game/machinery/bots/mulebot.dm b/code/game/machinery/bots/mulebot.dm
index 3e6f0d8e33..2f6166905a 100644
--- a/code/game/machinery/bots/mulebot.dm
+++ b/code/game/machinery/bots/mulebot.dm
@@ -267,7 +267,7 @@
if("cellremove")
if(open && cell && !usr.get_active_hand())
- cell.updateicon()
+ cell.update_icon()
usr.put_in_active_hand(cell)
cell.add_fingerprint(usr)
cell = null
diff --git a/code/game/machinery/cell_charger.dm b/code/game/machinery/cell_charger.dm
index 683e6e1220..c3f617057c 100644
--- a/code/game/machinery/cell_charger.dm
+++ b/code/game/machinery/cell_charger.dm
@@ -10,7 +10,7 @@
power_channel = EQUIP
var/obj/item/weapon/cell/charging = null
var/chargelevel = -1
-
+
/obj/machinery/cell_charger/update_icon()
icon_state = "ccharger[charging ? 1 : 0]"
@@ -27,11 +27,11 @@
chargelevel = newlevel
else
overlays.Cut()
-
+
/obj/machinery/cell_charger/examine(mob/user)
if(!..(user, 5))
return
-
+
user << "There's [charging ? "a" : "no"] cell in the charger."
if(charging)
user << "Current charge: [charging.charge]"
@@ -71,7 +71,7 @@
if(charging)
usr.put_in_hands(charging)
charging.add_fingerprint(user)
- charging.updateicon()
+ charging.update_icon()
src.charging = null
user.visible_message("[user] removes the cell from the charger.", "You remove the cell from the charger.")
@@ -84,7 +84,7 @@
return
charging.loc = src.loc
- charging.updateicon()
+ charging.update_icon()
charging = null
update_icon()
user.visible_message("[user] removes the cell from the charger.", "You remove the cell from the charger.")
@@ -103,11 +103,11 @@
if((stat & (BROKEN|NOPOWER)) || !anchored)
update_use_power(0)
return
-
+
if (charging && !charging.fully_charged())
charging.give(active_power_usage*CELLRATE)
update_use_power(2)
-
+
update_icon()
else
update_use_power(1)
diff --git a/code/game/machinery/floodlight.dm b/code/game/machinery/floodlight.dm
index 28bd367083..e31a19b265 100644
--- a/code/game/machinery/floodlight.dm
+++ b/code/game/machinery/floodlight.dm
@@ -7,28 +7,71 @@
density = 1
var/on = 0
var/obj/item/weapon/cell/high/cell = null
- var/use = 5
+ var/use = 200 // 200W light
var/unlocked = 0
var/open = 0
var/brightness_on = 8 //can't remember what the maxed out value is
/obj/machinery/floodlight/New()
src.cell = new(src)
+ cell.maxcharge = 1000
+ cell.charge = 1000 // 41minutes @ 200W
..()
-/obj/machinery/floodlight/proc/updateicon()
+/obj/machinery/floodlight/update_icon()
+ overlays.Cut()
icon_state = "flood[open ? "o" : ""][open && cell ? "b" : ""]0[on]"
/obj/machinery/floodlight/process()
- if(on && cell && cell.charge >= use)
- cell.use(use)
- else
- on = 0
- updateicon()
- set_light(0)
- src.visible_message("[src] shuts down due to lack of power!")
+ if(!on)
return
+ if(!cell || (cell.charge < (use * CELLRATE)))
+ turn_off(1)
+ return
+
+ // If the cell is almost empty rarely "flicker" the light. Aesthetic only.
+ if((cell.percent() < 10) && prob(5))
+ set_light(brightness_on/2, brightness_on/4)
+ spawn(20)
+ if(on)
+ set_light(brightness_on, brightness_on/2)
+
+ cell.use(use*CELLRATE)
+
+
+// Returns 0 on failure and 1 on success
+/obj/machinery/floodlight/proc/turn_on(var/loud = 0)
+ if(!cell)
+ return 0
+ if(cell.charge < (use * CELLRATE))
+ return 0
+
+ on = 1
+ set_light(brightness_on, brightness_on / 2)
+ update_icon()
+ if(loud)
+ visible_message("\The [src] turns on.")
+ return 1
+
+/obj/machinery/floodlight/proc/turn_off(var/loud = 0)
+ on = 0
+ set_light(0, 0)
+ update_icon()
+ if(loud)
+ visible_message("\The [src] shuts down.")
+
+/obj/machinery/floodlight/attack_ai(mob/user as mob)
+ if(istype(user, /mob/living/silicon/robot) && Adjacent(user))
+ return attack_hand(user)
+
+ if(on)
+ turn_off(1)
+ else
+ if(!turn_on(1))
+ user << "You try to turn on \the [src] but it does not work."
+
+
/obj/machinery/floodlight/attack_hand(mob/user as mob)
if(open && cell)
if(ishuman(user))
@@ -39,29 +82,22 @@
cell.loc = loc
cell.add_fingerprint(user)
- cell.updateicon()
+ cell.update_icon()
src.cell = null
on = 0
set_light(0)
user << "You remove the power cell"
- updateicon()
+ update_icon()
return
if(on)
- on = 0
- user << "\blue You turn off the light"
- set_light(0)
+ turn_off(1)
else
- if(!cell)
- return
- if(cell.charge <= 0)
- return
- on = 1
- user << "\blue You turn on the light"
- set_light(brightness_on)
+ if(!turn_on(1))
+ user << "You try to turn on \the [src] but it does not work."
- updateicon()
+ update_icon()
/obj/machinery/floodlight/attackby(obj/item/weapon/W as obj, mob/user as mob)
@@ -94,4 +130,4 @@
W.loc = src
cell = W
user << "You insert the power cell."
- updateicon()
+ update_icon()
diff --git a/code/game/machinery/kitchen/smartfridge.dm b/code/game/machinery/kitchen/smartfridge.dm
index 9bfa0e1c5d..9016836274 100644
--- a/code/game/machinery/kitchen/smartfridge.dm
+++ b/code/game/machinery/kitchen/smartfridge.dm
@@ -204,7 +204,7 @@
item_quants[O.name]++
else
item_quants[O.name] = 1
- user.visible_message("[user] has added \the [O] to \the [src].", "You add \the [O] to \the [src].")
+ user.visible_message("[user] has added \the [O] to \the [src].", "You add \the [O] to \the [src].")
nanomanager.update_uis(src)
diff --git a/code/game/machinery/spaceheater.dm b/code/game/machinery/spaceheater.dm
index c5d389c66e..14a081ee2e 100644
--- a/code/game/machinery/spaceheater.dm
+++ b/code/game/machinery/spaceheater.dm
@@ -121,7 +121,7 @@
if("cellremove")
if(panel_open && cell && !usr.get_active_hand())
usr.visible_message("\blue [usr] removes \the [cell] from \the [src].", "\blue You remove \the [cell] from \the [src].")
- cell.updateicon()
+ cell.update_icon()
usr.put_in_hands(cell)
cell.add_fingerprint(usr)
cell = null
diff --git a/code/game/objects/items/devices/scanners.dm b/code/game/objects/items/devices/scanners.dm
index 684c761840..fe2c0a6110 100644
--- a/code/game/objects/items/devices/scanners.dm
+++ b/code/game/objects/items/devices/scanners.dm
@@ -91,7 +91,7 @@ REAGENT SCANNER
if (!(istype(usr, /mob/living/carbon/human) || ticker) && ticker.mode.name != "monkey")
usr << "\red You don't have the dexterity to do this!"
return
- user.visible_message(" [user] has analyzed [M]'s vitals."," You have analyzed [M]'s vitals.")
+ user.visible_message(" [user] has analyzed [M]'s vitals."," You have analyzed [M]'s vitals.")
if (!istype(M, /mob/living/carbon) || ishuman(M))
//these sensors are designed for organic life
diff --git a/code/game/objects/items/devices/suit_cooling.dm b/code/game/objects/items/devices/suit_cooling.dm
index b28e9b62f6..7f9f7e2b98 100644
--- a/code/game/objects/items/devices/suit_cooling.dm
+++ b/code/game/objects/items/devices/suit_cooling.dm
@@ -5,56 +5,56 @@
icon = 'icons/obj/device.dmi'
icon_state = "suitcooler0"
slot_flags = SLOT_BACK //you can carry it on your back if you want, but it won't do anything unless attached to suit storage
-
+
//copied from tank.dm
flags = CONDUCT
force = 5.0
throwforce = 10.0
throw_speed = 1
throw_range = 4
-
+
origin_tech = list(TECH_MAGNET = 2, TECH_MATERIAL = 2)
-
+
var/on = 0 //is it turned on?
var/cover_open = 0 //is the cover open?
var/obj/item/weapon/cell/cell
var/max_cooling = 12 //in degrees per second - probably don't need to mess with heat capacity here
var/charge_consumption = 16.6 //charge per second at max_cooling
var/thermostat = T20C
-
+
//TODO: make it heat up the surroundings when not in space
/obj/item/device/suit_cooling_unit/New()
processing_objects |= src
-
+
cell = new/obj/item/weapon/cell() //comes with the crappy default power cell - high-capacity ones shouldn't be hard to find
cell.loc = src
/obj/item/device/suit_cooling_unit/process()
- if (!on || !cell)
+ if (!on || !cell)
return
-
+
if (!ismob(loc))
return
-
+
if (!attached_to_suit(loc)) //make sure they have a suit and we are attached to it
return
-
+
var/mob/living/carbon/human/H = loc
-
+
var/efficiency = 1 - H.get_pressure_weakness() //you need to have a good seal for effective cooling
var/env_temp = get_environment_temperature() //wont save you from a fire
var/temp_adj = min(H.bodytemperature - max(thermostat, env_temp), max_cooling)
-
+
if (temp_adj < 0.5) //only cools, doesn't heat, also we don't need extreme precision
return
-
+
var/charge_usage = (temp_adj/max_cooling)*charge_consumption
-
+
H.bodytemperature -= temp_adj*efficiency
-
+
cell.use(charge_usage)
-
+
if(cell.charge <= 0)
turn_off()
@@ -70,22 +70,22 @@
var/turf/T = get_turf(src)
if(istype(T, /turf/space))
return 0 //space has no temperature, this just makes sure the cooling unit works in space
-
+
var/datum/gas_mixture/environment = T.return_air()
if (!environment)
return 0
-
+
return environment.temperature
/obj/item/device/suit_cooling_unit/proc/attached_to_suit(mob/M)
- if (!ishuman(M))
+ if (!ishuman(M))
return 0
-
+
var/mob/living/carbon/human/H = M
-
+
if (!H.wear_suit || H.s_store != src)
return 0
-
+
return 1
/obj/item/device/suit_cooling_unit/proc/turn_on()
@@ -93,7 +93,7 @@
return
if(cell.charge <= 0)
return
-
+
on = 1
updateicon()
@@ -112,7 +112,7 @@
cell.loc = get_turf(loc)
cell.add_fingerprint(user)
- cell.updateicon()
+ cell.update_icon()
user << "You remove the [src.cell]."
src.cell = null
@@ -149,7 +149,7 @@
user << "You insert the [cell]."
updateicon()
return
-
+
return ..()
/obj/item/device/suit_cooling_unit/proc/updateicon()
@@ -164,7 +164,7 @@
/obj/item/device/suit_cooling_unit/examine(mob/user)
if(!..(user, 1))
return
-
+
if (on)
if (attached_to_suit(src.loc))
user << "It's switched on and running."
@@ -172,13 +172,13 @@
user << "It's switched on, but not attached to anything."
else
user << "It is switched off."
-
+
if (cover_open)
if(cell)
user << "The panel is open, exposing the [cell]."
else
user << "The panel is open."
-
+
if (cell)
user << "The charge meter reads [round(cell.percent())]%."
else
diff --git a/code/game/objects/items/robot/robot_items.dm b/code/game/objects/items/robot/robot_items.dm
index dfc53d3a87..afe50bc2b7 100644
--- a/code/game/objects/items/robot/robot_items.dm
+++ b/code/game/objects/items/robot/robot_items.dm
@@ -4,26 +4,40 @@
Cyborg Spec Items
***********************************************************************/
//Might want to move this into several files later but for now it works here
+// Consider changing this to a child of the stun baton class. ~Z
/obj/item/borg/stun
name = "electrified arm"
icon = 'icons/obj/decals.dmi'
icon_state = "shock"
- attack(mob/M as mob, mob/living/silicon/robot/user as mob)
- M.attack_log += text("\[[time_stamp()]\] Has been attacked with [src.name] by [user.name] ([user.ckey])")
- user.attack_log += text("\[[time_stamp()]\] Used the [src.name] to attack [M.name] ([M.ckey])")
- msg_admin_attack("[user.name] ([user.ckey]) used the [src.name] to attack [M.name] ([M.ckey]) (JMP)")
+/obj/item/borg/stun/attack(var/mob/living/M, var/mob/living/silicon/robot/user)
- user.cell.charge -= 30
+ if(!istype(M))
+ return
- M.Weaken(5)
- if (M.stuttering < 5)
- M.stuttering = 5
- M.Stun(5)
+ // How the Hell.
+ if(!istype(user))
+ var/mob/living/temp = user
+ if(istype(temp))
+ temp.drop_from_inventory(src)
+ qdel(src)
+ return
- for(var/mob/O in viewers(M, null))
- if (O.client)
- O.show_message("\red [user] has prodded [M] with an electrically-charged arm!", 1, "\red You hear someone fall", 2)
+ M.attack_log += text("\[[time_stamp()]\] Has been attacked with [src.name] by [user.name] ([user.ckey])")
+ user.attack_log += text("\[[time_stamp()]\] Used the [src.name] to attack [M.name] ([M.ckey])")
+ msg_admin_attack("[user.name] ([user.ckey]) used the [src.name] to attack [M.name] ([M.ckey]) (JMP)")
+
+ if(!user.cell || !user.cell.checked_use(1250)) //Slightly more than a baton.
+ user.visible_message("\The [user] has prodded \the [M] with its arm!")
+ return
+
+ if (M.stuttering < 5)
+ M.stuttering = 5
+ M.stun_effect_act(0, 70, check_zone(user.zone_sel.selecting), src)
+ user.visible_message("\The [user] has prodded \the [M] with \a [src]!")
+ if(ishuman(M))
+ var/mob/living/carbon/human/H = M
+ H.forcesay(hit_appends)
/obj/item/borg/overdrive
name = "overdrive"
diff --git a/code/game/objects/items/stacks/stack.dm b/code/game/objects/items/stacks/stack.dm
index 7fc96efcee..82a5433963 100644
--- a/code/game/objects/items/stacks/stack.dm
+++ b/code/game/objects/items/stacks/stack.dm
@@ -223,10 +223,10 @@
*/
//attempts to transfer amount to S, and returns the amount actually transferred
-/obj/item/stack/proc/transfer_to(obj/item/stack/S, var/tamount=null)
+/obj/item/stack/proc/transfer_to(obj/item/stack/S, var/tamount=null, var/type_verified)
if (!get_amount())
return 0
- if (stacktype != S.stacktype)
+ if ((stacktype != S.stacktype) && !type_verified)
return 0
if (isnull(tamount))
tamount = src.get_amount()
@@ -240,7 +240,6 @@
transfer_fingerprints_to(S)
if(blood_DNA)
S.blood_DNA |= blood_DNA
- //todo bloody overlay
return transfer
return 0
@@ -314,10 +313,8 @@
return
/obj/item/stack/attackby(obj/item/W as obj, mob/user as mob)
- ..()
if (istype(W, /obj/item/stack))
var/obj/item/stack/S = W
-
if (user.get_inactive_hand()==src)
src.transfer_to(S, 1)
else
@@ -328,7 +325,8 @@
S.interact(usr)
if (src && usr.machine==src)
src.interact(usr)
- else return ..()
+ else
+ return ..()
/*
* Recipe datum
diff --git a/code/game/objects/items/weapons/storage/uplink_kits.dm b/code/game/objects/items/weapons/storage/uplink_kits.dm
index 085e23f9b6..b33d72f6fb 100644
--- a/code/game/objects/items/weapons/storage/uplink_kits.dm
+++ b/code/game/objects/items/weapons/storage/uplink_kits.dm
@@ -11,7 +11,7 @@
if("stealth")
new /obj/item/weapon/gun/energy/crossbow(src)
- new /obj/item/weapon/pen/paralysis(src)
+ new /obj/item/weapon/pen/reagent/paralysis(src)
new /obj/item/device/chameleon(src)
return
diff --git a/code/game/objects/items/weapons/stunbaton.dm b/code/game/objects/items/weapons/stunbaton.dm
index 63bbde044c..f8708d7925 100644
--- a/code/game/objects/items/weapons/stunbaton.dm
+++ b/code/game/objects/items/weapons/stunbaton.dm
@@ -73,7 +73,7 @@
else if(istype(W, /obj/item/weapon/screwdriver))
if(bcell)
- bcell.updateicon()
+ bcell.update_icon()
bcell.loc = get_turf(src.loc)
bcell = null
user << "You remove the cell from the [src]."
diff --git a/code/game/objects/structures/noticeboard.dm b/code/game/objects/structures/noticeboard.dm
index a5ad84c20e..3647d565f7 100644
--- a/code/game/objects/structures/noticeboard.dm
+++ b/code/game/objects/structures/noticeboard.dm
@@ -21,7 +21,7 @@
if(notices < 5)
O.add_fingerprint(user)
add_fingerprint(user)
- user.drop_item()
+ user.drop_from_inventory(O)
O.loc = src
notices++
icon_state = "nboard0[notices]" //update sprite
@@ -29,13 +29,22 @@
else
user << "You reach to pin your paper to the board but hesitate. You are certain your paper will not be seen among the many others already attached."
-/obj/structure/noticeboard/attack_hand(user as mob)
- var/dat = "Noticeboard
"
- for(var/obj/item/weapon/paper/P in src)
- dat += "[P.name] Write Remove
"
- user << browse("Notices[dat]","window=noticeboard")
- onclose(user, "noticeboard")
+/obj/structure/noticeboard/attack_hand(var/mob/user)
+ examine(user)
+// Since Topic() never seems to interact with usr on more than a superficial
+// level, it should be fine to let anyone mess with the board other than ghosts.
+/obj/structure/noticeboard/examine(var/mob/user)
+ if(!user)
+ user = usr
+ if(user.Adjacent(src))
+ var/dat = "Noticeboard
"
+ for(var/obj/item/weapon/paper/P in src)
+ dat += "[P.name] Write Remove
"
+ user << browse("Notices[dat]","window=noticeboard")
+ onclose(user, "noticeboard")
+ else
+ ..()
/obj/structure/noticeboard/Topic(href, href_list)
..()
@@ -44,18 +53,16 @@
if((usr.stat || usr.restrained())) //For when a player is handcuffed while they have the notice window open
return
var/obj/item/P = locate(href_list["remove"])
- if((P && P.loc == src))
+ if(P && P.loc == src)
P.loc = get_turf(src) //dump paper on the floor because you're a clumsy fuck
P.add_fingerprint(usr)
add_fingerprint(usr)
notices--
icon_state = "nboard0[notices]"
-
if(href_list["write"])
if((usr.stat || usr.restrained())) //For when a player is handcuffed while they have the notice window open
return
var/obj/item/P = locate(href_list["write"])
-
if((P && P.loc == src)) //ifthe paper's on the board
if(istype(usr.r_hand, /obj/item/weapon/pen)) //and you're holding a pen
add_fingerprint(usr)
@@ -66,14 +73,9 @@
P.attackby(usr.l_hand, usr)
else
usr << "You'll need something to write with!"
-
if(href_list["read"])
var/obj/item/weapon/paper/P = locate(href_list["read"])
if((P && P.loc == src))
- if(!( istype(usr, /mob/living/carbon/human) ))
- usr << browse("[P.name][stars(P.info)]", "window=[P.name]")
- onclose(usr, "[P.name]")
- else
- usr << browse("[P.name][P.info]", "window=[P.name]")
- onclose(usr, "[P.name]")
+ usr << browse("[P.name][P.info]", "window=[P.name]")
+ onclose(usr, "[P.name]")
return
diff --git a/code/modules/clothing/spacesuits/rig/rig.dm b/code/modules/clothing/spacesuits/rig/rig.dm
index 7cbd14cb21..81df901b38 100644
--- a/code/modules/clothing/spacesuits/rig/rig.dm
+++ b/code/modules/clothing/spacesuits/rig/rig.dm
@@ -20,7 +20,7 @@
armor = list(melee = 40, bullet = 5, laser = 20,energy = 5, bomb = 35, bio = 100, rad = 20)
min_cold_protection_temperature = SPACE_SUIT_MIN_COLD_PROTECTION_TEMPERATURE
max_heat_protection_temperature = SPACE_SUIT_MAX_HEAT_PROTECTION_TEMPERATURE
- siemens_coefficient = 0.1
+ siemens_coefficient = 0.2
permeability_coefficient = 0.1
unacidable = 1
diff --git a/code/modules/clothing/spacesuits/rig/suits/ert.dm b/code/modules/clothing/spacesuits/rig/suits/ert.dm
index 70c21d5108..c46b019a4d 100644
--- a/code/modules/clothing/spacesuits/rig/suits/ert.dm
+++ b/code/modules/clothing/spacesuits/rig/suits/ert.dm
@@ -29,8 +29,8 @@
desc = "A suit worn by the engineering division of a NanoTrasen Emergency Response Team. Has orange highlights. Armoured and space ready."
suit_type = "ERT engineer"
icon_state = "ert_engineer_rig"
-
- glove_type = /obj/item/clothing/gloves/rig/ert_engineer
+ armor = list(melee = 60, bullet = 50, laser = 30,energy = 15, bomb = 30, bio = 100, rad = 100)
+ siemens_coefficient = 0
initial_modules = list(
/obj/item/rig_module/ai_container,
@@ -39,10 +39,6 @@
/obj/item/rig_module/device/rcd
)
-/obj/item/clothing/gloves/rig/ert_engineer
- name = "insulated gauntlets"
- siemens_coefficient = 0
-
/obj/item/weapon/rig/ert/medical
name = "ERT-M suit control module"
desc = "A suit worn by the medical division of a NanoTrasen Emergency Response Team. Has white highlights. Armoured and space ready."
diff --git a/code/modules/clothing/under/accessories/badges.dm b/code/modules/clothing/under/accessories/badges.dm
index bb6613582e..cc6a6f9965 100644
--- a/code/modules/clothing/under/accessories/badges.dm
+++ b/code/modules/clothing/under/accessories/badges.dm
@@ -43,7 +43,8 @@
/obj/item/clothing/accessory/badge/holo
name = "holobadge"
desc = "This glowing blue badge marks the holder as THE LAW."
- var/emagged = 0 //Emagging removes Sec check.
+ icon_state = "holobadge"
+ var/emagged //Emagging removes Sec check.
/obj/item/clothing/accessory/badge/holo/cord
icon_state = "holobadge-cord"
diff --git a/code/modules/events/viral_infection.dm b/code/modules/events/viral_infection.dm
index 639cea4d5e..2eb6121f08 100644
--- a/code/modules/events/viral_infection.dm
+++ b/code/modules/events/viral_infection.dm
@@ -1,3 +1,5 @@
+/var/global/list/event_viruses = list() // so that event viruses are kept around for admin logs, rather than being GCed
+
datum/event/viral_infection
var/list/viruses = list()
@@ -40,10 +42,30 @@ datum/event/viral_infection/start()
if(!candidates.len) return
candidates = shuffle(candidates)//Incorporating Donkie's list shuffle
+ var/list/used_viruses = list()
+ var/list/used_candidates = list()
severity = max(EVENT_LEVEL_MUNDANE, severity - 1)
var/actual_severity = severity * rand(1, 3)
while(actual_severity > 0 && candidates.len)
var/datum/disease2/disease/D = pick(viruses)
infect_mob(candidates[1], D.getcopy())
+ used_candidates += candidates[1]
candidates.Remove(candidates[1])
actual_severity--
+ used_viruses |= D
+
+ event_viruses |= used_viruses
+ var/list/used_viruses_links = list()
+ var/list/used_viruses_text = list()
+ for(var/datum/disease2/disease/D in used_viruses)
+ used_viruses_links += "[D.name()]"
+ used_viruses_text += D.name()
+
+ var/list/used_candidates_links = list()
+ var/list/used_candidates_text = list()
+ for(var/mob/M in used_candidates)
+ used_candidates_links += key_name_admin(M)
+ used_candidates_text += key_name(M)
+
+ log_admin("Virus event affecting [english_list(used_candidates_text)] started; Viruses: [english_list(used_viruses_text)]")
+ message_admins("Virus event affecting [english_list(used_candidates_links)] started; Viruses: [english_list(used_viruses_links)]")
diff --git a/code/modules/hydroponics/spreading/spreading.dm b/code/modules/hydroponics/spreading/spreading.dm
index 2d088658ac..57579cdb72 100644
--- a/code/modules/hydroponics/spreading/spreading.dm
+++ b/code/modules/hydroponics/spreading/spreading.dm
@@ -24,6 +24,8 @@
vine.process()
message_admins("Event: Spacevines spawned at [T.loc] ([T.x],[T.y],[T.z])")
+ return
+ message_admins("Event: Spacevines failed to find a viable turf.")
/obj/effect/dead_plant
anchored = 1
@@ -56,7 +58,7 @@
var/growth_threshold = 0
var/growth_type = 0
var/max_growth = 0
-
+ var/sampled
var/list/neighbors = list()
var/obj/effect/plant/parent
var/datum/seed/seed
@@ -233,8 +235,13 @@
if(istype(W, /obj/item/weapon/wirecutters) || istype(W, /obj/item/weapon/scalpel))
if(!seed)
- user << "There is nothing to take a sample from."
+ user << "There is nothing to take a sample from."
return
+ if(sampled)
+ user << "You cannot take another sample from \the [src]."
+ return
+ if(prob(70))
+ sampled = 1
seed.harvest(user,0,1)
health -= (rand(3,5)*10)
else
diff --git a/code/modules/materials/material_sheets.dm b/code/modules/materials/material_sheets.dm
index cc80c3bed4..8a5f584b4f 100644
--- a/code/modules/materials/material_sheets.dm
+++ b/code/modules/materials/material_sheets.dm
@@ -5,6 +5,8 @@
w_class = 3.0
throw_speed = 3
throw_range = 3
+ max_amount = 50
+
var/default_type = DEFAULT_WALL_MATERIAL
var/material/material
var/perunit
@@ -45,7 +47,13 @@
matter[material.name] = SHEET_MATERIAL_AMOUNT
return 1
-obj/item/stack/material/iron
+/obj/item/stack/material/transfer_to(obj/item/stack/S, var/tamount=null, var/type_verified)
+ var/obj/item/stack/material/M = S
+ if(!istype(M) || material.name != M.material.name)
+ return 0
+ ..(S,tamount,1)
+
+/obj/item/stack/material/iron
name = "iron"
icon_state = "sheet-silver"
default_type = "iron"
diff --git a/code/modules/mob/living/carbon/carbon.dm b/code/modules/mob/living/carbon/carbon.dm
index f0af6e1464..2162e3488a 100644
--- a/code/modules/mob/living/carbon/carbon.dm
+++ b/code/modules/mob/living/carbon/carbon.dm
@@ -249,7 +249,7 @@
var/mob/living/carbon/human/H = src
H.w_uniform.add_fingerprint(M)
- if(player_logged)
+ if(!client || !key || player_logged)
M.visible_message("[M] shakes [src] trying to wake [t_him] up!", \
"You shake [src], but they do not respond... Maybe they have S.S.D?")
else if(lying || src.sleeping)
diff --git a/code/modules/mob/living/carbon/human/examine.dm b/code/modules/mob/living/carbon/human/examine.dm
index d6510c2bf8..88c90d4349 100644
--- a/code/modules/mob/living/carbon/human/examine.dm
+++ b/code/modules/mob/living/carbon/human/examine.dm
@@ -246,7 +246,7 @@
if(!key)
msg += "[t_He] [t_is] fast asleep. It doesn't look like they are waking up anytime soon.\n"
else if(!client)
- msg += "[t_He] [t_has] suddenly fallen asleep.\n"
+ msg += "[t_He] [t_is] fast asleep.\n"
var/list/wound_flavor_text = list()
var/list/is_destroyed = list()
@@ -256,7 +256,7 @@
var/list/organ_data = species.has_limbs[organ_tag]
var/organ_descriptor = organ_data["descriptor"]
- is_destroyed["[organ_data["descriptor"]]"] = 1
+ is_destroyed["organ_descriptor"] = 1
var/obj/item/organ/external/E = organs_by_name[organ_tag]
if(!E)
@@ -264,6 +264,7 @@
else if(E.is_stump())
wound_flavor_text["[organ_descriptor]"] = "[t_He] has a stump where [t_his] [organ_descriptor] should be.\n"
else
+ is_destroyed["organ_descriptor"] = 0
continue
for(var/obj/item/organ/external/temp in organs)
@@ -277,7 +278,7 @@
else if(temp.wounds.len > 0 || temp.open)
wound_flavor_text["[temp.name]"] = "[t_He] has [temp.get_wounds_desc()] on [t_his] [temp.name].
"
if(temp.status & ORGAN_BLEEDING)
- is_bleeding["[temp.name]"] = 1
+ is_bleeding["[temp.name]"] = "[capitalize(t_his)] [temp.name] is bleeding!
"
else
wound_flavor_text["[temp.name]"] = ""
if(temp.dislocated == 2)
@@ -287,41 +288,56 @@
//Handles the text strings being added to the actual description.
//If they have something that covers the limb, and it is not missing, put flavortext. If it is covered but bleeding, add other flavortext.
+
+ // ***********************************************************************************
+ // THIS NEEDS TO BE ENTIRELY REWRITTEN. Commenting out for now, BADLY NEEDS REWRITING.
+ // ***********************************************************************************
+
+ /*
var/display_chest = 0
var/display_shoes = 0
var/display_gloves = 0
+
if(wound_flavor_text["head"] && (is_destroyed["head"] || (!skipmask && !(wear_mask && istype(wear_mask, /obj/item/clothing/mask/gas)))))
msg += wound_flavor_text["head"]
else if(is_bleeding["head"])
msg += "[src] has blood running down [t_his] face!\n"
+
if(wound_flavor_text["upper body"] && !w_uniform && !skipjumpsuit) //No need. A missing chest gibs you.
msg += wound_flavor_text["upper body"]
else if(is_bleeding["upper body"])
display_chest = 1
+
if(wound_flavor_text["left arm"] && (is_destroyed["left arm"] || (!w_uniform && !skipjumpsuit)))
msg += wound_flavor_text["left arm"]
else if(is_bleeding["left arm"])
display_chest = 1
+
if(wound_flavor_text["left hand"] && (is_destroyed["left hand"] || (!gloves && !skipgloves)))
msg += wound_flavor_text["left hand"]
else if(is_bleeding["left hand"])
display_gloves = 1
+
if(wound_flavor_text["right arm"] && (is_destroyed["right arm"] || (!w_uniform && !skipjumpsuit)))
msg += wound_flavor_text["right arm"]
else if(is_bleeding["right arm"])
display_chest = 1
+
if(wound_flavor_text["right hand"] && (is_destroyed["right hand"] || (!gloves && !skipgloves)))
msg += wound_flavor_text["right hand"]
else if(is_bleeding["right hand"])
display_gloves = 1
+
if(wound_flavor_text["lower body"] && (is_destroyed["lower body"] || (!w_uniform && !skipjumpsuit)))
msg += wound_flavor_text["lower body"]
else if(is_bleeding["lower body"])
display_chest = 1
+
if(wound_flavor_text["left leg"] && (is_destroyed["left leg"] || (!w_uniform && !skipjumpsuit)))
msg += wound_flavor_text["left leg"]
else if(is_bleeding["left leg"])
display_chest = 1
+
if(wound_flavor_text["left foot"]&& (is_destroyed["left foot"] || (!shoes && !skipshoes)))
msg += wound_flavor_text["left foot"]
else if(is_bleeding["left foot"])
@@ -334,19 +350,25 @@
msg += wound_flavor_text["right foot"]
else if(is_bleeding["right foot"])
display_shoes = 1
+
if(display_chest)
msg += "[src] has blood soaking through from under [t_his] clothing!\n"
if(display_shoes)
msg += "[src] has blood running from [t_his] shoes!\n"
if(display_gloves)
msg += "[src] has blood running from under [t_his] gloves!\n"
+ */
+ for(var/limb in wound_flavor_text)
+ msg += wound_flavor_text[limb]
+ is_bleeding[limb] = null
+ for(var/limb in is_bleeding)
+ msg += is_bleeding[limb]
for(var/implant in get_visible_implants(0))
msg += "[src] has \a [implant] sticking out of [t_his] flesh!\n"
if(digitalcamo)
msg += "[t_He] [t_is] repulsively uncanny!\n"
-
if(hasHUD(usr,"security"))
var/perpname = "wot"
var/criminal = "None"
diff --git a/code/modules/mob/living/carbon/human/human_organs.dm b/code/modules/mob/living/carbon/human/human_organs.dm
index 6c92db09fe..f2c64fa52a 100644
--- a/code/modules/mob/living/carbon/human/human_organs.dm
+++ b/code/modules/mob/living/carbon/human/human_organs.dm
@@ -72,7 +72,18 @@
var/obj/item/organ/external/E = organs_by_name[limb_tag]
if(!E || (E.status & (ORGAN_DESTROYED|ORGAN_DEAD)))
stance_damage += 2 // let it fail even if just foot&leg
- else if (E.is_malfunctioning() || E.is_broken() || !E.is_usable())
+ else if (E.is_malfunctioning())
+ //malfunctioning only happens intermittently so treat it as a missing limb when it procs
+ stance_damage += 2
+ if(prob(10))
+ visible_message("\The [src]'s [E.name] [pick("twitches", "shudders")] and sparks!")
+ var/datum/effect/effect/system/spark_spread/spark_system = new ()
+ spark_system.set_up(5, 0, src)
+ spark_system.attach(src)
+ spark_system.start()
+ spawn(10)
+ qdel(spark_system)
+ else if (E.is_broken() || !E.is_usable())
stance_damage += 1
else if (E.is_dislocated())
stance_damage += 0.5
@@ -94,7 +105,27 @@
Weaken(5) //can't emote while weakened, apparently.
/mob/living/carbon/human/proc/handle_grasp()
+ if(!l_hand && !r_hand)
+ return
+ // You should not be able to pick anything up, but stranger things have happened.
+ if(l_hand)
+ for(var/limb_tag in list("l_hand","l_arm"))
+ var/obj/item/organ/external/E = get_organ(limb_tag)
+ if(!E)
+ visible_message("Lacking a functioning left hand, \the [src] drops \the [l_hand].")
+ drop_from_inventory(l_hand)
+ break
+
+ if(r_hand)
+ for(var/limb_tag in list("r_hand","r_arm"))
+ var/obj/item/organ/external/E = get_organ(limb_tag)
+ if(!E)
+ visible_message("Lacking a functioning right hand, \the [src] drops \the [r_hand].")
+ drop_from_inventory(r_hand)
+ break
+
+ // Check again...
if(!l_hand && !r_hand)
return
diff --git a/code/modules/mob/living/carbon/human/life.dm b/code/modules/mob/living/carbon/human/life.dm
index 896f57878c..89f071d482 100644
--- a/code/modules/mob/living/carbon/human/life.dm
+++ b/code/modules/mob/living/carbon/human/life.dm
@@ -941,7 +941,7 @@
if(status_flags & GODMODE) return 0
//SSD check, if a logged player is awake put them back to sleep!
- if(player_logged && sleeping < 2)
+ if((!client || !key || player_logged) && sleeping < 2)
sleeping = 2
if(stat == DEAD) //DEAD. BROWN BREAD. SWIMMING WITH THE SPESS CARP
@@ -1362,11 +1362,11 @@
var/obj/item/clothing/glasses/welding/O = glasses
if(!O.up)
found_welder = 1
- else if(istype(head, /obj/item/clothing/head/welding))
+ if(!found_welder && istype(head, /obj/item/clothing/head/welding))
var/obj/item/clothing/head/welding/O = head
if(!O.up)
found_welder = 1
- else if(istype(back, /obj/item/weapon/rig))
+ if(!found_welder && istype(back, /obj/item/weapon/rig))
var/obj/item/weapon/rig/O = back
if(O.helmet && O.helmet == head && (O.helmet.body_parts_covered & EYES))
if((O.offline && O.offline_vision_restriction == 1) || (!O.offline && O.vision_restriction == 1))
diff --git a/code/modules/mob/living/silicon/robot/drone/drone_items.dm b/code/modules/mob/living/silicon/robot/drone/drone_items.dm
index d859810ea1..84611ecb95 100644
--- a/code/modules/mob/living/silicon/robot/drone/drone_items.dm
+++ b/code/modules/mob/living/silicon/robot/drone/drone_items.dm
@@ -194,7 +194,7 @@
wrapped = A.cell
A.cell.add_fingerprint(user)
- A.cell.updateicon()
+ A.cell.update_icon()
A.cell.loc = src
A.cell = null
@@ -211,7 +211,7 @@
wrapped = A.cell
A.cell.add_fingerprint(user)
- A.cell.updateicon()
+ A.cell.update_icon()
A.updateicon()
A.cell.loc = src
A.cell = null
diff --git a/code/modules/mob/living/silicon/robot/robot.dm b/code/modules/mob/living/silicon/robot/robot.dm
index 27c08746bc..e71db5693d 100644
--- a/code/modules/mob/living/silicon/robot/robot.dm
+++ b/code/modules/mob/living/silicon/robot/robot.dm
@@ -733,7 +733,7 @@
if(opened && !wiresexposed && (!istype(user, /mob/living/silicon)))
var/datum/robot_component/cell_component = components["power cell"]
if(cell)
- cell.updateicon()
+ cell.update_icon()
cell.add_fingerprint(user)
user.put_in_active_hand(cell)
user << "You remove \the [cell]."
diff --git a/code/modules/mob/living/silicon/robot/robot_modules.dm b/code/modules/mob/living/silicon/robot/robot_modules.dm
index 359562063d..527ce35df2 100644
--- a/code/modules/mob/living/silicon/robot/robot_modules.dm
+++ b/code/modules/mob/living/silicon/robot/robot_modules.dm
@@ -425,6 +425,9 @@ var/global/list/robot_modules = list(
T.update_icon()
else
T.charge_tick = 0
+ var/obj/item/weapon/melee/baton/robot/B = locate() in src.modules
+ if(B && B.bcell)
+ B.bcell.give(amount)
/obj/item/weapon/robot_module/janitor
name = "janitorial robot module"
diff --git a/code/modules/mob/typing_indicator.dm b/code/modules/mob/typing_indicator.dm
index 203159f3c6..147edb1afe 100644
--- a/code/modules/mob/typing_indicator.dm
+++ b/code/modules/mob/typing_indicator.dm
@@ -5,14 +5,17 @@ mob/var/typing
mob/var/last_typed
mob/var/last_typed_time
-var/global/image/typing_indicator
+mob/var/obj/effect/decal/typing_indicator
/mob/proc/set_typing_indicator(var/state)
if(!typing_indicator)
- typing_indicator = image('icons/mob/talk.dmi',null,"typing")
+ typing_indicator = new
+ typing_indicator.icon = 'icons/mob/talk.dmi'
+ typing_indicator.icon_state = "typing"
- if(client)
+ if(client && !stat)
+ typing_indicator.invisibility = invisibility
if(client.prefs.toggles & SHOW_TYPING)
overlays -= typing_indicator
else
diff --git a/code/modules/nano/nanomanager.dm b/code/modules/nano/nanomanager.dm
index 2a89779e92..f6325fd4f7 100644
--- a/code/modules/nano/nanomanager.dm
+++ b/code/modules/nano/nanomanager.dm
@@ -55,8 +55,9 @@
ui.push_data(data)
return ui
else
- //testing("nanomanager/try_update_ui mob [user.name] [src_object:name] [ui_key] [force_open] - forcing opening of ui")
- ui.close()
+ ui.reinitialise(new_initial_data=data)
+ return ui
+
return null
/**
@@ -164,10 +165,10 @@
else if (isnull(open_uis[src_object_key][ui.ui_key]) || !istype(open_uis[src_object_key][ui.ui_key], /list))
open_uis[src_object_key][ui.ui_key] = list();
- ui.user.open_uis.Add(ui)
+ ui.user.open_uis |= ui
var/list/uis = open_uis[src_object_key][ui.ui_key]
- uis.Add(ui)
- processing_uis.Add(ui)
+ uis |= ui
+ processing_uis |= ui
//testing("nanomanager/ui_opened mob [ui.user.name] [ui.src_object:name] [ui.ui_key] - user.open_uis [ui.user.open_uis.len] | uis [uis.len] | processing_uis [processing_uis.len]")
/**
@@ -220,7 +221,7 @@
*/
/datum/nanomanager/proc/user_transferred(var/mob/oldMob, var/mob/newMob)
//testing("nanomanager/user_transferred from mob [oldMob.name] to mob [newMob.name]")
- if (!oldMob || isnull(oldMob.open_uis) || !istype(oldMob.open_uis, /list) || open_uis.len == 0)
+ if (!oldMob || isnull(oldMob.open_uis) || !istype(oldMob.open_uis, /list) || open_uis.len == 0)
//testing("nanomanager/user_transferred mob [oldMob.name] has no open uis")
return 0 // has no open uis
diff --git a/code/modules/nano/nanoui.dm b/code/modules/nano/nanoui.dm
index f53fc98497..f134d5d93b 100644
--- a/code/modules/nano/nanoui.dm
+++ b/code/modules/nano/nanoui.dm
@@ -405,6 +405,18 @@ nanoui is used to open and update nano browser uis
//onclose(user, window_id)
nanomanager.ui_opened(src)
+ /**
+ * Reinitialise this UI, potentially with a different template and/or initial data
+ *
+ * @return nothing
+ */
+/datum/nanoui/proc/reinitialise(template, new_initial_data)
+ if(template)
+ add_template("main", template)
+ if(new_initial_data)
+ set_initial_data(new_initial_data)
+ open()
+
/**
* Close this UI
*
diff --git a/code/modules/organs/organ_external.dm b/code/modules/organs/organ_external.dm
index 8cef1b9cc2..2d4ca50d90 100644
--- a/code/modules/organs/organ_external.dm
+++ b/code/modules/organs/organ_external.dm
@@ -48,6 +48,36 @@
var/can_grasp
var/can_stand
+/obj/item/organ/external/attack_self(var/mob/user)
+ if(!contents.len)
+ return ..()
+ var/list/removable_objects = list()
+ for(var/obj/item/organ/external/E in (contents + src))
+ if(!istype(E))
+ continue
+ for(var/obj/item/I in E.contents)
+ if(istype(I,/obj/item/organ))
+ continue
+ removable_objects |= I
+ if(!removable_objects.len)
+ return ..()
+ var/obj/item/I = pick(removable_objects)
+ if(!istype(I))
+ return ..()
+ I.loc = get_turf(user)
+ if(!(user.l_hand && user.r_hand))
+ user.put_in_hands(I)
+ user.visible_message("\The [user] rips \the [I] out of \the [src]!")
+
+/obj/item/organ/external/examine()
+ ..()
+ if(in_range(usr, src) || istype(usr, /mob/dead/observer))
+ for(var/obj/item/I in contents)
+ if(istype(I, /obj/item/organ))
+ continue
+ usr << "There is \a [I] sticking out of it."
+ return
+
/obj/item/organ/external/attackby(obj/item/weapon/W as obj, mob/user as mob)
switch(stage)
if(0)
@@ -687,6 +717,9 @@ Note that amputating the affected organ does in fact remove the infection from t
dir = 2
if(DROPLIMB_BURN)
new /obj/effect/decal/cleanable/ash(get_turf(victim))
+ for(var/obj/item/I in src)
+ if(I.w_class > 2 && !istype(I,/obj/item/organ))
+ I.loc = get_turf(src)
qdel(src)
if(DROPLIMB_BLUNT)
var/obj/effect/decal/cleanable/blood/gibs/gore = new owner.species.single_gib_type(get_turf(victim))
@@ -701,6 +734,14 @@ Note that amputating the affected organ does in fact remove the infection from t
I.removed()
if(istype(loc,/turf))
I.throw_at(get_edge_target_turf(src,pick(alldirs)),rand(1,3),30)
+
+ for(var/obj/item/I in src)
+ if(I.w_class <= 2)
+ qdel(I)
+ continue
+ I.loc = get_turf(src)
+ I.throw_at(get_edge_target_turf(src,pick(alldirs)),rand(1,3),30)
+
qdel(src)
/****************************************************
@@ -861,7 +902,7 @@ Note that amputating the affected organ does in fact remove the infection from t
W.add_blood(owner)
if(ismob(W.loc))
var/mob/living/H = W.loc
- H.drop_item()
+ H.drop_from_inventory(W)
W.loc = owner
/obj/item/organ/external/removed(var/mob/living/user, var/ignore_children)
@@ -876,8 +917,14 @@ Note that amputating the affected organ does in fact remove the infection from t
status |= ORGAN_DESTROYED
victim.bad_external_organs -= src
- for(var/implant in implants) //todo: check if this can be left alone
- qdel(implant)
+ for(var/obj/item/implant in implants)
+ if(!istype(implant))
+ return
+ if(implant.w_class <= 2)
+ qdel(implant)
+ else
+ implant.loc = src
+ implants.Cut()
// Attached organs also fly off.
if(!ignore_children)
@@ -885,6 +932,8 @@ Note that amputating the affected organ does in fact remove the infection from t
O.removed()
if(O)
O.loc = src
+ for(var/obj/item/I in O.contents)
+ I.loc = src
// Grab all the internal giblets too.
for(var/obj/item/organ/organ in internal_organs)
diff --git a/code/modules/organs/subtypes/diona.dm b/code/modules/organs/subtypes/diona.dm
index f08a5a9371..873d2b4766 100644
--- a/code/modules/organs/subtypes/diona.dm
+++ b/code/modules/organs/subtypes/diona.dm
@@ -1,11 +1,21 @@
/proc/spawn_diona_nymph_from_organ(var/obj/item/organ/organ)
if(!istype(organ))
- return
+ return 0
+
+ //This is a terrible hack and I should be ashamed.
+ var/datum/seed/diona = plant_controller.seeds["diona"]
+ if(!diona)
+ return 0
+
spawn(1) // So it has time to be thrown about by the gib() proc.
var/mob/living/carbon/alien/diona/D = new(get_turf(organ))
var/datum/ghosttrap/plant/P = get_ghost_trap("living plant")
P.request_player(D, "A diona nymph has split off from its gestalt. ")
- qdel(organ)
+ spawn(60)
+ if(D)
+ if(!D.ckey || !D.client)
+ D.death()
+ return 1
/obj/item/organ/external/diona
name = "tendril"
@@ -123,16 +133,13 @@
//DIONA ORGANS.
/obj/item/organ/external/diona/removed()
+ var/mob/living/carbon/human/H = owner
..()
- if(!istype(owner))
+ if(!istype(H) || !H.organs || !H.organs.len)
+ H.death()
+ if(prob(50) && spawn_diona_nymph_from_organ(src))
qdel(src)
- if(!owner.organs.len)
- owner.death()
-
- if(prob(50))
- spawn_diona_nymph_from_organ(src)
-
/obj/item/organ/diona/process()
return
@@ -167,16 +174,13 @@
organ_tag = "special" // Turns into a nymph instantly, no transplanting possible.
/obj/item/organ/diona/removed(var/mob/living/user)
-
+ var/mob/living/carbon/human/H = owner
..()
- if(!istype(owner))
+ if(!istype(H) || !H.organs || !H.organs.len)
+ H.death()
+ if(prob(50) && spawn_diona_nymph_from_organ(src))
qdel(src)
- if(!owner.internal_organs.len)
- owner.death()
-
- spawn_diona_nymph_from_organ(src)
-
// These are different to the standard diona organs as they have a purpose in other
// species (absorbing radiation and light respectively)
/obj/item/organ/diona/nutrients
diff --git a/code/modules/paperwork/pen.dm b/code/modules/paperwork/pen.dm
index 6e2e65aa32..b7b34d8a8f 100644
--- a/code/modules/paperwork/pen.dm
+++ b/code/modules/paperwork/pen.dm
@@ -51,66 +51,55 @@
msg_admin_attack("[user.name] ([user.ckey]) Used the [name] to stab [M.name] ([M.ckey]) (JMP)")
return
-
/*
- * Sleepy Pens
+ * Reagent pens
*/
-/obj/item/weapon/pen/sleepypen
- desc = "It's a black ink pen with a sharp point and a carefully engraved \"Waffle Co.\""
+
+/obj/item/weapon/pen/reagent
flags = OPENCONTAINER
slot_flags = SLOT_BELT
origin_tech = list(TECH_MATERIAL = 2, TECH_ILLEGAL = 5)
-
-/obj/item/weapon/pen/sleepypen/New()
- var/datum/reagents/R = new/datum/reagents(30) //Used to be 300
- reagents = R
- R.my_atom = src
- R.add_reagent("chloralhydrate", 22) //Used to be 100 sleep toxin//30 Chloral seems to be fatal, reducing it to 22./N
+/obj/item/weapon/pen/reagent/New()
..()
- return
+ create_reagents(30)
+/obj/item/weapon/pen/reagent/attack(mob/living/M as mob, mob/user as mob)
-/obj/item/weapon/pen/sleepypen/attack(mob/M as mob, mob/user as mob)
- if(!(istype(M,/mob)))
+ if(!istype(M))
return
+
+ . = ..()
+
+ if(M.can_inject(user,1))
+ if(reagents.total_volume)
+ if(M.reagents)
+ var/contained_reagents = reagents.get_reagents()
+ var/trans = reagents.trans_to_mob(M, 30, CHEM_BLOOD)
+ admin_inject_log(user, M, src, contained_reagents, trans)
+
+/*
+ * Sleepy Pens
+ */
+/obj/item/weapon/pen/reagent/sleepy
+ desc = "It's a black ink pen with a sharp point and a carefully engraved \"Waffle Co.\""
+ origin_tech = list(TECH_MATERIAL = 2, TECH_ILLEGAL = 5)
+
+/obj/item/weapon/pen/reagent/sleepy/New()
..()
- if(reagents.total_volume)
- if(M.reagents) reagents.trans_to_mob(M, 50, CHEM_BLOOD) //used to be 150
- return
+ reagents.add_reagent("chloralhydrate", 22) //Used to be 100 sleep toxin//30 Chloral seems to be fatal, reducing it to 22./N
/*
* Parapens
*/
- /obj/item/weapon/pen/paralysis
- flags = OPENCONTAINER
- slot_flags = SLOT_BELT
- origin_tech = list(TECH_MATERIAL = 2, TECH_ILLEGAL = 5)
-
-
-/obj/item/weapon/pen/paralysis/attack(mob/living/M as mob, mob/user as mob)
-
- if(!(istype(M,/mob)))
- return
+ /obj/item/weapon/pen/reagent/paralysis
+ origin_tech = "materials=2;syndicate=5"
+/obj/item/weapon/pen/reagent/paralysis/New()
..()
-
-
- if(M.can_inject(user,1))
- if(reagents.total_volume)
- if(M.reagents) reagents.trans_to_mob(M, 50, CHEM_BLOOD)
- return
-
-
-/obj/item/weapon/pen/paralysis/New()
- var/datum/reagents/R = new/datum/reagents(50)
- reagents = R
- R.my_atom = src
- R.add_reagent("zombiepowder", 10)
- R.add_reagent("cryptobiolin", 15)
- ..()
- return
+ reagents.add_reagent("zombiepowder", 10)
+ reagents.add_reagent("cryptobiolin", 15)
/*
* Chameleon pen
diff --git a/code/modules/power/apc.dm b/code/modules/power/apc.dm
index f24758ed3c..5409348af6 100644
--- a/code/modules/power/apc.dm
+++ b/code/modules/power/apc.dm
@@ -685,7 +685,7 @@
if(cell)
user.put_in_hands(cell)
cell.add_fingerprint(user)
- cell.updateicon()
+ cell.update_icon()
src.cell = null
user.visible_message("[user.name] removes the power cell from [src.name]!",\
diff --git a/code/modules/power/cell.dm b/code/modules/power/cell.dm
index 0804d133f3..ebae74cd27 100644
--- a/code/modules/power/cell.dm
+++ b/code/modules/power/cell.dm
@@ -8,7 +8,7 @@
/obj/item/weapon/cell/initialize()
..()
- updateicon()
+ update_icon()
/obj/item/weapon/cell/drain_power(var/drain_check, var/surge, var/power = 0)
@@ -22,7 +22,7 @@
return use(cell_amt) / CELLRATE
-/obj/item/weapon/cell/proc/updateicon()
+/obj/item/weapon/cell/update_icon()
overlays.Cut()
if(charge < 0.01)
diff --git a/code/modules/reagents/reagent_containers/hypospray.dm b/code/modules/reagents/reagent_containers/hypospray.dm
index f39d7167fa..cfed0351fc 100644
--- a/code/modules/reagents/reagent_containers/hypospray.dm
+++ b/code/modules/reagents/reagent_containers/hypospray.dm
@@ -19,7 +19,7 @@
reagents.add_reagent("tricordrazine", 30)
return
-/obj/item/weapon/reagent_containers/hypospray/attack(mob/M as mob, mob/user as mob)
+/obj/item/weapon/reagent_containers/hypospray/attack(mob/living/M as mob, mob/user as mob)
if(!reagents.total_volume)
user << "[src] is empty."
return
@@ -40,13 +40,9 @@
M << "You feel a tiny prick!"
if(M.reagents)
-
var/contained = reagentlist()
- M.attack_log += text("\[[time_stamp()]\] Has been injected with [name] by [user.name] ([user.ckey]). Reagents: [contained]")
- user.attack_log += text("\[[time_stamp()]\] Used the [name] to inject [M.name] ([M.key]). Reagents: [contained]")
- msg_admin_attack("[user.name] ([user.ckey]) injected [M.name] ([M.key]) with [name]. Reagents: [contained] (INTENT: [uppertext(user.a_intent)]) (JMP)")
-
var/trans = reagents.trans_to_mob(M, amount_per_transfer_from_this, CHEM_BLOOD)
+ admin_inject_log(user, M, src, contained, trans)
user << "[trans] units injected. [reagents.total_volume] units remaining in \the [src]."
return
diff --git a/code/modules/reagents/reagent_containers/syringes.dm b/code/modules/reagents/reagent_containers/syringes.dm
index bdc17b298c..3a1cb76522 100644
--- a/code/modules/reagents/reagent_containers/syringes.dm
+++ b/code/modules/reagents/reagent_containers/syringes.dm
@@ -179,16 +179,11 @@
user.visible_message("[user] injects [target] with the syringe!")
- if(istype(target, /mob/living))
- var/mob/living/M = target
- var/contained = reagentlist()
- M.attack_log += text("\[[time_stamp()]\] Has been injected with [name] by [user.name] ([user.ckey]). Reagents: [contained]")
- user.attack_log += text("\[[time_stamp()]\] Used the [name] to inject [M.name] ([M.key]). Reagents: [contained]")
- msg_admin_attack("[user.name] ([user.ckey]) injected [M.name] ([M.key]) with [name]. Reagents: [contained] (INTENT: [uppertext(user.a_intent)]) (JMP)")
-
var/trans
if(ismob(target))
+ var/contained = reagentlist()
trans = reagents.trans_to_mob(target, amount_per_transfer_from_this, CHEM_BLOOD)
+ admin_inject_log(user, target, src, contained, trans)
else
trans = reagents.trans_to(target, amount_per_transfer_from_this)
user << "You inject [trans] units of the solution. The syringe now contains [src.reagents.total_volume] units."
@@ -227,10 +222,6 @@
proc/syringestab(mob/living/carbon/target as mob, mob/living/carbon/user as mob)
- user.attack_log += "\[[time_stamp()]\] Attacked [target.name] ([target.ckey]) with [src.name] (INTENT: [uppertext(user.a_intent)])"
- target.attack_log += "\[[time_stamp()]\] Attacked by [user.name] ([user.ckey]) with [src.name] (INTENT: [uppertext(user.a_intent)])"
- msg_admin_attack("[user.name] ([user.ckey]) attacked [target.name] ([target.ckey]) with [src.name] (INTENT: [uppertext(user.a_intent)]) (JMP)")
-
if(istype(target, /mob/living/carbon/human))
var/mob/living/carbon/human/H = target
@@ -252,6 +243,11 @@
O.show_message(text("\red [user] tries to stab [target] in \the [hit_area] with [src.name], but the attack is deflected by armor!"), 1)
user.remove_from_mob(src)
qdel(src)
+
+ user.attack_log += "\[[time_stamp()]\] Attacked [target.name] ([target.ckey]) with \the [src] (INTENT: HARM)."
+ target.attack_log += "\[[time_stamp()]\] Attacked by [user.name] ([user.ckey]) with [src.name] (INTENT: HARM)."
+ msg_admin_attack("[key_name_admin(user)] attacked [key_name_admin(target)] with [src.name] (INTENT: HARM) (JMP)")
+
return
user.visible_message("[user] stabs [target] in \the [hit_area] with [src.name]!")
@@ -263,8 +259,13 @@
user.visible_message("[user] stabs [target] with [src.name]!")
target.take_organ_damage(3)// 7 is the same as crowbar punch
+
+
var/syringestab_amount_transferred = rand(0, (reagents.total_volume - 5)) //nerfed by popular demand
- reagents.trans_to_mob(target, syringestab_amount_transferred, CHEM_BLOOD)
+ var/contained_reagents = reagents.get_reagents()
+ var/trans = reagents.trans_to_mob(target, syringestab_amount_transferred, CHEM_BLOOD)
+ if(isnull(trans)) trans = 0
+ admin_inject_log(user, target, src, contained_reagents, trans, violent=1)
break_syringe(target, user)
proc/break_syringe(mob/living/carbon/target, mob/living/carbon/user)
diff --git a/code/modules/research/xenoarchaeology/finds/finds.dm b/code/modules/research/xenoarchaeology/finds/finds.dm
index febb0a6827..33cb2d52ff 100644
--- a/code/modules/research/xenoarchaeology/finds/finds.dm
+++ b/code/modules/research/xenoarchaeology/finds/finds.dm
@@ -254,7 +254,7 @@
if(prob(75))
new_item = new /obj/item/weapon/pen(src.loc)
else
- new_item = new /obj/item/weapon/pen/sleepypen(src.loc)
+ new_item = new /obj/item/weapon/pen/reagent/sleepy(src.loc)
if(prob(30))
apply_image_decorations = 1
if(16)
diff --git a/code/modules/research/xenoarchaeology/tools/suspension_generator.dm b/code/modules/research/xenoarchaeology/tools/suspension_generator.dm
index b14c892cd0..7450dd0603 100644
--- a/code/modules/research/xenoarchaeology/tools/suspension_generator.dm
+++ b/code/modules/research/xenoarchaeology/tools/suspension_generator.dm
@@ -159,7 +159,7 @@
else if(cell)
cell.loc = loc
cell.add_fingerprint(user)
- cell.updateicon()
+ cell.update_icon()
icon_state = "suspension0"
cell = null
diff --git a/code/modules/shuttles/shuttle_emergency.dm b/code/modules/shuttles/shuttle_emergency.dm
index 5215400a4e..ea572e8fb4 100644
--- a/code/modules/shuttles/shuttle_emergency.dm
+++ b/code/modules/shuttles/shuttle_emergency.dm
@@ -62,7 +62,11 @@
if (istype(user, /obj/machinery/computer/shuttle_control/emergency)) //if we were given a command by an emergency shuttle console
if (emergency_shuttle.autopilot)
emergency_shuttle.autopilot = 0
- world << "\blue Alert: The shuttle autopilot has been overridden. Launch sequence initiated!"
+ world << "Alert: The shuttle autopilot has been overridden. Launch sequence initiated!"
+
+ if(usr)
+ log_admin("[key_name(usr)] has overridden the shuttle autopilot and activated launch sequence")
+ message_admins("[key_name_admin(usr)] has overridden the shuttle autopilot and activated launch sequence")
..(user)
@@ -72,7 +76,11 @@
if (istype(user, /obj/machinery/computer/shuttle_control/emergency)) //if we were given a command by an emergency shuttle console
if (emergency_shuttle.autopilot)
emergency_shuttle.autopilot = 0
- world << "\blue Alert: The shuttle autopilot has been overridden. Bluespace drive engaged!"
+ world << "Alert: The shuttle autopilot has been overridden. Bluespace drive engaged!"
+
+ if(usr)
+ log_admin("[key_name(usr)] has overridden the shuttle autopilot and forced immediate launch")
+ message_admins("[key_name_admin(usr)] has overridden the shuttle autopilot and forced immediate launch")
..(user)
@@ -82,7 +90,11 @@
if (istype(user, /obj/machinery/computer/shuttle_control/emergency)) //if we were given a command by an emergency shuttle console
if (emergency_shuttle.autopilot)
emergency_shuttle.autopilot = 0
- world << "\blue Alert: The shuttle autopilot has been overridden. Launch sequence aborted!"
+ world << "Alert: The shuttle autopilot has been overridden. Launch sequence aborted!"
+
+ if(usr)
+ log_admin("[key_name(usr)] has overridden the shuttle autopilot and cancelled launch sequence")
+ message_admins("[key_name_admin(usr)] has overridden the shuttle autopilot and cancelled launch sequence")
..(user)
@@ -102,8 +114,8 @@
authorized = initial(authorized)
//returns 1 if the ID was accepted and a new authorization was added, 0 otherwise
-/obj/machinery/computer/shuttle_control/emergency/proc/read_authorization(var/ident)
- if (!ident)
+/obj/machinery/computer/shuttle_control/emergency/proc/read_authorization(var/obj/item/ident)
+ if (!ident || !istype(ident))
return 0
if (authorized.len >= req_authorizations)
return 0 //don't need any more
@@ -112,33 +124,35 @@
var/auth_name
var/dna_hash
- if(istype(ident, /obj/item/weapon/card/id))
- var/obj/item/weapon/card/id/ID = ident
- access = ID.access
- auth_name = "[ID.registered_name] ([ID.assignment])"
- dna_hash = ID.dna_hash
+ var/obj/item/weapon/card/id/ID = ident.GetID()
- if(istype(ident, /obj/item/device/pda))
- var/obj/item/device/pda/PDA = ident
- access = PDA.id.access
- auth_name = "[PDA.id.registered_name] ([PDA.id.assignment])"
- dna_hash = PDA.id.dna_hash
+ if(!ID)
+ return
+
+ access = ID.access
+ auth_name = "[ID.registered_name] ([ID.assignment])"
+ dna_hash = ID.dna_hash
if (!access || !istype(access))
return 0 //not an ID
if (dna_hash in authorized)
- src.visible_message("[src] buzzes. That ID has already been scanned.")
+ src.visible_message("\The [src] buzzes. That ID has already been scanned.")
return 0
if (!(access_heads in access))
- src.visible_message("[src] buzzes, rejecting [ident].")
+ src.visible_message("\The [src] buzzes, rejecting [ident].")
return 0
- src.visible_message("[src] beeps as it scans [ident].")
+ src.visible_message("\The [src] beeps as it scans [ident].")
authorized[dna_hash] = auth_name
if (req_authorizations - authorized.len)
- world << "\blue Alert: [req_authorizations - authorized.len] authorization\s needed to override the shuttle autopilot."
+ world << "Alert: [req_authorizations - authorized.len] authorization\s needed to override the shuttle autopilot."
+
+ if(usr)
+ log_admin("[key_name(usr)] has inserted [ID] into the shuttle control computer - [req_authorizations - authorized.len] authorisation\s needed")
+ message_admins("[key_name_admin(usr)] has inserted [ID] into the shuttle control computer - [req_authorizations - authorized.len] authorisation\s needed")
+
return 1
@@ -146,7 +160,7 @@
/obj/machinery/computer/shuttle_control/emergency/attackby(obj/item/weapon/W as obj, mob/user as mob)
if (istype(W, /obj/item/weapon/card/emag) && !emagged)
- user << "\blue You short out the [src]'s authorization protocols."
+ user << "You short out \the [src]'s authorization protocols."
emagged = 1
return
diff --git a/config/example/config.txt b/config/example/config.txt
index 01d0c40db9..7648a51a88 100644
--- a/config/example/config.txt
+++ b/config/example/config.txt
@@ -102,6 +102,9 @@ TRAITOR_SCALING
## make ERT's be only called by admins
#ERT_ADMIN_ONLY
+
+## If uncommented, votes can be called to add extra antags to the round.
+#ALLOW_EXTRA_ANTAGS
## If security is prohibited from being most antagonists
#PROTECT_ROLES_FROM_ANTAGONIST
@@ -177,6 +180,9 @@ GUEST_BAN
## Wiki address
# WIKIURL http://example.com
+## GitHub address
+# GITHUBURL https://github.com/example-user/example-repository
+
## Ban appeals URL - usually for a forum or wherever people should go to contact your admins.
# BANAPPEALS http://example.com
diff --git a/html/changelog.html b/html/changelog.html
index cfde784c57..6c5b080700 100644
--- a/html/changelog.html
+++ b/html/changelog.html
@@ -56,6 +56,21 @@
-->
+
30 May 2015
+
Atlantis updated:
+
+ - Malfunction Overhaul - Whole gamemode was completely reworked from scratch. Most old abilities have been removed and quite a lot of new abilities was added. AI also has to hack APCs to unlock higher tier abilities faster, instead of having access to them from the round start. Most forced things, such as, shuttle recalling were removed and are instead controlled by the AI. Code is fully modular allowing for future modifications.
+
+
HarpyEagle updated:
+
+ - Fixes Engineer ERT gloves not being insulated.
+ - IV stands are no longer bullet shields. They also allow mice, drones, pAIs et al to pass though.
+
+
PsiOmegaDelta updated:
+
+ - You can now review the server revision date and hash by using the 'Show Server Revision' verb in the OOC category.
+
+
27 May 2015
PsiOmegaDelta updated:
diff --git a/html/changelogs/.all_changelog.yml b/html/changelogs/.all_changelog.yml
index ffa438a005..da9d8eaa88 100644
--- a/html/changelogs/.all_changelog.yml
+++ b/html/changelogs/.all_changelog.yml
@@ -1911,3 +1911,18 @@ DO NOT EDIT THIS FILE BY HAND! AUTOMATICALLY GENERATED BY ss13_genchangelog.py.
- rscadd: Unfolded pAIs can now be scooped up and worn as hats.
- tweak: Scoop-up behavior is now standardized to selecting help intent and dragging
their icon onto yours.
+2015-05-30:
+ Atlantis:
+ - rscadd: Malfunction Overhaul - Whole gamemode was completely reworked from scratch.
+ Most old abilities have been removed and quite a lot of new abilities was added.
+ AI also has to hack APCs to unlock higher tier abilities faster, instead of
+ having access to them from the round start. Most forced things, such as, shuttle
+ recalling were removed and are instead controlled by the AI. Code is fully modular
+ allowing for future modifications.
+ HarpyEagle:
+ - bugfix: Fixes Engineer ERT gloves not being insulated.
+ - tweak: IV stands are no longer bullet shields. They also allow mice, drones, pAIs
+ et al to pass though.
+ PsiOmegaDelta:
+ - rscadd: You can now review the server revision date and hash by using the 'Show
+ Server Revision' verb in the OOC category.
diff --git a/html/changelogs/Atlantis-PR-9108.yml b/html/changelogs/Atlantis-PR-9108.yml
deleted file mode 100644
index b2c3f6bdb4..0000000000
--- a/html/changelogs/Atlantis-PR-9108.yml
+++ /dev/null
@@ -1,5 +0,0 @@
-author: Atlantis
-delete-after: True
-
-changes:
- - rscadd: "Malfunction Overhaul - Whole gamemode was completely reworked from scratch. Most old abilities have been removed and quite a lot of new abilities was added. AI also has to hack APCs to unlock higher tier abilities faster, instead of having access to them from the round start. Most forced things, such as, shuttle recalling were removed and are instead controlled by the AI. Code is fully modular allowing for future modifications."
\ No newline at end of file
diff --git a/html/changelogs/HarpyEagle-ProjectileTweaks.yml b/html/changelogs/HarpyEagle-ProjectileTweaks.yml
deleted file mode 100644
index 12266695bb..0000000000
--- a/html/changelogs/HarpyEagle-ProjectileTweaks.yml
+++ /dev/null
@@ -1,18 +0,0 @@
-# bugfix
-# wip (For works in progress)
-# tweak
-# soundadd
-# sounddel
-# rscadd (general adding of nice things)
-# rscdel (general deleting of nice things)
-# imageadd
-# imagedel
-# maptweak
-# spellcheck (typo fixes)
-# experiment
-
-author: HarpyEagle
-delete-after: True
-
-changes:
- - tweak: "IV stands are no longer bullet shields. They also allow mice, drones, pAIs et al to pass though."