mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2026-07-11 08:06:33 +01:00
[BOUNTY] Re-adds Contractors (#79737)
## About The Pull Request Adds Contractors back to the game as a kit that Infiltrators (Only midround/latejoin Traitors, not roundstart) can buy. Buying this will give you access to the new Contractor items in the uplink (which replaces the Contractor shop). I've also refactored things about contractor and how it's handled, such as removed its sleep calls, swapping its UI to tsx, making it actually functional within more modern TG code and the reworked Traitors as a whole, among other things. I also fixed the contractor guide paper (the text was broken) and made contractor kit boxes no longer empty. Contractor items only appear once the contractor kit is purchased, but they can't be bought until you make an account. Video demonstration https://github.com/tgstation/tgstation/assets/53777086/c6aed4e8-bbd4-4ba0-b6a2-9f58fd308d09 Regular Traitors can't access it  The Contractor UI (Modified to not have a shop anymore) - Ignore the Invalid Targets, those appear when there's no possible targets  Roundend report  ## Why It's Good For The Game Contractor was a fun way of playing Traitor that isn't relying on RNG objectives to pop up, this is instead constant stream of content for the contractor that encourages non-lethal play, and is now a viable alternative now that Infiltrators don't have Reputation anymore. Link to bounty: https://tgstation13.org/phpBB/viewtopic.php?f=5&t=35160 Relevant image from bounty  ## Changelog 🆑 add: Infiltrators (Latejoin/Midround traitors) can now buy and use Contract kits again. del: Contractor baton can now only be purchased once. /🆑 --------- Co-authored-by: Jacquerel <hnevard@gmail.com>
This commit is contained in:
@@ -48,7 +48,7 @@
|
||||
|
||||
///Flag of the type of device the modular computer is, deciding what types of apps it can run.
|
||||
var/hardware_flag = NONE
|
||||
// Options: PROGRAM_ALL | PROGRAM_CONSOLE | PROGRAM_LAPTOP | PROGRAM_TABLET
|
||||
// Options: PROGRAM_ALL | PROGRAM_CONSOLE | PROGRAM_LAPTOP | PROGRAM_PDA
|
||||
|
||||
///The theme, used for the main menu and file browser apps.
|
||||
var/device_theme = PDA_THEME_NTOS
|
||||
|
||||
@@ -6,3 +6,6 @@
|
||||
|
||||
/obj/item/computer_disk/syndicate/camera_app
|
||||
starting_programs = list(/datum/computer_file/program/secureye/syndicate)
|
||||
|
||||
/obj/item/computer_disk/syndicate/contractor
|
||||
starting_programs = list(/datum/computer_file/program/contract_uplink)
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
icon_state_menu = "menu"
|
||||
max_capacity = 64
|
||||
allow_chunky = TRUE
|
||||
hardware_flag = PROGRAM_TABLET
|
||||
hardware_flag = PROGRAM_PDA
|
||||
max_idle_programs = 2
|
||||
w_class = WEIGHT_CLASS_SMALL
|
||||
slot_flags = ITEM_SLOT_ID | ITEM_SLOT_BELT
|
||||
@@ -272,6 +272,19 @@
|
||||
if(msg)
|
||||
msg.invisible = TRUE
|
||||
|
||||
/obj/item/modular_computer/pda/syndicate_contract_uplink
|
||||
name = "contractor tablet"
|
||||
device_theme = PDA_THEME_SYNDICATE
|
||||
icon_state_menu = "contractor-assign"
|
||||
comp_light_luminosity = 6.3
|
||||
has_pda_programs = FALSE
|
||||
greyscale_config = /datum/greyscale_config/tablet/stripe_double
|
||||
greyscale_colors = "#696969#000000#FFA500"
|
||||
|
||||
starting_programs = list(
|
||||
/datum/computer_file/program/contract_uplink,
|
||||
)
|
||||
|
||||
/**
|
||||
* Silicon PDA
|
||||
*
|
||||
|
||||
@@ -44,7 +44,7 @@ This is how the base program is setup. the rest is mostly tgui stuff. I'll use t
|
||||
/// ditto but on emagged syndie net. Use this for antag programs
|
||||
available_on_syndinet = 0
|
||||
|
||||
/// Bitflags (PROGRAM_CONSOLE, PROGRAM_LAPTOP, PROGRAM_TABLET combination)
|
||||
/// Bitflags (PROGRAM_CONSOLE, PROGRAM_LAPTOP, PROGRAM_PDA combination)
|
||||
/// or PROGRAM_ALL. Use this to limit what kind of machines can run the
|
||||
/// program. For example, comms program should be limited to consoles and laptops.
|
||||
usage_flags = PROGRAM_ALL
|
||||
|
||||
@@ -28,7 +28,7 @@
|
||||
var/requires_ntnet = FALSE
|
||||
/// NTNet status, updated every tick by computer running this program. Don't use this for checks if NTNet works, computers do that. Use this for calculations, etc.
|
||||
var/ntnet_status = 1
|
||||
/// Bitflags (PROGRAM_CONSOLE, PROGRAM_LAPTOP, PROGRAM_TABLET combination) or PROGRAM_ALL
|
||||
/// Bitflags (PROGRAM_CONSOLE, PROGRAM_LAPTOP, PROGRAM_PDA combination) or PROGRAM_ALL
|
||||
var/usage_flags = PROGRAM_ALL
|
||||
/// Whether the program can be downloaded from NTNet. Set to FALSE to disable.
|
||||
var/available_on_ntnet = TRUE
|
||||
|
||||
@@ -0,0 +1,173 @@
|
||||
/datum/computer_file/program/contract_uplink
|
||||
filename = "contractor uplink"
|
||||
filedesc = "Syndicate Contractor Uplink"
|
||||
extended_desc = "A standard, Syndicate issued system for handling important contracts while on the field."
|
||||
category = PROGRAM_CATEGORY_MISC
|
||||
program_icon_state = "contractor-assign"
|
||||
program_icon = "tasks"
|
||||
size = 10
|
||||
|
||||
requires_ntnet = FALSE
|
||||
available_on_ntnet = FALSE
|
||||
available_on_syndinet = FALSE
|
||||
usage_flags = PROGRAM_PDA //this is all we've got sprites for :sob:
|
||||
unique_copy = TRUE
|
||||
undeletable = TRUE
|
||||
tgui_id = "SyndicateContractor"
|
||||
|
||||
///The traitor datum stored on the program. Starts off as null and is set by the player.
|
||||
var/datum/antagonist/traitor/traitor_data
|
||||
///The error screen sent to the UI so they can show the player.
|
||||
var/error = ""
|
||||
///Boolean on whether the UI is on the Information screen.
|
||||
var/info_screen = TRUE
|
||||
///Boolean on whether the program is being loaded for the first time, for a unique screen animation.
|
||||
var/first_load = TRUE
|
||||
|
||||
/datum/computer_file/program/contract_uplink/clone()
|
||||
var/datum/computer_file/program/contract_uplink/temp = ..()
|
||||
temp.traitor_data = traitor_data
|
||||
return temp
|
||||
|
||||
/datum/computer_file/program/contract_uplink/Destroy(force)
|
||||
traitor_data = null
|
||||
return ..()
|
||||
|
||||
/datum/computer_file/program/contract_uplink/ui_act(action, params)
|
||||
. = ..()
|
||||
if(.)
|
||||
return
|
||||
|
||||
var/mob/living/user = usr
|
||||
|
||||
switch(action)
|
||||
if("PRG_contract-accept")
|
||||
var/contract_id = text2num(params["contract_id"])
|
||||
traitor_data.uplink_handler.contractor_hub.assigned_contracts[contract_id].status = CONTRACT_STATUS_ACTIVE
|
||||
traitor_data.uplink_handler.contractor_hub.current_contract = traitor_data.uplink_handler.contractor_hub.assigned_contracts[contract_id]
|
||||
program_icon_state = "contractor-contract"
|
||||
return TRUE
|
||||
|
||||
if("PRG_login")
|
||||
var/datum/antagonist/traitor/traitor_user = user.mind.has_antag_datum(/datum/antagonist/traitor)
|
||||
if(!traitor_user)
|
||||
error = "UNAUTHORIZED USER"
|
||||
return TRUE
|
||||
|
||||
traitor_data = traitor_user
|
||||
if(!traitor_data.uplink_handler.contractor_hub)
|
||||
traitor_data.uplink_handler.contractor_hub = new
|
||||
traitor_data.uplink_handler.contractor_hub.create_contracts(traitor_user.owner)
|
||||
user.playsound_local(user, 'sound/effects/contractstartup.ogg', 100, FALSE)
|
||||
program_icon_state = "contractor-contractlist"
|
||||
return TRUE
|
||||
|
||||
if("PRG_call_extraction")
|
||||
if (traitor_data.uplink_handler.contractor_hub.current_contract.status != CONTRACT_STATUS_EXTRACTING)
|
||||
if (traitor_data.uplink_handler.contractor_hub.current_contract.handle_extraction(user))
|
||||
user.playsound_local(user, 'sound/effects/confirmdropoff.ogg', 100, TRUE)
|
||||
traitor_data.uplink_handler.contractor_hub.current_contract.status = CONTRACT_STATUS_EXTRACTING
|
||||
|
||||
program_icon_state = "contractor-extracted"
|
||||
else
|
||||
user.playsound_local(user, 'sound/machines/uplinkerror.ogg', 50)
|
||||
error = "Either both you or your target aren't at the dropoff location, or the pod hasn't got a valid place to land. Clear space, or make sure you're both inside."
|
||||
else
|
||||
user.playsound_local(user, 'sound/machines/uplinkerror.ogg', 50)
|
||||
error = "Already extracting... Place the target into the pod. If the pod was destroyed, this contract is no longer possible."
|
||||
|
||||
return TRUE
|
||||
if("PRG_contract_abort")
|
||||
var/contract_id = traitor_data.uplink_handler.contractor_hub.current_contract.id
|
||||
|
||||
traitor_data.uplink_handler.contractor_hub.current_contract = null
|
||||
traitor_data.uplink_handler.contractor_hub.assigned_contracts[contract_id].status = CONTRACT_STATUS_ABORTED
|
||||
|
||||
program_icon_state = "contractor-contractlist"
|
||||
|
||||
return TRUE
|
||||
if("PRG_redeem_TC")
|
||||
if (traitor_data.uplink_handler.contractor_hub.contract_TC_to_redeem)
|
||||
var/obj/item/stack/telecrystal/crystals = new /obj/item/stack/telecrystal(get_turf(user), traitor_data.uplink_handler.contractor_hub.contract_TC_to_redeem)
|
||||
if(ishuman(user))
|
||||
var/mob/living/carbon/human/H = user
|
||||
if(H.put_in_hands(crystals))
|
||||
to_chat(H, span_notice("Your payment materializes into your hands!"))
|
||||
else
|
||||
to_chat(user, span_notice("Your payment materializes onto the floor."))
|
||||
|
||||
traitor_data.uplink_handler.contractor_hub.contract_TC_payed_out += traitor_data.uplink_handler.contractor_hub.contract_TC_to_redeem
|
||||
traitor_data.uplink_handler.contractor_hub.contract_TC_to_redeem = 0
|
||||
return TRUE
|
||||
else
|
||||
user.playsound_local(user, 'sound/machines/uplinkerror.ogg', 50)
|
||||
return TRUE
|
||||
if ("PRG_clear_error")
|
||||
error = ""
|
||||
return TRUE
|
||||
if("PRG_set_first_load_finished")
|
||||
first_load = FALSE
|
||||
return TRUE
|
||||
if("PRG_toggle_info")
|
||||
info_screen = !info_screen
|
||||
return TRUE
|
||||
|
||||
/datum/computer_file/program/contract_uplink/ui_data(mob/user)
|
||||
var/list/data = list()
|
||||
|
||||
data["first_load"] = first_load
|
||||
data["logged_in"] = !!traitor_data
|
||||
data["station_name"] = GLOB.station_name
|
||||
data["info_screen"] = info_screen
|
||||
data["error"] = error
|
||||
|
||||
if(!traitor_data)
|
||||
data["ongoing_contract"] = FALSE
|
||||
data["extraction_enroute"] = FALSE
|
||||
update_computer_icon()
|
||||
return data
|
||||
|
||||
data["ongoing_contract"] = !!traitor_data.uplink_handler.contractor_hub.current_contract
|
||||
if(traitor_data.uplink_handler.contractor_hub.current_contract)
|
||||
program_icon_state = "contractor-contract"
|
||||
if (traitor_data.uplink_handler.contractor_hub.current_contract.status == CONTRACT_STATUS_EXTRACTING)
|
||||
data["extraction_enroute"] = TRUE
|
||||
program_icon_state = "contractor-extracted"
|
||||
else
|
||||
data["extraction_enroute"] = FALSE
|
||||
var/turf/curr = get_turf(user)
|
||||
var/turf/dropoff_turf
|
||||
data["current_location"] = "[get_area_name(curr, TRUE)]"
|
||||
for (var/turf/content in traitor_data.uplink_handler.contractor_hub.current_contract.contract.dropoff.contents)
|
||||
if (isturf(content))
|
||||
dropoff_turf = content
|
||||
break
|
||||
var/direction
|
||||
if(curr.z == dropoff_turf.z) //Direction calculations for same z-level only
|
||||
direction = uppertext(dir2text(get_dir(curr, dropoff_turf))) //Direction text (East, etc). Not as precise, but still helpful.
|
||||
if(get_area(user) == traitor_data.uplink_handler.contractor_hub.current_contract.contract.dropoff)
|
||||
direction = "LOCATION CONFIRMED"
|
||||
else
|
||||
direction = "???"
|
||||
data["dropoff_direction"] = direction
|
||||
data["redeemable_tc"] = traitor_data.uplink_handler.contractor_hub.contract_TC_to_redeem
|
||||
data["earned_tc"] = traitor_data.uplink_handler.contractor_hub.contract_TC_payed_out
|
||||
data["contracts_completed"] = traitor_data.uplink_handler.contractor_hub.contracts_completed
|
||||
for (var/datum/syndicate_contract/contract in traitor_data.uplink_handler.contractor_hub.assigned_contracts)
|
||||
if(!contract.contract)
|
||||
stack_trace("Syndiate contract with null contract objective found in [traitor_data.owner]'s contractor hub!")
|
||||
contract.status = CONTRACT_STATUS_ABORTED
|
||||
continue
|
||||
data["contracts"] += list(list(
|
||||
"target" = contract.contract.target,
|
||||
"target_rank" = contract.target_rank,
|
||||
"payout" = contract.contract.payout,
|
||||
"payout_bonus" = contract.contract.payout_bonus,
|
||||
"dropoff" = contract.contract.dropoff,
|
||||
"id" = contract.id,
|
||||
"status" = contract.status,
|
||||
"message" = contract.wanted_message,
|
||||
))
|
||||
|
||||
update_computer_icon()
|
||||
return data
|
||||
@@ -57,7 +57,7 @@
|
||||
var/list/data = list()
|
||||
var/turf/turf = get_turf(computer)
|
||||
data["atmozphereMode"] = atmozphere_mode
|
||||
data["clickAtmozphereCompatible"] = (computer.hardware_flag & PROGRAM_TABLET)
|
||||
data["clickAtmozphereCompatible"] = (computer.hardware_flag & PROGRAM_PDA)
|
||||
switch (atmozphere_mode) //Null air wont cause errors, don't worry.
|
||||
if(ATMOZPHERE_SCAN_ENV)
|
||||
var/datum/gas_mixture/air = turf?.return_air()
|
||||
@@ -74,7 +74,7 @@
|
||||
atmozphere_mode = ATMOZPHERE_SCAN_ENV
|
||||
UnregisterSignal(computer, COMSIG_ITEM_ATTACK_SELF_SECONDARY)
|
||||
return TRUE
|
||||
if(!(computer.hardware_flag & PROGRAM_TABLET))
|
||||
if(!(computer.hardware_flag & PROGRAM_PDA))
|
||||
computer.say("Device incompatible for scanning objects!")
|
||||
return FALSE
|
||||
atmozphere_mode = ATMOZPHERE_SCAN_CLICK
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
program_icon_state = "request"
|
||||
extended_desc = "Nanotrasen Internal Requisition Network interface for supply purchasing using a department budget account."
|
||||
requires_ntnet = TRUE
|
||||
usage_flags = PROGRAM_LAPTOP | PROGRAM_TABLET
|
||||
usage_flags = PROGRAM_LAPTOP | PROGRAM_PDA
|
||||
size = 10
|
||||
tgui_id = "NtosCargo"
|
||||
///Are you actually placing orders with it?
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
category = PROGRAM_CATEGORY_MISC
|
||||
extended_desc = "This program allows the taking of pictures."
|
||||
size = 4
|
||||
usage_flags = PROGRAM_TABLET
|
||||
usage_flags = PROGRAM_PDA
|
||||
tgui_id = "NtosCamera"
|
||||
program_icon = "camera"
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
category = PROGRAM_CATEGORY_MISC
|
||||
extended_desc = "This program allows the tablet to scan physical objects and display a data output."
|
||||
size = 2
|
||||
usage_flags = PROGRAM_TABLET
|
||||
usage_flags = PROGRAM_PDA
|
||||
tgui_id = "NtosPhysScanner"
|
||||
program_icon = "barcode"
|
||||
/// Information from the last scanned person, to display on the app.
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
undeletable = TRUE // It comes by default in tablets, can't be downloaded, takes no space and should obviously not be able to be deleted.
|
||||
header_program = TRUE
|
||||
available_on_ntnet = FALSE
|
||||
usage_flags = PROGRAM_TABLET
|
||||
usage_flags = PROGRAM_PDA
|
||||
ui_header = "ntnrc_idle.gif"
|
||||
tgui_id = "NtosMessenger"
|
||||
program_icon = "comment-alt"
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
program_icon_state = "radarntos"
|
||||
requires_ntnet = TRUE
|
||||
available_on_ntnet = FALSE
|
||||
usage_flags = PROGRAM_LAPTOP | PROGRAM_TABLET
|
||||
usage_flags = PROGRAM_LAPTOP | PROGRAM_PDA
|
||||
size = 5
|
||||
tgui_id = "NtosRadar"
|
||||
///List of trackable entities. Updated by the scan() proc.
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
program_icon_state = "crew"
|
||||
tgui_id = "NtosRecords"
|
||||
size = 4
|
||||
usage_flags = PROGRAM_TABLET | PROGRAM_LAPTOP
|
||||
usage_flags = PROGRAM_PDA | PROGRAM_LAPTOP
|
||||
available_on_ntnet = FALSE
|
||||
detomatix_resistance = DETOMATIX_RESIST_MINOR
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
requires_ntnet = FALSE
|
||||
available_on_ntnet = FALSE
|
||||
undeletable = TRUE
|
||||
usage_flags = PROGRAM_TABLET
|
||||
usage_flags = PROGRAM_PDA
|
||||
size = 5
|
||||
tgui_id = "NtosRobotact"
|
||||
program_icon = "terminal"
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
size = 2
|
||||
tgui_id = "NtosSignaler"
|
||||
program_icon = "satellite-dish"
|
||||
usage_flags = PROGRAM_TABLET | PROGRAM_LAPTOP
|
||||
usage_flags = PROGRAM_PDA | PROGRAM_LAPTOP
|
||||
///What is the saved signal frequency?
|
||||
var/signal_frequency = FREQ_SIGNALER
|
||||
/// What is the saved signal code?
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
size = 2
|
||||
tgui_id = "NtosSkillTracker"
|
||||
program_icon = "medal"
|
||||
usage_flags = PROGRAM_TABLET // Must be a handheld device to read read your chakras or whatever
|
||||
usage_flags = PROGRAM_PDA // Must be a handheld device to read read your chakras or whatever
|
||||
|
||||
/datum/computer_file/program/skill_tracker/ui_data(mob/user)
|
||||
var/list/data = list()
|
||||
|
||||
Reference in New Issue
Block a user