mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2026-08-27 23:27:34 +01:00
Contractor Uplink tgui-next overhaul (#48453)
* tgui next contractor interface work cleanup more work getting close now final build more stuff for wanted messages rebuild spelling * fixes * rebuild * fix * disable button when contract not active or extraction enroute, disable limited when depleted
This commit is contained in:
@@ -398,6 +398,7 @@ GLOBAL_LIST_INIT(pda_styles, sortList(list(MONO, VT, ORBITRON, SHARE)))
|
||||
#define ARCADE_FILE "arcade.json"
|
||||
#define BOOMER_FILE "boomer.json"
|
||||
#define LOCATIONS_FILE "locations.json"
|
||||
#define WANTED_FILE "wanted_message.json"
|
||||
|
||||
//Fullscreen overlay resolution in tiles.
|
||||
#define FULLSCREEN_OVERLAY_RESOLUTION_X 15
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
#define pick_list(FILE, KEY) (pick(strings(FILE, KEY)))
|
||||
#define pick_list_weighted(FILE, KEY) (pickweight(strings(FILE, KEY)))
|
||||
#define pick_list_replacements(FILE, KEY) (strings_replacement(FILE, KEY))
|
||||
#define json_load(FILE) (json_decode(file2text(FILE)))
|
||||
|
||||
|
||||
@@ -355,11 +355,8 @@
|
||||
var result = ""
|
||||
var total_spent_rep = 0
|
||||
|
||||
var/completed_contracts = 0
|
||||
var/completed_contracts = contractor_hub.contracts_completed
|
||||
var/tc_total = contractor_hub.contract_TC_payed_out + contractor_hub.contract_TC_to_redeem
|
||||
for (var/datum/syndicate_contract/contract in contractor_hub.assigned_contracts)
|
||||
if (contract.status == CONTRACT_STATUS_COMPLETE)
|
||||
completed_contracts++
|
||||
|
||||
var/contractor_item_icons = "" // Icons of purchases
|
||||
var/contractor_support_unit = "" // Set if they had a support unit - and shows appended to their contracts completed
|
||||
|
||||
@@ -35,6 +35,7 @@
|
||||
|
||||
var/list/assigned_targets = list() // used as a blacklist to make sure we're not assigning targets already assigned
|
||||
|
||||
var/contracts_completed = 0
|
||||
var/contract_TC_payed_out = 0 // Keeping track for roundend reporting
|
||||
var/contract_TC_to_redeem = 0 // Used internally and roundend reporting - what TC we have available to cashout.
|
||||
|
||||
@@ -56,8 +57,12 @@
|
||||
CONTRACT_PAYOUT_SMALL
|
||||
)
|
||||
|
||||
//What the fuck
|
||||
if(length(to_generate) > length(GLOB.data_core.locked))
|
||||
to_generate.Cut(1, length(GLOB.data_core.locked))
|
||||
|
||||
// We don't want the sum of all the payouts to be under this amount
|
||||
var/lowest_TC_threshold = 30
|
||||
var/lowest_TC_threshold = 30
|
||||
|
||||
var/total = 0
|
||||
var/lowest_paying_sum = 0
|
||||
@@ -75,7 +80,7 @@
|
||||
for (var/i = 1; i <= to_generate.len; i++)
|
||||
var/datum/syndicate_contract/contract_to_add = new(owner, assigned_targets, to_generate[i])
|
||||
var/contract_payout_total = contract_to_add.contract.payout + contract_to_add.contract.payout_bonus
|
||||
|
||||
|
||||
assigned_targets.Add(contract_to_add.contract.target)
|
||||
|
||||
if (!lowest_paying_contract || (contract_payout_total < lowest_paying_sum))
|
||||
@@ -96,14 +101,14 @@
|
||||
var/name // Name of item
|
||||
var/desc // description of item
|
||||
var/item // item path, no item path means the purchase needs it's own handle_purchase()
|
||||
var/item_icon = "fa-broadcast-tower" // fontawesome icon to use inside the hub - https://fontawesome.com/icons/
|
||||
var/item_icon = "broadcast-tower" // fontawesome icon to use inside the hub - https://fontawesome.com/icons/
|
||||
var/limited = -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 = "fa-dice"
|
||||
item_icon = "dice"
|
||||
limited = 2
|
||||
cost = 0
|
||||
|
||||
@@ -118,7 +123,7 @@
|
||||
if (contract_check.contract.target)
|
||||
new_target_list.Add(contract_check.contract.target)
|
||||
continue
|
||||
|
||||
|
||||
/// Reroll contracts without duplicates
|
||||
for(var/datum/syndicate_contract/rerolling_contract in hub.assigned_contracts)
|
||||
if (rerolling_contract.status != CONTRACT_STATUS_ACTIVE && rerolling_contract.status != CONTRACT_STATUS_INACTIVE)
|
||||
@@ -134,7 +139,7 @@
|
||||
name = "Contractor Pinpointer"
|
||||
desc = "A pinpointer that finds targets even without active suit sensors. Due to taking advantage of an exploit within the system, it can't pinpoint to the same accuracy as the traditional models. Becomes permanently locked to the user that first activates it."
|
||||
item = /obj/item/pinpointer/crew/contractor
|
||||
item_icon = "fa-search-location"
|
||||
item_icon = "search-location"
|
||||
limited = 2
|
||||
cost = 1
|
||||
|
||||
@@ -142,14 +147,14 @@
|
||||
name = "Fulton Extraction Kit"
|
||||
desc = "For getting your target across the station to those difficult dropoffs. Place the beacon somewhere secure, and link the pack. Activating the pack on your target in space 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 = "fa-parachute-box"
|
||||
item_icon = "parachute-box"
|
||||
limited = 1
|
||||
cost = 1
|
||||
|
||||
/datum/contractor_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_icon = "fa-user-friends"
|
||||
item_icon = "user-friends"
|
||||
limited = 1
|
||||
cost = 2
|
||||
var/datum/mind/partner_mind = null
|
||||
@@ -175,7 +180,7 @@
|
||||
|
||||
/datum/outfit/contractor_partner
|
||||
name = "Contractor Support Unit"
|
||||
|
||||
|
||||
uniform = /obj/item/clothing/under/chameleon
|
||||
suit = /obj/item/clothing/suit/chameleon
|
||||
back = /obj/item/storage/backpack
|
||||
@@ -186,7 +191,7 @@
|
||||
id = /obj/item/card/id/syndicate
|
||||
r_hand = /obj/item/storage/toolbox/syndicate
|
||||
|
||||
backpack_contents = list(/obj/item/storage/box/survival, /obj/item/implanter/uplink, /obj/item/clothing/mask/chameleon,
|
||||
backpack_contents = list(/obj/item/storage/box/survival, /obj/item/implanter/uplink, /obj/item/clothing/mask/chameleon,
|
||||
/obj/item/storage/fancy/cigarettes/cigpack_syndicate, /obj/item/lighter)
|
||||
|
||||
/datum/outfit/contractor_partner/post_equip(mob/living/carbon/human/H, visualsOnly)
|
||||
@@ -229,7 +234,7 @@
|
||||
/datum/contractor_item/blackout
|
||||
name = "Blackout"
|
||||
desc = "Request Syndicate Command to distrupt the station's powernet. Disables power across the station for a short duration."
|
||||
item_icon = "fa-bolt"
|
||||
item_icon = "bolt"
|
||||
limited = 2
|
||||
cost = 3
|
||||
|
||||
@@ -242,10 +247,10 @@
|
||||
|
||||
// Subtract cost, and spawn if it's an item.
|
||||
/datum/contractor_item/proc/handle_purchase(var/datum/contractor_hub/hub, mob/living/user)
|
||||
|
||||
|
||||
if (hub.contract_rep >= cost)
|
||||
hub.contract_rep -= cost
|
||||
else
|
||||
else
|
||||
return FALSE
|
||||
|
||||
if (limited >= 1)
|
||||
@@ -259,7 +264,7 @@
|
||||
|
||||
if (item && ispath(item))
|
||||
var/atom/item_to_create = new item(get_turf(user))
|
||||
|
||||
|
||||
if(user.put_in_hands(item_to_create))
|
||||
to_chat(user, "<span class='notice'>Your purchase materializes into your hands!</span>")
|
||||
else
|
||||
|
||||
@@ -4,7 +4,8 @@
|
||||
var/datum/objective/contract/contract = new()
|
||||
var/target_rank
|
||||
var/ransom = 0
|
||||
var/payout_type = null
|
||||
var/payout_type
|
||||
var/wanted_message
|
||||
|
||||
var/list/victim_belongings = list()
|
||||
|
||||
@@ -16,11 +17,11 @@
|
||||
|
||||
/datum/syndicate_contract/proc/generate(blacklist)
|
||||
contract.find_target(null, blacklist)
|
||||
|
||||
|
||||
var/datum/data/record/record = find_record("name", contract.target.name, GLOB.data_core.general)
|
||||
if (record)
|
||||
target_rank = record.fields["rank"]
|
||||
else
|
||||
else
|
||||
target_rank = "Unknown"
|
||||
|
||||
if (payout_type == CONTRACT_PAYOUT_LARGE)
|
||||
@@ -35,6 +36,12 @@
|
||||
|
||||
ransom = 100 * rand(18, 45)
|
||||
|
||||
var/base = pick_list(WANTED_FILE, "basemessage")
|
||||
var/verb_string = pick_list(WANTED_FILE, "verb")
|
||||
var/noun = pick_list_weighted(WANTED_FILE, "noun")
|
||||
var/location = pick_list_weighted(WANTED_FILE, "location")
|
||||
wanted_message = "[base] [verb_string] [noun] [location]."
|
||||
|
||||
/datum/syndicate_contract/proc/handle_extraction(var/mob/living/user)
|
||||
if (contract.target && contract.dropoff_check(user, contract.target.current))
|
||||
|
||||
@@ -50,7 +57,7 @@
|
||||
// Launch the pod to collect our victim.
|
||||
/datum/syndicate_contract/proc/launch_extraction_pod(turf/empty_pod_turf)
|
||||
var/obj/structure/closet/supplypod/extractionpod/empty_pod = new()
|
||||
|
||||
|
||||
RegisterSignal(empty_pod, COMSIG_ATOM_ENTERED, .proc/enter_check)
|
||||
|
||||
empty_pod.stay_after_drop = TRUE
|
||||
@@ -65,23 +72,24 @@
|
||||
if (isliving(sent_mob))
|
||||
var/mob/living/M = sent_mob
|
||||
var/datum/antagonist/traitor/traitor_data = contract.owner.has_antag_datum(/datum/antagonist/traitor)
|
||||
|
||||
|
||||
if (M == contract.target.current)
|
||||
traitor_data.contractor_hub.contract_TC_to_redeem += contract.payout
|
||||
traitor_data.contractor_hub.contracts_completed += 1
|
||||
|
||||
if (M.stat != DEAD)
|
||||
traitor_data.contractor_hub.contract_TC_to_redeem += contract.payout_bonus
|
||||
|
||||
status = CONTRACT_STATUS_COMPLETE
|
||||
|
||||
if (traitor_data.contractor_hub.current_contract == src)
|
||||
if (traitor_data.contractor_hub.current_contract == src)
|
||||
traitor_data.contractor_hub.current_contract = null
|
||||
|
||||
|
||||
traitor_data.contractor_hub.contract_rep += 2
|
||||
else
|
||||
status = CONTRACT_STATUS_ABORTED // Sending a target that wasn't even yours is as good as just aborting it
|
||||
|
||||
if (traitor_data.contractor_hub.current_contract == src)
|
||||
|
||||
if (traitor_data.contractor_hub.current_contract == src)
|
||||
traitor_data.contractor_hub.current_contract = null
|
||||
|
||||
if (iscarbon(M))
|
||||
@@ -92,11 +100,11 @@
|
||||
continue //So all they're left with are shoes and uniform.
|
||||
if(W == H.shoes)
|
||||
continue
|
||||
|
||||
|
||||
|
||||
M.transferItemToLoc(W)
|
||||
victim_belongings.Add(W)
|
||||
|
||||
|
||||
var/obj/structure/closet/supplypod/extractionpod/pod = source
|
||||
|
||||
// Handle the pod returning
|
||||
@@ -104,14 +112,14 @@
|
||||
|
||||
if (ishuman(M))
|
||||
var/mob/living/carbon/human/target = M
|
||||
|
||||
|
||||
// After we remove items, at least give them what they need to live.
|
||||
target.dna.species.give_important_for_life(target)
|
||||
|
||||
// After pod is sent we start the victim narrative/heal.
|
||||
handleVictimExperience(M)
|
||||
|
||||
// This is slightly delayed because of the sleep calls above to handle the narrative.
|
||||
// This is slightly delayed because of the sleep calls above to handle the narrative.
|
||||
// We don't want to tell the station instantly.
|
||||
var/points_to_check
|
||||
var/datum/bank_account/D = SSeconomy.get_dep_account(ACCOUNT_CAR)
|
||||
@@ -119,7 +127,7 @@
|
||||
points_to_check = D.account_balance
|
||||
if(points_to_check >= ransom)
|
||||
D.adjust_money(-ransom)
|
||||
else
|
||||
else
|
||||
D.adjust_money(-points_to_check)
|
||||
|
||||
priority_announce("One of your crew was captured by a rival organisation - we've needed to pay their ransom to bring them back. \
|
||||
@@ -187,7 +195,7 @@
|
||||
|
||||
if (possible_drop_loc.len > 0)
|
||||
var/pod_rand_loc = rand(1, possible_drop_loc.len)
|
||||
|
||||
|
||||
var/obj/structure/closet/supplypod/return_pod = new()
|
||||
return_pod.bluespace = TRUE
|
||||
return_pod.explosionSize = list(0,0,0,0)
|
||||
@@ -207,7 +215,7 @@
|
||||
|
||||
for(var/obj/item/W in victim_belongings)
|
||||
W.forceMove(return_pod)
|
||||
|
||||
|
||||
M.forceMove(return_pod)
|
||||
|
||||
M.flash_act()
|
||||
|
||||
@@ -10,18 +10,19 @@
|
||||
undeletable = 1
|
||||
tgui_id = "synd_contract"
|
||||
ui_style = "syndicate"
|
||||
ui_x = 600
|
||||
ui_x = 500
|
||||
ui_y = 600
|
||||
var/error = ""
|
||||
var/page = CONTRACT_UPLINK_PAGE_CONTRACTS
|
||||
var/info_screen = TRUE
|
||||
var/assigned = FALSE
|
||||
var/first_load = TRUE
|
||||
|
||||
/datum/computer_file/program/contract_uplink/run_program(var/mob/living/user)
|
||||
. = ..(user)
|
||||
|
||||
/datum/computer_file/program/contract_uplink/ui_act(action, params)
|
||||
if(..())
|
||||
return 1
|
||||
return TRUE
|
||||
|
||||
var/mob/living/user = usr
|
||||
var/obj/item/computer_hardware/hard_drive/small/syndicate/hard_drive = computer.all_components[MC_HDD]
|
||||
@@ -33,9 +34,9 @@
|
||||
// Set as the active contract
|
||||
hard_drive.traitor_data.contractor_hub.assigned_contracts[contract_id].status = CONTRACT_STATUS_ACTIVE
|
||||
hard_drive.traitor_data.contractor_hub.current_contract = hard_drive.traitor_data.contractor_hub.assigned_contracts[contract_id]
|
||||
|
||||
|
||||
program_icon_state = "single_contract"
|
||||
return 1
|
||||
return TRUE
|
||||
if("PRG_login")
|
||||
var/datum/antagonist/traitor/traitor_data = user.mind.has_antag_datum(/datum/antagonist/traitor)
|
||||
|
||||
@@ -45,7 +46,7 @@
|
||||
if (traitor_data)
|
||||
// Only play greet sound, and handle contractor hub when assigning for the first time.
|
||||
if (!traitor_data.contractor_hub)
|
||||
user.playsound_local(user, 'sound/effects/contractstartup.ogg', 100, 0)
|
||||
user.playsound_local(user, 'sound/effects/contractstartup.ogg', 100, FALSE)
|
||||
traitor_data.contractor_hub = new
|
||||
traitor_data.contractor_hub.create_hub_items()
|
||||
|
||||
@@ -57,22 +58,24 @@
|
||||
|
||||
program_icon_state = "contracts"
|
||||
assigned = TRUE
|
||||
return 1
|
||||
else
|
||||
error = "UNAUTHORIZED USER"
|
||||
return TRUE
|
||||
if("PRG_call_extraction")
|
||||
if (hard_drive.traitor_data.contractor_hub.current_contract.status != CONTRACT_STATUS_EXTRACTING)
|
||||
if (hard_drive.traitor_data.contractor_hub.current_contract.handle_extraction(user))
|
||||
user.playsound_local(user, 'sound/effects/confirmdropoff.ogg', 100, 1)
|
||||
user.playsound_local(user, 'sound/effects/confirmdropoff.ogg', 100, TRUE)
|
||||
hard_drive.traitor_data.contractor_hub.current_contract.status = CONTRACT_STATUS_EXTRACTING
|
||||
|
||||
program_icon_state = "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
|
||||
else
|
||||
user.playsound_local(user, 'sound/machines/uplinkerror.ogg', 50)
|
||||
error = "Already extracting... Place the target into the pod. If the pod was destroyed, you will need to cancel this contract."
|
||||
|
||||
return 1
|
||||
return TRUE
|
||||
if("PRG_contract_abort")
|
||||
var/contract_id = hard_drive.traitor_data.contractor_hub.current_contract.id
|
||||
|
||||
@@ -81,10 +84,10 @@
|
||||
|
||||
program_icon_state = "contracts"
|
||||
|
||||
return 1
|
||||
return TRUE
|
||||
if("PRG_redeem_TC")
|
||||
if (hard_drive.traitor_data.contractor_hub.contract_TC_to_redeem)
|
||||
var/obj/item/stack/telecrystal/crystals = new /obj/item/stack/telecrystal(get_turf(user),
|
||||
var/obj/item/stack/telecrystal/crystals = new /obj/item/stack/telecrystal(get_turf(user),
|
||||
hard_drive.traitor_data.contractor_hub.contract_TC_to_redeem)
|
||||
if(ishuman(user))
|
||||
var/mob/living/carbon/human/H = user
|
||||
@@ -95,18 +98,19 @@
|
||||
|
||||
hard_drive.traitor_data.contractor_hub.contract_TC_payed_out += hard_drive.traitor_data.contractor_hub.contract_TC_to_redeem
|
||||
hard_drive.traitor_data.contractor_hub.contract_TC_to_redeem = 0
|
||||
return 1
|
||||
return TRUE
|
||||
else
|
||||
user.playsound_local(user, 'sound/machines/uplinkerror.ogg', 50)
|
||||
return 1
|
||||
return TRUE
|
||||
if ("PRG_clear_error")
|
||||
error = ""
|
||||
if("PRG_contractor_hub")
|
||||
page = CONTRACT_UPLINK_PAGE_HUB
|
||||
program_icon_state = "store"
|
||||
if ("PRG_hub_back")
|
||||
page = CONTRACT_UPLINK_PAGE_CONTRACTS
|
||||
program_icon_state = "contracts"
|
||||
return TRUE
|
||||
if("PRG_set_first_load_finished")
|
||||
first_load = FALSE
|
||||
return TRUE
|
||||
if("PRG_toggle_info")
|
||||
info_screen = !info_screen
|
||||
return TRUE
|
||||
if ("buy_hub")
|
||||
if (hard_drive.traitor_data.owner.current == user)
|
||||
var/item = params["item"]
|
||||
@@ -122,9 +126,11 @@
|
||||
var/obj/item/computer_hardware/hard_drive/small/syndicate/hard_drive = computer.all_components[MC_HDD]
|
||||
var/screen_to_be = null
|
||||
|
||||
data["first_load"] = first_load
|
||||
|
||||
if (hard_drive && hard_drive.traitor_data != null)
|
||||
var/datum/antagonist/traitor/traitor_data = hard_drive.traitor_data
|
||||
data = get_header_data()
|
||||
data += get_header_data()
|
||||
|
||||
if (traitor_data.contractor_hub.current_contract)
|
||||
data["ongoing_contract"] = TRUE
|
||||
@@ -132,13 +138,20 @@
|
||||
if (traitor_data.contractor_hub.current_contract.status == CONTRACT_STATUS_EXTRACTING)
|
||||
data["extraction_enroute"] = TRUE
|
||||
screen_to_be = "extracted"
|
||||
|
||||
else
|
||||
data["extraction_enroute"] = FALSE
|
||||
else
|
||||
data["ongoing_contract"] = FALSE
|
||||
data["extraction_enroute"] = FALSE
|
||||
|
||||
data["logged_in"] = TRUE
|
||||
data["station_name"] = GLOB.station_name
|
||||
data["redeemable_tc"] = traitor_data.contractor_hub.contract_TC_to_redeem
|
||||
data["earned_tc"] = traitor_data.contractor_hub.contract_TC_payed_out
|
||||
data["contracts_completed"] = traitor_data.contractor_hub.contracts_completed
|
||||
data["contract_rep"] = traitor_data.contractor_hub.contract_rep
|
||||
|
||||
data["page"] = page
|
||||
data["info_screen"] = info_screen
|
||||
|
||||
data["error"] = error
|
||||
|
||||
@@ -159,15 +172,16 @@
|
||||
"payout_bonus" = contract.contract.payout_bonus,
|
||||
"dropoff" = contract.contract.dropoff,
|
||||
"id" = contract.id,
|
||||
"status" = contract.status
|
||||
"status" = contract.status,
|
||||
"message" = contract.wanted_message
|
||||
))
|
||||
|
||||
var/direction
|
||||
if (traitor_data.contractor_hub.current_contract)
|
||||
var/turf/curr = get_turf(user)
|
||||
var/turf/dropoff_turf
|
||||
var/turf/dropoff_turf
|
||||
data["current_location"] = "[get_area_name(curr, TRUE)]"
|
||||
|
||||
|
||||
for (var/turf/content in traitor_data.contractor_hub.current_contract.contract.dropoff.contents)
|
||||
if (isturf(content))
|
||||
dropoff_turf = content
|
||||
@@ -182,16 +196,8 @@
|
||||
|
||||
data["dropoff_direction"] = direction
|
||||
|
||||
if (page == CONTRACT_UPLINK_PAGE_HUB)
|
||||
screen_to_be = "store"
|
||||
|
||||
if (!screen_to_be)
|
||||
screen_to_be = "contracts"
|
||||
else
|
||||
data["logged_in"] = FALSE
|
||||
|
||||
if (!screen_to_be)
|
||||
screen_to_be = "assign"
|
||||
|
||||
program_icon_state = screen_to_be
|
||||
update_computer_icon()
|
||||
|
||||
@@ -0,0 +1,74 @@
|
||||
{
|
||||
"basemessage": [
|
||||
"Fugitive from the law due to",
|
||||
"Needs to be interrogated for information about",
|
||||
"Wanted by The Syndicate for",
|
||||
"Ransomable to Nanotrasen for",
|
||||
"Has exploitable information about"
|
||||
],
|
||||
"verb": [
|
||||
"murdering",
|
||||
"killing",
|
||||
"accidentally destroying",
|
||||
"destroying",
|
||||
"knowing information about",
|
||||
"stealing",
|
||||
"slipping",
|
||||
"sabotaging",
|
||||
"robusting",
|
||||
"collaborating with",
|
||||
"being close friends with",
|
||||
"cloning",
|
||||
"befriending",
|
||||
"bombing",
|
||||
"kidnapping",
|
||||
"pretending to be",
|
||||
"seducing",
|
||||
"ignoring",
|
||||
"assassinating"
|
||||
],
|
||||
"noun": {
|
||||
"secret plans": 50,
|
||||
"the hand teleporter": 50,
|
||||
"an NT centcomm uniform": 50,
|
||||
"a supermatter shard": 50,
|
||||
"internal Syndicate documents": 50,
|
||||
"experimental Nanotrasen technology": 50,
|
||||
"bluespace crystals": 50,
|
||||
"a cult": 50,
|
||||
"shapeshifting creatures": 50,
|
||||
"a toolbox": 10,
|
||||
"a bar of soap": 10,
|
||||
"lizardmen": 10,
|
||||
"two million credits": 10,
|
||||
"a gondola": 10,
|
||||
"one billion credits": 5,
|
||||
"research on floor clowns": 5,
|
||||
"Officer Beepsky": 5,
|
||||
"clown tears": 5,
|
||||
"John F Kennedy 2": 5,
|
||||
"Nanotrasen's swimsuit calendar": 5,
|
||||
"a suspicious bus": 5,
|
||||
"administrators": 5,
|
||||
"a solid gold gondola": 5,
|
||||
"the anime archive": 5,
|
||||
"YALPER": 1,
|
||||
"absolutely nothing": 1,
|
||||
"Cuban Pete": 1,
|
||||
"your mother": 1,
|
||||
"WGW": 1
|
||||
},
|
||||
"location": {
|
||||
"on Space Station 13": 50,
|
||||
"somewhere in deep space": 50,
|
||||
"on a remote syndicate base": 50,
|
||||
"in a secure NT facility": 50,
|
||||
"while on an escape shuttle": 10,
|
||||
"while infilrating centcomm headquarters": 10,
|
||||
"deep in the necropolis": 10,
|
||||
"during a drunken bar fight": 5,
|
||||
"while stuck in a bathroom": 5,
|
||||
"in a back alley on Mars": 5,
|
||||
"on Virgo Orbital": 1
|
||||
}
|
||||
}
|
||||
@@ -68,6 +68,7 @@ const styleMapperByPropName = {
|
||||
lineHeight: mapUnitPropTo('line-height'),
|
||||
opacity: mapRawPropTo('opacity'),
|
||||
textAlign: mapRawPropTo('text-align'),
|
||||
verticalAlign: mapRawPropTo('vertical-align'),
|
||||
// Boolean props
|
||||
inline: mapBooleanPropTo('display', 'inline-block'),
|
||||
bold: mapBooleanPropTo('font-weight', 'bold'),
|
||||
|
||||
@@ -0,0 +1,382 @@
|
||||
import { Box, Button, Section, Dimmer, Table, Icon, NoticeBox, Tabs, Grid, LabeledList } from "../components";
|
||||
import { useBackend } from "../backend";
|
||||
import { Fragment, Component } from "inferno";
|
||||
|
||||
export class FakeTerminal extends Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.timer = null;
|
||||
this.state = {
|
||||
currentIndex: 0,
|
||||
currentDisplay: [],
|
||||
};
|
||||
}
|
||||
|
||||
tick() {
|
||||
const { props, state } = this;
|
||||
if (state.currentIndex <= props.allMessages.length) {
|
||||
this.setState(prevState => {
|
||||
return ({
|
||||
currentIndex: prevState.currentIndex + 1,
|
||||
});
|
||||
});
|
||||
const { currentDisplay } = state;
|
||||
currentDisplay.push(props.allMessages[state.currentIndex]);
|
||||
} else {
|
||||
clearTimeout(this.timer);
|
||||
setTimeout(props.onFinished, props.finishedTimeout);
|
||||
}
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
const {
|
||||
linesPerSecond = 2.5,
|
||||
} = this.props;
|
||||
this.timer = setInterval(() => this.tick(), 1000 / linesPerSecond);
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
clearTimeout(this.timer);
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<Box m={1}>
|
||||
{this.state.currentDisplay.map(value => (
|
||||
<Fragment key={value}>
|
||||
{value}
|
||||
<br />
|
||||
</Fragment>
|
||||
))}
|
||||
</Box>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export const SyndContractor = props => {
|
||||
const { data, act } = useBackend(props);
|
||||
|
||||
const terminalMessages = [
|
||||
"Recording biometric data...",
|
||||
"Analyzing embedded syndicate info...",
|
||||
"STATUS CONFIRMED",
|
||||
"Contacting syndicate database...",
|
||||
"Awaiting response...",
|
||||
"Awaiting response...",
|
||||
"Awaiting response...",
|
||||
"Awaiting response...",
|
||||
"Awaiting response...",
|
||||
"Awaiting response...",
|
||||
"Response received, ack 4851234...",
|
||||
"CONFIRM ACC " + (Math.round(Math.random() * 20000)),
|
||||
"Setting up private accounts...",
|
||||
"CONTRACTOR ACCOUNT CREATED",
|
||||
"Searching for available contracts...",
|
||||
"Searching for available contracts...",
|
||||
"Searching for available contracts...",
|
||||
"Searching for available contracts...",
|
||||
"CONTRACTS FOUND",
|
||||
"WELCOME, AGENT",
|
||||
];
|
||||
|
||||
const infoEntries = [
|
||||
"SyndTract v2.0",
|
||||
"",
|
||||
"We've identified potentional high-value targets that are",
|
||||
"currently assigned to your mission area. They are believed",
|
||||
"to hold valuable information which could be of immediate",
|
||||
"importance to our organisation.",
|
||||
"",
|
||||
"Listed below are all of the contracts available to you. You",
|
||||
"are to bring the specified target to the designated",
|
||||
"drop-off, and contact us via this uplink. We will send",
|
||||
"a specialised extraction unit to put the body into.",
|
||||
"",
|
||||
"We want targets alive - but we will sometimes pay slight",
|
||||
"amounts if they're not, you just won't recieve the shown",
|
||||
"bonus. You can redeem your payment through this uplink in",
|
||||
"the form of raw telecrystals, which can be put into your",
|
||||
"regular Syndicate uplink to purchase whatever you may need.",
|
||||
"We provide you with these crystals the moment you send the",
|
||||
"target up to us, which can be collected at anytime through",
|
||||
"this system.",
|
||||
"",
|
||||
"Targets extracted will be ransomed back to the station once",
|
||||
"their use to us is fulfilled, with us providing you a small",
|
||||
"percentage cut. You may want to be mindful of them",
|
||||
"identifying you when they come back. We provide you with",
|
||||
"a standard contractor loadout, which will help cover your",
|
||||
"identity.",
|
||||
];
|
||||
|
||||
const errorPane = !!data.error && (
|
||||
<Dimmer>
|
||||
<Box
|
||||
backgroundColor="red"
|
||||
minHeight="150px"
|
||||
mt={30}
|
||||
ml={15}
|
||||
mr={15}>
|
||||
<Table m={1}>
|
||||
<Table.Row>
|
||||
<Table.Cell collapsing fontSize="100px">
|
||||
<Icon
|
||||
name="exclamation-triangle"
|
||||
mt={4}
|
||||
ml={2} />
|
||||
</Table.Cell>
|
||||
<Table.Cell
|
||||
verticalAlign="top"
|
||||
textAlign="center">
|
||||
<Box
|
||||
m={1}
|
||||
textAlign="left"
|
||||
width="100%"
|
||||
minHeight="110px">
|
||||
{data.error}
|
||||
</Box>
|
||||
<Button
|
||||
content="Dismiss"
|
||||
onClick={() => act('PRG_clear_error')} />
|
||||
</Table.Cell>
|
||||
</Table.Row>
|
||||
</Table>
|
||||
</Box>
|
||||
</Dimmer>
|
||||
);
|
||||
|
||||
if (!data.logged_in) {
|
||||
return (
|
||||
<Section minHeight="525px">
|
||||
<Box
|
||||
width="100%"
|
||||
textAlign="center">
|
||||
<Button
|
||||
content="REGISTER USER"
|
||||
color="transparent"
|
||||
onClick={() => act('PRG_login')} />
|
||||
</Box>
|
||||
{!!data.error && (
|
||||
<NoticeBox>
|
||||
{data.error}
|
||||
</NoticeBox>
|
||||
)}
|
||||
</Section>
|
||||
);
|
||||
}
|
||||
|
||||
if (data.logged_in && data.first_load) {
|
||||
return (
|
||||
<Box
|
||||
backgroundColor="rgba(0, 0, 0, 0.8)"
|
||||
minHeight="525px">
|
||||
<FakeTerminal
|
||||
allMessages={terminalMessages}
|
||||
finishedTimeout={3000}
|
||||
onFinished={() => act('PRG_set_first_load_finished')} />
|
||||
</Box>
|
||||
);
|
||||
}
|
||||
|
||||
if (data.info_screen) {
|
||||
return (
|
||||
<Fragment>
|
||||
<Box
|
||||
backgroundColor="rgba(0, 0, 0, 0.8)"
|
||||
minHeight="500px">
|
||||
<FakeTerminal
|
||||
allMessages={infoEntries}
|
||||
linesPerSecond={10} />
|
||||
</Box>
|
||||
<Button
|
||||
fluid
|
||||
content="CONTINUE"
|
||||
color="transparent"
|
||||
textAlign="center"
|
||||
onClick={() => act('PRG_toggle_info')} />
|
||||
</Fragment>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<Fragment>
|
||||
{errorPane}
|
||||
<SyndPane state={props.state} />
|
||||
</Fragment>
|
||||
);
|
||||
};
|
||||
|
||||
export const StatusPane = props => {
|
||||
const { act, data } = useBackend(props);
|
||||
|
||||
return (
|
||||
<Section
|
||||
title={(
|
||||
<Fragment>
|
||||
Contractor Status
|
||||
<Button
|
||||
content="View Information Again"
|
||||
color="transparent"
|
||||
mb={0}
|
||||
ml={1}
|
||||
onClick={() => act('PRG_toggle_info')} />
|
||||
</Fragment>
|
||||
)}
|
||||
buttons={(
|
||||
<Box bold mr={1}>
|
||||
{data.contract_rep} Rep
|
||||
</Box>
|
||||
)}>
|
||||
<Grid>
|
||||
<Grid.Column size={0.85}>
|
||||
<LabeledList>
|
||||
<LabeledList.Item
|
||||
label="TC Availible"
|
||||
buttons={(
|
||||
<Button
|
||||
content="Claim"
|
||||
disabled={data.redeemable_tc <= 0}
|
||||
onClick={() => act('PRG_redeem_TC')} />
|
||||
)}>
|
||||
{data.redeemable_tc}
|
||||
</LabeledList.Item>
|
||||
<LabeledList.Item label="TC Earned">
|
||||
{data.earned_tc}
|
||||
</LabeledList.Item>
|
||||
</LabeledList>
|
||||
</Grid.Column>
|
||||
<Grid.Column>
|
||||
<LabeledList>
|
||||
<LabeledList.Item label="Contracts Completed">
|
||||
{data.contracts_completed}
|
||||
</LabeledList.Item>
|
||||
<LabeledList.Item label="Current Status">
|
||||
ACTIVE
|
||||
</LabeledList.Item>
|
||||
</LabeledList>
|
||||
</Grid.Column>
|
||||
</Grid>
|
||||
</Section>
|
||||
);
|
||||
};
|
||||
|
||||
export const SyndPane = props => {
|
||||
const { act, data } = useBackend(props);
|
||||
|
||||
const contractor_hub_items = data.contractor_hub_items || [];
|
||||
const contracts = data.contracts || [];
|
||||
|
||||
return (
|
||||
<Fragment>
|
||||
<StatusPane state={props.state} />
|
||||
<Tabs>
|
||||
<Tabs.Tab label="Contracts">
|
||||
<Section
|
||||
title="Availible Contracts"
|
||||
buttons={(
|
||||
<Button
|
||||
content="Call Extraction"
|
||||
disabled={!data.ongoing_contract || data.extraction_enroute}
|
||||
onClick={() => act('PRG_call_extraction')} />
|
||||
)}>
|
||||
{contracts.map(contract => {
|
||||
const active = (contract.status > 1);
|
||||
if (contract.status >= 5) {
|
||||
return;
|
||||
}
|
||||
return (
|
||||
<Section
|
||||
key={contract.target}
|
||||
title={`${contract.target} (${contract.target_rank})`}
|
||||
level={active ? 1 : 2}
|
||||
buttons={(
|
||||
<Fragment>
|
||||
<Box
|
||||
inline
|
||||
bold
|
||||
mr={1}>
|
||||
{contract.payout} (+{contract.payout_bonus}) TC
|
||||
</Box>
|
||||
<Button
|
||||
content={active ? "Abort" : "Accept"}
|
||||
disabled={contract.extraction_enroute}
|
||||
color={active && "bad"}
|
||||
onClick={() => act(
|
||||
'PRG_contract' + (active ? '_abort' : '-accept'),
|
||||
{
|
||||
contract_id: contract.id,
|
||||
})} />
|
||||
</Fragment>
|
||||
)}>
|
||||
<Grid>
|
||||
<Grid.Column>
|
||||
{contract.message}
|
||||
</Grid.Column>
|
||||
<Grid.Column size={0.5}>
|
||||
<Box
|
||||
bold
|
||||
mb={1}>
|
||||
Dropoff Location:
|
||||
</Box>
|
||||
<Box>
|
||||
{contract.dropoff}
|
||||
</Box>
|
||||
</Grid.Column>
|
||||
</Grid>
|
||||
</Section>
|
||||
);
|
||||
})}
|
||||
</Section>
|
||||
</Tabs.Tab>
|
||||
<Tabs.Tab label="Uplink">
|
||||
<Section>
|
||||
{contractor_hub_items.map(item => {
|
||||
const repInfo = item.cost ? (item.cost + ' Rep') : 'FREE';
|
||||
const limited = (item.limited !== -1);
|
||||
return (
|
||||
<Section
|
||||
key={item.name}
|
||||
title={item.name + ' - ' + repInfo}
|
||||
level={2}
|
||||
buttons={(
|
||||
<Fragment>
|
||||
{limited && (
|
||||
<Box
|
||||
inline
|
||||
bold
|
||||
mr={1}>
|
||||
{item.limited} remaining
|
||||
</Box>
|
||||
)}
|
||||
<Button
|
||||
content="Purchase"
|
||||
disabled={data.redeemable_tc < item.cost
|
||||
|| (limited && item.limited <= 0)}
|
||||
onClick={() => act('buy_hub', {
|
||||
item: item.name,
|
||||
cost: item.cost,
|
||||
})} />
|
||||
</Fragment>
|
||||
)}>
|
||||
<Table>
|
||||
<Table.Row>
|
||||
<Table.Cell>
|
||||
<Icon
|
||||
fontSize="60px"
|
||||
name={item.item_icon} />
|
||||
</Table.Cell>
|
||||
<Table.Cell
|
||||
verticalAlign="top">
|
||||
{item.desc}
|
||||
</Table.Cell>
|
||||
</Table.Row>
|
||||
</Table>
|
||||
</Section>
|
||||
);
|
||||
})}
|
||||
</Section>
|
||||
</Tabs.Tab>
|
||||
</Tabs>
|
||||
</Fragment>
|
||||
);
|
||||
};
|
||||
File diff suppressed because one or more lines are too long
@@ -97,6 +97,7 @@ import { Uplink } from './interfaces/Uplink';
|
||||
import { VaultController } from './interfaces/VaultController';
|
||||
import { Vending } from './interfaces/Vending';
|
||||
import { Wires } from './interfaces/Wires';
|
||||
import { SyndContractor } from './interfaces/SyndContractor';
|
||||
|
||||
const ROUTES = {
|
||||
achievements: {
|
||||
@@ -490,6 +491,12 @@ const ROUTES = {
|
||||
component: () => SuitStorageUnit,
|
||||
scrollable: false,
|
||||
},
|
||||
synd_contract: {
|
||||
component: () => SyndContractor,
|
||||
wrapper: () => NtosWrapper,
|
||||
scrollable: true,
|
||||
theme: 'syndicate',
|
||||
},
|
||||
tanks: {
|
||||
component: () => Tank,
|
||||
scrollable: false,
|
||||
|
||||
Reference in New Issue
Block a user