diff --git a/code/__DEFINES/~nova_defines/jobs.dm b/code/__DEFINES/~nova_defines/jobs.dm index 7aa6486c9d5..a8cc61a9cf7 100644 --- a/code/__DEFINES/~nova_defines/jobs.dm +++ b/code/__DEFINES/~nova_defines/jobs.dm @@ -6,9 +6,11 @@ #define JOB_UNAVAILABLE_FLAVOUR (JOB_UNAVAILABLE_LANGUAGE + 1) #define JOB_UNAVAILABLE_AUGMENT (JOB_UNAVAILABLE_FLAVOUR + 1) -#define SEC_RESTRICTED_QUIRKS "Blind" = TRUE, "Brain Tumor" = TRUE, "Deaf" = TRUE, "Paraplegic" = TRUE, "Hemiplegic" = TRUE, "Mute" = TRUE, "Foreigner" = TRUE, "Pacifist" = TRUE, "No Guns" = TRUE, "Illiterate" = TRUE, "Nerve Stapled" = TRUE -#define HEAD_RESTRICTED_QUIRKS "Blind" = TRUE, "Deaf" = TRUE, "Mute" = TRUE, "Foreigner" = TRUE, "Brain Tumor" = TRUE, "Illiterate" = TRUE +#define SEC_RESTRICTED_QUIRKS "Blind" = TRUE, "Brain Tumor" = TRUE, "Deaf" = TRUE, "Paraplegic" = TRUE, "Hemiplegic" = TRUE, "Mute" = TRUE, "Foreigner" = TRUE, "Pacifist" = TRUE, "No Guns" = TRUE, "Illiterate" = TRUE, "Nerve Stapled" = TRUE, "Underworld Connections" = TRUE +#define HEAD_RESTRICTED_QUIRKS "Blind" = TRUE, "Deaf" = TRUE, "Mute" = TRUE, "Foreigner" = TRUE, "Brain Tumor" = TRUE, "Illiterate" = TRUE, "Underworld Connections" = TRUE +#define HEAD_RESTRICTED_QUIRKS_QM "Blind" = TRUE, "Deaf" = TRUE, "Mute" = TRUE, "Foreigner" = TRUE, "Brain Tumor" = TRUE, "Illiterate" = TRUE #define GUARD_RESTRICTED_QUIRKS "Blind" = TRUE, "Deaf" = TRUE, "Foreigner" = TRUE, "Pacifist" = TRUE, "Nerve Stapled" = TRUE +#define PRISONER_RESTRICTED_QUIRKS "Underworld Connections" = TRUE #define RESTRICTED_QUIRKS_EXCEPTIONS list("Mute" = "Signer") diff --git a/modular_nova/modules/customization/modules/jobs/_job.dm b/modular_nova/modules/customization/modules/jobs/_job.dm index 189e643e2ff..f053abc3390 100644 --- a/modular_nova/modules/customization/modules/jobs/_job.dm +++ b/modular_nova/modules/customization/modules/jobs/_job.dm @@ -117,7 +117,7 @@ banned_augments = list(HEAD_RESTRICTED_AUGMENTS) /datum/job/quartermaster - banned_quirks = list(HEAD_RESTRICTED_QUIRKS) + banned_quirks = list(HEAD_RESTRICTED_QUIRKS_QM) banned_augments = list(HEAD_RESTRICTED_AUGMENTS) //Silicon @@ -142,6 +142,7 @@ /datum/job/prisoner required_languages = null + banned_quirks = list(PRISONER_RESTRICTED_QUIRKS) /datum/job/orderly banned_quirks = list(GUARD_RESTRICTED_QUIRKS) diff --git a/modular_nova/modules/underworld_connections/code/black_market_uplink.dm b/modular_nova/modules/underworld_connections/code/black_market_uplink.dm new file mode 100644 index 00000000000..42a060cca60 --- /dev/null +++ b/modular_nova/modules/underworld_connections/code/black_market_uplink.dm @@ -0,0 +1,2 @@ +/obj/item/market_uplink + w_class = WEIGHT_CLASS_SMALL diff --git a/modular_nova/modules/underworld_connections/code/markets/base_black_market.dm b/modular_nova/modules/underworld_connections/code/markets/base_black_market.dm new file mode 100644 index 00000000000..9b13c31b9bf --- /dev/null +++ b/modular_nova/modules/underworld_connections/code/markets/base_black_market.dm @@ -0,0 +1,222 @@ +// This file contains a WHOLE BUNCH of cost defuckulations to bring the ancient black market stuff back into line with our current cargo pricing. +// I've also taken the liberty of redoing a few descs because man they kinda suck. +// Some availability_probs have been upped considerably for items that I think should be core to the "dodgy" character archetype, like switchblades, science goggles and the various maintenance pills. + +// CLOTHING + +/datum/market_item/clothing/ninja_mask + price_min = PAYCHECK_CREW + price_max = PAYCHECK_CREW * 3 + +/datum/market_item/clothing/durathread_vest + desc = "Concerns about high asbestos content are completely unfounded. Note: may contain asbestos." + price_min = PAYCHECK_CREW * 0.5 + price_max = PAYCHECK_CREW * 1.5 + +/datum/market_item/clothing/durathread_helmet + desc = "Smells faintly like an icewalker. Weird. Goes on your head and is vaguely armoured. Note: may contain asbestos." + price_min = PAYCHECK_CREW * 0.5 + price_max = PAYCHECK_CREW * 1.5 + +/datum/market_item/clothing/full_spacesuit_set + desc = "Decommissioned thirty years ago, boxes of these ancient spaceproof relics keep showing up in warehouses somewhere. They're \"old style\"." + price_min = PAYCHECK_CREW * 6 + price_max = PAYCHECK_CREW * 12 + +/datum/market_item/clothing/chameleon_hat + desc = "Emulate the appearance of any hat in the sector! Warning: device not quality tested. \[REDACTED\] assumes no risk for malfunction or mortal injury." + price_min = PAYCHECK_CREW + price_max = PAYCHECK_CREW * 3 + +/datum/market_item/clothing/rocket_boots + price_min = PAYCHECK_CREW * 6 + price_max = PAYCHECK_CREW * 12 + +/datum/market_item/clothing/anti_sec_pin + price_min = PAYCHECK_CREW + price_max = PAYCHECK_CREW * 3 + availability_prob = 100 //it's funny so why not + +// CONSUMABLES +/datum/market_item/consumable/clown_tears + desc = "Wrung by force from ethically-sourced clowns by your local jester. 100% guaranteed baton free." + price_min = PAYCHECK_CREW * 0.5 + price_max = PAYCHECK_CREW * 1.5 + +/datum/market_item/consumable/donk_pocket_box + price_min = PAYCHECK_CREW * 0.3 + price_max = PAYCHECK_CREW * 1 + availability_prob = 100 //you can always afford some (illegal) donkpockets. Donk Co loves you. + +/datum/market_item/consumable/suspicious_pills + price_min = PAYCHECK_CREW * 0.5 + price_max = PAYCHECK_CREW * 1.5 + +/datum/market_item/consumable/floor_pill + desc = "Harvested daily by responsibly-paid assistants, this pill is guaranteed to a) have been on the floor, and b) is a pill. Good luck!" + price_min = PAYCHECK_CREW * 0.1 + price_max = PAYCHECK_CREW * 0.3 + availability_prob = 100 // no shortage of unmarked pills babyyyy + +/datum/market_item/consumable/pumpup + desc = "Clean-up crews sell off these things by the dozen after every shift - get your hands on some today! What could possibly go wrong with maintenance drugs?" + price_min = PAYCHECK_CREW * 0.2 + price_max = PAYCHECK_CREW * 0.4 + +// MISCELLANEOUS + +/datum/market_item/misc/Clear_PDA + desc = "Clearly show your appreciation for style with this limited edition clear PDA!" + price_min = PAYCHECK_CREW + price_max = PAYCHECK_CREW * 2 + +/datum/market_item/misc/jade_Lantern + price_min = PAYCHECK_CREW * 0.5 + price_max = PAYCHECK_CREW + +/datum/market_item/misc/cap_gun + price_min = PAYCHECK_CREW * 0.5 + price_max = PAYCHECK_CREW + +/datum/market_item/misc/shoulder_holster + name = "Shoulder Holster" + //why in great googly moogly were these so expensive? what the fuck? + price_min = PAYCHECK_CREW * 0.2 + price_max = PAYCHECK_CREW * 0.6 + +/datum/market_item/misc/donk_recycler + price_min = PAYCHECK_CREW * 2 + price_max = PAYCHECK_CREW * 4 + +/datum/market_item/misc/shove_blocker + // ok this is a seriously fucking good module so we'll make it cost a bit + price_min = PAYCHECK_CREW * 8 + price_max = PAYCHECK_CREW * 14 + +/datum/market_item/misc/holywater + desc = "The Spinward Independent Magicians assume no responsibility for the holy (or unholiness) of this magical reagent." + price_min = PAYCHECK_CREW + price_max = PAYCHECK_CREW * 3 + +/datum/market_item/misc/strange_seed + desc = "Exotic varieties of seed outlawed in most sectors, including this one. What's the worst that could happen?" + price_min = PAYCHECK_CREW * 0.5 + price_max = PAYCHECK_CREW + +/datum/market_item/misc/smugglers_satchel + //inventory gamers... + price_min = PAYCHECK_CREW * 3 + price_max = PAYCHECK_CREW * 6 + +/datum/market_item/misc/roulette + price_min = PAYCHECK_CREW * 0.5 + price_max = PAYCHECK_CREW * 6 // it's how the chips fall babyyy + +/datum/market_item/misc/jawed_hook + desc = "If you're struggling with the fishes, give 'em the jaws, see?" + price_min = PAYCHECK_CREW * 0.5 + price_max = PAYCHECK_CREW * 1.5 + +/datum/market_item/misc/v8_engine + name = "Genuine V8 Engine (Preserved)" + price_min = PAYCHECK_CREW * 6 + price_max = PAYCHECK_CREW * 12 + +/datum/market_item/misc/fish + name = "Case of Smuggled Fish" + desc = "What makes these fish such hot products? We'd have to kill you if we told you." + +/datum/market_item/misc/giant_wrench_parts + name = "Comically-Large Wrench Parts" + desc = "They're searching every broadband transmission for the name of this wrench, alright? You're mad if you assemble this thing. Mad, we tell you." + price_min = PAYCHECK_CREW * 4 + price_max = PAYCHECK_CREW * 8 + +// TOOLS +/datum/market_item/tool/caravan_wrench + price_min = PAYCHECK_CREW * 0.5 + price_max = PAYCHECK_CREW * 2 + availability_prob = 100 // let's have all the experimental tools be always available, because why not? + +/datum/market_item/tool/caravan_wirecutters + price_min = PAYCHECK_CREW * 0.5 + price_max = PAYCHECK_CREW * 2 + availability_prob = 100 + +/datum/market_item/tool/caravan_screwdriver + price_min = PAYCHECK_CREW * 0.5 + price_max = PAYCHECK_CREW * 2 + availability_prob = 100 + +/datum/market_item/tool/caravan_crowbar + price_min = PAYCHECK_CREW * 0.5 + price_max = PAYCHECK_CREW * 2 + availability_prob = 100 + +/datum/market_item/tool/binoculars + //we can roundstart with these so let's tone them way down + desc = "Offworld military surplus. They'll never see you coming." + price_min = PAYCHECK_CREW * 0.2 + price_max = PAYCHECK_CREW * 0.5 + +/datum/market_item/tool/riot_shield + desc = "Bloodstains not included." + price_min = PAYCHECK_CREW * 4 + price_max = PAYCHECK_CREW * 8 + +/datum/market_item/tool/thermite_bottle + desc = "Thirty galactic units of an incendiary compound that will burn through just about anything." + price_min = PAYCHECK_CREW * 2 + price_max = PAYCHECK_CREW * 6 + +/datum/market_item/tool/science_goggles + price_min = PAYCHECK_CREW * 0.5 + price_max = PAYCHECK_CREW * 2 + availability_prob = 100 // for people who want to make illicit drugs in maint + +/datum/market_item/tool/fake_scanner + price_min = PAYCHECK_CREW * 0.5 + price_max = PAYCHECK_CREW * 2 + +/datum/market_item/tool/program_disk + name = "Bootleg PDA Data Disk" + desc = "Contains a random selection of limited PDA programs purloined by bitrunners from the FTU. Wait, we're not supposed to tell you that." + price_min = PAYCHECK_CREW * 1.5 + price_max = PAYCHECK_CREW * 3 + availability_prob = 100 // not every program is useful but some of these are and they're fun and hackery, so why not? + +// WEAPONS + +/datum/market_item/weapon/bear_trap + price_min = PAYCHECK_CREW * 2 + price_max = PAYCHECK_CREW * 4 + +/datum/market_item/weapon/shotgun_dart + price_min = PAYCHECK_CREW * 0.1 + price_max = PAYCHECK_CREW * 0.3 + +/datum/market_item/weapon/bone_spear + price_min = PAYCHECK_CREW * 0.5 + price_max = PAYCHECK_CREW * 2 + +/datum/market_item/weapon/chainsaw + desc = "Once used to fell trees on Gaia worlds, the humble chainsaw has come into its own as the premiere anti-mold device of the sector. And you can have one right now for one easy payment!" + price_min = PAYCHECK_CREW * 2 + price_max = PAYCHECK_CREW * 4 + availability_prob = 75 // USE CHAINSAWS FOR MOLDS MORE OH MY GOD + +/datum/market_item/weapon/switchblade + // This is force 20 like the sabre/shamshir so price it similarly. Also, make it always available so you can shank people in maints. + desc = "Standard-issue hardware for shifty goons sector-wide. Pointy and sharp." + price_min = PAYCHECK_CREW * 4.25 + price_max = PAYCHECK_CREW * 8 + availability_prob = 100 + +/datum/market_item/weapon/emp_grenade + desc = "The bane of synthetics and station-engineers everywhere." + price_min = PAYCHECK_CREW * 1.5 + price_max = PAYCHECK_CREW * 5 + +/datum/market_item/weapon/fisher + price_min = PAYCHECK_CREW * 4 + price_max = PAYCHECK_CREW * 8 diff --git a/modular_nova/modules/underworld_connections/code/underworld_connections_quirk.dm b/modular_nova/modules/underworld_connections/code/underworld_connections_quirk.dm new file mode 100644 index 00000000000..f3d78d7df45 --- /dev/null +++ b/modular_nova/modules/underworld_connections/code/underworld_connections_quirk.dm @@ -0,0 +1,147 @@ +/datum/quirk/item_quirk/underworld_connections + name = "Underworld Connections" + desc = "You're in with the seedier elements of the galactic underworld, and can start with a customizable black market uplink, and access to information brokers with exploitable information about the crew. Security has suspicions about you, and you may struggle to obtain a weapons permit." + icon = FA_ICON_SUITCASE + value = 0 + gain_text = span_notice("Your contacts to the underworld are close at hand.") + lose_text = span_notice("Your contacts to the underworld have gone quiet.") + medical_record_text = "Patient records may have been tampered with in the past." + quirk_flags = QUIRK_HIDE_FROM_SCAN + mail_goodies = list(/obj/item/storage/briefcase/secure) + +/datum/quirk/item_quirk/underworld_connections/add_unique(client/client_source) + if (ishuman(quirk_holder)) + var/obj/item/market_uplink/blackmarket/roundstart_uplink = new + + //customize the goddamn uplink + var/uplink_skin = client_source?.prefs.read_preference(/datum/preference/choiced/uplink_skin) + var/list/uplink_skin_val = GLOB.possible_uplink_skins[uplink_skin] + if (uplink_skin_val) + roundstart_uplink.icon = uplink_skin_val[1] + roundstart_uplink.icon_state = uplink_skin_val[2] + + var/uplink_name = client_source?.prefs.read_preference(/datum/preference/text/uplink_name) + if (uplink_name) + roundstart_uplink.name = uplink_name + + var/uplink_desc = client_source?.prefs.read_preference(/datum/preference/text/uplink_desc) + if (uplink_desc) + roundstart_uplink.desc = uplink_desc + + give_item_to_holder( + roundstart_uplink, + list( + LOCATION_LPOCKET = ITEM_SLOT_LPOCKET, + LOCATION_RPOCKET = ITEM_SLOT_RPOCKET, + LOCATION_BACKPACK = ITEM_SLOT_BACKPACK, + LOCATION_HANDS = ITEM_SLOT_HANDS, + ) + ) + +/datum/quirk/item_quirk/underworld_connections/post_add() + . = ..() + + // Make sure we've got a client/mind first (hence, post_add), then give us exploitables access + quirk_holder.mind.has_exploitables_override = TRUE + quirk_holder.mind.handle_exploitables() + + // Also let the user know that they need to OPFOR if they want to do heavy antagonism. Policy request. + to_chat(quirk_holder, span_boldwarning("REMEMBER: The Underworld Connections quirk does NOT make you an antagonist. Please make an OPFOR request if you intend to do serious criminal activity.")) + + // Set us as 'suspected' on HUDs at roundstart and leave a note about our dark and mysterious past. No permits for us! If we're human. + if (ishuman(quirk_holder)) + var/mob/living/carbon/human/human_holder = quirk_holder + var/datum/record/crew/our_record = find_record(human_holder.name) + if (our_record) + our_record.wanted_status = WANTED_SUSPECT + our_record.security_note += "DO NOT ISSUE WEAPON PERMITS. Subject has suspected links to covert criminal elements." + +/datum/quirk/item_quirk/underworld_connections/remove() + if (ishuman(quirk_holder)) + var/mob/living/carbon/human/human_holder = quirk_holder + var/datum/record/crew/our_record = find_record(human_holder.name) + if (our_record.security_note) + our_record.security_note = replacetext(our_record.security_note, "DO NOT ISSUE WEAPON PERMITS. Subject has suspected links to covert criminal elements.", "") + if (!length(our_record.security_note)) // that was the only thing in the notes + our_record.security_note = null + if (isnull(our_record.security_note) && our_record.wanted_status == WANTED_SUSPECT) // only clear this if the security notes contain nothing but the quirk-generated note, just to be certain we are not accidentally resetting the wanted status for an unrelated crime + our_record.wanted_status = WANTED_NONE + + quirk_holder.mind.has_exploitables_override = FALSE + quirk_holder.mind.handle_exploitables() + +/datum/quirk_constant_data/underworld_connections + associated_typepath = /datum/quirk/item_quirk/underworld_connections + customization_options = list(/datum/preference/choiced/uplink_skin, /datum/preference/text/uplink_name, /datum/preference/text/uplink_desc) + +/datum/preference/choiced/uplink_skin + category = PREFERENCE_CATEGORY_MANUALLY_RENDERED + savefile_key = "underworld_uplink_skin" + savefile_identifier = PREFERENCE_CHARACTER + can_randomize = FALSE + +/// List of uplink skins, associated list where the value is a list containing icon dmi and then icon_state +GLOBAL_LIST_INIT(possible_uplink_skins, list( + "Brick Phone" = list('icons/obj/antags/gang/cell_phone.dmi', "phone_off"), + "Default Black Market Uplink" = list('icons/obj/blackmarket.dmi', "uplink"), + "Generic Radio" = list('icons/obj/devices/voice.dmi', "radio"), + "Green Walkie Talkie" = list('icons/obj/devices/voice.dmi', "walkietalkie"), + "Inconspicious PDA" = list('icons/obj/modular_pda.dmi', "pda"), + "Mining Radio" = list('icons/obj/miningradio.dmi', "miningradio"), + "Red Analogue Phone" = list('icons/obj/devices/voice.dmi', "red_phone"), + "Red Walkie Talkie" = list('icons/obj/devices/voice.dmi', "nukietalkie"), + "Syndicate Suspicious Phone" = list('icons/obj/antags/syndicate_tools.dmi', "suspiciousphone"), + "Syndicate Tablet (Silicon)" = list('icons/obj/modular_pda.dmi', "tablet-silicon-syndicate"), +)) + +/datum/preference/choiced/uplink_skin/init_possible_values() + return assoc_to_keys(GLOB.possible_uplink_skins) + +/datum/preference/choiced/uplink_skin/create_default_value() + return "Default Black Market Uplink" + +/datum/preference/choiced/uplink_skin/is_accessible(datum/preferences/preferences) + if (!..()) + return FALSE + + return "Underworld Connections" in preferences.all_quirks + +/datum/preference/choiced/uplink_skin/apply_to_human(mob/living/carbon/human/target, value) + return + +/datum/preference/text/uplink_name + category = PREFERENCE_CATEGORY_MANUALLY_RENDERED + savefile_key = "underworld_uplink_name" + savefile_identifier = PREFERENCE_CHARACTER + can_randomize = FALSE + maximum_value_length = 32 + +/datum/preference/text/uplink_name/is_accessible(datum/preferences/preferences) + if (!..()) + return FALSE + + return "Underworld Connections" in preferences.all_quirks + +/datum/preference/text/uplink_name/serialize(input) + return htmlrendertext(input) + +/datum/preference/text/uplink_name/apply_to_human(mob/living/carbon/human/target, value) + return + +/datum/preference/text/uplink_desc + category = PREFERENCE_CATEGORY_MANUALLY_RENDERED + savefile_key = "underworld_uplink_desc" + savefile_identifier = PREFERENCE_CHARACTER + can_randomize = FALSE + +/datum/preference/text/uplink_desc/is_accessible(datum/preferences/preferences) + if (!..()) + return FALSE + + return "Underworld Connections" in preferences.all_quirks + +/datum/preference/text/uplink_desc/serialize(input) + return htmlrendertext(input) + +/datum/preference/text/uplink_desc/apply_to_human(mob/living/carbon/human/target, value) + return diff --git a/tgstation.dme b/tgstation.dme index fca09db7cbf..8e80cbb8e44 100644 --- a/tgstation.dme +++ b/tgstation.dme @@ -8109,6 +8109,9 @@ #include "modular_nova\modules\trim_tokens\code\cards_ids.dm" #include "modular_nova\modules\trim_tokens\code\trim_tokens.dm" #include "modular_nova\modules\turretid\code\turret_id_system.dm" +#include "modular_nova\modules\underworld_connections\code\black_market_uplink.dm" +#include "modular_nova\modules\underworld_connections\code\underworld_connections_quirk.dm" +#include "modular_nova\modules\underworld_connections\code\markets\base_black_market.dm" #include "modular_nova\modules\verbs\code\looc.dm" #include "modular_nova\modules\verbs\code\say.dm" #include "modular_nova\modules\verbs\code\subtle.dm" diff --git a/tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/character_preferences/nova/underworld_connections.tsx b/tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/character_preferences/nova/underworld_connections.tsx new file mode 100644 index 00000000000..ce2d7763ffe --- /dev/null +++ b/tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/character_preferences/nova/underworld_connections.tsx @@ -0,0 +1,22 @@ +// THIS IS A NOVA SECTOR UI FILE +import { + Feature, + FeatureChoiced, + FeatureDropdownInput, + FeatureShortTextInput, +} from '../../base'; + +export const underworld_uplink_skin: FeatureChoiced = { + name: 'Uplink Skin', + component: FeatureDropdownInput, +}; + +export const underworld_uplink_name: Feature = { + name: 'Uplink Name', + component: FeatureShortTextInput, +}; + +export const underworld_uplink_desc: Feature = { + name: 'Uplink Description', + component: FeatureShortTextInput, +};