diff --git a/code/__DEFINES/role_preferences.dm b/code/__DEFINES/role_preferences.dm index e7ebc19c682..90e3f328f6e 100644 --- a/code/__DEFINES/role_preferences.dm +++ b/code/__DEFINES/role_preferences.dm @@ -86,6 +86,7 @@ #define ROLE_SLAUGHTER_DEMON "Slaughter Demon" #define ROLE_WIZARD_APPRENTICE "apprentice" #define ROLE_SYNDICATE_MONKEY "Syndicate Monkey Agent" +#define ROLE_CONTRACTOR_SUPPORT "Contractor Support Unit" //Spawner roles #define ROLE_ANCIENT_CREW "Ancient Crew" diff --git a/code/modules/antagonists/_common/antag_spawner.dm b/code/modules/antagonists/_common/antag_spawner.dm index 6ff809b59cb..9ef40a9cebf 100644 --- a/code/modules/antagonists/_common/antag_spawner.dm +++ b/code/modules/antagonists/_common/antag_spawner.dm @@ -332,7 +332,15 @@ return to_chat(user, span_notice("You activate [src] and wait for confirmation.")) - var/list/baddie_candidates = SSpolling.poll_ghost_candidates("Do you want to play as a [role_to_play]?", check_jobban = poll_role_check, role = poll_role_check, poll_time = 10 SECONDS, ignore_category = poll_ignore_category, pic_source = src, role_name_text = role_to_play) + var/list/baddie_candidates = SSpolling.poll_ghost_candidates( + "Do you want to play as a [role_to_play]?", + check_jobban = poll_role_check, + role = poll_role_check, + poll_time = 10 SECONDS, + ignore_category = poll_ignore_category, + pic_source = src, + role_name_text = role_to_play, + ) if(!LAZYLEN(baddie_candidates)) to_chat(user, span_warning(fail_text)) return @@ -359,7 +367,7 @@ else spawned_mob.forceMove(locate(1,1,1)) - antag_datum = new() + op_mind.add_antag_datum(antag_datum) if(ishuman(spawned_mob)) var/mob/living/carbon/human/human_mob = spawned_mob @@ -373,6 +381,21 @@ spawned_mob.forceMove(pod) new /obj/effect/pod_landingzone(get_turf(src), pod) +/obj/item/antag_spawner/loadout/contractor + name = "contractor support beacon" + desc = "A beacon sold to the most prestigeous syndicate members, a single-use radio for calling immediate backup." + icon = 'icons/obj/devices/voice.dmi' + icon_state = "nukietalkie" + outfit = /datum/outfit/contractor_partner + use_subtypes = FALSE + antag_datum = /datum/antagonist/traitor/contractor_support + poll_ignore_category = ROLE_TRAITOR + role_to_play = ROLE_CONTRACTOR_SUPPORT + +/obj/item/antag_spawner/loadout/contractor/do_special_things(mob/living/carbon/human/contractor_support, mob/user) + to_chat(contractor_support, "\n[span_alertwarning("[user.real_name] is your superior. Follow any, and all orders given by them. You're here to support their mission only.")]") + to_chat(contractor_support, "[span_alertwarning("Should they perish, or be otherwise unavailable, you're to assist other active agents in this mission area to the best of your ability.")]") + /obj/item/antag_spawner/loadout/monkey_man name = "monkey agent beacon" desc = "Call up some backup from ARC for monkey mayhem." diff --git a/code/modules/antagonists/traitor/contractor/contract_teammate.dm b/code/modules/antagonists/traitor/contractor/contract_teammate.dm index 1aebd9fb951..54fc958c1f8 100644 --- a/code/modules/antagonists/traitor/contractor/contract_teammate.dm +++ b/code/modules/antagonists/traitor/contractor/contract_teammate.dm @@ -1,35 +1,8 @@ -///Spawns a contractor partner to a spawning user, with a given key to assign to the new player. -/proc/spawn_contractor_partner(mob/living/user, key) - var/mob/living/carbon/human/partner = new() - var/datum/outfit/contractor_partner/partner_outfit = new() - - partner_outfit.equip(partner) - - var/obj/structure/closet/supplypod/arrival_pod = new(null, STYLE_SYNDICATE) - arrival_pod.explosionSize = list(0,0,0,1) - arrival_pod.bluespace = TRUE - - var/turf/free_location = find_obstruction_free_location(2, user) - - // We really want to send them - if we can't find a nice location just land it on top of them. - if (!free_location) - free_location = get_turf(user) - - partner.forceMove(arrival_pod) - partner.ckey = key - - /// We give a reference to the mind that'll be the support unit - var/datum/antagonist/traitor/contractor_support/new_datum = partner.mind.add_antag_datum(/datum/antagonist/traitor/contractor_support) - - to_chat(partner, "\n[span_alertwarning("[user.real_name] is your superior. Follow any, and all orders given by them. You're here to support their mission only.")]") - to_chat(partner, "[span_alertwarning("Should they perish, or be otherwise unavailable, you're to assist other active agents in this mission area to the best of your ability.")]") - - new /obj/effect/pod_landingzone(free_location, arrival_pod) - return new_datum - /// Support unit gets it's own very basic antag datum for admin logging. /datum/antagonist/traitor/contractor_support name = "Contractor Support Unit" + job_rank = ROLE_CONTRACTOR_SUPPORT + employer = "Contractor Support Unit" show_in_roundend = FALSE give_objectives = TRUE give_uplink = FALSE diff --git a/code/modules/antagonists/traitor/contractor/syndicate_contract.dm b/code/modules/antagonists/traitor/contractor/syndicate_contract.dm index 3f7370031da..6af7a8d81d5 100644 --- a/code/modules/antagonists/traitor/contractor/syndicate_contract.dm +++ b/code/modules/antagonists/traitor/contractor/syndicate_contract.dm @@ -100,16 +100,15 @@ if(traitor_data.uplink_handler.contractor_hub.current_contract == src) traitor_data.uplink_handler.contractor_hub.current_contract = null - if(iscarbon(person_sent)) - for(var/obj/item/person_contents in person_sent.gather_belongings()) - if(ishuman(person_sent)) - var/mob/living/carbon/human/human_sent = person_sent - if(person_contents == human_sent.w_uniform) - continue //So all they're left with are shoes and uniform. - if(person_contents == human_sent.shoes) - continue - person_sent.transferItemToLoc(person_contents) - victim_belongings.Add(WEAKREF(person_contents)) + for(var/obj/item/person_contents as anything in person_sent.gather_belongings()) + if(ishuman(person_sent)) + var/mob/living/carbon/human/human_sent = person_sent + if(person_contents == human_sent.w_uniform) + continue //So all they're left with are shoes and uniform. + if(person_contents == human_sent.shoes) + continue + person_sent.transferItemToLoc(person_contents) + victim_belongings.Add(WEAKREF(person_contents)) var/obj/structure/closet/supplypod/extractionpod/pod = source // Handle the pod returning diff --git a/code/modules/antagonists/traitor/datum_traitor.dm b/code/modules/antagonists/traitor/datum_traitor.dm index d338abca641..ea88c7e4900 100644 --- a/code/modules/antagonists/traitor/datum_traitor.dm +++ b/code/modules/antagonists/traitor/datum_traitor.dm @@ -34,7 +34,7 @@ ///if TRUE, this traitor will always get hijacking as their final objective var/is_hijacker = FALSE - ///the name of the antag flavor this traitor has. + ///the name of the antag flavor this traitor has, set in Traitor's setup if not preset. var/employer ///assoc list of strings set up after employer is given @@ -188,22 +188,23 @@ return ..() /datum/antagonist/traitor/proc/pick_employer() - var/faction = prob(75) ? FLAVOR_FACTION_SYNDICATE : FLAVOR_FACTION_NANOTRASEN - var/list/possible_employers = list() + if(!employer) + var/faction = prob(75) ? FLAVOR_FACTION_SYNDICATE : FLAVOR_FACTION_NANOTRASEN + var/list/possible_employers = list() - possible_employers.Add(GLOB.syndicate_employers, GLOB.nanotrasen_employers) + possible_employers.Add(GLOB.syndicate_employers, GLOB.nanotrasen_employers) - if(istype(ending_objective, /datum/objective/hijack)) - possible_employers -= GLOB.normal_employers - else //escape or martyrdom - possible_employers -= GLOB.hijack_employers + if(istype(ending_objective, /datum/objective/hijack)) + possible_employers -= GLOB.normal_employers + else //escape or martyrdom + possible_employers -= GLOB.hijack_employers - switch(faction) - if(FLAVOR_FACTION_SYNDICATE) - possible_employers -= GLOB.nanotrasen_employers - if(FLAVOR_FACTION_NANOTRASEN) - possible_employers -= GLOB.syndicate_employers - employer = pick(possible_employers) + switch(faction) + if(FLAVOR_FACTION_SYNDICATE) + possible_employers -= GLOB.nanotrasen_employers + if(FLAVOR_FACTION_NANOTRASEN) + possible_employers -= GLOB.syndicate_employers + employer = pick(possible_employers) traitor_flavor = strings(TRAITOR_FLAVOR_FILE, employer) /// Generates a complete set of traitor objectives up to the traitor objective limit, including non-generic objectives such as martyr and hijack. @@ -308,6 +309,7 @@ data["allies"] = traitor_flavor["allies"] data["goal"] = traitor_flavor["goal"] data["has_uplink"] = uplink ? TRUE : FALSE + data["given_uplink"] = give_uplink if(uplink) data["uplink_intro"] = traitor_flavor["uplink"] data["uplink_unlock_info"] = uplink.unlock_text diff --git a/code/modules/uplink/uplink_items/contractor.dm b/code/modules/uplink/uplink_items/contractor.dm index 1364f8b088b..b774d05e59d 100644 --- a/code/modules/uplink/uplink_items/contractor.dm +++ b/code/modules/uplink/uplink_items/contractor.dm @@ -82,28 +82,9 @@ cost = 1 /datum/uplink_item/contractor/partner - name = "Reinforcements" - desc = "Upon purchase we'll contact available units in the area. Should there be an agent free, \ - we'll send them down to assist you immediately. If no units are free, we give a full refund." - item = /obj/effect/gibspawner/generic + name = "Contractor Reinforcement" + desc = "A reinforecment operative will be sent to aid you in your goals, \ + they are paid separately, and will not take a cut from your profits." + item = /obj/item/antag_spawner/loadout/contractor limited_stock = 1 cost = 2 - -/datum/uplink_item/contractor/partner/spawn_item(spawn_path, mob/user, datum/uplink_handler/uplink_handler, atom/movable/source) - to_chat(user, span_notice("The uplink vibrates quietly, connecting to nearby agents...")) - var/list/candidates = SSpolling.poll_ghost_candidates( - question = "Do you want to play as the Contractor Support Unit for [user.real_name]?", - check_jobban = ROLE_TRAITOR, - role = ROLE_TRAITOR, - poll_time = 10 SECONDS, - ignore_category = POLL_IGNORE_CONTRACTOR_SUPPORT, - pic_source = /obj/item/modular_computer/pda/syndicate_contract_uplink, - role_name_text = "contractor support unit", - ) - if(!LAZYLEN(candidates)) - to_chat(user, span_notice("No available agents at this time, please try again later.")) - limited_stock++ - return //bobux no icon - var/mob/dead/observer/selected_player = pick(candidates) - uplink_handler.contractor_hub.contractor_teammate = spawn_contractor_partner(user, selected_player.key) - return source //for log icon diff --git a/strings/antagonist_flavor/traitor_flavor.json b/strings/antagonist_flavor/traitor_flavor.json index 93da8d01374..773d2f55370 100644 --- a/strings/antagonist_flavor/traitor_flavor.json +++ b/strings/antagonist_flavor/traitor_flavor.json @@ -111,5 +111,13 @@ "roundend_report": "was a terrorist from Waffle Corporation.", "ui_theme": "syndicate", "uplink": "You have been provided with a standard uplink to accomplish your task." + }, + "Contractor Support Unit": { + "allies": "You are being sent to help your designated agent. Their allegiences are above all others.", + "goal": "Help your designated agent to the furtest extent you can, their life is above your own.", + "introduction": "You are the Contractor Support Agent.", + "roundend_report": "was a contractor support agent.", + "ui_theme": "syndicate", + "uplink": "You do not come with your own uplink, defer to your agent." } } diff --git a/tgui/packages/tgui/interfaces/AntagInfoTraitor.tsx b/tgui/packages/tgui/interfaces/AntagInfoTraitor.tsx index 049a70313b8..3aea989ac27 100644 --- a/tgui/packages/tgui/interfaces/AntagInfoTraitor.tsx +++ b/tgui/packages/tgui/interfaces/AntagInfoTraitor.tsx @@ -37,6 +37,7 @@ type Info = { has_uplink: BooleanLike; uplink_intro: string; uplink_unlock_info: string; + given_uplink: BooleanLike; objectives: Objective[]; }; @@ -233,7 +234,7 @@ const CodewordsSection = (props) => { // SKYRAT EDIT: change height from 580 to 650 export const AntagInfoTraitor = (props) => { const { data } = useBackend(); - const { theme } = data; + const { theme, given_uplink } = data; return ( @@ -248,9 +249,11 @@ export const AntagInfoTraitor = (props) => { - - - + {!!given_uplink && ( + + + + )}