From 72f76caea025befde3e7043bd39e8d8bb1d075b2 Mon Sep 17 00:00:00 2001 From: MrMelbert <51863163+MrMelbert@users.noreply.github.com> Date: Fri, 5 Dec 2025 20:42:32 -0600 Subject: [PATCH] Spy loot tweaks (#94189) ## About The Pull Request 1. Ammo will no longer show as a loot option until a weapon that uses said ammo has been claimed. Some ammo, particularly shotgun ammo has unique status bypassing this, since you could reasonably acquire a shotgun from the armory, a bartender, or cargo. There is also a 10% chance that some ammo will show up anyways, to keep people on their toes. 2. If you claim another weapon of an already claimed ammo type, the ammo in the pool will be refreshed, meaning obtainable once again. 3. Unclaimed items have a 40% chance of being re-added to the loot pool. This is on top of the 80% chance for an item to not be removed from the pool when selecting loot. 4. When hard bounties empty out their loot pool, they will instead draw from the medium loot pool. Likewise medium bounties will draw from the easy pool when they run out. 5. Modified the antag info panel text slightly. 6. Made more appropriate use of `SStraitor.uplink_items`, and checks for abstract items more thoroughly. 7. Some weapons no longer come in gun cases for Spies ## Why It's Good For The Game 1. Initially the thought was Spies would just have dud bounties on occasion. They could take the time to lie low or work on their plans rather than prowl for loot. Alternatively, an aggressive spy would go after them *just in case* they got the correct gun, or a passive spy would go after them for the ability to later bribe someone carrying the correct gun. However, in practice it seems people largely just don't like having dud bounties, as it hurts the pacing. Someone who is on a roll doesn't want to sit there and do nothing. Ghommie tried to implement this earlier but I disagreed with the implementation, so here we are. 2. It would be pretty unappealing to go after a gun after realizing all the gun's ammo has been looted already. 3. I noticed in testing pools would drain themselves pretty fast. This serves as a bit of a stop-gap, and prevents items that rolled on particularly difficult targets from being lost forever. Now you can roll the dice and hope that it shows up again. 4. Might as well reward people with non-junk items if they manage to drain a tier's loot pool, especially since the top tier pool is pretty small. 5. People were oft confused about the wording of the text, thinking they'd get banned. 6. No reason to use the indexed list. 7. Having a gun case thrust into your hands is not very inconspicuous ## Changelog :cl: Melbert balance: Ammo will no longer show up in the Spy loot pool until a weapon that uses said ammo has been claimed. Some ammo for weapons easily obtainable on station (shotgun shot) are not limited by this restriction. Also, there's a rare chance ammo will show up anyways just to keep people on their toes. balance: Claiming a weapon will refresh ammo in the loot pool that has already been claimed or cycled out. balance: Bounty rewards that no Spy claimed have a chance to re-enter the loot pool after a bounty refresh, rather than being lost for the remainder of the round. balance: When higher tier Spy bounties empty their loot pools, they will attempt to draw from lower tier pools before defaulting to telecrystals. balance: Spies no longer are rewarded with gun cases for bounties; rather just the gun itself spellcheck: Modified the Spy antag info text /:cl: --- code/modules/antagonists/spy/spy_bounty.dm | 37 +++++++++- .../antagonists/spy/spy_bounty_handler.dm | 45 ++++++++++--- code/modules/antagonists/spy/spy_uplink.dm | 8 ++- code/modules/cargo/packs/general.dm | 3 +- .../research/techweb/nodes/syndicate_nodes.dm | 5 +- code/modules/uplink/uplink_items.dm | 3 + code/modules/uplink/uplink_items/bundle.dm | 6 +- code/modules/uplink/uplink_items/dangerous.dm | 19 +++++- code/modules/uplink/uplink_items/nukeops.dm | 67 +++++++++++++++++++ .../modules/uplink/uplink_items/spy_unique.dm | 50 ++++++++++++++ .../packages/tgui/interfaces/AntagInfoSpy.tsx | 4 +- 11 files changed, 220 insertions(+), 27 deletions(-) diff --git a/code/modules/antagonists/spy/spy_bounty.dm b/code/modules/antagonists/spy/spy_bounty.dm index c285362bcd2..975e42dd58a 100644 --- a/code/modules/antagonists/spy/spy_bounty.dm +++ b/code/modules/antagonists/spy/spy_bounty.dm @@ -31,6 +31,8 @@ VAR_FINAL/initalized = FALSE /// Whether the bounty has been completed. VAR_FINAL/claimed = FALSE + /// What pool we picked the loot from. + VAR_FINAL/loot_difficulty /// What uplink item the bounty will reward on completion. VAR_FINAL/datum/uplink_item/reward_item @@ -70,16 +72,47 @@ /// Selects what uplink item the bounty will reward on completion. /datum/spy_bounty/proc/select_reward(datum/spy_bounty_handler/handler) - var/list/loot_pool = handler.possible_uplink_items[difficulty] + loot_difficulty = difficulty + + var/list/loot_pool + // work backwards from the highest difficulty loot pool to find one that has items + for(var/i in length(handler.possible_uplink_items) to 1 step -1) + var/pool_tier = handler.possible_uplink_items[i] + // we're not looking for this difficult, skip + if(pool_tier != loot_difficulty) + continue + // we found our difficulty's loot pool, if it has items we're done + loot_pool = handler.possible_uplink_items[pool_tier] + if(length(loot_pool) || i == 1) + break + // if our difficult does not have items, and we're not at the lowest difficulty, step down and try again + loot_difficulty = handler.possible_uplink_items[i - 1] if(!length(loot_pool)) - reward_item = /datum/uplink_item/bundles_tc/telecrystal + reward_item = SStraitor.uplink_items_by_type[/datum/uplink_item/bundles_tc/telecrystal] return // future todo : add some junk items for when we run out of items reward_item = pick(loot_pool) + // we remove here, rather than on claim, to reduce the chance of duplicate rewards in a single batch + // otherwise it would be not only possible, but *likely* to get the same reward simultaneously across bounties + // (though the reason this is a probability is so there is a rare chance this can happen anyways, for the fun of it) if(prob(80)) loot_pool -= reward_item +/** + * Called when the bounty gets cleared after the end of a bounty period + * + * * handler - The bounty handler that is handling this bounty. + */ +/datum/spy_bounty/proc/clear_bounty(datum/spy_bounty_handler/handler) + ASSERT(initalized, "Trying to clear an uninitialized bounty!") + + // another chance to return unclaimed reward items to the bounty pool + if(!claimed && reward_item && prob(40)) + handler.possible_uplink_items[loot_difficulty || difficulty] |= reward_item + + qdel(src) + /** * Checks if the passed movable is a valid target for this bounty. * diff --git a/code/modules/antagonists/spy/spy_bounty_handler.dm b/code/modules/antagonists/spy/spy_bounty_handler.dm index 4b4ba9a835c..2f4cfc876c7 100644 --- a/code/modules/antagonists/spy/spy_bounty_handler.dm +++ b/code/modules/antagonists/spy/spy_bounty_handler.dm @@ -113,22 +113,43 @@ continue bounty_types[difficulty][bounty] = weight + var/list/limited_items = list() + var/list/show_anyways = list() + show_anyways += typesof(/datum/uplink_item/spy_unique/shotgun_ammo) // acquiring a shotgun is not difficult + for(var/datum/uplink_item/item as anything in SStraitor.uplink_items) - if(isnull(item.item) || item.item == ABSTRACT_UPLINK_ITEM) + // limited items is populated as we go + if(item in limited_items) continue - if(!(item.purchasable_from & UPLINK_SPY)) + // proc handles checking if the item is valid + if(!try_add_to_loot_pool(item)) continue - // This will have some overlap, and that's intentional - - // Adds some variety, rare moments where you can get a hard reward for an easier bounty (or visa versa) - if(item.cost <= CONFIG_GET(number/spy_easy_reward_tc_threshold)) - possible_uplink_items[SPY_DIFFICULTY_EASY] += item - if(item.cost >= CONFIG_GET(number/spy_easy_reward_tc_threshold) && item.cost <= CONFIG_GET(number/spy_hard_reward_tc_threshold)) - possible_uplink_items[SPY_DIFFICULTY_MEDIUM] += item - if(item.cost >= CONFIG_GET(number/spy_hard_reward_tc_threshold)) - possible_uplink_items[SPY_DIFFICULTY_HARD] += item + // any child items, such as ammo, are removed from the pool until the parent item is rewarded + for(var/child_item_type in (item.relevant_child_items || list()) - show_anyways) + if(prob(10)) // 10% chance to have it anyways though. teehee + continue + var/child_item = SStraitor.uplink_items_by_type[child_item_type] + for(var/difficulty in possible_uplink_items) + possible_uplink_items[difficulty] -= child_item + limited_items |= child_item refresh_bounty_list() +/// Helper to attempt to add the passed uplink item datum to the possible bounty pool(s). +/datum/spy_bounty_handler/proc/try_add_to_loot_pool(datum/uplink_item/item) + if(isnull(item.item) || item.item == ABSTRACT_UPLINK_ITEM || !(item.purchasable_from & UPLINK_SPY)) + return FALSE + + // This will have some overlap, and that's intentional - + // Adds some variety, rare moments where you can get a hard reward for an easier bounty (or visa versa) + if(item.cost <= CONFIG_GET(number/spy_easy_reward_tc_threshold)) + possible_uplink_items[SPY_DIFFICULTY_EASY] |= item + if(item.cost >= CONFIG_GET(number/spy_easy_reward_tc_threshold) && item.cost <= CONFIG_GET(number/spy_hard_reward_tc_threshold)) + possible_uplink_items[SPY_DIFFICULTY_MEDIUM] |= item + if(item.cost >= CONFIG_GET(number/spy_hard_reward_tc_threshold)) + possible_uplink_items[SPY_DIFFICULTY_HARD] |= item + return TRUE + /// Helper that returns a list of all active bounties in a single list, regardless of difficulty. /datum/spy_bounty_handler/proc/get_all_bounties() as /list var/list/all_bounties = list() @@ -152,7 +173,9 @@ bounties_to_give[SPY_DIFFICULTY_MEDIUM] += converted_medium_bounties for(var/difficulty in bounties) - QDEL_LIST(bounties[difficulty]) + for(var/datum/spy_bounty/bounty as anything in bounties[difficulty]) + bounty.clear_bounty(src) + bounties[difficulty].Cut() var/list/pool = bounty_types[difficulty] var/amount_to_give = bounties_to_give[difficulty] diff --git a/code/modules/antagonists/spy/spy_uplink.dm b/code/modules/antagonists/spy/spy_uplink.dm index 7131a0028ca..879061ed25a 100644 --- a/code/modules/antagonists/spy/spy_uplink.dm +++ b/code/modules/antagonists/spy/spy_uplink.dm @@ -148,12 +148,16 @@ return FALSE var/bounty_key = bounty.get_dupe_protection_key(stealing) + // record that we've claimed this type of bounty handler.all_claimed_bounty_types[bounty_key] += 1 handler.claimed_bounties_from_last_pool[bounty_key] = TRUE - + // clear up the bounty itself bounty.clean_up_stolen_item(stealing, spy, handler) bounty.claimed = TRUE - + // adds child items to the bounty pool, ie ammo for a newly acquired gun + for(var/child_item_type in bounty.reward_item.relevant_child_items) + handler.try_add_to_loot_pool(SStraitor.uplink_items_by_type[child_item_type]) + // and finally, spawn the reward var/atom/movable/reward = bounty.reward_item.spawn_item_for_generic_use(spy) if(isitem(reward)) spy.put_in_hands(reward) diff --git a/code/modules/cargo/packs/general.dm b/code/modules/cargo/packs/general.dm index 92364c33b8a..896649cc961 100644 --- a/code/modules/cargo/packs/general.dm +++ b/code/modules/cargo/packs/general.dm @@ -224,8 +224,7 @@ ///Generate assorted uplink items, taking into account the same surplus modifiers used for surplus crates /datum/supply_pack/misc/syndicate/fill(obj/structure/closet/crate/C) var/list/uplink_items = list() - for(var/datum/uplink_item/item_path as anything in SStraitor.uplink_items_by_type) - var/datum/uplink_item/item = SStraitor.uplink_items_by_type[item_path] + for(var/datum/uplink_item/item as anything in SStraitor.uplink_items) if(item.purchasable_from & contents_uplink_type && item.item) uplink_items += item diff --git a/code/modules/research/techweb/nodes/syndicate_nodes.dm b/code/modules/research/techweb/nodes/syndicate_nodes.dm index f4317669597..d031cf7c848 100644 --- a/code/modules/research/techweb/nodes/syndicate_nodes.dm +++ b/code/modules/research/techweb/nodes/syndicate_nodes.dm @@ -30,9 +30,8 @@ SIGNAL_HANDLER UnregisterSignal(SSearly_assets, COMSIG_SUBSYSTEM_POST_INITIALIZE) required_items_to_unlock = list() - for(var/datum/uplink_item/item_path as anything in SStraitor.uplink_items_by_type) - var/datum/uplink_item/item = SStraitor.uplink_items_by_type[item_path] - if(!item.item || !(item.uplink_item_flags & SYNDIE_ILLEGAL_TECH)) + for(var/datum/uplink_item/item as anything in SStraitor.uplink_items) + if(isnull(item.item) || item.item == ABSTRACT_UPLINK_ITEM || !(item.uplink_item_flags & SYNDIE_ILLEGAL_TECH)) continue required_items_to_unlock |= item.item //allows deconning to unlock. diff --git a/code/modules/uplink/uplink_items.dm b/code/modules/uplink/uplink_items.dm index b89fff956df..5644e058244 100644 --- a/code/modules/uplink/uplink_items.dm +++ b/code/modules/uplink/uplink_items.dm @@ -109,6 +109,9 @@ /// Uses the purchase log, so items purchased that are not visible in the purchase log will not count towards this. /// However, they won't be purchasable afterwards. var/lock_other_purchases = FALSE + /// A lazylist of typepaths to uplink items relevant to this this item + /// EX: a pistol would list its magazines or modifications here + var/list/relevant_child_items /datum/uplink_item/New() . = ..() diff --git a/code/modules/uplink/uplink_items/bundle.dm b/code/modules/uplink/uplink_items/bundle.dm index b6cdc2fd3d6..6247e32e3b8 100644 --- a/code/modules/uplink/uplink_items/bundle.dm +++ b/code/modules/uplink/uplink_items/bundle.dm @@ -18,8 +18,7 @@ /datum/uplink_item/bundles_tc/random/purchase(mob/user, datum/uplink_handler/handler, atom/movable/source) var/list/possible_items = list() - for(var/datum/uplink_item/item_path as anything in SStraitor.uplink_items_by_type) - var/datum/uplink_item/uplink_item = SStraitor.uplink_items_by_type[item_path] + for(var/datum/uplink_item/uplink_item as anything in SStraitor.uplink_items) if(src == uplink_item || !uplink_item.item) continue if(!handler.can_purchase_item(user, uplink_item)) @@ -81,8 +80,7 @@ /// generates items that can go inside crates, edit this proc to change what items could go inside your specialized crate /datum/uplink_item/bundles_tc/surplus/proc/generate_possible_items(mob/user, datum/uplink_handler/handler) var/list/possible_items = list() - for(var/datum/uplink_item/item_path as anything in SStraitor.uplink_items_by_type) - var/datum/uplink_item/uplink_item = SStraitor.uplink_items_by_type[item_path] + for(var/datum/uplink_item/uplink_item as anything in SStraitor.uplink_items) if(src == uplink_item || !uplink_item.item) continue if(!handler.check_if_restricted(uplink_item)) diff --git a/code/modules/uplink/uplink_items/dangerous.dm b/code/modules/uplink/uplink_items/dangerous.dm index 59d5644778d..ad8509a3e7c 100644 --- a/code/modules/uplink/uplink_items/dangerous.dm +++ b/code/modules/uplink/uplink_items/dangerous.dm @@ -15,7 +15,10 @@ item = /obj/item/storage/toolbox/guncase/traitor/donksoft cost = 6 surplus = 10 - purchasable_from = ~UPLINK_SERIOUS_OPS + purchasable_from = ~(UPLINK_SERIOUS_OPS | UPLINK_SPY) + relevant_child_items = list( + /datum/uplink_item/ammo/toydarts, + ) /datum/uplink_item/dangerous/pistol name = "Makarov Pistol Case" @@ -24,7 +27,13 @@ While not included in the kit, the pistol is compatible with suppressors, which can be purchased separately." item = /obj/item/storage/toolbox/guncase/traitor cost = 7 - purchasable_from = ~UPLINK_ALL_SYNDIE_OPS + purchasable_from = ~(UPLINK_ALL_SYNDIE_OPS | UPLINK_SPY) + relevant_child_items = list( + /datum/uplink_item/ammo/pistol, + /datum/uplink_item/ammo/pistolap, + /datum/uplink_item/ammo/pistolhp, + /datum/uplink_item/ammo/pistolfire, + ) /datum/uplink_item/dangerous/throwingweapons name = "Box of Throwing Weapons" @@ -96,3 +105,9 @@ cost = 13 surplus = 50 purchasable_from = ~UPLINK_ALL_SYNDIE_OPS //only traitors get the original revolver + relevant_child_items = list( + /datum/uplink_item/ammo/revolver, + /datum/uplink_item/ammo_nuclear/basic/revolver, + /datum/uplink_item/ammo_nuclear/special/revolver/phasic, + /datum/uplink_item/ammo_nuclear/special/revolver/heartseeker, + ) diff --git a/code/modules/uplink/uplink_items/nukeops.dm b/code/modules/uplink/uplink_items/nukeops.dm index 887a5165ad4..37ee8997aee 100644 --- a/code/modules/uplink/uplink_items/nukeops.dm +++ b/code/modules/uplink/uplink_items/nukeops.dm @@ -72,6 +72,17 @@ desc = "A fully-loaded 2-round burst fire drum-fed shotgun, complete with a secondary magazine you can hotswap. The gun has a handy label to explain how. \ Compatible with all 12g rounds. Designed for close quarter anti-personnel engagements. Comes with three spare magazines." item = /obj/item/storage/toolbox/guncase/bulldog + relevant_child_items = list( + /datum/uplink_item/ammo_nuclear/basic/buck, + /datum/uplink_item/ammo_nuclear/basic/donk, + /datum/uplink_item/ammo_nuclear/basic/flechette, + /datum/uplink_item/ammo_nuclear/basic/slug, + /datum/uplink_item/ammo_nuclear/incendiary/dragon, + /datum/uplink_item/ammo_nuclear/special/meteor, + /datum/uplink_item/spy_unique/shotgun_ammo, + /datum/uplink_item/spy_unique/shotgun_ammo/breacher_slug, + /datum/uplink_item/spy_unique/shotgun_ammo/slugs, + ) /datum/uplink_item/ammo_nuclear/basic/buck name = "12g Buckshot Drum (Bulldog)" @@ -122,6 +133,12 @@ desc = "A small, easily concealable handgun that uses 10mm auto rounds in 8-round magazines and is compatible \ with suppressors. Comes with three spare magazines." item = /obj/item/storage/toolbox/guncase/clandestine + relevant_child_items = list( + /datum/uplink_item/ammo_nuclear/basic/m10mm, + /datum/uplink_item/ammo_nuclear/ap/m10mm, + /datum/uplink_item/ammo_nuclear/hp/m10mm, + /datum/uplink_item/ammo_nuclear/incendiary/m10mm, + ) /datum/uplink_item/ammo_nuclear/basic/m10mm name = "10mm Handgun Magazine (Ansem)" @@ -164,6 +181,12 @@ desc = "A fully-loaded Scarborough Arms bullpup submachine gun. The C-20r fires .45 rounds with a \ 24-round magazine and is compatible with suppressors. Comes with spare three magazines." item = /obj/item/storage/toolbox/guncase/c20r + relevant_child_items = list( + /datum/uplink_item/ammo_nuclear/ap/smg, + /datum/uplink_item/ammo_nuclear/basic/smg, + /datum/uplink_item/ammo_nuclear/hp/smg, + /datum/uplink_item/ammo_nuclear/incendiary/smg, + ) /datum/uplink_item/ammo_nuclear/basic/smg name = ".45 SMG Magazine (C-20r)" @@ -213,6 +236,12 @@ desc = "Waffle Corp's modernized Syndicate revolver. Fires 7 brutal rounds of .357 Magnum. \ A classic operative weapon, improved for the modern era. Comes with 3 additional speedloaders of .357." item = /obj/item/storage/toolbox/guncase/revolver + relevant_child_items = list( + /datum/uplink_item/ammo/revolver, + /datum/uplink_item/ammo_nuclear/basic/revolver, + /datum/uplink_item/ammo_nuclear/special/revolver/phasic, + /datum/uplink_item/ammo_nuclear/special/revolver/heartseeker, + ) /datum/uplink_item/ammo_nuclear/basic/revolver name = ".357 Speed Loader (Revolver)" @@ -246,6 +275,10 @@ desc = "A reusable rocket propelled grenade launcher preloaded with a low-yield 84mm HE round. \ Guaranteed to take your target out with a bang, or your money back! Comes with a bouquet of additional rockets!" item = /obj/item/storage/toolbox/guncase/rocketlauncher + relevant_child_items = list( + /datum/uplink_item/ammo_nuclear/ap/rocket, + /datum/uplink_item/ammo_nuclear/basic/rocket, + ) /datum/uplink_item/ammo_nuclear/basic/rocket name = "84mm HE Rocket Bouquet (Rocket Launcher)" @@ -272,6 +305,13 @@ desc = "A fully-loaded Aussec Armoury belt-fed machine gun. \ This deadly weapon has a massive 50-round magazine of devastating 7mm ammunition." item = /obj/item/gun/ballistic/automatic/l6_saw + relevant_child_items = list( + /datum/uplink_item/ammo_nuclear/ap/machinegun, + /datum/uplink_item/ammo_nuclear/basic/machinegun, + /datum/uplink_item/ammo_nuclear/hp/machinegun, + /datum/uplink_item/ammo_nuclear/incendiary/machinegun, + /datum/uplink_item/ammo_nuclear/special/machinegun, + ) /datum/uplink_item/ammo_nuclear/basic/machinegun name = "7mm Box Magazine (L6 SAW)" @@ -311,6 +351,11 @@ Comes with a 40mm underbarrel grenade launcher. Use secondary-fire to fire the grenade launcher. Also comes with two spare magazines \ and a box of 40mm rubber slugs." item = /obj/item/storage/toolbox/guncase/m90gl + relevant_child_items = list( + /datum/uplink_item/ammo_nuclear/basic/carbine, + /datum/uplink_item/ammo_nuclear/special/carbine, + /datum/uplink_item/ammo_nuclear/basic/carbine/a40mm, + ) /datum/uplink_item/ammo_nuclear/basic/carbine name = ".223 Toploader Magazine (M-90gl)" @@ -340,6 +385,13 @@ Can be fitted with a suppressor. If anyone asks how that even works, tell them it's Nanotrasen's fault. Comes with \ 3 spare magazines; 2 regular magazines and 1 disruptor magazine. Also comes with a suit and tie." item = /obj/item/storage/briefcase/sniper + relevant_child_items = list( + /datum/uplink_item/ammo_nuclear/ap/sniper/penetrator, + /datum/uplink_item/ammo_nuclear/basic/sniper, + /datum/uplink_item/ammo_nuclear/basic/sniper/disruptor, + /datum/uplink_item/ammo_nuclear/incendiary/sniper, + /datum/uplink_item/ammo_nuclear/special/sniper/marksman, + ) /datum/uplink_item/ammo_nuclear/basic/sniper name = ".50 BMG Magazine (AMSR)" @@ -398,6 +450,9 @@ item = /obj/item/gun/ballistic/automatic/smartgun cost = 2 purchasable_from = UPLINK_SERIOUS_OPS + relevant_child_items = list( + /datum/uplink_item/ammo_nuclear/surplus_smg, + ) /datum/uplink_item/ammo_nuclear/surplus_smg name = "Surplus Smart-SMG Magazine (Smartgun)" @@ -629,6 +684,12 @@ item = /obj/item/storage/box/syndie_kit/cowboy cost = 18 purchasable_from = UPLINK_SERIOUS_OPS + relevant_child_items = list( + /datum/uplink_item/ammo/revolver, + /datum/uplink_item/ammo_nuclear/basic/revolver, + /datum/uplink_item/ammo_nuclear/special/revolver/phasic, + /datum/uplink_item/ammo_nuclear/special/revolver/heartseeker, + ) // Mech related gear @@ -650,6 +711,9 @@ for hit-and-run style attacks. Features a scattershot shotgun, armor boosters against melee and ranged attacks, and ion thrusters." item = /obj/vehicle/sealed/mecha/gygax/dark/loaded cost = 60 + relevant_child_items = list( + /datum/uplink_item/mech/support_bag/mauler, + ) /datum/uplink_item/mech/mauler name = "Mauler Exosuit" @@ -657,6 +721,9 @@ and deployable smoke. Comes equipped with an LMG, scattershot carbine, missile rack, and an antiprojectile armor booster." item = /obj/vehicle/sealed/mecha/marauder/mauler/loaded cost = 100 + relevant_child_items = list( + /datum/uplink_item/mech/support_bag/mauler, + ) // ~~ Mech Support ~~ diff --git a/code/modules/uplink/uplink_items/spy_unique.dm b/code/modules/uplink/uplink_items/spy_unique.dm index e201b804df5..abc7449e567 100644 --- a/code/modules/uplink/uplink_items/spy_unique.dm +++ b/code/modules/uplink/uplink_items/spy_unique.dm @@ -76,6 +76,11 @@ item = /obj/item/gun/ballistic/shotgun/automatic/dual_tube/deadly cost = SPY_UPPER_COST_THRESHOLD uplink_item_flags = SYNDIE_ILLEGAL_TECH | SYNDIE_TRIPS_CONTRABAND + relevant_child_items = list( + /datum/uplink_item/spy_unique/shotgun_ammo, + /datum/uplink_item/spy_unique/shotgun_ammo/breacher_slug, + /datum/uplink_item/spy_unique/shotgun_ammo/slugs, + ) /datum/uplink_item/spy_unique/bulldog_shotgun name = "Bulldog Shotgun" @@ -83,6 +88,17 @@ item = /obj/item/gun/ballistic/shotgun/bulldog/unrestricted cost = SPY_UPPER_COST_THRESHOLD uplink_item_flags = SYNDIE_ILLEGAL_TECH | SYNDIE_TRIPS_CONTRABAND + relevant_child_items = list( + /datum/uplink_item/ammo_nuclear/basic/buck, + /datum/uplink_item/ammo_nuclear/basic/donk, + /datum/uplink_item/ammo_nuclear/basic/flechette, + /datum/uplink_item/ammo_nuclear/basic/slug, + /datum/uplink_item/ammo_nuclear/incendiary/dragon, + /datum/uplink_item/ammo_nuclear/special/meteor, + /datum/uplink_item/spy_unique/shotgun_ammo, + /datum/uplink_item/spy_unique/shotgun_ammo/breacher_slug, + /datum/uplink_item/spy_unique/shotgun_ammo/slugs, + ) /datum/uplink_item/spy_unique/ansem_pistol name = "Ansem Pistol" @@ -90,6 +106,36 @@ item = /obj/item/gun/ballistic/automatic/pistol/clandestine cost = SPY_UPPER_COST_THRESHOLD uplink_item_flags = SYNDIE_ILLEGAL_TECH | SYNDIE_TRIPS_CONTRABAND + relevant_child_items = list( + /datum/uplink_item/ammo_nuclear/basic/m10mm, + /datum/uplink_item/ammo_nuclear/ap/m10mm, + /datum/uplink_item/ammo_nuclear/hp/m10mm, + /datum/uplink_item/ammo_nuclear/incendiary/m10mm, + ) + +/datum/uplink_item/spy_unique/makarov_pistol + name = "Makarov Pistol" + desc = "A Makarov pistol - Reliable and sturdy." + item = /obj/item/gun/ballistic/automatic/pistol + cost = SPY_LOWER_COST_THRESHOLD + uplink_item_flags = SYNDIE_ILLEGAL_TECH | SYNDIE_TRIPS_CONTRABAND + relevant_child_items = list( + /datum/uplink_item/ammo/pistol, + /datum/uplink_item/ammo/pistolap, + /datum/uplink_item/ammo/pistolhp, + /datum/uplink_item/ammo/pistolfire, + ) + +/datum/uplink_item/spy_unique/toy_pistol + name = "Donksoft Riot Pistol" + desc = "A Donksoft Riot Pistol - A toy pistol that fires foam darts at higher than normal velocity." + item = /obj/item/gun/ballistic/automatic/pistol/toy/riot/clandestine + cost = SPY_LOWER_COST_THRESHOLD + cost = SPY_LOWER_COST_THRESHOLD + uplink_item_flags = SYNDIE_ILLEGAL_TECH | SYNDIE_TRIPS_CONTRABAND + relevant_child_items = list( + /datum/uplink_item/ammo/toydarts, + ) /datum/uplink_item/spy_unique/rocket_launcher name = "Rocket Launcher" @@ -97,6 +143,10 @@ item = /obj/item/gun/ballistic/rocketlauncher cost = SPY_UPPER_COST_THRESHOLD - 1 // It's a meme item uplink_item_flags = SYNDIE_ILLEGAL_TECH | SYNDIE_TRIPS_CONTRABAND + relevant_child_items = list( + /datum/uplink_item/ammo_nuclear/ap/rocket, + /datum/uplink_item/ammo_nuclear/basic/rocket, + ) /datum/uplink_item/spy_unique/shotgun_ammo name = "Box of Buckshot" diff --git a/tgui/packages/tgui/interfaces/AntagInfoSpy.tsx b/tgui/packages/tgui/interfaces/AntagInfoSpy.tsx index ea1e142de19..3549e9fafd8 100644 --- a/tgui/packages/tgui/interfaces/AntagInfoSpy.tsx +++ b/tgui/packages/tgui/interfaces/AntagInfoSpy.tsx @@ -56,7 +56,9 @@ export const AntagInfoSpy = () => { Work together or work against them: The choice is yours, but{' '} - you cannot share the rewards. + + the same bounty cannot be claimed twice. +