diff --git a/code/modules/mob/say_vr.dm b/code/modules/mob/say_vr.dm
index d8ed1c311e..29cabcd4cc 100644
--- a/code/modules/mob/say_vr.dm
+++ b/code/modules/mob/say_vr.dm
@@ -306,3 +306,46 @@
else //There wasn't anyone to send the message to, pred or prey, so let's just emote it instead and correct our psay just in case.
M.forced_psay = FALSE
M.me_verb(message)
+
+/mob/living/verb/player_narrate(message as text|null)
+ set category = "IC"
+ set name = "Narrate (Player)"
+ set desc = "Narrate an action or event! An alternative to emoting, for when your emote shouldn't start with your name!"
+
+ if(src.client)
+ if(client.prefs.muted & MUTE_IC)
+ to_chat(src, "You cannot speak in IC (muted).")
+ return
+ if(!message)
+ message = tgui_input_text(usr, "Type a message to narrate.","Narrate")
+ message = sanitize_or_reflect(message,src)
+ if(!message)
+ return
+ if(stat == DEAD)
+ return say_dead(message)
+ message = "([name]) [message]"
+
+ //Below here stolen from emotes
+ var/turf/T = get_turf(src)
+
+ if(!T) return
+
+ var/ourfreq = null
+ if(voice_freq > 0 )
+ ourfreq = voice_freq
+
+ if(client)
+ playsound(T, pick(emote_sound), 25, TRUE, falloff = 1 , is_global = TRUE, frequency = ourfreq, ignore_walls = FALSE, preference = /datum/client_preference/emote_sounds)
+
+ var/list/in_range = get_mobs_and_objs_in_view_fast(T,world.view,2,remote_ghosts = client ? TRUE : FALSE)
+ var/list/m_viewers = in_range["mobs"]
+
+ for(var/mob/M as anything in m_viewers)
+ spawn(0) // It's possible that it could be deleted in the meantime, or that it runtimes.
+ if(M)
+ if(isobserver(M))
+ message = "[message] ([ghost_follow_link(src, M)])"
+ if(M.stat == UNCONSCIOUS || M.sleeping > 0)
+ continue
+ to_chat(M, message)
+ log_emote(message, src)
diff --git a/code/modules/vchat/css/ss13styles.css b/code/modules/vchat/css/ss13styles.css
index 9906041588..af6fe46bd3 100644
--- a/code/modules/vchat/css/ss13styles.css
+++ b/code/modules/vchat/css/ss13styles.css
@@ -196,6 +196,8 @@ h1.alert, h2.alert {color: #000000;}
.inverted .blue {color: #6666FF;}
.inverted .green {color: #44FF44;}
+.pnarrate {color: #009AB2;}
+
/*BIG IMG.icon {width: 32px; height: 32px;}*/
img.icon {vertical-align: middle; max-height: 1em;}
img.icon.bigicon {max-height: 32px;}
diff --git a/code/stylesheet.dm b/code/stylesheet.dm
index 4491e5f8b5..0031006404 100644
--- a/code/stylesheet.dm
+++ b/code/stylesheet.dm
@@ -140,5 +140,7 @@ BIG IMG.icon {width: 32px; height: 32px;}
.blue {color: #0000FF;}
.green {color: #00DD00;}
+.pnarrate {color: #009AB2;}
+
"}