diff --git a/code/__DEFINES/fonts.dm b/code/__DEFINES/fonts.dm
new file mode 100644
index 000000000000..ba799a62c9c7
--- /dev/null
+++ b/code/__DEFINES/fonts.dm
@@ -0,0 +1,7 @@
+// Font metrics bitfield
+/// Include leading A width and trailing C width in GetWidth() or in DrawText()
+#define INCLUDE_AC (1<<0)
+
+DEFINE_BITFIELD(font_flags, list(
+ "INCLUDE_AC" = INCLUDE_AC,
+))
diff --git a/code/__HELPERS/screentips.dm b/code/__HELPERS/screentips.dm
deleted file mode 100644
index aeceb0d41cd6..000000000000
--- a/code/__HELPERS/screentips.dm
+++ /dev/null
@@ -1,30 +0,0 @@
-#define HINT_ICON_FILE 'icons/UI_Icons/screentips/cursor_hints.dmi'
-
-// Generate intent icons
-GLOBAL_LIST_INIT_TYPED(screentip_context_icons, /image, prepare_screentip_context_icons())
-
-/proc/prepare_screentip_context_icons()
- . = list()
- for(var/state in icon_states(HINT_ICON_FILE))
- .[state] = image(HINT_ICON_FILE, icon_state = state)
-
-/*
- * # Builds context with each intent for this key
- * Args:
- * - context = list (REQUIRED)
- * - key = string (REQUIRED)
- * - allow_image = boolean (not required)
-*/
-/proc/build_context(list/context, key, allow_image)
- var/list/to_add
- for(var/intent in context[key])
- var/key_help = "[length(key) > 3 ? "[copytext(key, 1, -3)][allow_image ? " " : ""]" : ""]"
- var/icon = "[copytext(key, -3)]-[intent]"
- if(allow_image)
- icon = "\icon[GLOB.screentip_context_icons[icon]]"
- LAZYADD(to_add, "[key_help][icon]: [context[key][intent]]")
-
- var/separator = "[allow_image ? " " : " | "]"
- return english_list(to_add, "", separator, separator)
-
-#undef HINT_ICON_FILE
diff --git a/code/datums/screentips/screentips.dm b/code/datums/screentips/screentips.dm
new file mode 100644
index 000000000000..899d0d7f503f
--- /dev/null
+++ b/code/datums/screentips/screentips.dm
@@ -0,0 +1,40 @@
+#define HINT_ICON_FILE 'icons/UI_Icons/screentips/cursor_hints.dmi'
+
+/// Stores the cursor hint icons for screentip context.
+GLOBAL_LIST_INIT_TYPED(screentip_context_icons, /image, prepare_screentip_context_icons())
+
+/proc/prepare_screentip_context_icons()
+ var/list/output = list()
+ for(var/state in icon_states(HINT_ICON_FILE))
+ output[state] = image(HINT_ICON_FILE, icon_state = state)
+ return output
+
+/*
+ * # Builds context with each intent for this key
+ * Args:
+ * - context = list (REQUIRED)
+ * - context[key] = list (REQUIRED)
+ * - key = string (REQUIRED)
+ * - allow_image = boolean (not required)
+*/
+/proc/build_context(list/context, key, allow_image)
+ if(!(length(context) && length(context[key]) && key))
+ return ""
+ var/list/to_add
+ for(var/intent in context[key])
+ // Splits key combinations from mouse buttons. e.g. `Ctrl-Shift-LMB` goes in, `Ctrl-Shift-` goes out. Will be empty for single button actions.
+ var/key_combo = length(key) > 3 ? "[copytext(key, 1, -3)]" : ""
+ // Grab the mouse button, LMB/RMB+intent
+ var/button = "[copytext(key, -3)]-[intent]"
+ if(allow_image)
+ // Compile into image, if allowed
+ button = "\icon[GLOB.screentip_context_icons[button]]"
+ LAZYADD(to_add, "[key_combo][button][allow_image ? "" : ":"] [context[key][intent]]")
+
+ // Prepare separator for same button but different intent
+ var/separator = "[allow_image ? " " : " / "]"
+
+ // Voilá, final result
+ return to_add.Join(separator)
+
+#undef HINT_ICON_FILE
diff --git a/code/game/atoms.dm b/code/game/atoms.dm
index 353c7f89ade1..98cad49c9c77 100644
--- a/code/game/atoms.dm
+++ b/code/game/atoms.dm
@@ -1471,99 +1471,98 @@
//Update the screentip to reflect what we're hoverin over
/atom/MouseEntered(location, control, params)
. = ..()
- // Screentips
+
var/mob/user = usr
- if(isnull(user) && !user.client)
+ if(isnull(user))
+ return
+ if(!GET_CLIENT(user))
return
+ // Screentips
var/datum/hud/active_hud = user.hud_used
- if(active_hud)
- var/screentips_enabled = user.client.prefs.screentip_pref
- if(screentips_enabled == SCREENTIP_PREFERENCE_DISABLED || (flags_1 & NO_SCREENTIPS_1))
- active_hud.screentip_text.maptext = ""
- else
- active_hud.screentip_text.maptext_y = 0
- var/lmb_rmb_line = ""
- var/ctrl_lmb_ctrl_rmb_line = ""
- var/alt_lmb_alt_rmb_line = ""
- var/shift_lmb_ctrl_shift_lmb_line = ""
- var/extra_lines = 0
- var/extra_context = ""
-
- if ((isliving(user) || isovermind(user) || isaicamera(user)) && (user.client.prefs.screentip_pref != SCREENTIP_PREFERENCE_NO_CONTEXT))
- var/obj/item/held_item = user.get_active_held_item()
- var/allow_images = user.client.prefs.screentip_allow_images
-
- if (flags_1 & HAS_CONTEXTUAL_SCREENTIPS_1 || held_item?.item_flags & ITEM_HAS_CONTEXTUAL_SCREENTIPS)
- var/list/context = list()
-
- var/contextual_screentip_returns = \
- SEND_SIGNAL(src, COMSIG_ATOM_REQUESTING_CONTEXT_FROM_ITEM, context, held_item, user) \
- | (held_item && SEND_SIGNAL(held_item, COMSIG_ITEM_REQUESTING_CONTEXT_FOR_TARGET, context, src, user))
-
- if (contextual_screentip_returns & CONTEXTUAL_SCREENTIP_SET)
- // LMB and RMB on one line...
- var/lmb_text = ""
- if((SCREENTIP_CONTEXT_LMB in context) && (length(context[SCREENTIP_CONTEXT_LMB]) > 0))
- lmb_text = build_context(context, SCREENTIP_CONTEXT_LMB, allow_images)
- var/rmb_text = ""
- if((SCREENTIP_CONTEXT_RMB in context) && (length(context[SCREENTIP_CONTEXT_RMB]) > 0))
- rmb_text = build_context(context, SCREENTIP_CONTEXT_RMB, allow_images)
-
- if (lmb_text)
- lmb_rmb_line = lmb_text
- if (rmb_text)
- lmb_rmb_line += " | [allow_images ? " " : ""][rmb_text]"
- else if (rmb_text)
- lmb_rmb_line = rmb_text
-
- // Ctrl-LMB, Ctrl-RMB on one line...
- if (lmb_rmb_line != "")
- lmb_rmb_line += "
"
- extra_lines++
- if((SCREENTIP_CONTEXT_CTRL_LMB in context) && (length(context[SCREENTIP_CONTEXT_CTRL_LMB]) > 0))
- ctrl_lmb_ctrl_rmb_line = build_context(context, SCREENTIP_CONTEXT_CTRL_LMB, allow_images)
-
- if((SCREENTIP_CONTEXT_CTRL_RMB in context) && (length(context[SCREENTIP_CONTEXT_CTRL_RMB]) > 0))
- if (ctrl_lmb_ctrl_rmb_line != "")
- ctrl_lmb_ctrl_rmb_line += " | [allow_images ? " " : ""]"
- ctrl_lmb_ctrl_rmb_line += "[SCREENTIP_CONTEXT_CTRL_RMB]: [context[SCREENTIP_CONTEXT_CTRL_RMB]]"
- ctrl_lmb_ctrl_rmb_line = build_context(context, SCREENTIP_CONTEXT_CTRL_RMB, allow_images)
-
- // Alt-LMB, Alt-RMB on one line...
- if (ctrl_lmb_ctrl_rmb_line != "")
- ctrl_lmb_ctrl_rmb_line += "
"
- extra_lines++
- if((SCREENTIP_CONTEXT_ALT_LMB in context) && (length(context[SCREENTIP_CONTEXT_ALT_LMB]) > 0))
- alt_lmb_alt_rmb_line = build_context(context, SCREENTIP_CONTEXT_ALT_LMB, allow_images)
- if((SCREENTIP_CONTEXT_ALT_RMB in context) && (length(context[SCREENTIP_CONTEXT_ALT_RMB]) > 0))
- if (alt_lmb_alt_rmb_line != "")
- alt_lmb_alt_rmb_line += " | [allow_images ? " " : ""]"
- alt_lmb_alt_rmb_line = build_context(context, SCREENTIP_CONTEXT_ALT_RMB, allow_images)
-
- // Shift-LMB, Ctrl-Shift-LMB on one line...
- if (alt_lmb_alt_rmb_line != "")
- alt_lmb_alt_rmb_line += "
"
- extra_lines++
- if((SCREENTIP_CONTEXT_SHIFT_LMB in context) && (length(context[SCREENTIP_CONTEXT_SHIFT_LMB]) > 0))
- shift_lmb_ctrl_shift_lmb_line = build_context(context, SCREENTIP_CONTEXT_SHIFT_LMB, allow_images)
-
- if((SCREENTIP_CONTEXT_CTRL_SHIFT_LMB in context) && (length(context[SCREENTIP_CONTEXT_CTRL_SHIFT_LMB]) > 0))
- if (shift_lmb_ctrl_shift_lmb_line != "")
- shift_lmb_ctrl_shift_lmb_line += " | [allow_images ? " " : ""]"
- shift_lmb_ctrl_shift_lmb_line += "[SCREENTIP_CONTEXT_CTRL_SHIFT_LMB]: [context[SCREENTIP_CONTEXT_CTRL_SHIFT_LMB]]"
- shift_lmb_ctrl_shift_lmb_line = build_context(context, SCREENTIP_CONTEXT_CTRL_SHIFT_LMB, allow_images)
-
- if (shift_lmb_ctrl_shift_lmb_line != "")
- extra_lines++
-
- if(extra_lines)
- extra_context = "
[lmb_rmb_line][ctrl_lmb_ctrl_rmb_line][alt_lmb_alt_rmb_line][shift_lmb_ctrl_shift_lmb_line]"
- //first extra line pushes atom name line up 10px, subsequent lines push it up 9px, this offsets that and keeps the first line in the same place
- active_hud.screentip_text.maptext_y = -10 + (extra_lines - 1) * -9
-
- if (screentips_enabled == SCREENTIP_PREFERENCE_CONTEXT_ONLY && extra_context == "")
- active_hud.screentip_text.maptext = ""
- else
- //We inline a MAPTEXT() here, because there's no good way to statically add to a string like this
- active_hud.screentip_text.maptext = "[name][extra_context]"
+ if(!active_hud)
+ return
+
+ var/screentips_enabled = user.client.prefs.screentip_pref
+ if(screentips_enabled == SCREENTIP_PREFERENCE_DISABLED || (flags_1 & NO_SCREENTIPS_1))
+ active_hud.screentip_text.maptext = ""
+ return
+
+ active_hud.screentip_text.maptext_y = 10 // 10px lines us up with the action buttons top left corner
+ var/lmb_rmb_line = ""
+ var/ctrl_lmb_ctrl_rmb_line = ""
+ var/alt_lmb_alt_rmb_line = ""
+ var/shift_lmb_ctrl_shift_lmb_line = ""
+ var/extra_lines = 0
+ var/extra_context = ""
+
+ if ((isliving(user) || isovermind(user) || isaicamera(user)) && (user.client.prefs.screentip_pref != SCREENTIP_PREFERENCE_NO_CONTEXT))
+ var/obj/item/held_item = user.get_active_held_item()
+
+ if (flags_1 & HAS_CONTEXTUAL_SCREENTIPS_1 || held_item?.item_flags & ITEM_HAS_CONTEXTUAL_SCREENTIPS)
+ var/list/context = list()
+
+ var/contextual_screentip_returns = \
+ SEND_SIGNAL(src, COMSIG_ATOM_REQUESTING_CONTEXT_FROM_ITEM, context, held_item, user) \
+ | (held_item && SEND_SIGNAL(held_item, COMSIG_ITEM_REQUESTING_CONTEXT_FOR_TARGET, context, src, user))
+
+ if (contextual_screentip_returns & CONTEXTUAL_SCREENTIP_SET)
+ var/screentip_images = user.client.prefs.screentip_images
+ // LMB and RMB on one line...
+ var/lmb_text = build_context(context, SCREENTIP_CONTEXT_LMB, screentip_images)
+ var/rmb_text = build_context(context, SCREENTIP_CONTEXT_RMB, screentip_images)
+
+ if (lmb_text != "")
+ lmb_rmb_line = lmb_text
+ if (rmb_text != "")
+ lmb_rmb_line += " | [rmb_text]"
+ else if (rmb_text != "")
+ lmb_rmb_line = rmb_text
+
+ // Ctrl-LMB, Ctrl-RMB on one line...
+ if (lmb_rmb_line != "")
+ lmb_rmb_line += "
"
+ extra_lines++
+ if (SCREENTIP_CONTEXT_CTRL_LMB in context)
+ ctrl_lmb_ctrl_rmb_line += build_context(context, SCREENTIP_CONTEXT_CTRL_LMB, screentip_images)
+
+ if (SCREENTIP_CONTEXT_CTRL_RMB in context)
+ if (ctrl_lmb_ctrl_rmb_line != "")
+ ctrl_lmb_ctrl_rmb_line += " | "
+ ctrl_lmb_ctrl_rmb_line += build_context(context, SCREENTIP_CONTEXT_CTRL_RMB, screentip_images)
+
+ // Alt-LMB, Alt-RMB on one line...
+ if (ctrl_lmb_ctrl_rmb_line != "")
+ ctrl_lmb_ctrl_rmb_line += "
"
+ extra_lines++
+ if (SCREENTIP_CONTEXT_ALT_LMB in context)
+ alt_lmb_alt_rmb_line += build_context(context, SCREENTIP_CONTEXT_ALT_LMB, screentip_images)
+ if (SCREENTIP_CONTEXT_ALT_RMB in context)
+ if (alt_lmb_alt_rmb_line != "")
+ alt_lmb_alt_rmb_line += " | "
+ alt_lmb_alt_rmb_line += build_context(context, SCREENTIP_CONTEXT_ALT_RMB, screentip_images)
+
+ // Shift-LMB, Ctrl-Shift-LMB on one line...
+ if (alt_lmb_alt_rmb_line != "")
+ alt_lmb_alt_rmb_line += "
"
+ extra_lines++
+ if (SCREENTIP_CONTEXT_SHIFT_LMB in context)
+ shift_lmb_ctrl_shift_lmb_line += build_context(context, SCREENTIP_CONTEXT_SHIFT_LMB, screentip_images)
+ if (SCREENTIP_CONTEXT_CTRL_SHIFT_LMB in context)
+ if (shift_lmb_ctrl_shift_lmb_line != "")
+ shift_lmb_ctrl_shift_lmb_line += " | "
+ shift_lmb_ctrl_shift_lmb_line += build_context(context, SCREENTIP_CONTEXT_CTRL_SHIFT_LMB, screentip_images)
+
+ if (shift_lmb_ctrl_shift_lmb_line != "")
+ extra_lines++
+
+ if(extra_lines)
+ extra_context = "
[lmb_rmb_line][ctrl_lmb_ctrl_rmb_line][alt_lmb_alt_rmb_line][shift_lmb_ctrl_shift_lmb_line]"
+ //first extra line pushes atom name line up 10px, subsequent lines push it up 9px, this offsets that and keeps the first line in the same place
+ active_hud.screentip_text.maptext_y = -1 + (extra_lines - 1) * -9
+
+ if (screentips_enabled == SCREENTIP_PREFERENCE_CONTEXT_ONLY && extra_context == "")
+ active_hud.screentip_text.maptext = ""
+ else
+ //We inline a MAPTEXT() here, because there's no good way to statically add to a string like this
+ active_hud.screentip_text.maptext = "[name][extra_context]"
diff --git a/code/modules/client/preferences.dm b/code/modules/client/preferences.dm
index c915e13db287..dfa3309ffbef 100644
--- a/code/modules/client/preferences.dm
+++ b/code/modules/client/preferences.dm
@@ -64,7 +64,7 @@ GLOBAL_LIST_EMPTY(preferences_datums)
var/outline_color = COLOR_THEME_MIDNIGHT
var/screentip_pref = SCREENTIP_PREFERENCE_ENABLED
var/screentip_color = "#ffd391"
- var/screentip_allow_images = FALSE
+ var/screentip_images = TRUE
var/buttons_locked = FALSE
var/hotkeys = FALSE
@@ -1278,7 +1278,7 @@ GLOBAL_LIST_EMPTY(preferences_datums)
dat += "Screentip Color: [screentip_color] Change
"
dat += "\
- Screentip context with images: [screentip_allow_images ? "Allowed" : "Disallowed"]
"
+ Screentip context with images: [screentip_images ? "Allowed" : "Disallowed"]
"
dat += "tgui Monitors: [(tgui_lock) ? "Primary" : "All"]
"
dat += "tgui Style: [(tgui_fancy) ? "Fancy" : "No Frills"]
"
dat += "Show Runechat Chat Bubbles: [chat_on_map ? "Enabled" : "Disabled"]
"
@@ -3654,8 +3654,8 @@ GLOBAL_LIST_EMPTY(preferences_datums)
var/pickedScreentipColor = input(user, "Choose your screentip color.", "General Preference", screentip_color) as color|null
if(pickedScreentipColor)
screentip_color = pickedScreentipColor
- if("screentip_allow_images")
- screentip_allow_images = !screentip_allow_images
+ if("screentip_images")
+ screentip_images = !screentip_images
if("tgui_lock")
tgui_lock = !tgui_lock
if("winflash")
diff --git a/code/modules/client/preferences_savefile.dm b/code/modules/client/preferences_savefile.dm
index 4a1f23a2311c..77e63db5fc16 100644
--- a/code/modules/client/preferences_savefile.dm
+++ b/code/modules/client/preferences_savefile.dm
@@ -5,7 +5,7 @@
// You do not need to raise this if you are adding new values that have sane defaults.
// Only raise this value when changing the meaning/format/name/layout of an existing value
// where you would want the updater procs below to run
-#define SAVEFILE_VERSION_MAX 57.01
+#define SAVEFILE_VERSION_MAX 58
/*
SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Carn
@@ -382,6 +382,11 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
else
S["all_quirks"] = list("Dullahan")
+ // So, we're already on 57 even though we were meant to be on like, 56? i'm gonna try to correct this,
+ // And i'm so sorry for this.
+ if(current_version < 58)
+ S["screentip_images"] = TRUE // This was meant to default active, i'm so sorry. Turn it off if you must.
+
/datum/preferences/proc/load_path(ckey,filename="preferences.sav")
if(!ckey)
return
@@ -423,7 +428,7 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
S["outline_enabled"] >> outline_enabled
S["screentip_pref"] >> screentip_pref
S["screentip_color"] >> screentip_color
- S["screentip_allow_images"] >> screentip_allow_images
+ S["screentip_images"] >> screentip_images
S["hotkeys"] >> hotkeys
S["chat_on_map"] >> chat_on_map
S["max_chat_length"] >> max_chat_length
@@ -639,7 +644,7 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
WRITE_FILE(S["outline_color"], outline_color)
WRITE_FILE(S["screentip_pref"], screentip_pref)
WRITE_FILE(S["screentip_color"], screentip_color)
- WRITE_FILE(S["screentip_allow_images"], screentip_allow_images)
+ WRITE_FILE(S["screentip_images"], screentip_images)
WRITE_FILE(S["hotkeys"], hotkeys)
WRITE_FILE(S["chat_on_map"], chat_on_map)
WRITE_FILE(S["max_chat_length"], max_chat_length)
diff --git a/html/changelogs/archive/2023-07.yml b/html/changelogs/archive/2023-07.yml
index 1108f0cb152c..38c508f48379 100644
--- a/html/changelogs/archive/2023-07.yml
+++ b/html/changelogs/archive/2023-07.yml
@@ -51,3 +51,6 @@
Vhariik:
- rscadd: Layenia Station and it's contents (walls, floors and decals)
- tweak: Fixed firing pins
+2023-07-19:
+ SandPoot:
+ - rscadd: You can milk other people using the interaction menu.
diff --git a/interface/fonts/Grand9K_Pixel.ttf b/interface/fonts/Grand9K_Pixel.ttf
new file mode 100644
index 000000000000..cf6fdf44e2ec
Binary files /dev/null and b/interface/fonts/Grand9K_Pixel.ttf differ
diff --git a/interface/fonts/Pixellari.ttf b/interface/fonts/Pixellari.ttf
new file mode 100644
index 000000000000..5a3a3c2b1104
Binary files /dev/null and b/interface/fonts/Pixellari.ttf differ
diff --git a/interface/fonts/SpessFont.ttf b/interface/fonts/SpessFont.ttf
new file mode 100644
index 000000000000..8f7c7e08d0d8
Binary files /dev/null and b/interface/fonts/SpessFont.ttf differ
diff --git a/interface/fonts/TinyUnicode.ttf b/interface/fonts/TinyUnicode.ttf
new file mode 100644
index 000000000000..74d0d3e386e6
Binary files /dev/null and b/interface/fonts/TinyUnicode.ttf differ
diff --git a/interface/fonts/VCR_OSD_Mono.ttf b/interface/fonts/VCR_OSD_Mono.ttf
new file mode 100644
index 000000000000..dcca687a434d
Binary files /dev/null and b/interface/fonts/VCR_OSD_Mono.ttf differ
diff --git a/interface/fonts/fonts_datum.dm b/interface/fonts/fonts_datum.dm
new file mode 100644
index 000000000000..a346706d7fa0
--- /dev/null
+++ b/interface/fonts/fonts_datum.dm
@@ -0,0 +1,78 @@
+/// A font datum, it exists to define a custom font to use in a span style later.
+/datum/font
+ /// Font name, just so people know what to put in their span style.
+ var/name
+ /// The font file we link to.
+ var/font_family
+
+ /// Font features and metrics
+ /// Generated by Lummox's dmifontsplus (https://www.byond.com/developer/LummoxJR/DmiFontsPlus)
+ /// Note: these variable names have been changed, so you can't straight copy/paste from dmifontsplus.exe
+
+ /// list of font size/spacing metrics
+ var/list/metrics
+ /// total height of a line
+ var/height
+ /// distance above baseline (including whitespace)
+ var/ascent
+ /// distance below baseline
+ var/descent
+ /// average character width
+ var/average_width
+ /// maximum character width
+ var/max_width
+ /// extra width, such as from italics, for a line
+ var/overhang
+ /// internal leading vertical space, for accent marks
+ var/in_leading
+ /// external leading vertical space, just plain blank
+ var/ex_leading
+ /// default character (for undefined chars)
+ var/default_character
+ /// first character in metrics
+ var/start
+ /// last character in metrics
+ var/end
+
+/// Get font metrics
+/// From Lummox's dmifontsplus (https://www.byond.com/developer/LummoxJR/DmiFontsPlus)
+/datum/font/proc/get_metrics(text, flags, first_line)
+ . = 0
+ var/longest = 0
+ if(!length(text))
+ return
+
+ var/i = 1
+ var/idx
+ while(i <= length(text))
+ var/character = text2ascii(text, i++)
+ if(character <= 10)
+ if(character <= 7)
+ . += character // spacers for justification
+
+ if(character <= 9)
+ continue // soft-break chars
+
+ if(. && idx && !(flags & INCLUDE_AC))
+ . -= max(metrics[idx + 3], 0)
+
+ longest = max(longest, . + first_line)
+ . = 0
+ first_line = 0
+ idx = 0
+ continue
+
+ idx = (character - start) * 3
+ if(idx <= 0 || idx >= metrics.len)
+ idx = (default_character - start) * 3
+
+ if(!. && !(flags & INCLUDE_AC))
+ . -= metrics[idx + 1]
+ . += metrics[idx + 1] + metrics[idx + 2] + metrics[idx +3]
+
+ if(. && idx && !(flags & INCLUDE_AC))
+ . -= max(metrics[idx + 3], 0)
+
+ . = max(. + first_line, longest)
+ if(. > 0)
+ . += overhang
diff --git a/interface/fonts/grand_9k.dm b/interface/fonts/grand_9k.dm
new file mode 100644
index 000000000000..7993d307bcbe
--- /dev/null
+++ b/interface/fonts/grand_9k.dm
@@ -0,0 +1,253 @@
+/// For clean results on map, use only sizing pt, multiples of 6: 6pt 12pt 18pt 24pt etc. - Not for use with px sizing
+/// Can be used in TGUI etc, px sizing is pt / 0.75. 6pt = 8px, 12pt = 16px etc.
+
+/// Base font
+/datum/font/grand9k
+ name = "Grand9K Pixel"
+ font_family = 'interface/fonts/Grand9K_Pixel.ttf'
+
+/// For icon overlays
+/// Grand9K 6pt metrics generated using Lummox's dmifontsplus (https://www.byond.com/developer/LummoxJR/DmiFontsPlus)
+/// Note: these variable names have been changed, so you can't straight copy/paste from dmifontsplus.exe
+/datum/font/grand9k/size_6pt
+ name = "Grand9K Pixel 6pt"
+ height = 12
+ ascent = 10
+ descent = 2
+ average_width = 4
+ max_width = 9
+ overhang = 0
+ in_leading = 4
+ ex_leading = 1
+ default_character = 31
+ start = 30
+ end = 255
+ metrics = list(
+ 0, 5, 1, // char 30
+ 0, 5, 1, // char 31
+ 0, 1, 1, // char 32
+ 0, 1, 1, // char 33
+ 0, 3, 1, // char 34
+ 0, 6, 1, // char 35
+ 0, 5, 1, // char 36
+ 0, 7, 1, // char 37
+ 0, 5, 1, // char 38
+ 0, 1, 1, // char 39
+ 0, 3, 1, // char 40
+ 0, 3, 1, // char 41
+ 0, 5, 1, // char 42
+ 0, 5, 1, // char 43
+ 0, 1, 1, // char 44
+ 0, 4, 1, // char 45
+ 0, 1, 1, // char 46
+ 0, 3, 1, // char 47
+ 0, 5, 1, // char 48
+ 0, 2, 1, // char 49
+ 0, 5, 1, // char 50
+ 0, 4, 1, // char 51
+ 0, 5, 1, // char 52
+ 0, 5, 1, // char 53
+ 0, 5, 1, // char 54
+ 0, 5, 1, // char 55
+ 0, 5, 1, // char 56
+ 0, 5, 1, // char 57
+ 0, 1, 1, // char 58
+ 0, 1, 1, // char 59
+ 0, 4, 1, // char 60
+ 0, 4, 1, // char 61
+ 0, 4, 1, // char 62
+ 0, 4, 1, // char 63
+ 0, 7, 1, // char 64
+ 0, 5, 1, // char 65
+ 0, 5, 1, // char 66
+ 0, 4, 1, // char 67
+ 0, 5, 1, // char 68
+ 0, 4, 1, // char 69
+ 0, 4, 1, // char 70
+ 0, 5, 1, // char 71
+ 0, 5, 1, // char 72
+ 0, 1, 1, // char 73
+ 0, 5, 1, // char 74
+ 0, 5, 1, // char 75
+ 0, 5, 1, // char 76
+ 0, 5, 1, // char 77
+ 0, 5, 1, // char 78
+ 0, 5, 1, // char 79
+ 0, 5, 1, // char 80
+ 0, 6, 1, // char 81
+ 0, 5, 1, // char 82
+ 0, 5, 1, // char 83
+ 0, 5, 1, // char 84
+ 0, 5, 1, // char 85
+ 0, 5, 1, // char 86
+ 0, 5, 1, // char 87
+ 0, 5, 1, // char 88
+ 0, 5, 1, // char 89
+ 0, 5, 1, // char 90
+ 0, 3, 1, // char 91
+ 0, 3, 1, // char 92
+ 0, 3, 1, // char 93
+ 0, 5, 1, // char 94
+ 0, 4, 0, // char 95
+ 0, 2, 1, // char 96
+ 0, 4, 1, // char 97
+ 0, 4, 1, // char 98
+ 0, 3, 1, // char 99
+ 0, 4, 1, // char 100
+ 0, 4, 1, // char 101
+ 0, 4, 1, // char 102
+ 0, 4, 1, // char 103
+ 0, 4, 1, // char 104
+ 0, 1, 1, // char 105
+ 0, 3, 1, // char 106
+ 0, 4, 1, // char 107
+ 0, 1, 1, // char 108
+ 0, 5, 1, // char 109
+ 0, 4, 1, // char 110
+ 0, 4, 1, // char 111
+ 0, 4, 1, // char 112
+ 0, 4, 1, // char 113
+ 0, 4, 1, // char 114
+ 0, 4, 1, // char 115
+ 0, 4, 1, // char 116
+ 0, 4, 1, // char 117
+ 0, 5, 1, // char 118
+ 0, 5, 1, // char 119
+ 0, 5, 1, // char 120
+ 0, 4, 1, // char 121
+ 0, 5, 1, // char 122
+ 0, 4, 1, // char 123
+ 0, 1, 1, // char 124
+ 0, 4, 1, // char 125
+ 0, 6, 1, // char 126
+ 0, 5, 1, // char 127
+ 0, 5, 1, // char 128
+ 0, 5, 1, // char 129
+ 0, 1, 1, // char 130
+ 0, 5, 1, // char 131
+ 0, 3, 1, // char 132
+ 0, 5, 1, // char 133
+ 0, 5, 1, // char 134
+ 0, 5, 1, // char 135
+ 0, 5, 1, // char 136
+ 0, 5, 1, // char 137
+ 0, 5, 1, // char 138
+ 0, 3, 1, // char 139
+ 0, 6, 1, // char 140
+ 0, 5, 1, // char 141
+ 0, 5, 1, // char 142
+ 0, 5, 1, // char 143
+ 0, 5, 1, // char 144
+ 0, 1, 1, // char 145
+ 0, 1, 1, // char 146
+ 0, 3, 1, // char 147
+ 0, 3, 1, // char 148
+ 0, 1, 1, // char 149
+ 0, 5, 1, // char 150
+ 0, 5, 1, // char 151
+ 0, 5, 1, // char 152
+ 0, 8, 1, // char 153
+ 0, 4, 1, // char 154
+ 0, 3, 1, // char 155
+ 0, 5, 1, // char 156
+ 0, 5, 1, // char 157
+ 0, 5, 1, // char 158
+ 0, 5, 1, // char 159
+ 0, 1, 1, // char 160
+ 0, 1, 1, // char 161
+ 0, 4, 1, // char 162
+ 0, 5, 1, // char 163
+ 0, 5, 1, // char 164
+ 0, 5, 1, // char 165
+ 0, 1, 1, // char 166
+ 0, 5, 1, // char 167
+ 0, 3, 1, // char 168
+ 0, 8, 1, // char 169
+ 0, 5, 1, // char 170
+ 0, 6, 1, // char 171
+ 0, 4, 1, // char 172
+ 0, 5, 1, // char 173
+ 0, 8, 1, // char 174
+ 0, 5, 1, // char 175
+ 0, 3, 1, // char 176
+ 0, 5, 1, // char 177
+ 0, 5, 1, // char 178
+ 0, 5, 1, // char 179
+ 0, 2, 1, // char 180
+ 0, 4, 1, // char 181
+ 0, 5, 1, // char 182
+ 0, 1, 1, // char 183
+ 0, 2, 1, // char 184
+ 0, 5, 1, // char 185
+ 0, 5, 1, // char 186
+ 0, 6, 1, // char 187
+ 0, 5, 1, // char 188
+ 0, 5, 1, // char 189
+ 0, 5, 1, // char 190
+ 0, 4, 1, // char 191
+ 0, 5, 1, // char 192
+ 0, 5, 1, // char 193
+ 0, 5, 1, // char 194
+ 0, 6, 0, // char 195
+ 0, 5, 1, // char 196
+ 0, 5, 1, // char 197
+ 0, 6, 1, // char 198
+ 0, 4, 1, // char 199
+ 0, 4, 1, // char 200
+ 0, 4, 1, // char 201
+ 0, 4, 1, // char 202
+ 0, 4, 1, // char 203
+ 1, 2, 0, // char 204
+ 0, 2, 1, // char 205
+ 0, 3, 0, // char 206
+ 0, 3, 0, // char 207
+ 0, 6, 1, // char 208
+ 0, 6, 0, // char 209
+ 0, 5, 1, // char 210
+ 0, 5, 1, // char 211
+ 0, 5, 1, // char 212
+ 0, 6, 1, // char 213
+ 0, 5, 1, // char 214
+ 0, 5, 1, // char 215
+ 0, 5, 1, // char 216
+ 0, 5, 1, // char 217
+ 0, 5, 1, // char 218
+ 0, 5, 1, // char 219
+ 0, 5, 1, // char 220
+ 0, 5, 1, // char 221
+ 0, 5, 1, // char 222
+ 0, 5, 1, // char 223
+ 0, 4, 1, // char 224
+ 0, 4, 1, // char 225
+ 0, 4, 1, // char 226
+ 0, 4, 1, // char 227
+ 0, 4, 1, // char 228
+ 0, 4, 1, // char 229
+ 0, 5, 1, // char 230
+ 0, 3, 1, // char 231
+ 0, 4, 1, // char 232
+ 0, 4, 1, // char 233
+ 0, 4, 1, // char 234
+ 0, 4, 1, // char 235
+ 0, 2, 1, // char 236
+ 1, 2, 0, // char 237
+ 0, 3, 0, // char 238
+ 0, 3, 0, // char 239
+ 0, 5, 0, // char 240
+ 0, 4, 1, // char 241
+ 0, 4, 1, // char 242
+ 0, 4, 1, // char 243
+ 0, 4, 1, // char 244
+ 0, 4, 1, // char 245
+ 0, 4, 1, // char 246
+ 0, 5, 1, // char 247
+ 0, 4, 1, // char 248
+ 0, 4, 1, // char 249
+ 0, 4, 1, // char 250
+ 0, 4, 1, // char 251
+ 0, 4, 1, // char 252
+ 0, 4, 1, // char 253
+ 0, 4, 1, // char 254
+ 0, 4, 1, // char 255
+ 226
+ )
diff --git a/interface/fonts/license.txt b/interface/fonts/license.txt
new file mode 100644
index 000000000000..9aa70fbac2a9
--- /dev/null
+++ b/interface/fonts/license.txt
@@ -0,0 +1,13 @@
+Grand9K Pixel created by Jayvee Enaguas. Licensed under Creative Commons Attribution 4.0 International (CC BY 4.0)
+(https://creativecommons.org/licenses/by/4.0/) (https://www.dafont.com/grand9k-pixel.font)
+
+Pixellari created by Zacchary Dempsey-Plante. Website indicates free for commercial use.
+(https://www.dafont.com/pixellari.font?fpp=200)
+
+Spess Font created by MTandi (discord) for /tg/station.
+
+Tiny Unicode created by Jakob Riedle/DuffsDevice. Website indicates free for commercial use.
+(https://fontmeme.com/fonts/tiny-unicode-font/)
+
+VCR OSD Mono created by Riciery Leal/mrmanet. Website indicates 100% free, author confirms it's free for all to use.
+(https://www.dafont.com/font-comment.php?file=vcr_osd_mono)
diff --git a/interface/fonts/pixellari.dm b/interface/fonts/pixellari.dm
new file mode 100644
index 000000000000..24fcd1961fec
--- /dev/null
+++ b/interface/fonts/pixellari.dm
@@ -0,0 +1,252 @@
+/// For clean results on map, use only sizing pt, multiples of 12: 12pt 24pt 48pt etc. - Not for use with px sizing
+/// Can be used in TGUI etc, px sizing is pt / 0.75. 12pt = 16px, 24pt = 32px etc.
+
+/// Base font
+/datum/font/pixellari
+ name = "Pixellari"
+ font_family = 'interface/fonts/Pixellari.ttf'
+
+/// For icon overlays
+/// Pixellari 12pt metrics generated using Lummox's dmifontsplus (https://www.byond.com/developer/LummoxJR/DmiFontsPlus)
+/// Note: these variable names have been changed, so you can't straight copy/paste from dmifontsplus.exe
+/datum/font/pixellari/size_12pt
+ name = "Pixellari 12pt"
+ height = 16
+ ascent = 12
+ descent = 4
+ average_width = 7
+ max_width = 15
+ overhang = 0
+ in_leading = 0
+ ex_leading = 1
+ default_character = 31
+ start = 30
+ end = 255
+ metrics = list(\
+ 1, 5, 0, /* char 30 */ \
+ 1, 5, 0, /* char 31 */ \
+ 0, 1, 4, /* char 32 */ \
+ 1, 2, 1, /* char 33 */ \
+ 1, 5, 1, /* char 34 */ \
+ 0, 8, 1, /* char 35 */ \
+ 2, 6, 1, /* char 36 */ \
+ 0, 13, 1, /* char 37 */ \
+ 1, 8, 1, /* char 38 */ \
+ 1, 2, 1, /* char 39 */ \
+ 1, 3, 1, /* char 40 */ \
+ 2, 3, 1, /* char 41 */ \
+ 0, 6, 1, /* char 42 */ \
+ 1, 6, 1, /* char 43 */ \
+ 1, 2, 1, /* char 44 */ \
+ 1, 6, 1, /* char 45 */ \
+ 1, 2, 1, /* char 46 */ \
+ 0, 6, 1, /* char 47 */ \
+ 1, 7, 1, /* char 48 */ \
+ 2, 6, 1, /* char 49 */ \
+ 1, 6, 1, /* char 50 */ \
+ 1, 6, 1, /* char 51 */ \
+ 1, 7, 1, /* char 52 */ \
+ 1, 6, 1, /* char 53 */ \
+ 1, 6, 1, /* char 54 */ \
+ 1, 7, 1, /* char 55 */ \
+ 1, 6, 1, /* char 56 */ \
+ 1, 6, 1, /* char 57 */ \
+ 1, 2, 1, /* char 58 */ \
+ 1, 2, 1, /* char 59 */ \
+ 0, 10, 1, /* char 60 */ \
+ 1, 6, 1, /* char 61 */ \
+ 0, 10, 1, /* char 62 */ \
+ 1, 6, 1, /* char 63 */ \
+ 1, 12, 1, /* char 64 */ \
+ 1, 8, 1, /* char 65 */ \
+ 1, 8, 1, /* char 66 */ \
+ 2, 7, 1, /* char 67 */ \
+ 2, 8, 1, /* char 68 */ \
+ 2, 6, 1, /* char 69 */ \
+ 2, 6, 1, /* char 70 */ \
+ 2, 7, 1, /* char 71 */ \
+ 1, 8, 1, /* char 72 */ \
+ 1, 4, 1, /* char 73 */ \
+ 0, 7, 1, /* char 74 */ \
+ 1, 8, 1, /* char 75 */ \
+ 1, 6, 1, /* char 76 */ \
+ 1, 10, 1, /* char 77 */ \
+ 1, 9, 1, /* char 78 */ \
+ 2, 8, 1, /* char 79 */ \
+ 1, 7, 1, /* char 80 */ \
+ 2, 9, 1, /* char 81 */ \
+ 1, 8, 1, /* char 82 */ \
+ 1, 8, 1, /* char 83 */ \
+ 1, 8, 1, /* char 84 */ \
+ 2, 8, 1, /* char 85 */ \
+ 2, 8, 1, /* char 86 */ \
+ 1, 10, 1, /* char 87 */ \
+ 1, 8, 1, /* char 88 */ \
+ 1, 8, 1, /* char 89 */ \
+ 0, 10, 1, /* char 90 */ \
+ 1, 3, 1, /* char 91 */ \
+ 0, 6, 1, /* char 92 */ \
+ 2, 3, 1, /* char 93 */ \
+ 0, 7, 1, /* char 94 */ \
+ 0, 8, 1, /* char 95 */ \
+ 1, 3, 1, /* char 96 */ \
+ 1, 6, 1, /* char 97 */ \
+ 1, 7, 1, /* char 98 */ \
+ 1, 6, 1, /* char 99 */ \
+ 1, 7, 1, /* char 100 */ \
+ 1, 6, 1, /* char 101 */ \
+ 1, 4, 1, /* char 102 */ \
+ 1, 7, 1, /* char 103 */ \
+ 1, 7, 1, /* char 104 */ \
+ 1, 2, 1, /* char 105 */ \
+ -1, 4, 1, /* char 106 */ \
+ 0, 7, 1, /* char 107 */ \
+ 1, 2, 1, /* char 108 */ \
+ 1, 10, 1, /* char 109 */ \
+ 1, 6, 1, /* char 110 */ \
+ 1, 6, 1, /* char 111 */ \
+ 1, 7, 1, /* char 112 */ \
+ 1, 7, 1, /* char 113 */ \
+ 1, 6, 1, /* char 114 */ \
+ 1, 6, 1, /* char 115 */ \
+ 0, 4, 1, /* char 116 */ \
+ 1, 6, 1, /* char 117 */ \
+ 1, 6, 1, /* char 118 */ \
+ 1, 10, 1, /* char 119 */ \
+ 1, 6, 1, /* char 120 */ \
+ 1, 6, 1, /* char 121 */ \
+ 1, 6, 1, /* char 122 */ \
+ 0, 5, 1, /* char 123 */ \
+ 1, 2, 1, /* char 124 */ \
+ 0, 5, 1, /* char 125 */ \
+ 1, 8, 1, /* char 126 */ \
+ 1, 5, 0, /* char 127 */ \
+ 1, 8, 1, /* char 128 */ \
+ 1, 5, 0, /* char 129 */ \
+ 1, 5, 0, /* char 130 */ \
+ 1, 5, 0, /* char 131 */ \
+ 1, 5, 0, /* char 132 */ \
+ 1, 5, 0, /* char 133 */ \
+ 1, 5, 0, /* char 134 */ \
+ 1, 5, 0, /* char 135 */ \
+ 1, 5, 0, /* char 136 */ \
+ 1, 5, 0, /* char 137 */ \
+ 1, 8, 1, /* char 138 */ \
+ 1, 5, 0, /* char 139 */ \
+ 0, 14, 1, /* char 140 */ \
+ 1, 5, 0, /* char 141 */ \
+ 0, 10, 1, /* char 142 */ \
+ 1, 5, 0, /* char 143 */ \
+ 1, 5, 0, /* char 144 */ \
+ 1, 5, 0, /* char 145 */ \
+ 1, 5, 0, /* char 146 */ \
+ 1, 5, 0, /* char 147 */ \
+ 1, 5, 0, /* char 148 */ \
+ 1, 5, 0, /* char 149 */ \
+ 1, 5, 0, /* char 150 */ \
+ 1, 5, 0, /* char 151 */ \
+ 1, 5, 0, /* char 152 */ \
+ 1, 5, 0, /* char 153 */ \
+ 1, 6, 1, /* char 154 */ \
+ 1, 5, 0, /* char 155 */ \
+ 1, 11, 1, /* char 156 */ \
+ 1, 5, 0, /* char 157 */ \
+ 1, 6, 1, /* char 158 */ \
+ 1, 8, 1, /* char 159 */ \
+ 0, 1, 4, /* char 160 */ \
+ 1, 2, 1, /* char 161 */ \
+ 1, 6, 1, /* char 162 */ \
+ 0, 8, 1, /* char 163 */ \
+ 0, 9, 1, /* char 164 */ \
+ 1, 8, 1, /* char 165 */ \
+ 1, 2, 1, /* char 166 */ \
+ 1, 7, 1, /* char 167 */ \
+ 0, 5, 1, /* char 168 */ \
+ -1, 12, 1, /* char 169 */ \
+ 0, 6, 1, /* char 170 */ \
+ 0, 8, 1, /* char 171 */ \
+ 1, 8, 1, /* char 172 */ \
+ 1, 5, 0, /* char 173 */ \
+ -1, 12, 1, /* char 174 */ \
+ 2, 4, 1, /* char 175 */ \
+ 0, 6, 1, /* char 176 */ \
+ 1, 6, 1, /* char 177 */ \
+ 0, 5, 1, /* char 178 */ \
+ 0, 5, 1, /* char 179 */ \
+ 1, 3, 1, /* char 180 */ \
+ 1, 6, 1, /* char 181 */ \
+ 1, 7, 1, /* char 182 */ \
+ 1, 2, 1, /* char 183 */ \
+ 1, 3, 1, /* char 184 */ \
+ 1, 4, 1, /* char 185 */ \
+ 0, 6, 1, /* char 186 */ \
+ 0, 8, 1, /* char 187 */ \
+ 1, 13, 1, /* char 188 */ \
+ 1, 12, 1, /* char 189 */ \
+ 0, 13, 1, /* char 190 */ \
+ 1, 6, 1, /* char 191 */ \
+ 1, 8, 1, /* char 192 */ \
+ 1, 8, 1, /* char 193 */ \
+ 1, 8, 1, /* char 194 */ \
+ 1, 8, 1, /* char 195 */ \
+ 1, 8, 1, /* char 196 */ \
+ 1, 8, 1, /* char 197 */ \
+ 0, 13, 1, /* char 198 */ \
+ 2, 7, 1, /* char 199 */ \
+ 2, 6, 1, /* char 200 */ \
+ 2, 6, 1, /* char 201 */ \
+ 2, 6, 1, /* char 202 */ \
+ 2, 6, 1, /* char 203 */ \
+ 1, 4, 1, /* char 204 */ \
+ 1, 4, 1, /* char 205 */ \
+ 1, 4, 1, /* char 206 */ \
+ 1, 4, 1, /* char 207 */ \
+ 0, 10, 1, /* char 208 */ \
+ 1, 9, 1, /* char 209 */ \
+ 2, 8, 1, /* char 210 */ \
+ 2, 8, 1, /* char 211 */ \
+ 2, 8, 1, /* char 212 */ \
+ 2, 8, 1, /* char 213 */ \
+ 2, 8, 1, /* char 214 */ \
+ 1, 6, 1, /* char 215 */ \
+ -2, 14, 1, /* char 216 */ \
+ 2, 8, 1, /* char 217 */ \
+ 2, 8, 1, /* char 218 */ \
+ 2, 8, 1, /* char 219 */ \
+ 2, 8, 1, /* char 220 */ \
+ 1, 8, 1, /* char 221 */ \
+ 1, 8, 1, /* char 222 */ \
+ 1, 8, 1, /* char 223 */ \
+ 1, 6, 1, /* char 224 */ \
+ 1, 6, 1, /* char 225 */ \
+ 1, 6, 1, /* char 226 */ \
+ 1, 6, 1, /* char 227 */ \
+ 1, 6, 1, /* char 228 */ \
+ 1, 6, 1, /* char 229 */ \
+ 1, 11, 1, /* char 230 */ \
+ 1, 6, 1, /* char 231 */ \
+ 1, 6, 1, /* char 232 */ \
+ 1, 6, 1, /* char 233 */ \
+ 1, 6, 1, /* char 234 */ \
+ 1, 6, 1, /* char 235 */ \
+ 1, 2, 1, /* char 236 */ \
+ 1, 2, 1, /* char 237 */ \
+ 0, 4, 1, /* char 238 */ \
+ 0, 4, 1, /* char 239 */ \
+ 1, 7, 1, /* char 240 */ \
+ 1, 6, 1, /* char 241 */ \
+ 1, 6, 1, /* char 242 */ \
+ 1, 6, 1, /* char 243 */ \
+ 1, 6, 1, /* char 244 */ \
+ 1, 6, 1, /* char 245 */ \
+ 1, 6, 1, /* char 246 */ \
+ 1, 6, 1, /* char 247 */ \
+ 0, 10, 1, /* char 248 */ \
+ 1, 6, 1, /* char 249 */ \
+ 1, 6, 1, /* char 250 */ \
+ 1, 6, 1, /* char 251 */ \
+ 1, 6, 1, /* char 252 */ \
+ 1, 6, 1, /* char 253 */ \
+ 1, 8, 1, /* char 254 */ \
+ 1, 6, 1, /* char 255 */ \
+ 226)
diff --git a/interface/fonts/spess_font.dm b/interface/fonts/spess_font.dm
new file mode 100644
index 000000000000..07e8ea5b3ba6
--- /dev/null
+++ b/interface/fonts/spess_font.dm
@@ -0,0 +1,252 @@
+/// For clean results on map, use only sizing pt, multiples of 6: 6t 12pt 18pt etc. - Not for use with px sizing
+/// Can be used in TGUI etc, px sizing is pt / 0.75. 12pt = 16px, 24pt = 32px etc.
+
+/// Base font
+/datum/font/spessfont
+ name = "Spess Font"
+ font_family = 'interface/fonts/SpessFont.ttf'
+
+/// For icon overlays
+/// Spess Font 6pt metrics generated using Lummox's dmifontsplus (https://www.byond.com/developer/LummoxJR/DmiFontsPlus)
+/// Note: these variable names have been changed, so you can't straight copy/paste from dmifontsplus.exe
+/datum/font/spessfont/size_6pt
+ name = "Spess Font 6pt"
+ height = 8
+ ascent = 6
+ descent = 2
+ average_width = 4
+ max_width = 6
+ overhang = 0
+ in_leading = 0
+ ex_leading = 0
+ default_character = 31
+ start = 30
+ end = 255
+ metrics = list(\
+ 0, 1, 0, /* char 30 */ \
+ 0, 1, 0, /* char 31 */ \
+ 0, 1, 1, /* char 32 */ \
+ 0, 1, 1, /* char 33 */ \
+ 0, 3, 1, /* char 34 */ \
+ 0, 5, 1, /* char 35 */ \
+ 0, 3, 1, /* char 36 */ \
+ 0, 5, 1, /* char 37 */ \
+ 0, 5, 1, /* char 38 */ \
+ 0, 1, 1, /* char 39 */ \
+ 0, 2, 1, /* char 40 */ \
+ 0, 2, 1, /* char 41 */ \
+ 0, 3, 1, /* char 42 */ \
+ 0, 3, 1, /* char 43 */ \
+ 0, 1, 1, /* char 44 */ \
+ 0, 3, 1, /* char 45 */ \
+ 0, 1, 1, /* char 46 */ \
+ 0, 3, 1, /* char 47 */ \
+ 0, 4, 1, /* char 48 */ \
+ 0, 2, 1, /* char 49 */ \
+ 0, 4, 1, /* char 50 */ \
+ 0, 4, 1, /* char 51 */ \
+ 0, 4, 1, /* char 52 */ \
+ 0, 4, 1, /* char 53 */ \
+ 0, 4, 1, /* char 54 */ \
+ 0, 4, 1, /* char 55 */ \
+ 0, 4, 1, /* char 56 */ \
+ 0, 4, 1, /* char 57 */ \
+ 0, 1, 1, /* char 58 */ \
+ 0, 1, 1, /* char 59 */ \
+ 0, 3, 1, /* char 60 */ \
+ 0, 3, 1, /* char 61 */ \
+ 0, 3, 1, /* char 62 */ \
+ 0, 3, 1, /* char 63 */ \
+ 0, 4, 1, /* char 64 */ \
+ 0, 4, 1, /* char 65 */ \
+ 0, 4, 1, /* char 66 */ \
+ 0, 4, 1, /* char 67 */ \
+ 0, 4, 1, /* char 68 */ \
+ 0, 4, 1, /* char 69 */ \
+ 0, 4, 1, /* char 70 */ \
+ 0, 4, 1, /* char 71 */ \
+ 0, 4, 1, /* char 72 */ \
+ 0, 3, 1, /* char 73 */ \
+ 0, 4, 1, /* char 74 */ \
+ 0, 4, 1, /* char 75 */ \
+ 0, 4, 1, /* char 76 */ \
+ 0, 5, 1, /* char 77 */ \
+ 0, 4, 1, /* char 78 */ \
+ 0, 4, 1, /* char 79 */ \
+ 0, 4, 1, /* char 80 */ \
+ 0, 4, 1, /* char 81 */ \
+ 0, 4, 1, /* char 82 */ \
+ 0, 4, 1, /* char 83 */ \
+ 0, 5, 1, /* char 84 */ \
+ 0, 4, 1, /* char 85 */ \
+ 0, 4, 1, /* char 86 */ \
+ 0, 5, 1, /* char 87 */ \
+ 0, 5, 1, /* char 88 */ \
+ 0, 4, 1, /* char 89 */ \
+ 0, 4, 1, /* char 90 */ \
+ 0, 2, 1, /* char 91 */ \
+ 0, 3, 1, /* char 92 */ \
+ 0, 2, 1, /* char 93 */ \
+ 0, 3, 1, /* char 94 */ \
+ 0, 4, 1, /* char 95 */ \
+ 0, 2, 1, /* char 96 */ \
+ 0, 3, 1, /* char 97 */ \
+ 0, 4, 1, /* char 98 */ \
+ 0, 3, 1, /* char 99 */ \
+ 0, 4, 1, /* char 100 */ \
+ 0, 3, 1, /* char 101 */ \
+ 0, 2, 1, /* char 102 */ \
+ 0, 4, 1, /* char 103 */ \
+ 0, 3, 1, /* char 104 */ \
+ 0, 1, 1, /* char 105 */ \
+ 0, 1, 1, /* char 106 */ \
+ 0, 3, 1, /* char 107 */ \
+ 0, 1, 1, /* char 108 */ \
+ 0, 5, 1, /* char 109 */ \
+ 0, 3, 1, /* char 110 */ \
+ 0, 4, 1, /* char 111 */ \
+ 0, 4, 1, /* char 112 */ \
+ 0, 4, 1, /* char 113 */ \
+ 0, 2, 1, /* char 114 */ \
+ 0, 3, 1, /* char 115 */ \
+ 0, 2, 1, /* char 116 */ \
+ 0, 3, 1, /* char 117 */ \
+ 0, 3, 1, /* char 118 */ \
+ 0, 5, 1, /* char 119 */ \
+ 0, 3, 1, /* char 120 */ \
+ 0, 3, 1, /* char 121 */ \
+ 0, 3, 1, /* char 122 */ \
+ 0, 3, 1, /* char 123 */ \
+ 0, 1, 1, /* char 124 */ \
+ 0, 3, 1, /* char 125 */ \
+ 0, 4, 1, /* char 126 */ \
+ 0, 1, 0, /* char 127 */ \
+ 0, 1, 0, /* char 128 */ \
+ 0, 1, 0, /* char 129 */ \
+ 0, 1, 0, /* char 130 */ \
+ 0, 1, 0, /* char 131 */ \
+ 0, 1, 0, /* char 132 */ \
+ 0, 1, 0, /* char 133 */ \
+ 0, 1, 0, /* char 134 */ \
+ 0, 1, 0, /* char 135 */ \
+ 0, 1, 0, /* char 136 */ \
+ 0, 1, 0, /* char 137 */ \
+ 0, 1, 0, /* char 138 */ \
+ 0, 1, 0, /* char 139 */ \
+ 0, 1, 0, /* char 140 */ \
+ 0, 1, 0, /* char 141 */ \
+ 0, 1, 0, /* char 142 */ \
+ 0, 1, 0, /* char 143 */ \
+ 0, 1, 0, /* char 144 */ \
+ 0, 1, 0, /* char 145 */ \
+ 0, 1, 0, /* char 146 */ \
+ 0, 1, 0, /* char 147 */ \
+ 0, 1, 0, /* char 148 */ \
+ 0, 1, 0, /* char 149 */ \
+ 0, 1, 0, /* char 150 */ \
+ 0, 1, 0, /* char 151 */ \
+ 0, 1, 0, /* char 152 */ \
+ 0, 1, 0, /* char 153 */ \
+ 0, 1, 0, /* char 154 */ \
+ 0, 1, 0, /* char 155 */ \
+ 0, 1, 0, /* char 156 */ \
+ 0, 1, 0, /* char 157 */ \
+ 0, 1, 0, /* char 158 */ \
+ 0, 1, 0, /* char 159 */ \
+ 0, 1, 0, /* char 160 */ \
+ 0, 1, 0, /* char 161 */ \
+ 0, 1, 0, /* char 162 */ \
+ 0, 1, 0, /* char 163 */ \
+ 0, 1, 0, /* char 164 */ \
+ 0, 1, 0, /* char 165 */ \
+ 0, 1, 0, /* char 166 */ \
+ 0, 1, 0, /* char 167 */ \
+ 0, 1, 0, /* char 168 */ \
+ 0, 1, 0, /* char 169 */ \
+ 0, 1, 0, /* char 170 */ \
+ 0, 1, 0, /* char 171 */ \
+ 0, 1, 0, /* char 172 */ \
+ 0, 1, 0, /* char 173 */ \
+ 0, 1, 0, /* char 174 */ \
+ 0, 1, 0, /* char 175 */ \
+ 0, 1, 0, /* char 176 */ \
+ 0, 1, 0, /* char 177 */ \
+ 0, 1, 0, /* char 178 */ \
+ 0, 1, 0, /* char 179 */ \
+ 0, 1, 0, /* char 180 */ \
+ 0, 1, 0, /* char 181 */ \
+ 0, 1, 0, /* char 182 */ \
+ 0, 1, 0, /* char 183 */ \
+ 0, 1, 0, /* char 184 */ \
+ 0, 1, 0, /* char 185 */ \
+ 0, 1, 0, /* char 186 */ \
+ 0, 1, 0, /* char 187 */ \
+ 0, 1, 0, /* char 188 */ \
+ 0, 1, 0, /* char 189 */ \
+ 0, 1, 0, /* char 190 */ \
+ 0, 1, 0, /* char 191 */ \
+ 0, 1, 0, /* char 192 */ \
+ 0, 1, 0, /* char 193 */ \
+ 0, 1, 0, /* char 194 */ \
+ 0, 1, 0, /* char 195 */ \
+ 0, 1, 0, /* char 196 */ \
+ 0, 1, 0, /* char 197 */ \
+ 0, 1, 0, /* char 198 */ \
+ 0, 1, 0, /* char 199 */ \
+ 0, 1, 0, /* char 200 */ \
+ 0, 1, 0, /* char 201 */ \
+ 0, 1, 0, /* char 202 */ \
+ 0, 1, 0, /* char 203 */ \
+ 0, 1, 0, /* char 204 */ \
+ 0, 1, 0, /* char 205 */ \
+ 0, 1, 0, /* char 206 */ \
+ 0, 1, 0, /* char 207 */ \
+ 0, 1, 0, /* char 208 */ \
+ 0, 1, 0, /* char 209 */ \
+ 0, 1, 0, /* char 210 */ \
+ 0, 1, 0, /* char 211 */ \
+ 0, 1, 0, /* char 212 */ \
+ 0, 1, 0, /* char 213 */ \
+ 0, 1, 0, /* char 214 */ \
+ 0, 1, 0, /* char 215 */ \
+ 0, 1, 0, /* char 216 */ \
+ 0, 1, 0, /* char 217 */ \
+ 0, 1, 0, /* char 218 */ \
+ 0, 1, 0, /* char 219 */ \
+ 0, 1, 0, /* char 220 */ \
+ 0, 1, 0, /* char 221 */ \
+ 0, 1, 0, /* char 222 */ \
+ 0, 1, 0, /* char 223 */ \
+ 0, 1, 0, /* char 224 */ \
+ 0, 1, 0, /* char 225 */ \
+ 0, 1, 0, /* char 226 */ \
+ 0, 1, 0, /* char 227 */ \
+ 0, 1, 0, /* char 228 */ \
+ 0, 1, 0, /* char 229 */ \
+ 0, 1, 0, /* char 230 */ \
+ 0, 1, 0, /* char 231 */ \
+ 0, 1, 0, /* char 232 */ \
+ 0, 1, 0, /* char 233 */ \
+ 0, 1, 0, /* char 234 */ \
+ 0, 1, 0, /* char 235 */ \
+ 0, 1, 0, /* char 236 */ \
+ 0, 1, 0, /* char 237 */ \
+ 0, 1, 0, /* char 238 */ \
+ 0, 1, 0, /* char 239 */ \
+ 0, 1, 0, /* char 240 */ \
+ 0, 1, 0, /* char 241 */ \
+ 0, 1, 0, /* char 242 */ \
+ 0, 1, 0, /* char 243 */ \
+ 0, 1, 0, /* char 244 */ \
+ 0, 1, 0, /* char 245 */ \
+ 0, 1, 0, /* char 246 */ \
+ 0, 1, 0, /* char 247 */ \
+ 0, 1, 0, /* char 248 */ \
+ 0, 1, 0, /* char 249 */ \
+ 0, 1, 0, /* char 250 */ \
+ 0, 1, 0, /* char 251 */ \
+ 0, 1, 0, /* char 252 */ \
+ 0, 1, 0, /* char 253 */ \
+ 0, 1, 0, /* char 254 */ \
+ 0, 1, 0, /* char 255 */ \
+ 226)
diff --git a/interface/fonts/tiny_unicode.dm b/interface/fonts/tiny_unicode.dm
new file mode 100644
index 000000000000..d6af265d5182
--- /dev/null
+++ b/interface/fonts/tiny_unicode.dm
@@ -0,0 +1,253 @@
+/// For clean results on map, use only sizing pt, multiples of 12: 12pt 24pt 48pt etc. - Not for use with px sizing
+/// Can be used in TGUI etc, px sizing is pt / 0.75. 12pt = 16px, 24pt = 32px etc.
+
+/// Base font
+/datum/font/tiny_unicode
+ name = "TinyUnicode"
+ font_family = 'interface/fonts/TinyUnicode.ttf'
+
+/// For icon overlays
+/// TinyUnicode 12pt metrics generated using Lummox's dmifontsplus (https://www.byond.com/developer/LummoxJR/DmiFontsPlus)
+/// Note: these variable names have been changed, so you can't straight copy/paste from dmifontsplus.exe
+/datum/font/tiny_unicode/size_12pt
+ name = "TinyUnicode 12pt"
+ height = 13
+ ascent = 11
+ descent = 2
+ average_width = 5
+ max_width = 11
+ overhang = 0
+ in_leading = -3
+ ex_leading = 1
+ default_character = 31
+ start = 30
+ end = 255
+ metrics = list(
+ 1, 5, 0, // char 30
+ 1, 5, 0, // char 31
+ 0, 1, 4, // char 32
+ 0, 1, 1, // char 33
+ 0, 3, 1, // char 34
+ 0, 5, 1, // char 35
+ 0, 4, 1, // char 36
+ 0, 3, 1, // char 37
+ 0, 5, 1, // char 38
+ 0, 1, 1, // char 39
+ 0, 2, 1, // char 40
+ 0, 2, 1, // char 41
+ 0, 3, 1, // char 42
+ 0, 3, 1, // char 43
+ 0, 2, 1, // char 44
+ 0, 3, 1, // char 45
+ 0, 1, 1, // char 46
+ 0, 3, 1, // char 47
+ 0, 4, 1, // char 48
+ 0, 2, 1, // char 49
+ 0, 4, 1, // char 50
+ 0, 4, 1, // char 51
+ 0, 4, 1, // char 52
+ 0, 4, 1, // char 53
+ 0, 4, 1, // char 54
+ 0, 4, 1, // char 55
+ 0, 4, 1, // char 56
+ 0, 4, 1, // char 57
+ 0, 1, 1, // char 58
+ 0, 2, 1, // char 59
+ 0, 2, 1, // char 60
+ 0, 4, 1, // char 61
+ 0, 2, 1, // char 62
+ 0, 4, 1, // char 63
+ 0, 7, 1, // char 64
+ 0, 4, 1, // char 65
+ 0, 4, 1, // char 66
+ 0, 3, 1, // char 67
+ 0, 4, 1, // char 68
+ 0, 3, 1, // char 69
+ 0, 3, 1, // char 70
+ 0, 4, 1, // char 71
+ 0, 4, 1, // char 72
+ 0, 3, 1, // char 73
+ 0, 4, 1, // char 74
+ 0, 4, 1, // char 75
+ 0, 3, 1, // char 76
+ 0, 5, 1, // char 77
+ 0, 4, 1, // char 78
+ 0, 4, 1, // char 79
+ 0, 4, 1, // char 80
+ 0, 4, 1, // char 81
+ 0, 4, 1, // char 82
+ 0, 4, 1, // char 83
+ 0, 3, 1, // char 84
+ 0, 4, 1, // char 85
+ 0, 4, 1, // char 86
+ 0, 5, 1, // char 87
+ 0, 4, 1, // char 88
+ 0, 4, 1, // char 89
+ 0, 3, 1, // char 90
+ 0, 2, 1, // char 91
+ 0, 3, 1, // char 92
+ 0, 2, 1, // char 93
+ 0, 3, 1, // char 94
+ 0, 5, 1, // char 95
+ 0, 2, 1, // char 96
+ 0, 4, 1, // char 97
+ 0, 4, 1, // char 98
+ 0, 3, 1, // char 99
+ 0, 4, 1, // char 100
+ 0, 4, 1, // char 101
+ 0, 3, 1, // char 102
+ 0, 4, 1, // char 103
+ 0, 4, 1, // char 104
+ 0, 1, 1, // char 105
+ 0, 2, 1, // char 106
+ 0, 4, 1, // char 107
+ 0, 1, 1, // char 108
+ 0, 5, 1, // char 109
+ 0, 4, 1, // char 110
+ 0, 4, 1, // char 111
+ 0, 4, 1, // char 112
+ 0, 4, 1, // char 113
+ 0, 3, 1, // char 114
+ 0, 4, 1, // char 115
+ 0, 3, 1, // char 116
+ 0, 4, 1, // char 117
+ 0, 4, 1, // char 118
+ 0, 5, 1, // char 119
+ 0, 3, 1, // char 120
+ 0, 4, 1, // char 121
+ 0, 4, 1, // char 122
+ 0, 3, 1, // char 123
+ 0, 1, 1, // char 124
+ 0, 3, 1, // char 125
+ 0, 5, 1, // char 126
+ 1, 5, 0, // char 127
+ 0, 4, 1, // char 128
+ 1, 5, 0, // char 129
+ 1, 5, 0, // char 130
+ 1, 5, 0, // char 131
+ 1, 5, 0, // char 132
+ 1, 5, 0, // char 133
+ 1, 5, 0, // char 134
+ 1, 5, 0, // char 135
+ 1, 5, 0, // char 136
+ 0, 5, 1, // char 137
+ 1, 5, 0, // char 138
+ 1, 5, 0, // char 139
+ 0, 6, 1, // char 140
+ 1, 5, 0, // char 141
+ 1, 5, 0, // char 142
+ 1, 5, 0, // char 143
+ 1, 5, 0, // char 144
+ 1, 5, 0, // char 145
+ 1, 5, 0, // char 146
+ 1, 5, 0, // char 147
+ 1, 5, 0, // char 148
+ 0, 2, 1, // char 149
+ 1, 5, 0, // char 150
+ 1, 5, 0, // char 151
+ 1, 5, 0, // char 152
+ 0, 4, 1, // char 153
+ 1, 5, 0, // char 154
+ 1, 5, 0, // char 155
+ 1, 5, 0, // char 156
+ 1, 5, 0, // char 157
+ 1, 5, 0, // char 158
+ 0, 4, 1, // char 159
+ 1, 5, 0, // char 160
+ 0, 1, 1, // char 161
+ 0, 4, 1, // char 162
+ 0, 4, 1, // char 163
+ 0, 5, 1, // char 164
+ 0, 3, 1, // char 165
+ 0, 1, 1, // char 166
+ 0, 4, 1, // char 167
+ 0, 3, 1, // char 168
+ 0, 2, 1, // char 169
+ 0, 8, 1, // char 170
+ 0, 4, 1, // char 171
+ 0, 4, 1, // char 172
+ 1, 5, 0, // char 173
+ 0, 2, 1, // char 174
+ 0, 4, 1, // char 175
+ 0, 3, 1, // char 176
+ 0, 3, 1, // char 177
+ 0, 2, 1, // char 178
+ 0, 2, 1, // char 179
+ 0, 2, 1, // char 180
+ 0, 4, 1, // char 181
+ 0, 5, 1, // char 182
+ 1, 1, 1, // char 183
+ 0, 8, 1, // char 184
+ 0, 2, 1, // char 185
+ 0, 2, 1, // char 186
+ 0, 4, 1, // char 187
+ 0, 7, 1, // char 188
+ 0, 8, 1, // char 189
+ 0, 8, 1, // char 190
+ 0, 4, 1, // char 191
+ 0, 4, 1, // char 192
+ 0, 4, 1, // char 193
+ 0, 4, 1, // char 194
+ 0, 4, 1, // char 195
+ 0, 4, 1, // char 196
+ 0, 4, 1, // char 197
+ 0, 6, 1, // char 198
+ 0, 3, 1, // char 199
+ 0, 3, 1, // char 200
+ 0, 3, 1, // char 201
+ 0, 3, 1, // char 202
+ 0, 3, 1, // char 203
+ 0, 3, 1, // char 204
+ 0, 3, 1, // char 205
+ 0, 3, 1, // char 206
+ 0, 3, 1, // char 207
+ 0, 10, 1, // char 208
+ 0, 4, 1, // char 209
+ 0, 4, 1, // char 210
+ 0, 4, 1, // char 211
+ 0, 4, 1, // char 212
+ 0, 4, 1, // char 213
+ 0, 4, 1, // char 214
+ 0, 3, 1, // char 215
+ 0, 5, 1, // char 216
+ 0, 4, 1, // char 217
+ 0, 4, 1, // char 218
+ 0, 4, 1, // char 219
+ 0, 4, 1, // char 220
+ 0, 4, 1, // char 221
+ 0, 3, 1, // char 222
+ 0, 3, 1, // char 223
+ 0, 4, 1, // char 224
+ 0, 4, 1, // char 225
+ 0, 4, 1, // char 226
+ 0, 4, 1, // char 227
+ 0, 4, 1, // char 228
+ 0, 4, 1, // char 229
+ 0, 7, 1, // char 230
+ 0, 3, 1, // char 231
+ 0, 4, 1, // char 232
+ 0, 4, 1, // char 233
+ 0, 4, 1, // char 234
+ 0, 4, 1, // char 235
+ 0, 2, 1, // char 236
+ 0, 2, 1, // char 237
+ 0, 3, 1, // char 238
+ 0, 3, 1, // char 239
+ 0, 5, 1, // char 240
+ 0, 4, 1, // char 241
+ 0, 4, 1, // char 242
+ 0, 4, 1, // char 243
+ 0, 4, 1, // char 244
+ 0, 4, 1, // char 245
+ 0, 4, 1, // char 246
+ 0, 5, 1, // char 247
+ 0, 4, 1, // char 248
+ 0, 4, 1, // char 249
+ 0, 4, 1, // char 250
+ 0, 4, 1, // char 251
+ 0, 4, 1, // char 252
+ 0, 4, 1, // char 253
+ 0, 10, 1, // char 254
+ 0, 4, 1, // char 255
+ 226
+ )
diff --git a/interface/fonts/vcr_osd_mono.dm b/interface/fonts/vcr_osd_mono.dm
new file mode 100644
index 000000000000..301d90d2f7ea
--- /dev/null
+++ b/interface/fonts/vcr_osd_mono.dm
@@ -0,0 +1,3 @@
+/datum/font/vcr_osd_mono
+ name = "VCR OSD Mono"
+ font_family = 'interface/fonts/VCR_OSD_Mono.ttf'
diff --git a/interface/skin.dmf b/interface/skin.dmf
index 55d0700faac4..1a5dae09cc7f 100644
--- a/interface/skin.dmf
+++ b/interface/skin.dmf
@@ -108,7 +108,7 @@ window "mapwindow"
text-color = none
is-default = true
saved-params = "zoom;letterbox;zoom-mode"
- style = ".center { text-align: center; } .maptext { font-family: 'Small Fonts'; font-size: 7px; -dm-text-outline: 1px black; color: white; line-height: 1.1; } .command_headset { font-weight: bold;\tfont-size: 8px; } .small { font-size: 6px; } .big { font-size: 8px; } .reallybig { font-size: 8px; } .extremelybig { font-size: 8px; } .greentext { color: #00FF00; font-size: 7px; } .redtext { color: #FF0000; font-size: 7px; } .clown { color: #FF69Bf; font-size: 7px; font-weight: bold; } .his_grace { color: #15D512; } .hypnophrase { color: #0d0d0d; font-weight: bold; } .yell { font-weight: bold; } .italics { font-size: 6px; }"
+ style = ".center { text-align: center; } .maptext { font-family: 'Small Fonts'; font-size: 7px; -dm-text-outline: 1px black; color: white; line-height: 1.1; } .command_headset { font-weight: bold;\tfont-size: 8px; } .context { font-family: 'Pixellari'; font-size: 12pt; -dm-text-outline: 1px black; } .subcontext { font-family: 'TinyUnicode'; font-size: 12pt; line-height: 0.75; } .small { font-size: 6px; } .big { font-size: 8px; } .reallybig { font-size: 8px; } .extremelybig { font-size: 8px; } .greentext { color: #00FF00; font-size: 7px; } .redtext { color: #FF0000; font-size: 7px; } .clown { color: #FF69Bf; font-size: 7px; font-weight: bold; } .his_grace { color: #15D512; } .hypnophrase { color: #0d0d0d; font-weight: bold; } .yell { font-weight: bold; } .italics { font-size: 6px; }"
elem "status_bar"
type = LABEL
pos = 0,1008
diff --git a/modular_sand/code/datums/interactions/interaction_datums/lewd/breasts.dm b/modular_sand/code/datums/interactions/interaction_datums/lewd/breasts.dm
index 5f4c1354bad9..2434459cdc96 100644
--- a/modular_sand/code/datums/interactions/interaction_datums/lewd/breasts.dm
+++ b/modular_sand/code/datums/interactions/interaction_datums/lewd/breasts.dm
@@ -56,59 +56,98 @@
interaction_sound = null
max_distance = 1
+ additional_details = list(
+ list(
+ "info" = "You can fill a container if you hold it in your hand or pull it",
+ "icon" = "flask",
+ "color" = "transparent"
+ )
+ )
+
/datum/interaction/lewd/titgrope/display_interaction(mob/living/carbon/human/user, mob/living/carbon/human/target)
- if(user.a_intent == INTENT_HELP)
- user.visible_message(
- pick(span_lewd("\The [user] gently gropes \the [target]'s breast."),
- span_lewd("\The [user] softly squeezes \the [target]'s breasts."),
- span_lewd("\The [user] grips \the [target]'s breasts."),
- span_lewd("\The [user] runs a few fingers over \the [target]'s breast."),
- span_lewd("\The [user] delicately teases \the [target]'s nipple."),
- span_lewd("\The [user] traces a touch across \the [target]'s breast.")))
- if(user.a_intent == INTENT_HARM)
- user.visible_message(
- pick(span_lewd("\The [user] aggressively gropes \the [target]'s breast."),
- span_lewd("\The [user] grabs \the [target]'s breasts."),
- span_lewd("\The [user] tightly squeezes \the [target]'s breasts."),
- span_lewd("\The [user] slaps at \the [target]'s breasts."),
- span_lewd("\The [user] gropes \the [target]'s breasts roughly.")))
- if(prob(5 + target.get_lust()))
- if(target.a_intent == INTENT_HELP)
+ var/obj/item/reagent_containers/liquid_container
+
+ var/obj/item/cached_item = user.get_active_held_item()
+ if(istype(cached_item, /obj/item/reagent_containers))
+ liquid_container = cached_item
+ else
+ cached_item = user.pulling
+ if(istype(cached_item, /obj/item/reagent_containers))
+ liquid_container = cached_item
+
+ if(liquid_container)
+ var/obj/item/organ/genital/breasts/milkers = target.getorganslot(ORGAN_SLOT_BREASTS)
+ var/milktype = milkers?.fluid_id
+
+ if(milkers && milktype)
+ var/modifier
+ switch(milkers.size)
+ if("c", "d", "e")
+ modifier = 2
+ if("f", "g", "h")
+ modifier = 3
+ else
+ if(milkers.size in GLOB.breast_values) //SPLURT edit - global breast values
+ modifier = clamp(GLOB.breast_values[milkers.size] - 5, 0, INFINITY)
+ else
+ modifier = 1
+ liquid_container.reagents.add_reagent(milktype, rand(1,3 * modifier))
+
+ user.visible_message(span_lewd("\The [user] milks [target]'s breasts into \the [liquid_container]."), ignored_mobs = user.get_unconsenting())
+ playlewdinteractionsound(get_turf(user), 'modular_sand/sound/interactions/squelch1.ogg', 50, 1, -1)
+ else
+ if(user.a_intent == INTENT_HARM)
user.visible_message(
- pick(span_lewd("\The [target] shivers in arousal."),
- span_lewd("\The [target] moans quietly."),
- span_lewd("\The [target] breathes out a soft moan."),
- span_lewd("\The [target] gasps."),
- span_lewd("\The [target] shudders softly."),
- span_lewd("\The [target] trembles as hands run across bare skin.")))
- if(target.get_lust() < 5)
- target.set_lust(5)
- if(target.a_intent == INTENT_DISARM)
- if (target.restrained())
- user.visible_message(
- pick(span_lewd("\The [target] twists playfully against the restraints."),
- span_lewd("\The [target] squirms away from [user]'s hand."),
- span_lewd("\The [target] slides back from [user]'s roaming hand."),
- span_lewd("\The [target] thrusts bare breasts forward into [user]'s hands.")))
- else
+ pick(span_lewd("\The [user] aggressively gropes \the [target]'s breast."),
+ span_lewd("\The [user] grabs \the [target]'s breasts."),
+ span_lewd("\The [user] tightly squeezes \the [target]'s breasts."),
+ span_lewd("\The [user] slaps at \the [target]'s breasts."),
+ span_lewd("\The [user] gropes \the [target]'s breasts roughly.")))
+ else
+ user.visible_message(
+ pick(span_lewd("\The [user] gently gropes \the [target]'s breast."),
+ span_lewd("\The [user] softly squeezes \the [target]'s breasts."),
+ span_lewd("\The [user] grips \the [target]'s breasts."),
+ span_lewd("\The [user] runs a few fingers over \the [target]'s breast."),
+ span_lewd("\The [user] delicately teases \the [target]'s nipple."),
+ span_lewd("\The [user] traces a touch across \the [target]'s breast.")))
+ if(prob(5 + target.get_lust()))
+ if(target.a_intent == INTENT_HELP)
user.visible_message(
- pick(span_lewd("\The [target] playfully bats at [user]'s hand."),
- span_lewd("\The [target] squirms away from [user]'s hand."),
- span_lewd("\The [target] guides [user]'s hand across bare breasts."),
- span_lewd("\The [target] teasingly laces a few fingers over [user]'s knuckles.")))
- if(target.get_lust() < 10)
- target.handle_post_sex(NORMAL_LUST, CUM_TARGET_HAND, user, ORGAN_SLOT_BREASTS) //SPLURT edit
- if(target.a_intent == INTENT_GRAB)
- user.visible_message(
- pick(span_lewd("\The [target] grips [user]'s wrist tight."),
- span_lewd("\The [target] digs nails into [user]'s arm."),
- span_lewd("\The [target] grabs [user]'s wrist for a second.")))
- if(target.a_intent == INTENT_HARM)
- user.adjustBruteLoss(1)
- user.visible_message(
- pick(span_lewd("\The [target] pushes [user] roughly away."),
- span_lewd("\The [target] digs nails angrily into [user]'s arm."),
- span_lewd("\The [target] fiercely struggles against [user]."),
- span_lewd("\The [target] claws [user]'s forearm, drawing blood."),
- span_lewd("\The [target] slaps [user]'s hand away.")))
- return
+ pick(span_lewd("\The [target] shivers in arousal."),
+ span_lewd("\The [target] moans quietly."),
+ span_lewd("\The [target] breathes out a soft moan."),
+ span_lewd("\The [target] gasps."),
+ span_lewd("\The [target] shudders softly."),
+ span_lewd("\The [target] trembles as hands run across bare skin.")))
+ if(target.get_lust() < 5)
+ target.set_lust(5)
+ if(target.a_intent == INTENT_DISARM)
+ if (target.restrained())
+ user.visible_message(
+ pick(span_lewd("\The [target] twists playfully against the restraints."),
+ span_lewd("\The [target] squirms away from [user]'s hand."),
+ span_lewd("\The [target] slides back from [user]'s roaming hand."),
+ span_lewd("\The [target] thrusts bare breasts forward into [user]'s hands.")))
+ else
+ user.visible_message(
+ pick(span_lewd("\The [target] playfully bats at [user]'s hand."),
+ span_lewd("\The [target] squirms away from [user]'s hand."),
+ span_lewd("\The [target] guides [user]'s hand across bare breasts."),
+ span_lewd("\The [target] teasingly laces a few fingers over [user]'s knuckles.")))
+ if(target.get_lust() < 10)
+ target.add_lust(1)
+ if(target.a_intent == INTENT_GRAB)
+ user.visible_message(
+ pick(span_lewd("\The [target] grips [user]'s wrist tight."),
+ span_lewd("\The [target] digs nails into [user]'s arm."),
+ span_lewd("\The [target] grabs [user]'s wrist for a second.")))
+ if(target.a_intent == INTENT_HARM)
+ user.adjustBruteLoss(1)
+ user.visible_message(
+ pick(span_lewd("\The [target] pushes [user] roughly away."),
+ span_lewd("\The [target] digs nails angrily into [user]'s arm."),
+ span_lewd("\The [target] fiercely struggles against [user]."),
+ span_lewd("\The [target] claws [user]'s forearm, drawing blood."),
+ span_lewd("\The [target] slaps [user]'s hand away.")))
+
diff --git a/modular_sand/code/datums/interactions/interaction_datums/lewd/finger.dm b/modular_sand/code/datums/interactions/interaction_datums/lewd/finger.dm
index ce0688cc7df2..6a9adac9084f 100644
--- a/modular_sand/code/datums/interactions/interaction_datums/lewd/finger.dm
+++ b/modular_sand/code/datums/interactions/interaction_datums/lewd/finger.dm
@@ -5,12 +5,38 @@
interaction_sound = null
max_distance = 1
+ additional_details = list(
+ list(
+ "info" = "You can fill a container if you hold it in your hand or pull it",
+ "icon" = "flask",
+ "color" = "transparent"
+ )
+ )
+
/datum/interaction/lewd/finger/display_interaction(mob/living/user, mob/living/partner)
- user.visible_message(message = "\The [user] [pick("fingers \the [partner].",
- "fingers \the [partner]'s pussy.",
- "fingers \the [partner] hard.")]", ignored_mobs = user.get_unconsenting())
+ var/obj/item/reagent_containers/liquid_container
+
+ var/obj/item/cached_item = user.get_active_held_item()
+ if(istype(cached_item, /obj/item/reagent_containers))
+ liquid_container = cached_item
+ else
+ cached_item = user.pulling
+ if(istype(cached_item, /obj/item/reagent_containers))
+ liquid_container = cached_item
+
+ var/message = "[pick("fingers \the [partner]",
+ "fingers \the [partner]'s pussy",
+ "fingers \the [partner] hard")]"
+
+ if(!partner.is_fucking(user, CUM_TARGET_HAND, partner.getorganslot(ORGAN_SLOT_VAGINA)))
+ partner.set_is_fucking(user, CUM_TARGET_HAND, partner.getorganslot(ORGAN_SLOT_VAGINA))
+
+ if(liquid_container)
+ message += " over \the [liquid_container]"
+
+ user.visible_message(span_lewd("\The [user] [message]."), ignored_mobs = user.get_unconsenting())
playlewdinteractionsound(get_turf(user), 'modular_sand/sound/interactions/champ_fingering.ogg', 50, 1, -1)
- partner.handle_post_sex(NORMAL_LUST, null, user, ORGAN_SLOT_VAGINA) //SPLURT edit
+ partner.handle_post_sex(NORMAL_LUST, CUM_TARGET_HAND, liquid_container ? liquid_container : user, ORGAN_SLOT_VAGINA) //SPLURT edit
/datum/interaction/lewd/fingerass
description = "Finger their ass."
diff --git a/modular_sand/code/datums/interactions/interaction_datums/lewd/handjob.dm b/modular_sand/code/datums/interactions/interaction_datums/lewd/handjob.dm
index 8f90a1602a5b..1d55dc76bce1 100644
--- a/modular_sand/code/datums/interactions/interaction_datums/lewd/handjob.dm
+++ b/modular_sand/code/datums/interactions/interaction_datums/lewd/handjob.dm
@@ -5,23 +5,43 @@
require_target_penis = REQUIRE_EXPOSED
max_distance = 1
+ additional_details = list(
+ list(
+ "info" = "You can fill a container if you hold it in your hand or pull it",
+ "icon" = "flask",
+ "color" = "transparent"
+ )
+ )
+
/datum/interaction/lewd/handjob/display_interaction(mob/living/user, mob/living/partner)
var/message
var/u_His = user.p_their()
var/genital_name = partner.get_penetrating_genital_name()
- if(partner.is_fucking(user, CUM_TARGET_HAND))
- message = "[pick("jerks \the [partner] off.",
- "works \the [partner]'s shaft.",
- "wanks \the [partner]'s [genital_name] hard.")]"
+ var/obj/item/reagent_containers/liquid_container
+
+ var/obj/item/cached_item = user.get_active_held_item()
+ if(istype(cached_item, /obj/item/reagent_containers))
+ liquid_container = cached_item
+ else
+ cached_item = user.pulling
+ if(istype(cached_item, /obj/item/reagent_containers))
+ liquid_container = cached_item
+
+ if(partner.is_fucking(user, CUM_TARGET_HAND, partner.getorganslot(ORGAN_SLOT_PENIS)))
+ message = "[pick("jerks \the [partner] off",
+ "works \the [partner]'s shaft",
+ "wanks \the [partner]'s [genital_name] hard")]"
else
- message = "[pick("wraps [u_His] hand around \the [partner]'s [genital_name].",
+ message = "[pick("wraps [u_His] hand around \the [partner]'s [genital_name]",
"starts playing with \the [partner]'s [genital_name]")]"
partner.set_is_fucking(user, CUM_TARGET_HAND, partner.getorganslot(ORGAN_SLOT_PENIS))
+ if(liquid_container)
+ message += " over \the [liquid_container]"
playlewdinteractionsound(get_turf(user), pick('modular_sand/sound/interactions/bang1.ogg',
'modular_sand/sound/interactions/bang2.ogg',
'modular_sand/sound/interactions/bang3.ogg'), 70, 1, -1)
- user.visible_message(span_lewd("\The [user] [message]"), ignored_mobs = user.get_unconsenting())
+ user.visible_message(span_lewd("\The [user] [message]."), ignored_mobs = user.get_unconsenting())
if(partner.can_penetrating_genital_cum())
- partner.handle_post_sex(NORMAL_LUST, CUM_TARGET_HAND, user, ORGAN_SLOT_PENIS) //SPLURT edit
+ partner.handle_post_sex(NORMAL_LUST, CUM_TARGET_HAND, liquid_container ? liquid_container : user, ORGAN_SLOT_PENIS) //SPLURT edit
diff --git a/modular_sand/code/datums/interactions/interaction_datums/lewd/self/jack.dm b/modular_sand/code/datums/interactions/interaction_datums/lewd/self/jack.dm
index 965c3eefe499..36f74316ece0 100644
--- a/modular_sand/code/datums/interactions/interaction_datums/lewd/self/jack.dm
+++ b/modular_sand/code/datums/interactions/interaction_datums/lewd/self/jack.dm
@@ -48,6 +48,6 @@
playlewdinteractionsound(get_turf(user), pick('modular_sand/sound/interactions/bang1.ogg',
'modular_sand/sound/interactions/bang2.ogg',
'modular_sand/sound/interactions/bang3.ogg'), 70, 1, -1)
- user.visible_message(message = span_lewd("\The [user] [message]."), ignored_mobs = user.get_unconsenting())
+ user.visible_message(span_lewd("\The [user] [message]."), ignored_mobs = user.get_unconsenting())
if(user.can_penetrating_genital_cum())
user.handle_post_sex(NORMAL_LUST, CUM_TARGET_HAND, liquid_container ? liquid_container : user, ORGAN_SLOT_PENIS) //SPLURT edit
diff --git a/modular_sand/code/datums/interactions/lewd_definitions.dm b/modular_sand/code/datums/interactions/lewd_definitions.dm
index 494032c54a96..a10bd2aae1b2 100644
--- a/modular_sand/code/datums/interactions/lewd_definitions.dm
+++ b/modular_sand/code/datums/interactions/lewd_definitions.dm
@@ -420,6 +420,10 @@
var/partner_carbon_check = FALSE
var/obj/item/organ/genital/target_gen = null
var/mob/living/carbon/c_partner = null
+
+ // Do not display to those people as well
+ var/list/mob/obscure_to
+
//Carbon checks
if(iscarbon(partner))
c_partner = partner
@@ -754,11 +758,16 @@
else
message = pick("orgasms violently!", "twists in orgasm.")
else if(istype(partner, /obj/item/reagent_containers))
+ var/did_anything = TRUE
switch(last_genital.type)
if(/obj/item/organ/genital/penis)
- message = "cums into \the [partner]"
+ message = "cums into \the [partner]!"
if(/obj/item/organ/genital/vagina)
- message = "squirts into \the [partner]"
+ message = "squirts into \the [partner]!"
+ else
+ did_anything = FALSE
+ if(did_anything)
+ LAZYADD(obscure_to, src)
else //todo: better self cum messages
message = "cums all over themselves!"
if(gender == MALE)
@@ -767,15 +776,11 @@
'modular_sand/sound/interactions/final_m3.ogg',
'modular_sand/sound/interactions/final_m4.ogg',
'modular_sand/sound/interactions/final_m5.ogg'), 90, 1, 0)
- else if(gender == FEMALE)
- playlewdinteractionsound(loc, pick('modular_sand/sound/interactions/final_f1.ogg',
- 'modular_sand/sound/interactions/final_f2.ogg',
- 'modular_sand/sound/interactions/final_f3.ogg'), 70, 1, 0)
else
playlewdinteractionsound(loc, pick('modular_sand/sound/interactions/final_f1.ogg',
'modular_sand/sound/interactions/final_f2.ogg',
'modular_sand/sound/interactions/final_f3.ogg'), 70, 1, 0)
- visible_message(message = span_userlove("\The [src] [message]"), ignored_mobs = get_unconsenting())
+ visible_message(message = span_userlove("\The [src] [message]"), ignored_mobs = get_unconsenting(ignored_mobs = obscure_to))
multiorgasms += 1
COOLDOWN_START(src, refractory_period, (rand(300, 900) - get_sexual_potency()))//sex cooldown
diff --git a/tgstation.dme b/tgstation.dme
index 0e6a596f1c3f..53646ef6e637 100644
--- a/tgstation.dme
+++ b/tgstation.dme
@@ -54,6 +54,7 @@
#include "code\__DEFINES\explosion.dm"
#include "code\__DEFINES\exports.dm"
#include "code\__DEFINES\fantasy_affixes.dm"
+#include "code\__DEFINES\fonts.dm"
#include "code\__DEFINES\food.dm"
#include "code\__DEFINES\footsteps.dm"
#include "code\__DEFINES\gun.dm"
@@ -218,7 +219,6 @@
#include "code\__HELPERS\reagents.dm"
#include "code\__HELPERS\roundend.dm"
#include "code\__HELPERS\sanitize_values.dm"
-#include "code\__HELPERS\screentips.dm"
#include "code\__HELPERS\shell.dm"
#include "code\__HELPERS\stat_tracking.dm"
#include "code\__HELPERS\text.dm"
@@ -834,6 +834,7 @@
#include "code\datums\ruins\station.dm"
#include "code\datums\screentips\atom_context.dm"
#include "code\datums\screentips\item_context.dm"
+#include "code\datums\screentips\screentips.dm"
#include "code\datums\skills\_check_skills.dm"
#include "code\datums\skills\_skill.dm"
#include "code\datums\skills\_skill_holder.dm"
@@ -3893,6 +3894,12 @@
#include "interface\menu.dm"
#include "interface\stylesheet.dm"
#include "interface\skin.dmf"
+#include "interface\fonts\fonts_datum.dm"
+#include "interface\fonts\grand_9k.dm"
+#include "interface\fonts\pixellari.dm"
+#include "interface\fonts\spess_font.dm"
+#include "interface\fonts\tiny_unicode.dm"
+#include "interface\fonts\vcr_osd_mono.dm"
#include "modular_citadel\code\datums\components\souldeath.dm"
#include "modular_citadel\code\datums\status_effects\chems.dm"
#include "modular_citadel\code\game\objects\effects\temporary_visuals\souldeath.dm"