diff --git a/code/__DEFINES/achievements.dm b/code/__DEFINES/achievements.dm
index c39531971cb..9da8ea2440a 100644
--- a/code/__DEFINES/achievements.dm
+++ b/code/__DEFINES/achievements.dm
@@ -106,3 +106,6 @@
// DB ID for amount of consumed maintenance pills
#define MAINTENANCE_PILL_SCORE "Maintenance Pill Score"
+
+// DB ID for intento score
+#define INTENTO_SCORE "Intento Score"
diff --git a/code/_onclick/click.dm b/code/_onclick/click.dm
index 7512aa2fc59..23cfaba6ea4 100644
--- a/code/_onclick/click.dm
+++ b/code/_onclick/click.dm
@@ -126,7 +126,7 @@
var/obj/item/W = get_active_held_item()
if(W == A)
- W.attack_self(src)
+ W.attack_self(src, modifiers)
update_inv_hands()
return
diff --git a/code/_onclick/item_attack.dm b/code/_onclick/item_attack.dm
index 93c90fd49d1..4c77a25e21d 100644
--- a/code/_onclick/item_attack.dm
+++ b/code/_onclick/item_attack.dm
@@ -63,7 +63,7 @@
return afterattack(target, user, TRUE, params)
/// Called when the item is in the active hand, and clicked; alternately, there is an 'activate held object' verb or you can hit pagedown.
-/obj/item/proc/attack_self(mob/user)
+/obj/item/proc/attack_self(mob/user, modifiers)
if(SEND_SIGNAL(src, COMSIG_ITEM_ATTACK_SELF, user) & COMPONENT_CANCEL_ATTACK_CHAIN)
return TRUE
interact(user)
diff --git a/code/datums/achievements/misc_scores.dm b/code/datums/achievements/misc_scores.dm
index 7ffc50c0152..067cd68d7df 100644
--- a/code/datums/achievements/misc_scores.dm
+++ b/code/datums/achievements/misc_scores.dm
@@ -9,3 +9,9 @@
name = "Maintenance Pills Consumed"
desc = "Wait why?"
database_id = MAINTENANCE_PILL_SCORE
+
+///How high of a score on the Intento did we get?
+/datum/award/score/intento_score
+ name = "Intento Score"
+ desc = "A blast from the future?"
+ database_id = INTENTO_SCORE
diff --git a/code/game/objects/items/toys.dm b/code/game/objects/items/toys.dm
index ac922889034..367d0ca2742 100644
--- a/code/game/objects/items/toys.dm
+++ b/code/game/objects/items/toys.dm
@@ -178,6 +178,8 @@
inhand_icon_state = "arrestballoon"
random_color = FALSE
+#undef BALLOON_COLORS
+
/*
* Fake singularity
*/
@@ -1571,3 +1573,240 @@
animate(pixel_y = user.pixel_y - (2 * direction), time = 1, easing = SINE_EASING)
animate(pixel_y = user.pixel_y + (1 * direction), time = 1, easing = SINE_EASING)
user.changeNext_move(CLICK_CD_MELEE)
+
+#define HELP "help"
+#define DISARM "disarm"
+#define GRAB "grab"
+#define HARM "harm"
+#define ICON_SPLIT world.icon_size/2
+
+// These states do not have any associated processing.
+#define STATE_AWAITING_PLAYER_INPUT "awaiting_player_input"
+#define STATE_OFF "off"
+
+// When the Intento is in one of these four states, it has an accompanying
+// set of code that runs in processing()
+#define STATE_STARTING "starting"
+#define STATE_DEMO "demo"
+#define STATE_END_OF_GAME "end_of_game"
+#define STATE_RETALIATION "retaliation"
+
+#define TIME_TO_BEGIN 1.6 SECONDS
+#define TIME_PER_DEMO_STEP 0.6 SECONDS
+#define TIME_TO_RESET_ICON 0.5 SECONDS
+
+
+/obj/item/toy/intento
+ name = "\improper Intento"
+ desc = "Fundamentally useless for all intentsive purposes."
+ icon = 'icons/obj/intents.dmi'
+ icon_state = "blank"
+ /// Current sequence of intents
+ var/list/current_sequence = list()
+ /// Sequence player inputs
+ var/list/player_sequence = list()
+ /// Score of the player
+ var/score = 0
+ /// Associated list of intents to their sounds
+ var/static/list/sound_by_intent = list(
+ HELP = 'sound/items/intents/Help.ogg',
+ DISARM = 'sound/items/intents/Disarm.ogg',
+ GRAB = 'sound/items/intents/Grab.ogg',
+ HARM = 'sound/items/intents/Harm.ogg',
+ )
+
+ /// What state the toy is in.
+ var/state = STATE_OFF
+ /// Index used for iteration of steps for both demo and retaliation states
+ var/index
+ /// Time to delay until we start processing whatever state we're in
+ COOLDOWN_DECLARE(next_process)
+ /// Time until we reset the icon of the Intento
+ COOLDOWN_DECLARE(next_icon_reset)
+
+/obj/item/toy/intento/attack_self(mob/user, modifiers) //added params to attack_self, the alternative is registering a signal on clickon but i was advised not to
+ ..()
+ if(state == STATE_OFF)
+ boot()
+ return
+
+ if(!modifiers)
+ return
+
+ if(state != STATE_AWAITING_PLAYER_INPUT)
+ return
+
+ var/input
+ var/icon_x = text2num(modifiers["icon-x"])
+ var/icon_y = text2num(modifiers["icon-y"])
+ if(icon_x > ICON_SPLIT && icon_y > ICON_SPLIT)
+ input = DISARM
+ if(icon_x < ICON_SPLIT && icon_y > ICON_SPLIT)
+ input = HELP
+ if(icon_x > ICON_SPLIT && icon_y < ICON_SPLIT)
+ input = GRAB
+ if(icon_x < ICON_SPLIT && icon_y < ICON_SPLIT)
+ input = HARM
+
+ player_input(user, input)
+
+/obj/item/toy/intento/proc/boot()
+ say("Game starting!")
+ playsound(src, 'sound/machines/synth_yes.ogg', 50, FALSE)
+
+ state = STATE_STARTING
+ COOLDOWN_START(src, next_process, TIME_TO_BEGIN)
+ START_PROCESSING(SSfastprocess, src)
+
+/obj/item/toy/intento/proc/player_input(mob/player, intent)
+ // All branches of this proc lead to us wanting to process
+ START_PROCESSING(SSfastprocess, src)
+
+ render(intent)
+
+ player_sequence += intent
+ for(var/i in 1 to player_sequence.len)
+ if(player_sequence[i] != current_sequence[i])
+ state = STATE_END_OF_GAME
+ COOLDOWN_START(src, next_process, TIME_TO_RESET_ICON)
+ return
+
+ if(player_sequence.len == current_sequence.len)
+ score++
+
+ state = STATE_STARTING
+ COOLDOWN_START(src, next_process, TIME_TO_BEGIN)
+
+
+/obj/item/toy/intento/process()
+ if(next_icon_reset && next_icon_reset <= world.time)
+ icon_state = initial(icon_state)
+ COOLDOWN_RESET(src, next_icon_reset)
+
+ if(next_process && next_process > world.time)
+ return
+
+ switch(state)
+ if(STATE_STARTING)
+ process_start()
+
+ if(STATE_DEMO)
+ process_demo()
+
+ if(STATE_END_OF_GAME)
+ process_end(isliving(loc) ? loc : null)
+
+ if(STATE_RETALIATION)
+ process_retaliation()
+
+ if(!next_process && !next_icon_reset)
+ return PROCESS_KILL
+
+/obj/item/toy/intento/proc/process_start()
+ player_sequence.Cut()
+
+ current_sequence += pick(list(HELP, DISARM, GRAB, HARM))
+
+ state = STATE_DEMO
+ next_process = world.time
+ index = 1
+
+/obj/item/toy/intento/proc/process_demo()
+ if(index > length(current_sequence))
+ state = STATE_AWAITING_PLAYER_INPUT
+ COOLDOWN_RESET(src, next_process)
+ return
+
+ var/intent = current_sequence[index]
+ render(intent)
+
+ index += 1
+ COOLDOWN_START(src, next_process, TIME_PER_DEMO_STEP)
+
+/obj/item/toy/intento/proc/process_end(mob/user)
+ if(user)
+ var/award_score = score
+ var/award_status = user.client.get_award_status(/datum/award/score/intento_score)
+ if(award_score - award_status > 0)
+ award_score -= award_status
+ user.client.give_award(/datum/award/score/intento_score, user, award_score)
+
+ say("GAME OVER. Your score was [score]!")
+ playsound(src, 'sound/machines/synth_no.ogg', 50, FALSE)
+
+ if(user && loc == user && obj_flags & EMAGGED)
+ ADD_TRAIT(src, TRAIT_NODROP, type)
+ to_chat(user, "Bad mistake.")
+
+ state = STATE_RETALIATION
+ next_process = world.time
+ index = 1
+ else
+ cleanup()
+
+/obj/item/toy/intento/proc/process_retaliation()
+ var/mob/living/victim = loc
+ if(!isliving(victim) || index > length(current_sequence))
+ cleanup()
+ return
+
+ var/intent = current_sequence[index]
+ render(intent)
+ switch(intent)
+ if(HELP)
+ to_chat(victim, "[src] hugs you to make you feel better!")
+ SEND_SIGNAL(victim, COMSIG_ADD_MOOD_EVENT, "hug", /datum/mood_event/hug)
+ if(DISARM)
+ to_chat(victim, "You're knocked down from a shove by [src]!")
+ victim.Knockdown(2 SECONDS)
+ if(GRAB)
+ to_chat(victim, "[src] grabs you aggressively!")
+ victim.Stun(2 SECONDS)
+ if(HARM)
+ to_chat(victim, "You're punched by [src]!")
+ victim.apply_damage(rand(20, 30), BRUTE)
+
+ index += 1
+ COOLDOWN_START(src, next_process, TIME_PER_DEMO_STEP)
+
+/obj/item/toy/intento/proc/cleanup()
+ score = 0
+ index = 1
+ player_sequence.Cut()
+ current_sequence.Cut()
+
+ state = STATE_OFF
+ COOLDOWN_RESET(src, next_process)
+ REMOVE_TRAIT(src, TRAIT_NODROP, type)
+
+/obj/item/toy/intento/proc/render(input)
+ icon_state = input
+ playsound(src, sound_by_intent[input], 50, FALSE)
+
+ START_PROCESSING(SSfastprocess, src)
+ COOLDOWN_START(src, next_icon_reset, TIME_TO_RESET_ICON)
+
+/obj/item/toy/intento/emag_act(mob/user)
+ if(obj_flags & EMAGGED)
+ return
+ obj_flags |= EMAGGED
+ to_chat(user, "You short-circuit [src], activating the negative feedback loop.")
+
+/obj/item/toy/intento/Destroy()
+ STOP_PROCESSING(SSfastprocess, src)
+ return ..()
+
+#undef HELP
+#undef DISARM
+#undef GRAB
+#undef HARM
+#undef ICON_SPLIT
+#undef STATE_AWAITING_PLAYER_INPUT
+#undef STATE_OFF
+#undef STATE_STARTING
+#undef STATE_DEMO
+#undef STATE_END_OF_GAME
+#undef STATE_RETALIATION
+#undef TIME_TO_BEGIN
+#undef TIME_PER_DEMO_STEP
+#undef TIME_TO_RESET_ICON
diff --git a/code/modules/vending/games.dm b/code/modules/vending/games.dm
index 1d8873a15dc..4321952e15a 100644
--- a/code/modules/vending/games.dm
+++ b/code/modules/vending/games.dm
@@ -27,7 +27,8 @@
premium = list(/obj/item/melee/skateboard/pro = 3,
/obj/item/clothing/shoes/wheelys/rollerskates= 3,
/obj/item/melee/skateboard/hoverboard = 1,
- /obj/item/storage/box/tail_pin = 1)
+ /obj/item/storage/box/tail_pin = 1,
+ /obj/item/toy/intento = 3)
refill_canister = /obj/item/vending_refill/games
default_price = PAYCHECK_ASSISTANT
extra_price = PAYCHECK_HARD * 1.25
diff --git a/icons/obj/intents.dmi b/icons/obj/intents.dmi
new file mode 100644
index 00000000000..f08c169e9b2
Binary files /dev/null and b/icons/obj/intents.dmi differ
diff --git a/sound/items/intents/Disarm.ogg b/sound/items/intents/Disarm.ogg
new file mode 100644
index 00000000000..8c7a664c41a
Binary files /dev/null and b/sound/items/intents/Disarm.ogg differ
diff --git a/sound/items/intents/Grab.ogg b/sound/items/intents/Grab.ogg
new file mode 100644
index 00000000000..e63d5ceae20
Binary files /dev/null and b/sound/items/intents/Grab.ogg differ
diff --git a/sound/items/intents/Harm.ogg b/sound/items/intents/Harm.ogg
new file mode 100644
index 00000000000..f424def2e55
Binary files /dev/null and b/sound/items/intents/Harm.ogg differ
diff --git a/sound/items/intents/Help.ogg b/sound/items/intents/Help.ogg
new file mode 100644
index 00000000000..c7606a2ddfe
Binary files /dev/null and b/sound/items/intents/Help.ogg differ