diff --git a/code/__HELPERS/roundend.dm b/code/__HELPERS/roundend.dm
index a0b29cdfac3..1b43a540b2b 100644
--- a/code/__HELPERS/roundend.dm
+++ b/code/__HELPERS/roundend.dm
@@ -312,6 +312,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(FALSE)
/datum/controller/subsystem/ticker/proc/personal_report(client/C, popcount)
diff --git a/code/datums/browser.dm b/code/datums/browser.dm
index e5d466845e6..a00113713f2 100644
--- a/code/datums/browser.dm
+++ b/code/datums/browser.dm
@@ -43,8 +43,12 @@
var/datum/asset/spritesheet/sheet = name
stylesheets["spritesheet_[sheet.name].css"] = "data/spritesheets/[sheet.name]"
else
- stylesheets["[ckey(name)].css"] = file
- register_asset("[ckey(name)].css", file)
+ var/asset_name = "[name].css"
+
+ stylesheets[asset_name] = file
+
+ if (!SSassets.cache[asset_name])
+ register_asset(asset_name, file)
/datum/browser/proc/add_script(name, file)
scripts["[ckey(name)].js"] = file
diff --git a/code/datums/mind.dm b/code/datums/mind.dm
index 06437cc401c..da01e6136d1 100644
--- a/code/datums/mind.dm
+++ b/code/datums/mind.dm
@@ -582,6 +582,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/modules/antagonists/traitor/datum_traitor.dm b/code/modules/antagonists/traitor/datum_traitor.dm
index 3582eff0eee..64ec224e416 100644
--- a/code/modules/antagonists/traitor/datum_traitor.dm
+++ b/code/modules/antagonists/traitor/datum_traitor.dm
@@ -409,19 +409,7 @@
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!
"
+ result += contractor_round_end()
if(traitorwin)
result += "The [special_role_text] was successful!"
@@ -431,12 +419,51 @@
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 = 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++
+
+ 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
+
+ /// Get all the icons/total cost for all our items bought
+ for (var/datum/contractor_item/contractor_purchase in contractor_hub.purchased_items)
+ contractor_item_icons += "\[ [contractor_purchase.name] - [contractor_purchase.cost] Rep
[contractor_purchase.desc] \]"
+
+ total_spent_rep += contractor_purchase.cost
+
+ /// Special case for reinforcements, we want to show their ckey and name on round end.
+ if (istype(contractor_purchase, /datum/contractor_item/contractor_partner))
+ 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![contractor_support_unit]
"
+
+ 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/antagonists/traitor/equipment/contractor.dm b/code/modules/antagonists/traitor/equipment/contractor.dm
index 12bbc958f9e..c6b5a149618 100644
--- a/code/modules/antagonists/traitor/equipment/contractor.dm
+++ b/code/modules/antagonists/traitor/equipment/contractor.dm
@@ -1,3 +1,29 @@
+/// 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
+
+ show_in_roundend = FALSE /// We're already adding them in to the contractor's roundend.
+ give_objectives = TRUE /// We give them their own custom objective.
+ show_in_antagpanel = FALSE /// Not a proper/full antag.
+ should_equip = FALSE /// Don't give them an uplink.
+
+ var/datum/team/contractor_team/contractor_team
+
+/// 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
+
+ add_objective(generic_objective)
+
/datum/contractor_hub
var/contract_rep = 0
var/list/hub_items = list()
@@ -5,7 +31,6 @@
var/static/list/contractor_items = typecacheof(/datum/contractor_item/, TRUE)
-
/datum/contractor_hub/proc/create_hub_items()
for(var/path in contractor_items)
var/datum/contractor_item/contractor_item = new path
@@ -42,6 +67,7 @@
item_icon = "fa-user-friends"
limited = 1
cost = 2
+ var/datum/mind/partner_mind = null
/datum/contractor_item/contractor_partner/handle_purchase(var/datum/contractor_hub/hub, mob/living/user)
. = ..()
@@ -60,6 +86,7 @@
// refund and add the limit back.
limited += 1
hub.contract_rep += cost
+ hub.purchased_items -= src
/datum/outfit/contractor_partner
name = "Contractor Support Unit"
@@ -81,7 +108,7 @@
. = ..()
var/obj/item/clothing/mask/cigarette/syndicate/cig = H.get_item_by_slot(SLOT_WEAR_MASK)
- // pre-light their cig for extra badass
+ // pre-light their cig
cig.light()
/datum/contractor_item/contractor_partner/proc/spawn_contractor_partner(mob/living/user, key)
@@ -94,8 +121,9 @@
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(3, user)
+ 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)
@@ -104,11 +132,12 @@
partner.forceMove(arrival_pod)
partner.ckey = key
- // flavour text
- to_chat(partner, "You are the Syndicate agent that answered the requested for backup. Your mission is to support the specialist agent, [user.real_name], anyway possible - you must stay with them, and follow any orders they give.
\
-
\
- Work as a team with your assigned agent, their mission comes first above all else.")
- partner.playsound_local(partner, 'sound/ambience/antag/tatoralert.ogg', 100)
+ /// 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")
new /obj/effect/DPtarget(free_location, arrival_pod)
@@ -139,6 +168,8 @@
else if (limited == 0)
return FALSE
+ hub.purchased_items.Add(src)
+
if (item && ispath(item))
var/atom/item_to_create = new item(get_turf(user))