diff --git a/code/modules/modular_computers/NTNet/NTNRC/conversation.dm b/code/modules/modular_computers/NTNet/NTNRC/conversation.dm
index fada2229e5..1c79449a39 100644
--- a/code/modules/modular_computers/NTNet/NTNRC/conversation.dm
+++ b/code/modules/modular_computers/NTNet/NTNRC/conversation.dm
@@ -86,7 +86,7 @@
offline_clients.Add(offline)
/datum/ntnet_conversation/proc/mute_user(datum/computer_file/program/chatclient/op, datum/computer_file/program/chatclient/muted)
- if(operator != op) //sanity even if the person shouldn't be able to see the mute button
+ if(!op.netadmin_mode && operator != op) //sanity even if the person shouldn't be able to see the mute button
return
if(muted in muted_clients)
muted_clients.Remove(muted)
diff --git a/code/modules/modular_computers/file_system/programs/ntnrc_client.dm b/code/modules/modular_computers/file_system/programs/ntnrc_client.dm
index 29a4418d2c..b1cc503565 100644
--- a/code/modules/modular_computers/file_system/programs/ntnrc_client.dm
+++ b/code/modules/modular_computers/file_system/programs/ntnrc_client.dm
@@ -1,3 +1,6 @@
+#define USERNAME_SIZE 32
+#define CHANNELNAME_SIZE 12
+#define MESSAGE_SIZE 2048
/datum/computer_file/program/chatclient
filename = "ntnrc_client"
@@ -44,7 +47,7 @@
if("PRG_speak")
if(!channel || isnull(active_channel))
return
- var/message = reject_bad_text(params["message"])
+ var/message = reject_bad_text(params["message"], MESSAGE_SIZE, TRUE)
if(!message)
return
if(channel.password && (!(src in channel.active_clients) && !(src in channel.offline_clients)))
@@ -76,7 +79,7 @@
active_channel = null
return TRUE
if("PRG_newchannel")
- var/channel_title = reject_bad_text(params["new_channel_name"])
+ var/channel_title = reject_bad_text(params["new_channel_name"], CHANNELNAME_SIZE, TRUE)
if(!channel_title)
return
var/datum/ntnet_conversation/C = new /datum/ntnet_conversation()
@@ -99,7 +102,7 @@
netadmin_mode = TRUE
return TRUE
if("PRG_changename")
- var/newname = sanitize(params["new_name"])
+ var/newname = reject_bad_text(params["new_name"], USERNAME_SIZE, TRUE)
newname = replacetext(newname, " ", "_")
if(!newname || newname == username)
return
@@ -135,7 +138,7 @@
if("PRG_renamechannel")
if(!authed)
return
- var/newname = reject_bad_text(params["new_name"])
+ var/newname = reject_bad_text(params["new_name"], CHANNELNAME_SIZE, TRUE)
if(!newname || !channel)
return
channel.add_status_message("Channel renamed from [channel.title] to [newname] by operator.")
@@ -267,3 +270,7 @@
data["messages"] = list()
return data
+
+#undef USERNAME_SIZE
+#undef CHANNELNAME_SIZE
+#undef MESSAGE_SIZE
diff --git a/config/entries/general.txt b/config/entries/general.txt
index 248bd4695e..9b4452e41d 100644
--- a/config/entries/general.txt
+++ b/config/entries/general.txt
@@ -330,6 +330,7 @@ ROUNDSTART_RACES arachnid
ROUNDSTART_RACES mammal_synthetic
ROUNDSTART_RACES dullahan
ROUNDSTART_RACES spectre_bot
+ROUNDSTART_RACES vampire_roundstart
##-------------------------------------------------------------------------------------------
diff --git a/modular_splurt/code/datums/elements/crawl_under.dm b/modular_splurt/code/datums/elements/crawl_under.dm
index 10cbf4e4a9..8d6bb253b5 100644
--- a/modular_splurt/code/datums/elements/crawl_under.dm
+++ b/modular_splurt/code/datums/elements/crawl_under.dm
@@ -48,13 +48,18 @@
/datum/element/crawl_under/proc/do_crawl(obj/structure/source, mob/living/user)
if(QDELETED(source) || QDELETED(user)) //sanity
return
-
to_chat(user, span_notice("You start crawling under [source].."))
if(!do_after(user, 20, FALSE, source) || (user.mobility_flags & MOBILITY_STAND || user.incapacitated(TRUE, FALSE, TRUE)))
to_chat(user, span_warning("You fail to crawl under [source]!"))
return
+ user.pass_flags |= PASSCRAWL
ADD_TRAIT(user, IGNORE_FAKE_Z_AXIS, ELEMENT_CRAWL_UNDER)
+ step(user, get_dir(user, source))
+ if(!(source in user.loc))
+ REMOVE_TRAIT(user, IGNORE_FAKE_Z_AXIS, ELEMENT_CRAWL_UNDER)
+ user.pass_flags &= ~PASSCRAWL
+ return
ADD_TRAIT(user, TRAIT_FLOORED, ELEMENT_CRAWL_UNDER)
user.layer = source.layer - 0.01 //just a lil under it
user.pass_flags |= PASSCRAWL
diff --git a/modular_splurt/code/game/object/structures/bathroom.dm b/modular_splurt/code/game/object/structures/bathroom.dm
index f097999945..8ba710f406 100644
--- a/modular_splurt/code/game/object/structures/bathroom.dm
+++ b/modular_splurt/code/game/object/structures/bathroom.dm
@@ -39,13 +39,23 @@
/obj/structure/urinal/shit/screwdriver_act(mob/living/user, obj/item/I)
return FALSE
+/obj/structure/curtain
+ icon_state = "curtain_open"
+
/obj/structure/curtain/goliath
name = "goliath curtain"
desc = "Because tribals need privacy too."
icon = 'modular_splurt/icons/obj/structures/bathroom.dmi'
- icon_state = "goliath_curtain"
+ icon_state = "goliath_curtain_open"
color = null //Default color, didn't bother hardcoding other colors, mappers can and should easily change it.
alpha = 200 //Mappers can also just set this to 255 if they want curtains that can't be seen through <- No longer necessary unless you don't want to see through it no matter what.
layer = SIGN_LAYER
anchored = TRUE
max_integrity = 125.
+
+/obj/structure/curtain/update_icon_state()
+ . = ..()
+ if(!open)
+ icon_state = replacetext(initial(icon_state), "open", "closed")
+ else
+ icon_state = initial(icon_state)
diff --git a/modular_splurt/code/modules/cargo/packs/vending.dm b/modular_splurt/code/modules/cargo/packs/vending.dm
new file mode 100644
index 0000000000..8426d5441d
--- /dev/null
+++ b/modular_splurt/code/modules/cargo/packs/vending.dm
@@ -0,0 +1,2 @@
+/datum/supply_pack/vending/barkbox
+ contraband = FALSE //i'm not responsible for citcode
diff --git a/modular_splurt/code/modules/mob/dead/new_player/sprite_accesories/wings.dm b/modular_splurt/code/modules/mob/dead/new_player/sprite_accesories/wings.dm
index 59e490a158..672582d515 100644
--- a/modular_splurt/code/modules/mob/dead/new_player/sprite_accesories/wings.dm
+++ b/modular_splurt/code/modules/mob/dead/new_player/sprite_accesories/wings.dm
@@ -43,6 +43,25 @@
icon = 'modular_splurt/icons/mob/wings.dmi'
upgrade_to = SPECIES_WINGS_ANGEL
+//ripped from fulp
+/datum/sprite_accessory/deco_wings/aspen
+ name = "Aspen"
+ icon_state = "aspen"
+ icon = 'modular_splurt/icons/mob/wings.dmi'
+ upgrade_to = SPECIES_WINGS_MOTH
+
+/datum/sprite_accessory/deco_wings/dreamhead
+ name = "Dreamhead"
+ icon_state = "dreamhead"
+ icon = 'modular_splurt/icons/mob/wings.dmi'
+ upgrade_to = SPECIES_WINGS_MOTH
+
+/datum/sprite_accessory/deco_wings/delirious
+ name = "Delirious"
+ icon_state = "delirious"
+ icon = 'modular_splurt/icons/mob/wings.dmi'
+ upgrade_to = SPECIES_WINGS_MOTH
+
//insect wings
/datum/sprite_accessory/insect_wings/beetle
name = "Beetle (Hyper)"
@@ -64,3 +83,20 @@
icon = 'modular_splurt/icons/mob/wings.dmi'
upgrade_to = SPECIES_WINGS_INSECT
+/datum/sprite_accessory/insect_wings/aspen
+ name = "Aspen"
+ icon_state = "aspen"
+ icon = 'modular_splurt/icons/mob/wings.dmi'
+ upgrade_to = SPECIES_WINGS_MOTH
+
+/datum/sprite_accessory/insect_wings/dreamhead
+ name = "Dreamhead"
+ icon_state = "dreamhead"
+ icon = 'modular_splurt/icons/mob/wings.dmi'
+ upgrade_to = SPECIES_WINGS_MOTH
+
+/datum/sprite_accessory/insect_wings/delirious
+ name = "Delirious"
+ icon_state = "delirious"
+ icon = 'modular_splurt/icons/mob/wings.dmi'
+ upgrade_to = SPECIES_WINGS_MOTH
diff --git a/modular_splurt/code/modules/mob/living/carbon/human/examine.dm b/modular_splurt/code/modules/mob/living/carbon/human/examine.dm
new file mode 100644
index 0000000000..c074ba059a
--- /dev/null
+++ b/modular_splurt/code/modules/mob/living/carbon/human/examine.dm
@@ -0,0 +1,67 @@
+#define PAIRLESS_PANTIES list(\
+ /obj/item/clothing/underwear/briefs/jockstrap,\
+ /obj/item/clothing/underwear/briefs/panties/thong,\
+ /obj/item/clothing/underwear/briefs/panties/thong/babydoll,\
+ /obj/item/clothing/underwear/briefs/mankini\
+)
+
+
+/mob/living/carbon/human/examine(mob/user)
+ . = ..()
+ if(!isliving(user))
+ return
+
+ var/mob/living/living = user
+ if((user != src) && !(living.mobility_flags & MOBILITY_STAND) && (mobility_flags & MOBILITY_STAND) && (src.loc == living.loc) && (istype(w_uniform, /obj/item/clothing)))
+ var/string = "Peeking under [src]'s [w_uniform], you can see "
+ var/obj/item/clothing/underwear/worn_underwear = src.w_underwear
+ if(worn_underwear)
+ string += "a "
+ if(!(worn_underwear.type in PAIRLESS_PANTIES)) //a pair of thong
+ string += "pair of "
+ if(worn_underwear.color)
+ string += "[worn_underwear.name]."
+ else
+ string += "[worn_underwear.name]."
+
+ var/obj/item/organ/genital/penis/penis = getorganslot(ORGAN_SLOT_PENIS)
+ var/obj/item/organ/genital/vagina/vagina = getorganslot(ORGAN_SLOT_VAGINA)
+ if(penis?.aroused_state)
+ string += span_love(" There's a visible bulge on it's front.")
+ else if(vagina?.aroused_state)
+ string += span_love(" They're wet with arousal.")
+
+ else
+ string += "[p_theyre()] not wearing anything! - [p_their()] "
+ var/list/genitals = list()
+ for(var/obj/item/organ/genital/genital in internal_organs)
+ if(genital.genital_flags & (GENITAL_INTERNAL|GENITAL_HIDDEN))
+ continue
+
+ var/appended
+ if(genital.type == /obj/item/organ/genital/vagina)
+ if(genital.aroused_state)
+ appended += "wet "
+ if(lowertext(genital.shape) != "human")
+ appended += lowertext(genital.shape)
+ if(lowertext(genital.shape) != "cloaca") //their wet cloaca pussy
+ appended += " pussy"
+
+ else if(genital.type == /obj/item/organ/genital/testicles)
+ appended += "nuts"
+ else if(genital.type == /obj/item/organ/genital/penis)
+ if(genital.aroused_state)
+ appended += "fully erect, "
+ if(lowertext(genital.shape) != "human")
+ appended += lowertext(genital.shape)
+ appended += " penis"
+
+ if(appended) //I thought you'd know by now that nulls in lists aren't good
+ genitals += appended
+
+ string += english_list(genitals, "featureless groin")
+ string += " on full display."
+
+ . += span_purple(string)
+
+#undef PAIRLESS_PANTIES
diff --git a/modular_splurt/code/modules/mob/living/carbon/human/species_types/vampire.dm b/modular_splurt/code/modules/mob/living/carbon/human/species_types/vampire.dm
new file mode 100644
index 0000000000..026adfc062
--- /dev/null
+++ b/modular_splurt/code/modules/mob/living/carbon/human/species_types/vampire.dm
@@ -0,0 +1,5 @@
+/datum/species/vampire/roundstart/check_roundstart_eligible()
+ . = ..()
+ if(id in (CONFIG_GET(keyed_list/roundstart_races)))
+ return TRUE
+ return FALSE
diff --git a/modular_splurt/code/modules/shuttle/arrivals.dm b/modular_splurt/code/modules/shuttle/arrivals.dm
new file mode 100644
index 0000000000..c8c393238d
--- /dev/null
+++ b/modular_splurt/code/modules/shuttle/arrivals.dm
@@ -0,0 +1,2 @@
+/obj/docking_port/mobile/arrivals
+ movement_force = list("KNOCKDOWN" = 8, "THROW" = 2)
diff --git a/modular_splurt/code/modules/shuttle/shuttle.dm b/modular_splurt/code/modules/shuttle/shuttle.dm
new file mode 100644
index 0000000000..1cae0c2277
--- /dev/null
+++ b/modular_splurt/code/modules/shuttle/shuttle.dm
@@ -0,0 +1,2 @@
+/obj/docking_port/mobile
+ movement_force = list("KNOCKDOWN" = 8, "THROW" = 6)
diff --git a/modular_splurt/icons/mob/wings.dmi b/modular_splurt/icons/mob/wings.dmi
index 34a8044dd1..e81553e462 100644
Binary files a/modular_splurt/icons/mob/wings.dmi and b/modular_splurt/icons/mob/wings.dmi differ
diff --git a/modular_splurt/icons/obj/structures/bathroom.dmi b/modular_splurt/icons/obj/structures/bathroom.dmi
index 00979d942b..1517473e63 100644
Binary files a/modular_splurt/icons/obj/structures/bathroom.dmi and b/modular_splurt/icons/obj/structures/bathroom.dmi differ
diff --git a/tgstation.dme b/tgstation.dme
index 5070f93b3c..166f118407 100644
--- a/tgstation.dme
+++ b/tgstation.dme
@@ -4390,6 +4390,7 @@
#include "modular_splurt\code\modules\cargo\packs\goodies.dm"
#include "modular_splurt\code\modules\cargo\packs\misc.dm"
#include "modular_splurt\code\modules\cargo\packs\science.dm"
+#include "modular_splurt\code\modules\cargo\packs\vending.dm"
#include "modular_splurt\code\modules\cargo\sweatshop\metal.dm"
#include "modular_splurt\code\modules\cargo\sweatshop\sweatshop.dm"
#include "modular_splurt\code\modules\cargo\sweatshop\wooden.dm"
@@ -4495,6 +4496,7 @@
#include "modular_splurt\code\modules\mob\living\living_movement.dm"
#include "modular_splurt\code\modules\mob\living\living_signals.dm"
#include "modular_splurt\code\modules\mob\living\carbon\carbon.dm"
+#include "modular_splurt\code\modules\mob\living\carbon\human\examine.dm"
#include "modular_splurt\code\modules\mob\living\carbon\human\human.dm"
#include "modular_splurt\code\modules\mob\living\carbon\human\human_defines.dm"
#include "modular_splurt\code\modules\mob\living\carbon\human\species.dm"
@@ -4502,6 +4504,7 @@
#include "modular_splurt\code\modules\mob\living\carbon\human\simple_animal\hostile\deathclaw\funclaw.dm"
#include "modular_splurt\code\modules\mob\living\carbon\human\species_types\ashwalker.dm"
#include "modular_splurt\code\modules\mob\living\carbon\human\species_types\spectrebot.dm"
+#include "modular_splurt\code\modules\mob\living\carbon\human\species_types\vampire.dm"
#include "modular_splurt\code\modules\mob\living\silicon\robot\dogborg_equipment.dm"
#include "modular_splurt\code\modules\mob\living\silicon\robot\robot.dm"
#include "modular_splurt\code\modules\mob\living\silicon\robot\robot_modules.dm"
@@ -4560,6 +4563,8 @@
#include "modular_splurt\code\modules\resize\smallsprite_action.dm"
#include "modular_splurt\code\modules\ruins\objects_and_mobs\ash_walker_den.dm"
#include "modular_splurt\code\modules\ruins\spaceruin_code\hilbertshotel.dm"
+#include "modular_splurt\code\modules\shuttle\arrivals.dm"
+#include "modular_splurt\code\modules\shuttle\shuttle.dm"
#include "modular_splurt\code\modules\shuttle\slaver.dm"
#include "modular_splurt\code\modules\smithing\anvil.dm"
#include "modular_splurt\code\modules\smithing\finished_items.dm"
diff --git a/tgui/packages/tgui/interfaces/NtosNetChat.js b/tgui/packages/tgui/interfaces/NtosNetChat.js
index 56def6773f..9a573a44ad 100644
--- a/tgui/packages/tgui/interfaces/NtosNetChat.js
+++ b/tgui/packages/tgui/interfaces/NtosNetChat.js
@@ -1,7 +1,6 @@
import { useBackend } from '../backend';
-import { Box, Button, Dimmer, Icon, Input, Section, Stack, Table, Tooltip } from '../components';
+import { Box, Button, Dimmer, Icon, Input, Section, Stack } from '../components';
import { NtosWindow } from '../layouts';
-import { StackingConsole } from './StackingConsole';
// byond defines for the program state
const CLIENT_ONLINE = 2;
@@ -101,7 +100,7 @@ export const NtosNetChat = (props, context) => {
const this_client = clients.find(client => client.ref === selfref);
return (
@@ -152,7 +151,7 @@ export const NtosNetChat = (props, context) => {
-
+
@@ -205,7 +204,7 @@ export const NtosNetChat = (props, context) => {
{!!in_channel && (
<>
-
+
@@ -222,10 +221,10 @@ export const NtosNetChat = (props, context) => {
<>