diff --git a/__DEFINES/cameranet.dm b/__DEFINES/cameranet.dm
index d983342183e..7813a1b91ae 100644
--- a/__DEFINES/cameranet.dm
+++ b/__DEFINES/cameranet.dm
@@ -14,4 +14,5 @@
#define CAMERANET_ATMOSALARMS "Atmospheric Alarms"
#define CAMERANET_POWERALARMS "Power Alarms"
#define CAMERANET_SINGULARITY "Singularity"
-#define CAMERANET_RD "RD"
\ No newline at end of file
+#define CAMERANET_RD "RD"
+#define CAMERANET_SPESSTV "Spess.TV" // Sponsored
diff --git a/__DEFINES/reagents.dm b/__DEFINES/reagents.dm
index c16620a070f..a6771ead7f5 100644
--- a/__DEFINES/reagents.dm
+++ b/__DEFINES/reagents.dm
@@ -414,6 +414,7 @@
#define PLUMPHJUICE "plumphjuice"
#define PLUMPHWINE "phwine"
#define IRONROT "ironrot"
+#define GEOMETER "geometer"
#define TUNGSTEN "tungsten"
#define LITHIUMSODIUMTUNGSTATE "lithiumsodiumtungstate"
diff --git a/__DEFINES/role_datums_defines.dm b/__DEFINES/role_datums_defines.dm
index cec18705577..4dbba6df6e4 100644
--- a/__DEFINES/role_datums_defines.dm
+++ b/__DEFINES/role_datums_defines.dm
@@ -64,6 +64,7 @@
#define CATBEAST "loose catbeast"
#define RAMBLER "soul rambler"
#define PLAGUEMOUSE "plague mouse"
+#define STREAMER "streamer"
#define GREET_DEFAULT "default"
#define GREET_ROUNDSTART "roundstart"
diff --git a/__DEFINES/setup.dm b/__DEFINES/setup.dm
index 27bb6be8e5c..2ae174fdf32 100644
--- a/__DEFINES/setup.dm
+++ b/__DEFINES/setup.dm
@@ -1622,3 +1622,10 @@ var/proccalls = 1
// How many times to retry winset()ing window parameters before giving up
#define WINSET_MAX_ATTEMPTS 10
+
+// E-Sports teams
+#define ESPORTS_CULTISTS "Team Geometer"
+#define ESPORTS_SECURITY "Team Security"
+
+var/list/weekend_days = list("Friday", "Saturday", "Sunday")
+#define IS_WEEKEND (weekend_days.Find(time2text(world.timeofday, "Day")))
diff --git a/code/_onclick/hud/_defines.dm b/code/_onclick/hud/_defines.dm
index 4535f477613..305f9b1ce01 100644
--- a/code/_onclick/hud/_defines.dm
+++ b/code/_onclick/hud/_defines.dm
@@ -65,7 +65,7 @@
#define ui_internal "EAST-1:[28*PIXEL_MULTIPLIER],CENTER-0.5:[17*PIXEL_MULTIPLIER]"
#define ui_health "EAST-1:[28*PIXEL_MULTIPLIER],CENTER-1.5:[15*PIXEL_MULTIPLIER]"
#define ui_under_health "EAST-1:[28*PIXEL_MULTIPLIER],CENTER-2.5:[13*PIXEL_MULTIPLIER]"
-
+#define ui_more_under_health_and_to_the_left "EAST-2:[14*PIXEL_MULTIPLIER],CENTER-5:[24*PIXEL_MULTIPLIER]"
//borgs
#define ui_borg_health "EAST-1:[28*PIXEL_MULTIPLIER],SOUTH+5:[7*PIXEL_MULTIPLIER]"
#define ui_borg_album "EAST-1:[28*PIXEL_MULTIPLIER],SOUTH+4:[7*PIXEL_MULTIPLIER]"
diff --git a/code/_onclick/hud/hud.dm b/code/_onclick/hud/hud.dm
index c25b1b91030..6d33cee6dd7 100644
--- a/code/_onclick/hud/hud.dm
+++ b/code/_onclick/hud/hud.dm
@@ -26,6 +26,7 @@ var/global/obj/abstract/screen/clicker/catcher = new()
var/list/obj/abstract/screen/hand_hud_objects = list()
var/obj/abstract/screen/action_intent
var/obj/abstract/screen/move_intent
+ var/obj/abstract/screen/streamer_display // Sponsored
var/obj/abstract/screen/movable/action_button/hide_toggle/hide_actions_toggle
var/action_buttons_hidden = FALSE
diff --git a/code/_onclick/hud/other_mobs.dm b/code/_onclick/hud/other_mobs.dm
index 8978ce85e63..2c038c2ee45 100644
--- a/code/_onclick/hud/other_mobs.dm
+++ b/code/_onclick/hud/other_mobs.dm
@@ -170,6 +170,14 @@
mymob.client.screen += list(vampire_blood_display)
+/datum/hud/proc/streamer_hud(ui_style = 'icons/mob/screen1_Midnight.dmi')
+ streamer_display = getFromPool(/obj/abstract/screen)
+ streamer_display.name = "Streaming Stats"
+ streamer_display.icon = null
+ streamer_display.screen_loc = ui_more_under_health_and_to_the_left
+
+ mymob.client.screen += list(streamer_display)
+
/datum/hud/proc/changeling_hud()
vampire_blood_display = getFromPool(/obj/abstract/screen)
diff --git a/code/datums/gamemode/factions/bloodcult/bloodcult_items.dm b/code/datums/gamemode/factions/bloodcult/bloodcult_items.dm
index e1c5f288e7f..14198ec23c7 100644
--- a/code/datums/gamemode/factions/bloodcult/bloodcult_items.dm
+++ b/code/datums/gamemode/factions/bloodcult/bloodcult_items.dm
@@ -57,6 +57,8 @@ var/list/arcane_tomes = list()
var i = 1
for(var/subtype in subtypesof(/datum/rune_spell))
var/datum/rune_spell/blood_cult/instance = subtype
+ if(instance == /datum/rune_spell/blood_cult)
+ continue
if (initial(instance.Act_restriction) <= veil_thickness)
dat += " [initial(instance.name)] "
if (i == current_page)
@@ -1220,6 +1222,16 @@ var/list/arcane_tomes = list()
starting_materials = list(MAT_IRON = 3750)
w_type=RECYK_METAL
+/obj/item/weapon/storage/cult/sponsored
+ name = "sponsored coffer"
+ desc = "A sponsor-sticker-plastered storage chest."
+
+/obj/item/weapon/storage/cult/sponsored/New()
+ ..()
+ var/obj/item/weapon/reagent_containers/food/drinks/cult/cup = new(src)
+ cup.reagents.add_reagent(BLOOD, 50)
+ for(var/i in 1 to 2)
+ new /obj/item/weapon/reagent_containers/food/drinks/soda_cans/geometer(src)
///////////////////////////////////////CULT GLASS////////////////////////////////////////////////
/obj/item/weapon/reagent_containers/food/drinks/cult
@@ -1262,6 +1274,11 @@ var/list/arcane_tomes = list()
reagents.trans_to(H, gulp_size)
transfer(get_turf(hit_atom), null, splashable_units = -1)
+/obj/item/weapon/reagent_containers/food/drinks/cult/gamer
+ name = "gamer goblet"
+ desc = "A plastic cup in the shape of a skull. Typically full of Geometer-Fuel."
+ icon_state = "cult_gamer"
+
///////////////////////////////////////BLOOD TESSERACT////////////////////////////////////////////////
/obj/item/weapon/blood_tesseract
diff --git a/code/datums/gamemode/factions/bloodcult/bloodcult_runespells.dm b/code/datums/gamemode/factions/bloodcult/bloodcult_runespells.dm
index 9cf4951432b..f66c4a46d34 100644
--- a/code/datums/gamemode/factions/bloodcult/bloodcult_runespells.dm
+++ b/code/datums/gamemode/factions/bloodcult/bloodcult_runespells.dm
@@ -1037,6 +1037,10 @@
else
message_admins("Blood Cult: A conversion ritual occured...but we cannot find the cult faction...")//failsafe in case of admin varedit fuckery
cult_risk(activator)//risk of exposing the cult early if too many conversions
+ var/datum/role/streamer/streamer_role = activator?.mind?.GetRole(STREAMER)
+ if(streamer_role && streamer_role.team == ESPORTS_CULTISTS)
+ streamer_role.conversions += IS_WEEKEND ? 2 : 1
+ streamer_role.update_antag_hud()
switch (success)
if (CONVERSION_ACCEPT)
@@ -2699,6 +2703,33 @@ var/list/bloodcult_exitportals = list()
plane = ABOVE_HUMAN_PLANE
mouse_opacity = 0
+//RUNE XXI
+/datum/rune_spell/blood_cult/stream
+ name = "Stream"
+ desc = "Start or stop streaming on Spess.TV"
+ desc_talisman = "Start or stop streaming on Spess.TV"
+ Act_restriction = CULT_PROLOGUE
+ invocation = "L'k' c'mm'nt 'n' s'bscr'b! P'g ch'mp! Kappah!"
+ word1 = /datum/runeword/blood_cult/other
+ word2 = /datum/runeword/blood_cult/see
+ word3 = /datum/runeword/blood_cult/self
+ page = "This rune lets you start (or stop) streaming on Spess.TV so that you can let your audience watch and cheer for you while you slay infidels in the name of Nar-sie. #Sponsored"
+/datum/rune_spell/blood_cult/stream/cast()
+ var/datum/role/streamer/streamer = activator.mind.GetRole(STREAMER)
+ if(!streamer)
+ streamer = new /datum/role/streamer
+ streamer.team = ESPORTS_CULTISTS
+ if(!streamer.AssignToRole(activator.mind, 1))
+ streamer.Drop()
+ return
+ streamer.OnPostSetup()
+ streamer.Greet(GREET_DEFAULT)
+ streamer.AnnounceObjectives()
+ streamer.team = ESPORTS_CULTISTS
+ if(!streamer.camera)
+ streamer.set_camera(new /obj/machinery/camera/arena/spesstv(activator))
+ streamer.toggle_streaming()
+ qdel(src)
#undef RUNE_STAND
diff --git a/code/datums/gamemode/objectives/spesstv.dm b/code/datums/gamemode/objectives/spesstv.dm
new file mode 100644
index 00000000000..1851e855b90
--- /dev/null
+++ b/code/datums/gamemode/objectives/spesstv.dm
@@ -0,0 +1,37 @@
+/datum/objective/reach_followers
+ var/followers_jectie = 15
+ explanation_text = "Reach 15 followers."
+ name = "(streamer) Reach followers"
+
+/datum/objective/reach_followers/PostAppend()
+ followers_jectie = round(rand(10, 20))
+ explanation_text = "Reach [followers_jectie] followers."
+ return TRUE
+
+/datum/objective/reach_followers/IsFulfilled()
+ if (..())
+ return TRUE
+ var/datum/role/streamer/S = owner.GetRole(STREAMER)
+ if (!S)
+ message_admins("BUG: [owner.current] was given a streamer objective but is not affiliated with Spess.TV!")
+ return FALSE
+ return length(S.followers) >= followers_jectie
+
+/datum/objective/reach_subscribers
+ var/subscribers_jectie = 7
+ explanation_text = "Reach 7 subscribers."
+ name = "(streamer) Reach subscribers"
+
+/datum/objective/reach_subscribers/PostAppend()
+ subscribers_jectie = round(rand(5, 10))
+ explanation_text = "Reach [subscribers_jectie] subscribers."
+ return TRUE
+
+/datum/objective/reach_subscribers/IsFulfilled()
+ if (..())
+ return TRUE
+ var/datum/role/streamer/S = owner.GetRole(STREAMER)
+ if (!S)
+ message_admins("BUG: [owner.current] was given a streamer objective but is not affiliated with Spess.TV!")
+ return FALSE
+ return length(S.subscribers) >= subscribers_jectie
diff --git a/code/datums/gamemode/role/streamer.dm b/code/datums/gamemode/role/streamer.dm
new file mode 100644
index 00000000000..6e94f1fd3a9
--- /dev/null
+++ b/code/datums/gamemode/role/streamer.dm
@@ -0,0 +1,137 @@
+/datum/role/streamer
+ id = STREAMER
+ name = STREAMER
+ logo_state = "streamer-logo"
+ greets = list(GREET_DEFAULT, GREET_CUSTOM)
+
+ var/list/followers = list()
+ var/list/subscribers = list()
+ var/team
+ var/conversions = 0
+ var/hits = 0
+ var/obj/machinery/camera/arena/spesstv/camera
+
+/datum/role/streamer/Greet(greeting, custom)
+ if(!greeting)
+ return
+
+ var/icon/logo = icon('icons/logos.dmi', logo_state)
+ switch(greeting)
+ if (GREET_CUSTOM)
+ to_chat(antag.current, "
[custom]")
+ else
+ to_chat(antag.current, "
You are now online!
")
+ to_chat(antag.current, "Entertain your audience to obtain followers and subscribers!")
+ antag.current << sound('sound/machines/lawsync.ogg')
+
+/datum/role/streamer/OnPostSetup()
+ . = ..()
+ update_streamer_hud()
+ ForgeObjectives()
+
+/datum/role/streamer/RemoveFromRole(var/datum/mind/M)
+ if(antag.current.client && antag.current.hud_used)
+ if(antag.current.hud_used.streamer_display)
+ antag.current.client.screen -= list(antag.current.hud_used.streamer_display)
+ ..()
+
+/datum/role/streamer/AdminPanelEntry(var/show_logo = FALSE,var/datum/admins/A)
+ var/icon/logo = icon('icons/logos.dmi', logo_state)
+ var/mob/M = antag.current
+ var/text
+ if (!M) // Body destroyed
+ text = "[antag.name]/[antag.key] (BODY DESTROYED)"
+ else
+ text = {"[show_logo ? "
" : "" ]
+[name] [key_name(M)][M.client ? "" : " - (logged out)"][M.stat == DEAD ? " - (DEAD)" : ""]
+ - (priv msg)
+ - (role panel) - Give blood"}
+ return text
+
+/datum/role/streamer/ForgeObjectives()
+ AppendObjective(/datum/objective/reach_followers)
+ AppendObjective(/datum/objective/reach_subscribers)
+
+/datum/role/streamer/GetScoreboard()
+ switch(team)
+ if(ESPORTS_CULTISTS)
+ . += "Conversions: [conversions]
"
+ if(ESPORTS_SECURITY)
+ . += "Hits: [hits]
"
+ . += "Followers: [length(followers)]
"
+ . += "Subscribers: [length(subscribers)]
"
+ . += ..()
+
+/datum/role/streamer/update_antag_hud()
+ update_streamer_hud()
+
+/datum/role/streamer/proc/update_streamer_hud()
+ var/mob/M = antag.current
+ if(!M || M.gcDestroyed || !M.client || !M.hud_used)
+ return
+ var/obj/abstract/screen/streamer_display = M.hud_used.streamer_display
+ if(!streamer_display)
+ M.hud_used.streamer_hud()
+ streamer_display = M.hud_used.streamer_display
+ streamer_display.maptext_width = (WORLD_ICON_SIZE*2)+20
+ streamer_display.maptext_height = WORLD_ICON_SIZE*2
+ var/list/text = list("
")
+ if(IS_WEEKEND)
+ text += "Double XP enabled!
"
+ switch(team)
+ if(ESPORTS_CULTISTS)
+ text += "Conversions: [conversions]"
+ if(ESPORTS_SECURITY)
+ text += "Hits: [hits]"
+ text += "
Followers: [length(followers)]"
+ text += "
Subscribers:[length(subscribers)]
"
+ streamer_display.maptext = jointext(text, null)
+
+/datum/role/streamer/proc/try_add_follower(datum/mind/new_follower)
+ if(new_follower == antag)
+ to_chat(new_follower.current, "Following yourself is against Spess.TV's End User License Agreement.")
+ return
+ if(followers.Find(new_follower))
+ to_chat(new_follower.current, "You are already following [antag.name].")
+ return
+ followers += new_follower
+ update_antag_hud()
+ new_follower.current.visible_message("[new_follower.current] is now following [antag.name]!")
+
+/datum/role/streamer/proc/try_add_subscription(datum/mind/new_subscriber, obj/machinery/computer/security/telescreen/entertainment/spesstv/tv)
+ if(new_subscriber == antag)
+ to_chat(new_subscriber.current, "Subscribing to yourself is against Spess.TV's End User License Agreement.")
+ return
+ if(subscribers.Find(new_subscriber))
+ to_chat(new_subscriber.current, "You're already subscribed to [antag.name]!")
+ return
+ tv.reconnect_database()
+ if(tv.charge_flow(tv.linked_db, new_subscriber.current.get_id_card(), new_subscriber.current, 250, station_account, "Spess.TV subscription to [antag.name]") == CARD_CAPTURE_SUCCESS)
+ tv.visible_message("[new_subscriber.current] just subscribed to [name]!")
+ playsound(tv, pick('sound/effects/noisemaker1.ogg', 'sound/effects/noisemaker2.ogg', 'sound/effects/noisemaker3.ogg'), 100, TRUE)
+ playsound(antag.current, pick('sound/effects/noisemaker1.ogg', 'sound/effects/noisemaker2.ogg', 'sound/effects/noisemaker3.ogg'), 100, TRUE)
+ else
+ playsound(tv, 'sound/machines/alert.ogg', 50, TRUE)
+ tv.visible_message("[bicon(tv)]Something went wrong processing [new_subscriber.current]'s payment.")
+ return
+ subscribers += new_subscriber
+ update_antag_hud()
+ switch(team)
+ if(ESPORTS_CULTISTS)
+ new /obj/item/weapon/storage/cult/sponsored(get_turf(antag.current))
+ for(var/i in 1 to 3)
+ new /obj/item/weapon/reagent_containers/food/drinks/soda_cans/geometer(get_turf(new_subscriber.current))
+ if(ESPORTS_SECURITY)
+ new /obj/item/weapon/storage/lockbox/security_sponsored(get_turf(antag.current))
+ for(var/i in 1 to 4)
+ new /obj/item/weapon/reagent_containers/food/snacks/donitos(get_turf(new_subscriber.current))
+
+/datum/role/streamer/proc/toggle_streaming()
+ camera.deactivate()
+ antag.current.visible_message("[antag.current] is now [camera.status ? "streaming!" : "offline."]")
+
+/datum/role/streamer/proc/set_camera(obj/machinery/camera/arena/spesstv/new_camera)
+ ASSERT(istype(new_camera))
+ camera = new_camera
+ camera.streamer = src
+ camera.name_camera()
diff --git a/code/datums/religions.dm b/code/datums/religions.dm
index be28658670b..0261b8cf5f8 100755
--- a/code/datums/religions.dm
+++ b/code/datums/religions.dm
@@ -1188,10 +1188,10 @@
deity_name = "Peter Kropotkin"
bible_name = "The Conquest of Bread"
bible_type = /obj/item/weapon/storage/bible/booze
- male_adept = "Activist"
+ male_adept = "Activist"
female_adept = "Activist"
keys = list("anarcho-communism", "communalism", "mutualism")
-
+
/datum/religion/ancom/equip_chaplain(var/mob/living/carbon/human/H)
H.equip_or_collect(new /obj/item/clothing/mask/balaclava(H), slot_l_store) // Black Bloc
@@ -1365,4 +1365,58 @@
/datum/religion/belmont/equip_chaplain(var/mob/living/carbon/human/H)
H.equip_or_collect(new /obj/item/clothing/suit/vamphunter, slot_w_uniform)
- H.equip_or_collect(new /obj/item/clothing/head/vamphunter, slot_shoes)
\ No newline at end of file
+ H.equip_or_collect(new /obj/item/clothing/head/vamphunter, slot_shoes)
+
+/datum/religion/esports
+ name = "E-Sports"
+ deity_name = "E-Sports"
+ bible_name = "Spess.TV End User License Agreement"
+ male_adept = "Donitos Pope"
+ female_adept = "Donitos Priestess"
+ keys = list("gaming", "esport", "esports", "e-sports", "electronic sports", "donitos", "geometer")
+ convert_method = "having others hold a bag of Donitos, while you do the same."
+ bookstyle = "Creeper"
+
+/datum/religion/esports/equip_chaplain(mob/living/carbon/human/H)
+ var/turf/here = get_turf(H)
+ new /obj/item/weapon/crowbar/red(here)
+ var/obj/item/clothing/head/donitos_pope/pope_hat = new(here)
+ H.equip_to_appropriate_slot(pope_hat, override=TRUE)
+ var/obj/structure/closet/crate/flatpack/tv_pack1 = new(here)
+ tv_pack1.insert_machine(new /obj/machinery/computer/security/telescreen/entertainment/spesstv/flatscreen)
+ var/obj/structure/closet/crate/flatpack/tv_pack2 = new(here)
+ tv_pack2.insert_machine(new /obj/machinery/computer/security/telescreen/entertainment/spesstv/flatscreen)
+
+ var/obj/structure/closet/crate/flatpack/cameras_pack = new(here)
+ cameras_pack.insert_machine(new /obj/item/weapon/storage/lockbox/team_security_cameras)
+
+ var/obj/structure/closet/crate/flatpack/vending_machine_pack = new(here)
+ vending_machine_pack.insert_machine(new /obj/machinery/vending/team_security)
+
+ tv_pack1.add_stack(tv_pack2)
+ tv_pack1.add_stack(cameras_pack)
+ tv_pack1.add_stack(vending_machine_pack)
+
+/datum/religion/esports/convertCeremony(mob/living/preacher, mob/living/subject)
+ var/obj/item/weapon/reagent_containers/food/snacks/donitos/preacher_donitos = preacher.get_held_item_by_index(preacher.find_held_item_by_type(/obj/item/weapon/reagent_containers/food/snacks/donitos))
+ if(!preacher_donitos)
+ to_chat(preacher, "You need to hold a bag of Donitos to begin the conversion.")
+ return FALSE
+ var/obj/item/weapon/reagent_containers/food/snacks/donitos/subject_donitos = subject.get_held_item_by_index(subject.find_held_item_by_type(/obj/item/weapon/reagent_containers/food/snacks/donitos))
+ if(!subject_donitos)
+ to_chat(preacher, "The subject needs to hold a bag of Donitos to begin the conversion.")
+ return FALSE
+
+ subject.visible_message("\The [preacher] attemps to convert \the [subject] to [name].")
+
+ if(!convertCheck(subject))
+ subject.visible_message("\The [subject] refuses conversion.")
+ return FALSE
+
+ preacher_donitos.attack_self(preacher)
+ subject_donitos.attack_self(subject)
+
+ subject.visible_message("\The [subject] signs Spess.TV's End User License Agreement and becomes a registered user! Let's go watch some [deity_name]!")
+
+ convert(subject, preacher)
+ return TRUE
diff --git a/code/datums/supplypacks.dm b/code/datums/supplypacks.dm
index 454131e8f85..f43e90d62eb 100755
--- a/code/datums/supplypacks.dm
+++ b/code/datums/supplypacks.dm
@@ -2431,3 +2431,11 @@ var/list/all_supply_groups = list("Supplies","Clothing","Security","Hospitality"
containertype = /obj/structure/stackopacks
containername = "Al's Fun And Games stack of packs"
group = "Vending Machine Packs"
+
+/datum/supply_packs/teamsecurity
+ name = "Team Security stack of packs"
+ contains = list(/obj/structure/vendomatpack/team_security, /obj/structure/vendomatpack/team_security)
+ cost = 10
+ containertype = /obj/structure/stackopacks
+ containername = "Team Security stack of packs"
+ group = "Vending Machine packs"
diff --git a/code/game/atoms_movable.dm b/code/game/atoms_movable.dm
index 8984057f892..7142cd878b9 100644
--- a/code/game/atoms_movable.dm
+++ b/code/game/atoms_movable.dm
@@ -946,23 +946,41 @@
for(var/client/C in viewers)
C.images -= override_image
-//Attack Animation for ghost object being pixel shifted onto person
- var/image/item = image(icon=tool.icon, icon_state = tool.icon_state)
- item.appearance = tool.attack_icon()
- item.alpha = 128
- item.loc = target
- item.pixel_x = target.pixel_x - horizontal * 0.5 * WORLD_ICON_SIZE
- item.pixel_y = target.pixel_y - vertical * 0.5 * WORLD_ICON_SIZE
- item.mouse_opacity = 0
+ spawn()
+ //Attack Animation for ghost object being pixel shifted onto person
+ var/image/item = image(icon=tool.icon, icon_state = tool.icon_state)
+ item.appearance = tool.attack_icon()
+ item.alpha = 128
+ item.loc = target
+ item.pixel_x = target.pixel_x - horizontal * 0.5 * WORLD_ICON_SIZE
+ item.pixel_y = target.pixel_y - vertical * 0.5 * WORLD_ICON_SIZE
+ item.mouse_opacity = 0
- var/viewers = item_animation_viewers.Copy()
- for(var/client/C in viewers)
- C.images += item
+ var/viewers = item_animation_viewers.Copy()
+ for(var/client/C in viewers)
+ C.images += item
- animate(item, pixel_x = target.pixel_x, pixel_y = target.pixel_y, time = 3)
- sleep(3)
- for(var/client/C in viewers)
- C.images -= item
+ animate(item, pixel_x = target.pixel_x, pixel_y = target.pixel_y, time = 3)
+ sleep(3)
+ for(var/client/C in viewers)
+ C.images -= item
+
+ spawn()
+ target.do_hitmarker(usr)
+
+/atom/proc/do_hitmarker(mob/shooter)
+ spawn()
+ var/datum/role/streamer/streamer_role = shooter?.mind?.GetRole(STREAMER)
+ if(streamer_role?.team == ESPORTS_SECURITY)
+ streamer_role.hits += IS_WEEKEND ? 2 : 1
+ streamer_role.update_antag_hud()
+ playsound(src, 'sound/effects/hitmarker.ogg', 100, FALSE)
+ var/image/hitmarker = image(icon='icons/effects/effects.dmi', loc=src, icon_state="hitmarker")
+ for(var/client/C in clients)
+ C.images += hitmarker
+ sleep(3)
+ for(var/client/C in clients)
+ C.images -= hitmarker
/atom/movable/proc/make_invisible(var/source_define, var/time, var/include_clothing) //Makes things practically invisible, not actually invisible. Alpha is set to 1.
return invisibility || alpha <= 1 //already invisible
diff --git a/code/game/machinery/camera/camera.dm b/code/game/machinery/camera/camera.dm
index 692af09ffe7..3c30f6f9e41 100644
--- a/code/game/machinery/camera/camera.dm
+++ b/code/game/machinery/camera/camera.dm
@@ -352,7 +352,7 @@ var/list/camera_messages = list()
/obj/machinery/camera/attack_pai(mob/user as mob)
wirejack(user)
-/obj/machinery/camera/proc/deactivate(user as mob, var/choice = 1)
+/obj/machinery/camera/proc/deactivate(user as mob, var/choice = 1, quiet = FALSE)
vision_flags = SEE_SELF
if(assembly)
update_upgrades()
@@ -362,20 +362,21 @@ var/list/camera_messages = list()
update_icon()
if (!(src.status))
if(user)
- visible_message("[user] has deactivated [src]!")
- add_hiddenprint(user)
+ if(!quiet)
+ visible_message("[user] has deactivated [src]!")
else
- visible_message(" \The [src] deactivates!")
- playsound(src, 'sound/items/Wirecutter.ogg', 50, 1)
- add_hiddenprint(user)
+ if(!quiet)
+ visible_message(" \The [src] deactivates!")
else
if(user)
- visible_message(" [user] has reactivated [src]!")
- add_hiddenprint(user)
+ if(!quiet)
+ visible_message(" [user] has reactivated [src]!")
else
- visible_message(" \The [src] reactivates!")
+ if(!quiet)
+ visible_message(" \The [src] reactivates!")
+ if(!quiet)
playsound(src, 'sound/items/Wirecutter.ogg', 50, 1)
- add_hiddenprint(user)
+ add_hiddenprint(user)
cameranet.updateVisibility(src, 0)
// now disconnect anyone using the camera
//Apparently, this will disconnect anyone even if the camera was re-activated.
@@ -546,6 +547,35 @@ var/list/camera_messages = list()
/obj/machinery/camera/arena/bullet_act(var/obj/item/projectile/Proj)
return
+/obj/machinery/camera/arena/spesstv
+ name = "\improper Spess.TV camera"
+ network = list(CAMERANET_SPESSTV)
+ var/datum/role/streamer/streamer
+
+/obj/machinery/camera/arena/spesstv/New()
+ ..()
+ for(var/obj/item/weapon/reagent_containers/food/snacks/grown/carrot in assembly.upgrades)
+ assembly.upgrades -= carrot
+ update_upgrades()
+ deactivate()
+
+/obj/machinery/camera/arena/spesstv/name_camera()
+ var/team_name = streamer?.team
+ var/basename = streamer?.antag?.name || "Unknown"
+ if(team_name)
+ basename = "\[[team_name]\] [basename]"
+ var/nethash = english_list(network)
+ var/suffix = 0
+ while(!suffix || (nethash+c_tag in camera_names))
+ c_tag = "[basename]"
+ if(suffix)
+ c_tag += " [suffix]"
+ suffix++
+ camera_names[nethash+c_tag]=src
+
+/obj/machinery/camera/deactivate(mob/user, choice = TRUE, quiet = TRUE)
+ ..()
+
/obj/machinery/camera/kick_act(mob/living/carbon/human/H)
H.visible_message("[H] attempts to kick \the [src].", "You attempt to kick \the [src].")
to_chat(H, "Dumb move! You strain a muscle.")
diff --git a/code/game/machinery/computer/camera.dm b/code/game/machinery/computer/camera.dm
index c12191f1df7..3a21018a661 100644
--- a/code/game/machinery/computer/camera.dm
+++ b/code/game/machinery/computer/camera.dm
@@ -20,8 +20,7 @@ var/list/obj/machinery/camera/cyborg_cams = list(
light_color = LIGHT_COLOR_RED
-/obj/machinery/computer/security/New()
- ..()
+/obj/machinery/computer/security/proc/init_action_buttons()
var/datum/action/camera/previous/P = new(src)
var/datum/action/camera/cancel/C = new(src)
var/datum/action/camera/cyborg/C1 = new(src)
@@ -29,6 +28,10 @@ var/list/obj/machinery/camera/cyborg_cams = list(
var/datum/action/camera/next/N = new(src)
our_actions = list(P, C, C1, L, N)
+/obj/machinery/computer/security/New()
+ ..()
+ init_action_buttons()
+
if (ticker && ticker.current_state == GAME_STATE_PLAYING)
init_cams()
@@ -72,7 +75,7 @@ var/list/obj/machinery/camera/cyborg_cams = list(
if (src.z > 6)
to_chat(user, "Unable to establish a connection: You're too far away from the station!")
return
- if(stat & (NOPOWER|BROKEN))
+ if(!is_operational())
return
if(!isAI(user))
@@ -97,12 +100,13 @@ var/list/obj/machinery/camera/cyborg_cams = list(
density = 0
circuit = null
layer = ABOVE_WINDOW_LAYER
-
+ pass_flags = PASSTABLE
light_color = null
/obj/machinery/computer/security/telescreen/examine(mob/user)
..()
- to_chat(user, "Looks like the current channel is \"[current.c_tag]\"")
+ if(current?.c_tag)
+ to_chat(user, "Looks like the current channel is \"[current.c_tag]\"")
/obj/machinery/computer/security/telescreen/update_icon()
icon_state = initial(icon_state)
@@ -115,12 +119,43 @@ var/list/obj/machinery/camera/cyborg_cams = list(
desc = "Damn, they better have chicken-channel on these things."
icon = 'icons/obj/status_display.dmi'
icon_state = "entertainment"
- network = list(CAMERANET_THUNDER, CAMERANET_COURTROOM)
+ network = list(CAMERANET_THUNDER, CAMERANET_COURTROOM, CAMERANET_SPESSTV)
density = 0
circuit = null
light_color = null
+/obj/machinery/computer/security/telescreen/entertainment/spesstv
+ name = "low-latency Spess.TV CRT monitor"
+ desc = "An ancient computer monitor. They don't make them like they used to. A sticker reads: \"Come be their hero\"."
+ icon = 'icons/obj/spesstv.dmi'
+ icon_state = "crt"
+ network = list(CAMERANET_SPESSTV)
+ density = TRUE
+
+/obj/machinery/computer/security/telescreen/entertainment/spesstv/is_operational()
+ return TRUE
+
+/obj/machinery/computer/security/telescreen/entertainment/spesstv/update_icon()
+
+/obj/machinery/computer/security/telescreen/entertainment/spesstv/init_action_buttons()
+ var/datum/action/camera/previous/P = new(src)
+ var/datum/action/camera/cancel/C = new(src)
+ var/datum/action/camera/listing/L = new(src)
+ var/datum/action/camera/next/N = new(src)
+ var/datum/action/camera/follow/F = new(src)
+ var/datum/action/camera/subscribe/S = new(src)
+ our_actions = list(P, C, L, N, F, S)
+
+/obj/machinery/computer/security/telescreen/entertainment/spesstv/flatscreen
+ name = "high-definition Spess.TV telescreen"
+ icon = 'icons/obj/status_display.dmi'
+ icon_state = "entertainment"
+
+/obj/machinery/computer/security/telescreen/entertainment/spesstv/flatscreen/New()
+ ..()
+ overlays += "spesstv_overlay"
+
/obj/machinery/computer/security/telescreen/entertainment/wooden_tv
icon_state = "security_det"
icon = 'icons/obj/computer.dmi'
@@ -285,6 +320,39 @@ var/list/obj/machinery/camera/cyborg_cams = list(
var/mob/living/user = owner
user.cancel_camera()
+/datum/action/camera/follow
+ name = "Follow!"
+ desc = "Follow this streamer to be notified when they go online."
+ icon_icon = 'icons/obj/camera_buttons.dmi'
+ button_icon_state = "follow"
+
+/datum/action/camera/follow/Trigger()
+ if(usr.incapacitated())
+ return
+ var/obj/machinery/computer/security/telescreen/entertainment/spesstv/tv = target
+ if(!in_range(tv, usr))
+ return
+ var/obj/machinery/camera/arena/spesstv/camera = tv.current
+ var/datum/role/streamer/streamer_role = camera.streamer
+
+ streamer_role.try_add_follower(usr.mind)
+
+/datum/action/camera/subscribe
+ name = "Subscribe! ($250)"
+ desc = "Support this streamer and get a subscriber badge and a loot box!"
+ icon_icon = 'icons/obj/camera_buttons.dmi'
+ button_icon_state = "subscribe"
+
+/datum/action/camera/subscribe/Trigger()
+ if(usr.incapacitated())
+ return
+ var/obj/machinery/computer/security/telescreen/entertainment/spesstv/tv = target
+ if(!in_range(tv, usr))
+ return
+ var/obj/machinery/camera/arena/spesstv/camera = tv.current
+ var/datum/role/streamer/streamer_role = camera.streamer
+
+ streamer_role.try_add_subscription(usr.mind, tv)
/datum/action/camera/cyborg
name = "Cyborg camera listing"
desc = "List all the cyborg cameras conected to this network."
@@ -315,4 +383,4 @@ var/list/obj/machinery/camera/cyborg_cams = list(
var/obj/machinery/camera/C = L[t]
- our_computer.set_camera(user, C)
\ No newline at end of file
+ our_computer.set_camera(user, C)
diff --git a/code/game/machinery/vending.dm b/code/game/machinery/vending.dm
index 7e6d701481e..8d5fcfb9277 100644
--- a/code/game/machinery/vending.dm
+++ b/code/game/machinery/vending.dm
@@ -3383,3 +3383,48 @@ var/global/num_vending_terminals = 1
pack = /obj/structure/vendomatpack/games
vend_reply = "Don't have too much fun!"
+
+/obj/machinery/vending/team_security
+ name = "\improper Team Security Merch"
+ desc = "A refurbished vending machine selling merch for Team Security."
+ icon_state = "teamsec"
+ vend_reply = "Team Security is my Guideline."
+ product_slogans = list(
+ "Security helmet: on. Knuckles: cracked. Clown: brutalized. Yep...it's Team Security time.",
+ "It's a steal!",
+ "Get caught red-handed."
+ )
+ product_ads = list(
+ "For Security, by Security.",
+ "For the Bold.",
+ "Colonel Quality, guaranteed.",
+ "Red Team cuts off demon wings.",
+ )
+ products = list(
+ /obj/item/weapon/reagent_containers/food/snacks/donitos = 10,
+ /obj/item/clothing/head/soft/sec = 10,
+ /obj/item/clothing/under/team_security = 10,
+ /obj/item/clothing/under/team_security/dark = 10,
+ /obj/item/clothing/under/spesstv = 1,
+ /obj/item/clothing/shoes/jackboots = 10,
+ )
+ contraband = list(
+ /obj/item/clothing/under/team_geometer = 10,
+ /obj/item/weapon/reagent_containers/food/snacks/donitos/coolranch = 10,
+ )
+ premium = list(
+ /obj/item/clothing/under/team_nt = 1,
+ /obj/item/weapon/gun/energy/taser/team_security = 1,
+ )
+ prices = list(
+ /obj/item/weapon/reagent_containers/food/snacks/donitos = 10,
+ /obj/item/weapon/reagent_containers/food/snacks/donitos/coolranch = 10,
+ /obj/item/clothing/head/soft/sec = 25,
+ /obj/item/clothing/under/team_security = 25,
+ /obj/item/clothing/under/team_security/dark = 25,
+ /obj/item/clothing/shoes/jackboots = 25,
+ /obj/item/weapon/gun/energy/taser/team_security = 100,
+ )
+ pack = /obj/structure/vendomatpack/team_security
+
+ machine_flags = SCREWTOGGLE | WRENCHMOVE | FIXED2WORK | CROWDESTROY | EJECTNOTDEL | EMAGGABLE
diff --git a/code/game/machinery/vending_packs.dm b/code/game/machinery/vending_packs.dm
index c8f25140063..67476ffd7b8 100644
--- a/code/game/machinery/vending_packs.dm
+++ b/code/game/machinery/vending_packs.dm
@@ -224,6 +224,11 @@
targetvendomat = /obj/machinery/vending/games
icon_state = "games"
+/obj/structure/vendomatpack/team_security
+ name = "Team Security recharge pack"
+ targetvendomat = /obj/machinery/vending/team_security
+ icon_state = "team_security"
+
//////EMPTY PACKS//////
/obj/item/emptyvendomatpack
diff --git a/code/game/objects/items/trash.dm b/code/game/objects/items/trash.dm
index 803a580a165..ebcb3f3cf77 100644
--- a/code/game/objects/items/trash.dm
+++ b/code/game/objects/items/trash.dm
@@ -112,6 +112,14 @@
name = "\improper Discount Dan's Chocolate Bar"
icon_state = "danbar"
+/obj/item/trash/donitos
+ name = "Donitos"
+ icon_state = "donitos"
+
+/obj/item/trash/donitos_coolranch
+ name = "Donitos Cool Ranch"
+ icon_state = "donitos_coolranch"
+
/obj/item/trash/danitos
name = "\improper Danitos"
icon_state = "danitos"
diff --git a/code/game/objects/items/weapons/implants/implanter.dm b/code/game/objects/items/weapons/implants/implanter.dm
index 584dbfa3b9a..27677203a26 100644
--- a/code/game/objects/items/weapons/implants/implanter.dm
+++ b/code/game/objects/items/weapons/implants/implanter.dm
@@ -50,6 +50,10 @@
..()
update()
+/obj/item/weapon/implanter/spesstv
+ name = "promotional Spess.TV implanter"
+ desc = "Does anyone know where the implanter went? I have a lockbox full of loyalty implants here..."
+
/obj/item/weapon/implanter/traitor
name = "greytide conversion kit"
desc = "Any humanoid injected with this implant will become loyal to the injector and the greytide, unless of course the host is already loyal to someone else."
diff --git a/code/game/objects/items/weapons/storage/lockbox.dm b/code/game/objects/items/weapons/storage/lockbox.dm
index 18a5a077a72..5ce409d8c15 100644
--- a/code/game/objects/items/weapons/storage/lockbox.dm
+++ b/code/game/objects/items/weapons/storage/lockbox.dm
@@ -463,3 +463,26 @@
.=..()
if (.)
playsound(loc, 'sound/machines/click.ogg', 30, -5)
+
+/obj/item/weapon/storage/lockbox/security_sponsored
+ name = "sponsored Team Security lockbox"
+ desc = "A sponsor-sticker-plastered lockbox."
+ req_one_access = list(access_brig)
+ storage_slots = 6
+
+/obj/item/weapon/storage/lockbox/security_sponsored/New()
+ ..()
+ for(var/i in 1 to 4)
+ new /obj/item/weapon/reagent_containers/food/snacks/donitos/coolranch(src)
+ new /obj/item/weapon/implanter/spesstv(src)
+
+/obj/item/weapon/storage/lockbox/team_security_cameras
+ name = "sponsored Team Security cameras lockbox"
+ desc = "A sponsor-sticker-plastered lockbox."
+ req_one_access = list(access_brig)
+ storage_slots = 6
+
+/obj/item/weapon/storage/lockbox/team_security_cameras/New()
+ ..()
+ for(var/i in 1 to 6)
+ new /obj/item/clothing/accessory/spesstv_tactical_camera(src)
diff --git a/code/modules/clothing/accessories/spesstv.dm b/code/modules/clothing/accessories/spesstv.dm
new file mode 100644
index 00000000000..46f6bdf391b
--- /dev/null
+++ b/code/modules/clothing/accessories/spesstv.dm
@@ -0,0 +1,46 @@
+/obj/item/clothing/accessory/spesstv_tactical_camera
+ name = "\improper Spess.TV tactical camera"
+ desc = "A compact, tactical camera with built-in Spess.TV integration. Fits on uniform, armor and headgear. It features a Team Security logo."
+ icon_state = "small_camera" // Credits to https://github.com/discordia-space/CEV-Eris
+ accessory_exclusion = ACCESSORY_LIGHT
+ var/obj/machinery/camera/arena/spesstv/internal_camera
+
+/obj/item/clothing/accessory/spesstv_tactical_camera/New()
+ ..()
+ internal_camera = new(src)
+ new /datum/action/item_action/toggle_streaming(src)
+
+/obj/item/clothing/accessory/spesstv_tactical_camera/can_attach_to(obj/item/clothing/C)
+ var/static/list/allowed_clothing = list(/obj/item/clothing/under, /obj/item/clothing/head, /obj/item/clothing/suit/armor)
+ return is_type_in_list(C, allowed_clothing)
+
+/obj/item/clothing/accessory/spesstv_tactical_camera/attack_self(mob/user)
+ ..()
+ if(user.incapacitated())
+ return
+ if(!internal_camera.streamer)
+ if(user.mind.GetRole(STREAMER))
+ to_chat(user, "A camera is already linked to your Spess.TV account!")
+ return
+ var/datum/role/streamer/new_streamer_role = new /datum/role/streamer
+ if(!new_streamer_role.AssignToRole(user.mind, 1))
+ new_streamer_role.Drop()
+ to_chat(user, "Something went wrong during your registration to Spess.TV. Please try again.")
+ return
+ new_streamer_role.team = ESPORTS_SECURITY
+ new_streamer_role.camera = internal_camera
+ new_streamer_role.set_camera(internal_camera)
+ new_streamer_role.OnPostSetup()
+ new_streamer_role.Greet(GREET_DEFAULT)
+ new_streamer_role.AnnounceObjectives()
+ if(internal_camera.streamer.antag != user.mind)
+ to_chat(user, "You are not the registered user of this camera.")
+ return
+ internal_camera.streamer.toggle_streaming()
+
+/datum/action/item_action/toggle_streaming
+ name = "Toggle streaming"
+
+/datum/action/item_action/toggle_streaming/Trigger()
+ var/obj/item/target_item = target
+ target_item.attack_self(owner)
diff --git a/code/modules/clothing/clothing.dm b/code/modules/clothing/clothing.dm
index f07c3e85ff3..cdf9fcb7947 100644
--- a/code/modules/clothing/clothing.dm
+++ b/code/modules/clothing/clothing.dm
@@ -591,6 +591,20 @@
*/
var/displays_id = 1
clothing_flags = CANEXTINGUISH
+ var/icon/jersey_overlays
+
+// Associative list of exact type -> number
+var/list/jersey_numbers = list()
+
+/obj/item/clothing/under/New()
+ ..()
+ if(jersey_overlays)
+ var/number = jersey_numbers[type]++ % 99
+ var/first_digit = num2text(round((number / 10) % 10))
+ var/second_digit = num2text(round(number % 10))
+ var/image/jersey_overlay = image(jersey_overlays, src, "[first_digit]-")
+ jersey_overlay.overlays += image(jersey_overlays, src, second_digit)
+ dynamic_overlay["[UNIFORM_LAYER]"] = jersey_overlay
/obj/item/clothing/under/examine(mob/user)
..()
diff --git a/code/modules/clothing/head/misc.dm b/code/modules/clothing/head/misc.dm
index 1ee2a5123dc..6c735d83dbc 100644
--- a/code/modules/clothing/head/misc.dm
+++ b/code/modules/clothing/head/misc.dm
@@ -569,3 +569,7 @@
icon_state = "sombrero"
item_state = "sombrero"
+/obj/item/clothing/head/donitos_pope
+ name = "\improper Donitos Pope hat"
+ desc = "An oversized Donitos promotional plastic donut-shaped hat."
+ icon_state = "donitos_pope"
diff --git a/code/modules/clothing/under/miscellaneous.dm b/code/modules/clothing/under/miscellaneous.dm
index 065fb458740..d003ba2f81a 100644
--- a/code/modules/clothing/under/miscellaneous.dm
+++ b/code/modules/clothing/under/miscellaneous.dm
@@ -809,3 +809,42 @@
item_state = "clownpsyche"
_color = "clownpsyche"
clothing_flags = ONESIZEFITSALL
+
+/obj/item/clothing/under/team_security
+ name = "light Team Security suit"
+ desc = "A snappy white and red suit worn by Team Security members and fans."
+ icon_state = "teamsec_light"
+ _color = "teamsec_light"
+ jersey_overlays = 'icons/mob/uniform_overlays.dmi'
+ clothing_flags = ONESIZEFITSALL
+
+/obj/item/clothing/under/team_security/dark
+ name = "dark Team Security suit"
+ desc = "A snappy black and red suit worn by Team Security members and fans."
+ icon_state = "teamsec_dark"
+ _color = "teamsec_dark"
+ clothing_flags = ONESIZEFITSALL
+
+/obj/item/clothing/under/spesstv
+ name = "promotional Spess.TV suit"
+ desc = "A cheap green and white suit worn by Spess.TV members and fans."
+ icon_state = "spesstv"
+ _color = "spesstv"
+ jersey_overlays = 'icons/mob/uniform_overlays.dmi'
+ clothing_flags = ONESIZEFITSALL
+
+/obj/item/clothing/under/team_geometer
+ name = "\improper Team Geometer suit"
+ desc = "A smelly green and black suit worn by team Geometer members and fans."
+ icon_state = "teamgeometer"
+ _color = "teamgeometer"
+ jersey_overlays = 'icons/mob/uniform_overlays.dmi'
+ clothing_flags = ONESIZEFITSALL
+
+/obj/item/clothing/under/team_nt
+ name = "\improper NanoTrasen sports suit"
+ desc = "A dusty blue and white suit worn by NanoTrasen referees."
+ icon_state = "teamnt"
+ _color = "teamnt"
+ jersey_overlays = 'icons/mob/uniform_overlays.dmi'
+ clothing_flags = ONESIZEFITSALL
diff --git a/code/modules/projectiles/guns/energy/stun.dm b/code/modules/projectiles/guns/energy/stun.dm
index f23b584aa6d..2a9280d50fd 100644
--- a/code/modules/projectiles/guns/energy/stun.dm
+++ b/code/modules/projectiles/guns/energy/stun.dm
@@ -56,6 +56,11 @@
else
charge_tick = 0
+/obj/item/weapon/gun/energy/taser/team_security
+ name = "\improper Team Security sniper taser gun"
+ icon_state = "taser"
+ charge_cost = 500
+ fire_sound = 'sound/effects/intervention.ogg'
/obj/item/weapon/gun/energy/stunrevolver
name = "stun revolver"
diff --git a/code/modules/projectiles/projectile.dm b/code/modules/projectiles/projectile.dm
index b776b53ac5a..5dddf0f16f8 100644
--- a/code/modules/projectiles/projectile.dm
+++ b/code/modules/projectiles/projectile.dm
@@ -241,6 +241,7 @@ var/list/impact_master = list()
visible_message("[A.name] is hit by the [src.name] in the [parse_zone(def_zone)]!")//X has fired Y is now given by the guns so you cant tell who shot you if you could not see the shooter
admin_warn(M)
if(istype(firer, /mob))
+ M.do_hitmarker(firer)
if(!iscarbon(firer))
M.LAssailant = null
else
diff --git a/code/modules/reagents/Chemistry-Reagents.dm b/code/modules/reagents/Chemistry-Reagents.dm
index e29fe6ca0e8..d21d5ef36ff 100644
--- a/code/modules/reagents/Chemistry-Reagents.dm
+++ b/code/modules/reagents/Chemistry-Reagents.dm
@@ -5190,6 +5190,13 @@
M.dizziness += 5
M.drowsyness = 0
+/datum/reagent/drink/cold/geometer
+ name = "Geometer"
+ id = GEOMETER
+ description = "Summon the Beast."
+ color = "#ffd700"
+ adj_sleepy = -2
+
/datum/reagent/drink/cold/spacemountainwind
name = "Space Mountain Wind"
id = SPACEMOUNTAINWIND
diff --git a/code/modules/reagents/reagent_containers/food/drinks.dm b/code/modules/reagents/reagent_containers/food/drinks.dm
index a76482482e5..2595e3a2cce 100644
--- a/code/modules/reagents/reagent_containers/food/drinks.dm
+++ b/code/modules/reagents/reagent_containers/food/drinks.dm
@@ -848,6 +848,19 @@
reagents.add_reagent(BEER, 25)
reagents.add_reagent(POTATO, 25)
+/obj/item/weapon/reagent_containers/food/drinks/soda_cans/geometer
+ name = "Geometer"
+ desc = "Summon the Beast."
+ icon_state = "geometer"
+/obj/item/weapon/reagent_containers/food/drinks/soda_cans/geometer/New()
+ ..()
+ reagents.add_reagent(GEOMETER, 50)
+
+/obj/item/weapon/reagent_containers/food/drinks/soda_cans/geometer/blanco
+ name = "Geometer Blanco"
+ desc = "'member when we had to research words..."
+ icon_state = "geometer_blanco"
+
/obj/item/weapon/reagent_containers/food/drinks/soda_cans/greyshitvodka
name = "Greyshit Vodka"
desc = "Experts spent a long time squatting around a mixing bench to bring you this."
diff --git a/code/modules/reagents/reagent_containers/food/snacks.dm b/code/modules/reagents/reagent_containers/food/snacks.dm
index 0027f8dc331..3a3dd4f8af6 100644
--- a/code/modules/reagents/reagent_containers/food/snacks.dm
+++ b/code/modules/reagents/reagent_containers/food/snacks.dm
@@ -1525,6 +1525,27 @@
bitesize = 2
+/obj/item/weapon/reagent_containers/food/snacks/donitos
+ name = "Donitos"
+ desc = "Ranch or cool ranch?"
+ icon_state = "donitos"
+ trash = /obj/item/trash/donitos
+
+/obj/item/weapon/reagent_containers/food/snacks/donitos/New()
+ ..()
+ reagents.add_reagent(NUTRIMENT, 1)
+ reagents.add_reagent(SPRINKLES, 10)
+
+/obj/item/weapon/reagent_containers/food/snacks/donitos/coolranch
+ name = "Donitos Cool Ranch"
+ desc = "Cool ranch."
+ icon_state = "donitos_coolranch"
+ trash = /obj/item/trash/donitos_coolranch
+
+/obj/item/weapon/reagent_containers/food/snacks/donitos/coolranch/New()
+ ..()
+ reagents.add_reagent(SPRINKLES, 5)
+
/obj/item/weapon/reagent_containers/food/snacks/danitos
name = "Danitos"
desc = "For only the most MLG hardcore robust spessmen."
@@ -6206,4 +6227,4 @@ obj/item/weapon/reagent_containers/food/snacks/butterfingers_l
bitesize = 1
/obj/item/weapon/reagent_containers/food/snacks/breadslice/paibread/attackby(obj/item/I,mob/user,params)
- return ..() //sorry no custom pai sandwiches
\ No newline at end of file
+ return ..() //sorry no custom pai sandwiches
diff --git a/code/modules/research/mechanic/flatpack.dm b/code/modules/research/mechanic/flatpack.dm
index 5096616530a..b29d0243f3b 100644
--- a/code/modules/research/mechanic/flatpack.dm
+++ b/code/modules/research/mechanic/flatpack.dm
@@ -191,6 +191,12 @@
update_icon()
+/obj/structure/closet/crate/flatpack/proc/insert_machine(atom/movable/thing)
+ thing.forceMove(src)
+ name += " ([thing.name])"
+ machine = thing
+ update_icon()
+
/*
#define Fl_ACTION "action"
@@ -294,3 +300,4 @@
/obj/structure/closet/crate/flatpack/starscreen_capacitor/New()
..()
machine = new /obj/machinery/shield_capacitor(src)
+
diff --git a/code/modules/research/mechanic/flatpacker.dm b/code/modules/research/mechanic/flatpacker.dm
index 42cd6ce48af..3e8354907f4 100644
--- a/code/modules/research/mechanic/flatpacker.dm
+++ b/code/modules/research/mechanic/flatpacker.dm
@@ -64,10 +64,7 @@
src.overlays -= image(icon = icon, icon_state = "[base_state]_ani")
if(being_built)
var/obj/structure/closet/crate/flatpack/FP = new
- being_built.forceMove(FP)
- FP.name += " ([being_built.name])"
- FP.machine = being_built
- FP.update_icon()
+ FP.insert(being_built)
var/turf/output = get_output()
FP.forceMove(get_turf(output))
src.visible_message("[bicon(src)] \The [src] beeps: \"Successfully completed \the [being_built.name].\"")
diff --git a/icons/effects/effects.dmi b/icons/effects/effects.dmi
index 5ae0a216ea4..1212d28359d 100644
Binary files a/icons/effects/effects.dmi and b/icons/effects/effects.dmi differ
diff --git a/icons/logos.dmi b/icons/logos.dmi
index 8a763d824eb..3f93c214d72 100644
Binary files a/icons/logos.dmi and b/icons/logos.dmi differ
diff --git a/icons/mob/head.dmi b/icons/mob/head.dmi
index 1aa436aaf22..735edd523bd 100644
Binary files a/icons/mob/head.dmi and b/icons/mob/head.dmi differ
diff --git a/icons/mob/in-hand/left/clothing.dmi b/icons/mob/in-hand/left/clothing.dmi
index c3b83e88a38..da315b7fff9 100644
Binary files a/icons/mob/in-hand/left/clothing.dmi and b/icons/mob/in-hand/left/clothing.dmi differ
diff --git a/icons/mob/in-hand/right/clothing.dmi b/icons/mob/in-hand/right/clothing.dmi
index 59f09990eef..41b2ced01b4 100644
Binary files a/icons/mob/in-hand/right/clothing.dmi and b/icons/mob/in-hand/right/clothing.dmi differ
diff --git a/icons/mob/uniform.dmi b/icons/mob/uniform.dmi
index 0f97e8efbdf..59eda7123c8 100644
Binary files a/icons/mob/uniform.dmi and b/icons/mob/uniform.dmi differ
diff --git a/icons/mob/uniform_fat.dmi b/icons/mob/uniform_fat.dmi
index 57150ed758f..1c2d2203c29 100644
Binary files a/icons/mob/uniform_fat.dmi and b/icons/mob/uniform_fat.dmi differ
diff --git a/icons/mob/uniform_overlays.dmi b/icons/mob/uniform_overlays.dmi
new file mode 100644
index 00000000000..45b7b701ab6
Binary files /dev/null and b/icons/mob/uniform_overlays.dmi differ
diff --git a/icons/obj/camera_buttons.dmi b/icons/obj/camera_buttons.dmi
index 1b015e16570..1a189c38ea7 100644
Binary files a/icons/obj/camera_buttons.dmi and b/icons/obj/camera_buttons.dmi differ
diff --git a/icons/obj/clothing/accessories.dmi b/icons/obj/clothing/accessories.dmi
index 932e30f81ff..5478c25d4d9 100644
Binary files a/icons/obj/clothing/accessories.dmi and b/icons/obj/clothing/accessories.dmi differ
diff --git a/icons/obj/clothing/hats.dmi b/icons/obj/clothing/hats.dmi
index 313b65ca628..4b633a6b5e8 100644
Binary files a/icons/obj/clothing/hats.dmi and b/icons/obj/clothing/hats.dmi differ
diff --git a/icons/obj/clothing/uniforms.dmi b/icons/obj/clothing/uniforms.dmi
index 311322a3656..8c7950cec97 100644
Binary files a/icons/obj/clothing/uniforms.dmi and b/icons/obj/clothing/uniforms.dmi differ
diff --git a/icons/obj/device.dmi b/icons/obj/device.dmi
index 86e91223414..cda23ec89a2 100644
Binary files a/icons/obj/device.dmi and b/icons/obj/device.dmi differ
diff --git a/icons/obj/drinks.dmi b/icons/obj/drinks.dmi
index 8588d28f67f..ddcc036ac95 100644
Binary files a/icons/obj/drinks.dmi and b/icons/obj/drinks.dmi differ
diff --git a/icons/obj/food.dmi b/icons/obj/food.dmi
index e33d7a232a5..370602b84f2 100644
Binary files a/icons/obj/food.dmi and b/icons/obj/food.dmi differ
diff --git a/icons/obj/spesstv.dmi b/icons/obj/spesstv.dmi
new file mode 100644
index 00000000000..20c3108b9ca
Binary files /dev/null and b/icons/obj/spesstv.dmi differ
diff --git a/icons/obj/status_display.dmi b/icons/obj/status_display.dmi
index a792be62513..ffeb6c99966 100644
Binary files a/icons/obj/status_display.dmi and b/icons/obj/status_display.dmi differ
diff --git a/icons/obj/trash.dmi b/icons/obj/trash.dmi
index 3b09930b2ed..0c1809b5c0c 100644
Binary files a/icons/obj/trash.dmi and b/icons/obj/trash.dmi differ
diff --git a/icons/obj/vending.dmi b/icons/obj/vending.dmi
index 5f00f73556a..fef5d9761da 100755
Binary files a/icons/obj/vending.dmi and b/icons/obj/vending.dmi differ
diff --git a/icons/obj/vending_pack.dmi b/icons/obj/vending_pack.dmi
index a1be7b1a0ed..d9d3d7306d2 100644
Binary files a/icons/obj/vending_pack.dmi and b/icons/obj/vending_pack.dmi differ
diff --git a/sound/effects/hitmarker.ogg b/sound/effects/hitmarker.ogg
new file mode 100644
index 00000000000..69a6d632ea2
Binary files /dev/null and b/sound/effects/hitmarker.ogg differ
diff --git a/sound/effects/intervention.ogg b/sound/effects/intervention.ogg
new file mode 100644
index 00000000000..4c0cb772672
Binary files /dev/null and b/sound/effects/intervention.ogg differ
diff --git a/sound/effects/noisemaker1.ogg b/sound/effects/noisemaker1.ogg
new file mode 100644
index 00000000000..1126356760b
Binary files /dev/null and b/sound/effects/noisemaker1.ogg differ
diff --git a/sound/effects/noisemaker2.ogg b/sound/effects/noisemaker2.ogg
new file mode 100644
index 00000000000..cd975e3344a
Binary files /dev/null and b/sound/effects/noisemaker2.ogg differ
diff --git a/sound/effects/noisemaker3.ogg b/sound/effects/noisemaker3.ogg
new file mode 100644
index 00000000000..46392769f10
Binary files /dev/null and b/sound/effects/noisemaker3.ogg differ
diff --git a/vgstation13.dme b/vgstation13.dme
index 59ca25d48ee..9951a3cfebe 100644
--- a/vgstation13.dme
+++ b/vgstation13.dme
@@ -390,6 +390,7 @@
#include "code\datums\gamemode\objectives\ramble.dm"
#include "code\datums\gamemode\objectives\sample.dm"
#include "code\datums\gamemode\objectives\silence.dm"
+#include "code\datums\gamemode\objectives\spesstv.dm"
#include "code\datums\gamemode\objectives\spray_blood.dm"
#include "code\datums\gamemode\objectives\steal_priority_items.dm"
#include "code\datums\gamemode\objectives\summon_narsie.dm"
@@ -433,6 +434,7 @@
#include "code\datums\gamemode\role\rambler.dm"
#include "code\datums\gamemode\role\rev.dm"
#include "code\datums\gamemode\role\role.dm"
+#include "code\datums\gamemode\role\streamer.dm"
#include "code\datums\gamemode\role\summonsurvivors.dm"
#include "code\datums\gamemode\role\syndicate.dm"
#include "code\datums\gamemode\role\vampire_role.dm"
@@ -1328,6 +1330,7 @@
#include "code\modules\clothing\accessories\armor_shards.dm"
#include "code\modules\clothing\accessories\holomap.dm"
#include "code\modules\clothing\accessories\holster.dm"
+#include "code\modules\clothing\accessories\spesstv.dm"
#include "code\modules\clothing\accessories\storage.dm"
#include "code\modules\clothing\accessories\tactical_light.dm"
#include "code\modules\clothing\back\cape.dm"