Adds 5 Bond-tier gadgets to the Spy's reward pool (#92481)

## About The Pull Request

1. Penbang

A flashbang disguised as a pen. Clicking the pen arms the flashbang and
has no other visual or audio tell besides the pen clicking.
The fuse's length is based on the angle the pen cap is twisted. 
Works as a normal pen otherwise.

2. Camera Flash

A camera with a high power flash. 
Clicking on an adjacent target will flash them, ie, as a handheld flash.
Works as a normal camera otherwise - no tell.

3. Dagger Boot

A pair of jackboots with a blade embedded in them.
Makes your kicks sharp, meaning they will cause bleeding.
Looks like normal jackboots otherwise, though has a tell on
double-examine

4. Monster Cube Box

A box containing 5 monster cubes, which spawn into a random monster when
wet.
Monsters include Migos, Carps, Bears, Spiders, Wolves...

5. Spider Bite Scroll

A martial art focused around kicks and grabs. 
- Punches against standing, staggered targets will instead kick them,
applying the bonus accuracy and damage that you'd expect from a kick.
(Also combos with the dagger boots)
- All kicks have a chance to disarm the target's active weapon. Chance
increases per sequential kick.
- Grants you the innate ability to tackle. This form of tackling has a
very high skill modifier, meaning you are very likely to get a positive
outcome (or at least, not fail). You also get up fast from it.
- Your grabs are 20% harder to escape from and deal an additional 10
stam damage on fail.

## Why It's Good For The Game

1, 2, 3: Just some random flavorful items, giving them some more toys to
use to complete bounties.

4: Shenanigans, for people who just wanna do "funny thing" instead of
focusing on big loot.

5: I figured it would fill a fun niche: Spies are commonly depicted as
martial artists, and the only martial arts they can obtain is Krav Maga
(it's not unique to Spies) and Sleeping Carp (it's not unique to Spies).
This gives them their own thing that people may look forward to
acquiring and playing around with.
As for the design of it, I wanted to add something that synergizes with
one of the other other items, so in the field if you notice both of them
pop up you really want to go for both.
The rest of the design I just filled in as vaguely useful and flavorful
tools a spy might want for kidnapping or detaining people: Better grabs,
tackling, and disarms.
Then I just went with the flavor of it being something the Spider Clan
used to teach to their Spies / Ninjas, kinda like an analog to the real
life Ninjutsu. (Maybe we can give it to Space Ninjas as well later...
since it doesn't especially benefit Ninjas in any way.)

## Changelog

🆑 Melbert
add: Adds 5 rewards to the Spy item pool: Penbang, Camera Flash,
Dagger-Boot, Monster Cube Box, and the Spider Bite martial art
/🆑
This commit is contained in:
MrMelbert
2025-08-26 10:22:11 +10:00
committed by GitHub
parent 575cb93966
commit 59f8de91dc
15 changed files with 349 additions and 13 deletions
@@ -501,3 +501,98 @@ effective or pretty fucking useless.
/obj/projectile/bullet/toolbox_turret
damage = 10
speed = 1.6
/// Flashbang disguised as a pen
/obj/item/pen/penbang
degrees = 90
/obj/item/pen/penbang/on_transform(obj/item/source, mob/user, active)
. = ..()
var/det_time = 1 SECONDS + (4 SECONDS * (degrees / 90))
if(user)
to_chat(user, span_warning("You prime the penbang! [capitalize(DisplayTimeText(det_time))]!"))
log_bomber(user, "has primed a", src, "(penbang) for detonation")
addtimer(CALLBACK(src, PROC_REF(detonate), user), det_time)
/obj/item/pen/penbang/proc/detonate(mob/user)
var/obj/item/grenade/flashbang/bang = new(get_turf(src))
bang.detonate()
qdel(src)
/// A camera disguised as a flash
/obj/item/camera/flash
/// The flash we use to flash people with
var/obj/item/assembly/flash/handheld/internal_flash
/obj/item/camera/flash/Initialize(mapload)
. = ..()
internal_flash = new(src)
/obj/item/camera/flash/Destroy()
QDEL_NULL(internal_flash)
return ..()
/obj/item/camera/flash/Exited(atom/movable/gone, direction)
. = ..()
// i guess this is a normal camera now. shouldn't happen, though
if(gone == internal_flash)
internal_flash = null
/obj/item/camera/flash/interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers)
if(isliving(interacting_with))
return ITEM_INTERACT_SKIP_TO_ATTACK
return ..()
/obj/item/camera/flash/attack(mob/living/M, mob/user)
return internal_flash?.attack(M, user)
/// Jackboots with a dagger embedded into them - changes your kicks to be stab attacks, potetnially causing bleeding
/obj/item/clothing/shoes/jackboots/dagger
/// List of bodyparts modified by the dagger
var/list/modified_bodyparts = list()
/obj/item/clothing/shoes/jackboots/dagger/equipped(mob/living/user, slot)
. = ..()
if(!(slot & ITEM_SLOT_FEET) || !istype(user))
modified_bodyparts += user.get_bodypart(BODY_ZONE_L_LEG)
modified_bodyparts += user.get_bodypart(BODY_ZONE_R_LEG)
for(var/obj/item/bodypart/bodypart in modified_bodyparts)
bodypart.unarmed_sharpness |= SHARP_EDGED
bodypart.unarmed_attack_effect = ATTACK_EFFECT_SLASH
RegisterSignals(bodypart, list(COMSIG_BODYPART_REMOVED, COMSIG_QDELETING), PROC_REF(clear_modification))
RegisterSignal(user, COMSIG_CARBON_POST_ATTACH_LIMB, PROC_REF(modify_legs))
/obj/item/clothing/shoes/jackboots/dagger/dropped(mob/user)
. = ..()
UnregisterSignal(user, COMSIG_CARBON_POST_ATTACH_LIMB)
for(var/obj/item/bodypart/bodypart in modified_bodyparts)
clear_modification(bodypart)
/obj/item/clothing/shoes/jackboots/dagger/handle_deconstruct(disassembled)
. = ..()
new /obj/item/switchblade/extended(drop_location())
/obj/item/clothing/shoes/jackboots/dagger/proc/clear_modification(obj/item/bodypart/bodypart, ...)
SIGNAL_HANDLER
UnregisterSignal(bodypart, list(COMSIG_BODYPART_REMOVED, COMSIG_QDELETING))
bodypart.unarmed_sharpness = initial(bodypart.unarmed_sharpness)
bodypart.unarmed_attack_effect = initial(bodypart.unarmed_attack_effect)
modified_bodyparts -= bodypart
/obj/item/clothing/shoes/jackboots/dagger/proc/modify_legs(datum/source, obj/item/bodypart/bodypart, ...)
SIGNAL_HANDLER
if(bodypart in modified_bodyparts)
return
if(!istype(bodypart, /obj/item/bodypart/leg))
return
modified_bodyparts += bodypart
bodypart.unarmed_sharpness |= SHARP_EDGED
RegisterSignal(bodypart, list(COMSIG_BODYPART_REMOVED, COMSIG_QDELETING), PROC_REF(clear_modification))
/obj/item/clothing/shoes/jackboots/dagger/examine_more(mob/user)
. = ..()
. += span_notice("Upon closer inspection, you notice a dagger embedded into the sole.")
@@ -124,3 +124,37 @@
)
tastes = list("the loss of 5 TC" = 1, "eaten friend" = 1)
spawned_mob = /mob/living/basic/pony/dangerous
/obj/item/food/monkeycube/random
name = "monster cube"
desc = "A cube that, when water is added, creates a random creature. Who knows what's inside?"
food_reagents = list(
/datum/reagent/toxin = 15,
/datum/reagent/medicine/strange_reagent = 1,
)
/obj/item/food/monkeycube/random/Initialize(mapload)
. = ..()
spawned_mob = pick_weight(list(
/mob/living/basic/bear = 4,
/mob/living/basic/bear/snow = 1,
/mob/living/basic/blankbody = 2,
/mob/living/basic/blob_minion/blobbernaut = 2,
/mob/living/basic/blob_minion/spore = 2,
/mob/living/basic/carp = 4,
/mob/living/basic/carp/mega = 1,
/mob/living/basic/creature = 2,
/mob/living/basic/eyeball = 1,
/mob/living/basic/gorilla = 5,
/mob/living/basic/migo = 2,
/mob/living/basic/mining/basilisk = 5,
/mob/living/basic/mining/lobstrosity = 1,
/mob/living/basic/mining/lobstrosity/lava = 4,
/mob/living/basic/mining/wolf = 4,
/mob/living/basic/pet/cat/feral = 1,
/mob/living/basic/spider/giant = 5,
/mob/living/basic/spider/giant/hunter = 1,
/mob/living/basic/spider/giant/tank = 1,
/mob/living/basic/spider/giant/tarantula = 1,
/mob/living/basic/spider/giant/viper = 1,
))
@@ -0,0 +1,36 @@
/obj/item/book/granter/martial/spider_bite
martial = /datum/martial_art/spiders_bite
name = "mysterious scroll"
martial_name = "spider's bite"
desc = "A scroll filled with strange markings. It seems to be drawings of some sort of martial art."
greet = span_sciradio("You have learned the Spider Clan's historic technique, The Spider's Bite. \
You are now able to kick standing targets who are staggered, potentially disarming them of their weapons. \
You can also tackle targets with great effectiveness, and have more solid grabs.")
icon = 'icons/obj/scrolls.dmi'
icon_state = "sleepingcarp"
worn_icon_state = "scroll"
remarks = list(
"Float like spider silk, sting like a spider's bite.",
"I must be one with the spider.",
"I've never seen this language in my life. At least it has pictures.",
"The Flow of Gravity technique... can I harness the power of gravity?",
"The Jump and Climb technique... is my body that flexible?",
"The Many Legged Spider technique... are my kicks really that powerful?",
"The Wrap in Web technique... I just need to wrap my targets in my arms?",
)
/obj/item/book/granter/martial/spider_bite/on_reading_finished(mob/living/carbon/user)
. = ..()
update_appearance()
/obj/item/book/granter/martial/spider_bite/update_appearance(updates)
. = ..()
if(uses <= 0)
name = "empty scroll"
desc = "It's completely blank."
icon_state = "blankscroll"
else
name = initial(name)
desc = initial(desc)
icon_state = initial(icon_state)
@@ -50,6 +50,11 @@
desc = "Waffle Corp. brand monkey cubes. Just add water and a dash of subterfuge!"
cube_type = /obj/item/food/monkeycube/syndicate
/obj/item/storage/box/monkeycubes/random
name = "monster cube box"
desc = "A box containing a bunch of random cubes. Add water and see what you get!"
cube_type = /obj/item/food/monkeycube/random
/obj/item/storage/box/gorillacubes
name = "gorilla cube box"
desc = "Waffle Corp. brand gorilla cubes. Do not taunt."