diff --git a/code/__defines/ai.dm b/code/__defines/ai.dm
new file mode 100644
index 0000000000..2f7d9db3a0
--- /dev/null
+++ b/code/__defines/ai.dm
@@ -0,0 +1,9 @@
+
+/// Used in ai/manage_processing to indicate that the AI should be dequeued from slow and fast AI processing
+#define AI_NO_PROCESS 0
+
+/// Used in ai/manage_processing to indicate that the AI should be queued for slow AI processing, and for related subsystem checks
+#define AI_PROCESSING (1 << 0)
+
+/// Used in ai/manage_processing to indicate that the AI should be queued for fast AI processing, and for related subsystem checks
+#define AI_FASTPROCESSING (1 << 1)
diff --git a/code/__defines/mobs.dm b/code/__defines/mobs.dm
index 39fd330f8b..589d529bee 100644
--- a/code/__defines/mobs.dm
+++ b/code/__defines/mobs.dm
@@ -442,4 +442,14 @@
#define DEATHGASP_NO_MESSAGE "no message"
-#define RESIST_COOLDOWN 2 SECONDS
\ No newline at end of file
+#define RESIST_COOLDOWN 2 SECONDS
+
+
+/// Used by human/get_visible_gender(user, force) to return PLURAL
+#define VISIBLE_GENDER_FORCE_PLURAL 1
+
+/// Used by human/get_visible_gender(user, force) to return the mob's identifying gender
+#define VISIBLE_GENDER_FORCE_IDENTIFYING 2
+
+/// Used by human/get_visible_gender(user, force) to return the mob's biological gender
+#define VISIBLE_GENDER_FORCE_BIOLOGICAL 3
diff --git a/code/_helpers/global_lists.dm b/code/_helpers/global_lists.dm
index 8b578c760f..d9660d0195 100644
--- a/code/_helpers/global_lists.dm
+++ b/code/_helpers/global_lists.dm
@@ -53,7 +53,7 @@ GLOBAL_LIST_INIT(custom_species_bases, new) // Species that can be used for a Cu
var/datum/category_collection/underwear/global_underwear = new()
//Backpacks
-var/global/list/backbaglist = list("Nothing", "Backpack", "Satchel", "Satchel Alt", "Messenger Bag")
+var/global/list/backbaglist = list("Nothing", "Backpack", "Satchel", "Satchel Alt", "Messenger Bag", "Sports Bag")
var/global/list/pdachoicelist = list("Default", "Slim", "Old", "Rugged", "Holographic", "Wrist-Bound")
var/global/list/exclude_jobs = list(/datum/job/ai,/datum/job/cyborg)
diff --git a/code/_helpers/text.dm b/code/_helpers/text.dm
index 770881e49a..00648bfb2e 100644
--- a/code/_helpers/text.dm
+++ b/code/_helpers/text.dm
@@ -213,23 +213,58 @@
t = replacetext(t, char, repl_chars[char])
return t
-//Adds 'u' number of zeros ahead of the text 't'
-/proc/add_zero(t, u)
- while (length(t) < u)
- t = "0[t]"
- return t
-//Adds 'u' number of spaces ahead of the text 't'
-/proc/add_lspace(t, u)
- while(length(t) < u)
- t = " [t]"
- return t
+/// Returns a string of hexadecimal characters of length size, uppercased if uppercase is truthy
+/proc/random_hex_text(size, uppercase)
+ if (!ISINTEGER(size))
+ return
+ var/list/result = list()
+ for (var/i = size to 1 step -1)
+ result += num2hex(rand(0, 0xF))
+ result = jointext(result, null)
+ if (uppercase)
+ return uppertext(result)
+ return result
-//Adds 'u' number of spaces behind the text 't'
-/proc/add_tspace(t, u)
- while(length(t) < u)
- t = "[t] "
- return t
+
+/// Builds a string of padding repeated until its character count meets or exceeds size
+/proc/generate_padding(size, padding)
+ var/padding_size = length_char(padding)
+ if (!padding_size)
+ return ""
+ var/padding_count = CEILING(size / padding_size, 1)
+ var/list/result = list()
+ for (var/i = padding_count to 1 step -1)
+ result += padding // pow2 strategies could be used here at the cost of complexity
+ return result.Join(null)
+
+
+/// Pads the matter of padding onto the start of text until the result length is size
+/proc/pad_left(text, size, padding)
+ var/text_length = length_char(text)
+ if (text_length >= size)
+ return text
+ if (!text_length)
+ text = ""
+ var/result = "[generate_padding(size - text_length, padding)][text]"
+ var/length_difference = length_char(result) - size
+ if (!length_difference)
+ return result
+ return copytext_char(result, length_difference + 1)
+
+
+/// Pads the matter of padding onto the start of text until the result length is size
+/proc/pad_right(text, size, padding)
+ var/text_length = length_char(text)
+ if (text_length >= size)
+ return text
+ if (!text_length)
+ text = ""
+ var/result = "[text][generate_padding(size - text_length, padding)]"
+ var/length_difference = length_char(result) - size
+ if (!length_difference)
+ return result
+ return copytext_char(result, 1, -length_difference)
//Returns a string with reserved characters and spaces before the first letter removed
/proc/trim_left(text)
diff --git a/code/_helpers/time.dm b/code/_helpers/time.dm
index 0dc857baea..212d17fcc5 100644
--- a/code/_helpers/time.dm
+++ b/code/_helpers/time.dm
@@ -110,8 +110,8 @@ GLOBAL_VAR_INIT(round_start_time, 0)
var/mins = round((mills % 36000) / 600)
var/hours = round(mills / 36000)
- mins = mins < 10 ? add_zero(mins, 1) : mins
- hours = hours < 10 ? add_zero(hours, 1) : hours
+ mins = pad_left("[mins]", 2, "0")
+ hours = pad_left("[hours]", 2, "0")
last_round_duration = "[hours]:[mins]"
next_duration_update = world.time + 1 MINUTES
diff --git a/code/_helpers/turfs.dm b/code/_helpers/turfs.dm
index 109f29a4f9..ad4c343d9c 100644
--- a/code/_helpers/turfs.dm
+++ b/code/_helpers/turfs.dm
@@ -1,10 +1,20 @@
-// Returns the atom sitting on the turf.
-// For example, using this on a disk, which is in a bag, on a mob, will return the mob because it's on the turf.
-/proc/get_atom_on_turf(var/atom/movable/M)
- var/atom/mloc = M
- while(mloc && mloc.loc && !istype(mloc.loc, /turf/))
- mloc = mloc.loc
- return mloc
+/**
+* Returns a best attempt at the least-nested containing movable of subject, or subject.
+* eg, if subject is an item in a bag on a mob in a locker in the world, returns the locker.
+*/
+/proc/get_atom_on_turf(atom/movable/subject)
+ var/atom/parent = subject?.loc
+ if (!parent || !ismovable(subject) || isarea(parent))
+ return subject
+ var/atom/current = subject
+ do
+ parent = current.loc
+ if (isturf(parent))
+ return current
+ current = parent
+ while (current)
+ return subject
+
/proc/iswall(turf/T)
return (istype(T, /turf/simulated/wall) || istype(T, /turf/unsimulated/wall) || istype(T, /turf/simulated/shuttle/wall))
diff --git a/code/_helpers/type2type.dm b/code/_helpers/type2type.dm
index 3e6c3e9854..f1fff0ff74 100644
--- a/code/_helpers/type2type.dm
+++ b/code/_helpers/type2type.dm
@@ -1,55 +1,3 @@
-/*
- * Holds procs designed to change one type of value, into another.
- * Contains:
- * hex2num & num2hex
- * text2list & list2text
- * file2list
- * angle2dir
- * angle2text
- * worldtime2text
- */
-
-// Returns an integer given a hexadecimal number string as input.
-/proc/hex2num(hex)
- if (!istext(hex))
- return
-
- var/num = 0
- var/power = 1
- var/i = length(hex)
-
- while (i)
- var/char = text2ascii(hex, i)
- switch(char)
- if(48) // 0 -- do nothing
- if(49 to 57) num += (char - 48) * power // 1-9
- if(97, 65) num += power * 10 // A
- if(98, 66) num += power * 11 // B
- if(99, 67) num += power * 12 // C
- if(100, 68) num += power * 13 // D
- if(101, 69) num += power * 14 // E
- if(102, 70) num += power * 15 // F
- else
- return
- power *= 16
- i--
- return num
-
-// Returns the hex value of a number given a value assumed to be a base-ten value
-/proc/num2hex(num, padlength)
- var/global/list/hexdigits = list("0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "A", "B", "C", "D", "E", "F")
-
- . = ""
- while(num > 0)
- var/hexdigit = hexdigits[(num & 0xF) + 1]
- . = "[hexdigit][.]"
- num >>= 4 //go to the next half-byte
-
- //pad with zeroes
- var/left = padlength - length(.)
- while (left-- > 0)
- . = "0[.]"
-
/proc/text2numlist(text, delimiter="\n")
var/list/num_list = list()
for(var/x in splittext(text, delimiter))
@@ -151,25 +99,6 @@
if (rights & R_EVENT) . += "[seperator]+EVENT"
return .
-// Converts a hexadecimal color (e.g. #FF0050) to a list of numbers for red, green, and blue (e.g. list(255,0,80) ).
-/proc/hex2rgb(hex)
- // Strips the starting #, in case this is ever supplied without one, so everything doesn't break.
- if(findtext(hex,"#",1,2))
- hex = copytext(hex, 2)
- return list(hex2rgb_r(hex), hex2rgb_g(hex), hex2rgb_b(hex))
-
-// The three procs below require that the '#' part of the hex be stripped, which hex2rgb() does automatically.
-/proc/hex2rgb_r(hex)
- var/hex_to_work_on = copytext(hex,1,3)
- return hex2num(hex_to_work_on)
-
-/proc/hex2rgb_g(hex)
- var/hex_to_work_on = copytext(hex,3,5)
- return hex2num(hex_to_work_on)
-
-/proc/hex2rgb_b(hex)
- var/hex_to_work_on = copytext(hex,5,7)
- return hex2num(hex_to_work_on)
// heat2color functions. Adapted from: http://www.tannerhelland.com/4435/convert-temperature-rgb-algorithm-code/
/proc/heat2color(temp)
diff --git a/code/_helpers/unsorted.dm b/code/_helpers/unsorted.dm
index 9884581036..91bf996be7 100644
--- a/code/_helpers/unsorted.dm
+++ b/code/_helpers/unsorted.dm
@@ -14,30 +14,6 @@
locate(min(CENTER.x+(RADIUS),world.maxx), min(CENTER.y+(RADIUS),world.maxy), CENTER.z) \
)
-//Inverts the colour of an HTML string
-/proc/invertHTML(HTMLstring)
-
- if (!( istext(HTMLstring) ))
- CRASH("Given non-text argument!")
- else
- if (length(HTMLstring) != 7)
- CRASH("Given non-HTML argument!")
- var/textr = copytext(HTMLstring, 2, 4)
- var/textg = copytext(HTMLstring, 4, 6)
- var/textb = copytext(HTMLstring, 6, 8)
- var/r = hex2num(textr)
- var/g = hex2num(textg)
- var/b = hex2num(textb)
- textr = num2hex(255 - r)
- textg = num2hex(255 - g)
- textb = num2hex(255 - b)
- if (length(textr) < 2)
- textr = text("0[]", textr)
- if (length(textg) < 2)
- textr = text("0[]", textg)
- if (length(textb) < 2)
- textr = text("0[]", textb)
- return text("#[][][]", textr, textg, textb)
//Returns the middle-most value
/proc/dd_range(var/low, var/high, var/num)
@@ -1279,7 +1255,7 @@ var/list/WALLITEMS = list(
return colour
/proc/color_square(red, green, blue, hex)
- var/color = hex ? hex : "#[num2hex(red, 2)][num2hex(green, 2)][num2hex(blue, 2)]"
+ var/color = hex || rgb(red, green, blue)
return "___"
var/mob/dview/dview_mob = new
diff --git a/code/_macros.dm b/code/_macros.dm
index d122d9045f..a725086194 100644
--- a/code/_macros.dm
+++ b/code/_macros.dm
@@ -38,6 +38,15 @@
#define random_id(key,min_id,max_id) uniqueness_repository.Generate(/datum/uniqueness_generator/id_random, key, min_id, max_id)
+
+/// Given a hexadeximal text, returns the corresponding integer
+#define hex2num(hex) (text2num(hex, 16) || 0)
+
+
+/// Given an integer number, returns a hexadecimal representation
+#define num2hex(num) num2text(num, 1, 16)
+
+
#define ARGS_DEBUG log_debug("[__FILE__] - [__LINE__]") ; for(var/arg in args) { log_debug("\t[log_info_line(arg)]") }
#define WORLD_ICON_SIZE 32 //Needed for the R-UST port
diff --git a/code/_onclick/hud/_defines.dm b/code/_onclick/hud/_defines.dm
index af1527eed4..806ee7ca54 100644
--- a/code/_onclick/hud/_defines.dm
+++ b/code/_onclick/hud/_defines.dm
@@ -103,6 +103,12 @@
#define ui_alien_fire "EAST-1:28,NORTH-3:25"
#define ui_alien_oxygen "EAST-1:28,NORTH-4:25"
+// Goes above HUD, mid-right
+#define ui_ammo_hud1 "EAST-1:28,CENTER+1:25"
+#define ui_ammo_hud2 "EAST-1:28,CENTER+2:27"
+#define ui_ammo_hud3 "EAST-1:28,CENTER+3:29"
+#define ui_ammo_hud4 "EAST-1:28,CENTER+4:31"
+
//Middle right (status indicators)
#define ui_temp "EAST-1:28,CENTER-2:13"
#define ui_health "EAST-1:28,CENTER-1:15"
diff --git a/code/_onclick/hud/hud.dm b/code/_onclick/hud/hud.dm
index 71e32197ff..a6597f9b13 100644
--- a/code/_onclick/hud/hud.dm
+++ b/code/_onclick/hud/hud.dm
@@ -1,3 +1,4 @@
+#define MAX_AMMO_HUD_POSSIBLE 4 // Cap the amount of HUDs at 4.
/*
The global hud:
Uses the same visual objects for all players.
@@ -182,6 +183,9 @@ var/list/global_huds = list(
var/icon/ui_style
var/ui_color
var/ui_alpha
+
+ // TGMC Ammo HUD Port
+ var/list/obj/screen/ammo_hud_list = list()
var/list/minihuds = list()
@@ -210,6 +214,7 @@ var/list/global_huds = list(
other = null
hotkeybuttons = null
// item_action_list = null // ?
+ QDEL_LIST(ammo_hud_list)
mymob = null
/datum/hud/proc/hidden_inventory_update()
@@ -446,4 +451,37 @@ var/list/global_huds = list(
client.screen += client.void
/mob/new_player/add_click_catcher()
- return
\ No newline at end of file
+ return
+
+/* TGMC Ammo HUD Port
+ * These procs call to screen_objects.dm's respective procs.
+ * All these do is manage the amount of huds on screen and set the HUD.
+*/
+///Add an ammo hud to the user informing of the ammo count of G
+/datum/hud/proc/add_ammo_hud(mob/living/user, obj/item/weapon/gun/G)
+ if(length(ammo_hud_list) >= MAX_AMMO_HUD_POSSIBLE)
+ return
+ var/obj/screen/ammo/ammo_hud = new
+ ammo_hud_list[G] = ammo_hud
+ ammo_hud.screen_loc = ammo_hud.ammo_screen_loc_list[length(ammo_hud_list)]
+ ammo_hud.add_hud(user, G)
+ ammo_hud.update_hud(user, G)
+
+///Remove the ammo hud related to the gun G from the user
+/datum/hud/proc/remove_ammo_hud(mob/living/user, obj/item/weapon/gun/G)
+ var/obj/screen/ammo/ammo_hud = ammo_hud_list[G]
+ if(isnull(ammo_hud))
+ return
+ ammo_hud.remove_hud(user, G)
+ qdel(ammo_hud)
+ ammo_hud_list -= G
+ var/i = 1
+ for(var/key in ammo_hud_list)
+ ammo_hud = ammo_hud_list[key]
+ ammo_hud.screen_loc = ammo_hud.ammo_screen_loc_list[i]
+ i++
+
+///Update the ammo hud related to the gun G
+/datum/hud/proc/update_ammo_hud(mob/living/user, obj/item/weapon/gun/G)
+ var/obj/screen/ammo/ammo_hud = ammo_hud_list[G]
+ ammo_hud?.update_hud(user, G)
\ No newline at end of file
diff --git a/code/_onclick/hud/screen_objects.dm b/code/_onclick/hud/screen_objects.dm
index 2006f53adc..e8bb2bb7f4 100644
--- a/code/_onclick/hud/screen_objects.dm
+++ b/code/_onclick/hud/screen_objects.dm
@@ -833,3 +833,80 @@
icon_state = null
plane = PLANE_HOLOMAP_ICONS
appearance_flags = KEEP_TOGETHER
+
+// Begin TGMC Ammo HUD Port
+/obj/screen/ammo
+ name = "ammo"
+ icon = 'icons/mob/screen_ammo.dmi'
+ icon_state = "ammo"
+ screen_loc = ui_ammo_hud1
+ var/warned = FALSE
+ var/static/list/ammo_screen_loc_list = list(ui_ammo_hud1, ui_ammo_hud2, ui_ammo_hud3 ,ui_ammo_hud4)
+
+/obj/screen/ammo/proc/add_hud(var/mob/living/user, var/obj/item/weapon/gun/G)
+
+ if(!user?.client)
+ return
+
+ if(!G)
+ CRASH("/obj/screen/ammo/proc/add_hud() has been called from [src] without the required param of G")
+
+ if(!G.has_ammo_counter())
+ return
+
+ user.client.screen += src
+
+/obj/screen/ammo/proc/remove_hud(var/mob/living/user)
+ user?.client?.screen -= src
+
+/obj/screen/ammo/proc/update_hud(var/mob/living/user, var/obj/item/weapon/gun/G)
+ if(!user?.client?.screen.Find(src))
+ return
+
+ if(!G || !istype(G) || !G.has_ammo_counter() || !G.get_ammo_type() || isnull(G.get_ammo_count()))
+ remove_hud()
+ return
+
+ var/list/ammo_type = G.get_ammo_type()
+ var/rounds = G.get_ammo_count()
+
+ var/hud_state = ammo_type[1]
+ var/hud_state_empty = ammo_type[2]
+
+ overlays.Cut()
+
+ var/empty = image('icons/mob/screen_ammo.dmi', src, "[hud_state_empty]")
+
+ if(rounds == 0)
+ if(warned)
+ overlays += empty
+ else
+ warned = TRUE
+ var/obj/screen/ammo/F = new /obj/screen/ammo(src)
+ F.icon_state = "frame"
+ user.client.screen += F
+ flick("[hud_state_empty]_flash", F)
+ spawn(20)
+ user.client.screen -= F
+ qdel(F)
+ overlays += empty
+ else
+ warned = FALSE
+ overlays += image('icons/mob/screen_ammo.dmi', src, "[hud_state]")
+
+ rounds = num2text(rounds)
+ //Handle the amount of rounds
+ switch(length(rounds))
+ if(1)
+ overlays += image('icons/mob/screen_ammo.dmi', src, "o[rounds[1]]")
+ if(2)
+ overlays += image('icons/mob/screen_ammo.dmi', src, "o[rounds[2]]")
+ overlays += image('icons/mob/screen_ammo.dmi', src, "t[rounds[1]]")
+ if(3)
+ overlays += image('icons/mob/screen_ammo.dmi', src, "o[rounds[3]]")
+ overlays += image('icons/mob/screen_ammo.dmi', src, "t[rounds[2]]")
+ overlays += image('icons/mob/screen_ammo.dmi', src, "h[rounds[1]]")
+ else //"0" is still length 1 so this means it's over 999
+ overlays += image('icons/mob/screen_ammo.dmi', src, "o9")
+ overlays += image('icons/mob/screen_ammo.dmi', src, "t9")
+ overlays += image('icons/mob/screen_ammo.dmi', src, "h9")
\ No newline at end of file
diff --git a/code/controllers/emergency_shuttle_controller.dm b/code/controllers/emergency_shuttle_controller.dm
index fde8227376..191d4d89f5 100644
--- a/code/controllers/emergency_shuttle_controller.dm
+++ b/code/controllers/emergency_shuttle_controller.dm
@@ -228,14 +228,14 @@ var/global/datum/emergency_shuttle_controller/emergency_shuttle = new
if (online())
if (shuttle.has_arrive_time())
var/timeleft = emergency_shuttle.estimate_arrival_time()
- return "ETA-[(timeleft / 60) % 60]:[add_zero(num2text(timeleft % 60), 2)]"
+ return "ETA-[(timeleft / 60) % 60]:[pad_left(num2text(timeleft % 60), 2, "0")]"
if (waiting_to_leave())
if (shuttle.moving_status == SHUTTLE_WARMUP)
return "Departing..."
var/timeleft = emergency_shuttle.estimate_launch_time()
- return "ETD-[(timeleft / 60) % 60]:[add_zero(num2text(timeleft % 60), 2)]"
+ return "ETD-[(timeleft / 60) % 60]:[pad_left(num2text(timeleft % 60), 2, "0")]"
return ""
/*
diff --git a/code/controllers/globals.dm b/code/controllers/globals.dm
index c92d42d82a..7e088b6449 100644
--- a/code/controllers/globals.dm
+++ b/code/controllers/globals.dm
@@ -43,6 +43,12 @@ GLOBAL_REAL(GLOB, /datum/controller/global_vars)
return FALSE
return ..()
+
+/datum/controller/global_vars/VV_hidden()
+ return list(
+ "vchatdb"
+ )
+
/datum/controller/global_vars/Initialize()
gvars_datum_init_order = list()
gvars_datum_protected_varlist = list(NAMEOF(src, gvars_datum_protected_varlist) = TRUE)
diff --git a/code/controllers/subsystems/ai.dm b/code/controllers/subsystems/ai.dm
index 57bd5cc1ac..46b078cde9 100644
--- a/code/controllers/subsystems/ai.dm
+++ b/code/controllers/subsystems/ai.dm
@@ -1,32 +1,53 @@
SUBSYSTEM_DEF(ai)
name = "AI"
- init_order = INIT_ORDER_AI
- priority = FIRE_PRIORITY_AI
- wait = 2 SECONDS
flags = SS_NO_INIT
runlevels = RUNLEVEL_GAME | RUNLEVEL_POSTGAME
+ priority = FIRE_PRIORITY_AI
+ wait = 2 SECONDS
+
+ /// The list of AI datums to be processed.
+ var/static/tmp/list/queue = list()
+
+ /// The list of AI datums currently being processed.
+ var/static/tmp/list/current = list()
- var/list/processing = list()
- var/list/currentrun = list()
/datum/controller/subsystem/ai/stat_entry(msg_prefix)
var/list/msg = list(msg_prefix)
- msg += "P:[processing.len]"
+ msg += "P:[queue.len]"
..(msg.Join())
+
+/datum/controller/subsystem/ai/Recover()
+ current.Cut()
+
+
/datum/controller/subsystem/ai/fire(resumed, no_mc_tick)
if (!resumed)
- src.currentrun = processing.Copy()
-
- //cache for sanic speed (lists are references anyways)
- var/list/currentrun = src.currentrun
-
- while(currentrun.len)
- var/datum/ai_holder/A = currentrun[currentrun.len]
- --currentrun.len
- if(!A || QDELETED(A) || A.busy) // Doesn't exist or won't exist soon or not doing it this tick
+ current = queue.Copy()
+ var/datum/ai_holder/subject
+ for (var/i = current.len to 1 step -1)
+ subject = current[i]
+ if (QDELETED(subject) || subject.busy)
continue
- A.handle_strategicals()
-
- if(MC_TICK_CHECK)
+ subject.handle_strategicals()
+ if (no_mc_tick)
+ CHECK_TICK
+ else if (MC_TICK_CHECK)
+ current.Cut(i)
return
+ current.Cut()
+
+
+/// Convenience define for safely enqueueing an AI datum for slow processing.
+#define START_AIPROCESSING(DATUM) \
+if (!(DATUM.process_flags & AI_PROCESSING)) {\
+ DATUM.process_flags |= AI_PROCESSING;\
+ SSai.queue += DATUM;\
+}
+
+
+/// Convenience define for safely dequeueing an AI datum from slow processing.
+#define STOP_AIPROCESSING(DATUM) \
+DATUM.process_flags &= ~AI_PROCESSING; \
+SSai.queue -= DATUM;
diff --git a/code/controllers/subsystems/aifast.dm b/code/controllers/subsystems/aifast.dm
index 6ce841855d..d4a70a3853 100644
--- a/code/controllers/subsystems/aifast.dm
+++ b/code/controllers/subsystems/aifast.dm
@@ -1,32 +1,53 @@
SUBSYSTEM_DEF(aifast)
- name = "AI (Fast)"
- init_order = INIT_ORDER_AI_FAST
- priority = FIRE_PRIORITY_AI
- wait = 0.25 SECONDS
+ name = "AI Fast"
flags = SS_NO_INIT
runlevels = RUNLEVEL_GAME | RUNLEVEL_POSTGAME
+ priority = FIRE_PRIORITY_AI
+ wait = 0.25 SECONDS
+
+ /// The list of AI datums to be processed.
+ var/static/tmp/list/queue = list()
+
+ /// The list of AI datums currently being processed.
+ var/static/tmp/list/current = list()
- var/list/processing = list()
- var/list/currentrun = list()
/datum/controller/subsystem/aifast/stat_entry(msg_prefix)
var/list/msg = list(msg_prefix)
- msg += "P:[processing.len]"
+ msg += "P:[queue.len]"
..(msg.Join())
+
+/datum/controller/subsystem/aifast/Recover()
+ current.Cut()
+
+
/datum/controller/subsystem/aifast/fire(resumed, no_mc_tick)
if (!resumed)
- src.currentrun = processing.Copy()
-
- //cache for sanic speed (lists are references anyways)
- var/list/currentrun = src.currentrun
-
- while(currentrun.len)
- var/datum/ai_holder/A = currentrun[currentrun.len]
- --currentrun.len
- if(!A || QDELETED(A) || A.busy) // Doesn't exist or won't exist soon or not doing it this tick
+ current = queue.Copy()
+ var/datum/ai_holder/subject
+ for (var/i = current.len to 1 step -1)
+ subject = current[i]
+ if (QDELETED(subject) || subject.busy)
continue
- A.handle_tactics()
-
- if(MC_TICK_CHECK)
+ subject.handle_tactics()
+ if (no_mc_tick)
+ CHECK_TICK
+ else if (MC_TICK_CHECK)
+ current.Cut(i)
return
+ current.Cut()
+
+
+/// Convenience define for safely enqueueing an AI datum for fast processing.
+#define START_AIFASTPROCESSING(DATUM) \
+if (!(DATUM.process_flags & AI_FASTPROCESSING)) {\
+ DATUM.process_flags |= AI_FASTPROCESSING;\
+ SSaifast.queue += DATUM;\
+}
+
+
+/// Convenience define for safely dequeueing an AI datum from fast processing.
+#define STOP_AIFASTPROCESSING(DATUM) \
+DATUM.process_flags &= ~AI_FASTPROCESSING; \
+SSaifast.queue -= DATUM;
diff --git a/code/datums/datacore.dm b/code/datums/datacore.dm
index 1aaf8d66f3..2d957ecf38 100644
--- a/code/datums/datacore.dm
+++ b/code/datums/datacore.dm
@@ -416,7 +416,8 @@ var/global/list/PDA_Manifest = list()
return
/proc/generate_record_id()
- return add_zero(num2hex(rand(1, 65535)), 4) //no point generating higher numbers because of the limitations of num2hex
+ return "000[random_hex_text(3, TRUE)]"
+
/datum/datacore/proc/CreateGeneralRecord(var/mob/living/carbon/human/H, var/id, var/hidden)
ResetPDAManifest()
@@ -431,7 +432,7 @@ var/global/list/PDA_Manifest = list()
side = icon('html/images/no_image32.png')
if(!id)
- id = text("[]", add_zero(num2hex(rand(1, 65536)), 4))
+ id = generate_record_id()
var/datum/data/record/G = new /datum/data/record()
G.name = "Employee Record #[id]"
G.fields["name"] = "New Record"
diff --git a/code/datums/outfits/jobs/civilian.dm b/code/datums/outfits/jobs/civilian.dm
index 722a3fefb6..49d7efb494 100644
--- a/code/datums/outfits/jobs/civilian.dm
+++ b/code/datums/outfits/jobs/civilian.dm
@@ -54,6 +54,7 @@
backpack = /obj/item/weapon/storage/backpack/hydroponics
satchel_one = /obj/item/weapon/storage/backpack/satchel/hyd
messenger_bag = /obj/item/weapon/storage/backpack/messenger/hyd
+ sports_bag = /obj/item/weapon/storage/backpack/sport/hyd
id_type = /obj/item/weapon/card/id/civilian/botanist
pda_type = /obj/item/device/pda/botanist
diff --git a/code/datums/outfits/jobs/medical.dm b/code/datums/outfits/jobs/medical.dm
index 6622d3b285..dd5cb7fbcb 100644
--- a/code/datums/outfits/jobs/medical.dm
+++ b/code/datums/outfits/jobs/medical.dm
@@ -65,6 +65,7 @@
suit = /obj/item/clothing/suit/storage/toggle/labcoat/chemist
backpack = /obj/item/weapon/storage/backpack/chemistry
satchel_one = /obj/item/weapon/storage/backpack/satchel/chem
+ sports_bag = /obj/item/weapon/storage/backpack/sport/chem
id_type = /obj/item/weapon/card/id/medical/chemist
pda_type = /obj/item/device/pda/chemist
diff --git a/code/datums/outfits/jobs/science.dm b/code/datums/outfits/jobs/science.dm
index 4a6392d61f..fcccfb8f8c 100644
--- a/code/datums/outfits/jobs/science.dm
+++ b/code/datums/outfits/jobs/science.dm
@@ -7,6 +7,7 @@
backpack = /obj/item/weapon/storage/backpack/toxins
satchel_one = /obj/item/weapon/storage/backpack/satchel/tox
messenger_bag = /obj/item/weapon/storage/backpack/messenger/tox
+ sports_bag = /obj/item/weapon/storage/backpack/sport/tox
/decl/hierarchy/outfit/job/science/rd
name = OUTFIT_JOB_NAME("Research Director")
diff --git a/code/datums/outfits/jobs/security.dm b/code/datums/outfits/jobs/security.dm
index b1976b7f04..65388a7902 100644
--- a/code/datums/outfits/jobs/security.dm
+++ b/code/datums/outfits/jobs/security.dm
@@ -8,6 +8,7 @@
satchel_one = /obj/item/weapon/storage/backpack/satchel/sec
backpack_contents = list(/obj/item/weapon/handcuffs = 1)
messenger_bag = /obj/item/weapon/storage/backpack/messenger/sec
+ sports_bag = /obj/item/weapon/storage/backpack/sport/sec
/decl/hierarchy/outfit/job/security/hos
name = OUTFIT_JOB_NAME("Head of security")
diff --git a/code/datums/outfits/outfit.dm b/code/datums/outfits/outfit.dm
index 8cdcf117ee..7b74bc448b 100644
--- a/code/datums/outfits/outfit.dm
+++ b/code/datums/outfits/outfit.dm
@@ -41,7 +41,7 @@ var/list/outfits_decls_by_type_
var/l_hand = null
// In the list(path=count,otherpath=count) format
var/list/uniform_accessories = list() // webbing, armbands etc - fits in slot_tie
- var/list/backpack_contents = list()
+ var/list/backpack_contents = list()
var/id_type
var/id_desc
@@ -56,6 +56,7 @@ var/list/outfits_decls_by_type_
var/satchel_one = /obj/item/weapon/storage/backpack/satchel/norm
var/satchel_two = /obj/item/weapon/storage/backpack/satchel
var/messenger_bag = /obj/item/weapon/storage/backpack/messenger
+ var/sports_bag = /obj/item/weapon/storage/backpack/sport
var/flags // Specific flags
@@ -76,6 +77,7 @@ var/list/outfits_decls_by_type_
if(3) back = satchel_one
if(4) back = satchel_two
if(5) back = messenger_bag
+ if(6) back = sports_bag
else back = null
/decl/hierarchy/outfit/proc/post_equip(mob/living/carbon/human/H)
diff --git a/code/datums/wires/explosive.dm b/code/datums/wires/explosive.dm
index 52b0150b66..234f75a9e8 100644
--- a/code/datums/wires/explosive.dm
+++ b/code/datums/wires/explosive.dm
@@ -31,4 +31,5 @@
/datum/wires/explosive/c4/explode()
var/obj/item/weapon/plastique/P = holder
- P.explode(get_turf(P))
+ P.set_target(get_turf(P))
+ P.detonate()
diff --git a/code/game/atoms.dm b/code/game/atoms.dm
index 29632a7bfb..ea7326f51e 100644
--- a/code/game/atoms.dm
+++ b/code/game/atoms.dm
@@ -649,5 +649,5 @@ var/global/list/pre_init_created_atoms // atom creation ordering means some stuf
. = ..()
SEND_SIGNAL(src, COMSIG_ATOM_EXITED, AM, new_loc)
-/atom/proc/get_visible_gender()
+/atom/proc/get_visible_gender(mob/user, force)
return gender
diff --git a/code/game/dna/dna2.dm b/code/game/dna/dna2.dm
index 7a8d2f5d89..430145671f 100644
--- a/code/game/dna/dna2.dm
+++ b/code/game/dna/dna2.dm
@@ -328,8 +328,8 @@ var/global/list/datum/dna/gene/dna_genes[0]
SetSEBlock(block,newBlock,defer)
-/proc/EncodeDNABlock(var/value)
- return add_zero2(num2hex(value,1), 3)
+/proc/EncodeDNABlock(value)
+ return pad_left(num2hex(value), 3, "0")
/datum/dna/proc/UpdateUI()
src.uni_identity=""
diff --git a/code/game/dna/dna2_helpers.dm b/code/game/dna/dna2_helpers.dm
index 2287d3477c..2b7b00f303 100644
--- a/code/game/dna/dna2_helpers.dm
+++ b/code/game/dna/dna2_helpers.dm
@@ -2,15 +2,6 @@
// Helpers for DNA2
/////////////////////////////
-// Pads 0s to t until length == u
-/proc/add_zero2(t, u)
- var/temp1
- while (length(t) < u)
- t = "0[t]"
- temp1 = t
- if (length(t) > u)
- temp1 = copytext(t,2,u+1)
- return temp1
// DNA Gene activation boundaries, see dna2.dm.
// Returns a list object with 4 numbers.
diff --git a/code/game/jobs/job/captain.dm b/code/game/jobs/job/captain.dm
index 2138298e6d..87273128c6 100644
--- a/code/game/jobs/job/captain.dm
+++ b/code/game/jobs/job/captain.dm
@@ -26,7 +26,7 @@ var/datum/announcement/minor/captain_announcement = new(do_newscast = 1)
min_age_by_species = list(SPECIES_HUMAN_VATBORN = 14)
ideal_character_age = 70 // Old geezer captains ftw
ideal_age_by_species = list(SPECIES_HUMAN_VATBORN = 55) /// Vatborn live shorter, no other race eligible for captain besides human/skrell
- banned_job_species = list(SPECIES_UNATHI, SPECIES_TAJ, SPECIES_DIONA, SPECIES_PROMETHEAN, SPECIES_ZADDAT, "mechanical", "digital")
+ banned_job_species = list(SPECIES_UNATHI, SPECIES_TAJ, SPECIES_TESHARI, SPECIES_DIONA, SPECIES_PROMETHEAN, SPECIES_ZADDAT, "mechanical", "digital")
outfit_type = /decl/hierarchy/outfit/job/captain
job_description = "The Site Manager manages the other Command Staff, and through them the rest of the station. Though they have access to everything, \
diff --git a/code/game/machinery/computer/guestpass.dm b/code/game/machinery/computer/guestpass.dm
index f32858d8fa..8a002dc6b4 100644
--- a/code/game/machinery/computer/guestpass.dm
+++ b/code/game/machinery/computer/guestpass.dm
@@ -224,7 +224,7 @@
if ("issue")
if (giver)
- var/number = add_zero("[rand(0,9999)]", 4)
+ var/number = pad_left("[rand(1, 9999)]", 4, "0")
var/entry = "\[[stationtime2text()]\] Pass #[number] issued by [giver.registered_name] ([giver.assignment]) to [giv_name]. Reason: [reason]. Grants access to following areas: "
for (var/i=1 to accesses.len)
var/A = accesses[i]
diff --git a/code/game/machinery/computer/message.dm b/code/game/machinery/computer/message.dm
index e5074c06f0..2b408982ab 100644
--- a/code/game/machinery/computer/message.dm
+++ b/code/game/machinery/computer/message.dm
@@ -69,11 +69,15 @@
..()
/obj/machinery/computer/message_monitor/Initialize()
+ ..()
+ return INITIALIZE_HINT_LATELOAD
+
+/obj/machinery/computer/message_monitor/LateInitialize()
+ . = ..()
//Is the server isn't linked to a server, and there's a server available, default it to the first one in the list.
if(!linkedServer)
if(message_servers && message_servers.len > 0)
linkedServer = message_servers[1]
- return ..()
/obj/machinery/computer/message_monitor/tgui_interact(mob/user, datum/tgui/ui)
ui = SStgui.try_update_ui(user, src, ui)
diff --git a/code/game/machinery/status_display.dm b/code/game/machinery/status_display.dm
index c7cb351e70..1d486ab5e3 100644
--- a/code/game/machinery/status_display.dm
+++ b/code/game/machinery/status_display.dm
@@ -210,7 +210,7 @@
var/timeleft = emergency_shuttle.estimate_arrival_time()
if(timeleft < 0)
return ""
- return "[add_zero(num2text((timeleft / 60) % 60),2)]:[add_zero(num2text(timeleft % 60), 2)]"
+ return "[pad_left(num2text(timeleft / 60 % 60), 2, "0")]:[pad_left(num2text(timeleft % 60), 2, "0")]"
/obj/machinery/status_display/proc/get_shuttle_timer_departure()
if(!emergency_shuttle)
@@ -218,7 +218,7 @@
var/timeleft = emergency_shuttle.estimate_launch_time()
if(timeleft < 0)
return ""
- return "[add_zero(num2text((timeleft / 60) % 60),2)]:[add_zero(num2text(timeleft % 60), 2)]"
+ return "[pad_left(num2text(timeleft / 60 % 60), 2, "0")]:[pad_left(num2text(timeleft % 60), 2, "0")]"
/obj/machinery/status_display/proc/get_supply_shuttle_timer()
var/datum/shuttle/autodock/ferry/supply/shuttle = SSsupply.shuttle
@@ -229,7 +229,7 @@
var/timeleft = round((shuttle.arrive_time - world.time) / 10,1)
if(timeleft < 0)
return "Late"
- return "[add_zero(num2text((timeleft / 60) % 60),2)]:[add_zero(num2text(timeleft % 60), 2)]"
+ return "[pad_left(num2text(timeleft / 60 % 60), 2, "0")]:[pad_left(num2text(timeleft % 60), 2, "0")]"
return ""
/obj/machinery/status_display/proc/remove_display()
diff --git a/code/game/objects/effects/spiders.dm b/code/game/objects/effects/spiders.dm
index 4a9c8bf55f..c2b3fc1141 100644
--- a/code/game/objects/effects/spiders.dm
+++ b/code/game/objects/effects/spiders.dm
@@ -57,9 +57,12 @@
health -= Proj.get_structure_damage()
healthcheck()
+/obj/effect/spider/proc/die()
+ qdel(src)
+
/obj/effect/spider/proc/healthcheck()
if(health <= 0)
- qdel(src)
+ die()
/obj/effect/spider/fire_act(datum/gas_mixture/air, exposed_temperature, exposed_volume)
if(exposed_temperature > 300 + T0C)
@@ -141,7 +144,7 @@
layer = HIDING_LAYER
health = 3
var/last_itch = 0
- var/amount_grown = -1
+ var/amount_grown = 0
var/obj/machinery/atmospherics/unary/vent_pump/entry_vent
var/travelling_in_vent = 0
var/list/grow_as = list(/mob/living/simple_mob/animal/giant_spider, /mob/living/simple_mob/animal/giant_spider/nurse, /mob/living/simple_mob/animal/giant_spider/hunter)
@@ -171,16 +174,17 @@
else
..()
-/obj/effect/spider/spiderling/proc/die()
+/obj/effect/spider/spiderling/die()
visible_message("[src] dies!")
new /obj/effect/decal/cleanable/spiderling_remains(src.loc)
- qdel(src)
+ ..()
/obj/effect/spider/spiderling/healthcheck()
if(health <= 0)
die()
/obj/effect/spider/spiderling/process()
+ healthcheck()
if(travelling_in_vent)
if(istype(src.loc, /turf))
travelling_in_vent = 0
diff --git a/code/game/objects/items/weapons/chewables.dm b/code/game/objects/items/weapons/chewables.dm
index 186263897b..ef30947f5b 100644
--- a/code/game/objects/items/weapons/chewables.dm
+++ b/code/game/objects/items/weapons/chewables.dm
@@ -254,12 +254,12 @@
desc = "A chocolate-coated biscuit stick."
icon_state = "pocky"
item_state = "pocky"
+ filling = list("sugar" = 2, "chocolate" = 5)
+ type_butt = null
/obj/item/clothing/mask/chewable/candy/pocky/process()
chew()
if(chewtime < 1)
- spitout(0)
-
-/obj/item/clothing/mask/chewable/candy/pocky/Initialize()
- . = ..()
- reagents.add_reagent("chocolate", 10)
\ No newline at end of file
+ if(ismob(loc))
+ to_chat(loc, SPAN_NOTICE("There's no more of \the [name] left!"))
+ spitout(0)
\ No newline at end of file
diff --git a/code/game/objects/items/weapons/explosives.dm b/code/game/objects/items/weapons/explosives.dm
index 8cbd953a6b..4ecf203424 100644
--- a/code/game/objects/items/weapons/explosives.dm
+++ b/code/game/objects/items/weapons/explosives.dm
@@ -11,6 +11,7 @@
var/datum/wires/explosive/c4/wires = null
var/timer = 10
var/atom/target = null
+ var/list/location = list()
var/open_panel = 0
var/image_overlay = null
var/blast_dev = -1
@@ -53,9 +54,9 @@
to_chat(user, "Planting explosives...")
user.do_attack_animation(target)
- if(do_after(user, 50) && in_range(user, target))
+ if(do_after(user, 5 SECONDS) && in_range(user, target))
user.drop_item()
- src.target = target
+ set_target(target) // Saving coordinates in case the reference becomes invalid
loc = null
if (ismob(target))
@@ -67,16 +68,25 @@
target.overlays += image_overlay
to_chat(user, "Bomb has been planted. Timer counting down from [timer].")
- spawn(timer*10)
- explode(get_turf(target))
+ addtimer(CALLBACK(src, .proc/detonate), timer SECONDS)
-/obj/item/weapon/plastique/proc/explode(var/location)
+/obj/item/weapon/plastique/proc/set_target(var/atom/T)
+ if(!isatom(T))
+ return
+ target = T
+ location = list(T.x, T.y, T.z)
+
+/obj/item/weapon/plastique/proc/detonate()
if(!target)
target = get_atom_on_turf(src)
if(!target)
target = src
- if(location)
- explosion(location, blast_dev, blast_heavy, blast_light, blast_flash)
+
+ var/turf/T = get_turf(target)
+ if (!T && length(location))
+ T = locate(location[1], location[2], location[3])
+ if (T)
+ explosion(T, blast_dev, blast_heavy, blast_light, blast_flash)
if(target)
if (istype(target, /turf/simulated/wall))
diff --git a/code/game/objects/items/weapons/grenades/explosive.dm b/code/game/objects/items/weapons/grenades/explosive.dm
index 076a7accce..77e07e2c5f 100644
--- a/code/game/objects/items/weapons/grenades/explosive.dm
+++ b/code/game/objects/items/weapons/grenades/explosive.dm
@@ -12,6 +12,7 @@
//The radius of the circle used to launch projectiles. Lower values mean less projectiles are used but if set too low gaps may appear in the spread pattern
var/spread_range = 7
loadable = null
+ hud_state = "grenade_frag" // TGMC Ammo HUD Port
/obj/item/weapon/grenade/explosive/detonate()
..()
diff --git a/code/game/objects/items/weapons/grenades/grenade.dm b/code/game/objects/items/weapons/grenades/grenade.dm
index 209e47b253..9bdf650c64 100644
--- a/code/game/objects/items/weapons/grenades/grenade.dm
+++ b/code/game/objects/items/weapons/grenades/grenade.dm
@@ -13,6 +13,8 @@
var/det_time = 50
var/loadable = TRUE
var/arm_sound = 'sound/weapons/armbomb.ogg'
+ var/hud_state = "grenade_he" // TGMC Ammo HUD Port
+ var/hud_state_empty = "grenade_empty" // TGMC Ammo HUD Port
/obj/item/weapon/grenade/proc/clown_check(var/mob/living/user)
if((CLUMSY in user.mutations) && prob(50))
diff --git a/code/game/objects/items/weapons/grenades/smokebomb.dm b/code/game/objects/items/weapons/grenades/smokebomb.dm
index 51ec50d182..d3b417b6a7 100644
--- a/code/game/objects/items/weapons/grenades/smokebomb.dm
+++ b/code/game/objects/items/weapons/grenades/smokebomb.dm
@@ -6,6 +6,7 @@
det_time = 20
item_state = "flashbang"
slot_flags = SLOT_BELT
+ hud_state = "grenade_smoke"
var/datum/effect_system/smoke_spread/bad/smoke
var/smoke_color
var/smoke_strength = 8
diff --git a/code/game/objects/items/weapons/storage/backpack.dm b/code/game/objects/items/weapons/storage/backpack.dm
index b296c58b96..38b82beb36 100644
--- a/code/game/objects/items/weapons/storage/backpack.dm
+++ b/code/game/objects/items/weapons/storage/backpack.dm
@@ -127,6 +127,18 @@
desc = "It's an orange backpack which was designed to hold beakers, pill bottles and bottles."
icon_state = "chempack"
+/obj/item/weapon/storage/backpack/white
+ name = "white backpack"
+ icon_state = "backpack_white"
+
+/obj/item/weapon/storage/backpack/fancy
+ name = "fancy backpack"
+ icon_state = "backpack_fancy"
+
+/obj/item/weapon/storage/backpack/military
+ name = "military backpack"
+ icon_state = "backpack_military"
+
/*
* Duffle Types
*/
@@ -184,6 +196,16 @@
desc = "A large dufflebag for holding circuits and beakers."
icon_state = "duffle_sci"
+/obj/item/weapon/storage/backpack/dufflebag/drone
+ name = "drone dufflebag"
+ desc = "A large dufflebag for holding small robots? Or maybe it's one used by robots!"
+ icon_state = "duffle_drone"
+
+/obj/item/weapon/storage/backpack/dufflebag/cursed
+ name = "cursed dufflebag"
+ desc = "That probably shouldn't be moving..."
+ icon_state = "duffle_cursed"
+
/*
* Satchel Types
*/
@@ -192,7 +214,6 @@
name = "leather satchel"
desc = "It's a very fancy satchel made with fine leather."
icon_state = "satchel"
- item_state_slots = list(slot_r_hand_str = "briefcase", slot_l_hand_str = "briefcase")
/obj/item/weapon/storage/backpack/satchel/withwallet
starts_with = list(/obj/item/weapon/storage/wallet/random)
@@ -206,43 +227,36 @@
name = "industrial satchel"
desc = "A tough satchel with extra pockets."
icon_state = "satchel-eng"
- item_state_slots = list(slot_r_hand_str = "engiepack", slot_l_hand_str = "engiepack")
/obj/item/weapon/storage/backpack/satchel/med
name = "medical satchel"
desc = "A sterile satchel used in medical departments."
icon_state = "satchel-med"
- item_state_slots = list(slot_r_hand_str = "medicalpack", slot_l_hand_str = "medicalpack")
/obj/item/weapon/storage/backpack/satchel/vir
name = "virologist satchel"
desc = "A sterile satchel with virologist colours."
icon_state = "satchel-vir"
- item_state_slots = list(slot_r_hand_str = "viropack", slot_l_hand_str = "viropack")
/obj/item/weapon/storage/backpack/satchel/chem
name = "chemist satchel"
desc = "A sterile satchel with chemist colours."
icon_state = "satchel-chem"
- item_state_slots = list(slot_r_hand_str = "chempack", slot_l_hand_str = "chempack")
/obj/item/weapon/storage/backpack/satchel/gen
name = "geneticist satchel"
desc = "A sterile satchel with geneticist colours."
icon_state = "satchel-gen"
- item_state_slots = list(slot_r_hand_str = "genpack", slot_l_hand_str = "genpack")
/obj/item/weapon/storage/backpack/satchel/tox
name = "scientist satchel"
desc = "Useful for holding research materials."
icon_state = "satchel-tox"
- item_state_slots = list(slot_r_hand_str = "toxpack", slot_l_hand_str = "toxpack")
/obj/item/weapon/storage/backpack/satchel/sec
name = "security satchel"
desc = "A robust satchel for security related needs."
icon_state = "satchel-sec"
- item_state_slots = list(slot_r_hand_str = "securitypack", slot_l_hand_str = "securitypack")
/obj/item/weapon/storage/backpack/satchel/hyd
name = "hydroponics satchel"
@@ -253,7 +267,18 @@
name = "site manager's satchel"
desc = "An exclusive satchel for officers."
icon_state = "satchel-cap"
- item_state_slots = list(slot_r_hand_str = "captainpack", slot_l_hand_str = "captainpack")
+
+/obj/item/weapon/storage/backpack/satchel/white
+ name = "white satchel"
+ icon_state = "satchel_white"
+
+/obj/item/weapon/storage/backpack/satchel/fancy
+ name = "fancy satchel"
+ icon_state = "satchel_fancy"
+
+/obj/item/weapon/storage/backpack/satchel/military
+ name = "military satchel"
+ icon_state = "satchel_military"
//ERT backpacks.
/obj/item/weapon/storage/backpack/ert
@@ -293,56 +318,104 @@
name = "messenger bag"
desc = "A sturdy backpack worn over one shoulder."
icon_state = "courierbag"
- item_state_slots = list(slot_r_hand_str = "backpack", slot_l_hand_str = "backpack")
+ item_state_slots = list(slot_r_hand_str = "satchel-norm", slot_l_hand_str = "satchel-norm")
/obj/item/weapon/storage/backpack/messenger/chem
name = "chemistry messenger bag"
desc = "A serile backpack worn over one shoulder. This one is in Chemsitry colors."
icon_state = "courierbagchem"
- item_state_slots = list(slot_r_hand_str = "chempack", slot_l_hand_str = "chempack")
+ item_state_slots = list(slot_r_hand_str = "satchel-chem", slot_l_hand_str = "satchel-chem")
/obj/item/weapon/storage/backpack/messenger/med
name = "medical messenger bag"
desc = "A sterile backpack worn over one shoulder used in medical departments."
icon_state = "courierbagmed"
- item_state_slots = list(slot_r_hand_str = "medicalpack", slot_l_hand_str = "medicalpack")
+ item_state_slots = list(slot_r_hand_str = "satchel-med", slot_l_hand_str = "satchel-med")
/obj/item/weapon/storage/backpack/messenger/viro
name = "virology messenger bag"
desc = "A sterile backpack worn over one shoulder. This one is in Virology colors."
icon_state = "courierbagviro"
- item_state_slots = list(slot_r_hand_str = "viropack", slot_l_hand_str = "viropack")
+ item_state_slots = list(slot_r_hand_str = "satchel-vir", slot_l_hand_str = "satchel-vir")
/obj/item/weapon/storage/backpack/messenger/tox
name = "research messenger bag"
desc = "A backpack worn over one shoulder. Useful for holding science materials."
icon_state = "courierbagtox"
- item_state_slots = list(slot_r_hand_str = "toxpack", slot_l_hand_str = "toxpack")
+ item_state_slots = list(slot_r_hand_str = "satchel-tox", slot_l_hand_str = "satchel-tox")
/obj/item/weapon/storage/backpack/messenger/com
name = "command messenger bag"
desc = "A special backpack worn over one shoulder. This one is made specifically for officers."
icon_state = "courierbagcom"
- item_state_slots = list(slot_r_hand_str = "captainpack", slot_l_hand_str = "captainpack")
+ item_state_slots = list(slot_r_hand_str = "satchel-cap", slot_l_hand_str = "satchel-cap")
/obj/item/weapon/storage/backpack/messenger/engi
name = "engineering messenger bag"
icon_state = "courierbagengi"
- item_state_slots = list(slot_r_hand_str = "engiepack", slot_l_hand_str = "engiepack")
+ item_state_slots = list(slot_r_hand_str = "satchel-eng", slot_l_hand_str = "satchel-eng")
/obj/item/weapon/storage/backpack/messenger/hyd
name = "hydroponics messenger bag"
desc = "A backpack worn over one shoulder. This one is designed for plant-related work."
icon_state = "courierbaghyd"
+ item_state_slots = list(slot_r_hand_str = "satchel_hyd", slot_l_hand_str = "satchel_hyd")
/obj/item/weapon/storage/backpack/messenger/sec
name = "security messenger bag"
desc = "A tactical backpack worn over one shoulder. This one is in Security colors."
icon_state = "courierbagsec"
- item_state_slots = list(slot_r_hand_str = "securitypack", slot_l_hand_str = "securitypack")
+ item_state_slots = list(slot_r_hand_str = "satchel-sec", slot_l_hand_str = "satchel-sec")
/obj/item/weapon/storage/backpack/messenger/black
icon_state = "courierbagblk"
+ item_state_slots = list(slot_r_hand_str = "satchel-sec", slot_l_hand_str = "satchel-sec")
+
+/*
+ * Sport Bags
+ */
+
+/obj/item/weapon/storage/backpack/sport
+ name = "sports backpack"
+ icon_state = "backsport"
+
+/obj/item/weapon/storage/backpack/sport/white
+ name = "white sports backpack"
+ icon_state = "backsport_white"
+
+/obj/item/weapon/storage/backpack/sport/fancy
+ name = "fancy sports backpack"
+ icon_state = "backsport_fancy"
+
+/obj/item/weapon/storage/backpack/sport/vir
+ name = "virologist sports backpack"
+ desc = "A sterile sports backpack with virologist colours."
+ icon_state = "backsport_green"
+
+/obj/item/weapon/storage/backpack/sport/chem
+ name = "chemist sports backpack"
+ desc = "A sterile sports backpack with chemist colours."
+ icon_state = "backsport_orange"
+
+/obj/item/weapon/storage/backpack/sport/gen
+ name = "geneticist sports backpack"
+ desc = "A sterile sports backpack with geneticist colours."
+ icon_state = "backsport_blue"
+
+/obj/item/weapon/storage/backpack/sport/tox
+ name = "scientist sports backpack"
+ desc = "Useful for holding research materials."
+ icon_state = "backsport_purple"
+
+/obj/item/weapon/storage/backpack/sport/sec
+ name = "security sports backpack"
+ desc = "A robust sports backpack for security related needs."
+ icon_state = "backsport_security"
+
+/obj/item/weapon/storage/backpack/sport/hyd
+ name = "hydroponics sports backpack"
+ desc = "A green sports backpack for plant related work."
+ icon_state = "backsport_hydro"
//Purses
diff --git a/code/game/objects/items/weapons/storage/briefcase.dm b/code/game/objects/items/weapons/storage/briefcase.dm
index ed4d8fdbbe..a3cc27d926 100644
--- a/code/game/objects/items/weapons/storage/briefcase.dm
+++ b/code/game/objects/items/weapons/storage/briefcase.dm
@@ -20,4 +20,13 @@
force = 0
w_class = ITEMSIZE_NORMAL
max_w_class = ITEMSIZE_SMALL
- max_storage_space = ITEMSIZE_COST_SMALL * 4
\ No newline at end of file
+ max_storage_space = ITEMSIZE_COST_SMALL * 4
+
+/obj/item/weapon/storage/briefcase/bookbag
+ name = "bookbag"
+ desc = "A small bookbag for holding... things other than books?"
+ icon_state = "bookbag"
+ force = 4.0
+ w_class = ITEMSIZE_LARGE
+ max_w_class = ITEMSIZE_NORMAL
+ max_storage_space = ITEMSIZE_COST_NORMAL * 4
\ No newline at end of file
diff --git a/code/game/objects/structures/stool_bed_chair_nest/bed.dm b/code/game/objects/structures/stool_bed_chair_nest/bed.dm
index be833aec08..426db6b7dd 100644
--- a/code/game/objects/structures/stool_bed_chair_nest/bed.dm
+++ b/code/game/objects/structures/stool_bed_chair_nest/bed.dm
@@ -114,6 +114,7 @@
if(!istype(src.loc, /turf))
user.drop_from_inventory(src)
src.loc = get_turf(src)
+ playsound(src.loc, 'sound/effects/rustle5.ogg', 50, 1)
to_chat(user, "You add padding to \the [src].")
add_padding(padding_type)
return
diff --git a/code/game/objects/structures/stool_bed_chair_nest/chairs.dm b/code/game/objects/structures/stool_bed_chair_nest/chairs.dm
index 5d1322c3c3..ffef310fdf 100644
--- a/code/game/objects/structures/stool_bed_chair_nest/chairs.dm
+++ b/code/game/objects/structures/stool_bed_chair_nest/chairs.dm
@@ -132,6 +132,42 @@
/obj/structure/bed/chair/comfy/orange/Initialize(var/ml,var/newmaterial)
. = ..(ml, MAT_STEEL, "orange")
+/obj/structure/bed/chair/rounded
+ name = "rounded chair"
+ desc = "It's a rounded chair. It looks comfy."
+ icon_state = "roundedchair"
+ base_icon = "roundedchair"
+
+/obj/structure/bed/chair/rounded/brown/Initialize(var/ml,var/newmaterial)
+ . = ..(ml, MAT_STEEL, MAT_LEATHER)
+
+/obj/structure/bed/chair/rounded/red/Initialize(var/ml,var/newmaterial)
+ . = ..(ml, MAT_STEEL, "carpet")
+
+/obj/structure/bed/chair/rounded/teal/Initialize(var/ml,var/newmaterial)
+ . = ..(ml, MAT_STEEL, "teal")
+
+/obj/structure/bed/chair/rounded/black/Initialize(var/ml,var/newmaterial)
+ . = ..(ml, MAT_STEEL, "black")
+
+/obj/structure/bed/chair/rounded/green/Initialize(var/ml,var/newmaterial)
+ . = ..(ml, MAT_STEEL, "green")
+
+/obj/structure/bed/chair/rounded/purple/Initialize(var/ml,var/newmaterial)
+ . = ..(ml, MAT_STEEL, "purple")
+
+/obj/structure/bed/chair/rounded/blue/Initialize(var/ml,var/newmaterial)
+ . = ..(ml, MAT_STEEL, "blue")
+
+/obj/structure/bed/chair/rounded/beige/Initialize(var/ml,var/newmaterial)
+ . = ..(ml, MAT_STEEL, "beige")
+
+/obj/structure/bed/chair/rounded/lime/Initialize(var/ml,var/newmaterial)
+ . = ..(ml, MAT_STEEL, "lime")
+
+/obj/structure/bed/chair/rounded/yellow/Initialize(var/ml,var/newmaterial)
+ . = ..(ml, MAT_STEEL, "yellow")
+
/obj/structure/bed/chair/office
anchored = 0
buckle_movable = 1
diff --git a/code/modules/admin/player_panel.dm b/code/modules/admin/player_panel.dm
index 459d5b2bc7..c309ebdf53 100644
--- a/code/modules/admin/player_panel.dm
+++ b/code/modules/admin/player_panel.dm
@@ -393,11 +393,11 @@
else
if (emergency_shuttle.wait_for_launch)
var/timeleft = emergency_shuttle.estimate_launch_time()
- dat += "ETL: [(timeleft / 60) % 60]:[add_zero(num2text(timeleft % 60), 2)]
"
+ dat += "ETL: [(timeleft / 60) % 60]:[pad_left(num2text(timeleft % 60), 2, "0")]
"
else if (emergency_shuttle.shuttle.has_arrive_time())
var/timeleft = emergency_shuttle.estimate_arrival_time()
- dat += "ETA: [(timeleft / 60) % 60]:[add_zero(num2text(timeleft % 60), 2)]
"
+ dat += "ETA: [(timeleft / 60) % 60]:[pad_left(num2text(timeleft % 60), 2, "0")]
"
dat += "Send Back
"
if (emergency_shuttle.shuttle.moving_status == SHUTTLE_WARMUP)
diff --git a/code/modules/admin/view_variables/view_variables_global.dm b/code/modules/admin/view_variables/view_variables_global.dm
index 1f6f2d52d6..3d7302caf2 100644
--- a/code/modules/admin/view_variables/view_variables_global.dm
+++ b/code/modules/admin/view_variables/view_variables_global.dm
@@ -1,40 +1,49 @@
-/proc/readglobal(which)
- . = global.vars[which]
-
-/proc/writeglobal(which, newval)
- global.vars[which] = newval
+GLOBAL_DATUM(debug_real_globals, /debug_real_globals) // :3c
-/proc/getallglobals()
- . = list()
- for(var/some_global in global.vars)
- . += some_global
-/var/decl/global_vars/global_vars_
+/debug_real_globals/vv_get_header()
+ return list("Debug: Real Globals
")
-/decl/global_vars
- var/name = "Global Variables"
-/decl/global_vars/get_view_variables_options()
- return "" // Ensuring changes to the base proc never affect us
+/debug_real_globals/get_variables()
+ var/static/list/cache
+ if (!cache)
+ cache = list()
+ var/list/hidden = VV_hidden()
+ for (var/name in global.vars)
+ if (name in hidden)
+ continue
+ cache |= name
+ cache = sortList(cache)
+ if (!usr || !check_rights(R_ADMIN|R_DEBUG, FALSE))
+ var/static/list/locked
+ if (!locked)
+ locked = VV_locked()
+ return (cache - locked)
+ return cache.Copy()
-/decl/global_vars/get_variables()
- . = getallglobals() - VV_hidden()
- if(!usr || !check_rights(R_ADMIN|R_DEBUG, FALSE))
- . -= VV_secluded()
-/decl/global_vars/get_variable_value(varname)
- return readglobal(varname)
+/debug_real_globals/make_view_variables_variable_entry(name, value)
+ return {"(E) "}
-/decl/global_vars/set_variable_value(varname, value)
- writeglobal(varname, value)
-/decl/global_vars/make_view_variables_variable_entry(varname, value)
- return "(E) "
+/debug_real_globals/set_variable_value(name, value)
+ global.vars[name] = value
-/decl/global_vars/VV_locked()
+
+/debug_real_globals/get_variable_value(name)
+ return global.vars[name]
+
+
+/debug_real_globals/get_view_variables_options()
+ return ""
+
+
+/debug_real_globals/VV_locked()
return vars
-/decl/global_vars/VV_hidden()
+
+/debug_real_globals/VV_hidden()
return list(
"forumsqladdress",
"forumsqldb",
@@ -79,13 +88,14 @@
"adminlogs",
"cardinal",
"cardinalz",
- "IClog"
+ "IClog",
+ "vchatdb"
)
+
/client/proc/debug_global_variables()
set category = "Debug"
- set name = "View Global Variables"
-
- if(!global_vars_)
- global_vars_ = new()
- debug_variables(global_vars_)
\ No newline at end of file
+ set name = "View Real Globals"
+ if (!GLOB.debug_real_globals)
+ GLOB.debug_real_globals = new
+ debug_variables(GLOB.debug_real_globals)
diff --git a/code/modules/ai/ai_holder.dm b/code/modules/ai/ai_holder.dm
index 21d9cd8588..a285225286 100644
--- a/code/modules/ai/ai_holder.dm
+++ b/code/modules/ai/ai_holder.dm
@@ -1,14 +1,6 @@
// This is a datum-based artificial intelligence for simple mobs (and possibly others) to use.
// The neat thing with having this here instead of on the mob is that it is independant of Life(), and that different mobs
// can use a more or less complex AI by giving it a different datum.
-#define AI_NO_PROCESS 0
-#define AI_PROCESSING (1<<0)
-#define AI_FASTPROCESSING (1<<1)
-
-#define START_AIPROCESSING(Datum) if (!(Datum.process_flags & AI_PROCESSING)) {Datum.process_flags |= AI_PROCESSING;SSai.processing += Datum}
-#define STOP_AIPROCESSING(Datum) Datum.process_flags &= ~AI_PROCESSING;SSai.processing -= Datum
-#define START_AIFASTPROCESSING(Datum) if (!(Datum.process_flags & AI_FASTPROCESSING)) {Datum.process_flags |= AI_FASTPROCESSING;SSaifast.processing += Datum}
-#define STOP_AIFASTPROCESSING(Datum) Datum.process_flags &= ~AI_FASTPROCESSING;SSaifast.processing -= Datum
/mob/living
var/datum/ai_holder/ai_holder = null
diff --git a/code/modules/antagonist/outsider/mercenary.dm b/code/modules/antagonist/outsider/mercenary.dm
index 94b362fca8..623291dde7 100644
--- a/code/modules/antagonist/outsider/mercenary.dm
+++ b/code/modules/antagonist/outsider/mercenary.dm
@@ -42,6 +42,7 @@ var/datum/antagonist/mercenary/mercs
if(player.backbag == 3) player.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/satchel/norm(player), slot_back)
if(player.backbag == 4) player.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/satchel(player), slot_back)
if(player.backbag == 5) player.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/messenger(player), slot_back)
+ if(player.backbag == 6) player.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/sport(player), slot_back)
player.equip_to_slot_or_del(new /obj/item/weapon/reagent_containers/pill/cyanide(player), slot_in_backpack)
player.mind.tcrystals = DEFAULT_TELECRYSTAL_AMOUNT
diff --git a/code/modules/antagonist/outsider/wizard.dm b/code/modules/antagonist/outsider/wizard.dm
index f362f6b3a8..6a3aea1f9e 100644
--- a/code/modules/antagonist/outsider/wizard.dm
+++ b/code/modules/antagonist/outsider/wizard.dm
@@ -84,6 +84,7 @@ var/datum/antagonist/wizard/wizards
if(wizard_mob.backbag == 3) wizard_mob.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/satchel/norm(wizard_mob), slot_back)
if(wizard_mob.backbag == 4) wizard_mob.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/satchel(wizard_mob), slot_back)
if(wizard_mob.backbag == 5) wizard_mob.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack(wizard_mob), slot_back)
+ if(wizard_mob.backbag == 6) wizard_mob.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/sport(wizard_mob), slot_back)
wizard_mob.equip_to_slot_or_del(new /obj/item/weapon/storage/box(wizard_mob), slot_in_backpack)
wizard_mob.equip_to_slot_or_del(new /obj/item/weapon/teleportation_scroll(wizard_mob), slot_r_store)
wizard_mob.equip_to_slot_or_del(new /obj/item/weapon/spellbook(wizard_mob), slot_r_hand)
diff --git a/code/modules/client/preference_setup/general/04_equipment.dm b/code/modules/client/preference_setup/general/04_equipment.dm
index c5a940e868..13d079c60a 100644
--- a/code/modules/client/preference_setup/general/04_equipment.dm
+++ b/code/modules/client/preference_setup/general/04_equipment.dm
@@ -36,8 +36,8 @@
pref.all_underwear -= underwear_category_name
// TODO - Looks like this is duplicating the work of sanitize_character() if so, remove
- if(pref.backbag > 5 || pref.backbag < 1)
- pref.backbag = 1 //Same as above
+ if(pref.backbag > backbaglist.len || pref.backbag < 1)
+ pref.backbag = 2 //Same as above
character.backbag = pref.backbag
if(pref.pdachoice > 6 || pref.pdachoice < 1)
diff --git a/code/modules/client/preference_setup/loadout/loadout_accessories.dm b/code/modules/client/preference_setup/loadout/loadout_accessories.dm
index 4a271fde93..e26a98cc25 100644
--- a/code/modules/client/preference_setup/loadout/loadout_accessories.dm
+++ b/code/modules/client/preference_setup/loadout/loadout_accessories.dm
@@ -121,6 +121,18 @@
..()
gear_tweaks += gear_tweak_free_color_choice
+/datum/gear/accessory/bowtie
+ display_name = "bowtie selection"
+ path = /obj/item/clothing/accessory/bowtie
+ cost = 1
+
+/datum/gear/accessory/bowtie/New()
+ ..()
+ var/list/bowties = list()
+ for(var/obj/item/clothing/accessory/bowtie_type as anything in typesof(/obj/item/clothing/accessory/bowtie))
+ bowties[initial(bowtie_type.name)] = bowtie_type
+ gear_tweaks += new/datum/gear_tweak/path(sortAssoc(bowties))
+
/datum/gear/accessory/jacket
display_name = "suit jacket selection"
path = /obj/item/clothing/accessory/jacket
@@ -306,4 +318,17 @@
for(var/pridepin in typesof(/obj/item/clothing/accessory/pride))
var/obj/item/clothing/accessory/pridepin_type = pridepin
pridepins[initial(pridepin_type.name)] = pridepin_type
- gear_tweaks += new/datum/gear_tweak/path(sortAssoc(pridepins))
\ No newline at end of file
+ gear_tweaks += new/datum/gear_tweak/path(sortAssoc(pridepins))
+
+/datum/gear/accessory/corpbadge
+ display_name = "investigator holobadge (IAA)"
+ path = /obj/item/clothing/accessory/badge/holo/investigator
+ allowed_roles = list("Internal affairs agent")
+
+/datum/gear/accessory/pressbadge
+ display_name = "corporate press pass"
+ path = /obj/item/clothing/accessory/badge/press
+
+/datum/gear/accessory/pressbadge
+ display_name = "freelance press pass"
+ path = /obj/item/clothing/accessory/badge/press/independent
\ No newline at end of file
diff --git a/code/modules/client/preference_setup/loadout/loadout_gloves.dm b/code/modules/client/preference_setup/loadout/loadout_gloves.dm
index fe56eea868..226006d10f 100644
--- a/code/modules/client/preference_setup/loadout/loadout_gloves.dm
+++ b/code/modules/client/preference_setup/loadout/loadout_gloves.dm
@@ -78,6 +78,10 @@
display_name = "fingerless gloves"
path = /obj/item/clothing/gloves/fingerless
+/datum/gear/gloves/fingerless/New()
+ ..()
+ gear_tweaks += gear_tweak_free_color_choice
+
/datum/gear/gloves/ring
display_name = "ring selection"
description = "Choose from a number of rings."
diff --git a/code/modules/clothing/gloves/color.dm b/code/modules/clothing/gloves/color.dm
index 75121c608e..a6409e1d0e 100644
--- a/code/modules/clothing/gloves/color.dm
+++ b/code/modules/clothing/gloves/color.dm
@@ -90,4 +90,5 @@
desc = "A pair of gloves that don't actually cover the fingers."
name = "fingerless gloves"
icon_state = "fingerlessgloves"
+ addblends = "fingerlessgloves_a"
fingerprint_chance = 100
\ No newline at end of file
diff --git a/code/modules/clothing/head/hardhat.dm b/code/modules/clothing/head/hardhat.dm
index f974c321c0..c78749f6f8 100644
--- a/code/modules/clothing/head/hardhat.dm
+++ b/code/modules/clothing/head/hardhat.dm
@@ -37,37 +37,3 @@
/obj/item/clothing/head/hardhat/dblue
name = "blue hard hat"
icon_state = "hardhat0_dblue"
-
-/obj/item/clothing/head/hardhat/ranger
- var/hatcolor = "white"
- name = "ranger helmet"
- desc = "A special helmet designed for the Go Go ERT-Rangers, able to withstand a pressureless environment, filter gas and provide air. It has thermal vision and sometimes \
- mesons to find breaches, as well as an integrated radio... well, only in the show, of course. This one has none of those features- it just has a flashlight instead."
- icon = 'icons/obj/clothing/ranger.dmi'
- icon_state = "ranger_helmet"
- light_overlay = "helmet_light"
- flags_inv = HIDEMASK|HIDEEARS|HIDEEYES|HIDEFACE|BLOCKHAIR
-
-/obj/item/clothing/head/hardhat/ranger/Initialize()
- . = ..()
- if(icon_state == "ranger_helmet")
- name = "[hatcolor] ranger helmet"
- icon_state = "[hatcolor]_ranger_helmet"
-
-/obj/item/clothing/head/hardhat/ranger/black
- hatcolor = "black"
-
-/obj/item/clothing/head/hardhat/ranger/pink
- hatcolor = "pink"
-
-/obj/item/clothing/head/hardhat/ranger/green
- hatcolor = "green"
-
-/obj/item/clothing/head/hardhat/ranger/cyan
- hatcolor = "cyan"
-
-/obj/item/clothing/head/hardhat/ranger/orange
- hatcolor = "orange"
-
-/obj/item/clothing/head/hardhat/ranger/yellow
- hatcolor = "yellow"
\ No newline at end of file
diff --git a/code/modules/clothing/head/misc.dm b/code/modules/clothing/head/misc.dm
index ba20ceb2f5..925d6cae31 100644
--- a/code/modules/clothing/head/misc.dm
+++ b/code/modules/clothing/head/misc.dm
@@ -502,4 +502,41 @@
desc = "A marine helmet prop from the popular game 'Ruin'."
icon_state = "marine"
flags_inv = HIDEMASK|HIDEEARS|HIDEEYES|HIDEFACE|BLOCKHAIR
- body_parts_covered = HEAD|FACE|EYES
\ No newline at end of file
+ body_parts_covered = HEAD|FACE|EYES
+
+/obj/item/clothing/head/ranger
+ var/hatcolor = "white"
+ name = "ranger helmet"
+ desc = "A special helmet designed for the Go Go ERT-Rangers, able to withstand a pressureless environment, filter gas and provide air. It has thermal vision and sometimes \
+ mesons to find breaches, as well as an integrated radio... well, only in the show, of course."
+ icon = 'icons/obj/clothing/ranger.dmi'
+ icon_state = "ranger_helmet"
+ light_overlay = "helmet_light"
+ flags_inv = HIDEMASK|HIDEEARS|HIDEEYES|HIDEFACE|BLOCKHAIR
+ drop_sound = 'sound/items/drop/helm.ogg'
+ pickup_sound = 'sound/items/pickup/helm.ogg'
+ w_class = ITEMSIZE_NORMAL
+
+/obj/item/clothing/head/ranger/Initialize()
+ . = ..()
+ if(icon_state == "ranger_helmet")
+ name = "[hatcolor] ranger helmet"
+ icon_state = "[hatcolor]_ranger_helmet"
+
+/obj/item/clothing/head/ranger/black
+ hatcolor = "black"
+
+/obj/item/clothing/head/ranger/pink
+ hatcolor = "pink"
+
+/obj/item/clothing/head/ranger/green
+ hatcolor = "green"
+
+/obj/item/clothing/head/ranger/cyan
+ hatcolor = "cyan"
+
+/obj/item/clothing/head/ranger/orange
+ hatcolor = "orange"
+
+/obj/item/clothing/head/ranger/yellow
+ hatcolor = "yellow"
\ No newline at end of file
diff --git a/code/modules/clothing/shoes/miscellaneous.dm b/code/modules/clothing/shoes/miscellaneous.dm
index b8151b7743..ef7d53d5e6 100644
--- a/code/modules/clothing/shoes/miscellaneous.dm
+++ b/code/modules/clothing/shoes/miscellaneous.dm
@@ -174,34 +174,36 @@
drop_sound = 'sound/items/drop/clothing.ogg'
pickup_sound = 'sound/items/pickup/clothing.ogg'
-/obj/item/clothing/shoes/boots/ranger
+/obj/item/clothing/shoes/ranger
var/bootcolor = "white"
name = "ranger boots"
desc = "The Rangers special lightweight hybrid magboots-jetboots perfect for EVA. If only these functions were so easy to copy in reality.\
These ones are just a well-made pair of boots in appropriate colours."
icon = 'icons/obj/clothing/ranger.dmi'
icon_state = "ranger_boots"
+ step_volume_mod = 1.2
+ drop_sound = 'sound/items/drop/boots.ogg'
-/obj/item/clothing/shoes/boots/ranger/Initialize()
+/obj/item/clothing/shoes/ranger/Initialize()
. = ..()
if(icon_state == "ranger_boots")
name = "[bootcolor] ranger boots"
icon_state = "[bootcolor]_ranger_boots"
-/obj/item/clothing/shoes/boots/ranger/black
+/obj/item/clothing/shoes/ranger/black
bootcolor = "black"
-/obj/item/clothing/shoes/boots/ranger/pink
+/obj/item/clothing/shoes/ranger/pink
bootcolor = "pink"
-/obj/item/clothing/shoes/boots/ranger/green
+/obj/item/clothing/shoes/ranger/green
bootcolor = "green"
-/obj/item/clothing/shoes/boots/ranger/cyan
+/obj/item/clothing/shoes/ranger/cyan
bootcolor = "cyan"
-/obj/item/clothing/shoes/boots/ranger/orange
+/obj/item/clothing/shoes/ranger/orange
bootcolor = "orange"
-/obj/item/clothing/shoes/boots/ranger/yellow
+/obj/item/clothing/shoes/ranger/yellow
bootcolor = "yellow"
\ No newline at end of file
diff --git a/code/modules/clothing/suits/solgov.dm b/code/modules/clothing/suits/solgov.dm
index aebec733a8..184d4e11ac 100644
--- a/code/modules/clothing/suits/solgov.dm
+++ b/code/modules/clothing/suits/solgov.dm
@@ -180,8 +180,8 @@
/obj/item/clothing/suit/storage/solgov/dress
name = "dress jacket"
desc = "A uniform dress jacket, fancy."
- icon_state = "sgdress_xpl"
- item_state = "sgdress_xpl"
+ icon_state = "ecdress_xpl"
+ item_state = "ecdress_xpl"
body_parts_covered = UPPER_TORSO|ARMS
armor = list(melee = 0, bullet = 0, laser = 0,energy = 0, bomb = 0, bio = 0, rad = 0)
siemens_coefficient = 0.9
@@ -192,39 +192,37 @@
/obj/item/clothing/suit/storage/solgov/dress/sifguard
name = "\improper SifGuard dress jacket"
desc = "A silver and grey dress jacket belonging to the Sif Defense Force. Fashionable, for the 25th century at least."
- icon_state = "sgdress_xpl"
- item_state = "sgdress_xpl"
/obj/item/clothing/suit/storage/solgov/dress/sifguard/senior
name = "\improper SifGuard senior's dress coat"
- icon_state = "sgdress_sxpl"
- item_state = "sgdress_sxpl"
+ icon_state = "ecdress_sxpl"
+ item_state = "ecdress_sxpl"
/obj/item/clothing/suit/storage/solgov/dress/sifguard/chief
name = "\improper SifGuard chief's dress coat"
icon_state = "ecdress_cxpl"
- item_state = "sgdress_cxpl"
+ item_state = "ecdress_cxpl"
/obj/item/clothing/suit/storage/solgov/dress/sifguard/command
name = "\improper SifGuard officer's dress coat"
desc = "A gold and black dress peacoat belonging to the Sif Defense Force. The height of fashion."
icon_state = "ecdress_ofcr"
- item_state = "sgdress_ofcr"
+ item_state = "ecdress_ofcr"
/obj/item/clothing/suit/storage/solgov/dress/sifguard/command/cdr
name = "\improper SifGuard commander's dress coat"
- icon_state = "sgdress_cdr"
- item_state = "sgdress_cdr"
+ icon_state = "ecdress_cdr"
+ item_state = "ecdress_cdr"
/obj/item/clothing/suit/storage/solgov/dress/sifguard/command/capt
name = "\improper SifGuard captain's dress coat"
- icon_state = "sgdress_capt"
- item_state = "sgdress_capt"
+ icon_state = "ecdress_capt"
+ item_state = "ecdress_capt"
/obj/item/clothing/suit/storage/solgov/dress/sifguard/command/adm
name = "\improper SifGuard admiral's dress coat"
- icon_state = "sgdress_adm"
- item_state = "sgdress_adm"
+ icon_state = "ecdress_adm"
+ item_state = "ecdress_adm"
/obj/item/clothing/suit/storage/solgov/dress/fleet
name = "fleet dress jacket"
@@ -273,7 +271,7 @@
name = "fleet dress overwear"
desc = "A navy blue SCG Fleet dress suit. Almost looks like a school-girl outfit."
icon_state = "sailordress"
- item_state = "whitedress"
+ item_state = "sailordress"
/obj/item/clothing/suit/dress/solgov/army
name = "marine dress jacket"
@@ -313,7 +311,7 @@
name = "clasped dress jacket"
desc = "A uniform dress jacket with gold toggles."
icon_state = "whitedress"
- item_state = "labcoat"
+ item_state = "whitedress"
blood_overlay_type = "coat"
/obj/item/clothing/suit/storage/toggle/dress/fleet
@@ -324,7 +322,7 @@
name = "fleet command dress jacket"
desc = "A crisp white SCG Fleet dress jacket dripping with gold accents. So bright it's blinding."
icon_state = "whitedress_com"
- item_state = "labcoat"
+ item_state = "whitedress_com"
blood_overlay_type = "coat"
/obj/item/clothing/suit/storage/eio_jacket
diff --git a/code/modules/clothing/under/accessories/accessory.dm b/code/modules/clothing/under/accessories/accessory.dm
index c6a886d26d..29e5c57526 100644
--- a/code/modules/clothing/under/accessories/accessory.dm
+++ b/code/modules/clothing/under/accessories/accessory.dm
@@ -157,6 +157,20 @@
desc = "A neosilk clip-on tie. This one is disgusting."
icon_state = "horribletie"
+/obj/item/clothing/accessory/bowtie
+ name = "red bow tie"
+ desc = "Snazzy!"
+ icon_state = "redbowtie"
+ slot = ACCESSORY_SLOT_TIE
+
+/obj/item/clothing/accessory/bowtie/black
+ name = "black bow tie"
+ icon_state = "blackbowtie"
+
+/obj/item/clothing/accessory/bowtie/white
+ name = "white bow tie"
+ icon_state = "whitebowtie"
+
/obj/item/clothing/accessory/stethoscope
name = "stethoscope"
desc = "An outdated medical apparatus for listening to the sounds of the human body. It also makes you look like you know what you're doing."
diff --git a/code/modules/clothing/under/accessories/badges.dm b/code/modules/clothing/under/accessories/badges.dm
index 75e8dc8e4d..49d66dcb6b 100644
--- a/code/modules/clothing/under/accessories/badges.dm
+++ b/code/modules/clothing/under/accessories/badges.dm
@@ -6,19 +6,14 @@
/obj/item/clothing/accessory/badge
name = "detective's badge"
- desc = "Security Department detective's badge, made from gold."
- icon_state = "badge"
+ desc = "NanoTrasen Security Department detective's badge, made from gold."
+ icon_state = "marshalbadge"
slot_flags = SLOT_BELT | SLOT_TIE
slot = ACCESSORY_SLOT_MEDAL
var/stored_name
var/badge_string = "Corporate Security"
-/obj/item/clothing/accessory/badge/old
- name = "faded badge"
- desc = "A faded badge, backed with leather. It bears the emblem of the Forensic division."
- icon_state = "badge_round"
-
/obj/item/clothing/accessory/badge/proc/set_name(var/new_name)
stored_name = new_name
name = "[initial(name)] ([stored_name])"
@@ -48,8 +43,8 @@
/obj/item/clothing/accessory/badge/sheriff
name = "sheriff badge"
desc = "This town ain't big enough for the two of us, pardner."
- icon_state = "sheriff"
- item_state = "goldbadge"
+ icon_state = "sheriff_toy"
+ item_state = "sheriff_toy"
/obj/item/clothing/accessory/badge/sheriff/attack_self(mob/user as mob)
user.visible_message("[user] shows their sheriff badge. There's a new sheriff in town!",\
@@ -61,10 +56,10 @@
user.do_attack_animation(M)
user.setClickCooldown(DEFAULT_QUICK_COOLDOWN) //to prevent spam
-//.Holobadges.
+//Security Holobadges
/obj/item/clothing/accessory/badge/holo
name = "holobadge"
- desc = "This glowing blue badge marks the holder as THE LAW."
+ desc = "This glowing blue badge marks the holder as law enforcement."
icon_state = "holobadge"
var/emagged //Emagging removes Sec check.
@@ -111,9 +106,16 @@
desc = "A box claiming to contain holobadges."
starts_with = list(
/obj/item/clothing/accessory/badge/holo = 4,
+ /obj/item/clothing/accessory/badge/holo/officer = 2,
/obj/item/clothing/accessory/badge/holo/cord = 2
)
+/obj/item/clothing/accessory/badge/holo/officer
+ name = "officer's badge"
+ desc = "A bronze corporate security badge. Stamped with the words 'Security Officer.'"
+ icon_state = "bronzebadge"
+ slot_flags = SLOT_TIE | SLOT_BELT
+
/obj/item/clothing/accessory/badge/holo/warden
name = "warden's holobadge"
desc = "A silver corporate security badge. Stamped with the words 'Warden.'"
@@ -122,7 +124,7 @@
/obj/item/clothing/accessory/badge/holo/hos
name = "head of security's holobadge"
- desc = "An immaculately polished gold security badge. Labeled 'Head of Security.'"
+ desc = "An immaculately polished gold security badge. Stamped with the words 'Head of Security.'"
icon_state = "goldbadge"
slot_flags = SLOT_TIE | SLOT_BELT
@@ -141,9 +143,65 @@
/obj/item/clothing/accessory/badge/holo/detective = 2,
/obj/item/clothing/accessory/badge/holo/hos = 1,
/obj/item/clothing/accessory/badge/holo/cord = 1
-
+
)
+/obj/item/clothing/accessory/badge/holo/investigator
+ name = "\improper Internal Investigations holobadge"
+ desc = "This badge marks the holder as an internal affairs investigator."
+ icon_state = "invbadge"
+ badge_string = "Internal Investigations"
+ slot_flags = SLOT_TIE | SLOT_BELT
+
+/obj/item/clothing/accessory/badge/holo/sheriff
+ name = "sheriff badge"
+ desc = "A star-shaped brass badge denoting who the law is around these parts."
+ icon_state = "sheriff"
+ slot_flags = SLOT_TIE | SLOT_BELT
+
+//Other badges
+
+/obj/item/clothing/accessory/badge/old
+ name = "faded badge"
+ desc = "A faded law enforcement badge in an older design."
+ icon_state = "badge_round"
+
+/obj/item/clothing/accessory/badge/solid
+ name = "\improper SolGov ID badge"
+ desc = "A descriptive identification badge with the holder's credentials. This one indicates the holder is representing the SCG."
+ icon_state = "solbadge"
+ badge_string = null
+
+/obj/item/clothing/accessory/badge/ntid
+ name = "\improper NT ID badge"
+ desc = "A descriptive identification badge with the holder's credentials. This one has red marks with the NanoTrasen logo on it."
+ icon_state = "ntbadge"
+ badge_string = null
+
+/obj/item/clothing/accessory/badge/press
+ name = "corporate press pass"
+ desc = "A corporate reporter's pass, emblazoned with the NanoTrasen logo."
+ icon_state = "pressbadge"
+ item_state = "pbadge"
+ badge_string = "Corporate Reporter"
+ w_class = ITEMSIZE_TINY
+
+ drop_sound = 'sound/items/drop/rubber.ogg'
+ pickup_sound = 'sound/items/pickup/rubber.ogg'
+
+/obj/item/clothing/accessory/badge/press/independent
+ name = "press pass"
+ desc = "A freelance journalist's pass, certified by Oculum Broadcast."
+ icon_state = "pressbadge-i"
+ badge_string = "Freelance Journalist"
+
+/obj/item/clothing/accessory/badge/press/plastic
+ name = "plastic press pass"
+ desc = "A journalist's 'pass' shaped, for whatever reason, like a security badge. It is made of plastic."
+ icon_state = "pbadge"
+ badge_string = "Sicurity Journelist"
+ w_class = ITEMSIZE_SMALL
+
// Synthmorph bag / Corporation badges. Primarily used on the robobag, but can be worn. Default is NT.
/obj/item/clothing/accessory/badge/corporate_tag
diff --git a/code/modules/clothing/under/accessories/holster.dm b/code/modules/clothing/under/accessories/holster.dm
index 72cbcb91ae..e99a816e86 100644
--- a/code/modules/clothing/under/accessories/holster.dm
+++ b/code/modules/clothing/under/accessories/holster.dm
@@ -135,22 +135,34 @@
desc = "A worn-out handgun holster. Perfect for concealed carry"
icon_state = "holster"
+/obj/item/clothing/accessory/holster/armpit/black
+ icon_state = "holster_b"
+
/obj/item/clothing/accessory/holster/waist
name = "waist holster"
desc = "A handgun holster. Made of expensive leather."
- icon_state = "holster"
+ icon_state = "holster_low"
overlay_state = "holster_low"
concealed_holster = 0
+/obj/item/clothing/accessory/holster/waist/black
+ icon_state = "holster_b_low"
+
/obj/item/clothing/accessory/holster/hip
name = "hip holster"
- desc = "A handgun holster slung low on the hip, draw pardner!"
+ desc = "No one dared to ask his business, no one dared to make a slip. The stranger there among them had a big iron on his hip."
icon_state = "holster_hip"
concealed_holster = 0
+/obj/item/clothing/accessory/holster/hip/black
+ icon_state = "holster_b_hip"
+
/obj/item/clothing/accessory/holster/leg
name = "leg holster"
- desc = "A tacticool handgun holster. Worn on the upper leg."
+ desc = "A drop leg holster worn on the upper leg."
icon_state = "holster_leg"
overlay_state = "holster_leg"
concealed_holster = 0
+
+/obj/item/clothing/accessory/holster/leg/black
+ icon_state = "holster_b_leg"
\ No newline at end of file
diff --git a/code/modules/clothing/under/miscellaneous.dm b/code/modules/clothing/under/miscellaneous.dm
index bcca912dcc..0533cbd9b4 100644
--- a/code/modules/clothing/under/miscellaneous.dm
+++ b/code/modules/clothing/under/miscellaneous.dm
@@ -1216,6 +1216,7 @@ Uniforms and such
desc = "A waistline this high is just made for ripping bodices, swashing buckles, or - just occasionally - sucking blood."
icon_state = "gayvampire"
worn_state = "gayvampire"
+ index = 1
/obj/item/clothing/under/rank/psych/turtleneck/sweater
desc = "A warm looking sweater and a pair of dark blue slacks."
@@ -1275,34 +1276,35 @@ Uniforms and such
//Ranger uniforms
//On-mob sprites go in icons\mob\uniform.dmi with the format "white_ranger_uniform_s" - with 'white' replaced with green, cyan, etc... of course! Note the _s - this is not optional.
//Item sprites go in icons\obj\clothing\ranger.dmi with the format "white_ranger_uniform"
-/obj/item/clothing/under/color/ranger
+/obj/item/clothing/under/ranger
var/unicolor = "white"
name = "ranger uniform"
desc = "Made from a space-proof fibre and tight fitting, this uniform usually gives the agile Rangers all kinds of protection while not inhibiting their movement. \
This costume is instead made from genuine cotton fibre and is based on the season three uniform."
icon = 'icons/obj/clothing/ranger.dmi'
icon_state = "ranger_uniform"
+ rolled_sleeves = FALSE
-/obj/item/clothing/under/color/ranger/Initialize()
+/obj/item/clothing/under/ranger/Initialize()
. = ..()
if(icon_state == "ranger_uniform") //allows for custom items
name = "[unicolor] ranger uniform"
icon_state = "[unicolor]_ranger_uniform"
-/obj/item/clothing/under/color/ranger/black
+/obj/item/clothing/under/ranger/black
unicolor = "black"
-/obj/item/clothing/under/color/ranger/pink
+/obj/item/clothing/under/ranger/pink
unicolor = "pink"
-/obj/item/clothing/under/color/ranger/green
+/obj/item/clothing/under/ranger/green
unicolor = "green"
-/obj/item/clothing/under/color/ranger/cyan
+/obj/item/clothing/under/ranger/cyan
unicolor = "cyan"
-/obj/item/clothing/under/color/ranger/orange
+/obj/item/clothing/under/ranger/orange
unicolor = "orange"
-/obj/item/clothing/under/color/ranger/yellow
+/obj/item/clothing/under/ranger/yellow
unicolor = "yellow"
\ No newline at end of file
diff --git a/code/modules/events/money_hacker.dm b/code/modules/events/money_hacker.dm
index 025bcc6901..86f7be0e49 100644
--- a/code/modules/events/money_hacker.dm
+++ b/code/modules/events/money_hacker.dm
@@ -52,7 +52,7 @@ GLOBAL_VAR_INIT(account_hack_attempted, 0)
var/date2 = "[num2text(rand(1,31))] [pick("January","February","March","April","May","June","July","August","September","October","November","December")], [rand(1000,3000)]"
T.date = pick("", current_date_string, date1, date2)
var/time1 = rand(0, 99999999)
- var/time2 = "[round(time1 / 36000)+12]:[(time1 / 600 % 60) < 10 ? add_zero(time1 / 600 % 60, 1) : time1 / 600 % 60]"
+ var/time2 = "[round(time1 / 36000)+12]:[(time1 / 600 % 60) < 10 ? pad_left("[time1 / 600 % 60]", 2, "0") : time1 / 600 % 60]"
T.time = pick("", stationtime2text(), time2)
T.source_terminal = pick("","[pick("Biesel","New Gibson")] GalaxyNet Terminal #[rand(111,999)]","your mums place","nantrasen high CommanD")
diff --git a/code/modules/gamemaster/event2/events/command/money_hacker.dm b/code/modules/gamemaster/event2/events/command/money_hacker.dm
index b365fdaef2..a0831495a8 100644
--- a/code/modules/gamemaster/event2/events/command/money_hacker.dm
+++ b/code/modules/gamemaster/event2/events/command/money_hacker.dm
@@ -103,7 +103,7 @@
T.date = pick("", current_date_string, date1, date2,"Nowhen")
var/time1 = rand(0, 99999999)
- var/time2 = "[round(time1 / 36000)+12]:[(time1 / 600 % 60) < 10 ? add_zero(time1 / 600 % 60, 1) : time1 / 600 % 60]"
+ var/time2 = "[round(time1 / 36000)+12]:[(time1 / 600 % 60) < 10 ? pad_left("[time1 / 600 % 60]", 2, "0") : time1 / 600 % 60]"
T.time = pick("", stationtime2text(), time2, "Never")
T.source_terminal = pick("","[pick("Biesel","New Gibson")] GalaxyNet Terminal #[rand(111,999)]","your mums place","nantrasen high CommanD","Angessa's Pearl","Nowhere")
diff --git a/code/modules/hydroponics/seed_controller.dm b/code/modules/hydroponics/seed_controller.dm
index 85c6a5f51e..6a5012f514 100644
--- a/code/modules/hydroponics/seed_controller.dm
+++ b/code/modules/hydroponics/seed_controller.dm
@@ -97,11 +97,10 @@ var/global/datum/controller/plants/plant_controller // Set in New().
var/list/plant_traits = ALL_GENES
while(plant_traits && plant_traits.len)
var/gene_tag = pick(plant_traits)
- var/gene_mask = "[uppertext(num2hex(rand(0,255), 2))]"
-
- while(gene_mask in used_masks)
- gene_mask = "[uppertext(num2hex(rand(0,255), 2))]"
-
+ var/gene_mask
+ do
+ gene_mask = random_hex_text(2, TRUE)
+ while (gene_mask in used_masks)
var/decl/plantgene/G
for(var/D in gene_datums)
diff --git a/code/modules/materials/materials/metals/steel.dm b/code/modules/materials/materials/metals/steel.dm
index 10560dec36..e871e03070 100644
--- a/code/modules/materials/materials/metals/steel.dm
+++ b/code/modules/materials/materials/metals/steel.dm
@@ -28,6 +28,18 @@
new /datum/stack_recipe("yellow comfy chair", /obj/structure/bed/chair/comfy/yellow, 2, one_per_turf = 1, on_floor = 1, recycle_material = "[name]"),
new /datum/stack_recipe("orange comfy chair", /obj/structure/bed/chair/comfy/orange, 2, one_per_turf = 1, on_floor = 1, recycle_material = "[name]"),
)),
+ new /datum/stack_recipe_list("rounded chairs", list(
+ new /datum/stack_recipe("beige rounded chair", /obj/structure/bed/chair/rounded/beige, 2, one_per_turf = 1, on_floor = 1, recycle_material = "[name]"),
+ new /datum/stack_recipe("black rounded chair", /obj/structure/bed/chair/rounded/black, 2, one_per_turf = 1, on_floor = 1, recycle_material = "[name]"),
+ new /datum/stack_recipe("brown rounded chair", /obj/structure/bed/chair/rounded/brown, 2, one_per_turf = 1, on_floor = 1, recycle_material = "[name]"),
+ new /datum/stack_recipe("lime rounded chair", /obj/structure/bed/chair/rounded/lime, 2, one_per_turf = 1, on_floor = 1, recycle_material = "[name]"),
+ new /datum/stack_recipe("teal rounded chair", /obj/structure/bed/chair/rounded/teal, 2, one_per_turf = 1, on_floor = 1, recycle_material = "[name]"),
+ new /datum/stack_recipe("red rounded chair", /obj/structure/bed/chair/rounded/red, 2, one_per_turf = 1, on_floor = 1, recycle_material = "[name]"),
+ new /datum/stack_recipe("blue rounded chair", /obj/structure/bed/chair/rounded/blue, 2, one_per_turf = 1, on_floor = 1, recycle_material = "[name]"),
+ new /datum/stack_recipe("purple rounded chair", /obj/structure/bed/chair/rounded/purple, 2, one_per_turf = 1, on_floor = 1, recycle_material = "[name]"),
+ new /datum/stack_recipe("green rounded chair", /obj/structure/bed/chair/rounded/green, 2, one_per_turf = 1, on_floor = 1, recycle_material = "[name]"),
+ new /datum/stack_recipe("yellow rounded chair", /obj/structure/bed/chair/rounded/yellow, 2, one_per_turf = 1, on_floor = 1, recycle_material = "[name]"),
+ )),
new /datum/stack_recipe_list("airlock assemblies", list(
new /datum/stack_recipe("standard airlock assembly", /obj/structure/door_assembly, 4, time = 50, one_per_turf = 1, on_floor = 1, recycle_material = "[name]"),
new /datum/stack_recipe("command airlock assembly", /obj/structure/door_assembly/door_assembly_com, 4, time = 50, one_per_turf = 1, on_floor = 1, recycle_material = "[name]"),
diff --git a/code/modules/materials/materials/organic/leather.dm b/code/modules/materials/materials/organic/leather.dm
index f5fc8cb2f9..cb564bcbd6 100644
--- a/code/modules/materials/materials/organic/leather.dm
+++ b/code/modules/materials/materials/organic/leather.dm
@@ -1,6 +1,6 @@
/datum/material/leather
name = MAT_LEATHER
- display_name = "plainleather"
+ display_name = "plain leather"
icon_colour = "#5C4831"
stack_type = /obj/item/stack/material/leather
stack_origin_tech = list(TECH_MATERIAL = 2, TECH_BIO = 2)
diff --git a/code/modules/mining/mine_turfs.dm b/code/modules/mining/mine_turfs.dm
index 2c537bd4c8..30fe22fc78 100644
--- a/code/modules/mining/mine_turfs.dm
+++ b/code/modules/mining/mine_turfs.dm
@@ -23,6 +23,8 @@ var/list/mining_overlay_cache = list()
var/rock_side_icon_state = "rock_side"
var/sand_icon_state = "asteroid"
var/rock_icon_state = "rock"
+ var/sand_icon_path = 'icons/turf/flooring/asteroid.dmi' // Override this on a subtype turf if you want a custom icon
+ var/rock_icon_path = 'icons/turf/walls.dmi' // Override this on a subtype turf if you want a custom icon
var/random_icon = 0
var/ore/mineral
@@ -30,6 +32,7 @@ var/list/mining_overlay_cache = list()
var/mined_ore = 0
var/last_act = 0
var/overlay_detail
+ var/overlay_detail_icon_path = 'icons/turf/flooring/decals.dmi' // Override this on a subtype turf if you want a custom icon
var/datum/geosample/geologic_data
var/excavation_level = 0
@@ -266,7 +269,7 @@ var/list/mining_overlay_cache = list()
else
name = "rock"
- icon = 'icons/turf/walls.dmi'
+ icon = rock_icon_path
icon_state = rock_icon_state
//Apply overlays if we should have borders
@@ -284,7 +287,7 @@ var/list/mining_overlay_cache = list()
//We are a sand floor
else
name = floor_name
- icon = 'icons/turf/flooring/asteroid.dmi'
+ icon = sand_icon_path
icon_state = sand_icon_state
if(sand_dug)
@@ -299,11 +302,11 @@ var/list/mining_overlay_cache = list()
else
var/turf/T = get_step(src, direction)
if(istype(T) && T.density)
- add_overlay(get_cached_border(rock_side_icon_state,direction,'icons/turf/walls.dmi',rock_side_icon_state))
+ add_overlay(get_cached_border(rock_side_icon_state,direction,rock_icon_path,rock_side_icon_state))
if(overlay_detail)
if(overlay_detail in icon_states(icon))
- add_overlay('icons/turf/flooring/decals.dmi',overlay_detail)
+ add_overlay(overlay_detail_icon_path,overlay_detail)
if(update_neighbors)
for(var/direction in alldirs)
diff --git a/code/modules/mob/living/autohiss.dm b/code/modules/mob/living/autohiss.dm
index 7a3999ea36..a51616a56f 100644
--- a/code/modules/mob/living/autohiss.dm
+++ b/code/modules/mob/living/autohiss.dm
@@ -55,6 +55,18 @@
)
autohiss_exempt = list(LANGUAGE_SIIK,LANGUAGE_AKHANI)
+/datum/species/zaddat
+ autohiss_basic_map = list(
+ "f" = list("v","vh"),
+ "ph" = list("v", "vh")
+ )
+ autohiss_extra_map = list(
+ "s" = list("z", "zz", "zzz"),
+ "ce" = list("z", "zz"),
+ "ci" = list("z", "zz"),
+ "v" = list("vv", "vvv")
+ )
+ autohiss_exempt = list(LANGUAGE_ZADDAT)
/datum/species/proc/handle_autohiss(message, datum/language/lang, mode)
if(!autohiss_basic_map)
diff --git a/code/modules/mob/living/carbon/human/examine.dm b/code/modules/mob/living/carbon/human/examine.dm
index efa90d3116..ba0d770728 100644
--- a/code/modules/mob/living/carbon/human/examine.dm
+++ b/code/modules/mob/living/carbon/human/examine.dm
@@ -76,22 +76,12 @@
BP_L_LEG = skip_body & EXAMINE_SKIPLEGS,
BP_R_LEG = skip_body & EXAMINE_SKIPLEGS)
- var/datum/gender/T = gender_datums[get_visible_gender()]
-
- if((skip_gear & EXAMINE_SKIPJUMPSUIT) && (skip_body & EXAMINE_SKIPFACE)) //big suits/masks/helmets make it hard to tell their gender
- T = gender_datums[PLURAL]
-
- else if(species && species.ambiguous_genders)
- if(ishuman(user))
- var/mob/living/carbon/human/H = user
- if(H.species && !istype(species, H.species))
- T = gender_datums[PLURAL]// Species with ambiguous_genders will not show their true gender upon examine if the examiner is not also the same species.
- if(!(issilicon(user) || isobserver(user))) // Ghosts and borgs are all knowing
- T = gender_datums[PLURAL]
-
- if(!T)
- // Just in case someone VVs the gender to something strange. It'll runtime anyway when it hits usages, better to CRASH() now with a helpful message.
- CRASH("Gender datum was null; key was '[((skip_gear & EXAMINE_SKIPJUMPSUIT) && (skip_body & EXAMINE_SKIPFACE)) ? PLURAL : gender]'")
+
+ var/gender_hidden = (skip_gear & EXAMINE_SKIPJUMPSUIT) && (skip_body & EXAMINE_SKIPFACE)
+ var/gender_key = get_visible_gender(user, gender_hidden)
+ var/datum/gender/T = gender_datums[gender_key]
+ if (!T)
+ CRASH({"Null gender datum on examine: mob="[src]",hidden="[gender_hidden]",key="[gender_key]",bio="[gender]",id="[identifying_gender]""})
var/name_ender = ""
if(!((skip_gear & EXAMINE_SKIPJUMPSUIT) && (skip_body & EXAMINE_SKIPFACE)))
diff --git a/code/modules/mob/living/carbon/human/human.dm b/code/modules/mob/living/carbon/human/human.dm
index b0b2a7c8ae..20e5469e75 100644
--- a/code/modules/mob/living/carbon/human/human.dm
+++ b/code/modules/mob/living/carbon/human/human.dm
@@ -849,13 +849,27 @@
remoteview_target = null
reset_view(0)
-/mob/living/carbon/human/get_visible_gender()
- if(wear_suit && wear_suit.flags_inv & HIDEJUMPSUIT && ((head && head.flags_inv & HIDEMASK) || wear_mask))
- return PLURAL //plural is the gender-neutral default
- if(species)
- if(species.ambiguous_genders)
- return PLURAL // regardless of what you're wearing, your gender can't be figured out
- return get_gender()
+
+/mob/living/carbon/human/get_visible_gender(mob/user, force)
+ switch (force)
+ if (VISIBLE_GENDER_FORCE_PLURAL)
+ return PLURAL
+ if (VISIBLE_GENDER_FORCE_IDENTIFYING)
+ return get_gender()
+ if (VISIBLE_GENDER_FORCE_BIOLOGICAL)
+ return gender
+ else
+ if ((wear_mask || (head?.flags_inv & HIDEMASK)) && (wear_suit?.flags_inv & HIDEJUMPSUIT))
+ return PLURAL
+ if (species?.ambiguous_genders && user)
+ if (ishuman(user))
+ var/mob/living/carbon/human/human = user
+ if (!istype(human.species, species))
+ return PLURAL
+ else if (!isobserver(user) && !issilicon(user))
+ return PLURAL
+ return get_gender()
+
/mob/living/carbon/human/proc/increase_germ_level(n)
if(gloves)
diff --git a/code/modules/mob/living/carbon/human/species/species_shapeshift.dm b/code/modules/mob/living/carbon/human/species/species_shapeshift.dm
index 79d19b66db..1691d87bb2 100644
--- a/code/modules/mob/living/carbon/human/species/species_shapeshift.dm
+++ b/code/modules/mob/living/carbon/human/species/species_shapeshift.dm
@@ -322,7 +322,7 @@ var/list/wrapped_species_by_ref = list()
/mob/living/carbon/human/proc/shapeshifter_set_eye_color(var/new_eyes)
- var/list/new_color_rgb_list = hex2rgb(new_eyes)
+ var/list/new_color_rgb_list = rgb2num(new_eyes)
// First, update mob vars.
r_eyes = new_color_rgb_list[1]
g_eyes = new_color_rgb_list[2]
diff --git a/code/modules/mob/living/living.dm b/code/modules/mob/living/living.dm
index b0373cbcef..67a57e4f33 100644
--- a/code/modules/mob/living/living.dm
+++ b/code/modules/mob/living/living.dm
@@ -938,7 +938,7 @@
var/B = 0
for(var/C in colors_to_blend)
- var/RGB = hex2rgb(C)
+ var/RGB = rgb2num(C)
R = between(0, R + RGB[1], 255)
G = between(0, G + RGB[2], 255)
B = between(0, B + RGB[3], 255)
diff --git a/code/modules/mob/living/silicon/pai/pai.dm b/code/modules/mob/living/silicon/pai/pai.dm
index fcc1fd62df..dff56aef72 100644
--- a/code/modules/mob/living/silicon/pai/pai.dm
+++ b/code/modules/mob/living/silicon/pai/pai.dm
@@ -133,7 +133,7 @@
/mob/living/silicon/pai/proc/show_silenced()
if(src.silence_time)
var/timeleft = round((silence_time - world.timeofday)/10 ,1)
- stat(null, "Communications system reboot in -[(timeleft / 60) % 60]:[add_zero(num2text(timeleft % 60), 2)]")
+ stat(null, "Communications system reboot in -[(timeleft / 60) % 60]:[pad_left(num2text(timeleft % 60), 2, "0")]")
/mob/living/silicon/pai/Stat()
diff --git a/code/modules/mob/living/simple_mob/subtypes/mechanical/viscerator.dm b/code/modules/mob/living/simple_mob/subtypes/mechanical/viscerator.dm
index 915c14e9f7..6c1d5b738b 100644
--- a/code/modules/mob/living/simple_mob/subtypes/mechanical/viscerator.dm
+++ b/code/modules/mob/living/simple_mob/subtypes/mechanical/viscerator.dm
@@ -57,14 +57,14 @@
// Used for a special grenade, to ensure they don't attack the wrong thing.
/mob/living/simple_mob/mechanical/viscerator/mercenary/IIsAlly(mob/living/L)
. = ..()
- if(!.) // Not friendly, see if they're a baddie first.
+ if(!. && isliving(L)) // Not friendly, see if they're a baddie first.
if(L.mind && mercs.is_antagonist(L.mind))
return TRUE
// Similar to above but for raiders.
/mob/living/simple_mob/mechanical/viscerator/raider/IIsAlly(mob/living/L)
. = ..()
- if(!.) // Not friendly, see if they're a baddie first.
+ if(!. && isliving(L)) // Not friendly, see if they're a baddie first.
if(L.mind && raiders.is_antagonist(L.mind))
return TRUE
@@ -83,7 +83,7 @@
/mob/living/simple_mob/mechanical/viscerator/station/IIsAlly(mob/living/L)
. = ..()
- if(!.)
+ if(!. && isliving(L))
if(isrobot(L)) // They ignore synths.
return TRUE
if(istype(L, /mob/living/simple_mob/mechanical/ward/monitor/crew)) // Also ignore friendly monitor wards
@@ -97,4 +97,4 @@
movement_cooldown = 0.5
/decl/mob_organ_names/viscerator
- hit_zones = list("chassis", "rotor blades", "sensor array")
\ No newline at end of file
+ hit_zones = list("chassis", "rotor blades", "sensor array")
diff --git a/code/modules/mob/mob_helpers.dm b/code/modules/mob/mob_helpers.dm
index c908b7952b..2383700ed3 100644
--- a/code/modules/mob/mob_helpers.dm
+++ b/code/modules/mob/mob_helpers.dm
@@ -86,13 +86,6 @@
return check_rights(R_ADMIN|R_EVENT, 0, user) != 0
-/proc/hsl2rgb(h, s, l)
- return //TODO: Implement
-
-/*
- Miss Chance
-*/
-
/proc/check_zone(zone)
if(!zone) return BP_TORSO
switch(zone)
diff --git a/code/modules/mob/new_player/preferences_setup.dm b/code/modules/mob/new_player/preferences_setup.dm
index 9ac1263238..7796c86ea1 100644
--- a/code/modules/mob/new_player/preferences_setup.dm
+++ b/code/modules/mob/new_player/preferences_setup.dm
@@ -29,7 +29,7 @@
all_underwear[WRC.name] = WRI.name
- backbag = rand(1,5)
+ backbag = rand(1,6)
pdachoice = rand(1,5)
age = rand(current_species.min_age, current_species.max_age)
b_type = RANDOM_BLOOD_TYPE
diff --git a/code/modules/organs/internal/eyes.dm b/code/modules/organs/internal/eyes.dm
index e7e8c5f135..18307d69a9 100644
--- a/code/modules/organs/internal/eyes.dm
+++ b/code/modules/organs/internal/eyes.dm
@@ -40,7 +40,7 @@
var/new_color = input("Pick a new color for your eyes.","Eye Color", current_color) as null|color
if(new_color && owner)
// input() supplies us with a hex color, which we can't use, so we convert it to rbg values.
- var/list/new_color_rgb_list = hex2rgb(new_color)
+ var/list/new_color_rgb_list = rgb2num(new_color)
// First, update mob vars.
owner.r_eyes = new_color_rgb_list[1]
owner.g_eyes = new_color_rgb_list[2]
diff --git a/code/modules/paperwork/pen.dm b/code/modules/paperwork/pen.dm
index 1c8af09d9e..5a988e3100 100644
--- a/code/modules/paperwork/pen.dm
+++ b/code/modules/paperwork/pen.dm
@@ -43,10 +43,6 @@
icon_state = "pen_red"
colour = "red"
-/obj/item/weapon/pen/fountain
- desc = "A well made fountain pen."
- icon_state = "pen_fountain"
-
/obj/item/weapon/pen/multi
desc = "It's a pen with multiple colors of ink!"
var/selectedColor = 1
@@ -75,6 +71,46 @@
icon_state = "pen"
colour = "white"
+//Fountain Pens
+
+/obj/item/weapon/pen/fountain
+ desc = "A well made fountain pen with a faux-wood finish."
+ icon_state = "pen_fountain"
+
+/obj/item/weapon/pen/fountain2
+ desc = "A well made fountain pen, with a faux wood body. This one has golden accents."
+ icon_state = "pen_fountain2"
+
+/obj/item/weapon/pen/fountain3
+ desc = "A well made expensive rosewood pen with golden accents. Very pretty."
+ icon_state = "red_fountain"
+
+/obj/item/weapon/pen/fountain4
+ desc = "A well made and expensive fountain pen. This one has silver accents."
+ icon_state = "blues_fountain"
+
+/obj/item/weapon/pen/fountain5
+ desc = "A well made and expensive fountain pen. This one has gold accents."
+ icon_state = "blueg_fountain"
+
+/obj/item/weapon/pen/fountain6
+ desc = "A well made and expensive fountain pen. The nib is quite sharp."
+ icon_state = "command_fountain"
+
+/obj/item/weapon/pen/fountain7
+ desc = "A well made and expensive fountain pen made from gold."
+ icon_state = "gold_fountain"
+
+/obj/item/weapon/pen/fountain8
+ desc = "A well made and expensive fountain pen."
+ icon_state = "black_fountain"
+
+/obj/item/weapon/pen/fountain9
+ desc = "A well made and expensive fountain pen made for gesturing."
+ icon_state = "mime_fountain"
+
+
+
/*
* Reagent pens
*/
diff --git a/code/modules/paperwork/photocopier.dm b/code/modules/paperwork/photocopier.dm
index 5d554b05d3..738017e5d7 100644
--- a/code/modules/paperwork/photocopier.dm
+++ b/code/modules/paperwork/photocopier.dm
@@ -2,8 +2,8 @@
name = "photocopier"
desc = "Copy all your important papers here!"
icon = 'icons/obj/library.dmi'
- icon_state = "bigscanner"
- var/insert_anim = "bigscanner1"
+ icon_state = "photocopier"
+ var/insert_anim = "photocopier_scan"
anchored = 1
density = 1
use_power = USE_POWER_IDLE
@@ -72,12 +72,14 @@
sleep(11)
copy(copyitem)
audible_message("You can hear [src] whirring as it finishes printing.", runemessage = "whirr")
+ flick("photocopier_print", src)
playsound(src, "sound/machines/buzzbeep.ogg", 30)
else if (istype(copyitem, /obj/item/weapon/photo))
playsound(loc, "sound/machines/copier.ogg", 100, 1)
sleep(11)
photocopy(copyitem)
audible_message("You can hear [src] whirring as it finishes printing.", runemessage = "whirr")
+ flick("photocopier_print", src)
playsound(src, "sound/machines/buzzbeep.ogg", 30)
else if (istype(copyitem, /obj/item/weapon/paper_bundle))
sleep(11)
@@ -85,6 +87,7 @@
var/obj/item/weapon/paper_bundle/B = bundlecopy(copyitem)
sleep(11*B.pages.len)
audible_message("You can hear [src] whirring as it finishes printing.", runemessage = "whirr")
+ flick("photocopier_print", src)
playsound(src, "sound/machines/buzzbeep.ogg", 30)
else
to_chat(user, "\The [copyitem] can't be copied by [src].")
@@ -151,11 +154,15 @@
if(toner <= 10) //allow replacing when low toner is affecting the print darkness
user.drop_item()
to_chat(user, "You insert the toner cartridge into \the [src].")
+ flick("photocopier_toner", src)
+ playsound(loc, 'sound/machines/click.ogg', 50, 1)
var/obj/item/device/toner/T = O
toner += T.toner_amount
qdel(O)
else
to_chat(user, "This cartridge is not yet ready for replacement! Use up the rest of the toner.")
+ flick("photocopier_notoner", src)
+ playsound(loc, 'sound/machines/buzz-two.ogg', 75, 1)
else if(O.is_wrench())
playsound(src, O.usesound, 50, 1)
anchored = !anchored
diff --git a/code/modules/paperwork/stamps.dm b/code/modules/paperwork/stamps.dm
index 449f08e723..f567cf478a 100644
--- a/code/modules/paperwork/stamps.dm
+++ b/code/modules/paperwork/stamps.dm
@@ -48,6 +48,10 @@
icon_state = "stamp-deny"
attack_verb = list("DENIED")
+/obj/item/weapon/stamp/accepted
+ name = "\improper ACCEPTED rubber stamp"
+ icon_state = "stamp-ok"
+
/obj/item/weapon/stamp/clown
name = "clown's rubber stamp"
icon_state = "stamp-clown"
@@ -72,6 +76,21 @@
name = "\improper Sol Government rubber stamp"
icon_state = "stamp-sg"
+/obj/item/weapon/stamp/solgovlogo
+ name = "\improper Sol Government logo stamp"
+ icon_state = "stamp-sol"
+
+/obj/item/stamp/einstein
+ name = "\improper Einstein Engines rubber stamp"
+ icon_state = "stamp-einstein"
+
+/obj/item/stamp/hephaestus
+ name = "\improper Hephaestus Industries rubber stamp"
+ icon_state = "stamp-heph"
+
+/obj/item/stamp/zeng_hu
+ name = "\improper Zeng-Hu Pharmaceuticals rubber stamp"
+ icon_state = "stamp-zenghu"
// Syndicate stamp to forge documents.
/obj/item/weapon/stamp/chameleon/attack_self(mob/user as mob)
diff --git a/code/modules/planet/sif.dm b/code/modules/planet/sif.dm
index b418a42db0..867fc829f0 100644
--- a/code/modules/planet/sif.dm
+++ b/code/modules/planet/sif.dm
@@ -81,12 +81,12 @@ var/datum/planet/sif/planet_sif = null
if(weather_holder && weather_holder.current_weather && weather_holder.current_weather.light_color)
new_color = weather_holder.current_weather.light_color
else
- var/list/low_color_list = hex2rgb(low_color)
+ var/list/low_color_list = rgb2num(low_color)
var/low_r = low_color_list[1]
var/low_g = low_color_list[2]
var/low_b = low_color_list[3]
- var/list/high_color_list = hex2rgb(high_color)
+ var/list/high_color_list = rgb2num(high_color)
var/high_r = high_color_list[1]
var/high_g = high_color_list[2]
var/high_b = high_color_list[3]
diff --git a/code/modules/power/cell.dm b/code/modules/power/cell.dm
index a1d31cdfa1..7fd8688a2c 100644
--- a/code/modules/power/cell.dm
+++ b/code/modules/power/cell.dm
@@ -53,6 +53,12 @@
if(self_recharge)
if(world.time >= last_use + charge_delay)
give(charge_amount)
+ // TGMC Ammo HUD - Update the HUD every time we're called to recharge.
+ if(istype(loc, /obj/item/weapon/gun/energy)) // Are we in a gun currently?
+ var/obj/item/weapon/gun/energy/gun = loc
+ var/mob/living/user = gun.loc
+ if(istype(user))
+ user?.hud_used.update_ammo_hud(user, gun) // Update the HUD
else
return PROCESS_KILL
diff --git a/code/modules/power/cells/esoteric_cells.dm b/code/modules/power/cells/esoteric_cells.dm
index b9bb06bf68..346d3b3ad1 100644
--- a/code/modules/power/cells/esoteric_cells.dm
+++ b/code/modules/power/cells/esoteric_cells.dm
@@ -69,6 +69,7 @@
C4.visible_message("The current fries \the [C4]!")
if(prob(10))
- C4.explode(get_turf(src))
+ C4.set_target(src)
+ C4.detonate()
else
qdel(C4)
diff --git a/code/modules/projectiles/gun.dm b/code/modules/projectiles/gun.dm
index d19e6d6ca9..0bb9c643bb 100644
--- a/code/modules/projectiles/gun.dm
+++ b/code/modules/projectiles/gun.dm
@@ -401,6 +401,8 @@
if(muzzle_flash)
set_light(0)
+
+ user.hud_used.update_ammo_hud(user, src)
// Similar to the above proc, but does not require a user, which is ideal for things like turrets.
/obj/item/weapon/gun/proc/Fire_userless(atom/target)
@@ -493,6 +495,7 @@
/obj/item/weapon/gun/proc/handle_click_empty(mob/user)
if (user)
user.visible_message("*click click*", "*click*")
+ user.hud_used.update_ammo_hud(user, src)
else
src.visible_message("*click click*")
playsound(src, 'sound/weapons/empty.ogg', 100, 1)
@@ -724,8 +727,35 @@
var/datum/firemode/new_mode = firemodes[sel_mode]
new_mode.apply_to(src)
to_chat(user, "\The [src] is now set to [new_mode.name].")
+ user.hud_used.update_ammo_hud(user, src)
return new_mode
/obj/item/weapon/gun/attack_self(mob/user)
switch_firemodes(user)
+
+/* TGMC Ammo HUD Port Begin */
+/obj/item/weapon/gun
+ var/hud_enabled = TRUE
+
+/obj/item/weapon/gun/proc/has_ammo_counter()
+ return FALSE
+
+/obj/item/weapon/gun/proc/get_ammo_type()
+ return FALSE
+
+/obj/item/weapon/gun/proc/get_ammo_count()
+ return FALSE
+
+/obj/item/weapon/gun/equipped(mob/living/user, slot) // When a gun is equipped to your hands, we'll add the HUD to the user. Pending porting over TGMC guncode where wielding is far more sensible.
+ if(slot == slot_l_hand || slot == slot_r_hand)
+ user.hud_used.add_ammo_hud(user, src)
+ else
+ user.hud_used.remove_ammo_hud(user, src)
+
+ return ..()
+
+/obj/item/weapon/gun/dropped(mob/living/user) // Ditto as above, we remove the HUD. Pending porting TGMC code to clean up this fucking nightmare of spaghetti.
+ user.hud_used.remove_ammo_hud(user, src)
+
+ ..()
\ No newline at end of file
diff --git a/code/modules/projectiles/guns/energy.dm b/code/modules/projectiles/guns/energy.dm
index 245aad9a95..91ca21f48e 100644
--- a/code/modules/projectiles/guns/energy.dm
+++ b/code/modules/projectiles/guns/energy.dm
@@ -90,6 +90,9 @@
power_supply.give(rechargeamt) //... to recharge 1/5th the battery
update_icon()
+ var/mob/living/M = loc // TGMC Ammo HUD
+ if(istype(M)) // TGMC Ammo HUD
+ M?.hud_used.update_ammo_hud(M, src) // TGMC Ammo HUD
else
charge_tick = 0
return 1
@@ -109,6 +112,9 @@
if(!power_supply) return null
if(!ispath(projectile_type)) return null
if(!power_supply.checked_use(charge_cost)) return null
+ var/mob/living/M = loc // TGMC Ammo HUD
+ if(istype(M)) // TGMC Ammo HUD
+ M?.hud_used.update_ammo_hud(M, src)
return new projectile_type(src)
/obj/item/weapon/gun/energy/proc/load_ammo(var/obj/item/C, mob/user)
@@ -130,6 +136,7 @@
playsound(src, 'sound/weapons/flipblade.ogg', 50, 1)
update_icon()
update_held_icon()
+ user.hud_used.update_ammo_hud(user, src) // TGMC Ammo HUD
else
to_chat(user, "This cell is not fitted for [src].")
return
@@ -146,6 +153,7 @@
playsound(src, 'sound/weapons/empty.ogg', 50, 1)
update_icon()
update_held_icon()
+ user.hud_used.update_ammo_hud(user, src) // TGMC Ammo HUD
else
to_chat(user, "[src] does not have a power cell.")
@@ -231,4 +239,21 @@
results += ..()
- return results
\ No newline at end of file
+ return results
+
+// TGMC AMMO HUD
+/obj/item/weapon/gun/energy/has_ammo_counter()
+ return TRUE
+
+/obj/item/weapon/gun/energy/get_ammo_type()
+ if(!projectile_type)
+ return list("unknown", "unknown")
+ else
+ var/obj/item/projectile/P = projectile_type
+ return list(initial(P.hud_state), initial(P.hud_state_empty))
+
+/obj/item/weapon/gun/energy/get_ammo_count()
+ if(!power_supply)
+ return 0
+ else
+ return FLOOR(power_supply.charge / max(charge_cost, 1), 1)
\ No newline at end of file
diff --git a/code/modules/projectiles/guns/projectile.dm b/code/modules/projectiles/guns/projectile.dm
index a8b1ab929d..8ce418b5f1 100644
--- a/code/modules/projectiles/guns/projectile.dm
+++ b/code/modules/projectiles/guns/projectile.dm
@@ -54,6 +54,10 @@
chambered = ammo_magazine.stored_ammo[ammo_magazine.stored_ammo.len]
if(handle_casings != HOLD_CASINGS)
ammo_magazine.stored_ammo -= chambered
+
+ var/mob/living/M = loc
+ if(istype(M))
+ M?.hud_used.update_ammo_hud(M, src)
if (chambered)
return chambered.BB
@@ -98,6 +102,10 @@
if(handle_casings != HOLD_CASINGS)
chambered = null
+
+ var/mob/living/M = loc
+ if(istype(M))
+ M?.hud_used.update_ammo_hud(M, src)
//Attempts to load A into src, depending on the type of thing being loaded and the load_method
@@ -117,6 +125,7 @@
AM.loc = src
ammo_magazine = AM
user.visible_message("[user] inserts [AM] into [src].", "You insert [AM] into [src].")
+ user.hud_used.update_ammo_hud(user, src)
playsound(src, 'sound/weapons/flipblade.ogg', 50, 1)
if(SPEEDLOADER)
if(loaded.len >= max_shells)
@@ -131,8 +140,10 @@
loaded += C
AM.stored_ammo -= C //should probably go inside an ammo_magazine proc, but I guess less proc calls this way...
count++
+ user.hud_used.update_ammo_hud(user, src)
if(count)
user.visible_message("[user] reloads [src].", "You load [count] round\s into [src].")
+ user.hud_used.update_ammo_hud(user, src)
playsound(src, 'sound/weapons/empty.ogg', 50, 1)
AM.update_icon()
else if(istype(A, /obj/item/ammo_casing))
@@ -168,6 +179,7 @@
sleep(1 SECOND)
update_icon()
+ user.hud_used.update_ammo_hud(user, src)
//attempts to unload src. If allow_dump is set to 0, the speedloader unloading method will be disabled
/obj/item/weapon/gun/projectile/proc/unload_ammo(mob/user, var/allow_dump=1)
@@ -177,6 +189,7 @@
playsound(src, 'sound/weapons/empty.ogg', 50, 1)
ammo_magazine.update_icon()
ammo_magazine = null
+ user.hud_used.update_ammo_hud(user, src)
else if(loaded.len)
//presumably, if it can be speed-loaded, it can be speed-unloaded.
if(allow_dump && (load_method & SPEEDLOADER))
@@ -195,9 +208,11 @@
user.put_in_hands(C)
user.visible_message("[user] removes \a [C] from [src].", "You remove \a [C] from [src].")
playsound(src, 'sound/weapons/empty.ogg', 50, 1)
+ user.hud_used.update_ammo_hud(user, src)
else
to_chat(user, "[src] is empty.")
update_icon()
+ user.hud_used.update_ammo_hud(user, src)
/obj/item/weapon/gun/projectile/attackby(var/obj/item/A as obj, mob/user as mob)
..()
@@ -228,6 +243,7 @@
ammo_magazine.update_icon()
ammo_magazine = null
update_icon() //make sure to do this after unsetting ammo_magazine
+ user.hud_used.update_ammo_hud(user, src)
/obj/item/weapon/gun/projectile/examine(mob/user)
. = ..()
@@ -256,3 +272,72 @@
unload_ammo(usr)
*/
+
+// TGMC Ammo HUD Insertion
+/obj/item/weapon/gun/projectile/has_ammo_counter()
+ return TRUE
+
+/obj/item/weapon/gun/projectile/get_ammo_type()
+ if(load_method & MAGAZINE)
+ if(chambered) // Do we have an ammo casing chambered
+ var/obj/item/ammo_casing/A = chambered
+ var/obj/item/projectile/P = A.projectile_type
+ return list(initial(P.hud_state), initial(P.hud_state_empty))
+ else if(ammo_magazine && ammo_magazine.stored_ammo.len) // Do we have a mag, and have ammo in the mag, but nothing chambered?
+ var/obj/item/ammo_casing/A = ammo_magazine.stored_ammo[1]
+ var/obj/item/projectile/P = A.projectile_type
+ return list(initial(P.hud_state), initial(P.hud_state_empty))
+ else if(src.projectile_type) // Else, we're entirely empty, and irregardless of the mag we have loaded (as it's empty, or it would've passed the length check above), return the DEFAULT projectile_type on the gun, if set.
+ var/obj/item/projectile/P = src.projectile_type
+ return list(initial(P.hud_state), initial(P.hud_state_empty))
+ else
+ return list("unknown", "unknown") // Safety, this shouldn't happen, but just in case
+ else if(load_method & (SINGLE_CASING|SPEEDLOADER)) // Do we load with single casings OR speedloaders?
+ if(chambered) // Do we have an ammo casing loaded in the chamber? All casings still have a projectile_type var.
+ var/obj/item/ammo_casing/A = chambered
+ var/obj/item/projectile/P = A.projectile_type
+ return list(initial(P.hud_state), initial(P.hud_state_empty)) // Return the casing's projectile_type ammo hud state
+ else if(loaded.len) // Else, is the gun loaded, but no ammo casings in chamber currently?
+ var/obj/item/ammo_casing/A = loaded[1]
+ var/obj/item/projectile/P = A.projectile_type
+ return list(initial(P.hud_state), initial(P.hud_state_empty)) // Return the ammunition loaded in the gun's hud_state
+ else if(src.projectile_type) // Else, we're entirely empty, and have nothing loaded in the gun, and nothing in the chamber. Return the DEFAULT projectile_type on the gun, if set.
+ var/obj/item/projectile/P = src.projectile_type
+ return list(initial(P.hud_state), initial(P.hud_state_empty))
+ else
+ return list("unknown", "unknown") // Safety, this shouldn't happen, but just in case
+ else if(src.projectile_type) // Failsafe if we somehow don't pass the above. Return the DEFAULT projectile_type on the gun, if set.
+ var/obj/item/projectile/P = src.projectile_type
+ return list(initial(P.hud_state), initial(P.hud_state_empty))
+ else // Failsafe if we somehow fail all three methods
+ return list("unknown", "unknown")
+
+/obj/item/weapon/gun/projectile/get_ammo_count()
+ if(ammo_magazine) // Do we have a magazine loaded?
+ var/shots_left
+ if(chambered && chambered.BB) // Do we have a bullet in the currently-chambered casing, if any?
+ shots_left++
+ for(var/obj/item/ammo_casing/bullet in ammo_magazine.stored_ammo)
+ if(bullet.BB)
+ shots_left++
+
+ if(shots_left > 0)
+ return shots_left
+ else
+ return 0 // No ammo left or failsafe.
+ else if(loaded) // Do we use internal ammunition
+ var/shots_left
+ if(chambered && chambered.BB) // Do we have a bullet in the currently-chambered casing, if any?
+ shots_left++
+ for(var/obj/item/ammo_casing/bullet in loaded)
+ if(bullet.BB) // Only increment how many shots we have left if we're loaded.
+ shots_left++
+
+ if(shots_left > 0)
+ return shots_left
+ else
+ return 0 // No ammo left or failsafe.
+ else if(chambered) // If we don't have a magazine or internal ammunition loaded, but we have a casing in chamber, return the amount.
+ return chambered.BB ? 1 : 0
+ else // Failsafe, or completely unloaded
+ return 0
diff --git a/code/modules/projectiles/guns/projectile/shotgun.dm b/code/modules/projectiles/guns/projectile/shotgun.dm
index 4f6cb0b018..161f3ea29e 100644
--- a/code/modules/projectiles/guns/projectile/shotgun.dm
+++ b/code/modules/projectiles/guns/projectile/shotgun.dm
@@ -1,3 +1,7 @@
+/*
+ * Shotgun
+ */
+
/obj/item/weapon/gun/projectile/shotgun/pump
name = "shotgun"
desc = "The mass-produced MarsTech Meteor 29 shotgun is a favourite of police and security forces on many worlds. Uses 12g rounds."
@@ -39,12 +43,14 @@
else
chambered.loc = get_turf(src) // Eject casing
chambered = null
+ M.hud_used.update_ammo_hud(M, src) // TGMC Ammo HUD Port
// Load next shell
if(loaded.len)
var/obj/item/ammo_casing/AC = loaded[1] // load next casing.
loaded -= AC // Remove casing from loaded list.
chambered = AC
+ M.hud_used.update_ammo_hud(M, src) // TGMC Ammo HUD Port
if(pump_animation) // This affects all bolt action and shotguns.
flick("[pump_animation]", src) // This plays any pumping
@@ -125,6 +131,7 @@
burst = 2
user.visible_message("The shotgun goes off!", "The shotgun goes off in your face!")
Fire_userless(user)
+ user.hud_used.update_ammo_hud(user, src) // TGMC Ammo HUD Port
burst = burstsetting
return
if(do_after(user, 30)) //SHIT IS STEALTHY EYYYYY
diff --git a/code/modules/projectiles/projectile.dm b/code/modules/projectiles/projectile.dm
index b06e33db76..1686a6e6e1 100644
--- a/code/modules/projectiles/projectile.dm
+++ b/code/modules/projectiles/projectile.dm
@@ -135,6 +135,10 @@
var/impact_effect_type = null
var/list/impacted_mobs = list()
+
+ // TGMC Ammo HUD Port
+ var/hud_state = "unknown" // What HUD state we use when we have ammunition.
+ var/hud_state_empty = "unknown" // The empty state. DON'T USE _FLASH IN THE NAME OF THE EMPTY STATE STRING, THAT IS ADDED BY THE CODE.
/obj/item/projectile/proc/Range()
range--
diff --git a/code/modules/projectiles/projectile/beams.dm b/code/modules/projectiles/projectile/beams.dm
index 559fb2a12b..829d660c81 100644
--- a/code/modules/projectiles/projectile/beams.dm
+++ b/code/modules/projectiles/projectile/beams.dm
@@ -23,6 +23,9 @@
tracer_type = /obj/effect/projectile/tracer/laser
impact_type = /obj/effect/projectile/impact/laser
+ hud_state = "laser"
+ hud_state_empty = "battery_empty"
+
/obj/item/projectile/beam/practice
name = "laser"
icon_state = "laser"
@@ -31,23 +34,28 @@
damage_type = BURN
check_armour = "laser"
eyeblur = 2
+ hud_state = "laser"
/obj/item/projectile/beam/weaklaser
name = "weak laser"
icon_state = "laser"
damage = 15
+ hud_state = "laser"
/obj/item/projectile/beam/smalllaser
damage = 25
+ hud_state = "laser"
/obj/item/projectile/beam/burstlaser
damage = 30
armor_penetration = 10
+ hud_state = "laser"
/obj/item/projectile/beam/midlaser
damage = 40
armor_penetration = 10
+ hud_state = "laser"
/obj/item/projectile/beam/mininglaser
name = "pulsating laser"
@@ -74,6 +82,7 @@
muzzle_type = /obj/effect/projectile/muzzle/laser_heavy
tracer_type = /obj/effect/projectile/tracer/laser_heavy
impact_type = /obj/effect/projectile/impact/laser_heavy
+ hud_state = "laser_overcharge"
/obj/item/projectile/beam/heavylaser/fakeemitter
name = "emitter beam"
@@ -81,6 +90,7 @@
fire_sound = 'sound/weapons/emitter.ogg'
light_color = "#00CC33"
excavation_amount = 140 // 2 shots to dig a standard rock turf. Superior due to being a mounted tool beam, to make it actually viable.
+ hud_state = "laser_overcharge"
muzzle_type = /obj/effect/projectile/muzzle/emitter
tracer_type = /obj/effect/projectile/tracer/emitter
@@ -90,6 +100,7 @@
damage = 80
armor_penetration = 50
light_color = "#FF0D00"
+ hud_state = "laser_overcharge"
/obj/item/projectile/beam/xray
name = "xray beam"
@@ -98,6 +109,7 @@
damage = 25
armor_penetration = 50
light_color = "#00CC33"
+ hud_state = "laser_sniper"
muzzle_type = /obj/effect/projectile/muzzle/xray
tracer_type = /obj/effect/projectile/tracer/xray
@@ -111,6 +123,7 @@
armor_penetration = 90
irradiate = 20
light_color = "#00CC33"
+ hud_state = "laser_sniper"
muzzle_type = /obj/effect/projectile/muzzle/xray
tracer_type = /obj/effect/projectile/tracer/xray
@@ -122,6 +135,7 @@
fire_sound = 'sound/weapons/eluger.ogg'
damage = 40
light_color = "#00C6FF"
+ hud_state = "laser_disabler"
muzzle_type = /obj/effect/projectile/muzzle/laser_omni
tracer_type = /obj/effect/projectile/tracer/laser_omni
@@ -134,6 +148,7 @@
damage = 100 //Badmin toy, don't care
armor_penetration = 100
light_color = "#0066FF"
+ hud_state = "pulse"
muzzle_type = /obj/effect/projectile/muzzle/laser_pulse
tracer_type = /obj/effect/projectile/tracer/laser_pulse
@@ -151,6 +166,7 @@
damage = 0 // The actual damage is computed in /code/modules/power/singularity/emitter.dm
light_color = "#00CC33"
excavation_amount = 70 // 3 shots to mine a turf
+ hud_state = "laser_overcharge"
muzzle_type = /obj/effect/projectile/muzzle/emitter
tracer_type = /obj/effect/projectile/tracer/emitter
@@ -164,13 +180,14 @@
no_attack_log = 1
damage_type = BURN
check_armour = "laser"
+ hud_state = "monkey"
combustion = FALSE
/obj/item/projectile/beam/lasertag/blue
icon_state = "bluelaser"
light_color = "#0066FF"
-
+ hud_state = "monkey"
muzzle_type = /obj/effect/projectile/muzzle/laser_blue
tracer_type = /obj/effect/projectile/tracer/laser_blue
impact_type = /obj/effect/projectile/impact/laser_blue
@@ -185,6 +202,7 @@
/obj/item/projectile/beam/lasertag/red
icon_state = "laser"
light_color = "#FF0D00"
+ hud_state = "monkey"
/obj/item/projectile/beam/lasertag/red/on_hit(var/atom/target, var/blocked = 0)
if(ishuman(target))
@@ -196,6 +214,7 @@
/obj/item/projectile/beam/lasertag/omni//A laser tag bolt that stuns EVERYONE
icon_state = "omnilaser"
light_color = "#00C6FF"
+ hud_state = "monkey"
muzzle_type = /obj/effect/projectile/muzzle/laser_omni
tracer_type = /obj/effect/projectile/tracer/laser_omni
@@ -215,6 +234,7 @@
damage = 50
armor_penetration = 10
light_color = "#00CC33"
+ hud_state = "laser_sniper"
muzzle_type = /obj/effect/projectile/muzzle/xray
tracer_type = /obj/effect/projectile/tracer/xray
@@ -231,12 +251,15 @@
light_color = "#FFFFFF"
hitsound = 'sound/weapons/zapbang.ogg'
+
combustion = FALSE
muzzle_type = /obj/effect/projectile/muzzle/stun
tracer_type = /obj/effect/projectile/tracer/stun
impact_type = /obj/effect/projectile/impact/stun
+ hud_state = "taser" // TGMC Ammo HUD port
+
/obj/item/projectile/beam/stun/weak
name = "weak stun beam"
icon_state = "stun"
@@ -277,6 +300,7 @@
agony = 15
eyeblur = 2
hitsound = 'sound/weapons/zapbang.ogg'
+ hud_state = "taser"
/obj/item/projectile/beam/shock/weak
damage = 5
@@ -294,7 +318,7 @@
damage_type = ELECTROCUTE //You should be safe inside a voidsuit
sharp = FALSE //"Wide" spectrum beam
light_color = COLOR_GOLD
-
+ hud_state = "monkey"
excavation_amount = 200 // Good at shooting rocks
muzzle_type = /obj/effect/projectile/muzzle/pointdefense
diff --git a/code/modules/projectiles/projectile/bullets.dm b/code/modules/projectiles/projectile/bullets.dm
index 812bc8b829..113f7d7387 100644
--- a/code/modules/projectiles/projectile/bullets.dm
+++ b/code/modules/projectiles/projectile/bullets.dm
@@ -12,6 +12,8 @@
impact_effect_type = /obj/effect/temp_visual/impact_effect
excavation_amount = 20
var/mob_passthrough_check = 0
+ hud_state = "pistol_lightap"
+ hud_state_empty = "pistol_empty" // Just in case we somehow have no hud_state_empty defined
muzzle_type = /obj/effect/projectile/muzzle/bullet
@@ -96,30 +98,38 @@
/obj/item/projectile/bullet/pistol // 9mm pistols and most SMGs. Sacrifice power for capacity.
fire_sound = 'sound/weapons/gunshot2.ogg'
damage = 20
+ hud_state = "pistol"
+ hud_state_empty = "pistol_empty"
/obj/item/projectile/bullet/pistol/ap
damage = 15
armor_penetration = 30
+ hud_state = "pistol_light_ap"
/obj/item/projectile/bullet/pistol/hp
damage = 25
armor_penetration = -50
+ hud_state = "pistol_ap"
/obj/item/projectile/bullet/pistol/medium // .45 (and maybe .40 if it ever gets added) caliber security pistols. Balance between capacity and power.
fire_sound = 'sound/weapons/gunshot3.ogg' // Snappier sound.
damage = 25
+ hud_state = "pistol"
/obj/item/projectile/bullet/pistol/medium/ap
damage = 20
armor_penetration = 15
+ hud_state = "pistol_light_ap"
/obj/item/projectile/bullet/pistol/medium/hp
damage = 30
armor_penetration = -50
+ hud_state = "pistol_ap"
/obj/item/projectile/bullet/pistol/strong // .357 and .44 caliber stuff. High power pistols like the Mateba or Desert Eagle. Sacrifice capacity for power.
fire_sound = 'sound/weapons/gunshot4.ogg'
damage = 60
+ hud_state = "pistol_heavy"
/obj/item/projectile/bullet/pistol/rubber/strong // "Rubber" bullets for high power pistols.
fire_sound = 'sound/weapons/gunshot3.ogg' // Rubber shots have less powder, but these still have more punch than normal rubber shot.
@@ -128,6 +138,7 @@
embed_chance = 0
sharp = 0
check_armour = "melee"
+ hud_state = "pistol_special"
/obj/item/projectile/bullet/pistol/rubber // "Rubber" bullets for all other pistols.
name = "rubber bullet"
@@ -136,6 +147,7 @@
embed_chance = 0
sharp = 0
check_armour = "melee"
+ hud_state = "pistol_special"
fire_sound ='sound/weapons/Gunshot_pathetic.ogg' // Rubber shots have less powder in the casing.
/* shotgun projectiles */
@@ -145,6 +157,8 @@
fire_sound = 'sound/weapons/Gunshot_shotgun.ogg'
damage = 50
armor_penetration = 20
+ hud_state = "shotgun_slug"
+ hud_state_empty = "shotgun_empty"
/obj/item/projectile/bullet/shotgun/beanbag //because beanbags are not bullets
name = "beanbag"
@@ -153,6 +167,7 @@
embed_chance = 0
sharp = 0
check_armour = "melee"
+ hud_state = "shotgun_beanbag"
//Should do about 80 damage at 1 tile distance (adjacent), and 50 damage at 3 tiles distance.
//Overall less damage than slugs in exchange for more damage at very close range and more embedding
@@ -163,12 +178,14 @@
pellets = 6
range_step = 1
spread_step = 10
+ hud_state = "shotgun_buckshot"
/obj/item/projectile/bullet/pellet/shotgun/flak
damage = 2 //The main weapon using these fires four at a time, usually with different destinations. Usually.
range_step = 2
spread_step = 30
armor_penetration = 10
+ hud_state = "shotgun_flechette"
//EMP shotgun 'slug', it's basically a beanbag that pops a tiny emp when it hits. //Not currently used
/obj/item/projectile/bullet/shotgun/ion
@@ -178,6 +195,7 @@
embed_chance = 0
sharp = 0
check_armour = "melee"
+ hud_state = "shotgun_ion"
combustion = FALSE
@@ -193,46 +211,57 @@
fire_sound = 'sound/weapons/Gunshot_generic_rifle.ogg'
armor_penetration = 15
penetrating = 1
+ hud_state = "rifle"
+ hud_state_empty = "rifle_empty"
/obj/item/projectile/bullet/rifle/a762
fire_sound = 'sound/weapons/Gunshot_heavy.ogg'
damage = 35
+ hud_state = "rifle_heavy"
/obj/item/projectile/bullet/rifle/a762/sniper // Hitscan specifically for sniper ammo; to be implimented at a later date, probably for the SVD. -Ace
fire_sound = 'sound/weapons/Gunshot_sniper.ogg'
hitscan = 1 //so the ammo isn't useless as a sniper weapon
+ hud_state = "hivelo"
/obj/item/projectile/bullet/rifle/a762/ap
damage = 30
armor_penetration = 50 // At 30 or more armor, this will do more damage than standard rounds.
+ hud_state = "rifle_ap"
/obj/item/projectile/bullet/rifle/a762/hp
damage = 40
armor_penetration = -50
penetrating = 0
+ hud_state = "hivelo_iff"
/obj/item/projectile/bullet/rifle/a762/hunter // Optimized for killing simple animals and not people, because Balance(tm)
damage = 20
SA_bonus_damage = 50 // 70 total on animals.
SA_vulnerability = SA_ANIMAL
+ hud_state = "rifle_heavy"
/obj/item/projectile/bullet/rifle/a545
fire_sound = 'sound/weapons/Gunshot_light.ogg'
damage = 25
+ hud_state = "rifle"
/obj/item/projectile/bullet/rifle/a545/ap
damage = 20
armor_penetration = 50 // At 40 or more armor, this will do more damage than standard rounds.
+ hud_state = "rifle_ap"
/obj/item/projectile/bullet/rifle/a545/hp
damage = 35
armor_penetration = -50
penetrating = 0
+ hud_state = "hivelo_iff"
/obj/item/projectile/bullet/rifle/a545/hunter
damage = 15
SA_bonus_damage = 35 // 50 total on animals.
SA_vulnerability = SA_ANIMAL
+ hud_state = "rifle_heavy"
/obj/item/projectile/bullet/rifle/a145 // 14.5�114mm is bigger than a .50 BMG round.
fire_sound = 'sound/weapons/Gunshot_cannon.ogg' // This is literally an anti-tank rifle caliber. It better sound like a fucking cannon.
@@ -242,6 +271,7 @@
penetrating = 5
armor_penetration = 80
hitscan = 1 //so the PTR isn't useless as a sniper weapon
+ hud_state = "sniper"
icon_state = "bullet_alt"
tracer_type = /obj/effect/projectile/tracer/cannon
@@ -252,10 +282,12 @@
weaken = 0
penetrating = 15
armor_penetration = 90
+ hud_state = "sniper_flak"
/obj/item/projectile/bullet/rifle/a44rifle
fire_sound = 'sound/weapons/gunshot4.ogg'
damage = 50
+ hud_state = "revolver"
/* Mech rounds */
@@ -274,18 +306,21 @@
name = "co bullet"
damage = 20
damage_type = OXY
+ hud_state = "pistol_tranq"
/obj/item/projectile/bullet/cyanideround
name = "poison bullet"
damage = 40
damage_type = TOX
+ hud_state = "pistol_tranq"
/obj/item/projectile/bullet/burstbullet
name = "exploding bullet"
fire_sound = 'sound/effects/Explosion1.ogg'
damage = 20
embed_chance = 0
- edge = 1
+ edge = TRUE
+ hud_state = "pistol_fire"
/obj/item/projectile/bullet/burstbullet/on_hit(var/atom/target, var/blocked = 0)
if(isturf(target))
@@ -301,6 +336,7 @@
damage_type = BURN
incendiary = 0.5
flammability = 2
+ hud_state = "pistol_fire"
/obj/item/projectile/bullet/incendiary/flamethrower
name = "ball of fire"
@@ -313,12 +349,14 @@
agony = 30
range = 4
vacuum_traversal = 0
+ hud_state = "flame"
/obj/item/projectile/bullet/incendiary/flamethrower/large
damage = 5
incendiary = 3
flammability = 2
range = 6
+ hud_state = "flame"
/obj/item/projectile/bullet/incendiary/flamethrower/tiny
damage = 2
@@ -328,11 +366,13 @@
modifier_duration = 20 SECONDS
range = 6
agony = 0
+ hud_state = "flame"
/* Practice rounds and blanks */
/obj/item/projectile/bullet/practice
damage = 5
+ hud_state = "smg_light"
/obj/item/projectile/bullet/pistol/cap // Just the primer, such as a cap gun.
name = "cap"
@@ -341,7 +381,8 @@
damage = 0
nodamage = 1
embed_chance = 0
- sharp = 0
+ sharp = FALSE
+ hud_state = "monkey"
combustion = FALSE
@@ -356,7 +397,8 @@
damage = 0
nodamage = 1
embed_chance = 0
- sharp = 0
+ sharp = FALSE
+ hud_state = "smg_light"
/obj/item/projectile/bullet/blank/cap/process()
loc = null
@@ -370,6 +412,7 @@
embed_chance = 0
sharp = FALSE
silenced = TRUE
+ hud_state = "pistol_light"
/obj/item/projectile/bullet/pellet/shotgun/bb // Shotgun
name = "BB"
diff --git a/code/modules/projectiles/projectile/energy.dm b/code/modules/projectiles/projectile/energy.dm
index 35e4c61ea4..3be445f264 100644
--- a/code/modules/projectiles/projectile/energy.dm
+++ b/code/modules/projectiles/projectile/energy.dm
@@ -8,6 +8,8 @@
impact_effect_type = /obj/effect/temp_visual/impact_effect
hitsound_wall = 'sound/weapons/effects/searwall.ogg'
hitsound = 'sound/weapons/zapbang.ogg'
+ hud_state = "plasma"
+ hud_state_empty = "battery_empty"
var/flash_strength = 10
@@ -22,6 +24,7 @@
var/flash_range = 0
var/brightness = 7
var/light_colour = "#ffffff"
+ hud_state = "grenade_dummy"
/obj/item/projectile/energy/flash/on_impact(var/atom/A)
var/turf/T = flash_range? src.loc : get_turf(A)
@@ -59,6 +62,7 @@
flash_range = 1
brightness = 15
flash_strength = 20
+ hud_state = "grenade_dummy"
/obj/item/projectile/energy/flash/flare/on_impact(var/atom/A)
light_colour = pick("#e58775", "#ffffff", "#90ff90", "#a09030")
@@ -77,15 +81,18 @@
light_range = 2
light_power = 0.5
light_color = "#FFFFFF"
+ hud_state = "taser"
//Damage will be handled on the MOB side, to prevent window shattering.
/obj/item/projectile/energy/electrode/strong
agony = 55
+ hud_state = "taser"
/obj/item/projectile/energy/electrode/stunshot
name = "stunshot"
damage = 5
agony = 80
+ hud_state = "taser"
/obj/item/projectile/energy/declone
name = "declone"
@@ -100,6 +107,7 @@
impact_effect_type = /obj/effect/temp_visual/impact_effect/monochrome_laser
combustion = FALSE
+ hud_state = "plasma_pistol"
/obj/item/projectile/energy/excavate
name = "kinetic blast"
@@ -113,6 +121,7 @@
vacuum_traversal = 0
combustion = FALSE
+ hud_state = "plasma_blast"
/obj/item/projectile/energy/dart
name = "dart"
@@ -121,6 +130,7 @@
damage_type = TOX
agony = 120
check_armour = "energy"
+ hud_state = "pistol_tranq"
combustion = FALSE
@@ -131,10 +141,12 @@
damage_type = TOX
agony = 40
stutter = 10
+ hud_state = "electrothermal"
/obj/item/projectile/energy/bolt/large
name = "largebolt"
damage = 20
+ hud_state = "electrothermal"
/obj/item/projectile/energy/acid //Slightly up-gunned (Read: The thing does agony and checks bio resist) variant of the simple alien mob's projectile, for queens and sentinels.
name = "acidic spit"
@@ -155,6 +167,7 @@
agony = 80
check_armour = "bio"
armor_penetration = 25 // It's acid-based
+ hud_state = "electrothermal"
combustion = FALSE
@@ -164,6 +177,7 @@
damage = 20
damage_type = BIOACID
agony = 20
+ hud_state = "electrothermal"
check_armour = "bio"
armor_penetration = 25 // It's acid-based
@@ -193,6 +207,7 @@
light_power = 0.5
light_color = "#33CC00"
impact_effect_type = /obj/effect/temp_visual/impact_effect/monochrome_laser
+ hud_state = "plasma_rifle"
combustion = FALSE
@@ -206,6 +221,7 @@
agony = 55
damage_type = BURN
vacuum_traversal = 0 //Projectile disappears in empty space
+ hud_state = "plasma_rifle_blast"
/obj/item/projectile/energy/plasmastun/proc/bang(var/mob/living/carbon/M)
@@ -250,6 +266,7 @@
embed_chance = 0
muzzle_type = /obj/effect/projectile/muzzle/pulse
impact_effect_type = /obj/effect/temp_visual/impact_effect/monochrome_laser
+ hud_state = "plasma_sphere"
/obj/item/projectile/energy/phase
name = "phase wave"
@@ -258,17 +275,20 @@
range = 6
damage = 5
SA_bonus_damage = 45 // 50 total on animals
- SA_vulnerability = SA_ANIMAL
+ hud_state = "laser_heat"
/obj/item/projectile/energy/phase/light
range = 4
SA_bonus_damage = 35 // 40 total on animals
+ hud_state = "laser_heat"
/obj/item/projectile/energy/phase/heavy
range = 8
SA_bonus_damage = 55 // 60 total on animals
+ hud_state = "laser_heat"
/obj/item/projectile/energy/phase/heavy/cannon
range = 10
damage = 15
- SA_bonus_damage = 60 // 75 total on animals
\ No newline at end of file
+ SA_bonus_damage = 60 // 75 total on animals
+ hud_state = "laser_heat"
\ No newline at end of file
diff --git a/code/modules/projectiles/projectile/explosive.dm b/code/modules/projectiles/projectile/explosive.dm
index 307febc8bc..76da8f3e3a 100644
--- a/code/modules/projectiles/projectile/explosive.dm
+++ b/code/modules/projectiles/projectile/explosive.dm
@@ -7,6 +7,8 @@
icon_state = "missile"
damage = 30 //Meaty whack. *Chuckles*
does_spin = 0
+ hud_state = "rocket_he"
+ hud_state_empty = "rocket_empty"
/obj/item/projectile/bullet/srmrocket/on_hit(atom/target, blocked=0)
if(!isliving(target)) //if the target isn't alive, so is a wall or something
@@ -24,6 +26,7 @@
/obj/item/projectile/bullet/srmrocket/weak //Used in the jury rigged one.
damage = 10
+ hud_state = "rocket_he"
/obj/item/projectile/bullet/srmrocket/weak/on_hit(atom/target, blocked=0)
explosion(target, 0, 0, 2, 4)//No need to have a question.
diff --git a/code/modules/projectiles/projectile/magnetic.dm b/code/modules/projectiles/projectile/magnetic.dm
index 12452d4618..3ccc8618da 100644
--- a/code/modules/projectiles/projectile/magnetic.dm
+++ b/code/modules/projectiles/projectile/magnetic.dm
@@ -8,12 +8,14 @@
weaken = 1
penetrating = 5
armor_penetration = 70
+ hud_state = "alloy_spike"
/obj/item/projectile/bullet/magnetic/slug
name = "slug"
icon_state = "gauss_silenced"
damage = 75
armor_penetration = 90
+ hud_state = "alloy_spike"
/obj/item/projectile/bullet/magnetic/flechette
name = "flechette"
@@ -21,6 +23,7 @@
fire_sound = 'sound/weapons/rapidslice.ogg'
damage = 20
armor_penetration = 100
+ hud_state = "alloy_spike"
/obj/item/projectile/bullet/magnetic/flechette/small
name = "small flechette"
@@ -28,12 +31,14 @@
fire_sound = 'sound/weapons/rapidslice.ogg'
damage = 12
armor_penetration = 100
+ hud_state = "alloy_spike"
/obj/item/projectile/bullet/magnetic/flechette/hunting
name = "shredder slug"
armor_penetration = 30
SA_bonus_damage = 40
SA_vulnerability = SA_ANIMAL
+ hud_state = "alloy_spike"
/obj/item/projectile/bullet/magnetic/heated
name = "slug"
@@ -45,6 +50,7 @@
embed_chance = 0
armor_penetration = 40
penetrating = 1
+ hud_state = "alloy_spike"
/obj/item/projectile/bullet/magnetic/heated/weak
icon_state = "gauss_silenced"
@@ -53,6 +59,7 @@
embed_chance = 0
armor_penetration = 30
penetrating = 0
+ hud_state = "alloy_spike"
/obj/item/projectile/bullet/magnetic/fuelrod
name = "fuel rod"
@@ -67,6 +74,7 @@
embed_chance = 0
armor_penetration = 40
range = 20
+ hud_state = "rocket_he"
var/searing = 0 //Does this fuelrod ignore shields?
var/detonate_travel = 0 //Will this fuelrod explode when it reaches maximum distance?
@@ -113,6 +121,7 @@
flammability = -1
armor_penetration = 50
penetrating = 3
+ hud_state = "rocket_ap"
/obj/item/projectile/bullet/magnetic/fuelrod/phoron
name = "blazing fuel rod"
@@ -124,6 +133,7 @@
penetrating = 5
irradiate = 20
detonate_mob = 1
+ hud_state = "rocket_fire"
/obj/item/projectile/bullet/magnetic/fuelrod/supermatter
name = "painfully incandescent fuel rod"
@@ -140,6 +150,7 @@
detonate_travel = 1
detonate_mob = 1
energetic_impact = 1
+ hud_state = "rocket_thermobaric"
/obj/item/projectile/bullet/magnetic/fuelrod/supermatter/on_hit(var/atom/target, var/blocked = 0, var/def_zone = null) //You cannot touch the supermatter without disentigrating. Assumedly, this is true for condensed rods of it flying at relativistic speeds.
if(istype(target,/turf/simulated/wall) || istype(target,/mob/living))
@@ -160,6 +171,7 @@
check_armour = "melee"
irradiate = 20
range = 6
+ hud_state = "plasma_rifle_blast"
/obj/item/projectile/bullet/magnetic/bore/Initialize(loc, range_mod) // i'm gonna be real honest i dunno how this works but it does
. = ..()
diff --git a/code/modules/projectiles/projectile/special.dm b/code/modules/projectiles/projectile/special.dm
index 9c06241ecf..fff673befc 100644
--- a/code/modules/projectiles/projectile/special.dm
+++ b/code/modules/projectiles/projectile/special.dm
@@ -9,6 +9,8 @@
light_range = 2
light_power = 0.5
light_color = "#55AAFF"
+ hud_state = "plasma_blast"
+ hud_state_empty = "battery_empty"
combustion = FALSE
impact_effect_type = /obj/effect/temp_visual/impact_effect/ion
@@ -41,8 +43,9 @@
icon_state= "bolter"
damage = 50
check_armour = "bullet"
- sharp = 1
- edge = 1
+ sharp = TRUE
+ edge = TRUE
+ hud_state = "rocket_fire"
/obj/item/projectile/bullet/gyro/on_hit(var/atom/target, var/blocked = 0)
explosion(target, -1, 0, 2)
@@ -62,6 +65,7 @@
light_power = 0.5
light_color = "#55AAFF"
impact_effect_type = /obj/effect/temp_visual/impact_effect/monochrome_laser
+ hud_state = "water"
combustion = FALSE
@@ -93,6 +97,7 @@
/obj/item/projectile/temp/hot
name = "heat beam"
target_temperature = 1000
+ hud_state = "flame"
combustion = TRUE
@@ -104,6 +109,7 @@
damage_type = BRUTE
nodamage = 1
check_armour = "bullet"
+ hud_state = "monkey"
/obj/item/projectile/meteor/Bump(atom/A as mob|obj|turf|area)
if(A == firer)
@@ -140,6 +146,7 @@
impact_effect_type = /obj/effect/temp_visual/impact_effect/monochrome_laser
combustion = FALSE
+ hud_state = "electrothermal"
/obj/item/projectile/energy/floramut/on_hit(var/atom/target, var/blocked = 0)
var/mob/living/M = target
@@ -182,6 +189,7 @@
nodamage = 1
check_armour = "energy"
var/decl/plantgene/gene = null
+ hud_state = "electrothermal"
/obj/item/projectile/energy/florayield
name = "beta somatoray"
@@ -195,6 +203,7 @@
light_power = 0.5
light_color = "#FFFFFF"
impact_effect_type = /obj/effect/temp_visual/impact_effect/monochrome_laser
+ hud_state = "electrothermal"
/obj/item/projectile/energy/florayield/on_hit(var/atom/target, var/blocked = 0)
var/mob/living/M = target
@@ -212,6 +221,7 @@
name = "flayer ray"
combustion = FALSE
+ hud_state = "electrothermal"
/obj/item/projectile/beam/mindflayer/on_hit(var/atom/target, var/blocked = 0)
if(ishuman(target))
@@ -227,6 +237,7 @@
nodamage = 1
damage_type = HALLOSS
muzzle_type = /obj/effect/projectile/muzzle/bullet
+ hud_state = "monkey"
/obj/item/projectile/bola
name = "bola"
@@ -235,6 +246,7 @@
embed_chance = 0 //Nada.
damage_type = HALLOSS
muzzle_type = null
+ hud_state = "monkey"
combustion = FALSE
@@ -254,7 +266,7 @@
embed_chance = 0 //Nada.
damage_type = BRUTE
muzzle_type = null
-
+ hud_state = "monkey"
combustion = FALSE
/obj/item/projectile/webball/on_hit(var/atom/target, var/blocked = 0)
@@ -276,6 +288,7 @@
light_range = 4
light_power = 3
light_color = "#3300ff"
+ hud_state = "alloy_spike"
muzzle_type = /obj/effect/projectile/muzzle/tungsten
tracer_type = /obj/effect/projectile/tracer/tungsten
diff --git a/code/modules/reagents/reagents/food_drinks.dm b/code/modules/reagents/reagents/food_drinks.dm
index c445659d37..a0a06d2aa1 100644
--- a/code/modules/reagents/reagents/food_drinks.dm
+++ b/code/modules/reagents/reagents/food_drinks.dm
@@ -401,6 +401,15 @@
nutriment_factor = 5
color = "#302000"
+/datum/reagent/nutriment/chocolate
+ name = "Chocolate"
+ id = "chocolate"
+ description = "Great for cooking or on its own!"
+ taste_description = "chocolate"
+ color = "#582815"
+ nutriment_factor = 5
+ taste_mult = 1.3
+
/datum/reagent/nutriment/instantjuice
name = "Juice Powder"
id = "instantjuice"
diff --git a/code/modules/shieldgen/directional_shield.dm b/code/modules/shieldgen/directional_shield.dm
index 469adeb887..c383ebd2f3 100644
--- a/code/modules/shieldgen/directional_shield.dm
+++ b/code/modules/shieldgen/directional_shield.dm
@@ -158,12 +158,12 @@
// This is done at the projector instead of the shields themselves to avoid needing to calculate this more than once every update.
var/interpolate_weight = shield_health / max_shield_health
- var/list/low_color_list = hex2rgb(low_color)
+ var/list/low_color_list = rgb2num(low_color)
var/low_r = low_color_list[1]
var/low_g = low_color_list[2]
var/low_b = low_color_list[3]
- var/list/high_color_list = hex2rgb(high_color)
+ var/list/high_color_list = rgb2num(high_color)
var/high_r = high_color_list[1]
var/high_g = high_color_list[2]
var/high_b = high_color_list[3]
diff --git a/code/modules/tgui/modules/communications.dm b/code/modules/tgui/modules/communications.dm
index d30f3a8a17..8ae0a48435 100644
--- a/code/modules/tgui/modules/communications.dm
+++ b/code/modules/tgui/modules/communications.dm
@@ -152,7 +152,7 @@
if(emergency_shuttle.has_eta())
var/timeleft = emergency_shuttle.estimate_arrival_time()
data["esc_status"] = emergency_shuttle.online() ? "ETA:" : "RECALLING:"
- data["esc_status"] += " [timeleft / 60 % 60]:[add_zero(num2text(timeleft % 60), 2)]"
+ data["esc_status"] += " [timeleft / 60 % 60]:[pad_left(num2text(timeleft % 60), 2, "0")]"
return data
/datum/tgui_module/communications/proc/setCurrentMessage(mob/user, value)
diff --git a/code/modules/virus2/disease2.dm b/code/modules/virus2/disease2.dm
index 08d52b1706..c6932b4df6 100644
--- a/code/modules/virus2/disease2.dm
+++ b/code/modules/virus2/disease2.dm
@@ -14,7 +14,7 @@
var/resistance = 10 // % chance a disease will resist cure, up to 100
/datum/disease2/disease/New()
- uniqueID = rand(0,10000)
+ uniqueID = rand(1, 9999)
..()
/datum/disease2/disease/proc/makerandom(var/severity=1)
@@ -25,7 +25,7 @@
holder.getrandomeffect(severity, excludetypes)
excludetypes += holder.effect.type
effects += holder
- uniqueID = rand(0,10000)
+ uniqueID = rand(1, 9999)
switch(severity)
if(1)
infectionchance = 1
@@ -135,13 +135,13 @@
BITSET(mob.hud_updateflag, STATUS_HUD)
/datum/disease2/disease/proc/minormutate()
- //uniqueID = rand(0,10000)
+ //uniqueID = rand(1, 9999)
var/datum/disease2/effectholder/holder = pick(effects)
holder.minormutate()
//infectionchance = min(50,infectionchance + rand(0,10))
/datum/disease2/disease/proc/majormutate()
- uniqueID = rand(0,10000)
+ uniqueID = rand(1, 9999)
var/datum/disease2/effectholder/holder = pick(effects)
var/list/exclude = list()
for(var/datum/disease2/effectholder/D in effects)
@@ -208,7 +208,7 @@
var/global/list/virusDB = list()
/datum/disease2/disease/proc/name()
- .= "stamm #[add_zero("[uniqueID]", 4)]"
+ .= "stamm #[pad_left(uniqueID, 8, "0")]"
if ("[uniqueID]" in virusDB)
var/datum/data/record/V = virusDB["[uniqueID]"]
.= V.fields["name"]
diff --git a/code/modules/xenobio2/controller.dm b/code/modules/xenobio2/controller.dm
index 584d820cb2..22f5e70b3e 100644
--- a/code/modules/xenobio2/controller.dm
+++ b/code/modules/xenobio2/controller.dm
@@ -34,11 +34,10 @@ var/global/datum/controller/xenobio/xenobio_controller // Set in New().
var/list/xenobio_traits = ALL_XENO_GENES
while(xenobio_traits && xenobio_traits.len)
var/gene_tag = pick(xenobio_traits)
- var/gene_mask = "[uppertext(num2hex(rand(0,255), 2))]"
-
- while(gene_mask in used_masks)
- gene_mask = "[uppertext(num2hex(rand(0,255), 2))]"
-
+ var/gene_mask
+ do
+ gene_mask = random_hex_text(2, TRUE)
+ while (gene_mask in used_masks)
used_masks += gene_mask
xenobio_traits -= gene_tag
gene_tag_masks[gene_tag] = gene_mask
\ No newline at end of file
diff --git a/icons/mob/back.dmi b/icons/mob/back.dmi
index f1b934a287..46a696e64f 100644
Binary files a/icons/mob/back.dmi and b/icons/mob/back.dmi differ
diff --git a/icons/mob/hands.dmi b/icons/mob/hands.dmi
index 32008f190b..d1e4839233 100644
Binary files a/icons/mob/hands.dmi and b/icons/mob/hands.dmi differ
diff --git a/icons/mob/items/lefthand_storage.dmi b/icons/mob/items/lefthand_storage.dmi
index 6b5a4defb8..cdbd3cc252 100644
Binary files a/icons/mob/items/lefthand_storage.dmi and b/icons/mob/items/lefthand_storage.dmi differ
diff --git a/icons/mob/items/righthand_storage.dmi b/icons/mob/items/righthand_storage.dmi
index 783540cefc..e2f54f84e9 100644
Binary files a/icons/mob/items/righthand_storage.dmi and b/icons/mob/items/righthand_storage.dmi differ
diff --git a/icons/mob/screen_ammo.dmi b/icons/mob/screen_ammo.dmi
new file mode 100644
index 0000000000..57ab8e772e
Binary files /dev/null and b/icons/mob/screen_ammo.dmi differ
diff --git a/icons/mob/ties.dmi b/icons/mob/ties.dmi
index db8f1bda59..f701e0ebcd 100644
Binary files a/icons/mob/ties.dmi and b/icons/mob/ties.dmi differ
diff --git a/icons/obj/bureaucracy.dmi b/icons/obj/bureaucracy.dmi
index e45c3d2f40..32b465fb34 100644
Binary files a/icons/obj/bureaucracy.dmi and b/icons/obj/bureaucracy.dmi differ
diff --git a/icons/obj/clothing/backpack.dmi b/icons/obj/clothing/backpack.dmi
index 7132925559..f5a13f5461 100644
Binary files a/icons/obj/clothing/backpack.dmi and b/icons/obj/clothing/backpack.dmi differ
diff --git a/icons/obj/clothing/masks.dmi b/icons/obj/clothing/masks.dmi
index d7daacb379..5902e2920d 100644
Binary files a/icons/obj/clothing/masks.dmi and b/icons/obj/clothing/masks.dmi differ
diff --git a/icons/obj/clothing/ties.dmi b/icons/obj/clothing/ties.dmi
index eb60fbfdf9..7aae8c7560 100644
Binary files a/icons/obj/clothing/ties.dmi and b/icons/obj/clothing/ties.dmi differ
diff --git a/icons/obj/device.dmi b/icons/obj/device.dmi
index a86db9a720..ad7bac8531 100644
Binary files a/icons/obj/device.dmi and b/icons/obj/device.dmi differ
diff --git a/icons/obj/furniture.dmi b/icons/obj/furniture.dmi
index 7e0badd1e8..f75fef6207 100644
Binary files a/icons/obj/furniture.dmi and b/icons/obj/furniture.dmi differ
diff --git a/icons/obj/library.dmi b/icons/obj/library.dmi
index c3f730e586..bc8cba2747 100644
Binary files a/icons/obj/library.dmi and b/icons/obj/library.dmi differ
diff --git a/icons/obj/papershredder.dmi b/icons/obj/papershredder.dmi
index 36764945df..5670b38553 100644
Binary files a/icons/obj/papershredder.dmi and b/icons/obj/papershredder.dmi differ
diff --git a/icons/obj/storage.dmi b/icons/obj/storage.dmi
index 7f13fc75f1..55eee87e4b 100644
Binary files a/icons/obj/storage.dmi and b/icons/obj/storage.dmi differ
diff --git a/polaris.dme b/polaris.dme
index 00dcb611a9..9f31d34e0d 100644
--- a/polaris.dme
+++ b/polaris.dme
@@ -26,6 +26,7 @@
#include "code\__defines\_protect.dm"
#include "code\__defines\_tick.dm"
#include "code\__defines\admin.dm"
+#include "code\__defines\ai.dm"
#include "code\__defines\appearance.dm"
#include "code\__defines\atmos.dm"
#include "code\__defines\callbacks.dm"