diff --git a/code/__HELPERS/areas.dm b/code/__HELPERS/areas.dm index d7378abfa6..715f17af92 100644 --- a/code/__HELPERS/areas.dm +++ b/code/__HELPERS/areas.dm @@ -1,5 +1,10 @@ #define BP_MAX_ROOM_SIZE 300 +GLOBAL_LIST_INIT(typecache_powerfailure_safe_areas, typecacheof(/area/engine/engineering, \ + /area/engine/supermatter, \ + /area/engine/atmospherics_engine, \ + /area/ai_monitored/turret_protected/ai)) + //Repopulates sortedAreas list /proc/repopulate_sorted_areas() GLOB.sortedAreas = list() diff --git a/code/__HELPERS/game.dm b/code/__HELPERS/game.dm index 60d7fa42b9..75e711ad03 100644 --- a/code/__HELPERS/game.dm +++ b/code/__HELPERS/game.dm @@ -549,3 +549,36 @@ var/pressure = environment.return_pressure() if(pressure <= LAVALAND_EQUIPMENT_EFFECT_PRESSURE) . = TRUE + +/proc/ispipewire(item) + var/static/list/pipe_wire = list( + /obj/machinery/atmospherics, + /obj/structure/disposalpipe, + /obj/structure/cable + ) + return (is_type_in_list(item, pipe_wire)) + +// Find a obstruction free turf that's within the range of the center. Can also condition on if it is of a certain area type. +/proc/find_obstruction_free_location(var/range, var/atom/center, var/area/specific_area) + var/list/turfs = RANGE_TURFS(range, center) + var/list/possible_loc = list() + for(var/turf/found_turf in turfs) + var/area/turf_area = get_area(found_turf) + if (specific_area) // We check if both the turf is a floor, and that it's actually in the area. // We also want a location that's clear of any obstructions. + if(!istype(turf_area, specific_area)) + continue + if(!isspaceturf(found_turf)) + if(!is_blocked_turf(found_turf)) + possible_loc.Add(found_turf) + if (possible_loc.len < 1) // Need at least one free location. + return FALSE + return pick(possible_loc) + +/proc/power_fail(duration_min, duration_max) + for(var/P in GLOB.apcs_list) + var/obj/machinery/power/apc/C = P + if(C.cell && SSmapping.level_trait(C.z, ZTRAIT_STATION)) + var/area/A = C.area + if(GLOB.typecache_powerfailure_safe_areas[A.type]) + continue + C.energy_fail(rand(duration_min,duration_max)) \ No newline at end of file diff --git a/code/__HELPERS/roundend.dm b/code/__HELPERS/roundend.dm index 0f1e75ff73..8a26b1f44b 100644 --- a/code/__HELPERS/roundend.dm +++ b/code/__HELPERS/roundend.dm @@ -354,6 +354,7 @@ roundend_report.set_content(content) roundend_report.stylesheets = list() roundend_report.add_stylesheet("roundend", 'html/browser/roundend.css') + roundend_report.add_stylesheet("font-awesome", 'html/font-awesome/css/all.min.css') roundend_report.open(0) /datum/controller/subsystem/ticker/proc/personal_report(client/C, popcount) diff --git a/code/_globalvars/lists/poll_ignore.dm b/code/_globalvars/lists/poll_ignore.dm index e30ce1d1ed..f5f3adbcc0 100644 --- a/code/_globalvars/lists/poll_ignore.dm +++ b/code/_globalvars/lists/poll_ignore.dm @@ -18,6 +18,7 @@ #define POLL_IGNORE_DEMON "demon" #define POLL_IGNORE_WIZARD "wizard" #define POLL_IGNORE_CLONE "clone" +#define POLL_IGNORE_CONTRACTOR_SUPPORT "contractor_support" GLOBAL_LIST_INIT(poll_ignore_desc, list( POLL_IGNORE_SENTIENCE_POTION = "Sentience potion", @@ -37,7 +38,8 @@ GLOBAL_LIST_INIT(poll_ignore_desc, list( POLL_IGNORE_SPLITPERSONALITY = "Split Personality", POLL_IGNORE_DEMON = "Demons", POLL_IGNORE_WIZARD = "Wizards", - POLL_IGNORE_CLONE = "Defective/SDGF clones" + POLL_IGNORE_CLONE = "Defective/SDGF clones", + POLL_IGNORE_CONTRACTOR_SUPPORT = "Contractor Support Unit" )) GLOBAL_LIST_INIT(poll_ignore, init_poll_ignore()) diff --git a/code/datums/mind.dm b/code/datums/mind.dm index 4689d52bd9..29bb694a6f 100644 --- a/code/datums/mind.dm +++ b/code/datums/mind.dm @@ -617,6 +617,10 @@ if(!(has_antag_datum(/datum/antagonist/traitor))) add_antag_datum(/datum/antagonist/traitor) +/datum/mind/proc/make_Contractor_Support() + if(!(has_antag_datum(/datum/antagonist/traitor/contractor_support))) + add_antag_datum(/datum/antagonist/traitor/contractor_support) + /datum/mind/proc/make_Changeling() var/datum/antagonist/changeling/C = has_antag_datum(/datum/antagonist/changeling) if(!C) diff --git a/code/game/gamemodes/objective.dm b/code/game/gamemodes/objective.dm index 4acd2ac6c0..95f6f8cbae 100644 --- a/code/game/gamemodes/objective.dm +++ b/code/game/gamemodes/objective.dm @@ -1166,7 +1166,7 @@ GLOBAL_LIST_EMPTY(possible_sabotages) var/found = FALSE while(!found) var/area/dropoff_area = pick(GLOB.sortedAreas) - if(dropoff_area && is_station_level(dropoff_area.z) && dropoff_area.valid_territory) + if(dropoff_area && is_station_level(dropoff_area.z) && !dropoff_area.outdoors) dropoff = dropoff_area found = TRUE diff --git a/code/game/objects/items/melee/misc.dm b/code/game/objects/items/melee/misc.dm index 2f8b562cca..3fcfb77603 100644 --- a/code/game/objects/items/melee/misc.dm +++ b/code/game/objects/items/melee/misc.dm @@ -376,7 +376,7 @@ w_class = WEIGHT_CLASS_SMALL item_flags = NONE force = 5 - cooldown = 30 + cooldown = 20 stam_dmg = 45 //3 hit stamcrit affect_silicon = TRUE on_sound = 'sound/weapons/contractorbatonextend.ogg' diff --git a/code/game/objects/items/pinpointer.dm b/code/game/objects/items/pinpointer.dm index 65eb7ab658..261a842807 100644 --- a/code/game/objects/items/pinpointer.dm +++ b/code/game/objects/items/pinpointer.dm @@ -17,6 +17,7 @@ var/active = FALSE var/atom/movable/target //The thing we're searching for var/minimum_range = 0 //at what range the pinpointer declares you to be at your destination + var/ignore_suit_sensor_level = FALSE // Do we find people even if their suit sensors are turned off var/alert = FALSE // TRUE to display things more seriously /obj/item/pinpointer/Initialize() @@ -77,6 +78,8 @@ name = "crew pinpointer" desc = "A handheld tracking device that points to crew suit sensors." icon_state = "pinpointer_crew" + var/has_owner = FALSE + var/pinpointer_owner = null /obj/item/pinpointer/crew/proc/trackable(mob/living/carbon/human/H) var/turf/here = get_turf(src) @@ -101,7 +104,11 @@ STOP_PROCESSING(SSfastprocess, src) update_icon() return - + if (has_owner && !pinpointer_owner) + pinpointer_owner = user + if (pinpointer_owner && pinpointer_owner != user) + to_chat(user, "The pinpointer doesn't respond. It seems to only recognise its owner.") + return var/list/name_counts = list() var/list/names = list() diff --git a/code/game/objects/items/storage/uplink_kits.dm b/code/game/objects/items/storage/uplink_kits.dm index 43b69676eb..ab55555562 100644 --- a/code/game/objects/items/storage/uplink_kits.dm +++ b/code/game/objects/items/storage/uplink_kits.dm @@ -419,6 +419,8 @@ to any form you need for the moment. The cigarettes are a special blend - it'll heal your injuries slowly overtime.

The three additional items, apart from the tablet and loadout box, have been randomly selected from what we had available. We hope they're useful to you for you mission.

+

The contractor hub, available at the top right of the uplink, will provide you unique items and abilities. These are bought using Contractor Rep, + with two Rep being provided each time you complete a contract.

Using the tablet

  1. Open the Syndicate Contract Uplink program.
  2. @@ -443,13 +445,13 @@

    We need your target for our own reasons, but we ransom them back to your mission area once their use is served. They will return back from where you sent them off from in several minutes time. You will be paid in TC for your services.

    -

    Good luck agent.

    "} +

    Good luck agent. You can burn this document with the supplied lighter.

    "} return ..() /obj/item/storage/box/syndicate/contractor_loadout/PopulateContents() - new /obj/item/clothing/head/helmet/space/syndicate/contract/black/red(src) - new /obj/item/clothing/suit/space/syndicate/contract/black/red(src) + new /obj/item/clothing/head/helmet/space/syndicate/contract(src) + new /obj/item/clothing/suit/space/syndicate/contract(src) new /obj/item/clothing/under/chameleon(src) new /obj/item/clothing/mask/chameleon(src) new /obj/item/card/id/syndicate(src) @@ -479,7 +481,8 @@ /obj/item/clothing/gloves/krav_maga/combatglovesplus, /obj/item/gun/ballistic/automatic/c20r/toy/unrestricted/riot, /obj/item/reagent_containers/syringe/stimulants, - /obj/item/storage/box/syndie_kit/imp_freedom + /obj/item/storage/box/syndie_kit/imp_freedom, + /obj/item/toy/eightball/haunted ) var/obj/item1 = pick_n_take(item_list) var/obj/item2 = pick_n_take(item_list) diff --git a/code/modules/antagonists/_common/antag_team.dm b/code/modules/antagonists/_common/antag_team.dm index 027abc7c94..653853cfb5 100644 --- a/code/modules/antagonists/_common/antag_team.dm +++ b/code/modules/antagonists/_common/antag_team.dm @@ -4,6 +4,7 @@ var/name = "team" var/member_name = "member" var/list/objectives = list() //common objectives, these won't be added or removed automatically, subtypes handle this, this is here for bookkeeping purposes. + var/show_roundend_report = TRUE /datum/team/New(starting_members) . = ..() @@ -25,6 +26,8 @@ //Display members/victory/failure/objectives for the team /datum/team/proc/roundend_report() + if(!show_roundend_report) + return var/list/report = list() report += "[name]:" diff --git a/code/modules/antagonists/traitor/datum_traitor.dm b/code/modules/antagonists/traitor/datum_traitor.dm index d05d1e383d..0b6b3f7f7a 100644 --- a/code/modules/antagonists/traitor/datum_traitor.dm +++ b/code/modules/antagonists/traitor/datum_traitor.dm @@ -13,10 +13,7 @@ var/should_give_codewords = TRUE var/should_equip = TRUE var/traitor_kind = TRAITOR_HUMAN //Set on initial assignment - var/datum/syndicate_contract/current_contract - var/list/assigned_contracts = list() - var/contract_TC_payed_out = 0 - var/contract_TC_to_redeem = 0 + var/datum/contractor_hub/contractor_hub hijack_speed = 0.5 //10 seconds per hijack stage by default /datum/antagonist/traitor/on_gain() @@ -30,36 +27,6 @@ finalize_traitor() ..() -/datum/antagonist/traitor/proc/create_contracts() - // 6 contracts - var/list/to_generate = list( - CONTRACT_PAYOUT_LARGE, - CONTRACT_PAYOUT_MEDIUM, - CONTRACT_PAYOUT_SMALL, - CONTRACT_PAYOUT_SMALL, - CONTRACT_PAYOUT_SMALL, - CONTRACT_PAYOUT_SMALL - ) - var/lowest_TC_threshold = 30 // We don't want the sum of all the payouts to be under this amount - var/total = 0 - var/lowest_paying_sum = 0 - var/datum/syndicate_contract/lowest_paying_contract - - to_generate = shuffle(to_generate) // Randomise order, so we don't have contracts always in payout order. - var/list/assigned_targets = list() - for (var/i = 1; i <= to_generate.len; i++) // Generate contracts, and find the lowest paying. - var/datum/syndicate_contract/contract_to_add = new(owner, to_generate[i], assigned_targets) - 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)) - lowest_paying_sum = contract_payout_total - lowest_paying_contract = contract_to_add - total += contract_payout_total - contract_to_add.id = i - assigned_contracts.Add(contract_to_add) - if(total < lowest_TC_threshold) // If the threshold for TC payouts isn't reached, boost the lowest paying contract - lowest_paying_contract.contract.payout_bonus += (lowest_TC_threshold - total) - /datum/antagonist/traitor/apply_innate_effects() if(owner.assigned_role == "Clown") var/mob/living/carbon/human/traitor_mob = owner.current @@ -447,19 +414,8 @@ var/special_role_text = lowertext(name) - var/completed_contracts = 0 - var/tc_total = contract_TC_payed_out + contract_TC_to_redeem - for (var/datum/syndicate_contract/contract in assigned_contracts) - if (contract.status == CONTRACT_STATUS_COMPLETE) - completed_contracts++ - - - if (completed_contracts > 0) - var/pluralCheck = "contract" - if (completed_contracts > 1) - pluralCheck = "contracts" - result += "
    Completed [completed_contracts] [pluralCheck] for a total of \ - [tc_total] TC!
    " + if(contractor_hub) + result += contractor_round_end() if(traitorwin) result += "The [special_role_text] was successful!" @@ -469,12 +425,44 @@ return result.Join("
    ") +/// Proc detailing contract kit buys/completed contracts/additional info +/datum/antagonist/traitor/proc/contractor_round_end() + var result = "" + var total_spent_rep = 0 + + var/completed_contracts = 0 + 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 + + for(var/datum/contractor_item/contractor_purchase in contractor_hub.purchased_items) // Get all the icons/total cost for all our items bought + contractor_item_icons += "\[ [contractor_purchase.name] - [contractor_purchase.cost] Rep

    [contractor_purchase.desc]
    \]
    " + total_spent_rep += contractor_purchase.cost + if(istype(contractor_purchase, /datum/contractor_item/contractor_partner)) // Special case for reinforcements, we want to show their ckey and name on round end. + 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) + result += contractor_item_icons + result += "
    (used [total_spent_rep] Rep)" + result += "
    " + if(completed_contracts > 0) + var/pluralCheck = "contract" + if(completed_contracts > 1) + pluralCheck = "contracts" + result += "Completed [completed_contracts] [pluralCheck] for a total of \ + [tc_total] TC!
    " + return result + /datum/antagonist/traitor/roundend_report_footer() var/phrases = jointext(GLOB.syndicate_code_phrase, ", ") var/responses = jointext(GLOB.syndicate_code_response, ", ") var message = "
    The code phrases were: [phrases]
    \ - The code responses were: [responses]
    " + The code responses were: [responses]
    " return message diff --git a/code/modules/clothing/spacesuits/syndi.dm b/code/modules/clothing/spacesuits/syndi.dm index 30014f4292..aca98df232 100644 --- a/code/modules/clothing/spacesuits/syndi.dm +++ b/code/modules/clothing/spacesuits/syndi.dm @@ -76,21 +76,21 @@ item_state = "syndicate-black" //Black-red syndicate contract varient -/obj/item/clothing/head/helmet/space/syndicate/contract/black/red +/obj/item/clothing/head/helmet/space/syndicate/contract name = "contractor helmet" - desc = "A specialised black and red helmet that's quicker, and more compact that its counterpart. Can be ultra-compressed into even the tightest of spaces." + desc = "A specialised black and gold helmet that's more compact than its standard Syndicate counterpart. Can be ultra-compressed into even the tightest of spaces." slowdown = 0.55 w_class = WEIGHT_CLASS_SMALL - icon_state = "syndicate-helm-black-red" - item_state = "syndicate-helm-black-red" + icon_state = "syndicate-contract-helm" + item_state = "syndicate-contract-helm" -/obj/item/clothing/suit/space/syndicate/contract/black/red +/obj/item/clothing/suit/space/syndicate/contract name = "contractor space suit" - desc = "A specialised black and red space suit that's quicker, and more compact that its counterpart. Can be ultra-compressed into even the tightest of spaces." + desc = "A specialised black and gold space suit that's quicker, and more compact than its standard Syndicate counterpart. Can be ultra-compressed into even the tightest of spaces." slowdown = 0.55 w_class = WEIGHT_CLASS_SMALL - icon_state = "syndicate-black-red" - item_state = "syndicate-black-red" + icon_state = "syndicate-contract" + item_state = "syndicate-contract" //Black-green syndicate space suit /obj/item/clothing/head/helmet/space/syndicate/black/green diff --git a/code/modules/events/grid_check.dm b/code/modules/events/grid_check.dm index b289c8ae1b..5bb3862422 100644 --- a/code/modules/events/grid_check.dm +++ b/code/modules/events/grid_check.dm @@ -13,7 +13,4 @@ /datum/round_event/grid_check/start() - for(var/P in GLOB.apcs_list) - var/obj/machinery/power/apc/C = P - if(C.cell && is_station_level(C.z)) - C.energy_fail(rand(30,120)) \ No newline at end of file + power_fail(30, 120) \ No newline at end of file diff --git a/code/modules/modular_computers/computers/item/tablet.dm b/code/modules/modular_computers/computers/item/tablet.dm index 154e3b5e41..0818ce8034 100644 --- a/code/modules/modular_computers/computers/item/tablet.dm +++ b/code/modules/modular_computers/computers/item/tablet.dm @@ -12,24 +12,26 @@ slot_flags = ITEM_SLOT_ID | ITEM_SLOT_BELT has_light = TRUE //LED flashlight! comp_light_luminosity = 2.3 //Same as the PDA + var/has_variants = TRUE var/finish_color = null /obj/item/modular_computer/tablet/update_icon() ..() - if(!finish_color) - finish_color = pick("red","blue","brown","green","black") - icon_state = "tablet-[finish_color]" - icon_state_unpowered = "tablet-[finish_color]" - icon_state_powered = "tablet-[finish_color]" + if(has_variants) + if(!finish_color) + finish_color = pick("red","blue","brown","green","black") + icon_state = "tablet-[finish_color]" + icon_state_unpowered = "tablet-[finish_color]" + icon_state_powered = "tablet-[finish_color]" /obj/item/modular_computer/tablet/syndicate_contract_uplink - name = "tablet computer" - icon = 'icons/obj/modular_tablet.dmi' + name = "contractor tablet" + icon = 'icons/obj/contractor_tablet.dmi' icon_state = "tablet-red" icon_state_unpowered = "tablet" icon_state_powered = "tablet" - icon_state_menu = "hostile" + icon_state_menu = "assign" w_class = WEIGHT_CLASS_SMALL slot_flags = ITEM_SLOT_ID | ITEM_SLOT_BELT - comp_light_luminosity = 4.3 - finish_color = "red" \ No newline at end of file + comp_light_luminosity = 6.3 + has_variants = FALSE \ No newline at end of file diff --git a/code/modules/modular_computers/computers/item/tablet_presets.dm b/code/modules/modular_computers/computers/item/tablet_presets.dm index 09b3a73ff0..f516d3802f 100644 --- a/code/modules/modular_computers/computers/item/tablet_presets.dm +++ b/code/modules/modular_computers/computers/item/tablet_presets.dm @@ -28,10 +28,14 @@ install_component(new /obj/item/computer_hardware/network_card) install_component(new /obj/item/computer_hardware/printer/mini) -/obj/item/modular_computer/tablet/syndicate_contract_uplink/preset/uplink/Initialize() // Given by the syndicate as part of the contract uplink bundle +/obj/item/modular_computer/tablet/syndicate_contract_uplink/preset/uplink/Initialize() // Given by the syndicate as part of the contract uplink bundle - loads in the Contractor Uplink. . = ..() var/obj/item/computer_hardware/hard_drive/small/syndicate/hard_drive = new - hard_drive.store_file(new /datum/computer_file/program/contract_uplink) + var/datum/computer_file/program/contract_uplink/uplink = new + active_program = uplink + uplink.program_state = PROGRAM_STATE_ACTIVE + uplink.computer = src + hard_drive.store_file(uplink) install_component(new /obj/item/computer_hardware/processor_unit/small) install_component(new /obj/item/computer_hardware/battery(src, /obj/item/stock_parts/cell/computer)) install_component(hard_drive) diff --git a/icons/mob/head.dmi b/icons/mob/head.dmi index 01e9f2ac2c..a5497145ca 100644 Binary files a/icons/mob/head.dmi and b/icons/mob/head.dmi differ diff --git a/icons/mob/suit.dmi b/icons/mob/suit.dmi index 41f2693800..d1a012908f 100644 Binary files a/icons/mob/suit.dmi and b/icons/mob/suit.dmi differ diff --git a/tgstation.dme b/tgstation.dme index 44218f00fc..377252be6d 100755 --- a/tgstation.dme +++ b/tgstation.dme @@ -1469,6 +1469,7 @@ #include "code\modules\antagonists\swarmer\swarmer_event.dm" #include "code\modules\antagonists\traitor\datum_traitor.dm" #include "code\modules\antagonists\traitor\syndicate_contract.dm" +#include "code\modules\antagonists\traitor\equipment\contractor.dm" #include "code\modules\antagonists\traitor\equipment\Malf_Modules.dm" #include "code\modules\antagonists\traitor\IAA\internal_affairs.dm" #include "code\modules\antagonists\valentines\heartbreaker.dm"