diff --git a/_maps/map_files/BoxStation/BoxStation.dmm b/_maps/map_files/BoxStation/BoxStation.dmm
index e72ebcab8c..a0244ae4d1 100644
--- a/_maps/map_files/BoxStation/BoxStation.dmm
+++ b/_maps/map_files/BoxStation/BoxStation.dmm
@@ -83843,8 +83843,8 @@ awb
axt
ayG
azJ
-aBd
-aBX
+azM
+azL
aDi
aEQ
aFW
@@ -84357,8 +84357,8 @@ vgJ
hSl
ayG
azL
-aBf
-aBY
+azM
+azJ
aDw
aES
aJh
diff --git a/code/modules/antagonists/clockcult/clock_items/clockwork_slab.dm b/code/modules/antagonists/clockcult/clock_items/clockwork_slab.dm
index 5837ac302d..83c3987cc9 100644
--- a/code/modules/antagonists/clockcult/clock_items/clockwork_slab.dm
+++ b/code/modules/antagonists/clockcult/clock_items/clockwork_slab.dm
@@ -25,6 +25,9 @@
/datum/clockwork_scripture/ranged_ability/kindle, /datum/clockwork_scripture/ranged_ability/hateful_manacles) //quickbound scripture, accessed by index
var/maximum_quickbound = 5 //how many quickbound scriptures we can have
+ var/ui_x = 800
+ var/ui_z = 420
+
var/obj/structure/destructible/clockwork/trap/linking //If we're linking traps together, which ones we're doing
/obj/item/clockwork/slab/internal //an internal motor for mobs running scripture
@@ -165,18 +168,19 @@
user.emote("scream")
user.apply_damage(5, BURN, BODY_ZONE_L_ARM)
user.apply_damage(5, BURN, BODY_ZONE_R_ARM)
- return 0
+ return FALSE
if(!is_servant_of_ratvar(user))
to_chat(user, "The information on [src]'s display shifts rapidly. After a moment, your head begins to pound, and you tear your eyes away.")
- user.confused += 5
- user.dizziness += 5
- return 0
+ if(user.confused || user.dizziness) //We dont want this to stack.
+ user.confused += 5
+ user.dizziness += 5
+ return FALSE
if(busy)
to_chat(user, "[src] refuses to work, displaying the message: \"[busy]!\"")
- return 0
+ return FALSE
if(!no_cost && !can_recite_scripture(user))
to_chat(user, "[src] hums fitfully in your hands, but doesn't seem to do anything...")
- return 0
+ return FALSE
access_display(user)
/obj/item/clockwork/slab/AltClick(mob/living/user)
@@ -195,11 +199,9 @@
/obj/item/clockwork/slab/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, datum/tgui/master_ui = null, datum/ui_state/state = GLOB.inventory_state)
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
if(!ui)
- ui = new(user, src, ui_key, "clockwork_slab", name, 800, 420, master_ui, state)
- ui.set_autoupdate(FALSE) //we'll update this occasionally, but not as often as possible
- ui.set_style("clockwork")
+ ui = new(user, src, ui_key, "ClockworkSlab", name, ui_x, ui_z, master_ui, state)
ui.open()
-
+
/obj/item/clockwork/slab/proc/recite_scripture(datum/clockwork_scripture/scripture, mob/living/user)
if(!scripture || !user || !user.canUseTopic(src) || (!no_cost && !can_recite_scripture(user)))
return FALSE
@@ -426,8 +428,29 @@
/obj/item/clockwork/slab/ui_data(mob/user) //we display a lot of data via TGUI
var/list/data = list()
- data["power"] = "[DisplayPower(get_clockwork_power())] power is available for scripture and other consumers."
+ data["power"] = DisplayPower(get_clockwork_power())
+ data["scripture"] = list()
+ for(var/s in GLOB.all_scripture)
+ var/datum/clockwork_scripture/S = GLOB.all_scripture[s]
+ if(S.tier == selected_scripture) //display only scriptures of the selected tier
+ var/scripture_color = get_component_color_bright(S.primary_component)
+ var/list/temp_info = list("name" = "[S.name]",
+ "descname" = "([S.descname])",
+ "tip" = "[S.desc]\n[S.usage_tip]",
+ "required" = "([DisplayPower(S.power_cost)][S.special_power_text ? "+ [replacetext(S.special_power_text, "POWERCOST", "[DisplayPower(S.special_power_cost)]")]" : ""])",
+ "type" = "[S.type]",
+ "quickbind" = S.quickbind)
+ if(S.important)
+ temp_info["name"] = "[temp_info["name"]]"
+ var/found = quickbound.Find(S.type)
+ if(found)
+ temp_info["bound"] = "[found]"
+ if(S.invokers_required > 1)
+ temp_info["invokers"] = "Invokers: [S.invokers_required]"
+ data["scripture"] += list(temp_info)
+/obj/item/clockwork/slab/ui_static_data(mob/user)
+ var/list/data = list()
switch(selected_scripture) //display info based on selected scripture tier
if(SCRIPTURE_DRIVER)
data["tier_info"] = "These scriptures are permanently unlocked."
@@ -449,26 +472,6 @@
Scriptures in purple are niche but still important!
\
Scriptures with italicized names are important to success."
generate_all_scripture()
-
- data["scripture"] = list()
- for(var/s in GLOB.all_scripture)
- var/datum/clockwork_scripture/S = GLOB.all_scripture[s]
- if(S.tier == selected_scripture) //display only scriptures of the selected tier
- var/scripture_color = get_component_color_bright(S.primary_component)
- var/list/temp_info = list("name" = "[S.name]",
- "descname" = "([S.descname])",
- "tip" = "[S.desc]\n[S.usage_tip]",
- "required" = "([DisplayPower(S.power_cost)][S.special_power_text ? "+ [replacetext(S.special_power_text, "POWERCOST", "[DisplayPower(S.special_power_cost)]")]" : ""])",
- "type" = "[S.type]",
- "quickbind" = S.quickbind)
- if(S.important)
- temp_info["name"] = "[temp_info["name"]]"
- var/found = quickbound.Find(S.type)
- if(found)
- temp_info["bound"] = "[found]"
- if(S.invokers_required > 1)
- temp_info["invokers"] = "Invokers: [S.invokers_required]"
- data["scripture"] += list(temp_info)
data["recollection"] = recollecting
if(recollecting)
data["recollection_categories"] = GLOB.ratvar_awakens ? list() : list(\
diff --git a/code/modules/antagonists/traitor/equipment/contractor.dm b/code/modules/antagonists/traitor/equipment/contractor.dm
index 6c5d5766e4..94a3059b5f 100644
--- a/code/modules/antagonists/traitor/equipment/contractor.dm
+++ b/code/modules/antagonists/traitor/equipment/contractor.dm
@@ -1,4 +1,4 @@
-// Support unit gets it's own very basic antag datum for admin logging.
+/// Support unit gets it's own very basic antag datum for admin logging.
/datum/antagonist/traitor/contractor_support
name = "Contractor Support Unit"
antag_moodlet = /datum/mood_event/focused
@@ -8,11 +8,13 @@
should_equip = FALSE /// Don't give them an uplink.
var/datum/team/contractor_team/contractor_team
-/datum/team/contractor_team // Team for storing both the contractor and their support unit - only really for the HUD and admin logging.
+/// Team for storing both the contractor and their support unit - only really for the HUD and admin logging.
+/datum/team/contractor_team
show_roundend_report = FALSE
/datum/antagonist/traitor/contractor_support/forge_traitor_objectives()
var/datum/objective/generic_objective = new
+
generic_objective.name = "Follow Contractor's Orders"
generic_objective.explanation_text = "Follow your orders. Assist agents in this mission area."
generic_objective.completed = TRUE
@@ -25,7 +27,9 @@
var/static/list/contractor_items = typecacheof(/datum/contractor_item/, TRUE)
var/datum/syndicate_contract/current_contract
var/list/datum/syndicate_contract/assigned_contracts = list()
+
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.
@@ -34,7 +38,8 @@
var/datum/contractor_item/contractor_item = new path
hub_items.Add(contractor_item)
-/datum/contractor_hub/proc/create_contracts(datum/mind/owner) // 6 initial contracts
+/datum/contractor_hub/proc/create_contracts(datum/mind/owner)
+ // 6 initial contracts
var/list/to_generate = list(
CONTRACT_PAYOUT_LARGE,
CONTRACT_PAYOUT_MEDIUM,
@@ -44,61 +49,74 @@
CONTRACT_PAYOUT_SMALL
)
- var/lowest_TC_threshold = 30 // We don't want the sum of all the payouts to be under this amount
+ //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/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/start_index = 1 // Support contract generation happening multiple times
- if(assigned_contracts.len != 0)
+ // Randomise order, so we don't have contracts always in payout order.
+ to_generate = shuffle(to_generate)
+ // Support contract generation happening multiple times
+ var/start_index = 1
+ if (assigned_contracts.len != 0)
start_index = assigned_contracts.len + 1
- for(var/i = 1; i <= to_generate.len; i++) // Generate contracts, and find the lowest paying.
+ // Generate contracts, and find the lowest paying.
+ 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))
+ 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 = start_index
assigned_contracts.Add(contract_to_add)
start_index++
- if(total < lowest_TC_threshold) // If the threshold for TC payouts isn't reached, boost the lowest paying contract
+
+ // If the threshold for TC payouts isn't reached, boost the lowest paying contract
+ if (total < lowest_TC_threshold)
lowest_paying_contract.contract.payout_bonus += (lowest_TC_threshold - total)
/datum/contractor_item
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
/datum/contractor_item/contract_reroll/handle_purchase(var/datum/contractor_hub/hub)
. = ..()
if (.)
- var/list/new_target_list = list() // We're not regenerating already completed/aborted/extracting contracts, but we don't want to repeat their targets.
+ /// We're not regenerating already completed/aborted/extracting contracts, but we don't want to repeat their targets.
+ var/list/new_target_list = list()
for(var/datum/syndicate_contract/contract_check in hub.assigned_contracts)
if (contract_check.status != CONTRACT_STATUS_ACTIVE && contract_check.status != CONTRACT_STATUS_INACTIVE)
if (contract_check.contract.target)
new_target_list.Add(contract_check.contract.target)
continue
- for(var/datum/syndicate_contract/rerolling_contract in hub.assigned_contracts) // Reroll contracts without duplicates
+ /// 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)
continue
rerolling_contract.generate(new_target_list)
new_target_list.Add(rerolling_contract.contract.target)
- hub.assigned_targets = new_target_list // Set our target list with the new set we've generated.
+ /// Set our target list with the new set we've generated.
+ hub.assigned_targets = new_target_list
/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, it can't pinpoint to the same accuracy as the traditional models. Becomes permanently locked to the user that first activates it."
@@ -125,20 +143,25 @@
/datum/contractor_item/contractor_partner/handle_purchase(var/datum/contractor_hub/hub, mob/living/user)
. = ..()
+
if (.)
to_chat(user, "The uplink vibrates quietly, connecting to nearby agents...")
- var/list/mob/candidates = pollGhostCandidates("Do you want to play as the Contractor Support Unit for [user.real_name]?", ROLE_PAI, null, FALSE, 100, POLL_IGNORE_CONTRACTOR_SUPPORT)
+
+ var/list/mob/dead/observer/candidates = pollGhostCandidates("Do you want to play as the Contractor Support Unit for [user.real_name]?", ROLE_PAI, null, FALSE, 100, POLL_IGNORE_CONTRACTOR_SUPPORT)
+
if(LAZYLEN(candidates))
var/mob/dead/observer/C = pick(candidates)
spawn_contractor_partner(user, C.key)
else
to_chat(user, "No available agents at this time, please try again later.")
- limited += 1 // refund and add the limit back.
+ // refund and add the limit back.
+ limited += 1
hub.contract_rep += cost
hub.purchased_items -= src
/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
@@ -148,28 +171,35 @@
ears = /obj/item/radio/headset/chameleon
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,
/obj/item/storage/fancy/cigarettes/cigpack_syndicate, /obj/item/lighter)
/datum/outfit/contractor_partner/post_equip(mob/living/carbon/human/H, visualsOnly)
. = ..()
- var/obj/item/clothing/mask/cigarette/syndicate/cig = H.get_item_by_slot(SLOT_WEAR_MASK)
- cig.light() // pre-light their cig for extra badass
+ var/obj/item/clothing/mask/cigarette/syndicate/cig = H.get_item_by_slot(ITEM_SLOT_MASK)
+ // pre-light their cig
+ cig.light()
/datum/contractor_item/contractor_partner/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()
+
arrival_pod.style = STYLE_SYNDICATE
arrival_pod.explosionSize = list(0,0,0,1)
arrival_pod.bluespace = TRUE
var/turf/free_location = find_obstruction_free_location(2, user)
- if (!free_location) // We really want to send them - if we can't find a nice location just land it on top of them.
+ // 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
- partner_mind = partner.mind // We give a reference to the mind that'll be the support unit
+ /// We give a reference to the mind that'll be the support unit
+ partner_mind = partner.mind
partner_mind.make_Contractor_Support()
to_chat(partner_mind.current, "\n[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_mind.current, "Should they perish, or be otherwise unavailable, you're to assist other active agents in this mission area to the best of your ability.\n\n")
@@ -186,7 +216,7 @@
. = ..()
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", "poweroff")
+ 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", "poweroff.ogg")
// Subtract cost, and spawn if it's an item.
/datum/contractor_item/proc/handle_purchase(var/datum/contractor_hub/hub, mob/living/user)
@@ -199,6 +229,7 @@
else if (limited == 0)
return FALSE
hub.purchased_items.Add(src)
+ user.playsound_local(user, 'sound/machines/uplinkpurchase.ogg', 100)
if (item && ispath(item))
var/atom/item_to_create = new item(get_turf(user))
diff --git a/code/modules/antagonists/traitor/syndicate_contract.dm b/code/modules/antagonists/traitor/syndicate_contract.dm
index 45dedb94d9..9dc79ea29c 100644
--- a/code/modules/antagonists/traitor/syndicate_contract.dm
+++ b/code/modules/antagonists/traitor/syndicate_contract.dm
@@ -68,7 +68,7 @@
empty_pod.explosionSize = list(0,0,0,1)
empty_pod.leavingSound = 'sound/effects/podwoosh.ogg'
- new /obj/effect/DPtarget(empty_pod_turf, empty_pod)
+ new /obj/effect/abstract/DPtarget(empty_pod_turf, empty_pod)
/datum/syndicate_contract/proc/enter_check(datum/source, sent_mob)
if(istype(source, /obj/structure/closet/supplypod/extractionpod))
@@ -131,7 +131,7 @@
SSshuttle.points -= 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. \
- As is policy we've taken a portion of the station's funds to offset the overall cost.", null, 'sound/ai/attention.ogg', null, "Nanotrasen Asset Protection")
+ As is policy we've taken a portion of the station's funds to offset the overall cost.", null, "attention", null, "Nanotrasen Asset Protection")
// They're off to holding - handle the return timer and give some text about what's going on.
/datum/syndicate_contract/proc/handleVictimExperience(var/mob/living/M)
@@ -199,7 +199,7 @@
M.blur_eyes(30)
M.Dizzy(35)
M.confused += 20
- new /obj/effect/DPtarget(possible_drop_loc[pod_rand_loc], return_pod)
+ new /obj/effect/abstract/DPtarget(possible_drop_loc[pod_rand_loc], return_pod)
else
to_chat(M, "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.\"")
diff --git a/code/modules/asset_cache/asset_list.dm b/code/modules/asset_cache/asset_list.dm
index 927a2ce20d..717a94c3b0 100644
--- a/code/modules/asset_cache/asset_list.dm
+++ b/code/modules/asset_cache/asset_list.dm
@@ -138,8 +138,8 @@ GLOBAL_LIST_EMPTY(asset_datums)
var/size_id = "[I.Width()]x[I.Height()]"
var/size = sizes[size_id]
- if (sprites[sprite_name])
- CRASH("duplicate sprite \"[sprite_name]\" in sheet [name] ([type])")
+ //if (sprites[sprite_name])
+ //CRASH("duplicate sprite \"[sprite_name]\" in sheet [name] ([type])") TODO FIGURE OUT WHERE THE FUCK ARE THE DUPLICATES.
if (size)
var/position = size[SPRSZ_COUNT]++
diff --git a/code/modules/asset_cache/asset_list_items.dm b/code/modules/asset_cache/asset_list_items.dm
index f77b4c6321..856f28117e 100644
--- a/code/modules/asset_cache/asset_list_items.dm
+++ b/code/modules/asset_cache/asset_list_items.dm
@@ -168,9 +168,9 @@
/datum/asset/spritesheet/goonchat/register()
InsertAll("emoji", 'icons/emoji.dmi')
- // pre-loading all lanugage icons also helps to avoid meta
+ // Pre-loading all language icons also helps to avoid meta
InsertAll("language", 'icons/misc/language.dmi')
- // catch languages which are pulling icons from another file
+ // Catch languages which are pulling icons from another file
for(var/path in typesof(/datum/language))
var/datum/language/L = path
var/icon = initial(L.icon)
diff --git a/code/modules/mining/equipment/marker_beacons.dm b/code/modules/mining/equipment/marker_beacons.dm
index 8853a56911..0a928e83c7 100644
--- a/code/modules/mining/equipment/marker_beacons.dm
+++ b/code/modules/mining/equipment/marker_beacons.dm
@@ -19,7 +19,7 @@ GLOBAL_LIST_INIT(marker_beacon_colors, list(
singular_name = "marker beacon"
desc = "Prism-brand path illumination devices. Used by miners to mark paths and warn of danger."
icon = 'icons/obj/lighting.dmi'
- icon_state = "marker"
+ icon_state = "markerbronze"
merge_type = /obj/item/stack/marker_beacon
max_amount = 100
novariants = TRUE
diff --git a/tgui/packages/tgui/interfaces/ClockworkSlab.js b/tgui/packages/tgui/interfaces/ClockworkSlab.js
new file mode 100644
index 0000000000..e41664b021
--- /dev/null
+++ b/tgui/packages/tgui/interfaces/ClockworkSlab.js
@@ -0,0 +1,18 @@
+import { useBackend } from '../backend';
+import { AnimatedNumber, Box, Button, Flex, LabeledList, Section, Table, Tabs } from '../components';
+import { Fragment } from 'inferno';
+
+export const ClockworkSlab = (props, context) => {
+ const { data } = useBackend(context);
+ const { power } = data;
+ return (
+
+
+
+
+
+ );
+};
diff --git a/tgui/packages/tgui/styles/themes/clockcult.scss b/tgui/packages/tgui/styles/themes/clockcult.scss
new file mode 100644
index 0000000000..5c44df7a8b
--- /dev/null
+++ b/tgui/packages/tgui/styles/themes/clockcult.scss
@@ -0,0 +1,56 @@
+@use 'sass:color';
+@use 'sass:meta';
+
+@use '../colors.scss' with (
+ $primary: #B18B25,
+ $fg-map-keys: (),
+ $bg-map-keys: (),
+);
+@use '../base.scss' with (
+ $color-bg: #CFBA47,
+ $color-bg-grad-spread: 6%,
+ $border-radius: 2px,
+);
+
+.theme-clockcult {
+ // Atomic classes
+ @include meta.load-css('../atomic/color.scss');
+
+ // Components
+ @include meta.load-css('../components/Button.scss', $with: (
+ 'color-default': colors.$primary,
+ 'color-disabled': #2D1400,
+ 'color-selected': #CFBA47,
+ 'color-caution': #FFAE42,
+ 'color-danger': #f0ff23,
+ ));
+ @include meta.load-css('../components/Input.scss', $with: (
+ 'border-color': #8faa2e,
+ ));
+ @include meta.load-css('../components/NoticeBox.scss', $with: (
+ 'color-background': #170800,
+ ));
+ @include meta.load-css('../components/NumberInput.scss', $with: (
+ 'border-color': #87ce87,
+ ));
+ @include meta.load-css('../components/ProgressBar.scss', $with: (
+ 'color-background': rgba(0, 0, 0, 0.5),
+ ));
+ @include meta.load-css('../components/Section.scss');
+ @include meta.load-css('../components/Tooltip.scss', $with: (
+ 'color-background': #2D1400,
+ 'border-color': #170800,
+ ));
+
+ // Layouts
+ @include meta.load-css('../layouts/Layout.scss');
+ @include meta.load-css('../layouts/Window.scss');
+ @include meta.load-css('../layouts/TitleBar.scss', $with: (
+ 'color-background': #910101,
+ ));
+
+ .Layout__content {
+ background-image: none;
+
+ }
+}