From e0671107c1ecac9dbaa55ad686e8be6b6c2ef1a4 Mon Sep 17 00:00:00 2001
From: wraith-54321 <69217972+wraith-54321@users.noreply.github.com>
Date: Wed, 15 Nov 2023 11:36:25 -0800
Subject: [PATCH 01/60] cool
---
code/__DEFINES/admin.dm | 3 -
code/__DEFINES/~monkestation/admin.dm | 12 +++
code/__DEFINES/{ => ~monkestation}/patreon.dm | 0
code/modules/admin/topic.dm | 9 +-
code/modules/mob/login.dm | 4 +-
monkestation/code/datums/antag_tokens.dm | 2 +-
monkestation/code/datums/patreon_data.dm | 1 +
.../code/modules/admin/antag_tokens.dm | 9 +-
.../code/modules/admin/event_tokens.dm | 17 ++++
.../{ggg => smites}/where_are_your_fingers.dm | 0
.../modules/cassettes/cassette_approval.dm | 12 +--
.../code/modules/client/event_tokens.dm | 1 +
.../code/modules/client/preferences.dm | 6 ++
monkestation/code/modules/client/verbs.dm | 98 +++++++++++++------
.../modules/code_redemption/code_redeemer.dm | 2 +-
.../events/{base_event.dm => _base_event.dm} | 2 +
tgstation.dme | 9 +-
17 files changed, 128 insertions(+), 59 deletions(-)
create mode 100644 code/__DEFINES/~monkestation/admin.dm
rename code/__DEFINES/{ => ~monkestation}/patreon.dm (100%)
create mode 100644 monkestation/code/modules/admin/event_tokens.dm
rename monkestation/code/modules/admin/{ggg => smites}/where_are_your_fingers.dm (100%)
create mode 100644 monkestation/code/modules/client/event_tokens.dm
rename monkestation/code/modules/twitch_bits/events/{base_event.dm => _base_event.dm} (93%)
diff --git a/code/__DEFINES/admin.dm b/code/__DEFINES/admin.dm
index 2d29562e1ebb..6c65c1ae747d 100644
--- a/code/__DEFINES/admin.dm
+++ b/code/__DEFINES/admin.dm
@@ -73,9 +73,6 @@
#define ADMIN_SHOW_PAPER(atom) "(SHOW)"
/// Displays "(PLAY)" in the chat, when clicked it tries to play internet sounds from the request.
#define ADMIN_PLAY_INTERNET(text) "(PLAY)"
-#define ADMIN_APPROVE_TOKEN(user) "(Yes)"
-#define ADMIN_REJECT_TOKEN(user) "(No)"
-#define ADMIN_OPEN_REVIEW(id) "(Open Review)"
/atom/proc/Admin_Coordinates_Readable(area_name, admin_jump_ref)
var/turf/T = Safe_COORD_Location()
diff --git a/code/__DEFINES/~monkestation/admin.dm b/code/__DEFINES/~monkestation/admin.dm
new file mode 100644
index 000000000000..584dad8665aa
--- /dev/null
+++ b/code/__DEFINES/~monkestation/admin.dm
@@ -0,0 +1,12 @@
+#define ADMIN_APPROVE_TOKEN(user) "(Yes)"
+#define ADMIN_REJECT_TOKEN(user) "(No)"
+#define ADMIN_OPEN_REVIEW(id) "(Open Review)"
+#define ADMIN_APPROVE_TOKEN_EVENT(user) "(Yes)"
+#define ADMIN_REJECT_TOKEN_EVENT(user) "(No)"
+
+///Sends all admins the chosen sound
+#define SEND_ADMINS_NOTFICATION_SOUND(sound) for(var/client/X in GLOB.admins){X << sound;}
+///Sends a message in adminchat
+#define SEND_ADMINCHAT_MESSAGE(message) to_chat(GLOB.admins, type = MESSAGE_TYPE_ADMINCHAT, html = message, confidential = TRUE)
+///Sends a message in adminchat with the chosen notfication sound
+#define SEND_NOTFIED_ADMIN_MESSAGE(sound, message) SEND_ADMINS_NOTFICATION_SOUND(sound); SEND_ADMINCHAT_MESSAGE(message)
diff --git a/code/__DEFINES/patreon.dm b/code/__DEFINES/~monkestation/patreon.dm
similarity index 100%
rename from code/__DEFINES/patreon.dm
rename to code/__DEFINES/~monkestation/patreon.dm
diff --git a/code/modules/admin/topic.dm b/code/modules/admin/topic.dm
index b3600978a9a6..807cc82af0bc 100644
--- a/code/modules/admin/topic.dm
+++ b/code/modules/admin/topic.dm
@@ -1758,7 +1758,7 @@
return
web_sound(usr, link_url)
-
+//monkestation edit start
else if(href_list["approve_token"])
if(!check_rights(R_ADMIN))
return
@@ -1766,7 +1766,7 @@
if(!IS_CLIENT_OR_MOCK(target))
return
var/client/user_client = target
- user_client.saved_tokens.approve_token()
+ user_client.client_saved_tokens.approve_token()
message_admins("[user_client]'s token has been approved, by [owner]")
else if(href_list["reject_token"])
@@ -1776,7 +1776,7 @@
if(!IS_CLIENT_OR_MOCK(target))
return
var/client/user_client = target
- user_client.saved_tokens.reject_token()
+ user_client.client_saved_tokens.reject_token()
message_admins("[user_client]'s token has been rejected, by [owner]")
else if(href_list["open_music_review"])
@@ -1787,3 +1787,6 @@
if(!istype(cassette_review))
return
cassette_review.ui_interact(usr)
+
+ else if()
+//monkestation edit end
diff --git a/code/modules/mob/login.dm b/code/modules/mob/login.dm
index d7300dcbabbc..a3d0262f4960 100644
--- a/code/modules/mob/login.dm
+++ b/code/modules/mob/login.dm
@@ -131,8 +131,8 @@
if(!client.patreon)
client.patreon = new(client)
- if(!client.saved_tokens)
- client.saved_tokens = new(client)
+ if(!client.client_saved_tokens)
+ client.client_saved_tokens = new(client)
return TRUE
diff --git a/monkestation/code/datums/antag_tokens.dm b/monkestation/code/datums/antag_tokens.dm
index 0654ffb30693..ec5df443fe4b 100644
--- a/monkestation/code/datums/antag_tokens.dm
+++ b/monkestation/code/datums/antag_tokens.dm
@@ -1,7 +1,7 @@
GLOBAL_LIST_INIT(used_monthly_token, list())
/client
- var/datum/antag_token_holder/saved_tokens
+ var/datum/antag_token_holder/client_saved_tokens
/datum/antag_token_holder
var/client/owner
diff --git a/monkestation/code/datums/patreon_data.dm b/monkestation/code/datums/patreon_data.dm
index f64889c11f66..6c8629fc3c41 100644
--- a/monkestation/code/datums/patreon_data.dm
+++ b/monkestation/code/datums/patreon_data.dm
@@ -1,5 +1,6 @@
/client
var/datum/patreon_data/patreon
+
/datum/patreon_data
///the client that owns this data
var/client/owner
diff --git a/monkestation/code/modules/admin/antag_tokens.dm b/monkestation/code/modules/admin/antag_tokens.dm
index 9698d8d93151..4947d1a13756 100644
--- a/monkestation/code/modules/admin/antag_tokens.dm
+++ b/monkestation/code/modules/admin/antag_tokens.dm
@@ -4,17 +4,16 @@
set name = "Adjust Antag Tokens"
set desc = "You can modifiy a targets metacoin balance by adding or subtracting."
- var/mob/chosen_player
- chosen_player = tgui_input_list(src, "Choose a Player", "Player List", GLOB.player_list)
+ var/mob/chosen_player = tgui_input_list(src, "Choose a Player", "Player List", GLOB.player_list)
if(!chosen_player)
return
- var/client/chosen_client = chosen_player.client
+ var/client/chosen_client = chosen_player.client
var/adjustment_amount = tgui_input_number(src, "How much should we adjust this users antag tokens by?", "Input Value", TRUE, 10, -10)
- if(!adjustment_amount)
+ if(!adjustment_amount || !chosen_client)
return
var/tier = tgui_input_list(src, "Choose a tier for the token", "Tier list", list(HIGH_THREAT, MEDIUM_THREAT, LOW_THREAT))
if(!tier)
return
- chosen_client.saved_tokens.adjust_tokens(tier, adjustment_amount)
+ chosen_client.client_saved_tokens.adjust_tokens(tier, adjustment_amount)
diff --git a/monkestation/code/modules/admin/event_tokens.dm b/monkestation/code/modules/admin/event_tokens.dm
new file mode 100644
index 000000000000..1c633ebde0fd
--- /dev/null
+++ b/monkestation/code/modules/admin/event_tokens.dm
@@ -0,0 +1,17 @@
+/client/proc/set_players_event_tokens()
+ set category = "Admin.Fun"
+//due to the fact that these reset each month im just making this directly this this value instead of add or subtract
+ set name = "Set Event Tokens"
+ set desc = "Set how many event tokens someone has."
+
+ var/mob/chosen_player = tgui_input_list(src, "Choose a Player", "Player List", GLOB.player_list)
+ if(!chosen_player)
+ return
+
+ var/client/chosen_client = chosen_player.client
+ var/adjustment_amount = tgui_input_number(src, "What should we set this users tokens to?", "Input Value", TRUE)
+ if(!adjustment_amount || !chosen_client || !chosen_client.patreon)
+ return
+
+ check_event_tokens(chosen_client)
+ chosen_client.prefs.event_tokens = adjustment_amount
diff --git a/monkestation/code/modules/admin/ggg/where_are_your_fingers.dm b/monkestation/code/modules/admin/smites/where_are_your_fingers.dm
similarity index 100%
rename from monkestation/code/modules/admin/ggg/where_are_your_fingers.dm
rename to monkestation/code/modules/admin/smites/where_are_your_fingers.dm
diff --git a/monkestation/code/modules/cassettes/cassette_approval.dm b/monkestation/code/modules/cassettes/cassette_approval.dm
index 6bae8ae8a81b..c758bb1dc658 100644
--- a/monkestation/code/modules/cassettes/cassette_approval.dm
+++ b/monkestation/code/modules/cassettes/cassette_approval.dm
@@ -20,16 +20,8 @@ GLOBAL_LIST_INIT(cassette_reviews, list())
new_review.submitted_tape = submitted
GLOB.cassette_reviews["[new_review.id]"] = new_review
-
- var/message = "[span_big(span_admin("[span_prefix("MUSIC APPROVAL:")] [key_name(user)] [ADMIN_OPEN_REVIEW(new_review.id)] has requested a review on their cassette."))]"
-
- for(var/client/X in GLOB.admins)
- X << 'sound/items/bikehorn.ogg'
-
- to_chat(GLOB.admins,
- type = MESSAGE_TYPE_ADMINCHAT,
- html = message,
- confidential = TRUE)
+ SEND_NOTIFIED_ADMIN_MESSAGE('sound/items/bikehorn.ogg', "[span_big(span_admin("[span_prefix("MUSIC APPROVAL:")] [key_name(user)] [ADMIN_OPEN_REVIEW(new_review.id)] \
+ has requested a review on their cassette."))]")
to_chat(user, span_notice("Your Cassette has been sent to the Space Board of Music for review, you will be notified when an outcome has been made."))
/obj/item/device/cassette_tape/proc/generate_cassette_json()
diff --git a/monkestation/code/modules/client/event_tokens.dm b/monkestation/code/modules/client/event_tokens.dm
new file mode 100644
index 000000000000..8b137891791f
--- /dev/null
+++ b/monkestation/code/modules/client/event_tokens.dm
@@ -0,0 +1 @@
+
diff --git a/monkestation/code/modules/client/preferences.dm b/monkestation/code/modules/client/preferences.dm
index a266c0a24036..226aae63cf2b 100644
--- a/monkestation/code/modules/client/preferences.dm
+++ b/monkestation/code/modules/client/preferences.dm
@@ -30,3 +30,9 @@
var/list/alt_job_titles = list()
/// the month we used our last donator token on
var/token_month = 0
+
+ ///how many event tokens we currently have
+ var/event_tokens = 0
+ ///the month we last used event tokens on
+ var/event_token_month = 0
+ ///what token event do we currently have queued
diff --git a/monkestation/code/modules/client/verbs.dm b/monkestation/code/modules/client/verbs.dm
index 40fbcc906dc9..7e5780f1a99c 100644
--- a/monkestation/code/modules/client/verbs.dm
+++ b/monkestation/code/modules/client/verbs.dm
@@ -16,7 +16,16 @@ GLOBAL_LIST_INIT(low_threat_antags, list(
/datum/antagonist/paradox_clone,
))
-
+//PLACEHOLDER VALUES(1 to 1 cent to token conversion, also you get a free token if you dont pay yeah totally)
+///assoc list of how many event tokens each role gets each month
+GLOBAL_LIST_INIT(patreon_etoken_values, list(
+ NO_RANK = 0,
+ RANK_TANKS = 100,
+ ASSISTANT_RANK = 500,
+ COMMAND_RANK = 1000,
+ TRAITOR_RANK = 2500,
+ NUKIE_RANK = 5000,
+))
/client/verb/spend_antag_tokens()
set category = "IC"
@@ -31,15 +40,18 @@ GLOBAL_LIST_INIT(low_threat_antags, list(
if(isobserver(mob))
to_chat(src, span_notice("NOTE: You will be spawned where ever your ghost is when approved, so becareful where you are."))
- if(!saved_tokens)
- saved_tokens = new(src)
+ if(!client_saved_tokens)
+ client_saved_tokens = new(src)
- var/tier = tgui_input_list(src, "High:[saved_tokens.total_high_threat_tokens] | Med: [saved_tokens.total_medium_threat_tokens] | Low: [saved_tokens.total_low_threat_tokens] | Donator:[saved_tokens.donator_token]", "Choose A Tier To Spend", list(HIGH_THREAT, MEDIUM_THREAT, LOW_THREAT))
+ var/tier = tgui_input_list(src, "High:[client_saved_tokens.total_high_threat_tokens] | \
+ Med: [client_saved_tokens.total_medium_threat_tokens] | \
+ Low: [client_saved_tokens.total_low_threat_tokens] | \
+ Donator:[client_saved_tokens.donator_token]", "Choose A Tier To Spend", list(HIGH_THREAT, MEDIUM_THREAT, LOW_THREAT))
if(!tier)
return
var/using_donor = FALSE
- if(saved_tokens.donator_token)
+ if(client_saved_tokens.donator_token)
var/choice = tgui_alert(src, "Use Donator Token?" , "Spend Tokens", list("Yes", "No"))
if(choice == "Yes")
using_donor = TRUE
@@ -47,41 +59,65 @@ GLOBAL_LIST_INIT(low_threat_antags, list(
if(!using_donor)
switch(tier)
if(HIGH_THREAT)
- if(saved_tokens.total_high_threat_tokens <= 0)
+ if(client_saved_tokens.total_high_threat_tokens <= 0)
return
if(MEDIUM_THREAT)
- if(saved_tokens.total_medium_threat_tokens <= 0)
+ if(client_saved_tokens.total_medium_threat_tokens <= 0)
return
if(LOW_THREAT)
- if(saved_tokens.total_low_threat_tokens <= 0)
+ if(client_saved_tokens.total_low_threat_tokens <= 0)
return
var/datum/antagonist/chosen_antagonist
- switch(tier)
- if(HIGH_THREAT)
- chosen_antagonist = tgui_input_list(src, "Choose an Antagonist", "Spend Tokens", GLOB.high_threat_antags)
- if(MEDIUM_THREAT)
- chosen_antagonist = tgui_input_list(src, "Choose an Antagonist", "Spend Tokens", GLOB.medium_threat_antags)
- if(LOW_THREAT)
- chosen_antagonist = tgui_input_list(src, "Choose an Antagonist", "Spend Tokens", GLOB.low_threat_antags)
+ var/static/list/token_values = list(
+ HIGH_THREAT = GLOB.high_threat_antags,
+ MEDIUM_THREAT = GLOB.medium_threat_antags,
+ LOW_THREAT = GLOB.low_threat_antags,
+ )
+ chosen_antagonist = tgui_input_list(src, "Choose an Antagonist", "Spend Tokens", token_values[tier])
if(!chosen_antagonist)
return
- saved_tokens.queued_donor = using_donor
- saved_tokens.in_queued_tier = tier
- saved_tokens.in_queue = new chosen_antagonist
+ client_saved_tokens.queued_donor = using_donor
+ client_saved_tokens.in_queued_tier = tier
+ client_saved_tokens.in_queue = new chosen_antagonist
to_chat(src, "Your request has been sent to the admins.")
- wait_for_approval(src, chosen_antagonist)
-
-
-/proc/wait_for_approval(client/requestor, datum/antagonist/requested_antag)
- var/msg = "[span_admin("[span_prefix("ANTAG TOKEN:")] [key_name(requestor)] [ADMIN_APPROVE_TOKEN(requestor)] [ADMIN_REJECT_TOKEN(requestor)] | [requestor] has requested to use their antag token to be a [requested_antag].")]"
-
- for(var/client/X in GLOB.admins)
- X << 'sound/items/bikehorn.ogg'
-
- to_chat(GLOB.admins,
- type = MESSAGE_TYPE_ADMINCHAT,
- html = msg,
- confidential = TRUE)
+ SEND_NOTFIED_ADMIN_MESSAGE('sound/items/bikehorn.ogg', "[span_admin("[span_prefix("ANTAG TOKEN:")] [key_name(src)] [ADMIN_APPROVE_TOKEN(src)] [ADMIN_REJECT_TOKEN(src)] | \
+ [src] has requested to use their antag token to be a [chosen_antagonist].")]")
+
+/client/proc/trigger_token_event()
+ set category = "Ghost"
+ set name = "Trigger Token Event"
+ set desc = "Opens a ui to spend event tokens on"
+
+ if(!isobserver(mob))
+ to_chat(src, "You can only trigger events as a ghost.")
+
+ var/static/list/event_list
+ if(!event_list)
+ event_list = subtypesof(/datum/twitch_event)
+ for(var/datum/twitch_event/event as anything in event_list)
+ if(!event.token_cost)
+ event_list -= event
+
+ check_event_tokens(src)
+
+ var/datum/twitch_event/selected_event = tgui_input_list(src, "Event tokens: [prefs.event_tokens]", "Choose an event to trigger", event_list)
+ var/confirm = tgui_alert(src, "Are you sure you want to trigger [selected_event.event_name]? It will cost [selected_event.token_cost] event tokens.", "Trigger token event", \
+ list("Yes", "No"))
+ if(confirm == "Yes")
+ if(prefs.event_tokens >= selected_event.token_cost)
+ SEND_NOTFIED_ADMIN_MESSAGE('sound/items/bikehorn.ogg', "MESSAGE")
+ return
+ to_chat(src, "You dont have enough tokens to trigger this event.")
+
+/proc/approve_token_event()
+
+/proc/reject_token_event()
+
+/proc/check_event_tokens(client/checked_client)
+ var/month_number = text2num(time2text(world.time, "MM"))
+ if(checked_client.prefs.event_token_month != month_number)
+ checked_client.prefs.event_token_month = month_number
+ checked_client.prefs.event_tokens = GLOB.patreon_etoken_values[checked_client.patreon.owned_rank]
diff --git a/monkestation/code/modules/code_redemption/code_redeemer.dm b/monkestation/code/modules/code_redemption/code_redeemer.dm
index d02aeaa14ea8..cf0e7941e8ef 100644
--- a/monkestation/code/modules/code_redemption/code_redeemer.dm
+++ b/monkestation/code/modules/code_redemption/code_redeemer.dm
@@ -26,7 +26,7 @@ GLOBAL_LIST_INIT(redeemed_codes, list())
if(isnum(path))
usr.client.prefs.adjust_metacoins(usr.ckey, path, "Redeemed a Giveaway Code", donator_multipler = FALSE)
else if(path == HIGH_THREAT || path == MEDIUM_THREAT || path == LOW_THREAT)
- usr.client.saved_tokens.adjust_tokens(path, 1)
+ usr.client.client_saved_tokens.adjust_tokens(path, 1)
to_chat(usr, span_boldnotice("You have successfully redeemed a giveaway code for: [path] Antag Token."))
else
var/pathedstring = text2path(path)
diff --git a/monkestation/code/modules/twitch_bits/events/base_event.dm b/monkestation/code/modules/twitch_bits/events/_base_event.dm
similarity index 93%
rename from monkestation/code/modules/twitch_bits/events/base_event.dm
rename to monkestation/code/modules/twitch_bits/events/_base_event.dm
index b38ecfb8691f..ead023a1c4f6 100644
--- a/monkestation/code/modules/twitch_bits/events/base_event.dm
+++ b/monkestation/code/modules/twitch_bits/events/_base_event.dm
@@ -13,6 +13,8 @@
var/id_tag
///should we announce this event
var/announce = TRUE
+ ///how many event tokens does this cost to trigger
+ var/token_cost = 0
/datum/twitch_event/proc/run_event(name)
if(event_flags & TWITCH_AFFECTS_STREAMER)
diff --git a/tgstation.dme b/tgstation.dme
index d3bc1729f965..70a2d47a85eb 100644
--- a/tgstation.dme
+++ b/tgstation.dme
@@ -175,7 +175,6 @@
#include "code\__DEFINES\paper.dm"
#include "code\__DEFINES\particles.dm"
#include "code\__DEFINES\path.dm"
-#include "code\__DEFINES\patreon.dm"
#include "code\__DEFINES\perf_test.dm"
#include "code\__DEFINES\pinpointers.dm"
#include "code\__DEFINES\pipe_construction.dm"
@@ -371,6 +370,7 @@
#include "code\__DEFINES\research\anomalies.dm"
#include "code\__DEFINES\research\research_categories.dm"
#include "code\__DEFINES\~monkestation\access.dm"
+#include "code\__DEFINES\~monkestation\admin.dm"
#include "code\__DEFINES\~monkestation\ai.dm"
#include "code\__DEFINES\~monkestation\antagonists.dm"
#include "code\__DEFINES\~monkestation\clock_cult.dm"
@@ -386,6 +386,7 @@
#include "code\__DEFINES\~monkestation\mecha.dm"
#include "code\__DEFINES\~monkestation\misc.dm"
#include "code\__DEFINES\~monkestation\mobs.dm"
+#include "code\__DEFINES\~monkestation\patreon.dm"
#include "code\__DEFINES\~monkestation\robots.dm"
#include "code\__DEFINES\~monkestation\smoothing.dm"
#include "code\__DEFINES\~monkestation\span.dm"
@@ -5552,9 +5553,10 @@
#include "monkestation\code\game\turfs\open\water.dm"
#include "monkestation\code\modules\admin\antag_tokens.dm"
#include "monkestation\code\modules\admin\camera_view.dm"
-#include "monkestation\code\modules\admin\ggg\where_are_your_fingers.dm"
+#include "monkestation\code\modules\admin\event_tokens.dm"
#include "monkestation\code\modules\admin\smites\dagothkillsmite.dm"
#include "monkestation\code\modules\admin\smites\dagothstripsmite.dm"
+#include "monkestation\code\modules\admin\smites\where_are_your_fingers.dm"
#include "monkestation\code\modules\aesthetics\airlock\airlock.dm"
#include "monkestation\code\modules\aesthetics\items\clothing.dm"
#include "monkestation\code\modules\aesthetics\mapping\tilecoloring.dm"
@@ -5812,6 +5814,7 @@
#include "monkestation\code\modules\cassettes\machines\media\track.dm"
#include "monkestation\code\modules\cassettes\machines\media\subsystem\media_track_manager.dm"
#include "monkestation\code\modules\cassettes\walkman\_walkmen.dm"
+#include "monkestation\code\modules\client\event_tokens.dm"
#include "monkestation\code\modules\client\preference_savefile.dm"
#include "monkestation\code\modules\client\preferences.dm"
#include "monkestation\code\modules\client\verbs.dm"
@@ -6349,10 +6352,10 @@
#include "monkestation\code\modules\surgery\organs\internal\tongue.dm"
#include "monkestation\code\modules\twitch_bits\admin_command.dm"
#include "monkestation\code\modules\twitch_bits\twitch_system.dm"
+#include "monkestation\code\modules\twitch_bits\events\_base_event.dm"
#include "monkestation\code\modules\twitch_bits\events\amongus.dm"
#include "monkestation\code\modules\twitch_bits\events\anime_ook.dm"
#include "monkestation\code\modules\twitch_bits\events\australia_mode.dm"
-#include "monkestation\code\modules\twitch_bits\events\base_event.dm"
#include "monkestation\code\modules\twitch_bits\events\buff.dm"
#include "monkestation\code\modules\twitch_bits\events\chuckle_nut.dm"
#include "monkestation\code\modules\twitch_bits\events\die_fate.dm"
From f8ca0c542128192855a8dfcf0af921158d57885e Mon Sep 17 00:00:00 2001
From: wraith-54321 <69217972+wraith-54321@users.noreply.github.com>
Date: Wed, 15 Nov 2023 11:48:45 -0800
Subject: [PATCH 02/60] meta tokens
---
code/modules/admin/topic.dm | 2 +-
.../{antag_tokens.dm => meta_tokens.dm} | 20 +++++++++----------
.../modules/cassettes/cassette_approval.dm | 2 +-
.../code/modules/client/preferences.dm | 1 +
tgstation.dme | 2 +-
5 files changed, 14 insertions(+), 13 deletions(-)
rename monkestation/code/datums/{antag_tokens.dm => meta_tokens.dm} (83%)
diff --git a/code/modules/admin/topic.dm b/code/modules/admin/topic.dm
index 807cc82af0bc..22800494bfef 100644
--- a/code/modules/admin/topic.dm
+++ b/code/modules/admin/topic.dm
@@ -1788,5 +1788,5 @@
return
cassette_review.ui_interact(usr)
- else if()
+// else if()
//monkestation edit end
diff --git a/monkestation/code/datums/antag_tokens.dm b/monkestation/code/datums/meta_tokens.dm
similarity index 83%
rename from monkestation/code/datums/antag_tokens.dm
rename to monkestation/code/datums/meta_tokens.dm
index ec5df443fe4b..454ee33c7126 100644
--- a/monkestation/code/datums/antag_tokens.dm
+++ b/monkestation/code/datums/meta_tokens.dm
@@ -1,9 +1,9 @@
GLOBAL_LIST_INIT(used_monthly_token, list())
/client
- var/datum/antag_token_holder/client_saved_tokens
+ var/datum/meta_token_holder/client_saved_tokens
-/datum/antag_token_holder
+/datum/meta_token_holder
var/client/owner
///are they a donator? and do they have their free token?
var/donator_token = FALSE
@@ -20,7 +20,7 @@ GLOBAL_LIST_INIT(used_monthly_token, list())
var/in_queued_tier
var/queued_donor = FALSE
-/datum/antag_token_holder/New(client/creator)
+/datum/meta_token_holder/New(client/creator)
. = ..()
if(!creator)
return
@@ -30,7 +30,7 @@ GLOBAL_LIST_INIT(used_monthly_token, list())
convert_list_to_tokens(owners_prefs.saved_tokens)
donator_token = check_for_donator_token()
-/datum/antag_token_holder/proc/convert_list_to_tokens(list/saved_tokens)
+/datum/meta_token_holder/proc/convert_list_to_tokens(list/saved_tokens)
if(!length(saved_tokens))
return
total_low_threat_tokens = saved_tokens["low_threat"]
@@ -39,7 +39,7 @@ GLOBAL_LIST_INIT(used_monthly_token, list())
total_antag_tokens = total_low_threat_tokens + total_medium_threat_tokens + total_high_threat_tokens
-/datum/antag_token_holder/proc/convert_tokens_to_list()
+/datum/meta_token_holder/proc/convert_tokens_to_list()
owner.prefs.saved_tokens = list(
"low_threat" = total_low_threat_tokens,
"medium_threat" = total_medium_threat_tokens,
@@ -47,7 +47,7 @@ GLOBAL_LIST_INIT(used_monthly_token, list())
)
owner.prefs.save_preferences()
-/datum/antag_token_holder/proc/check_for_donator_token()
+/datum/meta_token_holder/proc/check_for_donator_token()
if(!owner.patreon)
return FALSE
if(!owner.patreon.has_access(ACCESS_TRAITOR_RANK))
@@ -57,7 +57,7 @@ GLOBAL_LIST_INIT(used_monthly_token, list())
return FALSE
return TRUE
-/datum/antag_token_holder/proc/spend_token(tier, use_donor = FALSE)
+/datum/meta_token_holder/proc/spend_token(tier, use_donor = FALSE)
if(use_donor)
if(donator_token)
donator_token = FALSE
@@ -76,7 +76,7 @@ GLOBAL_LIST_INIT(used_monthly_token, list())
convert_tokens_to_list()
///adjusts the users tokens, yes they can be in antag token debt
-/datum/antag_token_holder/proc/adjust_tokens(tier, amount)
+/datum/meta_token_holder/proc/adjust_tokens(tier, amount)
switch(tier)
if(HIGH_THREAT)
total_high_threat_tokens += amount
@@ -88,7 +88,7 @@ GLOBAL_LIST_INIT(used_monthly_token, list())
convert_tokens_to_list()
-/datum/antag_token_holder/proc/approve_token()
+/datum/meta_token_holder/proc/approve_token()
if(!in_queue)
return
to_chat(owner, "Your request to play as [in_queue] has been approved.")
@@ -103,7 +103,7 @@ GLOBAL_LIST_INIT(used_monthly_token, list())
in_queued_tier = null
queued_donor = FALSE
-/datum/antag_token_holder/proc/reject_token()
+/datum/meta_token_holder/proc/reject_token()
to_chat(owner, "Your request to play as [in_queue] has been denied.")
in_queue = null
in_queued_tier = null
diff --git a/monkestation/code/modules/cassettes/cassette_approval.dm b/monkestation/code/modules/cassettes/cassette_approval.dm
index c758bb1dc658..d658372c26c4 100644
--- a/monkestation/code/modules/cassettes/cassette_approval.dm
+++ b/monkestation/code/modules/cassettes/cassette_approval.dm
@@ -20,7 +20,7 @@ GLOBAL_LIST_INIT(cassette_reviews, list())
new_review.submitted_tape = submitted
GLOB.cassette_reviews["[new_review.id]"] = new_review
- SEND_NOTIFIED_ADMIN_MESSAGE('sound/items/bikehorn.ogg', "[span_big(span_admin("[span_prefix("MUSIC APPROVAL:")] [key_name(user)] [ADMIN_OPEN_REVIEW(new_review.id)] \
+ SEND_NOTFIED_ADMIN_MESSAGE('sound/items/bikehorn.ogg', "[span_big(span_admin("[span_prefix("MUSIC APPROVAL:")] [key_name(user)] [ADMIN_OPEN_REVIEW(new_review.id)] \
has requested a review on their cassette."))]")
to_chat(user, span_notice("Your Cassette has been sent to the Space Board of Music for review, you will be notified when an outcome has been made."))
diff --git a/monkestation/code/modules/client/preferences.dm b/monkestation/code/modules/client/preferences.dm
index 226aae63cf2b..8086108e086f 100644
--- a/monkestation/code/modules/client/preferences.dm
+++ b/monkestation/code/modules/client/preferences.dm
@@ -36,3 +36,4 @@
///the month we last used event tokens on
var/event_token_month = 0
///what token event do we currently have queued
+ var/datum/twitch_event/queued_token_event
diff --git a/tgstation.dme b/tgstation.dme
index 70a2d47a85eb..dcc757bda72c 100644
--- a/tgstation.dme
+++ b/tgstation.dme
@@ -5474,9 +5474,9 @@
#include "monkestation\code\__HELPERS\turfs.dm"
#include "monkestation\code\_onclick\hud\alert.dm"
#include "monkestation\code\datums\action.dm"
-#include "monkestation\code\datums\antag_tokens.dm"
#include "monkestation\code\datums\emotes.dm"
#include "monkestation\code\datums\interaction_particle.dm"
+#include "monkestation\code\datums\meta_tokens.dm"
#include "monkestation\code\datums\patreon_data.dm"
#include "monkestation\code\datums\stamina_container.dm"
#include "monkestation\code\datums\ai\idle_behaviors\idle_dukeman.dm"
From 34a339d9898a71917071eb1b99a6046cb5560d2b Mon Sep 17 00:00:00 2001
From: wraith-54321 <69217972+wraith-54321@users.noreply.github.com>
Date: Wed, 15 Nov 2023 11:50:57 -0800
Subject: [PATCH 03/60] client token holder
---
code/modules/admin/topic.dm | 4 +--
code/modules/mob/login.dm | 4 +--
monkestation/code/datums/meta_tokens.dm | 2 +-
.../code/modules/admin/antag_tokens.dm | 2 +-
monkestation/code/modules/client/verbs.dm | 26 +++++++++----------
.../modules/code_redemption/code_redeemer.dm | 2 +-
6 files changed, 20 insertions(+), 20 deletions(-)
diff --git a/code/modules/admin/topic.dm b/code/modules/admin/topic.dm
index 22800494bfef..b1a08181f125 100644
--- a/code/modules/admin/topic.dm
+++ b/code/modules/admin/topic.dm
@@ -1766,7 +1766,7 @@
if(!IS_CLIENT_OR_MOCK(target))
return
var/client/user_client = target
- user_client.client_saved_tokens.approve_token()
+ user_client.client_token_holder.approve_token()
message_admins("[user_client]'s token has been approved, by [owner]")
else if(href_list["reject_token"])
@@ -1776,7 +1776,7 @@
if(!IS_CLIENT_OR_MOCK(target))
return
var/client/user_client = target
- user_client.client_saved_tokens.reject_token()
+ user_client.client_token_holder.reject_token()
message_admins("[user_client]'s token has been rejected, by [owner]")
else if(href_list["open_music_review"])
diff --git a/code/modules/mob/login.dm b/code/modules/mob/login.dm
index a3d0262f4960..a1e9324a535c 100644
--- a/code/modules/mob/login.dm
+++ b/code/modules/mob/login.dm
@@ -131,8 +131,8 @@
if(!client.patreon)
client.patreon = new(client)
- if(!client.client_saved_tokens)
- client.client_saved_tokens = new(client)
+ if(!client.client_token_holder)
+ client.client_token_holder = new(client)
return TRUE
diff --git a/monkestation/code/datums/meta_tokens.dm b/monkestation/code/datums/meta_tokens.dm
index 454ee33c7126..aa0d32cc6c6c 100644
--- a/monkestation/code/datums/meta_tokens.dm
+++ b/monkestation/code/datums/meta_tokens.dm
@@ -1,7 +1,7 @@
GLOBAL_LIST_INIT(used_monthly_token, list())
/client
- var/datum/meta_token_holder/client_saved_tokens
+ var/datum/meta_token_holder/client_token_holder
/datum/meta_token_holder
var/client/owner
diff --git a/monkestation/code/modules/admin/antag_tokens.dm b/monkestation/code/modules/admin/antag_tokens.dm
index 4947d1a13756..def24b5fdea1 100644
--- a/monkestation/code/modules/admin/antag_tokens.dm
+++ b/monkestation/code/modules/admin/antag_tokens.dm
@@ -16,4 +16,4 @@
if(!tier)
return
- chosen_client.client_saved_tokens.adjust_tokens(tier, adjustment_amount)
+ chosen_client.client_token_holder.adjust_tokens(tier, adjustment_amount)
diff --git a/monkestation/code/modules/client/verbs.dm b/monkestation/code/modules/client/verbs.dm
index 7e5780f1a99c..a62bfebb884d 100644
--- a/monkestation/code/modules/client/verbs.dm
+++ b/monkestation/code/modules/client/verbs.dm
@@ -40,18 +40,18 @@ GLOBAL_LIST_INIT(patreon_etoken_values, list(
if(isobserver(mob))
to_chat(src, span_notice("NOTE: You will be spawned where ever your ghost is when approved, so becareful where you are."))
- if(!client_saved_tokens)
- client_saved_tokens = new(src)
+ if(!client_token_holder)
+ client_token_holder = new(src)
- var/tier = tgui_input_list(src, "High:[client_saved_tokens.total_high_threat_tokens] | \
- Med: [client_saved_tokens.total_medium_threat_tokens] | \
- Low: [client_saved_tokens.total_low_threat_tokens] | \
- Donator:[client_saved_tokens.donator_token]", "Choose A Tier To Spend", list(HIGH_THREAT, MEDIUM_THREAT, LOW_THREAT))
+ var/tier = tgui_input_list(src, "High:[client_token_holder.total_high_threat_tokens] | \
+ Med: [client_token_holder.total_medium_threat_tokens] | \
+ Low: [client_token_holder.total_low_threat_tokens] | \
+ Donator:[client_token_holder.donator_token]", "Choose A Tier To Spend", list(HIGH_THREAT, MEDIUM_THREAT, LOW_THREAT))
if(!tier)
return
var/using_donor = FALSE
- if(client_saved_tokens.donator_token)
+ if(client_token_holder.donator_token)
var/choice = tgui_alert(src, "Use Donator Token?" , "Spend Tokens", list("Yes", "No"))
if(choice == "Yes")
using_donor = TRUE
@@ -59,13 +59,13 @@ GLOBAL_LIST_INIT(patreon_etoken_values, list(
if(!using_donor)
switch(tier)
if(HIGH_THREAT)
- if(client_saved_tokens.total_high_threat_tokens <= 0)
+ if(client_token_holder.total_high_threat_tokens <= 0)
return
if(MEDIUM_THREAT)
- if(client_saved_tokens.total_medium_threat_tokens <= 0)
+ if(client_token_holder.total_medium_threat_tokens <= 0)
return
if(LOW_THREAT)
- if(client_saved_tokens.total_low_threat_tokens <= 0)
+ if(client_token_holder.total_low_threat_tokens <= 0)
return
var/datum/antagonist/chosen_antagonist
@@ -78,9 +78,9 @@ GLOBAL_LIST_INIT(patreon_etoken_values, list(
if(!chosen_antagonist)
return
- client_saved_tokens.queued_donor = using_donor
- client_saved_tokens.in_queued_tier = tier
- client_saved_tokens.in_queue = new chosen_antagonist
+ client_token_holder.queued_donor = using_donor
+ client_token_holder.in_queued_tier = tier
+ client_token_holder.in_queue = new chosen_antagonist
to_chat(src, "Your request has been sent to the admins.")
SEND_NOTFIED_ADMIN_MESSAGE('sound/items/bikehorn.ogg', "[span_admin("[span_prefix("ANTAG TOKEN:")] [key_name(src)] [ADMIN_APPROVE_TOKEN(src)] [ADMIN_REJECT_TOKEN(src)] | \
diff --git a/monkestation/code/modules/code_redemption/code_redeemer.dm b/monkestation/code/modules/code_redemption/code_redeemer.dm
index cf0e7941e8ef..7e394286b0d4 100644
--- a/monkestation/code/modules/code_redemption/code_redeemer.dm
+++ b/monkestation/code/modules/code_redemption/code_redeemer.dm
@@ -26,7 +26,7 @@ GLOBAL_LIST_INIT(redeemed_codes, list())
if(isnum(path))
usr.client.prefs.adjust_metacoins(usr.ckey, path, "Redeemed a Giveaway Code", donator_multipler = FALSE)
else if(path == HIGH_THREAT || path == MEDIUM_THREAT || path == LOW_THREAT)
- usr.client.client_saved_tokens.adjust_tokens(path, 1)
+ usr.client.client_token_holder.adjust_tokens(path, 1)
to_chat(usr, span_boldnotice("You have successfully redeemed a giveaway code for: [path] Antag Token."))
else
var/pathedstring = text2path(path)
From f74ee9a7bba79382548626e7c184d3ae838bf657 Mon Sep 17 00:00:00 2001
From: wraith-54321 <69217972+wraith-54321@users.noreply.github.com>
Date: Wed, 15 Nov 2023 12:08:33 -0800
Subject: [PATCH 04/60] well
---
code/__DEFINES/~monkestation/admin.dm | 4 ++--
code/modules/admin/topic.dm | 4 ++--
monkestation/code/datums/meta_tokens.dm | 17 ++++++++++++++---
monkestation/code/modules/client/preferences.dm | 9 ++-------
4 files changed, 20 insertions(+), 14 deletions(-)
diff --git a/code/__DEFINES/~monkestation/admin.dm b/code/__DEFINES/~monkestation/admin.dm
index 584dad8665aa..bf7b9207aa53 100644
--- a/code/__DEFINES/~monkestation/admin.dm
+++ b/code/__DEFINES/~monkestation/admin.dm
@@ -1,5 +1,5 @@
-#define ADMIN_APPROVE_TOKEN(user) "(Yes)"
-#define ADMIN_REJECT_TOKEN(user) "(No)"
+#define ADMIN_APPROVE_TOKEN(user) "(Yes)"
+#define ADMIN_REJECT_TOKEN(user) "(No)"
#define ADMIN_OPEN_REVIEW(id) "(Open Review)"
#define ADMIN_APPROVE_TOKEN_EVENT(user) "(Yes)"
#define ADMIN_REJECT_TOKEN_EVENT(user) "(No)"
diff --git a/code/modules/admin/topic.dm b/code/modules/admin/topic.dm
index b1a08181f125..c436d382d3a5 100644
--- a/code/modules/admin/topic.dm
+++ b/code/modules/admin/topic.dm
@@ -1759,7 +1759,7 @@
web_sound(usr, link_url)
//monkestation edit start
- else if(href_list["approve_token"])
+ else if(href_list["approve_antag_token"])
if(!check_rights(R_ADMIN))
return
var/atom/movable/target = locate(href_list["approve_token"])
@@ -1769,7 +1769,7 @@
user_client.client_token_holder.approve_token()
message_admins("[user_client]'s token has been approved, by [owner]")
- else if(href_list["reject_token"])
+ else if(href_list["reject_antag_token"])
if(!check_rights(R_ADMIN))
return
var/atom/movable/target = locate(href_list["reject_token"])
diff --git a/monkestation/code/datums/meta_tokens.dm b/monkestation/code/datums/meta_tokens.dm
index aa0d32cc6c6c..29ad1493723e 100644
--- a/monkestation/code/datums/meta_tokens.dm
+++ b/monkestation/code/datums/meta_tokens.dm
@@ -4,6 +4,7 @@ GLOBAL_LIST_INIT(used_monthly_token, list())
var/datum/meta_token_holder/client_token_holder
/datum/meta_token_holder
+ ///the client that owns this holder
var/client/owner
///are they a donator? and do they have their free token?
var/donator_token = FALSE
@@ -18,7 +19,14 @@ GLOBAL_LIST_INIT(used_monthly_token, list())
///the antagonist we are currently waiting for a reply on whether we can use
var/datum/antagonist/in_queue
var/in_queued_tier
+ ///is the queued token a donor token
var/queued_donor = FALSE
+ ///how many event tokens we currently have
+ var/event_tokens = 0
+ ///the month we last used event tokens on
+ var/event_token_month = 0
+ ///what token event do we currently have queued
+ var/datum/twitch_event/queued_token_event
/datum/meta_token_holder/New(client/creator)
. = ..()
@@ -36,6 +44,8 @@ GLOBAL_LIST_INIT(used_monthly_token, list())
total_low_threat_tokens = saved_tokens["low_threat"]
total_medium_threat_tokens = saved_tokens["medium_threat"]
total_high_threat_tokens = saved_tokens["high_threat"]
+ event_tokens = saved_tokens["event_tokens"]
+ event_token_month = saved_tokens["event_token_month"]
total_antag_tokens = total_low_threat_tokens + total_medium_threat_tokens + total_high_threat_tokens
@@ -44,6 +54,8 @@ GLOBAL_LIST_INIT(used_monthly_token, list())
"low_threat" = total_low_threat_tokens,
"medium_threat" = total_medium_threat_tokens,
"high_threat" = total_high_threat_tokens,
+ "event_tokens" = event_tokens,
+ "event_token_month" = event_token_month,
)
owner.prefs.save_preferences()
@@ -87,8 +99,7 @@ GLOBAL_LIST_INIT(used_monthly_token, list())
convert_tokens_to_list()
-
-/datum/meta_token_holder/proc/approve_token()
+/datum/meta_token_holder/proc/approve_token(thing_to_approve)
if(!in_queue)
return
to_chat(owner, "Your request to play as [in_queue] has been approved.")
@@ -103,7 +114,7 @@ GLOBAL_LIST_INIT(used_monthly_token, list())
in_queued_tier = null
queued_donor = FALSE
-/datum/meta_token_holder/proc/reject_token()
+/datum/meta_token_holder/proc/reject_token(thing_to_reject)
to_chat(owner, "Your request to play as [in_queue] has been denied.")
in_queue = null
in_queued_tier = null
diff --git a/monkestation/code/modules/client/preferences.dm b/monkestation/code/modules/client/preferences.dm
index 8086108e086f..a93b287440ce 100644
--- a/monkestation/code/modules/client/preferences.dm
+++ b/monkestation/code/modules/client/preferences.dm
@@ -21,6 +21,8 @@
"high_threat" = 0,
"medium_threat" = 0,
"low_threat" = 0,
+ "event_tokens" = 0,
+ "event_token_month" = 0,
)
///amount of metaconis you can earn per shift
@@ -30,10 +32,3 @@
var/list/alt_job_titles = list()
/// the month we used our last donator token on
var/token_month = 0
-
- ///how many event tokens we currently have
- var/event_tokens = 0
- ///the month we last used event tokens on
- var/event_token_month = 0
- ///what token event do we currently have queued
- var/datum/twitch_event/queued_token_event
From 41696e038d8f538f3ce27eb347331fe98d748eb5 Mon Sep 17 00:00:00 2001
From: wraith-54321 <69217972+wraith-54321@users.noreply.github.com>
Date: Thu, 16 Nov 2023 01:27:14 -0800
Subject: [PATCH 05/60] workstm
---
code/__DEFINES/~monkestation/admin.dm | 4 +-
code/modules/admin/admin_verbs.dm | 5 +-
code/modules/admin/topic.dm | 36 ++++++++---
monkestation/code/datums/meta_tokens.dm | 60 ++++++++++++++++---
.../code/modules/admin/antag_tokens.dm | 3 +-
.../code/modules/admin/event_tokens.dm | 16 ++---
.../code/modules/client/event_tokens.dm | 1 -
monkestation/code/modules/client/verbs.dm | 53 +++++++---------
.../modules/code_redemption/code_redeemer.dm | 2 +-
.../modules/twitch_bits/events/amongus.dm | 3 +-
.../modules/twitch_bits/events/anime_ook.dm | 1 +
.../twitch_bits/events/australia_mode.dm | 1 +
.../code/modules/twitch_bits/events/buff.dm | 1 +
.../modules/twitch_bits/events/chuckle_nut.dm | 1 +
.../modules/twitch_bits/events/die_fate.dm | 2 +
.../modules/twitch_bits/events/random_item.dm | 1 +
.../code/modules/twitch_bits/events/rod.dm | 1 +
.../code/modules/twitch_bits/events/skinny.dm | 1 +
.../code/modules/twitch_bits/twitch_system.dm | 14 ++++-
tgstation.dme | 1 -
20 files changed, 141 insertions(+), 66 deletions(-)
delete mode 100644 monkestation/code/modules/client/event_tokens.dm
diff --git a/code/__DEFINES/~monkestation/admin.dm b/code/__DEFINES/~monkestation/admin.dm
index bf7b9207aa53..f705fdb26b2b 100644
--- a/code/__DEFINES/~monkestation/admin.dm
+++ b/code/__DEFINES/~monkestation/admin.dm
@@ -1,5 +1,5 @@
-#define ADMIN_APPROVE_TOKEN(user) "(Yes)"
-#define ADMIN_REJECT_TOKEN(user) "(No)"
+#define ADMIN_APPROVE_ANTAG_TOKEN(user) "(Yes)"
+#define ADMIN_REJECT_ANTAG_TOKEN(user) "(No)"
#define ADMIN_OPEN_REVIEW(id) "(Open Review)"
#define ADMIN_APPROVE_TOKEN_EVENT(user) "(Yes)"
#define ADMIN_REJECT_TOKEN_EVENT(user) "(No)"
diff --git a/code/modules/admin/admin_verbs.dm b/code/modules/admin/admin_verbs.dm
index c01ab9e5b21d..dd3d514254e9 100644
--- a/code/modules/admin/admin_verbs.dm
+++ b/code/modules/admin/admin_verbs.dm
@@ -104,8 +104,9 @@ GLOBAL_LIST_INIT(admin_verbs_fun, list(
// Client procs
/client/proc/admin_away,
/client/proc/add_mob_ability,
- /client/proc/adjust_players_antag_tokens,
- /client/proc/adjust_players_metacoins,
+ /client/proc/adjust_players_antag_tokens, //monkestation edit
+ /client/proc/adjust_players_event_tokens, //monkestation edit
+ /client/proc/adjust_players_metacoins, //monkestation edit
/client/proc/admin_change_sec_level,
/client/proc/change_ocean, //monkestation addition
/client/proc/cinematic,
diff --git a/code/modules/admin/topic.dm b/code/modules/admin/topic.dm
index c436d382d3a5..fc36a8e8a8ba 100644
--- a/code/modules/admin/topic.dm
+++ b/code/modules/admin/topic.dm
@@ -1762,22 +1762,24 @@
else if(href_list["approve_antag_token"])
if(!check_rights(R_ADMIN))
return
- var/atom/movable/target = locate(href_list["approve_token"])
+ var/atom/movable/target = locate(href_list["approve_antag_token"])
if(!IS_CLIENT_OR_MOCK(target))
return
var/client/user_client = target
- user_client.client_token_holder.approve_token()
- message_admins("[user_client]'s token has been approved, by [owner]")
+ user_client.client_token_holder.approve_antag_token()
+ message_admins("[user_client]'s token has been approved by [owner].")
+ log_admin("[user_client]'s token has been approved by [owner].")
else if(href_list["reject_antag_token"])
if(!check_rights(R_ADMIN))
return
- var/atom/movable/target = locate(href_list["reject_token"])
+ var/atom/movable/target = locate(href_list["reject_antag_token"])
if(!IS_CLIENT_OR_MOCK(target))
return
var/client/user_client = target
- user_client.client_token_holder.reject_token()
- message_admins("[user_client]'s token has been rejected, by [owner]")
+ user_client.client_token_holder.reject_antag_token()
+ message_admins("[user_client]'s token has been rejected by [owner].")
+ log_admin("[user_client]'s token has been rejected by [owner].")
else if(href_list["open_music_review"])
if(!check_rights(R_ADMIN))
@@ -1788,5 +1790,25 @@
return
cassette_review.ui_interact(usr)
-// else if()
+ else if(href_list["approve_token_event"])
+ if(!check_rights(R_ADMIN))
+ return
+ var/atom/movable/target = locate(href_list["approve_token_event"])
+ if(!IS_CLIENT_OR_MOCK(target))
+ return
+ var/client/user_client = target
+ user_client.client_token_holder.approve_token_event()
+ message_admins("[user_client]'s token event has been approved by [owner].")
+ log_admin("[user_client]'s token event has been approved by [owner].")
+
+ else if(href_list["reject_token_event"])
+ if(!check_rights(R_ADMIN))
+ return
+ var/atom/movable/target = locate(href_list["reject_token_event"])
+ if(!IS_CLIENT_OR_MOCK(target))
+ return
+ var/client/user_client = target
+ user_client.client_token_holder.reject_token_event()
+ message_admins("[user_client]'s token event has been rejected by [owner].")
+ log_admin("[user_client]'s token event has been rejected by [owner].")
//monkestation edit end
diff --git a/monkestation/code/datums/meta_tokens.dm b/monkestation/code/datums/meta_tokens.dm
index 29ad1493723e..12031c8c2d3e 100644
--- a/monkestation/code/datums/meta_tokens.dm
+++ b/monkestation/code/datums/meta_tokens.dm
@@ -1,5 +1,15 @@
GLOBAL_LIST_INIT(used_monthly_token, list())
+///assoc list of how many event tokens each role gets each month
+GLOBAL_LIST_INIT(patreon_etoken_values, list(
+ NO_RANK = 0,
+ RANK_TANKS = 100,
+ ASSISTANT_RANK = 500,
+ COMMAND_RANK = 1000,
+ TRAITOR_RANK = 2500,
+ NUKIE_RANK = 5000,
+))
+
/client
var/datum/meta_token_holder/client_token_holder
@@ -69,7 +79,7 @@ GLOBAL_LIST_INIT(used_monthly_token, list())
return FALSE
return TRUE
-/datum/meta_token_holder/proc/spend_token(tier, use_donor = FALSE)
+/datum/meta_token_holder/proc/spend_antag_token(tier, use_donor = FALSE)
if(use_donor)
if(donator_token)
donator_token = FALSE
@@ -88,7 +98,8 @@ GLOBAL_LIST_INIT(used_monthly_token, list())
convert_tokens_to_list()
///adjusts the users tokens, yes they can be in antag token debt
-/datum/meta_token_holder/proc/adjust_tokens(tier, amount)
+/datum/meta_token_holder/proc/adjust_antag_tokens(tier, amount)
+ var/list/old_token_values = list(HIGH_THREAT = total_high_threat_tokens, MEDIUM_THREAT = total_medium_threat_tokens, LOW_THREAT = total_low_threat_tokens)
switch(tier)
if(HIGH_THREAT)
total_high_threat_tokens += amount
@@ -97,25 +108,60 @@ GLOBAL_LIST_INIT(used_monthly_token, list())
if(LOW_THREAT)
total_low_threat_tokens += amount
+ log_admin("[key_name(owner)] had their antag tokens adjusted from high: [old_token_values[HIGH_THREAT]], medium: [old_token_values[MEDIUM_THREAT]], \
+ low: [old_token_values[LOW_THREAT]], to, high: [total_high_threat_tokens], medium: [total_medium_threat_tokens], low: [total_low_threat_tokens]")
convert_tokens_to_list()
-/datum/meta_token_holder/proc/approve_token(thing_to_approve)
+/datum/meta_token_holder/proc/approve_antag_token()
if(!in_queue)
return
- to_chat(owner, "Your request to play as [in_queue] has been approved.")
- spend_token(in_queued_tier, queued_donor)
+ to_chat(owner, "Your request to play as [in_queue] has been approved.")
+ spend_antag_token(in_queued_tier, queued_donor)
if(!owner.mob.mind)
owner.mob.mind_initialize()
- in_queue.antag_token(owner.mob.mind, owner.mob)
+ in_queue.antag_token(owner.mob.mind, owner.mob) //might not be in queue
qdel(in_queue)
in_queue = null
in_queued_tier = null
queued_donor = FALSE
-/datum/meta_token_holder/proc/reject_token(thing_to_reject)
+/datum/meta_token_holder/proc/reject_antag_token()
+ if(!in_queue)
+ return
+
to_chat(owner, "Your request to play as [in_queue] has been denied.")
in_queue = null
in_queued_tier = null
queued_donor = FALSE
+
+/datum/meta_token_holder/proc/adjust_event_tokens(amount)
+ check_event_tokens(owner)
+ var/old_value = event_tokens
+ event_tokens += amount
+ log_admin("[key_name(owner)] had their event tokens adjusted from [old_value] to, [event_tokens].")
+ convert_tokens_to_list()
+
+/datum/meta_token_holder/proc/check_event_tokens(client/checked_client)
+ var/month_number = text2num(time2text(world.time, "MM"))
+ if(event_token_month != month_number)
+ event_token_month = month_number
+ event_tokens = GLOB.patreon_etoken_values[checked_client.patreon.owned_rank]
+ convert_tokens_to_list()
+
+/datum/meta_token_holder/proc/approve_token_event()
+ if(!queued_token_event)
+ return
+
+ to_chat(owner, "Your request to trigger [queued_token_event] has been approved.")
+ adjust_event_tokens(-queued_token_event.token_cost)
+ SStwitch.add_to_queue(initial(queued_token_event.id_tag))
+ queued_token_event = null
+
+/datum/meta_token_holder/proc/reject_token_event()
+ if(!queued_token_event)
+ return
+
+ to_chat(owner, "Your request to trigger [queued_token_event] has been denied.")
+ queued_token_event = null
diff --git a/monkestation/code/modules/admin/antag_tokens.dm b/monkestation/code/modules/admin/antag_tokens.dm
index def24b5fdea1..67754d61f5a4 100644
--- a/monkestation/code/modules/admin/antag_tokens.dm
+++ b/monkestation/code/modules/admin/antag_tokens.dm
@@ -16,4 +16,5 @@
if(!tier)
return
- chosen_client.client_token_holder.adjust_tokens(tier, adjustment_amount)
+ log_admin("[key_name(src)] adjusted the [tier] antag tokens of [key_name(chosen_client)] by [adjustment_amount].")
+ chosen_client.client_token_holder.adjust_antag_tokens(tier, adjustment_amount)
diff --git a/monkestation/code/modules/admin/event_tokens.dm b/monkestation/code/modules/admin/event_tokens.dm
index 1c633ebde0fd..8e89c4960cbd 100644
--- a/monkestation/code/modules/admin/event_tokens.dm
+++ b/monkestation/code/modules/admin/event_tokens.dm
@@ -1,17 +1,17 @@
-/client/proc/set_players_event_tokens()
+/client/proc/adjust_players_event_tokens()
set category = "Admin.Fun"
-//due to the fact that these reset each month im just making this directly this this value instead of add or subtract
- set name = "Set Event Tokens"
- set desc = "Set how many event tokens someone has."
+
+ set name = "Adjust Event Tokens"
+ set desc = "Adjust how many event tokens someone has."
var/mob/chosen_player = tgui_input_list(src, "Choose a Player", "Player List", GLOB.player_list)
if(!chosen_player)
return
var/client/chosen_client = chosen_player.client
- var/adjustment_amount = tgui_input_number(src, "What should we set this users tokens to?", "Input Value", TRUE)
- if(!adjustment_amount || !chosen_client || !chosen_client.patreon)
+ var/adjustment_amount = tgui_input_number(src, "How much should we adjust this users tokens by?", "Input Value", TRUE)
+ if(!adjustment_amount || !chosen_client)
return
- check_event_tokens(chosen_client)
- chosen_client.prefs.event_tokens = adjustment_amount
+ log_admin("[key_name(src)] adjusted the event tokens of [key_name(chosen_client)] by [adjustment_amount].")
+ chosen_client.client_token_holder.adjust_event_tokens(adjustment_amount)
diff --git a/monkestation/code/modules/client/event_tokens.dm b/monkestation/code/modules/client/event_tokens.dm
deleted file mode 100644
index 8b137891791f..000000000000
--- a/monkestation/code/modules/client/event_tokens.dm
+++ /dev/null
@@ -1 +0,0 @@
-
diff --git a/monkestation/code/modules/client/verbs.dm b/monkestation/code/modules/client/verbs.dm
index a62bfebb884d..b6ec997e08d8 100644
--- a/monkestation/code/modules/client/verbs.dm
+++ b/monkestation/code/modules/client/verbs.dm
@@ -16,17 +16,6 @@ GLOBAL_LIST_INIT(low_threat_antags, list(
/datum/antagonist/paradox_clone,
))
-//PLACEHOLDER VALUES(1 to 1 cent to token conversion, also you get a free token if you dont pay yeah totally)
-///assoc list of how many event tokens each role gets each month
-GLOBAL_LIST_INIT(patreon_etoken_values, list(
- NO_RANK = 0,
- RANK_TANKS = 100,
- ASSISTANT_RANK = 500,
- COMMAND_RANK = 1000,
- TRAITOR_RANK = 2500,
- NUKIE_RANK = 5000,
-))
-
/client/verb/spend_antag_tokens()
set category = "IC"
set name = "Spend Antag Tokens"
@@ -83,11 +72,12 @@ GLOBAL_LIST_INIT(patreon_etoken_values, list(
client_token_holder.in_queue = new chosen_antagonist
to_chat(src, "Your request has been sent to the admins.")
- SEND_NOTFIED_ADMIN_MESSAGE('sound/items/bikehorn.ogg', "[span_admin("[span_prefix("ANTAG TOKEN:")] [key_name(src)] [ADMIN_APPROVE_TOKEN(src)] [ADMIN_REJECT_TOKEN(src)] | \
+ SEND_NOTFIED_ADMIN_MESSAGE('sound/items/bikehorn.ogg', "[span_admin("[span_prefix("ANTAG TOKEN:")] [key_name(src)] \
+ [ADMIN_APPROVE_ANTAG_TOKEN(src)] [ADMIN_REJECT_ANTAG_TOKEN(src)] | \
[src] has requested to use their antag token to be a [chosen_antagonist].")]")
-/client/proc/trigger_token_event()
- set category = "Ghost"
+/client/verb/trigger_token_event()
+ set category = "IC"
set name = "Trigger Token Event"
set desc = "Opens a ui to spend event tokens on"
@@ -96,28 +86,27 @@ GLOBAL_LIST_INIT(patreon_etoken_values, list(
var/static/list/event_list
if(!event_list)
- event_list = subtypesof(/datum/twitch_event)
- for(var/datum/twitch_event/event as anything in event_list)
- if(!event.token_cost)
- event_list -= event
+ event_list = list()
+ for(var/event as anything in GLOB.twitch_events_by_type)
+ var/datum/twitch_event/event_instance = GLOB.twitch_events_by_type[event]
+ if(!event_instance.token_cost)
+ continue
+ event_list += event_instance
+
+ client_token_holder.check_event_tokens(src)
- check_event_tokens(src)
+ var/datum/twitch_event/selected_event = tgui_input_list(src, "Event tokens: [client_token_holder.event_tokens]", "Choose an event to trigger", event_list)
+ if(!selected_event)
+ return
- var/datum/twitch_event/selected_event = tgui_input_list(src, "Event tokens: [prefs.event_tokens]", "Choose an event to trigger", event_list)
var/confirm = tgui_alert(src, "Are you sure you want to trigger [selected_event.event_name]? It will cost [selected_event.token_cost] event tokens.", "Trigger token event", \
list("Yes", "No"))
if(confirm == "Yes")
- if(prefs.event_tokens >= selected_event.token_cost)
- SEND_NOTFIED_ADMIN_MESSAGE('sound/items/bikehorn.ogg', "MESSAGE")
+ if(client_token_holder.event_tokens >= selected_event.token_cost)
+ client_token_holder.queued_token_event = selected_event
+ to_chat(src, "Your request has been sent.")
+ SEND_NOTFIED_ADMIN_MESSAGE('sound/items/bikehorn.ogg', "[span_admin("[span_prefix("TOKEN EVENT:")] [key_name(src)] \
+ [ADMIN_APPROVE_TOKEN_EVENT(src)] [ADMIN_REJECT_TOKEN_EVENT(src)] | \
+ [src] has requested use their event tokens to trigger [selected_event].")]")
return
to_chat(src, "You dont have enough tokens to trigger this event.")
-
-/proc/approve_token_event()
-
-/proc/reject_token_event()
-
-/proc/check_event_tokens(client/checked_client)
- var/month_number = text2num(time2text(world.time, "MM"))
- if(checked_client.prefs.event_token_month != month_number)
- checked_client.prefs.event_token_month = month_number
- checked_client.prefs.event_tokens = GLOB.patreon_etoken_values[checked_client.patreon.owned_rank]
diff --git a/monkestation/code/modules/code_redemption/code_redeemer.dm b/monkestation/code/modules/code_redemption/code_redeemer.dm
index 7e394286b0d4..208b1618cbfa 100644
--- a/monkestation/code/modules/code_redemption/code_redeemer.dm
+++ b/monkestation/code/modules/code_redemption/code_redeemer.dm
@@ -26,7 +26,7 @@ GLOBAL_LIST_INIT(redeemed_codes, list())
if(isnum(path))
usr.client.prefs.adjust_metacoins(usr.ckey, path, "Redeemed a Giveaway Code", donator_multipler = FALSE)
else if(path == HIGH_THREAT || path == MEDIUM_THREAT || path == LOW_THREAT)
- usr.client.client_token_holder.adjust_tokens(path, 1)
+ usr.client.client_token_holder.adjust_antag_tokens(path, 1)
to_chat(usr, span_boldnotice("You have successfully redeemed a giveaway code for: [path] Antag Token."))
else
var/pathedstring = text2path(path)
diff --git a/monkestation/code/modules/twitch_bits/events/amongus.dm b/monkestation/code/modules/twitch_bits/events/amongus.dm
index d0739aefbff1..871ea5095193 100644
--- a/monkestation/code/modules/twitch_bits/events/amongus.dm
+++ b/monkestation/code/modules/twitch_bits/events/amongus.dm
@@ -3,13 +3,14 @@
event_duration = 15 MINUTES
event_flags = TWITCH_AFFECTS_ALL
id_tag = "amongus-all15"
+ token_cost = 500
/datum/twitch_event/amongus/ook
event_name = "Amongus Ook"
event_duration = 30 MINUTES
event_flags = TWITCH_AFFECTS_STREAMER
id_tag = "amongus-ook10"
-
+ token_cost = 500
/datum/twitch_event/amongus/run_event(name)
. = ..()
diff --git a/monkestation/code/modules/twitch_bits/events/anime_ook.dm b/monkestation/code/modules/twitch_bits/events/anime_ook.dm
index 1237e91d18cb..70e9573dce98 100644
--- a/monkestation/code/modules/twitch_bits/events/anime_ook.dm
+++ b/monkestation/code/modules/twitch_bits/events/anime_ook.dm
@@ -3,6 +3,7 @@
event_duration = 1 SECONDS
event_flags = TWITCH_AFFECTS_STREAMER
id_tag = "anime-ook"
+ token_cost = 100
/datum/twitch_event/anime_ook/run_event(name)
. = ..()
diff --git a/monkestation/code/modules/twitch_bits/events/australia_mode.dm b/monkestation/code/modules/twitch_bits/events/australia_mode.dm
index 9204c81c2ae1..2bf42cc3eee2 100644
--- a/monkestation/code/modules/twitch_bits/events/australia_mode.dm
+++ b/monkestation/code/modules/twitch_bits/events/australia_mode.dm
@@ -3,6 +3,7 @@
event_duration = 15 MINUTES //effect is very minor so it lasts for a while
event_flags = TWITCH_AFFECTS_ALL
id_tag = "australia-mode"
+ token_cost = 500
/datum/twitch_event/australia_mode/run_event(name)
. = ..()
diff --git a/monkestation/code/modules/twitch_bits/events/buff.dm b/monkestation/code/modules/twitch_bits/events/buff.dm
index 97c10978ad3d..fd92367a5aac 100644
--- a/monkestation/code/modules/twitch_bits/events/buff.dm
+++ b/monkestation/code/modules/twitch_bits/events/buff.dm
@@ -3,6 +3,7 @@
event_duration = 5 MINUTES
event_flags = TWITCH_AFFECTS_ALL
id_tag = "buff-5"
+ token_cost = 500
/datum/twitch_event/buff/run_event(name)
. = ..()
diff --git a/monkestation/code/modules/twitch_bits/events/chuckle_nut.dm b/monkestation/code/modules/twitch_bits/events/chuckle_nut.dm
index 9608cf4e5a2f..d462f440400e 100644
--- a/monkestation/code/modules/twitch_bits/events/chuckle_nut.dm
+++ b/monkestation/code/modules/twitch_bits/events/chuckle_nut.dm
@@ -3,6 +3,7 @@
event_duration = 1 SECONDS
event_flags = TWITCH_AFFECTS_STREAMER
id_tag = "chucklenuts-ook"
+ token_cost = 800
/datum/twitch_event/chucklenuts/random
event_name = "Think Fast"
diff --git a/monkestation/code/modules/twitch_bits/events/die_fate.dm b/monkestation/code/modules/twitch_bits/events/die_fate.dm
index 9bb6dabfa845..30934772ec20 100644
--- a/monkestation/code/modules/twitch_bits/events/die_fate.dm
+++ b/monkestation/code/modules/twitch_bits/events/die_fate.dm
@@ -3,6 +3,7 @@
event_duration = 1 SECONDS
event_flags = TWITCH_AFFECTS_STREAMER
id_tag = "ook-die-fate"
+ token_cost = 2500
/datum/twitch_event/free_wiz/run_event(name)
. = ..()
@@ -19,3 +20,4 @@
event_name = "Change Everyone's Fate"
event_flags = TWITCH_AFFECTS_ALL
id_tag = "everyone-die-fate"
+ token_cost = 5002 // :)
diff --git a/monkestation/code/modules/twitch_bits/events/random_item.dm b/monkestation/code/modules/twitch_bits/events/random_item.dm
index 0bcc67025703..de5de7c6d2a7 100644
--- a/monkestation/code/modules/twitch_bits/events/random_item.dm
+++ b/monkestation/code/modules/twitch_bits/events/random_item.dm
@@ -3,6 +3,7 @@
event_duration = 1 SECONDS
event_flags = TWITCH_AFFECTS_STREAMER
id_tag = "give-ook-item"
+ token_cost = 1000
/datum/twitch_event/give_smsword/run_event(name)
. = ..()
diff --git a/monkestation/code/modules/twitch_bits/events/rod.dm b/monkestation/code/modules/twitch_bits/events/rod.dm
index 7de830e3cbca..235988add906 100644
--- a/monkestation/code/modules/twitch_bits/events/rod.dm
+++ b/monkestation/code/modules/twitch_bits/events/rod.dm
@@ -4,6 +4,7 @@
event_flags = TWITCH_AFFECTS_STREAMER
id_tag = "rod-ook"
announce = FALSE //takes a while to reach its target so dont announce it
+ token_cost = 3000
/datum/twitch_event/clang/run_event(name)
. = ..()
diff --git a/monkestation/code/modules/twitch_bits/events/skinny.dm b/monkestation/code/modules/twitch_bits/events/skinny.dm
index 1a670135e2da..b0d7a5865825 100644
--- a/monkestation/code/modules/twitch_bits/events/skinny.dm
+++ b/monkestation/code/modules/twitch_bits/events/skinny.dm
@@ -3,6 +3,7 @@
event_duration = 5 MINUTES
event_flags = TWITCH_AFFECTS_ALL
id_tag = "skinny-5"
+ token_cost = 500
/datum/twitch_event/skinny/run_event(name)
. = ..()
diff --git a/monkestation/code/modules/twitch_bits/twitch_system.dm b/monkestation/code/modules/twitch_bits/twitch_system.dm
index 56f90afce6d1..465f89da211a 100644
--- a/monkestation/code/modules/twitch_bits/twitch_system.dm
+++ b/monkestation/code/modules/twitch_bits/twitch_system.dm
@@ -1,10 +1,13 @@
+///assoc list of instances of all twitch events keyed by their type
+GLOBAL_LIST_EMPTY(twitch_events_by_type)
+
/datum/config_entry/string/twitch_key
default = "changethisplease"
SUBSYSTEM_DEF(twitch)
name = "Twitch Events"
wait = 0.5 SECONDS
- flags = SS_KEEP_TIMING | SS_NO_INIT
+ flags = SS_KEEP_TIMING
runlevels = RUNLEVEL_GAME | RUNLEVEL_POSTGAME
priority = FIRE_PRIORITY_TWITCH
init_order = INIT_ORDER_TWITCH
@@ -19,6 +22,11 @@ SUBSYSTEM_DEF(twitch)
var/last_event_execution = 0
var/last_executor
+/datum/controller/subsystem/twitch/Initialize()
+ for(var/event as anything in subtypesof(/datum/twitch_event))
+ GLOB.twitch_events_by_type[event] = new event
+ return SS_INIT_SUCCESS
+
/datum/controller/subsystem/twitch/stat_entry(msg)
msg += "Running Events:[running_events.len]"
return ..()
@@ -44,7 +52,7 @@ SUBSYSTEM_DEF(twitch)
for(var/datum/twitch_event/listed_events as anything in subtypesof(/datum/twitch_event))
if(incoming[3] != initial(listed_events.id_tag))
continue
- chosen_one = new listed_events
+ chosen_one = GLOB.twitch_events_by_type[listed_events]
if(!chosen_one)
return
@@ -76,7 +84,7 @@ SUBSYSTEM_DEF(twitch)
for(var/datum/twitch_event/listed_events as anything in subtypesof(/datum/twitch_event))
if(listed_item != initial(listed_events.id_tag))
continue
- chosen_one = new listed_events
+ chosen_one = GLOB.twitch_events_by_type[listed_events]
if(!chosen_one)
return
chosen_one.run_event()
diff --git a/tgstation.dme b/tgstation.dme
index dcc757bda72c..bf23f2499a5b 100644
--- a/tgstation.dme
+++ b/tgstation.dme
@@ -5814,7 +5814,6 @@
#include "monkestation\code\modules\cassettes\machines\media\track.dm"
#include "monkestation\code\modules\cassettes\machines\media\subsystem\media_track_manager.dm"
#include "monkestation\code\modules\cassettes\walkman\_walkmen.dm"
-#include "monkestation\code\modules\client\event_tokens.dm"
#include "monkestation\code\modules\client\preference_savefile.dm"
#include "monkestation\code\modules\client\preferences.dm"
#include "monkestation\code\modules\client\verbs.dm"
From 914ad1f33d6f561ad410cebe53db0f5c244cb50c Mon Sep 17 00:00:00 2001
From: wraith-54321 <69217972+wraith-54321@users.noreply.github.com>
Date: Thu, 16 Nov 2023 17:35:08 -0800
Subject: [PATCH 06/60] defines and modular
---
code/__DEFINES/twitch.dm | 3 ---
code/__DEFINES/~monkestation/admin.dm | 6 ------
code/__DEFINES/~monkestation/twitch.dm | 18 ++++++++++++++++++
.../modules/cassettes/cassette_approval.dm | 3 +++
monkestation/code/modules/client/verbs.dm | 9 +++++++++
.../modules/twitch_bits/events/_base_event.dm | 2 +-
.../code/modules/twitch_bits/events/amongus.dm | 4 ++--
.../modules/twitch_bits/events/anime_ook.dm | 2 +-
.../twitch_bits/events/australia_mode.dm | 2 +-
.../code/modules/twitch_bits/events/buff.dm | 2 +-
.../modules/twitch_bits/events/chuckle_nut.dm | 5 +++--
.../modules/twitch_bits/events/die_fate.dm | 8 ++++----
.../modules/twitch_bits/events/random_item.dm | 8 +++++++-
.../code/modules/twitch_bits/events/rod.dm | 4 ++--
.../code/modules/twitch_bits/events/skinny.dm | 2 +-
tgstation.dme | 2 +-
16 files changed, 54 insertions(+), 26 deletions(-)
delete mode 100644 code/__DEFINES/twitch.dm
create mode 100644 code/__DEFINES/~monkestation/twitch.dm
diff --git a/code/__DEFINES/twitch.dm b/code/__DEFINES/twitch.dm
deleted file mode 100644
index 5d408fede4e9..000000000000
--- a/code/__DEFINES/twitch.dm
+++ /dev/null
@@ -1,3 +0,0 @@
-#define TWITCH_AFFECTS_STREAMER (1 << 0)
-#define TWITCH_AFFECTS_ALL (1 << 1)
-#define TWITCH_AFFECTS_RANDOM (1 << 2)
diff --git a/code/__DEFINES/~monkestation/admin.dm b/code/__DEFINES/~monkestation/admin.dm
index f705fdb26b2b..198511a23db1 100644
--- a/code/__DEFINES/~monkestation/admin.dm
+++ b/code/__DEFINES/~monkestation/admin.dm
@@ -1,9 +1,3 @@
-#define ADMIN_APPROVE_ANTAG_TOKEN(user) "(Yes)"
-#define ADMIN_REJECT_ANTAG_TOKEN(user) "(No)"
-#define ADMIN_OPEN_REVIEW(id) "(Open Review)"
-#define ADMIN_APPROVE_TOKEN_EVENT(user) "(Yes)"
-#define ADMIN_REJECT_TOKEN_EVENT(user) "(No)"
-
///Sends all admins the chosen sound
#define SEND_ADMINS_NOTFICATION_SOUND(sound) for(var/client/X in GLOB.admins){X << sound;}
///Sends a message in adminchat
diff --git a/code/__DEFINES/~monkestation/twitch.dm b/code/__DEFINES/~monkestation/twitch.dm
new file mode 100644
index 000000000000..ccf5c48238ca
--- /dev/null
+++ b/code/__DEFINES/~monkestation/twitch.dm
@@ -0,0 +1,18 @@
+#define TWITCH_AFFECTS_STREAMER (1 << 0)
+#define TWITCH_AFFECTS_ALL (1 << 1)
+#define TWITCH_AFFECTS_RANDOM (1 << 2)
+
+// twitch event IDs
+#define T_EVENT_AMONGUS_ALL_15 "amongus-all15"
+#define T_EVENT_AMONGUS_OOK_10 "amongus-ook10"
+#define T_EVENT_ANIME_OOK "anime-ook"
+#define T_EVENT_AUSTRALIA_MODE "australia-mode"
+#define T_EVENT_BUFF_5 "buff-5"
+#define T_EVENT_CHUCKLENUTS_OOK "chucklenuts-ook"
+#define T_EVENT_CHUCKLENUTS_RANDOM "chucklenuts-random"
+#define T_EVENT_OOK_DIE_FATE "ook-die-fate"
+#define T_EVENT_EVERYONE_DIE_FATE "everyone-die-fate"
+#define T_EVENT_GIVE_OOK_ITEM "give-ook-item"
+#define T_EVENT_GIVE_EVERYONE_ITEM "give-everyone-item"
+#define T_EVENT_ROD_OOK "rod-ook"
+#define T_EVENT_SKINNY_5 "skinny-5"
diff --git a/monkestation/code/modules/cassettes/cassette_approval.dm b/monkestation/code/modules/cassettes/cassette_approval.dm
index d658372c26c4..3ba2f63b7be8 100644
--- a/monkestation/code/modules/cassettes/cassette_approval.dm
+++ b/monkestation/code/modules/cassettes/cassette_approval.dm
@@ -1,5 +1,6 @@
GLOBAL_LIST_INIT(cassette_reviews, list())
+#define ADMIN_OPEN_REVIEW(id) "(Open Review)"
/proc/submit_cassette_for_review(obj/item/device/cassette_tape/submitted, mob/user)
if(!user.client)
return
@@ -131,3 +132,5 @@ GLOBAL_LIST_INIT(cassette_reviews, list())
/proc/fetch_review(id)
return GLOB.cassette_reviews[id]
+
+#undef ADMIN_OPEN_REVIEW
diff --git a/monkestation/code/modules/client/verbs.dm b/monkestation/code/modules/client/verbs.dm
index b6ec997e08d8..d9f00c008753 100644
--- a/monkestation/code/modules/client/verbs.dm
+++ b/monkestation/code/modules/client/verbs.dm
@@ -16,6 +16,10 @@ GLOBAL_LIST_INIT(low_threat_antags, list(
/datum/antagonist/paradox_clone,
))
+#define ADMIN_APPROVE_ANTAG_TOKEN(user) "(Yes)"
+#define ADMIN_REJECT_ANTAG_TOKEN(user) "(No)"
+#define ADMIN_APPROVE_TOKEN_EVENT(user) "(Yes)"
+#define ADMIN_REJECT_TOKEN_EVENT(user) "(No)"
/client/verb/spend_antag_tokens()
set category = "IC"
set name = "Spend Antag Tokens"
@@ -110,3 +114,8 @@ GLOBAL_LIST_INIT(low_threat_antags, list(
[src] has requested use their event tokens to trigger [selected_event].")]")
return
to_chat(src, "You dont have enough tokens to trigger this event.")
+
+#undef ADMIN_APPROVE_ANTAG_TOKEN
+#undef ADMIN_REJECT_ANTAG_TOKEN
+#undef ADMIN_APPROVE_TOKEN_EVENT
+#undef ADMIN_REJECT_TOKEN_EVENT
diff --git a/monkestation/code/modules/twitch_bits/events/_base_event.dm b/monkestation/code/modules/twitch_bits/events/_base_event.dm
index ead023a1c4f6..015ef7e3ee28 100644
--- a/monkestation/code/modules/twitch_bits/events/_base_event.dm
+++ b/monkestation/code/modules/twitch_bits/events/_base_event.dm
@@ -9,7 +9,7 @@
var/random_count = 0
///list of targets
var/list/targets = list()
- ///the tag tied to this event, should make these be defines at some point
+ ///the tag tied to this event
var/id_tag
///should we announce this event
var/announce = TRUE
diff --git a/monkestation/code/modules/twitch_bits/events/amongus.dm b/monkestation/code/modules/twitch_bits/events/amongus.dm
index 871ea5095193..4a842ba7beaf 100644
--- a/monkestation/code/modules/twitch_bits/events/amongus.dm
+++ b/monkestation/code/modules/twitch_bits/events/amongus.dm
@@ -2,14 +2,14 @@
event_name = "Amongus Everyone"
event_duration = 15 MINUTES
event_flags = TWITCH_AFFECTS_ALL
- id_tag = "amongus-all15"
+ id_tag = T_EVENT_AMONGUS_ALL_15
token_cost = 500
/datum/twitch_event/amongus/ook
event_name = "Amongus Ook"
event_duration = 30 MINUTES
event_flags = TWITCH_AFFECTS_STREAMER
- id_tag = "amongus-ook10"
+ id_tag = T_EVENT_AMONGUS_OOK_10
token_cost = 500
/datum/twitch_event/amongus/run_event(name)
diff --git a/monkestation/code/modules/twitch_bits/events/anime_ook.dm b/monkestation/code/modules/twitch_bits/events/anime_ook.dm
index 70e9573dce98..b7ccb229deec 100644
--- a/monkestation/code/modules/twitch_bits/events/anime_ook.dm
+++ b/monkestation/code/modules/twitch_bits/events/anime_ook.dm
@@ -2,7 +2,7 @@
event_name = "Anime Ook"
event_duration = 1 SECONDS
event_flags = TWITCH_AFFECTS_STREAMER
- id_tag = "anime-ook"
+ id_tag = T_EVENT_ANIME_OOK
token_cost = 100
/datum/twitch_event/anime_ook/run_event(name)
diff --git a/monkestation/code/modules/twitch_bits/events/australia_mode.dm b/monkestation/code/modules/twitch_bits/events/australia_mode.dm
index 2bf42cc3eee2..50c4843b77f4 100644
--- a/monkestation/code/modules/twitch_bits/events/australia_mode.dm
+++ b/monkestation/code/modules/twitch_bits/events/australia_mode.dm
@@ -2,7 +2,7 @@
event_name = "Australia Mode"
event_duration = 15 MINUTES //effect is very minor so it lasts for a while
event_flags = TWITCH_AFFECTS_ALL
- id_tag = "australia-mode"
+ id_tag = T_EVENT_AUSTRALIA_MODE
token_cost = 500
/datum/twitch_event/australia_mode/run_event(name)
diff --git a/monkestation/code/modules/twitch_bits/events/buff.dm b/monkestation/code/modules/twitch_bits/events/buff.dm
index fd92367a5aac..46c6e361b64b 100644
--- a/monkestation/code/modules/twitch_bits/events/buff.dm
+++ b/monkestation/code/modules/twitch_bits/events/buff.dm
@@ -2,7 +2,7 @@
event_name = "Bodybuilder Mode"
event_duration = 5 MINUTES
event_flags = TWITCH_AFFECTS_ALL
- id_tag = "buff-5"
+ id_tag = T_EVENT_BUFF_5
token_cost = 500
/datum/twitch_event/buff/run_event(name)
diff --git a/monkestation/code/modules/twitch_bits/events/chuckle_nut.dm b/monkestation/code/modules/twitch_bits/events/chuckle_nut.dm
index d462f440400e..4fad6aea1dde 100644
--- a/monkestation/code/modules/twitch_bits/events/chuckle_nut.dm
+++ b/monkestation/code/modules/twitch_bits/events/chuckle_nut.dm
@@ -2,14 +2,15 @@
event_name = "Think Fast Ook"
event_duration = 1 SECONDS
event_flags = TWITCH_AFFECTS_STREAMER
- id_tag = "chucklenuts-ook"
+ id_tag = T_EVENT_CHUCKLENUTS_OOK
token_cost = 800
/datum/twitch_event/chucklenuts/random
event_name = "Think Fast"
event_duration = 1 SECONDS
event_flags = TWITCH_AFFECTS_RANDOM
- id_tag = "chucklenuts-random"
+ id_tag = T_EVENT_CHUCKLENUTS_RANDOM
+ token_cost = null
/datum/twitch_event/chucklenuts/run_event(name)
. = ..()
diff --git a/monkestation/code/modules/twitch_bits/events/die_fate.dm b/monkestation/code/modules/twitch_bits/events/die_fate.dm
index 30934772ec20..9487260add50 100644
--- a/monkestation/code/modules/twitch_bits/events/die_fate.dm
+++ b/monkestation/code/modules/twitch_bits/events/die_fate.dm
@@ -2,7 +2,7 @@
event_name = "Change Ook's Fate"
event_duration = 1 SECONDS
event_flags = TWITCH_AFFECTS_STREAMER
- id_tag = "ook-die-fate"
+ id_tag = T_EVENT_OOK_DIE_FATE
token_cost = 2500
/datum/twitch_event/free_wiz/run_event(name)
@@ -12,12 +12,12 @@
var/mob/living/future_wiz = target
var/obj/item/dice/d20/fate/one_use/the_die = new(get_turf(future_wiz))
future_wiz.put_in_hands(the_die)
- to_chat(future_wiz, span_warning("Something apears in your hand and- oh no you fumbled it. That can't be good."))
- the_die.diceroll(future_wiz)
+ to_chat(future_wiz, span_userdanger("Something apears in your hand and- oh no you fumbled it. That can't be good."))
+ addtimer(CALLBACK(the_die, TYPE_PROC_REF(/obj/item/dice, diceroll), future_wiz), 0.5 SECONDS)
//this is more of a joke, could maybe cost 100k bits or something
/datum/twitch_event/free_wiz/everyone
event_name = "Change Everyone's Fate"
event_flags = TWITCH_AFFECTS_ALL
- id_tag = "everyone-die-fate"
+ id_tag = T_EVENT_EVERYONE_DIE_FATE
token_cost = 5002 // :)
diff --git a/monkestation/code/modules/twitch_bits/events/random_item.dm b/monkestation/code/modules/twitch_bits/events/random_item.dm
index de5de7c6d2a7..981a54c37a2b 100644
--- a/monkestation/code/modules/twitch_bits/events/random_item.dm
+++ b/monkestation/code/modules/twitch_bits/events/random_item.dm
@@ -2,7 +2,7 @@
event_name = "Give Ook Random Item"
event_duration = 1 SECONDS
event_flags = TWITCH_AFFECTS_STREAMER
- id_tag = "give-ook-item"
+ id_tag = T_EVENT_GIVE_OOK_ITEM
token_cost = 1000
/datum/twitch_event/give_smsword/run_event(name)
@@ -13,3 +13,9 @@
var/obj/item/gamer_item = pick(subtypesof(/obj/item))
gamer_item = new gamer_item()
debug_uplink_reciever.put_in_hands(gamer_item)
+
+/datum/twitch_event/give_smsword/everyone
+ event_name = "Give Everyone Random Item"
+ event_flags = TWITCH_AFFECTS_ALL
+ id_tag = T_EVENT_GIVE_EVERYONE_ITEM
+ token_cost = null
diff --git a/monkestation/code/modules/twitch_bits/events/rod.dm b/monkestation/code/modules/twitch_bits/events/rod.dm
index 235988add906..b82c7d10eff1 100644
--- a/monkestation/code/modules/twitch_bits/events/rod.dm
+++ b/monkestation/code/modules/twitch_bits/events/rod.dm
@@ -2,9 +2,9 @@
event_name = "Immovable Rod Ook"
event_duration = 1 SECONDS
event_flags = TWITCH_AFFECTS_STREAMER
- id_tag = "rod-ook"
+ id_tag = T_EVENT_ROD_OOK
announce = FALSE //takes a while to reach its target so dont announce it
- token_cost = 3000
+ token_cost = 3500
/datum/twitch_event/clang/run_event(name)
. = ..()
diff --git a/monkestation/code/modules/twitch_bits/events/skinny.dm b/monkestation/code/modules/twitch_bits/events/skinny.dm
index b0d7a5865825..27dbdce76fe6 100644
--- a/monkestation/code/modules/twitch_bits/events/skinny.dm
+++ b/monkestation/code/modules/twitch_bits/events/skinny.dm
@@ -2,7 +2,7 @@
event_name = "Thinned Out Mode"
event_duration = 5 MINUTES
event_flags = TWITCH_AFFECTS_ALL
- id_tag = "skinny-5"
+ id_tag = T_EVENT_SKINNY_5
token_cost = 500
/datum/twitch_event/skinny/run_event(name)
diff --git a/tgstation.dme b/tgstation.dme
index bf23f2499a5b..7a1d604c350f 100644
--- a/tgstation.dme
+++ b/tgstation.dme
@@ -246,7 +246,6 @@
#include "code\__DEFINES\tram.dm"
#include "code\__DEFINES\turbine_defines.dm"
#include "code\__DEFINES\turfs.dm"
-#include "code\__DEFINES\twitch.dm"
#include "code\__DEFINES\typeids.dm"
#include "code\__DEFINES\unit_tests.dm"
#include "code\__DEFINES\uplink.dm"
@@ -393,6 +392,7 @@
#include "code\__DEFINES\~monkestation\status_effects.dm"
#include "code\__DEFINES\~monkestation\storytellers.dm"
#include "code\__DEFINES\~monkestation\traits.dm"
+#include "code\__DEFINES\~monkestation\twitch.dm"
#include "code\__DEFINES\~monkestation\dcs\signals\signals_atom.dm"
#include "code\__DEFINES\~monkestation\dcs\signals\signals_carbon.dm"
#include "code\__DEFINES\~monkestation\dcs\signals\signals_traitor.dm"
From 62b27763c2b185e7a4035dc03deeb9f256ee54c9 Mon Sep 17 00:00:00 2001
From: wraith-54321 <69217972+wraith-54321@users.noreply.github.com>
Date: Sun, 19 Nov 2023 15:08:42 -0800
Subject: [PATCH 07/60] should commit
---
.../__DEFINES/~monkestation/baton_upgrades.dm | 3 +
.../antagonists/traitor/datum_traitor.dm | 5 +
monkestation/code/datums/components/uplink.dm | 2 +
.../game/objects/items/storage/uplink_kits.dm | 77 +++++++-
.../contractor/datums/contractor_datum.dm | 25 +++
.../contractor/datums/contractor_hub.dm | 4 +
.../contractor/datums/contractor_items.dm | 172 ++++++++++++++++++
.../contractor/datums/contractor_support.dm | 54 ++++++
.../contractor/datums/mind_datum.dm | 4 +
.../antagonists/contractor/items/baton.dm | 85 +++++++++
.../antagonists/contractor/items/boxes.dm | 8 +
.../antagonists/contractor/items/misc.dm | 14 ++
.../contractor/items/modsuit/modsuit.dm | 39 ++++
.../contractor/items/modsuit/modules.dm | 87 +++++++++
.../contractor/items/modsuit/theme.dm | 68 +++++++
.../antagonists/traitor/datum_traitor.dm | 3 +
.../antagonists/traitor/traitor_objective.dm | 3 +
.../antagonists/traitor/uplink_handler.dm | 1 +
.../code/modules/paperwork/paper_premade.dm | 39 ++++
.../modules/uplink/uplink_items/bundle.dm | 6 +
.../icons/mob/clothing/worn_modsuit.dmi | Bin 0 -> 1829 bytes
.../clothing/modsuits/contractor_modsuit.dmi | Bin 0 -> 1230 bytes
.../icons/obj/items/baton_upgrades.dmi | Bin 0 -> 354 bytes
monkestation/icons/obj/items/fulton.dmi | Bin 0 -> 1352 bytes
.../icons/obj/items/modsuit_modules.dmi | Bin 0 -> 382 bytes
tgstation.dme | 18 ++
26 files changed, 714 insertions(+), 3 deletions(-)
create mode 100644 code/__DEFINES/~monkestation/baton_upgrades.dm
create mode 100644 monkestation/code/datums/components/uplink.dm
create mode 100644 monkestation/code/modules/antagonists/contractor/datums/contractor_datum.dm
create mode 100644 monkestation/code/modules/antagonists/contractor/datums/contractor_hub.dm
create mode 100644 monkestation/code/modules/antagonists/contractor/datums/contractor_items.dm
create mode 100644 monkestation/code/modules/antagonists/contractor/datums/contractor_support.dm
create mode 100644 monkestation/code/modules/antagonists/contractor/datums/mind_datum.dm
create mode 100644 monkestation/code/modules/antagonists/contractor/items/baton.dm
create mode 100644 monkestation/code/modules/antagonists/contractor/items/boxes.dm
create mode 100644 monkestation/code/modules/antagonists/contractor/items/misc.dm
create mode 100644 monkestation/code/modules/antagonists/contractor/items/modsuit/modsuit.dm
create mode 100644 monkestation/code/modules/antagonists/contractor/items/modsuit/modules.dm
create mode 100644 monkestation/code/modules/antagonists/contractor/items/modsuit/theme.dm
create mode 100644 monkestation/code/modules/antagonists/traitor/datum_traitor.dm
create mode 100644 monkestation/code/modules/antagonists/traitor/traitor_objective.dm
create mode 100644 monkestation/code/modules/antagonists/traitor/uplink_handler.dm
create mode 100644 monkestation/code/modules/paperwork/paper_premade.dm
create mode 100644 monkestation/code/modules/uplink/uplink_items/bundle.dm
create mode 100644 monkestation/icons/mob/clothing/worn_modsuit.dmi
create mode 100644 monkestation/icons/obj/clothing/modsuits/contractor_modsuit.dmi
create mode 100644 monkestation/icons/obj/items/baton_upgrades.dmi
create mode 100644 monkestation/icons/obj/items/fulton.dmi
create mode 100644 monkestation/icons/obj/items/modsuit_modules.dmi
diff --git a/code/__DEFINES/~monkestation/baton_upgrades.dm b/code/__DEFINES/~monkestation/baton_upgrades.dm
new file mode 100644
index 000000000000..dcfbfbabe45c
--- /dev/null
+++ b/code/__DEFINES/~monkestation/baton_upgrades.dm
@@ -0,0 +1,3 @@
+#define BATON_ALL_UPGRADE (1<<0)
+#define BATON_CUFF_UPGRADE (1<<1)
+#define BATON_MUTE_UPGRADE (1<<2)
diff --git a/code/modules/antagonists/traitor/datum_traitor.dm b/code/modules/antagonists/traitor/datum_traitor.dm
index b150289f2e4d..4e40ab3efc60 100644
--- a/code/modules/antagonists/traitor/datum_traitor.dm
+++ b/code/modules/antagonists/traitor/datum_traitor.dm
@@ -350,6 +350,11 @@
var/special_role_text = lowertext(name)
+//monkestation edit start
+ if(contractor_hub)
+ result += contractor_round_end()
+//monkestation edit end
+
if(traitor_won)
result += span_greentext("The [special_role_text] was successful!")
else
diff --git a/monkestation/code/datums/components/uplink.dm b/monkestation/code/datums/components/uplink.dm
new file mode 100644
index 000000000000..5477d2b5b667
--- /dev/null
+++ b/monkestation/code/datums/components/uplink.dm
@@ -0,0 +1,2 @@
+//this file contains extra stuff we have for uplink components like contractors
+
diff --git a/monkestation/code/game/objects/items/storage/uplink_kits.dm b/monkestation/code/game/objects/items/storage/uplink_kits.dm
index aabb3983d513..48b654a2341f 100644
--- a/monkestation/code/game/objects/items/storage/uplink_kits.dm
+++ b/monkestation/code/game/objects/items/storage/uplink_kits.dm
@@ -1,11 +1,12 @@
+#define KIT_ITEM_CATEGORY_SUPPORT "support"
+#define KIT_ITEM_CATEGORY_WEAPONS "weapons"
+#define KIT_ITEM_CATEGORY_MISC "misc"
/obj/item/storage/box/syndie_kit/imp_hard_spear
name = "hardlight spear implant box"
/obj/item/storage/box/syndie_kit/imp_hard_spear/PopulateContents()
new /obj/item/implanter/hard_spear(src)
-
-
/obj/item/storage/box/syndimaid
name = "Syndicate maid outfit"
desc = "A box containing a 'tactical' and 'practical' maid outfit."
@@ -17,4 +18,74 @@
/obj/item/clothing/under/syndicate/skirt/maid = 1,
/obj/item/clothing/gloves/combat/maid = 1,
/obj/item/clothing/accessory/maidapron/syndicate = 1,)
- generate_items_inside(items_inside,src)\
+ generate_items_inside(items_inside,src)
+
+/obj/item/storage/box/syndie_kit/contractor_loadout
+ name = "Standard Loadout"
+ desc = "Supplied to Syndicate contractors, providing their specialised space suit and chameleon uniform."
+ icon_state = "syndiebox"
+ illustration = "writing_syndie"
+
+/obj/item/storage/box/syndie_kit/contractor_loadout/PopulateContents()
+ new /obj/item/mod/control/pre_equipped/contractor(src)
+ new /obj/item/storage/box/syndie_kit/chameleon(src)
+ new /obj/item/storage/fancy/cigarettes/cigpack_syndicate(src)
+ new /obj/item/card/id/advanced/chameleon(src)
+ new /obj/item/lighter(src)
+ new /obj/item/jammer(src)
+
+/obj/item/storage/box/syndie_kit/contract_kit/PopulateContents()
+ new /obj/item/storage/box/syndicate/contractor_loadout(src)
+ new /obj/item/melee/baton/telescopic/contractor_baton(src)
+
+ // You get one item from each sub list
+ var/static/list/item_list = list(
+ KIT_ITEM_CATEGORY_SUPPORT = list(
+ /obj/item/pen/sleepy,
+ /obj/item/storage/medkit/tactical,
+ /obj/item/pen/sleepy,
+ /obj/item/gun/syringe/syndicate,
+ /obj/item/storage/backpack/duffelbag/syndie/x4,
+ /obj/item/clothing/shoes/chameleon/noslip,
+ /obj/item/clothing/glasses/thermal/syndi,
+ /obj/item/storage/box/syndie_kit/imp_freedom,
+ /obj/item/reagent_containers/hypospray/medipen/stimulants,
+ /obj/item/card/emag/doorjack,
+ ),
+
+ KIT_ITEM_CATEGORY_WEAPONS = list(
+ /obj/item/melee/powerfist, //over value but its never used
+ /obj/item/storage/box/syndie_kit/origami_bundle,
+ /obj/item/clothing/gloves/krav_maga/combatglovesplus,
+ /obj/item/gun/ballistic/automatic/c20r/toy/unrestricted/riot,
+ /obj/item/storage/box/syndie_kit/throwing_weapons,
+ /obj/item/storage/box/syndie_kit/chemical, //technically over value but it cant be used on its own
+ /obj/item/autosurgeon/syndicate/anti_stun, //way over value but you dont get a real weapon, might have to remove this one
+ ),
+
+ KIT_ITEM_CATEGORY_MISC = list(
+ /obj/item/syndie_glue,
+ /obj/item/slimepotion/slime/sentience/nuclear,
+ /obj/item/storage/box/syndie_kit/imp_uplink,
+ /obj/item/grenade/clusterbuster/soap,
+ /obj/item/flashlight/emp,
+ /obj/item/encryptionkey/syndicate,
+ /obj/item/multitool/ai_detect,
+ /obj/item/storage/toolbox/syndicate,
+ /obj/item/card/emag,
+ /obj/item/ai_module/syndicate,
+ )
+ )
+
+ var/list/items_to_give = list()
+ items_to_give += pick(item_list[KIT_ITEM_CATEGORY_SUPPORT])
+ items_to_give += pick(item_list[KIT_ITEM_CATEGORY_WEAPONS])
+ items_to_give += pick(item_list[KIT_ITEM_CATEGORY_MISC])
+ generate_items_inside(items_to_give, src)
+
+ // Paper guide
+ new /obj/item/paper/contractor_guide(src)
+
+#undef KIT_ITEM_CATEGORY_SUPPORT
+#undef KIT_ITEM_CATEGORY_WEAPONS
+#undef KIT_ITEM_CATEGORY_MISC
diff --git a/monkestation/code/modules/antagonists/contractor/datums/contractor_datum.dm b/monkestation/code/modules/antagonists/contractor/datums/contractor_datum.dm
new file mode 100644
index 000000000000..68acfd7ee2e8
--- /dev/null
+++ b/monkestation/code/modules/antagonists/contractor/datums/contractor_datum.dm
@@ -0,0 +1,25 @@
+// Proc detailing contract kit buys/completed contracts/additional info
+/datum/antagonist/traitor/proc/contractor_round_end()
+ var/result = ""
+ var/total_spent_rep = 0
+
+ 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 += "
(used [total_spent_rep] Rep) "
+ result += contractor_item_icons
+ result += "
"
+
+ return result
diff --git a/monkestation/code/modules/antagonists/contractor/datums/contractor_hub.dm b/monkestation/code/modules/antagonists/contractor/datums/contractor_hub.dm
new file mode 100644
index 000000000000..6ac1f55aa061
--- /dev/null
+++ b/monkestation/code/modules/antagonists/contractor/datums/contractor_hub.dm
@@ -0,0 +1,4 @@
+/datum/contractor_hub
+ var/contract_rep = 0
+ var/static/list/hub_items = list()
+ var/list/purchased_items = list()
diff --git a/monkestation/code/modules/antagonists/contractor/datums/contractor_items.dm b/monkestation/code/modules/antagonists/contractor/datums/contractor_items.dm
new file mode 100644
index 000000000000..33f6de3a1933
--- /dev/null
+++ b/monkestation/code/modules/antagonists/contractor/datums/contractor_items.dm
@@ -0,0 +1,172 @@
+/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 = "broadcast-tower" // fontawesome icon to use inside the hub - https://fontawesome.com/icons/
+ var/stock = -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/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."
+ item = /obj/item/pinpointer/crew/contractor
+ item_icon = "search-location"
+ stock = 2
+ cost = 1
+
+/datum/contractor_item/fulton_extraction_kit
+ 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 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 = "parachute-box"
+ stock = 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 = "user-friends"
+ stock = 1
+ cost = 2
+ var/datum/mind/partner_mind = null
+
+/datum/contractor_item/contractor_partner/handle_purchase(datum/contractor_hub/hub, mob/living/user)
+ . = ..()
+ if(!.)
+ return
+
+ to_chat(user, span_notice("The uplink vibrates quietly, connecting to nearby agents..."))
+
+ var/list/mob/dead/observer/candidates = poll_ghost_candidates("Do you want to play as the Contractor Support Unit for [user.real_name]?", ROLE_TRAITOR, FALSE, 100, \
+ POLL_IGNORE_CONTRACTOR_SUPPORT)
+
+ if(LAZYLEN(candidates))
+ var/mob/dead/observer/candidate = pick(candidates)
+ spawn_contractor_partner(user, candidate.key)
+ else
+ to_chat(user, span_notice("No available agents at this time, please try again later."))
+
+ // refund and add the limit back.
+ stock += 1
+ hub.contract_rep += cost
+ hub.purchased_items -= src
+
+/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(null, STYLE_SYNDICATE)
+ arrival_pod.explosionSize = list(0,0,0,0)
+ arrival_pod.bluespace = TRUE
+
+ 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)
+ free_location = get_turf(user)
+
+ partner.forceMove(arrival_pod)
+ partner.ckey = key
+
+ /// 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[span_alertwarning("[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, "[span_alertwarning("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/pod_landingzone(free_location, arrival_pod)
+
+//this can be bought for TC, might have to be removed/replaced
+/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 = "bolt"
+ stock = 2
+ cost = 3
+
+/datum/contractor_item/blackout/handle_purchase(datum/contractor_hub/hub)
+ . = ..()
+
+ 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", ANNOUNCER_POWEROFF)
+
+// Subtract cost, and spawn if it's an item.
+/datum/contractor_item/proc/handle_purchase(datum/contractor_hub/hub, mob/living/user)
+
+ if (hub.contract_rep >= cost)
+ hub.contract_rep -= cost
+ else
+ return FALSE
+
+ if (stock >= 1)
+ stock -= 1
+ else if (stock == 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))
+
+ if(user.put_in_hands(item_to_create))
+ to_chat(user, span_notice("Your purchase materializes into your hands!"))
+ else
+ to_chat(user, span_notice("Your purchase materializes onto the floor."))
+
+ return item_to_create
+ return TRUE
+
+/obj/item/pinpointer/crew/contractor
+ name = "contractor pinpointer"
+ desc = "A handheld tracking device that locks onto certain signals. Ignores suit sensors, but is much less accurate."
+ icon_state = "pinpointer_syndicate"
+ worn_icon_state = "pinpointer_black"
+ minimum_range = 25
+ has_owner = TRUE
+ ignore_suit_sensor_level = TRUE
+
+/obj/item/storage/box/contractor/fulton_extraction
+ name = "Fulton Extraction Kit"
+ icon_state = "syndiebox"
+ illustration = "writing_syndie"
+
+/obj/item/storage/box/contractor/fulton_extraction/PopulateContents()
+ new /obj/item/extraction_pack(src)
+ new /obj/item/fulton_core(src)
+
+/datum/contractor_item/baton_holster
+ name = "Baton Holster Module"
+ desc = "Never worry about dropping your baton again with this holster module! Simply insert your baton into the module, put it in your MODsuit, \
+ and the baton will retract whenever dropped."
+ item = /obj/item/mod/module/baton_holster
+ item_icon = "arrow-up-from-arc" //I cannot find anything better, replace if you find something more fitting
+ stock = 1
+ cost = 1
+
+/datum/contractor_item/baton_upgrade_cuff
+ name = "Baton Cuff Upgrade"
+ desc = "Using technology reverse-engineered from some alien batons we had lying around, you can now cuff people using your baton with the secondary attack. \
+ Due to technical limitations, only cable cuffs and zipties work, and they need to be loaded into the baton manually."
+ item = /obj/item/baton_upgrade/cuff
+ item_icon = "handcuff"
+ stock = 1
+ cost = 1
+
+/datum/contractor_item/baton_upgrade_mute
+ name = "Baton Mute Upgrade"
+ desc = "A relatively new advancement in completely proprietary baton technology, this baton upgrade will mute anyone hit for ten seconds, maximizing at twenty seconds."
+ item = /obj/item/baton_upgrade/mute
+ item_icon = "comment-slash"
+ stock = 1
+ cost = 2
diff --git a/monkestation/code/modules/antagonists/contractor/datums/contractor_support.dm b/monkestation/code/modules/antagonists/contractor/datums/contractor_support.dm
new file mode 100644
index 000000000000..412839847373
--- /dev/null
+++ b/monkestation/code/modules/antagonists/contractor/datums/contractor_support.dm
@@ -0,0 +1,54 @@
+/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.
+ give_uplink = FALSE // Don't give them an uplink.
+ give_secondary_objectives = FALSE
+ /// Team datum that contains the contractor and the support unit
+ 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 the Contractor's Orders"
+ generic_objective.explanation_text = "Follow your orders. Assist agents in this mission area."
+
+ generic_objective.completed = TRUE
+
+ objectives += generic_objective
+
+/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
+ belt = /obj/item/modular_computer/pda/chameleon
+ mask = /obj/item/clothing/mask/cigarette/syndicate
+ shoes = /obj/item/clothing/shoes/chameleon/noslip
+ ears = /obj/item/radio/headset/chameleon
+ id = /obj/item/card/id/advanced/chameleon
+ r_hand = /obj/item/storage/toolbox/syndicate
+ id_trim = /datum/id_trim/chameleon/operative
+
+ 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/partner, visualsOnly)
+ . = ..()
+ var/obj/item/clothing/mask/cigarette/syndicate/cig = partner.get_item_by_slot(ITEM_SLOT_MASK)
+
+ // pre-light their cig
+ cig.light()
diff --git a/monkestation/code/modules/antagonists/contractor/datums/mind_datum.dm b/monkestation/code/modules/antagonists/contractor/datums/mind_datum.dm
new file mode 100644
index 000000000000..91cb9a5ac69b
--- /dev/null
+++ b/monkestation/code/modules/antagonists/contractor/datums/mind_datum.dm
@@ -0,0 +1,4 @@
+/datum/mind/proc/make_contractor_support()
+ if(has_antag_datum(/datum/antagonist/traitor/contractor_support))
+ return
+ add_antag_datum(/datum/antagonist/traitor/contractor_support)
diff --git a/monkestation/code/modules/antagonists/contractor/items/baton.dm b/monkestation/code/modules/antagonists/contractor/items/baton.dm
new file mode 100644
index 000000000000..b23f5dc2b5d9
--- /dev/null
+++ b/monkestation/code/modules/antagonists/contractor/items/baton.dm
@@ -0,0 +1,85 @@
+#define CUFF_MAXIMUM 3
+#define MUTE_CYCLES 5
+
+/obj/item/melee/baton/telescopic/contractor_baton
+ /// Ref to the baton holster, should the baton have one.
+ var/obj/item/mod/module/baton_holster/holster
+ /// Bitflags for what upgrades the baton has
+ var/upgrade_flags
+
+/obj/item/melee/baton/telescopic/contractor_baton/dropped(mob/user, silent)
+ . = ..()
+ if(!holster)
+ return
+ holster.undeploy(user)
+
+/obj/item/melee/baton/telescopic/contractor_baton/attack_secondary(mob/living/victim, mob/living/user, params)
+ if(!(upgrade_flags & BATON_CUFF_UPGRADE) || !active)
+ return
+ for(var/obj/item/restraints/handcuffs/cuff in src.contents)
+ cuff.attack(victim, user)
+ break
+
+/obj/item/melee/baton/telescopic/contractor_baton/attackby(obj/item/attacking_item, mob/user, params)
+ . = ..()
+ if(istype(attacking_item, /obj/item/baton_upgrade))
+ var/obj/item/baton_upgrade/upgrade = attacking_item
+ if(!(upgrade_flags & upgrade.upgrade_flag))
+ upgrade_flags |= upgrade.upgrade_flag
+ upgrade.desc_update(src)
+ attacking_item.forceMove(src)
+ balloon_alert(user, "[attacking_item] attached")
+ if(!(upgrade_flags & BATON_CUFF_UPGRADE) && !(upgrade_flags & BATON_ALL_UPGRADE))
+ return
+ if(!istype(attacking_item, /obj/item/restraints/handcuffs/cable))
+ return
+ var/cuffcount = 0
+ for(var/obj/item/restraints/handcuffs/cuff in src.contents)
+ cuffcount++
+ if(cuffcount >= CUFF_MAXIMUM)
+ balloon_alert(user, "baton at maximum cuffs")
+ return
+ attacking_item.forceMove(src)
+ balloon_alert(user, "[attacking_item] inserted")
+
+/obj/item/melee/baton/telescopic/contractor_baton/wrench_act(mob/living/user, obj/item/tool)
+ . = ..()
+ for(var/obj/item/baton_upgrade/upgrade in src.contents)
+ upgrade.forceMove(get_turf(src))
+ upgrade_flags &= ~upgrade.upgrade_flag
+ tool.play_tool_sound(src)
+ desc = initial(desc)
+
+/obj/item/melee/baton/telescopic/contractor_baton/additional_effects_non_cyborg(mob/living/carbon/target, mob/living/user)
+ . = ..()
+ if(!((upgrade_flags & BATON_MUTE_UPGRADE) && !(upgrade_flags & BATON_ALL_UPGRADE))|| !istype(target))
+ return
+ target.adjust_silence_up_to(10 SECONDS, 20 SECONDS)
+
+/obj/item/melee/baton/telescopic/contractor_baton/upgraded
+ upgrade_flags = BATON_ALL_UPGRADE
+ desc = "A compact, specialised baton assigned to Syndicate contractors. Applies light electrical shocks to targets. This one seems to be fully upgraded with unremovable parts."
+
+/obj/item/baton_upgrade
+ icon = 'monkestation/icons/obj/items/baton_upgrades.dmi'
+ var/upgrade_flag
+
+/obj/item/baton_upgrade/proc/desc_update(obj/item/melee/baton/telescopic/contractor_baton/batong)
+ if(!batong.upgrade_flags)
+ desc += "
[span_boldnotice("[batong] has the following upgrades attached:")]"
+ desc += "
[span_notice("[src].")]"
+
+/obj/item/baton_upgrade/cuff
+ name = "handcuff baton upgrade"
+ desc = "Allows the user to apply restraints to a target via baton, requires to be loaded with up to three prior."
+ icon_state = "cuff_upgrade"
+ upgrade_flag = BATON_CUFF_UPGRADE
+
+/obj/item/baton_upgrade/mute
+ name = "mute baton upgrade"
+ desc = "Use of the baton on a target will mute them for a short period."
+ icon_state = "mute_upgrade"
+ upgrade_flag = BATON_MUTE_UPGRADE
+
+#undef CUFF_MAXIMUM
+#undef MUTE_CYCLES
diff --git a/monkestation/code/modules/antagonists/contractor/items/boxes.dm b/monkestation/code/modules/antagonists/contractor/items/boxes.dm
new file mode 100644
index 000000000000..4f15be95e2fb
--- /dev/null
+++ b/monkestation/code/modules/antagonists/contractor/items/boxes.dm
@@ -0,0 +1,8 @@
+/obj/item/storage/box/contractor/fulton_extraction
+ name = "Fulton Extraction Kit"
+ icon_state = "syndiebox"
+ illustration = "writing_syndie"
+
+/obj/item/storage/box/contractor/fulton_extraction/PopulateContents()
+ new /obj/item/extraction_pack/contractor(src)
+ new /obj/item/fulton_core(src)
diff --git a/monkestation/code/modules/antagonists/contractor/items/misc.dm b/monkestation/code/modules/antagonists/contractor/items/misc.dm
new file mode 100644
index 000000000000..12f4db60ecf3
--- /dev/null
+++ b/monkestation/code/modules/antagonists/contractor/items/misc.dm
@@ -0,0 +1,14 @@
+/obj/item/pinpointer/crew/contractor
+ name = "contractor pinpointer"
+ desc = "A handheld tracking device that locks onto certain signals. Ignores suit sensors, but is much less accurate."
+ icon_state = "pinpointer_syndicate"
+ worn_icon_state = "pinpointer_black"
+ minimum_range = 15
+ has_owner = TRUE
+ ignore_suit_sensor_level = TRUE
+
+/obj/item/extraction_pack/contractor
+ name = "black fulton extraction pack"
+ desc = "A modified fulton pack that can be used indoors thanks to Bluespace technology. Favored by Syndicate Contractors."
+ icon = 'monkestation/icons/obj/items/fulton.dmi'
+ can_use_indoors = TRUE
diff --git a/monkestation/code/modules/antagonists/contractor/items/modsuit/modsuit.dm b/monkestation/code/modules/antagonists/contractor/items/modsuit/modsuit.dm
new file mode 100644
index 000000000000..31418e6c32c6
--- /dev/null
+++ b/monkestation/code/modules/antagonists/contractor/items/modsuit/modsuit.dm
@@ -0,0 +1,39 @@
+/obj/item/mod/control/pre_equipped/contractor
+ worn_icon = 'monkestation/icons/mob/clothing/worn_modsuit.dmi'
+ icon = 'monkestation/icons/obj/clothing/modsuits/contractor_modsuit.dmi'
+ theme = /datum/mod_theme/contractor
+ applied_cell = /obj/item/stock_parts/cell/hyper
+ applied_modules = list(
+ /obj/item/mod/module/storage/syndicate,
+ /obj/item/mod/module/tether,
+ /obj/item/mod/module/flashlight,
+ /obj/item/mod/module/dna_lock,
+ /obj/item/mod/module/holster,
+ )
+
+/obj/item/mod/control/pre_equipped/contractor/upgraded
+ applied_cell = /obj/item/stock_parts/cell/bluespace
+ applied_modules = list(
+ /obj/item/mod/module/storage/syndicate,
+ /obj/item/mod/module/jetpack,
+ /obj/item/mod/module/dna_lock,
+ /obj/item/mod/module/holster,
+ /obj/item/mod/module/baton_holster/preloaded,
+ )
+
+// I absolutely fuckin hate having to do this
+/obj/item/clothing/head/mod/contractor
+ worn_icon = 'monkestation/icons/mob/clothing/worn_modsuit.dmi'
+ icon = 'monkestation/icons/obj/clothing/modsuits/contractor_modsuit.dmi'
+
+/obj/item/clothing/suit/mod/contractor
+ worn_icon = 'monkestation/icons/mob/clothing/worn_modsuit.dmi'
+ icon = 'monkestation/icons/obj/clothing/modsuits/contractor_modsuit.dmi'
+
+/obj/item/clothing/gloves/mod/contractor
+ worn_icon = 'monkestation/icons/mob/clothing/worn_modsuit.dmi'
+ icon = 'monkestation/icons/obj/clothing/modsuits/contractor_modsuit.dmi'
+
+/obj/item/clothing/shoes/mod/contractor
+ worn_icon = 'monkestation/icons/mob/clothing/worn_modsuit.dmi'
+ icon = 'monkestation/icons/obj/clothing/modsuits/contractor_modsuit.dmi'
diff --git a/monkestation/code/modules/antagonists/contractor/items/modsuit/modules.dm b/monkestation/code/modules/antagonists/contractor/items/modsuit/modules.dm
new file mode 100644
index 000000000000..45fe4d1f1894
--- /dev/null
+++ b/monkestation/code/modules/antagonists/contractor/items/modsuit/modules.dm
@@ -0,0 +1,87 @@
+/obj/item/mod/module/baton_holster
+ name = "MOD baton holster module"
+ desc = "A module installed into the chest of a MODSuit, this allows you \
+ to retrieve an inserted baton from the suit at will. Insert a baton \
+ by using the module with the baton in hand. \
+ Remove an inserted baton by using a wrench on the module while it is removed from the suit."
+ icon_state = "holster"
+ icon = 'monkestation/icons/obj/items/modsuit_modules.dmi'
+ complexity = 3
+ incompatible_modules = list(/obj/item/mod/module/baton_holster)
+ module_type = MODULE_USABLE
+ /// Ref to the baton
+ var/obj/item/melee/baton/telescopic/contractor_baton/stored_batong
+ /// If the baton is out or not
+ var/deployed = FALSE
+
+// doesn't give a shit if it's deployed or not
+/obj/item/mod/module/baton_holster/on_select()
+ on_use()
+ SEND_SIGNAL(mod, COMSIG_MOD_MODULE_SELECTED, src)
+
+/obj/item/mod/module/baton_holster/wrench_act(mob/living/user, obj/item/tool)
+ . = ..()
+ if(!stored_batong)
+ return
+ balloon_alert(user, "[stored_batong] removed")
+ stored_batong.forceMove(get_turf(src))
+ stored_batong.holster = null
+ stored_batong = null
+ tool.play_tool_sound(src)
+
+/obj/item/mod/module/baton_holster/Destroy()
+ if(stored_batong)
+ stored_batong.forceMove(get_turf(src))
+ stored_batong.holster = null
+ stored_batong = null
+ . = ..()
+
+/obj/item/mod/module/baton_holster/on_use()
+ var/obj/item/held_item = mod.wearer.get_active_held_item()
+ if(istype(held_item, /obj/item/melee/baton/telescopic/contractor_baton) && !stored_batong)
+ balloon_alert(mod.wearer, "[held_item] inserted")
+ held_item.forceMove(src)
+ stored_batong = held_item
+ stored_batong.holster = src
+ return
+
+ if(!deployed)
+ deploy(mod.wearer)
+ else
+ undeploy(mod.wearer)
+
+/obj/item/mod/module/baton_holster/proc/deploy(mob/living/user)
+ if(!(stored_batong in src))
+ return
+ if(!user.put_in_hands(stored_batong))
+ to_chat(user, span_warning("You need a free hand to hold [stored_batong]!"))
+ return
+ deployed = TRUE
+ balloon_alert(user, "[stored_batong] deployed")
+
+/obj/item/mod/module/baton_holster/proc/undeploy(mob/living/user)
+ if(QDELETED(stored_batong))
+ return
+ stored_batong.forceMove(src)
+ deployed = FALSE
+ balloon_alert(user, "[stored_batong] retracted")
+
+/obj/item/mod/module/baton_holster/preloaded
+
+/obj/item/mod/module/baton_holster/preloaded/Initialize(mapload)
+ . = ..()
+ stored_batong = new/obj/item/melee/baton/telescopic/contractor_baton/upgraded(src)
+ stored_batong.holster = src
+//making this slow you down this will most likely not get used, might rework this
+/obj/item/mod/module/armor_booster/contractor // Much flatter distribution because contractor suit gets a shitton of armor already
+ armor_mod = /datum/armor/mod_module_armor_booster_contractor
+ speed_added = -0.3
+ desc = "An embedded set of armor plates, allowing the suit's already extremely high protection \
+ to be increased further. However, the plating, while deployed, will slow down the user \
+ and make the suit unable to vacuum seal so this extra armor provides zero ability for extravehicular activity while deployed."
+
+/datum/armor/mod_module_armor_booster_contractor
+ melee = 20
+ bullet = 20
+ laser = 20
+ energy = 20
diff --git a/monkestation/code/modules/antagonists/contractor/items/modsuit/theme.dm b/monkestation/code/modules/antagonists/contractor/items/modsuit/theme.dm
new file mode 100644
index 000000000000..fb71e85bbb56
--- /dev/null
+++ b/monkestation/code/modules/antagonists/contractor/items/modsuit/theme.dm
@@ -0,0 +1,68 @@
+/datum/mod_theme/contractor
+ name = "contractor"
+ desc = "A top-tier MODSuit developed with cooperation of Cybersun Industries and the Gorlex Marauders, a favorite of Syndicate Contractors."
+ extended_desc = "A rare depart from the Syndicate's usual color scheme, the Contractor MODsuit is produced and manufactured \
+ for specialty contractors. The build is a streamlined layering consisting of shaped Plastitanium, \
+ and composite ceramic, while the under suit is lined with a lightweight Kevlar and durathread hybrid weave \
+ to provide ample protection to the user where the plating doesn't, with an illegal onboard electric powered \
+ ablative shield module to provide resistance against conventional energy firearms. \
+ In addition, it has an in-built chameleon system, allowing you to disguise the suit while undeployed. \
+ A small tag hangs off of it reading; 'Property of the Gorlex Marauders, with assistance from Cybersun Industries. \
+ All rights reserved, tampering with suit will void warranty."
+ default_skin = "contractor"
+ armor_type = /datum/armor/mod_contractor_armor
+ atom_flags = PREVENT_CONTENTS_EXPLOSION_1
+ resistance_flags = FIRE_PROOF | ACID_PROOF
+ max_heat_protection_temperature = FIRE_SUIT_MAX_TEMP_PROTECT
+ siemens_coefficient = 0
+ slowdown_inactive = 1
+ slowdown_active = 0.5
+ ui_theme = "syndicate"
+ inbuilt_modules = list(/obj/item/mod/module/armor_booster/contractor, /obj/item/mod/module/chameleon)
+ allowed_suit_storage = list(
+ /obj/item/flashlight,
+ /obj/item/tank/internals,
+ /obj/item/ammo_box,
+ /obj/item/ammo_casing,
+ /obj/item/restraints/handcuffs,
+ /obj/item/assembly/flash,
+ /obj/item/melee/baton,
+ /obj/item/melee/energy/sword,
+ /obj/item/shield/energy,
+ /obj/item/gun/ballistic,
+ /obj/item/gun/energy,
+ )
+ skins = list(
+ "contractor" = list(
+ HELMET_LAYER = NECK_LAYER,
+ HELMET_FLAGS = list(
+ UNSEALED_CLOTHING = SNUG_FIT,
+ SEALED_CLOTHING = THICKMATERIAL|STOPSPRESSUREDAMAGE,
+ UNSEALED_INVISIBILITY = HIDEFACIALHAIR,
+ SEALED_INVISIBILITY = HIDEMASK|HIDEEARS|HIDEEYES|HIDEFACE|HIDEHAIR|HIDESNOUT,
+ SEALED_COVER = HEADCOVERSMOUTH|HEADCOVERSEYES|PEPPERPROOF,
+ ),
+ CHESTPLATE_FLAGS = list(
+ UNSEALED_CLOTHING = THICKMATERIAL,
+ SEALED_CLOTHING = STOPSPRESSUREDAMAGE,
+ ),
+ GAUNTLETS_FLAGS = list(
+ UNSEALED_CLOTHING = THICKMATERIAL,
+ SEALED_CLOTHING = STOPSPRESSUREDAMAGE,
+ ),
+ BOOTS_FLAGS = list(
+ UNSEALED_CLOTHING = THICKMATERIAL,
+ SEALED_CLOTHING = STOPSPRESSUREDAMAGE,
+ ),
+ ),
+ )
+
+/datum/armor/mod_contractor_armor
+ melee = 40
+ bullet = 50
+ laser = 30
+ energy = 40
+ bomb = 30
+ bio = 40
+ fire = 80
+ acid = 85
diff --git a/monkestation/code/modules/antagonists/traitor/datum_traitor.dm b/monkestation/code/modules/antagonists/traitor/datum_traitor.dm
new file mode 100644
index 000000000000..902fa6ef7c73
--- /dev/null
+++ b/monkestation/code/modules/antagonists/traitor/datum_traitor.dm
@@ -0,0 +1,3 @@
+/datum/antagonist/traitor
+ ///ref to our contractor hub datum, if we have one
+ var/datum/contractor_hub/contractor_hub
diff --git a/monkestation/code/modules/antagonists/traitor/traitor_objective.dm b/monkestation/code/modules/antagonists/traitor/traitor_objective.dm
new file mode 100644
index 000000000000..f728ec22b2ff
--- /dev/null
+++ b/monkestation/code/modules/antagonists/traitor/traitor_objective.dm
@@ -0,0 +1,3 @@
+/datum/traitor_objective
+ ///a bitfield for what types of uplinks can gain this objective
+ var/valid_uplinks = ALL //this is a secret tool that will help us later
diff --git a/monkestation/code/modules/antagonists/traitor/uplink_handler.dm b/monkestation/code/modules/antagonists/traitor/uplink_handler.dm
new file mode 100644
index 000000000000..8b137891791f
--- /dev/null
+++ b/monkestation/code/modules/antagonists/traitor/uplink_handler.dm
@@ -0,0 +1 @@
+
diff --git a/monkestation/code/modules/paperwork/paper_premade.dm b/monkestation/code/modules/paperwork/paper_premade.dm
new file mode 100644
index 000000000000..7ac48dd6302b
--- /dev/null
+++ b/monkestation/code/modules/paperwork/paper_premade.dm
@@ -0,0 +1,39 @@
+/obj/item/paper/contractor_guide
+ name = "Contractor Guide"
+
+/obj/item/paper/contractor_guide/Initialize(mapload)
+ default_raw_text = {"
Welcome agent, congratulations on your new position as contractor. On top of your already assigned objectives, + this kit will provide you contracts to take on for TC payments.
+Provided within, we give your specialist contractor space suit. It's even more compact, being able to fit into a pocket, and faster than the + Syndicate space suit available to you on the uplink. We also provide your chameleon jumpsuit and mask, both of which can be changed + to any form you need for the moment. The cigarettes are a special blend - it'll heal your injuries slowly overtime.
+Your standard issue contractor baton hits harder than the ones you might be used to, and likely be your go to weapon for kidnapping your + targets. The three additional items have been randomly selected from what we had available. We hope they're useful to you for your 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.
+Be careful when accepting a contract. While you'll be able to see the location of the dropoff point, cancelling will make it + unavailable to take on again.
+The tablet can also be recharged at any cell charger.
+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. Don't worry, we give you a cut of what we get paid. We pay this into whatever + ID card you have equipped, on top of the TC payment we give.
+Good luck agent. You can burn this document with the supplied lighter.
"} + + return ..() diff --git a/monkestation/code/modules/uplink/uplink_items/bundle.dm b/monkestation/code/modules/uplink/uplink_items/bundle.dm new file mode 100644 index 000000000000..7687174e936e --- /dev/null +++ b/monkestation/code/modules/uplink/uplink_items/bundle.dm @@ -0,0 +1,6 @@ +/datum/uplink_item/bundles_tc/contract_kit + name = "Contractor Bundle" + desc = "A box containing everything you need to take contracts from the Syndicate. Kidnap people and drop them off at specified locations for rewards in the form of Telecrystals \ + (Usable in the provided uplink) and Contractor Points. Can not be bought if you have completed any secondary objectives." + item = /obj/item/storage/box/syndicate/contract_kit + cost = 20 diff --git a/monkestation/icons/mob/clothing/worn_modsuit.dmi b/monkestation/icons/mob/clothing/worn_modsuit.dmi new file mode 100644 index 0000000000000000000000000000000000000000..5bb12b10c05eed0fb2704ef1da23401bed1c9829 GIT binary patch literal 1829 zcmV+=2io|FP)Wx{_qK$7^)61<5}G
zdPcva*AFPj;`>S|Go!^cg_-AE2^-iBHNtN0EzX g+n`zRz$k+X|tnBb8=B)@Oh3P_(AKHCYCp9*0kXEW_+14W~?NQ@m`n
z9h75$H1P%UJ1F9O1#d0ZNyfdxaXcHjwtVYd)%+oG=TeqpCRfV+1aYM%oq#ExQ){>_
zzruhE^Ewg4CZ$NDVZBW@2%I;v;j;S!4uC|DY1qPPD>G(0%L}c;h-7vv=kHb?{k?W*
z7ZGGkj*;HR|Cp(AvVbz4<7Hd=QtefMfzr
aHaOj{n%Phg|0|+
zu^2g{Y@Iq8k8t+r{M$!s{q2n&!Wr||7lzEq>Q(%+zJ#)O)PhHJH03gcRiSWpQ~m;-
z1TZ$GJH+9uGoZxySE=me?#Uef4sN1aNe
zWVC0?+3kI2d5-D~b+8Lj`KvTSA#QURJSqniJoo#u8oXV5xV=-(U{88WZFDL6*#1hb
z22$YT0v%<1{w8<-^lUuk_-)b1)DFc^wxI^Yi@JABuHly8=uPM|P4C_)x$vi^3pN96
zfBgAHq2aLoc$05rEyH=fTALiH%a_VQF`|mcBbz9=Md&}$nOxTxspBYEE$d$iyhbkt
z#MS6b(ESJ&0^?|ec2Ld
bcn5LD)5u25JRyJJNAtI
zpe(pIWoj0?JypLVDXu9KP}S#(KVXEHrF_nWte&5@-yn9qG^9YCo;$>JQ1TLVZIM6W
z?4k21c(Xhp?UGfYuNti!P2O7PzcW22veP_65)gC+CWMRr3Qss$I;Q`UyMQ)-Q6+@L
zC(78Id?=$5&5bzXG9I|Yk?~|q0y6!PSg%)!XFc^M;xt6
sOA`;GI?@JaXFI-TG#UA
z_lI5K+u`rTuTWX*`qQyQ0uo=9Yy}}5wIuUQFQZ1t^ZyvxpK(S$d7r=lST)lxIKV9u
zsN{B#DlAwYkatWLgpu!)@@aBg-)MF+s*JQY