From 93ee5f617c6c139415768b0f0b1df174e5f9556e Mon Sep 17 00:00:00 2001 From: wraith-54321 <69217972+wraith-54321@users.noreply.github.com> Date: Wed, 22 Nov 2023 19:56:02 -0800 Subject: [PATCH] very nice --- code/__DEFINES/~monkestation/uplink.dm | 2 + code/datums/components/uplink.dm | 26 +- code/game/objects/items/melee/baton.dm | 5 +- .../antagonists/traitor/datum_traitor.dm | 13 +- .../antagonists/traitor/objective_category.dm | 16 +- .../traitor/objectives/kidnapping.dm | 3 + .../antagonists/traitor/traitor_objective.dm | 5 + .../antagonists/traitor/uplink_handler.dm | 16 +- code/modules/uplink/uplink_items/special.dm | 1 + monkestation/code/datums/components/uplink.dm | 17 +- .../game/objects/items/storage/uplink_kits.dm | 10 +- .../contractor/datums/contractor_datum.dm | 8 +- .../contractor/datums/contractor_hub.dm | 4 - .../contractor/datums/contractor_items.dm | 68 ++-- .../contractor/datums/contractor_support.dm | 1 - .../antagonists/contractor/items/boxes.dm | 2 +- .../contractor/items/modsuit/modsuit.dm | 11 +- .../contractor/items/modsuit/theme.dm | 2 +- .../antagonists/traitor/datum_traitor.dm | 3 - .../final_objective/final_objective.dm | 2 + .../traitor/objectives/kidnapping.dm | 309 ++++++++++++++++++ .../antagonists/traitor/traitor_objective.dm | 4 +- .../antagonists/traitor/uplink_handler.dm | 20 ++ .../modules/uplink/uplink_items/bundle.dm | 16 +- .../{contractor_modsuit.dmi => modsuit.dmi} | Bin tgstation.dme | 5 +- .../tgui/interfaces/Uplink/ContractorMenu.tsx | 64 ++++ .../tgui/interfaces/Uplink/ObjectiveMenu.tsx | 5 + .../packages/tgui/interfaces/Uplink/index.tsx | 24 +- 29 files changed, 580 insertions(+), 82 deletions(-) create mode 100644 code/__DEFINES/~monkestation/uplink.dm delete mode 100644 monkestation/code/modules/antagonists/contractor/datums/contractor_hub.dm delete mode 100644 monkestation/code/modules/antagonists/traitor/datum_traitor.dm create mode 100644 monkestation/code/modules/antagonists/traitor/objectives/final_objective/final_objective.dm create mode 100644 monkestation/code/modules/antagonists/traitor/objectives/kidnapping.dm rename monkestation/icons/obj/clothing/modsuits/{contractor_modsuit.dmi => modsuit.dmi} (100%) create mode 100644 tgui/packages/tgui/interfaces/Uplink/ContractorMenu.tsx diff --git a/code/__DEFINES/~monkestation/uplink.dm b/code/__DEFINES/~monkestation/uplink.dm new file mode 100644 index 000000000000..fc05b3f16e34 --- /dev/null +++ b/code/__DEFINES/~monkestation/uplink.dm @@ -0,0 +1,2 @@ +/// the uplink flag for contractors +#define UPLINK_CONTRACTORS (1 << 6) diff --git a/code/datums/components/uplink.dm b/code/datums/components/uplink.dm index e7fe90891cf1..aa04e64a0cae 100644 --- a/code/datums/components/uplink.dm +++ b/code/datums/components/uplink.dm @@ -253,7 +253,22 @@ data["current_stock"] = remaining_stock data["shop_locked"] = uplink_handler.shop_locked data["purchased_items"] = length(uplink_handler.purchase_log?.purchase_log) - data["locked_entries"] = uplink_handler.locked_entries //monkestation edit +//monkestation edit start + data["locked_entries"] = uplink_handler.locked_entries + data["is_contractor"] = (uplink_handler.uplink_flag == UPLINK_CONTRACTORS) + var/list/contractor_items = list() + for(var/datum/contractor_item/item in uplink_handler.contractor_market_items) + contractor_items += list(list( + "id" = item.type, + "name" = item.name, + "desc" = item.desc, + "cost" = item.cost, + "stock" = item.stock, + "item_icon" = item.item_icon, + )) + data["contractor_items"] = contractor_items + data["contractor_rep"] = uplink_handler.contractor_rep +//monkestation edit end return data /datum/component/uplink/ui_static_data(mob/user) @@ -302,6 +317,15 @@ if(uplink_handler.owner?.current != ui.user || !uplink_handler.can_take_objectives) return TRUE +//monkestation edit start + switch(action) + if("buy_contractor") + var/item = params["item"] + for(var/datum/contractor_item/hub_item in uplink_handler.contractor_market_items) + if(hub_item.name == item) + hub_item.handle_purchase(uplink_handler, ui.user) +//monkestation edit end + switch(action) if("regenerate_objectives") uplink_handler.generate_objectives() diff --git a/code/game/objects/items/melee/baton.dm b/code/game/objects/items/melee/baton.dm index 0b8c9b0a4da9..cbffeac6c620 100644 --- a/code/game/objects/items/melee/baton.dm +++ b/code/game/objects/items/melee/baton.dm @@ -322,9 +322,11 @@ ) RegisterSignal(src, COMSIG_TRANSFORMING_ON_TRANSFORM, PROC_REF(on_transform)) +//monkestation edit start /obj/item/melee/baton/telescopic/additional_effects_non_cyborg(mob/living/target, mob/living/user) . = ..() target.Disorient(6 SECONDS, 5, paralyze = 3 SECONDS, stack_status = FALSE) +//monkestation edit end /obj/item/melee/baton/telescopic/suicide_act(mob/living/user) var/mob/living/carbon/human/human_user = user @@ -375,7 +377,7 @@ force = 5 cooldown = 2.5 SECONDS force_say_chance = 80 //very high force say chance because it's funny - stamina_damage = 170 + stamina_damage = 170 //monkestation edit: stam damage increased clumsy_knockdown_time = 24 SECONDS affect_cyborg = TRUE on_stun_sound = 'sound/effects/contractorbatonhit.ogg' @@ -390,6 +392,7 @@ /obj/item/melee/baton/telescopic/contractor_baton/additional_effects_non_cyborg(mob/living/target, mob/living/user) target.set_jitter_if_lower(40 SECONDS) target.set_stutter_if_lower(40 SECONDS) + target.Disorient(6 SECONDS, 5, paralyze = 3 SECONDS, stack_status = TRUE) //monkestation edit /obj/item/melee/baton/security name = "stun baton" diff --git a/code/modules/antagonists/traitor/datum_traitor.dm b/code/modules/antagonists/traitor/datum_traitor.dm index 4e40ab3efc60..18e7a0da65f6 100644 --- a/code/modules/antagonists/traitor/datum_traitor.dm +++ b/code/modules/antagonists/traitor/datum_traitor.dm @@ -79,6 +79,10 @@ if(give_secondary_objectives) uplink_handler.has_objectives = TRUE uplink_handler.generate_objectives() +//monkestation edit start + else + uplink_handler.has_objectives = FALSE +//monkestation edit end if(uplink_handler.progression_points < SStraitor.current_global_progression) uplink_handler.progression_points = SStraitor.current_global_progression * SStraitor.newjoin_progression_coeff @@ -344,14 +348,15 @@ var/completed_objectives_text = "Completed Uplink Objectives: " for(var/datum/traitor_objective/objective as anything in uplink_handler.completed_objectives) if(objective.objective_state == OBJECTIVE_STATE_COMPLETED) - completed_objectives_text += "
[objective.name] - ([objective.telecrystal_reward] TC, [DISPLAY_PROGRESSION(objective.progression_reward)] Reputation)" + completed_objectives_text += "
[objective.name] - ([objective.telecrystal_reward] TC, [DISPLAY_PROGRESSION(objective.progression_reward)] Threat Level)" +//monkestation edit on previous line: replaced "Reputation" with "Threat Level" result += completed_objectives_text - result += "
The traitor had a total of [DISPLAY_PROGRESSION(uplink_handler.progression_points)] Reputation and [uplink_handler.telecrystals] Unused Telecrystals." - + result += "
The traitor had a total of [DISPLAY_PROGRESSION(uplink_handler.progression_points)] Threat Level and [uplink_handler.telecrystals] Unused Telecrystals." +//monkestation edit on previous line: replaced "Reputation" with "Threat Level" var/special_role_text = lowertext(name) //monkestation edit start - if(contractor_hub) + if(uplink_handler?.purchased_contractor_items) result += contractor_round_end() //monkestation edit end diff --git a/code/modules/antagonists/traitor/objective_category.dm b/code/modules/antagonists/traitor/objective_category.dm index 5484d2937985..d4e38d70130c 100644 --- a/code/modules/antagonists/traitor/objective_category.dm +++ b/code/modules/antagonists/traitor/objective_category.dm @@ -12,27 +12,31 @@ // Category should just get autoGC'd here if they don't have any length, this may not be necessary qdel(category) -/datum/traitor_category_handler/proc/objective_valid(datum/traitor_objective/objective_path, progression_points) +/datum/traitor_category_handler/proc/objective_valid(datum/traitor_objective/objective_path, progression_points, uplink_flag) //monkestation edit: adds uplink_flag if(initial(objective_path.abstract_type) == objective_path) return FALSE if(progression_points < initial(objective_path.progression_minimum)) return FALSE if(progression_points > initial(objective_path.progression_maximum)) return FALSE +//monkestation edit start + if(!(initial(objective_path.valid_uplinks) & uplink_flag)) + return FALSE +//monkestation edit end return TRUE -/datum/traitor_category_handler/proc/get_possible_objectives(progression_points) +/datum/traitor_category_handler/proc/get_possible_objectives(progression_points, uplink_flag) //monkestation edit: adds uplink_flag var/list/valid_objectives = list() for(var/datum/traitor_objective_category/category as anything in all_categories) var/list/category_list = list() for(var/value in category.objectives) if(islist(value)) - var/list/objective_category = filter_invalid_objective_list(value, progression_points) + var/list/objective_category = filter_invalid_objective_list(value, progression_points, uplink_flag) //monkestation edit:: adds uplink_flag if(!length(objective_category)) continue category_list[objective_category] = category.objectives[value] else - if(!objective_valid(value, progression_points)) + if(!objective_valid(value, progression_points, uplink_flag)) //monkestation edit: adds uplink_flag continue category_list[value] = category.objectives[value] if(!length(category_list)) @@ -41,7 +45,7 @@ return valid_objectives -/datum/traitor_category_handler/proc/filter_invalid_objective_list(list/objectives, progression_points) +/datum/traitor_category_handler/proc/filter_invalid_objective_list(list/objectives, progression_points, uplink_flag) //monkestation edit: adds uplink_flag var/list/filtered_objectives = list() for(var/value in objectives) if(islist(value)) @@ -50,7 +54,7 @@ continue filtered_objectives[result] = objectives[value] else - if(!objective_valid(value, progression_points)) + if(!objective_valid(value, progression_points, uplink_flag)) //monkestation edit: adds uplink_flag continue filtered_objectives[value] = objectives[value] return filtered_objectives diff --git a/code/modules/antagonists/traitor/objectives/kidnapping.dm b/code/modules/antagonists/traitor/objectives/kidnapping.dm index 72551716a491..2ad4a74a57d1 100644 --- a/code/modules/antagonists/traitor/objectives/kidnapping.dm +++ b/code/modules/antagonists/traitor/objectives/kidnapping.dm @@ -1,3 +1,5 @@ +//MONKESTATIONFILE REMOVAL, CHECK THE FILE IN THE MODULAR DIRECTORY +/* /datum/traitor_objective/target_player/kidnapping name = "Kidnap %TARGET% the %JOB TITLE% and deliver them to %AREA%" description = "%TARGET% holds extremely important information regarding secret NT projects - and you'll need to kidnap and deliver them to %AREA%, where our transport pod will be waiting. \ @@ -321,3 +323,4 @@ for (var/obj/item/implant/storage/internal_bag in kidnapee.implants) belongings += internal_bag.contents return belongings +*/ diff --git a/code/modules/antagonists/traitor/traitor_objective.dm b/code/modules/antagonists/traitor/traitor_objective.dm index 30a8ba679441..b77bdd281c31 100644 --- a/code/modules/antagonists/traitor/traitor_objective.dm +++ b/code/modules/antagonists/traitor/traitor_objective.dm @@ -228,6 +228,10 @@ /datum/traitor_objective/proc/completion_payout() handler.progression_points += progression_reward handler.telecrystals += telecrystal_reward +//monkestation edit start + if(given_contractor_rep) + handler.contractor_rep += given_contractor_rep +//monkestation edit end /// Used for sending data to the uplink UI /datum/traitor_objective/proc/uplink_ui_data(mob/user) @@ -241,6 +245,7 @@ "objective_state" = objective_state, "original_progression" = original_progression, "telecrystal_penalty" = telecrystal_penalty, + "contractor_rep" = given_contractor_rep, //monkestation edit ) /datum/traitor_objective/proc/on_objective_taken(mob/user) diff --git a/code/modules/antagonists/traitor/uplink_handler.dm b/code/modules/antagonists/traitor/uplink_handler.dm index 40b5d97c0cff..4103f8f45176 100644 --- a/code/modules/antagonists/traitor/uplink_handler.dm +++ b/code/modules/antagonists/traitor/uplink_handler.dm @@ -114,14 +114,24 @@ on_update() return TRUE -/// Generates objectives for this uplink handler -/datum/uplink_handler/proc/generate_objectives() +/** Generates objectives for this uplink handler + * forced_types - an assoc list of objective types that when passed will always be generated first if possible to generate, value is how many of that type to generate + */ +/datum/uplink_handler/proc/generate_objectives(list/forced_types = list()) //monkestation edit: adds forced_types var/potential_objectives_left = maximum_potential_objectives - (length(potential_objectives) + length(active_objectives)) - var/list/objectives = SStraitor.category_handler.get_possible_objectives(progression_points) + var/list/objectives = SStraitor.category_handler.get_possible_objectives(progression_points, uplink_flag) //monkestation edit: adds uplink_flag if(!length(objectives)) return while(length(objectives) && potential_objectives_left > 0) var/objective_typepath = pick_weight(objectives) +//monkestation edit start + if(length(forced_types)) + var/picked_type = pick(forced_types) + forced_types[picked_type] -= 1 + if(!forced_types[picked_type]) + forced_types -= picked_type + objective_typepath = picked_type +//monkestation edit end var/list/target_list = objectives while(islist(objective_typepath)) if(!length(objective_typepath)) diff --git a/code/modules/uplink/uplink_items/special.dm b/code/modules/uplink/uplink_items/special.dm index 00425f2089a7..24d91ccd9341 100644 --- a/code/modules/uplink/uplink_items/special.dm +++ b/code/modules/uplink/uplink_items/special.dm @@ -18,3 +18,4 @@ ..() if(HAS_TRAIT(SSstation, STATION_TRAIT_CYBERNETIC_REVOLUTION)) purchasable_from |= UPLINK_TRAITORS + purchasable_from |= UPLINK_CONTRACTORS //monkestation edit diff --git a/monkestation/code/datums/components/uplink.dm b/monkestation/code/datums/components/uplink.dm index 5477d2b5b667..e7c39c911559 100644 --- a/monkestation/code/datums/components/uplink.dm +++ b/monkestation/code/datums/components/uplink.dm @@ -1,2 +1,17 @@ -//this file contains extra stuff we have for uplink components like contractors +#define STARTING_COMMON_CONTRACTS 3 +#define STARTING_UNCOMMON_CONTRACTS 2 +#define STARTING_RARE_CONTRACTS 1 +/datum/component/uplink/proc/become_contractor() + uplink_handler.uplink_flag = UPLINK_CONTRACTORS + uplink_handler.clear_secondaries() + uplink_handler.generate_objectives(list( + /datum/traitor_objective/target_player/kidnapping/common = STARTING_COMMON_CONTRACTS, + /datum/traitor_objective/target_player/kidnapping/uncommon = STARTING_UNCOMMON_CONTRACTS, + /datum/traitor_objective/target_player/kidnapping/rare = STARTING_RARE_CONTRACTS, + )) + for(var/item as anything in subtypesof(/datum/contractor_item)) + uplink_handler.contractor_market_items += new item +#undef STARTING_COMMON_CONTRACTS +#undef STARTING_UNCOMMON_CONTRACTS +#undef STARTING_RARE_CONTRACTS diff --git a/monkestation/code/game/objects/items/storage/uplink_kits.dm b/monkestation/code/game/objects/items/storage/uplink_kits.dm index 394aea4247db..d68a9559b3a4 100644 --- a/monkestation/code/game/objects/items/storage/uplink_kits.dm +++ b/monkestation/code/game/objects/items/storage/uplink_kits.dm @@ -24,7 +24,7 @@ /obj/item/clothing/under/syndicate/skirt/maid = 1, /obj/item/clothing/gloves/combat/maid = 1, /obj/item/clothing/accessory/maidapron/syndicate = 1,) - generate_items_inside(items_inside,src) + generate_items_inside(items_inside, src) /obj/item/storage/box/syndie_kit/contractor_loadout name = "Standard Loadout" @@ -41,7 +41,7 @@ new /obj/item/jammer(src) /obj/item/storage/box/syndie_kit/contract_kit/PopulateContents() - new /obj/item/storage/box/syndicate/contractor_loadout(src) + new /obj/item/storage/box/syndie_kit/contractor_loadout(src) new /obj/item/melee/baton/telescopic/contractor_baton(src) // You get one item from each sub list @@ -84,9 +84,9 @@ ) var/list/items_to_give = list() - items_to_give += pick(item_list[KIT_ITEM_CATEGORY_SUPPORT]) - items_to_give += pick(item_list[KIT_ITEM_CATEGORY_WEAPONS]) - items_to_give += pick(item_list[KIT_ITEM_CATEGORY_MISC]) + items_to_give[pick(item_list[KIT_ITEM_CATEGORY_SUPPORT])] = 1 + items_to_give[pick(item_list[KIT_ITEM_CATEGORY_WEAPONS])] = 1 + items_to_give[pick(item_list[KIT_ITEM_CATEGORY_MISC])] = 1 generate_items_inside(items_to_give, src) // Paper guide diff --git a/monkestation/code/modules/antagonists/contractor/datums/contractor_datum.dm b/monkestation/code/modules/antagonists/contractor/datums/contractor_datum.dm index 68acfd7ee2e8..c83c7efa12ad 100644 --- a/monkestation/code/modules/antagonists/contractor/datums/contractor_datum.dm +++ b/monkestation/code/modules/antagonists/contractor/datums/contractor_datum.dm @@ -7,17 +7,17 @@ var/contractor_support_unit = "" // Set if they had a support unit - and shows appended to their contracts completed /// Get all the icons/total cost for all our items bought - for (var/datum/contractor_item/contractor_purchase in contractor_hub.purchased_items) + for(var/datum/contractor_item/contractor_purchase in uplink_handler.purchased_contractor_items) contractor_item_icons += "\[ [contractor_purchase.name] - [contractor_purchase.cost] Rep

[contractor_purchase.desc]
\]
" - +//TEST SPANS total_spent_rep += contractor_purchase.cost /// Special case for reinforcements, we want to show their ckey and name on round end. - if (istype(contractor_purchase, /datum/contractor_item/contractor_partner)) + if(istype(contractor_purchase, /datum/contractor_item/contractor_partner)) var/datum/contractor_item/contractor_partner/partner = contractor_purchase contractor_support_unit += "
[partner.partner_mind.key] played [partner.partner_mind.current.name], their contractor support unit." - if (contractor_hub.purchased_items.len) + if(length(uplink_handler.purchased_contractor_items)) result += "
(used [total_spent_rep] Rep) " result += contractor_item_icons result += "
" diff --git a/monkestation/code/modules/antagonists/contractor/datums/contractor_hub.dm b/monkestation/code/modules/antagonists/contractor/datums/contractor_hub.dm deleted file mode 100644 index 6ac1f55aa061..000000000000 --- a/monkestation/code/modules/antagonists/contractor/datums/contractor_hub.dm +++ /dev/null @@ -1,4 +0,0 @@ -/datum/contractor_hub - var/contract_rep = 0 - var/static/list/hub_items = list() - var/list/purchased_items = list() diff --git a/monkestation/code/modules/antagonists/contractor/datums/contractor_items.dm b/monkestation/code/modules/antagonists/contractor/datums/contractor_items.dm index 33f6de3a1933..6dc8adcdddac 100644 --- a/monkestation/code/modules/antagonists/contractor/datums/contractor_items.dm +++ b/monkestation/code/modules/antagonists/contractor/datums/contractor_items.dm @@ -6,6 +6,21 @@ var/stock = -1 // Any number above 0 for how many times it can be bought in a round for a single traitor. -1 is unlimited. var/cost // Cost of the item in contract rep. +/datum/contractor_item/contract_reroll + name = "Contract Reroll" + desc = "Request a reroll of your current contract list. Will generate a new target, payment, and dropoff for the contracts you currently have available." + item_icon = "dice" + stock = 2 + cost = 0 + +/datum/contractor_item/contract_reroll/handle_purchase(datum/uplink_handler/handler, mob/living/user) + . = ..() + if(!.) + return FALSE + + handler.clear_secondaries() + handler.generate_objectives() + /datum/contractor_item/contractor_pinpointer name = "Contractor Pinpointer" desc = "A pinpointer that finds targets even without active suit sensors. Due to taking advantage of an exploit within the system, \ @@ -21,7 +36,7 @@ Activating the pack on your target will send them over to the beacon - make sure they're not just going to run away though!" item = /obj/item/storage/box/contractor/fulton_extraction item_icon = "parachute-box" - stock = 1 + stock = 2 cost = 1 /datum/contractor_item/contractor_partner @@ -33,10 +48,10 @@ cost = 2 var/datum/mind/partner_mind = null -/datum/contractor_item/contractor_partner/handle_purchase(datum/contractor_hub/hub, mob/living/user) +/datum/contractor_item/contractor_partner/handle_purchase(datum/uplink_handler/handler, mob/living/user) . = ..() if(!.) - return + return FALSE to_chat(user, span_notice("The uplink vibrates quietly, connecting to nearby agents...")) @@ -51,8 +66,8 @@ // refund and add the limit back. stock += 1 - hub.contract_rep += cost - hub.purchased_items -= src + handler.contractor_rep += cost + handler.purchased_contractor_items -= src /datum/contractor_item/contractor_partner/proc/spawn_contractor_partner(mob/living/user, key) var/mob/living/carbon/human/partner = new() @@ -91,28 +106,29 @@ stock = 2 cost = 3 -/datum/contractor_item/blackout/handle_purchase(datum/contractor_hub/hub) +/datum/contractor_item/blackout/handle_purchase(datum/uplink_handler/handler) . = ..() - if (.) - power_fail(35, 50) - priority_announce("Abnormal activity detected in [station_name()]'s powernet. As a precautionary measure, the station's power will be shut off for an indeterminate duration.", \ - "Critical Power Failure", ANNOUNCER_POWEROFF) + if(!.) + return FALSE -// Subtract cost, and spawn if it's an item. -/datum/contractor_item/proc/handle_purchase(datum/contractor_hub/hub, mob/living/user) + power_fail(35, 50) + priority_announce("Abnormal activity detected in [station_name()]'s powernet. As a precautionary measure, the station's power will be shut off for an indeterminate duration.", \ + "Critical Power Failure", ANNOUNCER_POWEROFF) - if (hub.contract_rep >= cost) - hub.contract_rep -= cost +// Subtract cost, and spawn if it's an item. +/datum/contractor_item/proc/handle_purchase(datum/uplink_handler/handler, mob/living/user) + if(handler.contractor_rep >= cost) + handler.contractor_rep -= cost else return FALSE - if (stock >= 1) + if(stock >= 1) stock -= 1 - else if (stock == 0) + else if(stock == 0) return FALSE - hub.purchased_items.Add(src) + handler.purchased_contractor_items.Add(src) user.playsound_local(user, 'sound/machines/uplinkpurchase.ogg', 100) @@ -127,24 +143,6 @@ return item_to_create return TRUE -/obj/item/pinpointer/crew/contractor - name = "contractor pinpointer" - desc = "A handheld tracking device that locks onto certain signals. Ignores suit sensors, but is much less accurate." - icon_state = "pinpointer_syndicate" - worn_icon_state = "pinpointer_black" - minimum_range = 25 - has_owner = TRUE - ignore_suit_sensor_level = TRUE - -/obj/item/storage/box/contractor/fulton_extraction - name = "Fulton Extraction Kit" - icon_state = "syndiebox" - illustration = "writing_syndie" - -/obj/item/storage/box/contractor/fulton_extraction/PopulateContents() - new /obj/item/extraction_pack(src) - new /obj/item/fulton_core(src) - /datum/contractor_item/baton_holster name = "Baton Holster Module" desc = "Never worry about dropping your baton again with this holster module! Simply insert your baton into the module, put it in your MODsuit, \ diff --git a/monkestation/code/modules/antagonists/contractor/datums/contractor_support.dm b/monkestation/code/modules/antagonists/contractor/datums/contractor_support.dm index 412839847373..b8f4e2edef20 100644 --- a/monkestation/code/modules/antagonists/contractor/datums/contractor_support.dm +++ b/monkestation/code/modules/antagonists/contractor/datums/contractor_support.dm @@ -5,7 +5,6 @@ show_in_roundend = FALSE // We're already adding them in to the contractor's roundend. give_objectives = TRUE // We give them their own custom objective. show_in_antagpanel = FALSE // Not a proper/full antag. - give_uplink = FALSE // Don't give them an uplink. give_secondary_objectives = FALSE /// Team datum that contains the contractor and the support unit var/datum/team/contractor_team/contractor_team diff --git a/monkestation/code/modules/antagonists/contractor/items/boxes.dm b/monkestation/code/modules/antagonists/contractor/items/boxes.dm index 4f15be95e2fb..fdff852150e1 100644 --- a/monkestation/code/modules/antagonists/contractor/items/boxes.dm +++ b/monkestation/code/modules/antagonists/contractor/items/boxes.dm @@ -5,4 +5,4 @@ /obj/item/storage/box/contractor/fulton_extraction/PopulateContents() new /obj/item/extraction_pack/contractor(src) - new /obj/item/fulton_core(src) + generate_items_inside(list(/obj/item/fulton_core = 3), src) diff --git a/monkestation/code/modules/antagonists/contractor/items/modsuit/modsuit.dm b/monkestation/code/modules/antagonists/contractor/items/modsuit/modsuit.dm index 31418e6c32c6..97cf27b3e1d1 100644 --- a/monkestation/code/modules/antagonists/contractor/items/modsuit/modsuit.dm +++ b/monkestation/code/modules/antagonists/contractor/items/modsuit/modsuit.dm @@ -1,6 +1,7 @@ /obj/item/mod/control/pre_equipped/contractor worn_icon = 'monkestation/icons/mob/clothing/worn_modsuit.dmi' - icon = 'monkestation/icons/obj/clothing/modsuits/contractor_modsuit.dmi' + icon = 'monkestation/icons/obj/clothing/modsuits/modsuit.dmi' + icon_state = "contractor-control" theme = /datum/mod_theme/contractor applied_cell = /obj/item/stock_parts/cell/hyper applied_modules = list( @@ -24,16 +25,16 @@ // I absolutely fuckin hate having to do this /obj/item/clothing/head/mod/contractor worn_icon = 'monkestation/icons/mob/clothing/worn_modsuit.dmi' - icon = 'monkestation/icons/obj/clothing/modsuits/contractor_modsuit.dmi' + icon = 'monkestation/icons/obj/clothing/modsuits/modsuit.dmi' /obj/item/clothing/suit/mod/contractor worn_icon = 'monkestation/icons/mob/clothing/worn_modsuit.dmi' - icon = 'monkestation/icons/obj/clothing/modsuits/contractor_modsuit.dmi' + icon = 'monkestation/icons/obj/clothing/modsuits/modsuit.dmi' /obj/item/clothing/gloves/mod/contractor worn_icon = 'monkestation/icons/mob/clothing/worn_modsuit.dmi' - icon = 'monkestation/icons/obj/clothing/modsuits/contractor_modsuit.dmi' + icon = 'monkestation/icons/obj/clothing/modsuits/modsuit.dmi' /obj/item/clothing/shoes/mod/contractor worn_icon = 'monkestation/icons/mob/clothing/worn_modsuit.dmi' - icon = 'monkestation/icons/obj/clothing/modsuits/contractor_modsuit.dmi' + icon = 'monkestation/icons/obj/clothing/modsuits/modsuit.dmi' diff --git a/monkestation/code/modules/antagonists/contractor/items/modsuit/theme.dm b/monkestation/code/modules/antagonists/contractor/items/modsuit/theme.dm index fb71e85bbb56..530c18f2a442 100644 --- a/monkestation/code/modules/antagonists/contractor/items/modsuit/theme.dm +++ b/monkestation/code/modules/antagonists/contractor/items/modsuit/theme.dm @@ -56,7 +56,7 @@ ), ), ) - +//ICONS BORKED /datum/armor/mod_contractor_armor melee = 40 bullet = 50 diff --git a/monkestation/code/modules/antagonists/traitor/datum_traitor.dm b/monkestation/code/modules/antagonists/traitor/datum_traitor.dm deleted file mode 100644 index 902fa6ef7c73..000000000000 --- a/monkestation/code/modules/antagonists/traitor/datum_traitor.dm +++ /dev/null @@ -1,3 +0,0 @@ -/datum/antagonist/traitor - ///ref to our contractor hub datum, if we have one - var/datum/contractor_hub/contractor_hub diff --git a/monkestation/code/modules/antagonists/traitor/objectives/final_objective/final_objective.dm b/monkestation/code/modules/antagonists/traitor/objectives/final_objective/final_objective.dm new file mode 100644 index 000000000000..fa64e26afccc --- /dev/null +++ b/monkestation/code/modules/antagonists/traitor/objectives/final_objective/final_objective.dm @@ -0,0 +1,2 @@ +/datum/traitor_objective/ultimate + valid_uplinks = UPLINK_TRAITORS | UPLINK_CONTRACTORS diff --git a/monkestation/code/modules/antagonists/traitor/objectives/kidnapping.dm b/monkestation/code/modules/antagonists/traitor/objectives/kidnapping.dm new file mode 100644 index 000000000000..6b7ac9c9bbe7 --- /dev/null +++ b/monkestation/code/modules/antagonists/traitor/objectives/kidnapping.dm @@ -0,0 +1,309 @@ +#define STARTING_COMMON_OBJECTIVES +/datum/traitor_objective/target_player/kidnapping + name = "Kidnap %TARGET% the %JOB TITLE% and deliver them to %AREA%" + description = "%TARGET% holds extremely important information regarding secret NT projects - and you'll need to kidnap and deliver them to %AREA%, where our transport pod will be waiting. \ + If %TARGET% is delivered alive, you will be rewarded with an additional %TC% telecrystals." + + abstract_type = /datum/traitor_objective/target_player/kidnapping + valid_uplinks = UPLINK_CONTRACTORS + given_contractor_rep = 1 + progression_minimum = 0 MINUTES + + /// The jobs that this objective is targetting. + var/list/target_jobs + /// Area that the target needs to be delivered to + var/area/dropoff_area + /// Have we called the pod yet? + var/pod_called = FALSE + /// How much TC do we get from sending the target alive + var/alive_bonus = 0 + /// All stripped targets belongings + var/list/target_belongings = list() + +/datum/traitor_objective/target_player/kidnapping/common + progression_reward = list(2 MINUTES, 4 MINUTES) + telecrystal_reward = list(2, 3) + target_jobs = list( + // Cargo + /datum/job/cargo_technician, + // Engineering + /datum/job/atmospheric_technician, + /datum/job/station_engineer, + // Medical + /datum/job/chemist, + /datum/job/doctor, + /datum/job/psychologist, + /datum/job/virologist, + // Science + /datum/job/geneticist, + /datum/job/roboticist, + /datum/job/scientist, + // Service + /datum/job/bartender, + /datum/job/botanist, + /datum/job/chaplain, + /datum/job/clown, + /datum/job/curator, + /datum/job/janitor, + /datum/job/lawyer, + /datum/job/mime, + ) + alive_bonus = 3 + +/datum/traitor_objective/target_player/kidnapping/common/assistant + target_jobs = list( + /datum/job/assistant + ) + telecrystal_reward = 3 //go bully the assistants + +/datum/traitor_objective/target_player/kidnapping/uncommon //Hard to fish out targets + progression_reward = list(4 MINUTES, 8 MINUTES) + telecrystal_reward = list(3, 4) + given_contractor_rep = 2 + + target_jobs = list( + // Cargo + /datum/job/quartermaster, + /datum/job/shaft_miner, + // Medical + /datum/job/paramedic, + // Service + /datum/job/cook, + ) + alive_bonus = 4 + +/datum/traitor_objective/target_player/kidnapping/rare + progression_reward = list(8 MINUTES, 12 MINUTES) + telecrystal_reward = list(4, 5) + given_contractor_rep = 3 + + target_jobs = list( + // Heads of staff + /datum/job/chief_engineer, + /datum/job/chief_medical_officer, + /datum/job/head_of_personnel, + /datum/job/research_director, + // Security + /datum/job/detective, + /datum/job/security_officer, + /datum/job/warden, + ) + alive_bonus = 5 + +/datum/traitor_objective/target_player/kidnapping/captain + progression_reward = list(12 MINUTES, 16 MINUTES) + telecrystal_reward = list(5, 6) + given_contractor_rep = 4 + + target_jobs = list( + /datum/job/captain, + /datum/job/head_of_security, + ) + alive_bonus = 6 + +/datum/traitor_objective/target_player/kidnapping/generate_objective(datum/mind/generating_for, list/possible_duplicates) + + var/list/already_targeting = list() //List of minds we're already targeting. The possible_duplicates is a list of objectives, so let's not mix things + for(var/datum/objective/task as anything in handler.primary_objectives) + if(!istype(task.target, /datum/mind)) + continue + already_targeting += task.target //Removing primary objective kill targets from the list + + var/list/possible_targets = list() + for(var/datum/mind/possible_target as anything in get_crewmember_minds()) + if(possible_target == generating_for) + continue + + if(possible_target in already_targeting) + continue + + if(!ishuman(possible_target.current)) + continue + + if(possible_target.current.stat == DEAD) + continue + + if(HAS_TRAIT(possible_target, TRAIT_HAS_BEEN_KIDNAPPED)) + continue + + if(possible_target.has_antag_datum(/datum/antagonist/traitor)) + continue + + if(!(possible_target.assigned_role.type in target_jobs)) + continue + + possible_targets += possible_target + + for(var/datum/traitor_objective/target_player/objective as anything in possible_duplicates) + if(!objective.target) //the old objective was already completed. + continue + possible_targets -= objective.target.mind + + if(!length(possible_targets)) + return FALSE + + var/datum/mind/target_mind = pick(possible_targets) + target = target_mind.current + AddComponent(/datum/component/traitor_objective_register, target, fail_signals = list(COMSIG_PARENT_QDELETING)) + var/list/possible_areas = GLOB.the_station_areas.Copy() + for(var/area/possible_area as anything in possible_areas) + if(ispath(possible_area, /area/station/hallway) || ispath(possible_area, /area/station/security) || initial(possible_area.outdoors)) + possible_areas -= possible_area + + dropoff_area = pick(possible_areas) + replace_in_name("%TARGET%", target_mind.name) + replace_in_name("%JOB TITLE%", target_mind.assigned_role.title) + replace_in_name("%AREA%", initial(dropoff_area.name)) + replace_in_name("%TC%", alive_bonus) + return TRUE + +/datum/traitor_objective/target_player/kidnapping/ungenerate_objective() + target = null + dropoff_area = null + +/datum/traitor_objective/target_player/kidnapping/on_objective_taken(mob/user) + . = ..() + INVOKE_ASYNC(src, PROC_REF(generate_holding_area)) + +/datum/traitor_objective/target_player/kidnapping/proc/generate_holding_area() + // Let's load in the holding facility ahead of time + // even if they fail the objective it's better to get done now rather than later + SSmapping.lazy_load_template(LAZY_TEMPLATE_KEY_NINJA_HOLDING_FACILITY) + +/datum/traitor_objective/target_player/kidnapping/generate_ui_buttons(mob/user) + var/list/buttons = list() + if(!pod_called) + buttons += add_ui_button("Call Extraction Pod", "Pressing this will call down an extraction pod.", "rocket", "call_pod") + return buttons + +/datum/traitor_objective/target_player/kidnapping/ui_perform_action(mob/living/user, action) + . = ..() + switch(action) + if("call_pod") + if(pod_called) + return + var/area/user_area = get_area(user) + var/area/target_area = get_area(target) + + if(user_area.type != dropoff_area) + to_chat(user, span_warning("You must be in [initial(dropoff_area.name)] to call the extraction pod.")) + return + + if(target_area.type != dropoff_area) + to_chat(user, span_warning("[target.real_name] must be in [initial(dropoff_area.name)] for you to call the extraction pod.")) + return + + call_pod(user) + +/datum/traitor_objective/target_player/kidnapping/proc/call_pod(mob/living/user) + pod_called = TRUE + var/obj/structure/closet/supplypod/extractionpod/new_pod = new() + RegisterSignal(new_pod, COMSIG_ATOM_ENTERED, PROC_REF(enter_check)) + new /obj/effect/pod_landingzone(get_turf(user), new_pod) + +/datum/traitor_objective/target_player/kidnapping/proc/enter_check(obj/structure/closet/supplypod/extractionpod/source, entered_atom) + if(!istype(source)) + CRASH("Kidnapping objective's enter_check called with source being not an extraction pod: [source ? source.type : "N/A"]") + + if(!ishuman(entered_atom)) + return + + var/mob/living/carbon/human/sent_mob = entered_atom + + if(sent_mob.mind) + ADD_TRAIT(sent_mob.mind, TRAIT_HAS_BEEN_KIDNAPPED, TRAIT_GENERIC) + + for(var/obj/item/belonging in gather_belongings(sent_mob)) + if(belonging == sent_mob.get_item_by_slot(ITEM_SLOT_ICLOTHING) || belonging == sent_mob.get_item_by_slot(ITEM_SLOT_FEET)) + continue + + var/unequipped = sent_mob.transferItemToLoc(belonging) + if (!unequipped) + continue + target_belongings.Add(belonging) + + var/datum/bank_account/cargo_account = SSeconomy.get_dep_account(ACCOUNT_CAR) + + if(cargo_account) //Just in case + cargo_account.adjust_money(-min(rand(1000, 3000), cargo_account.account_balance)) //Not so much, especially for competent cargo. Plus this can't be mass-triggered like it has been done with contractors + + priority_announce("One of your crew was captured by a rival organisation - we've needed to pay their ransom to bring them back. As is policy we've taken a portion of the station's funds to offset the overall cost.", "Nanotrasen Asset Protection", has_important_message = TRUE) + + addtimer(CALLBACK(src, PROC_REF(handle_target), sent_mob), 1.5 SECONDS) + + if(sent_mob != target) + fail_objective(penalty_cost = telecrystal_penalty) + source.startExitSequence(source) + return + + if(sent_mob.stat != DEAD) + telecrystal_reward += alive_bonus + + succeed_objective() + source.startExitSequence(source) + +/datum/traitor_objective/target_player/kidnapping/proc/handle_target(mob/living/carbon/human/sent_mob) + addtimer(CALLBACK(src, PROC_REF(return_target), sent_mob), 3 MINUTES) + if(sent_mob.stat == DEAD) + return + + sent_mob.flash_act() + sent_mob.adjust_confusion(10 SECONDS) + sent_mob.adjust_dizzy(10 SECONDS) + sent_mob.set_eye_blur_if_lower(100 SECONDS) + sent_mob.dna.species.give_important_for_life(sent_mob) // so plasmamen do not get left for dead + to_chat(sent_mob, span_hypnophrase(span_reallybig("A million voices echo in your head... \"Your mind held many valuable secrets - \ + we thank you for providing them. Your value is expended, and you will be ransomed back to your station. We always get paid, \ + so it's only a matter of time before we ship you back...\""))) + +/datum/traitor_objective/target_player/kidnapping/proc/return_target(mob/living/carbon/human/sent_mob) + if(!sent_mob || QDELETED(sent_mob)) //suicided and qdeleted themselves + return + + var/list/possible_turfs = list() + for(var/turf/open/open_turf in dropoff_area) + if(open_turf.is_blocked_turf() || isspaceturf(open_turf)) + continue + possible_turfs += open_turf + + if(!LAZYLEN(possible_turfs)) + var/turf/new_turf = get_safe_random_station_turf() + if(!new_turf) //SOMEHOW + to_chat(sent_mob, span_hypnophrase(span_reallybig("A million voices echo in your head... \"Seems where you got sent here from won't \ + be able to handle our pod... You will die here instead.\""))) + if (sent_mob.can_heartattack()) + sent_mob.set_heartattack(TRUE) + return + + possible_turfs += new_turf + + var/obj/structure/closet/supplypod/return_pod = new() + return_pod.bluespace = TRUE + return_pod.explosionSize = list(0,0,0,0) + return_pod.style = STYLE_SYNDICATE + + do_sparks(8, FALSE, sent_mob) + sent_mob.visible_message(span_notice("[sent_mob] vanishes!")) + for(var/obj/item/belonging in gather_belongings(sent_mob)) + if(belonging == sent_mob.get_item_by_slot(ITEM_SLOT_ICLOTHING) || belonging == sent_mob.get_item_by_slot(ITEM_SLOT_FEET)) + continue + sent_mob.dropItemToGround(belonging) // No souvenirs, except shoes and t-shirts + + for(var/obj/item/belonging in target_belongings) + belonging.forceMove(return_pod) + + sent_mob.forceMove(return_pod) + sent_mob.flash_act() + sent_mob.adjust_confusion(10 SECONDS) + sent_mob.adjust_dizzy(10 SECONDS) + sent_mob.set_eye_blur_if_lower(100 SECONDS) + sent_mob.dna.species.give_important_for_life(sent_mob) // so plasmamen do not get left for dead + + new /obj/effect/pod_landingzone(pick(possible_turfs), return_pod) + +/// Returns a list of things that the provided mob has which we would rather that they do not have +/datum/traitor_objective/target_player/kidnapping/proc/gather_belongings(mob/living/carbon/human/kidnapee) + var/list/belongings = kidnapee.get_all_gear() + for (var/obj/item/implant/storage/internal_bag in kidnapee.implants) + belongings += internal_bag.contents + return belongings diff --git a/monkestation/code/modules/antagonists/traitor/traitor_objective.dm b/monkestation/code/modules/antagonists/traitor/traitor_objective.dm index f728ec22b2ff..9d0c0e802c2f 100644 --- a/monkestation/code/modules/antagonists/traitor/traitor_objective.dm +++ b/monkestation/code/modules/antagonists/traitor/traitor_objective.dm @@ -1,3 +1,5 @@ /datum/traitor_objective ///a bitfield for what types of uplinks can gain this objective - var/valid_uplinks = ALL //this is a secret tool that will help us later + var/valid_uplinks = UPLINK_TRAITORS //this is a secret tool that will help us later + ///how much contractor rep this gives for completion + var/given_contractor_rep diff --git a/monkestation/code/modules/antagonists/traitor/uplink_handler.dm b/monkestation/code/modules/antagonists/traitor/uplink_handler.dm index 4848d52468e5..98f9657b6213 100644 --- a/monkestation/code/modules/antagonists/traitor/uplink_handler.dm +++ b/monkestation/code/modules/antagonists/traitor/uplink_handler.dm @@ -1,8 +1,28 @@ /datum/uplink_handler /// Extra stuff that cannot be purchased by an uplink, regardless of flag. var/list/locked_entries = list() + ///how much contractor rep we have + var/contractor_rep = 10 //SET THIS BACK TO 0 + ///list of our contractor market items + var/list/contractor_market_items = list() + ///list of purchased contractor items + var/list/purchased_contractor_items = list() ///Add items to our locked_entries /datum/uplink_handler/proc/add_locked_entries(list/items_to_add) for(var/datum/uplink_item/item as anything in items_to_add) locked_entries |= item + +///Clear a handler's potential_objectives +/** + * fail_active - should we also call fail_objective() their active_objectives + * regenerate_objectives - should we let their objectives regenerate or not + */ +/datum/uplink_handler/proc/clear_secondaries(fail_active = FALSE, regenerate_objectives = FALSE) + var/original_max = maximum_potential_objectives + if(!regenerate_objectives) + maximum_potential_objectives = 0 //janky, but it needs the least new code and should work with what this proc does + + for(var/datum/traitor_objective/possible_objective in potential_objectives + (fail_active ? active_objectives : list())) + possible_objective.fail_objective() + maximum_potential_objectives = original_max diff --git a/monkestation/code/modules/uplink/uplink_items/bundle.dm b/monkestation/code/modules/uplink/uplink_items/bundle.dm index 7687174e936e..86e2496adf42 100644 --- a/monkestation/code/modules/uplink/uplink_items/bundle.dm +++ b/monkestation/code/modules/uplink/uplink_items/bundle.dm @@ -1,6 +1,18 @@ /datum/uplink_item/bundles_tc/contract_kit name = "Contractor Bundle" desc = "A box containing everything you need to take contracts from the Syndicate. Kidnap people and drop them off at specified locations for rewards in the form of Telecrystals \ - (Usable in the provided uplink) and Contractor Points. Can not be bought if you have completed any secondary objectives." - item = /obj/item/storage/box/syndicate/contract_kit + (Usable in the provided uplink) and Contractor Points. Can not be bought if you have taken any secondary objectives." + item = /obj/item/storage/box/syndie_kit/contract_kit cost = 20 + purchasable_from = UPLINK_TRAITORS + +/datum/uplink_item/bundles_tc/contract_kit/unique_checks(mob/user, datum/uplink_handler/handler, atom/movable/source) + if(length(handler.completed_objectives) || length(handler.active_objectives) || !handler.can_take_objectives || !handler.has_objectives) + return FALSE + return TRUE + +/datum/uplink_item/bundles_tc/contract_kit/purchase(mob/user, datum/uplink_handler/uplink_handler, atom/movable/source) + . = ..() + var/datum/component/uplink/our_uplink = source.GetComponent(/datum/component/uplink) + if(uplink_handler && our_uplink) + our_uplink.become_contractor() diff --git a/monkestation/icons/obj/clothing/modsuits/contractor_modsuit.dmi b/monkestation/icons/obj/clothing/modsuits/modsuit.dmi similarity index 100% rename from monkestation/icons/obj/clothing/modsuits/contractor_modsuit.dmi rename to monkestation/icons/obj/clothing/modsuits/modsuit.dmi diff --git a/tgstation.dme b/tgstation.dme index 9c8e2f1d3e32..37ef1e5acf45 100644 --- a/tgstation.dme +++ b/tgstation.dme @@ -393,6 +393,7 @@ #include "code\__DEFINES\~monkestation\status_effects.dm" #include "code\__DEFINES\~monkestation\storytellers.dm" #include "code\__DEFINES\~monkestation\traits.dm" +#include "code\__DEFINES\~monkestation\uplink.dm" #include "code\__DEFINES\~monkestation\dcs\signals\signals_atom.dm" #include "code\__DEFINES\~monkestation\dcs\signals\signals_carbon.dm" #include "code\__DEFINES\~monkestation\dcs\signals\signals_traitor.dm" @@ -5670,7 +5671,6 @@ #include "monkestation\code\modules\antagonists\clock_cult\structures\traps\senders\lever.dm" #include "monkestation\code\modules\antagonists\clock_cult\structures\traps\senders\pressure_sensor.dm" #include "monkestation\code\modules\antagonists\contractor\datums\contractor_datum.dm" -#include "monkestation\code\modules\antagonists\contractor\datums\contractor_hub.dm" #include "monkestation\code\modules\antagonists\contractor\datums\contractor_items.dm" #include "monkestation\code\modules\antagonists\contractor\datums\contractor_support.dm" #include "monkestation\code\modules\antagonists\contractor\datums\mind_datum.dm" @@ -5702,11 +5702,12 @@ #include "monkestation\code\modules\antagonists\slasher\slasher_outfit\slasher_footwear.dm" #include "monkestation\code\modules\antagonists\slasher\slasher_outfit\slasher_headgear.dm" #include "monkestation\code\modules\antagonists\slasher\slasher_outfit\slasher_middlewear.dm" -#include "monkestation\code\modules\antagonists\traitor\datum_traitor.dm" #include "monkestation\code\modules\antagonists\traitor\traitor_objective.dm" #include "monkestation\code\modules\antagonists\traitor\uplink_handler.dm" +#include "monkestation\code\modules\antagonists\traitor\objectives\kidnapping.dm" #include "monkestation\code\modules\antagonists\traitor\objectives\tide_bug_department.dm" #include "monkestation\code\modules\antagonists\traitor\objectives\final_objective\become_wizard.dm" +#include "monkestation\code\modules\antagonists\traitor\objectives\final_objective\final_objective.dm" #include "monkestation\code\modules\antagonists\wizard\equipment\artefact.dm" #include "monkestation\code\modules\antagonists\wizard\equipment\spellbook_entries\defensive.dm" #include "monkestation\code\modules\antagonists\wizard\equipment\spellbook_entries\mobility.dm" diff --git a/tgui/packages/tgui/interfaces/Uplink/ContractorMenu.tsx b/tgui/packages/tgui/interfaces/Uplink/ContractorMenu.tsx new file mode 100644 index 000000000000..6d7bd74ecc03 --- /dev/null +++ b/tgui/packages/tgui/interfaces/Uplink/ContractorMenu.tsx @@ -0,0 +1,64 @@ +import { useBackend } from '../../backend'; +import { Box, Button, Icon, Section, Table } from '../../components'; + +export type ContractorItem = { + id: string; + name: string; + desc: string; + cost: number; + stock: number; + item_icon: string; +}; + +type ContractorMenuProps = { + items: ContractorItem[]; + rep: number; +}; + +export const ContractorMenu = (props: ContractorMenuProps, context) => { + const { act, data } = useBackend(context); + const contractor_hub_items = props.items || []; + return ( +
+ Reputation: {props.rep} + {contractor_hub_items.map((item) => { + const repInfo = item.cost ? item.cost + ' Rep' : 'FREE'; + const stock = item.stock !== -1; + return ( +
+ {stock && ( + + {item.stock} remaining + + )} +
+ ); + })} +
+ ); +}; diff --git a/tgui/packages/tgui/interfaces/Uplink/ObjectiveMenu.tsx b/tgui/packages/tgui/interfaces/Uplink/ObjectiveMenu.tsx index 8e932cf10934..ecc1b439e691 100644 --- a/tgui/packages/tgui/interfaces/Uplink/ObjectiveMenu.tsx +++ b/tgui/packages/tgui/interfaces/Uplink/ObjectiveMenu.tsx @@ -13,6 +13,7 @@ export type Objective = { progression_reward: number; telecrystal_reward: number; telecrystal_penalty: number; + contractor_rep?: number; ui_buttons?: ObjectiveUiButton[]; objective_state: ObjectiveState; original_progression: number; @@ -290,6 +291,7 @@ const ObjectiveFunction = ( telecrystalReward={objective.telecrystal_reward} telecrystalPenalty={objective.telecrystal_penalty} progressionReward={objective.progression_reward} + contractorRep={objective.contractor_rep} objectiveState={objective.objective_state} originalProgression={objective.original_progression} hideTcRep={objective.final_objective} @@ -339,6 +341,7 @@ type ObjectiveElementProps = { description: string; telecrystalReward: number; progressionReward: number; + contractorRep?: number; uiButtons?: InfernoNode; objectiveState?: ObjectiveState; originalProgression: number; @@ -360,6 +363,7 @@ export const ObjectiveElement = (props: ObjectiveElementProps, context) => { uiButtons = null, telecrystalReward, progressionReward, + contractorRep, objectiveState, telecrystalPenalty, handleCompletion, @@ -457,6 +461,7 @@ export const ObjectiveElement = (props: ObjectiveElementProps, context) => { width="100%" textAlign="center"> {telecrystalReward} TC, + {!!contractorRep ? ' ' + contractorRep + ' REP,' : ''} {calculateProgression(progressionReward)} Threat Level {Math.abs(progressionDiff) > 10 && ( diff --git a/tgui/packages/tgui/interfaces/Uplink/index.tsx b/tgui/packages/tgui/interfaces/Uplink/index.tsx index fe2aa6b0d08b..3d35b56e4281 100644 --- a/tgui/packages/tgui/interfaces/Uplink/index.tsx +++ b/tgui/packages/tgui/interfaces/Uplink/index.tsx @@ -8,6 +8,7 @@ import { BooleanLike } from 'common/react'; import { Box, Tabs, Button, Stack, Section, Tooltip, Dimmer } from '../../components'; import { PrimaryObjectiveMenu } from './PrimaryObjectiveMenu'; import { Objective, ObjectiveMenu } from './ObjectiveMenu'; +import { ContractorItem, ContractorMenu } from './ContractorMenu'; import { calculateProgression, calculateDangerLevel, dangerDefault, dangerLevelsTooltip } from './calculateDangerLevel'; type UplinkItem = { @@ -60,6 +61,9 @@ type UplinkData = { purchased_items: number; shop_locked: BooleanLike; locked_entries: string[]; + is_contractor: BooleanLike; + contractor_items: ContractorItem[]; + contractor_rep: number; }; type UplinkState = { @@ -178,6 +182,9 @@ export class Uplink extends Component<{}, UplinkState> { purchased_items, shop_locked, locked_entries, + is_contractor, + contractor_items, + contractor_rep, } = data; const { allItems, allCategories, currentTab } = this.state as UplinkState; @@ -359,9 +366,16 @@ export class Uplink extends Component<{}, UplinkState> { )} + {!!is_contractor && ( + this.setState({ currentTab: 2 })}> + Contractor Market + + )} this.setState({ currentTab: 2 })}> + selected={currentTab === 3 || !has_objectives} + onClick={() => this.setState({ currentTab: 3 })}> Market @@ -419,6 +433,12 @@ export class Uplink extends Component<{}, UplinkState> { } handleRequestObjectives={() => act('regenerate_objectives')} /> + )) || + (currentTab === 2 && is_contractor && ( + )) || (