diff --git a/code/__DEFINES/rockpaperscissors.dm b/code/__DEFINES/rockpaperscissors.dm
new file mode 100644
index 0000000000..77ba81938d
--- /dev/null
+++ b/code/__DEFINES/rockpaperscissors.dm
@@ -0,0 +1,7 @@
+#define ROCKPAPERSCISSORS_RANGE 3
+#define ROCKPAPERSCISSORS_TIME_LIMIT 20 SECONDS
+
+#define ROCKPAPERSCISSORS_LOSE "lose"
+#define ROCKPAPERSCISSORS_WIN "win"
+#define ROCKPAPERSCISSORS_TIE "tie"
+#define ROCKPAPERSCISSORS_NOT_DECIDED "not_decided"
\ No newline at end of file
diff --git a/code/_globalvars/lists/objects.dm b/code/_globalvars/lists/objects.dm
index 4de7c88bf7..fee70ee3d5 100644
--- a/code/_globalvars/lists/objects.dm
+++ b/code/_globalvars/lists/objects.dm
@@ -41,3 +41,6 @@ GLOBAL_LIST_EMPTY(ai_status_displays)
GLOBAL_LIST_EMPTY(mob_spawners) // All mob_spawn objects
GLOBAL_LIST_EMPTY(alert_consoles) // Station alert consoles, /obj/machinery/computer/station_alert
+
+//list of everyone playing rock paper scissors
+GLOBAL_LIST_EMPTY(rockpaperscissors_players)
diff --git a/code/modules/mob/living/carbon/human/emote.dm b/code/modules/mob/living/carbon/human/emote.dm
index 1bfb72a415..d2cc9e58b0 100644
--- a/code/modules/mob/living/carbon/human/emote.dm
+++ b/code/modules/mob/living/carbon/human/emote.dm
@@ -192,3 +192,71 @@
key_third_person = "chimes"
message = "chimes."
sound = 'sound/machines/chime.ogg'
+
+//rock paper scissors emote handling
+/mob/living/carbon/human/proc/beginRockPaperScissors(var/chosen_move)
+ GLOB.rockpaperscissors_players[src] = list(chosen_move, ROCKPAPERSCISSORS_NOT_DECIDED)
+ do_after_advanced(src, ROCKPAPERSCISSORS_TIME_LIMIT, src, DO_AFTER_REQUIRES_USER_ON_TURF|DO_AFTER_NO_COEFFICIENT|DO_AFTER_NO_PROGRESSBAR, CALLBACK(src, .proc/rockpaperscissors_tick))
+ var/new_entry = GLOB.rockpaperscissors_players[src]
+ if(new_entry[2] == ROCKPAPERSCISSORS_NOT_DECIDED)
+ to_chat(src, "You put your hand back down.")
+ GLOB.rockpaperscissors_players -= src
+
+/mob/living/carbon/human/proc/rockpaperscissors_tick() //called every cycle of the progress bar for rock paper scissors while waiting for an opponent
+ var/mob/living/carbon/human/opponent
+ for(var/mob/living/carbon/human/potential_opponent in (GLOB.rockpaperscissors_players - src)) //dont play against yourself
+ if(get_dist(src, potential_opponent) <= ROCKPAPERSCISSORS_RANGE)
+ opponent = potential_opponent
+ break
+ if(opponent)
+ //we found an opponent before they found us
+ var/move_to_number = list("rock" = 0, "paper" = 1, "scissors" = 2)
+ var/our_move = move_to_number[GLOB.rockpaperscissors_players[src][1]]
+ var/their_move = move_to_number[GLOB.rockpaperscissors_players[opponent][1]]
+ var/result_us = ROCKPAPERSCISSORS_WIN
+ var/result_them = ROCKPAPERSCISSORS_LOSE
+ if(our_move == their_move)
+ result_us = ROCKPAPERSCISSORS_TIE
+ result_them = ROCKPAPERSCISSORS_TIE
+ else
+ if(((our_move + 1) % 3) == their_move)
+ result_us = ROCKPAPERSCISSORS_LOSE
+ result_them = ROCKPAPERSCISSORS_WIN
+ //we decided our results so set them in the list
+ GLOB.rockpaperscissors_players[src][2] = result_us
+ GLOB.rockpaperscissors_players[opponent][2] = result_them
+
+ //show what happened
+ src.visible_message("[src] makes [GLOB.rockpaperscissors_players[src][1]] with their hand!")
+ opponent.visible_message("[opponent] makes [GLOB.rockpaperscissors_players[opponent][1]] with their hands!")
+ switch(result_us)
+ if(ROCKPAPERSCISSORS_TIE)
+ src.visible_message("It was a tie!")
+ if(ROCKPAPERSCISSORS_WIN)
+ src.visible_message("[src] wins!")
+ if(ROCKPAPERSCISSORS_LOSE)
+ src.visible_message("[opponent] wins!")
+
+ //make the progress bar end so that each player can handle the result
+ return DO_AFTER_STOP
+
+ //no opponent was found, so keep searching
+ return DO_AFTER_PROCEED
+
+//the actual emotes
+/datum/emote/living/carbon/human/rockpaperscissors
+ message = "is attempting to play rock paper scissors!"
+
+/datum/emote/living/carbon/human/rockpaperscissors/rock
+ key = "rock"
+
+/datum/emote/living/carbon/human/rockpaperscissors/paper
+ key = "paper"
+
+/datum/emote/living/carbon/human/rockpaperscissors/scissors
+ key = "scissors"
+
+/datum/emote/living/carbon/human/rockpaperscissors/run_emote(mob/living/carbon/human/user, params)
+ if(!(user in GLOB.rockpaperscissors_players)) //no using the emote again while already playing!
+ . = ..()
+ user.beginRockPaperScissors(key)
diff --git a/tgstation.dme b/tgstation.dme
index 79c4274722..de6ee1a6bf 100644
--- a/tgstation.dme
+++ b/tgstation.dme
@@ -96,6 +96,7 @@
#include "code\__DEFINES\reagents_specific_heat.dm"
#include "code\__DEFINES\research.dm"
#include "code\__DEFINES\robots.dm"
+#include "code\__DEFINES\rockpaperscissors.dm"
#include "code\__DEFINES\role_preferences.dm"
#include "code\__DEFINES\rust_g.dm"
#include "code\__DEFINES\say.dm"