Keep a sharp on any crew that appear to be oddly-dressed or using what appear to be magical powers, as these crew may be defectors \
- working for this entity and utilizing highly-advanced technology to cross the great distance at will. If they should turn out to be a credible threat, the task falls on you and \
- your crew to dispatch it in a timely manner."
-
-/datum/game_mode/proc/update_servant_icons_added(datum/mind/M)
- var/datum/atom_hud/antag/A = GLOB.huds[ANTAG_HUD_CLOCKWORK]
- A.join_hud(M.current)
- set_antag_hud(M.current, "clockwork")
-
-/datum/game_mode/proc/update_servant_icons_removed(datum/mind/M)
- var/datum/atom_hud/antag/A = GLOB.huds[ANTAG_HUD_CLOCKWORK]
- A.leave_hud(M.current)
- set_antag_hud(M.current, null)
-
-
-
-//Servant of Ratvar outfit
-/datum/outfit/servant_of_ratvar
- name = "Servant of Ratvar"
- uniform = /obj/item/clothing/under/chameleon/ratvar
- shoes = /obj/item/clothing/shoes/sneakers/black
- back = /obj/item/storage/backpack
- ears = /obj/item/radio/headset
- gloves = /obj/item/clothing/gloves/color/yellow
- belt = /obj/item/storage/belt/utility/servant
- backpack_contents = list(/obj/item/storage/box/engineer = 1, \
- /obj/item/clockwork/replica_fabricator = 1, /obj/item/stack/tile/brass/fifty = 1, /obj/item/paper/servant_primer = 1)
- id = /obj/item/pda
- var/plasmaman //We use this to determine if we should activate internals in post_equip()
-
-/datum/outfit/servant_of_ratvar/pre_equip(mob/living/carbon/human/H, visualsOnly = FALSE)
- if(H.dna.species.id == "plasmaman") //Plasmamen get additional equipment because of how they work
- head = /obj/item/clothing/head/helmet/space/plasmaman
- uniform = /obj/item/clothing/under/plasmaman //Plasmamen generally shouldn't need chameleon suits anyways, since everyone expects them to wear their fire suit
- r_hand = /obj/item/tank/internals/plasmaman/belt/full
- mask = /obj/item/clothing/mask/breath
- plasmaman = TRUE
-
-/datum/outfit/servant_of_ratvar/post_equip(mob/living/carbon/human/H, visualsOnly = FALSE)
- var/obj/item/card/id/W = new(H)
- var/obj/item/pda/PDA = H.wear_id
- W.assignment = "Assistant"
- W.access += ACCESS_MAINT_TUNNELS
- W.registered_name = H.real_name
- W.update_label()
- if(plasmaman && !visualsOnly) //If we need to breathe from the plasma tank, we should probably start doing that
- H.internal = H.get_item_for_held_index(2)
- H.update_internals_hud_icon(1)
- PDA.owner = H.real_name
- PDA.ownjob = "Assistant"
- PDA.update_label()
- PDA.id_check(H, W)
- H.sec_hud_set_ID()
-
-
-//This paper serves as a quick run-down to the cult as well as a changelog to refer to.
-//Check strings/clockwork_cult_changelog.txt for the changelog, and update it when you can!
-/obj/item/paper/servant_primer
- name = "The Ark And You: A Primer On Servitude"
- color = "#DAAA18"
- info = "DON'T PANIC.
\
- Here's a quick primer on what you should know here.\
-
\
-
You're in a place called Reebe right now. The crew can't get here normally.
\
-
In the north is your base camp, with supplies, consoles, and the Ark. In the south is an inaccessible area that the crew can walk between \
- once they arrive (more on that later.) Everything between that space is an open area.
\
-
Your job as a servant is to build fortifications and defenses to protect the Ark and your base once the Ark activates. You can do this \
- however you like, but work with your allies and coordinate your efforts.
\
-
Once the Ark activates, the station will be alerted. Portals to Reebe will open up in nearly every room. When they take these portals, \
- the crewmembers will arrive in the area that you can't access, but can get through it freely - whereas you can't. Treat this as the \"spawn\" of the \
- crew and defend it accordingly.
\
- \
- \
- Here is the layout of Reebe, from left to right:\
-
\
-
Dressing Room: Contains clothing, a dresser, and a mirror. There are spare slabs and absconders here.
\
-
Listening Station: Contains intercoms, a telecomms relay, and a list of frequencies.
\
-
Ark Chamber: Houses the Ark.
\
-
Observation Room: Contains five camera observers. These can be used to watch the station through its cameras, as well as to teleport down \
- to most areas. To do this, use the Warp action while hovering over the tile you want to warp to.
\
-
Infirmary: Contains sleepers and basic medical supplies for superficial wounds. The sleepers can consume Vitality to heal any occupants. \
- This room is generally more useful during the preparation phase; when defending the Ark, scripture is more useful.
"
- info = replacetext(info, "CLOCKCULTCHANGELOG", changelog_contents)
-
-/obj/item/paper/servant_primer/examine(mob/user)
- . = ..()
- if(!is_servant_of_ratvar(user) && !isobserver(user))
- . += "You can't understand any of the words on [src]."
diff --git a/code/game/gamemodes/cult/cult.dm b/code/game/gamemodes/cult/cult.dm
index 202bc0faafe..069e048b894 100644
--- a/code/game/gamemodes/cult/cult.dm
+++ b/code/game/gamemodes/cult/cult.dm
@@ -26,8 +26,8 @@
return FALSE
else
return FALSE
- if(HAS_TRAIT(M, TRAIT_MINDSHIELD) || issilicon(M) || isbot(M) || isdrone(M) || is_servant_of_ratvar(M) || !M.client)
- return FALSE //can't convert machines, shielded, braindead, or ratvar's dogs
+ if(HAS_TRAIT(M, TRAIT_MINDSHIELD) || issilicon(M) || isbot(M) || isdrone(M) || !M.client)
+ return FALSE //can't convert machines, shielded, or braindead
return TRUE
/datum/game_mode/cult
diff --git a/code/game/gamemodes/dynamic/dynamic_rulesets_roundstart.dm b/code/game/gamemodes/dynamic/dynamic_rulesets_roundstart.dm
index 532100547f9..a4b3a87d88d 100644
--- a/code/game/gamemodes/dynamic/dynamic_rulesets_roundstart.dm
+++ b/code/game/gamemodes/dynamic/dynamic_rulesets_roundstart.dm
@@ -124,7 +124,7 @@
/datum/dynamic_ruleset/roundstart/changeling/execute()
var/team_mode = FALSE
- if(prob(team_mode_probability))
+ if(prob(team_mode_probability))
team_mode = TRUE
var/list/team_objectives = subtypesof(/datum/objective/changeling_team_objective)
var/list/possible_team_objectives = list()
@@ -172,7 +172,7 @@
/datum/dynamic_ruleset/roundstart/wizard/pre_execute()
if(GLOB.wizardstart.len == 0)
return FALSE
-
+
var/mob/M = pick_n_take(candidates)
if (M)
assigned += M.mind
@@ -186,7 +186,7 @@
M.current.forceMove(pick(GLOB.wizardstart))
M.add_antag_datum(new antag_datum())
return TRUE
-
+
//////////////////////////////////////////////
// //
// BLOOD CULT //
@@ -232,7 +232,7 @@
var/datum/antagonist/cult/new_cultist = new antag_datum()
new_cultist.cult_team = main_cult
new_cultist.give_equipment = TRUE
- M.add_antag_datum(new_cultist)
+ M.add_antag_datum(new_cultist)
GLOB.pre_setup_antags -= M
main_cult.setup_objectives()
return TRUE
@@ -384,7 +384,7 @@
revolution.update_heads()
SSshuttle.registerHostileEnvironment(src)
return TRUE
-
+
/datum/dynamic_ruleset/roundstart/revs/rule_process()
if(check_rev_victory())
finished = 1
@@ -449,110 +449,6 @@
mode.spend_threat(mode.threat)
return TRUE
-//////////////////////////////////////////////
-// //
-// CLOCKCULT //
-// //
-//////////////////////////////////////////////
-
-/datum/dynamic_ruleset/roundstart/clockcult
- name = "Clockcult"
- antag_flag = ROLE_SERVANT_OF_RATVAR
- antag_datum = /datum/antagonist/clockcult
- restricted_roles = list("AI", "Cyborg", "Security Officer", "Warden", "Detective", "Head of Security", "Captain", "Chaplain", "Head of Personnel")
- required_candidates = 4
- weight = 3
- cost = 0
- requirements = list(101,101,101,101,101,101,101,101,101,101)
- high_population_requirement = 101
- flags = HIGHLANDER_RULESET
- var/ark_time
-
-/datum/dynamic_ruleset/roundstart/clockcult/pre_execute()
- var/list/errorList = list()
- var/list/reebes = SSmapping.LoadGroup(errorList, "Reebe", "map_files/generic", "City_of_Cogs.dmm", default_traits = ZTRAITS_REEBE, silent = TRUE)
- if(errorList.len)
- message_admins("Reebe failed to load!")
- log_game("Reebe failed to load!")
- return FALSE
- for(var/datum/parsed_map/PM in reebes)
- PM.initTemplateBounds()
-
- var/starter_servants = 4
- var/number_players = mode.roundstart_pop_ready
- if(number_players > 30)
- number_players -= 30
- starter_servants += round(number_players / 10)
- starter_servants = min(starter_servants, 8)
- for (var/i in 1 to starter_servants)
- var/mob/servant = pick_n_take(candidates)
- assigned += servant.mind
- servant.mind.assigned_role = ROLE_SERVANT_OF_RATVAR
- servant.mind.special_role = ROLE_SERVANT_OF_RATVAR
- GLOB.pre_setup_antags += servant.mind
- ark_time = 30 + round((number_players / 5))
- ark_time = min(ark_time, 35)
- return TRUE
-
-/datum/dynamic_ruleset/roundstart/clockcult/execute()
- var/list/spread_out_spawns = GLOB.servant_spawns.Copy()
- for(var/datum/mind/servant in assigned)
- var/mob/S = servant.current
- if(!spread_out_spawns.len)
- spread_out_spawns = GLOB.servant_spawns.Copy()
- log_game("[key_name(servant)] was made an initial servant of Ratvar")
- var/turf/T = pick_n_take(spread_out_spawns)
- S.forceMove(T)
- greet_servant(S)
- equip_servant(S)
- add_servant_of_ratvar(S, TRUE)
- GLOB.pre_setup_antags -= S.mind
- var/obj/structure/destructible/clockwork/massive/celestial_gateway/G = GLOB.ark_of_the_clockwork_justiciar //that's a mouthful
- G.final_countdown(ark_time)
- return TRUE
-
-/datum/dynamic_ruleset/roundstart/clockcult/proc/greet_servant(mob/M) //Description of their role
- if(!M)
- return 0
- to_chat(M, "You are a servant of Ratvar, the Clockwork Justiciar!")
- to_chat(M, "You have approximately [ark_time] minutes until the Ark activates.")
- to_chat(M, "Unlock Script scripture by converting a new servant.")
- to_chat(M, "Application scripture will be unlocked halfway until the Ark's activation.")
- M.playsound_local(get_turf(M), 'sound/ambience/antag/clockcultalr.ogg', 100, FALSE, pressure_affected = FALSE)
- return 1
-
-/datum/dynamic_ruleset/roundstart/clockcult/proc/equip_servant(mob/living/M) //Grants a clockwork slab to the mob, with one of each component
- if(!M || !ishuman(M))
- return FALSE
- var/mob/living/carbon/human/L = M
- L.equipOutfit(/datum/outfit/servant_of_ratvar)
- var/obj/item/clockwork/slab/S = new
- var/slot = "At your feet"
- var/list/slots = list("In your left pocket" = SLOT_L_STORE, "In your right pocket" = SLOT_R_STORE, "In your backpack" = SLOT_IN_BACKPACK, "On your belt" = SLOT_BELT)
- if(ishuman(L))
- var/mob/living/carbon/human/H = L
- slot = H.equip_in_one_of_slots(S, slots)
- if(slot == "In your backpack")
- slot = "In your [H.back.name]"
- if(slot == "At your feet")
- if(!S.forceMove(get_turf(L)))
- qdel(S)
- if(S && !QDELETED(S))
- to_chat(L, "There is a paper in your backpack! It'll tell you if anything's changed, as well as what to expect.")
- to_chat(L, "[slot] is a clockwork slab, a multipurpose tool used to construct machines and invoke ancient words of power. If this is your first time \
- as a servant, you can find a concise tutorial in the Recollection category of its interface.")
- to_chat(L, "If you want more information, you can read the wiki page to learn more.")
- return TRUE
- return FALSE
-
-/datum/dynamic_ruleset/roundstart/clockcult/round_result()
- if(GLOB.clockwork_gateway_activated)
- SSticker.news_report = CLOCK_SUMMON
- SSticker.mode_result = "win - servants completed their objective (summon ratvar)"
- else
- SSticker.news_report = CULT_FAILURE
- SSticker.mode_result = "loss - servants failed their objective (summon ratvar)"
-
//////////////////////////////////////////////
// //
// CLOWN OPS //
@@ -596,7 +492,7 @@
high_population_requirement = 101
var/devil_limit = 4 // Hard limit on devils if scaling is turned off
-/datum/dynamic_ruleset/roundstart/devil/pre_execute()
+/datum/dynamic_ruleset/roundstart/devil/pre_execute()
var/tsc = CONFIG_GET(number/traitor_scaling_coeff)
var/num_devils = 1
diff --git a/code/game/gamemodes/traitor/traitor.dm b/code/game/gamemodes/traitor/traitor.dm
index 81813188f32..f0a2351aeac 100644
--- a/code/game/gamemodes/traitor/traitor.dm
+++ b/code/game/gamemodes/traitor/traitor.dm
@@ -65,7 +65,6 @@
else
for(var/antag in pre_traitors)
GLOB.pre_setup_antags += antag
- to_chat(world, "Added [antag] to pre-antag list")
return TRUE
diff --git a/code/game/machinery/computer/_computer.dm b/code/game/machinery/computer/_computer.dm
index 737fe9a1675..963e17d09c2 100644
--- a/code/game/machinery/computer/_computer.dm
+++ b/code/game/machinery/computer/_computer.dm
@@ -12,7 +12,6 @@
var/brightness_on = 1
var/icon_keyboard = "generic_key"
var/icon_screen = "generic"
- var/clockwork = FALSE
var/time_to_screwdrive = 20
var/authenticated = 0
@@ -33,22 +32,6 @@
return 0
return 1
-/obj/machinery/computer/ratvar_act()
- if(!clockwork)
- clockwork = TRUE
- icon_screen = "ratvar[rand(1, 4)]"
- icon_keyboard = "ratvar_key[rand(1, 6)]"
- icon_state = "ratvarcomputer[rand(1, 4)]"
- update_icon()
-
-/obj/machinery/computer/narsie_act()
- if(clockwork && clockwork != initial(clockwork)) //if it's clockwork but isn't normally clockwork
- clockwork = FALSE
- icon_screen = initial(icon_screen)
- icon_keyboard = initial(icon_keyboard)
- icon_state = initial(icon_state)
- update_icon()
-
/obj/machinery/computer/update_icon()
cut_overlays()
SSvis_overlays.remove_vis_overlay(src, managed_vis_overlays)
diff --git a/code/game/machinery/computer/arcade.dm b/code/game/machinery/computer/arcade.dm
index 9f0117502b3..fd157c3f559 100644
--- a/code/game/machinery/computer/arcade.dm
+++ b/code/game/machinery/computer/arcade.dm
@@ -53,7 +53,6 @@ GLOBAL_LIST_INIT(arcade_prize_pool, list(
icon_state = "arcade"
icon_keyboard = null
icon_screen = "invaders"
- clockwork = TRUE //it'd look weird
var/list/prize_override
light_color = LIGHT_COLOR_GREEN
diff --git a/code/game/machinery/computer/camera.dm b/code/game/machinery/computer/camera.dm
index 3affc53a9b0..0e8b79f6e23 100644
--- a/code/game/machinery/computer/camera.dm
+++ b/code/game/machinery/computer/camera.dm
@@ -162,7 +162,6 @@
icon_state = "television"
icon_keyboard = null
icon_screen = "detective_tv"
- clockwork = TRUE //it'd look weird
pass_flags = PASSTABLE
/obj/machinery/computer/security/mining
@@ -208,7 +207,6 @@
network = list("thunder")
density = FALSE
circuit = null
- clockwork = TRUE //it'd look very weird
light_power = 0
/obj/machinery/computer/security/telescreen/update_icon()
diff --git a/code/game/machinery/computer/camera_advanced.dm b/code/game/machinery/computer/camera_advanced.dm
index 45b9716ae78..c9e6050d5c4 100644
--- a/code/game/machinery/computer/camera_advanced.dm
+++ b/code/game/machinery/computer/camera_advanced.dm
@@ -26,8 +26,6 @@
z_lock |= SSmapping.levels_by_trait(ZTRAIT_MINING)
if(lock_override & CAMERA_LOCK_CENTCOM)
z_lock |= SSmapping.levels_by_trait(ZTRAIT_CENTCOM)
- if(lock_override & CAMERA_LOCK_REEBE)
- z_lock |= SSmapping.levels_by_trait(ZTRAIT_REEBE)
/obj/machinery/computer/camera_advanced/connect_to_shuttle(obj/docking_port/mobile/port, obj/docking_port/stationary/dock, idnum, override=FALSE)
for(var/i in networks)
@@ -281,108 +279,3 @@
else
playsound(origin, 'sound/machines/terminal_prompt_deny.ogg', 25, FALSE)
-
-//Used by servants of Ratvar! They let you beam to the station.
-/obj/machinery/computer/camera_advanced/ratvar
- name = "ratvarian camera observer"
- desc = "A console used to snoop on the station's goings-on. A jet of steam occasionally whooshes out from slats on its sides."
- use_power = FALSE
- networks = list("ss13", "minisat") //:eye:
- var/datum/action/innate/servant_warp/warp_action = new
-
-/obj/machinery/computer/camera_advanced/ratvar/Initialize()
- . = ..()
- ratvar_act()
-
-/obj/machinery/computer/camera_advanced/ratvar/process()
- if(prob(1))
- playsound(src, 'sound/machines/clockcult/steam_whoosh.ogg', 25, TRUE)
- new/obj/effect/temp_visual/steam_release(get_turf(src))
-
-/obj/machinery/computer/camera_advanced/ratvar/CreateEye()
- ..()
- eyeobj.visible_icon = TRUE
- eyeobj.icon = 'icons/mob/cameramob.dmi' //in case you still had any doubts
- eyeobj.icon_state = "generic_camera"
-
-/obj/machinery/computer/camera_advanced/ratvar/GrantActions(mob/living/carbon/user)
- ..()
- if(warp_action)
- warp_action.Grant(user)
- warp_action.target = src
- actions += warp_action
-
-/obj/machinery/computer/camera_advanced/ratvar/can_use(mob/living/user)
- if(!is_servant_of_ratvar(user))
- to_chat(user, "[src]'s keys are in a language foreign to you, and you don't understand anything on its screen.")
- return
- if(clockwork_ark_active())
- to_chat(user, "The Ark is active, and [src] has shut down.")
- return
- . = ..()
-
-/datum/action/innate/servant_warp
- name = "Warp"
- desc = "Warps to the tile you're viewing. You can use the Abscond scripture to return. Clicking this button again cancels the warp."
- icon_icon = 'icons/mob/actions/actions_clockcult.dmi'
- button_icon_state = "warp_down"
- background_icon_state = "bg_clock"
- buttontooltipstyle = "clockcult"
- var/cancel = FALSE //if TRUE, an active warp will be canceled
- var/obj/effect/temp_visual/ratvar/warp_marker/warping
-
-/datum/action/innate/servant_warp/Activate()
- if(QDELETED(target) || !(ishuman(owner) || iscyborg(owner)) || !owner.canUseTopic(target))
- return
- if(!GLOB.servants_active) //No leaving unless there's servants from the get-go
- return
- if(warping)
- cancel = TRUE
- return
- var/mob/living/carbon/human/user = owner
- var/mob/camera/aiEye/remote/remote_eye = user.remote_control
- var/obj/machinery/computer/camera_advanced/ratvar/R = target
- var/turf/T = get_turf(remote_eye)
- if(!is_reebe(user.z) || !is_station_level(T.z))
- return
- if(isclosedturf(T))
- to_chat(user, "You can't teleport into a wall.")
- return
- else if(isspaceturf(T))
- to_chat(user, "[prob(1) ? "Servant cannot into space." : "You can't teleport into space."]")
- return
- else if(T.flags_1 & NOJAUNT_1)
- to_chat(user, "This tile is blessed by holy water and deflects the warp.")
- return
- var/area/AR = get_area(T)
- if(!AR.clockwork_warp_allowed)
- to_chat(user, "[AR.clockwork_warp_fail]")
- return
- if(alert(user, "Are you sure you want to warp to [AR]?", target.name, "Warp", "Cancel") == "Cancel" || QDELETED(R) || !user.canUseTopic(R))
- return
- do_sparks(5, TRUE, user)
- do_sparks(5, TRUE, T)
- warping = new(T)
- user.visible_message("[user]'s [target.name] flares!", "You begin warping to [AR]...")
- button_icon_state = "warp_cancel"
- owner.update_action_buttons()
- if(!do_after(user, 50, target = warping, extra_checks = CALLBACK(src, .proc/is_canceled)))
- to_chat(user, "Warp interrupted.")
- QDEL_NULL(warping)
- button_icon_state = "warp_down"
- owner.update_action_buttons()
- cancel = FALSE
- return
- button_icon_state = "warp_down"
- owner.update_action_buttons()
- T.visible_message("[user] warps in!")
- playsound(user, 'sound/magic/magic_missile.ogg', 50, TRUE)
- playsound(T, 'sound/magic/magic_missile.ogg', 50, TRUE)
- user.forceMove(get_turf(T))
- user.setDir(SOUTH)
- flash_color(user, flash_color = "#AF0AAF", flash_time = 5)
- R.remove_eye_control(user)
- QDEL_NULL(warping)
-
-/datum/action/innate/servant_warp/proc/is_canceled()
- return !cancel
diff --git a/code/game/machinery/computer/medical.dm b/code/game/machinery/computer/medical.dm
index 016ad5414f6..14cb45430ce 100644
--- a/code/game/machinery/computer/medical.dm
+++ b/code/game/machinery/computer/medical.dm
@@ -576,5 +576,4 @@
icon_state = "laptop"
icon_screen = "medlaptop"
icon_keyboard = "laptop_key"
- clockwork = TRUE //it'd look weird
pass_flags = PASSTABLE
diff --git a/code/game/machinery/computer/robot.dm b/code/game/machinery/computer/robot.dm
index ba306b5492e..056b2a513de 100644
--- a/code/game/machinery/computer/robot.dm
+++ b/code/game/machinery/computer/robot.dm
@@ -68,9 +68,7 @@
dat += "Unit Controls: "
if(issilicon(user) && user != R)
var/mob/living/silicon/S = user
- if(is_servant_of_ratvar(S) && !is_servant_of_ratvar(R))
- dat += "(Convert) "
- else if(S.hack_software && !R.emagged)
+ if(S.hack_software && !R.emagged)
dat += "(Hack) "
else if(IsAdminGhost(user) && !R.emagged)
dat += "(Hack) "
@@ -155,14 +153,6 @@
message_admins("[ADMIN_LOOKUPFLW(usr)] emagged cyborg [key_name_admin(R)] using robotic console!")
R.SetEmagged(TRUE)
- else if(href_list["convert"])
- if(isAI(usr) && is_servant_of_ratvar(usr))
- var/mob/living/silicon/robot/R = locate(href_list["convert"]) in GLOB.silicon_mobs
- if(istype(R) && !is_servant_of_ratvar(R) && R.connected_ai == usr)
- log_game("[key_name(usr)] converted [key_name(R)] using robotic console!")
- message_admins("[ADMIN_LOOKUPFLW(usr)] converted cyborg [key_name_admin(R)] using robotic console!")
- add_servant_of_ratvar(R)
-
else if (href_list["killdrone"])
if(allowed(usr))
var/mob/living/simple_animal/drone/D = locate(href_list["killdrone"]) in GLOB.mob_list
diff --git a/code/game/machinery/computer/security.dm b/code/game/machinery/computer/security.dm
index 59ecc803950..10a9c4f051d 100644
--- a/code/game/machinery/computer/security.dm
+++ b/code/game/machinery/computer/security.dm
@@ -30,7 +30,6 @@
icon_state = "laptop"
icon_screen = "seclaptop"
icon_keyboard = "laptop_key"
- clockwork = TRUE //it'd look weird
pass_flags = PASSTABLE
//Someone needs to break down the dat += into chunks instead of long ass lines.
diff --git a/code/game/machinery/doors/airlock.dm b/code/game/machinery/doors/airlock.dm
index f34c0b17432..e3d9ab92b16 100644
--- a/code/game/machinery/doors/airlock.dm
+++ b/code/game/machinery/doors/airlock.dm
@@ -283,15 +283,6 @@
A = new /obj/machinery/door/airlock/cult/weak(T)
qdel(src)
-/obj/machinery/door/airlock/ratvar_act() //Airlocks become pinion airlocks that only allow servants
- var/obj/machinery/door/airlock/clockwork/A
- if(glass)
- A = new/obj/machinery/door/airlock/clockwork/brass(get_turf(src))
- else
- A = new/obj/machinery/door/airlock/clockwork(get_turf(src))
- A.name = name
- qdel(src)
-
/obj/machinery/door/airlock/Destroy()
QDEL_NULL(wires)
QDEL_NULL(electronics)
@@ -1374,7 +1365,7 @@
datum/tgui/master_ui = null, datum/ui_state/state = GLOB.default_state)
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
if(!ui)
- ui = new(user, src, ui_key, "ai_airlock", name, 550, 456, master_ui, state)
+ ui = new(user, src, ui_key, "ai_airlock", name, 500, 390, master_ui, state)
ui.open()
return TRUE
@@ -1443,85 +1434,41 @@
if("shock-perm")
shock_perm(usr)
. = TRUE
- if("idscan-on")
- if(wires.is_cut(WIRE_IDSCAN))
to_chat(usr, "You can't enable IdScan - The IdScan wire has been cut.")
- else if(aiDisabledIdScanner)
- aiDisabledIdScanner = FALSE
- else
- to_chat(usr, "The IdScan feature is not disabled.")
+ to_chat(usr, "The IdScan feature is not disabled.")
+ if("idscan-toggle")
+ aiDisabledIdScanner = !aiDisabledIdScanner
. = TRUE
- if("idscan-off")
- if(wires.is_cut(WIRE_IDSCAN))
- to_chat(usr, "The IdScan wire has been cut - so, you can't disable it, but it is already disabled anyways.")
- else if(aiDisabledIdScanner)
- to_chat(usr, "You've already disabled the IdScan feature.")
- else
- aiDisabledIdScanner = TRUE
+ to_chat(usr, "The IdScan wire has been cut - So, you can't disable it, but it is already disabled anyways.")
+ to_chat(usr, "You've already disabled the IdScan feature!")
+ if("emergency-toggle")
+ toggle_emergency(usr)
. = TRUE
- if("emergency-on")
- emergency_on(usr)
+ if("bolt-toggle")
+ toggle_bolt(usr)
. = TRUE
- if("emergency-off")
- emergency_off(usr)
+ if("light-toggle")
+ lights = !lights
+ update_icon()
. = TRUE
- if("bolt-raise")
- bolt_raise(usr)
+ if("safe-toggle")
+ safe = !safe
. = TRUE
- if("bolt-drop")
- bolt_drop(usr)
+ if("speed-toggle")
+ normalspeed = !normalspeed
. = TRUE
- if("light-on")
- if(wires.is_cut(WIRE_LIGHT))
- to_chat(usr, "Control to door bolt lights has been severed.")
- else if (!lights)
- lights = TRUE
- update_icon()
- else
+ to_chat(usr, "Control to door bolt lights has been severed!")
to_chat(usr, text("Door bolt lights are already enabled!"))
- . = TRUE
- if("light-off")
- if(wires.is_cut(WIRE_LIGHT))
- to_chat(usr, "Control to door bolt lights has been severed.")
- else if (lights)
- lights = FALSE
- update_icon()
- else
+ to_chat(usr, "Control to door bolt lights has been severed!")
to_chat(usr, "Door bolt lights are already disabled!")
- . = TRUE
- if("safe-on")
- if(wires.is_cut(WIRE_SAFETY))
- to_chat(usr, "Control to door sensors is disabled.")
- else if (!safe)
- safe = TRUE
- else
- to_chat(usr, "Firmware reports safeties already in place.")
- . = TRUE
- if("safe-off")
- if(wires.is_cut(WIRE_SAFETY))
- to_chat(usr, "Control to door sensors is disabled.")
- else if (safe)
- safe = FALSE
- else
- to_chat(usr, "Firmware reports safeties already overridden.")
- . = TRUE
- if("speed-on")
- if(wires.is_cut(WIRE_TIMING))
- to_chat(usr, "Control to door timing circuitry has been severed.")
- else if (!normalspeed)
- normalspeed = 1
- else
- to_chat(usr,"Door timing circuitry currently operating normally.")
- . = TRUE
- if("speed-off")
- if(wires.is_cut(WIRE_TIMING))
- to_chat(usr, "Control to door timing circuitry has been severed.")
- else if (normalspeed)
- normalspeed = 0
- else
- to_chat(usr, "Door timing circuitry already accelerated.")
-
- . = TRUE
+ to_chat(usr, "Control to door sensors is disabled!")
+ to_chat(usr, "Firmware reports safeties already in place!")
+ to_chat(usr, "Control to door sensors is disabled!")
+ to_chat(usr, "Firmware reports safeties already overridden!")
+ to_chat(usr, "Control to door timing circuitry has been severed!")
+ to_chat(usr,"Door timing circuitry currently operating normally.")
+ to_chat(usr, "Control to door timing circuitry has been severed!")
+ to_chat(usr, "Door timing circuitry already accelerated!")
if("open-close")
user_toggle_open(usr)
. = TRUE
@@ -1553,45 +1500,32 @@
else
set_electrified(MACHINE_ELECTRIFIED_PERMANENT, user)
-/obj/machinery/door/airlock/proc/emergency_on(mob/user)
+/obj/machinery/door/airlock/proc/toggle_bolt(mob/user)
if(!user_allowed(user))
return
- if (!emergency)
- emergency = TRUE
- update_icon()
- else
to_chat(user, "Emergency access is already enabled!")
-
-/obj/machinery/door/airlock/proc/emergency_off(mob/user)
- if(!user_allowed(user))
+ if(wires.is_cut(WIRE_BOLTS))
+ to_chat(user, "The door bolt drop wire is cut - you can't toggle the door bolts.")
return
- if (emergency)
- emergency = FALSE
- update_icon()
+ if(locked)
+ if(!hasPower())
+ to_chat(user, "The door has no power - you can't raise the door bolts.")
+ else
+ unbolt()
else
to_chat(user, "Emergency access is already disabled!")
-
-/obj/machinery/door/airlock/proc/bolt_raise(mob/user)
- if(!user_allowed(user))
- return
- if(wires.is_cut(WIRE_BOLTS))
- to_chat(user, "The door bolt drop wire is cut - you can't raise the door bolts.")
- else if(!locked)
- to_chat(user, "The door bolts are already up.")
- else
- if(hasPower())
- unbolt()
- else
- to_chat(user, "Cannot raise door bolts due to power failure.")
-
-/obj/machinery/door/airlock/proc/bolt_drop(mob/user)
- if(!user_allowed(user))
- return
- if(wires.is_cut(WIRE_BOLTS))
- to_chat(user, "You can't drop the door bolts - The door bolt dropping wire has been cut.")
- else
bolt()
+/obj/machinery/door/airlock/proc/toggle_emergency(mob/user)
+ if(!user_allowed(user))
+ return
+ to_chat(user, "The door bolt drop wire is cut - you can't raise the door bolts!")
+ to_chat(user, "The door bolts are already up!")
+ to_chat(user, "Cannot raise door bolts due to power failure!")
+ emergency = !emergency
+ update_icon()
+
+ to_chat(user, "You can't drop the door bolts - The door bolt dropping wire has been cut.")
/obj/machinery/door/airlock/proc/user_toggle_open(mob/user)
if(!user_allowed(user))
return
diff --git a/code/game/machinery/doors/airlock_electronics.dm b/code/game/machinery/doors/airlock_electronics.dm
index 48d826fac53..395d581527a 100644
--- a/code/game/machinery/doors/airlock_electronics.dm
+++ b/code/game/machinery/doors/airlock_electronics.dm
@@ -15,7 +15,7 @@
datum/tgui/master_ui = null, datum/ui_state/state = GLOB.hands_state)
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
if(!ui)
- ui = new(user, src, ui_key, "airlock_electronics", name, 975, 420, master_ui, state)
+ ui = new(user, src, ui_key, "airlock_electronics", name, 420, 485, master_ui, state)
ui.open()
/obj/item/electronics/airlock/ui_data()
@@ -44,10 +44,13 @@
if(..())
return
switch(action)
- if("clear")
+ if("clear_all")
accesses = list()
one_access = 0
. = TRUE
+ if("grant_all")
+ accesses = get_all_accesses()
+ . = TRUE
if("one_access")
one_access = !one_access
. = TRUE
diff --git a/code/game/machinery/doors/airlock_types.dm b/code/game/machinery/doors/airlock_types.dm
index 5c5fb1eeff5..5763bb2f07f 100644
--- a/code/game/machinery/doors/airlock_types.dm
+++ b/code/game/machinery/doors/airlock_types.dm
@@ -533,123 +533,6 @@
damage_deflection = 5
armor = list("melee" = 0, "bullet" = 0, "laser" = 0,"energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 0, "acid" = 0)
-//Pinion airlocks: Clockwork doors that only let servants of Ratvar through.
-/obj/machinery/door/airlock/clockwork
- name = "pinion airlock"
- desc = "A massive cogwheel set into two heavy slabs of brass."
- icon = 'icons/obj/doors/airlocks/clockwork/pinion_airlock.dmi'
- overlays_file = 'icons/obj/doors/airlocks/clockwork/overlays.dmi'
- hackProof = TRUE
- aiControlDisabled = 1
- req_access = list(ACCESS_CLOCKCULT)
- use_power = FALSE
- resistance_flags = FIRE_PROOF | ACID_PROOF
- damage_deflection = 30
- normal_integrity = 240
- var/construction_state = GEAR_SECURE //Pinion airlocks have custom deconstruction
-
-/obj/machinery/door/airlock/clockwork/Initialize()
- . = ..()
- new /obj/effect/temp_visual/ratvar/door(loc)
- new /obj/effect/temp_visual/ratvar/beam/door(loc)
- change_construction_value(5)
-
-/obj/machinery/door/airlock/clockwork/Destroy()
- change_construction_value(-5)
- return ..()
-
-/obj/machinery/door/airlock/clockwork/examine(mob/user)
- . = ..()
- var/gear_text = "The cogwheel is flickering and twisting wildly. Report this to a coder."
- switch(construction_state)
- if(GEAR_SECURE)
- gear_text = "The cogwheel is solidly wrenched to the brass around it."
- if(GEAR_LOOSE)
- gear_text = "The cogwheel has been loosened, but remains connected loosely to the door!"
- . += gear_text
-
-/obj/machinery/door/airlock/clockwork/emp_act(severity)
- if(prob(80/severity))
- open()
-
-/obj/machinery/door/airlock/clockwork/canAIControl(mob/user)
- return (is_servant_of_ratvar(user) && !isAllPowerCut())
-
-/obj/machinery/door/airlock/clockwork/ratvar_act()
- return 0
-
-/obj/machinery/door/airlock/clockwork/narsie_act()
- ..()
- if(src)
- var/previouscolor = color
- color = "#960000"
- animate(src, color = previouscolor, time = 8)
- addtimer(CALLBACK(src, /atom/proc/update_atom_colour), 8)
-
-/obj/machinery/door/airlock/clockwork/attackby(obj/item/I, mob/living/user, params)
- if(!attempt_construction(I, user))
- return ..()
-
-/obj/machinery/door/airlock/clockwork/allowed(mob/M)
- if(is_servant_of_ratvar(M))
- return 1
- return 0
-
-/obj/machinery/door/airlock/clockwork/hasPower()
- return TRUE //yes we do have power
-
-/obj/machinery/door/airlock/clockwork/obj_break(damage_flag)
- SHOULD_CALL_PARENT(FALSE)
- return
-
-/obj/machinery/door/airlock/clockwork/deconstruct(disassembled = TRUE)
- playsound(src, 'sound/items/deconstruct.ogg', 50, TRUE)
- if(!(flags_1 & NODECONSTRUCT_1))
- var/turf/T = get_turf(src)
- if(disassembled)
- new/obj/item/stack/tile/brass(T, 4)
- else
- new/obj/item/clockwork/alloy_shards(T)
- new/obj/item/clockwork/alloy_shards/pinion_lock(T)
- qdel(src)
-
-/obj/machinery/door/airlock/clockwork/proc/attempt_construction(obj/item/I, mob/living/user)
- if(!I || !user || !user.canUseTopic(src))
- return 0
- else if(I.tool_behaviour == TOOL_WRENCH)
- if(construction_state == GEAR_SECURE)
- user.visible_message("[user] begins loosening [src]'s cogwheel...", "You begin loosening [src]'s cogwheel...")
- if(!I.use_tool(src, user, 75, volume=50) || construction_state != GEAR_SECURE)
- return 1
- user.visible_message("[user] loosens [src]'s cogwheel!", "[src]'s cogwheel pops off and dangles loosely.")
- playsound(src, 'sound/items/deconstruct.ogg', 50, TRUE)
- construction_state = GEAR_LOOSE
- else if(construction_state == GEAR_LOOSE)
- user.visible_message("[user] begins tightening [src]'s cogwheel...", "You begin tightening [src]'s cogwheel into place...")
- if(!I.use_tool(src, user, 75, volume=50) || construction_state != GEAR_LOOSE)
- return 1
- user.visible_message("[user] tightens [src]'s cogwheel!", "You firmly tighten [src]'s cogwheel into place.")
- playsound(src, 'sound/items/deconstruct.ogg', 50, TRUE)
- construction_state = GEAR_SECURE
- return 1
- else if(I.tool_behaviour == TOOL_CROWBAR)
- if(construction_state == GEAR_SECURE)
- to_chat(user, "[src]'s cogwheel is too tightly secured! Your [I.name] can't reach under it!")
- return 1
- else if(construction_state == GEAR_LOOSE)
- user.visible_message("[user] begins slowly lifting off [src]'s cogwheel...", "You slowly begin lifting off [src]'s cogwheel...")
- if(!I.use_tool(src, user, 75, volume=50) || construction_state != GEAR_LOOSE)
- return 1
- user.visible_message("[user] lifts off [src]'s cogwheel, causing it to fall apart!", \
- "You lift off [src]'s cogwheel, causing it to fall apart!")
- deconstruct(TRUE)
- return 1
- return 0
-
-/obj/machinery/door/airlock/clockwork/brass
- glass = TRUE
- opacity = 0
-
//////////////////////////////////
/*
Misc Airlocks
diff --git a/code/game/machinery/doors/brigdoors.dm b/code/game/machinery/doors/brigdoors.dm
index b193017dc37..18384a611bf 100644
--- a/code/game/machinery/doors/brigdoors.dm
+++ b/code/game/machinery/doors/brigdoors.dm
@@ -38,7 +38,7 @@
maptext_width = 32
maptext_y = -1
ui_x = 300
- ui_y = 200
+ ui_y = 138
/obj/machinery/door_timer/Initialize()
. = ..()
diff --git a/code/game/machinery/doors/door.dm b/code/game/machinery/doors/door.dm
index 28084be33e6..40d09afcb96 100644
--- a/code/game/machinery/doors/door.dm
+++ b/code/game/machinery/doors/door.dm
@@ -283,6 +283,7 @@
set_opacity(0)
sleep(5)
density = FALSE
+ flags_1 &= ~PREVENT_CLICK_UNDER_1
sleep(5)
layer = initial(layer)
update_icon()
@@ -312,6 +313,7 @@
layer = closingLayer
sleep(5)
density = TRUE
+ flags_1 |= PREVENT_CLICK_UNDER_1
sleep(5)
update_icon()
if(visible && !glass)
diff --git a/code/game/machinery/doors/windowdoor.dm b/code/game/machinery/doors/windowdoor.dm
index a393f38bd28..1f638324599 100644
--- a/code/game/machinery/doors/windowdoor.dm
+++ b/code/game/machinery/doors/windowdoor.dm
@@ -197,11 +197,6 @@
/obj/machinery/door/window/narsie_act()
add_atom_colour("#7D1919", FIXED_COLOUR_PRIORITY)
-/obj/machinery/door/window/ratvar_act()
- var/obj/machinery/door/window/clockwork/C = new(loc, dir)
- C.name = name
- qdel(src)
-
/obj/machinery/door/window/temperature_expose(datum/gas_mixture/air, exposed_temperature, exposed_volume)
if(exposed_temperature > T0C + (reinf ? 1600 : 800))
take_damage(round(exposed_volume / 200), BURN, 0, 0)
@@ -356,57 +351,6 @@
name = "holding cell door"
req_one_access = list(ACCESS_SEC_DOORS, ACCESS_LAWYER) //love for the lawyer
-/obj/machinery/door/window/clockwork
- name = "brass windoor"
- desc = "A thin door with translucent brass paneling."
- icon_state = "clockwork"
- base_state = "clockwork"
- shards = 0
- rods = 0
- resistance_flags = FIRE_PROOF | ACID_PROOF
- var/made_glow = FALSE
-
-/obj/machinery/door/window/clockwork/Initialize(mapload, set_dir)
- . = ..()
- for(var/i in 1 to 2)
- debris += new/obj/item/clockwork/alloy_shards/medium/gear_bit/large(src)
- change_construction_value(2)
-
-/obj/machinery/door/window/clockwork/setDir(direct)
- if(!made_glow)
- var/obj/effect/E = new /obj/effect/temp_visual/ratvar/door/window(get_turf(src))
- E.setDir(direct)
- made_glow = TRUE
- ..()
-
-/obj/machinery/door/window/clockwork/Destroy()
- change_construction_value(-2)
- return ..()
-
-/obj/machinery/door/window/clockwork/emp_act(severity)
- if(prob(80/severity))
- open()
-
-/obj/machinery/door/window/clockwork/ratvar_act()
- if(GLOB.ratvar_awakens)
- obj_integrity = max_integrity
-
-/obj/machinery/door/window/clockwork/hasPower()
- return TRUE //yup that's power all right
-
-/obj/machinery/door/window/clockwork/narsie_act()
- take_damage(rand(30, 60), BRUTE)
- if(src)
- var/previouscolor = color
- color = "#960000"
- animate(src, color = previouscolor, time = 8)
- addtimer(CALLBACK(src, /atom/proc/update_atom_colour), 8)
-
-/obj/machinery/door/window/clockwork/allowed(mob/M)
- if(is_servant_of_ratvar(M))
- return 1
- return 0
-
/obj/machinery/door/window/northleft
dir = NORTH
diff --git a/code/game/machinery/telecomms/machines/relay.dm b/code/game/machinery/telecomms/machines/relay.dm
index 65f70a4f236..57565aacdef 100644
--- a/code/game/machinery/telecomms/machines/relay.dm
+++ b/code/game/machinery/telecomms/machines/relay.dm
@@ -72,14 +72,6 @@
toggled = FALSE
autolinkers = list("r_relay")
-/obj/machinery/telecomms/relay/preset/reebe
- name = "hierophant relay"
- desc = "An arcane telecommunications relay that ingeniously combines bluespace technology with the Hierophant network to send and receive messages to and from Reebe."
- id = "Hierophant Relay"
- icon = 'icons/obj/clockwork_objects.dmi'
- hide = TRUE
- autolinkers = list("h_relay")
-
//Generic preset relay
/obj/machinery/telecomms/relay/preset/auto
hide = TRUE
diff --git a/code/game/mecha/equipment/tools/other_tools.dm b/code/game/mecha/equipment/tools/other_tools.dm
index 12d62d54a78..9ad1e442a05 100644
--- a/code/game/mecha/equipment/tools/other_tools.dm
+++ b/code/game/mecha/equipment/tools/other_tools.dm
@@ -399,7 +399,7 @@
/obj/item/mecha_parts/mecha_equipment/generator/get_equip_info()
var/output = ..()
if(output)
- return "[output] \[[fuel]: [round(fuel.amount*fuel.perunit,0.1)] cm3\] - [equip_ready?"A":"Dea"]ctivate"
+ return "[output] \[[fuel]: [round(fuel.amount*fuel.mats_per_stack,0.1)] cm3\] - [equip_ready?"A":"Dea"]ctivate"
/obj/item/mecha_parts/mecha_equipment/generator/action(target)
if(chassis)
@@ -409,9 +409,9 @@
/obj/item/mecha_parts/mecha_equipment/generator/proc/load_fuel(var/obj/item/stack/sheet/P)
if(P.type == fuel.type && P.amount > 0)
- var/to_load = max(max_fuel - fuel.amount*fuel.perunit,0)
+ var/to_load = max(max_fuel - fuel.amount*fuel.mats_per_stack,0)
if(to_load)
- var/units = min(max(round(to_load / P.perunit),1),P.amount)
+ var/units = min(max(round(to_load / P.mats_per_stack),1),P.amount)
fuel.amount += units
P.use(units)
occupant_message("[units] unit\s of [fuel] successfully loaded.")
@@ -447,7 +447,7 @@
if(cur_charge < chassis.cell.maxcharge)
use_fuel = fuel_per_cycle_active
chassis.give_power(power_per_cycle)
- fuel.amount -= min(use_fuel/fuel.perunit,fuel.amount)
+ fuel.amount -= min(use_fuel/fuel.mats_per_stack,fuel.amount)
update_equip_info()
return 1
diff --git a/code/game/mecha/mecha_defense.dm b/code/game/mecha/mecha_defense.dm
index 12afc636758..334aaad8b63 100644
--- a/code/game/mecha/mecha_defense.dm
+++ b/code/game/mecha/mecha_defense.dm
@@ -337,16 +337,6 @@
/obj/mecha/narsie_act()
emp_act(EMP_HEAVY)
-/obj/mecha/ratvar_act()
- if((GLOB.ratvar_awakens || GLOB.clockwork_gateway_activated) && occupant)
- if(is_servant_of_ratvar(occupant)) //reward the minion that got a mech by repairing it
- full_repair(TRUE)
- else
- var/mob/living/L = occupant
- go_out(TRUE)
- if(L)
- L.ratvar_act()
-
/obj/mecha/do_attack_animation(atom/A, visual_effect_icon, obj/item/used_item, no_effect)
if(!no_effect)
if(selected)
diff --git a/code/game/objects/effects/countdown.dm b/code/game/objects/effects/countdown.dm
index 7426ba22a06..3937aa51535 100644
--- a/code/game/objects/effects/countdown.dm
+++ b/code/game/objects/effects/countdown.dm
@@ -103,19 +103,6 @@
var/completion = round(C.get_completion())
return completion
-/obj/effect/countdown/clockworkgate
- name = "gateway countdown"
- text_size = 1
- color = "#BE8700"
- layer = POINT_LAYER
-
-/obj/effect/countdown/clockworkgate/get_value()
- var/obj/structure/destructible/clockwork/massive/celestial_gateway/G = attached_to
- if(!istype(G))
- return
- else if(G.obj_integrity && !G.purpose_fulfilled)
- return "
[G.get_arrival_time(FALSE)]
"
-
/obj/effect/countdown/supermatter
name = "supermatter damage"
text_size = 1
diff --git a/code/game/objects/effects/decals/cleanable/robots.dm b/code/game/objects/effects/decals/cleanable/robots.dm
index ca7cdaf90c7..937c620a4ae 100644
--- a/code/game/objects/effects/decals/cleanable/robots.dm
+++ b/code/game/objects/effects/decals/cleanable/robots.dm
@@ -54,7 +54,7 @@
/obj/effect/decal/cleanable/oil/Initialize()
. = ..()
- reagents.add_reagent(/datum/reagent/oil, 30)
+ reagents.add_reagent(/datum/reagent/fuel/oil, 30)
/obj/effect/decal/cleanable/oil/attackby(obj/item/I, mob/living/user)
var/attacked_by_hot_thing = I.get_temperature()
diff --git a/code/game/objects/effects/landmarks.dm b/code/game/objects/effects/landmarks.dm
index 37a87d1f11b..351f95f3854 100644
--- a/code/game/objects/effects/landmarks.dm
+++ b/code/game/objects/effects/landmarks.dm
@@ -303,7 +303,7 @@ INITIALIZE_IMMEDIATE(/obj/effect/landmark/start/new_player)
GLOB.xeno_spawn += loc
return INITIALIZE_HINT_QDEL
-//objects with the stationloving component (nuke disk) respawn here.
+//objects with the stationloving component (nuke disk) respawn here.
//also blobs that have their spawn forcemoved (running out of time when picking their spawn spot), santa and respawning devils
/obj/effect/landmark/blobstart
name = "blobstart"
@@ -389,28 +389,7 @@ INITIALIZE_IMMEDIATE(/obj/effect/landmark/start/new_player)
GLOB.tdomeadmin += loc
return INITIALIZE_HINT_QDEL
-//Servant spawn locations
-/obj/effect/landmark/servant_of_ratvar
- name = "servant of ratvar spawn"
- icon_state = "clockwork_orange"
- layer = MOB_LAYER
-
-/obj/effect/landmark/servant_of_ratvar/Initialize(mapload)
- ..()
- GLOB.servant_spawns += loc
- return INITIALIZE_HINT_QDEL
-
-//City of Cogs entrances
-/obj/effect/landmark/city_of_cogs
- name = "city of cogs entrance"
- icon_state = "city_of_cogs"
-
-/obj/effect/landmark/city_of_cogs/Initialize(mapload)
- ..()
- GLOB.city_of_cogs_spawns += loc
- return INITIALIZE_HINT_QDEL
-
-//handles clockwork portal+eminence teleport destinations
+//generic event spawns
/obj/effect/landmark/event_spawn
name = "generic event spawn"
icon_state = "generic_event"
diff --git a/code/game/objects/effects/temporary_visuals/clockcult.dm b/code/game/objects/effects/temporary_visuals/clockcult.dm
deleted file mode 100644
index 59c4e23283d..00000000000
--- a/code/game/objects/effects/temporary_visuals/clockcult.dm
+++ /dev/null
@@ -1,269 +0,0 @@
-//temporary visual effects(/obj/effect/temp_visual) used by clockcult stuff
-/obj/effect/temp_visual/ratvar
- name = "ratvar's light"
- icon = 'icons/effects/clockwork_effects.dmi'
- duration = 8
- randomdir = 0
- layer = ABOVE_NORMAL_TURF_LAYER
-
-/obj/effect/temp_visual/ratvar/door
- icon_state = "ratvardoorglow"
- layer = CLOSED_DOOR_LAYER //above closed doors
-
-/obj/effect/temp_visual/ratvar/door/window
- icon_state = "ratvarwindoorglow"
- layer = ABOVE_WINDOW_LAYER
-
-/obj/effect/temp_visual/ratvar/beam
- icon_state = "ratvarbeamglow"
-
-/obj/effect/temp_visual/ratvar/beam/door
- layer = CLOSED_DOOR_LAYER
-
-/obj/effect/temp_visual/ratvar/beam/grille
- layer = BELOW_OBJ_LAYER
-
-/obj/effect/temp_visual/ratvar/beam/itemconsume
- layer = HIGH_OBJ_LAYER
-
-/obj/effect/temp_visual/ratvar/beam/falsewall
- layer = OBJ_LAYER
-
-/obj/effect/temp_visual/ratvar/beam/catwalk
- layer = LATTICE_LAYER
-
-/obj/effect/temp_visual/ratvar/wall
- icon_state = "ratvarwallglow"
-
-/obj/effect/temp_visual/ratvar/wall/false
- layer = OBJ_LAYER
-
-/obj/effect/temp_visual/ratvar/floor
- icon_state = "ratvarfloorglow"
-
-/obj/effect/temp_visual/ratvar/floor/catwalk
- layer = LATTICE_LAYER
-
-/obj/effect/temp_visual/ratvar/window
- icon_state = "ratvarwindowglow"
- layer = ABOVE_OBJ_LAYER
-
-/obj/effect/temp_visual/ratvar/window/single
- icon_state = "ratvarwindowglow_s"
-
-/obj/effect/temp_visual/ratvar/gear
- icon_state = "ratvargearglow"
- layer = BELOW_OBJ_LAYER
-
-/obj/effect/temp_visual/ratvar/grille
- icon_state = "ratvargrilleglow"
- layer = BELOW_OBJ_LAYER
-
-/obj/effect/temp_visual/ratvar/grille/broken
- icon_state = "ratvarbrokengrilleglow"
-
-/obj/effect/temp_visual/ratvar/belligerent
- layer = ABOVE_MOB_LAYER
- icon = 'icons/obj/clockwork_objects.dmi'
- icon_state = "belligerent_eye"
- pixel_y = 20
- duration = 20
-
-/obj/effect/temp_visual/ratvar/belligerent_cast/Initialize()
- . = ..()
- animate(src, alpha = 0, time = duration, easing = EASE_OUT)
-
-/obj/effect/temp_visual/ratvar/mending_mantra
- layer = ABOVE_MOB_LAYER
- duration = 20
- alpha = 200
- icon_state = "mending_mantra"
- light_range = 1.5
- light_color = "#1E8CE1"
-
-/obj/effect/temp_visual/ratvar/mending_mantra/Initialize(mapload)
- . = ..()
- transform = matrix()*2
- var/matrix/M = transform
- M.Turn(90)
- animate(src, alpha = 20, time = duration, easing = BOUNCE_EASING, flags = ANIMATION_PARALLEL)
- animate(src, transform = M, time = duration, flags = ANIMATION_PARALLEL)
-
-/obj/effect/temp_visual/ratvar/ocular_warden
- name = "warden's gaze"
- layer = ABOVE_MOB_LAYER
- icon_state = "warden_gaze"
- duration = 3
-
-/obj/effect/temp_visual/ratvar/ocular_warden/Initialize()
- . = ..()
- pixel_x = rand(-8, 8)
- pixel_y = rand(-10, 10)
- animate(src, alpha = 0, time = duration, easing = EASE_OUT)
-
-/obj/effect/temp_visual/ratvar/prolonging_prism
- icon = 'icons/effects/64x64.dmi'
- icon_state = "prismhex1"
- layer = RIPPLE_LAYER
- pixel_y = -16
- pixel_x = -16
- duration = 30
-
-/obj/effect/temp_visual/ratvar/prolonging_prism/Initialize(mapload, set_appearance)
- . = ..()
- if(set_appearance)
- appearance = set_appearance
- animate(src, alpha = 0, time = duration, easing = BOUNCE_EASING)
-
-/obj/effect/temp_visual/ratvar/spearbreak
- icon = 'icons/effects/64x64.dmi'
- icon_state = "ratvarspearbreak"
- layer = BELOW_MOB_LAYER
- pixel_y = -16
- pixel_x = -16
-
-/obj/effect/temp_visual/ratvar/geis_binding
- icon_state = "geisbinding"
-
-/obj/effect/temp_visual/ratvar/geis_binding/top
- icon_state = "geisbinding_top"
-
-/obj/effect/temp_visual/ratvar/component
- icon = 'icons/obj/clockwork_objects.dmi'
- icon_state = "belligerent_eye"
- layer = ABOVE_MOB_LAYER
- duration = 10
-
-/obj/effect/temp_visual/ratvar/component/Initialize()
- . = ..()
- transform = matrix()*0.75
- pixel_x = rand(-10, 10)
- pixel_y = rand(-10, -2)
- animate(src, pixel_y = pixel_y + 10, alpha = 50, time = 10, easing = EASE_OUT)
-
-/obj/effect/temp_visual/ratvar/component/cogwheel
- icon_state = "vanguard_cogwheel"
-
-/obj/effect/temp_visual/ratvar/component/capacitor
- icon_state = "geis_capacitor"
-
-/obj/effect/temp_visual/ratvar/component/alloy
- icon_state = "replicant_alloy"
-
-/obj/effect/temp_visual/ratvar/component/ansible
- icon_state = "hierophant_ansible"
-
-/obj/effect/temp_visual/ratvar/sigil
- name = "glowing circle"
- icon_state = "sigildull"
-
-/obj/effect/temp_visual/ratvar/sigil/transgression
- color = "#FAE48C"
- layer = ABOVE_MOB_LAYER
- duration = 70
- light_range = 5
- light_power = 2
- light_color = "#FAE48C"
-
-/obj/effect/temp_visual/ratvar/sigil/transgression/Initialize()
- . = ..()
- var/oldtransform = transform
- animate(src, transform = matrix()*2, time = 5)
- animate(transform = oldtransform, alpha = 0, time = 65)
-
-/obj/effect/temp_visual/ratvar/sigil/transmission
- color = "#EC8A2D"
- layer = ABOVE_MOB_LAYER
- duration = 20
- light_range = 3
- light_power = 1
- light_color = "#EC8A2D"
-
-/obj/effect/temp_visual/ratvar/sigil/transmission/Initialize(mapload, transform_multiplier)
- . = ..()
- var/oldtransform = transform
- transform = matrix()*transform_multiplier
- animate(src, transform = oldtransform, alpha = 0, time = 20)
-
-/obj/effect/temp_visual/ratvar/sigil/vitality
- color = "#1E8CE1"
- icon_state = "sigilactivepulse"
- layer = ABOVE_MOB_LAYER
- light_range = 1.4
- light_power = 0.5
- light_color = "#1E8CE1"
-
-/obj/effect/temp_visual/ratvar/sigil/submission
- color = "#AF0AAF"
- layer = ABOVE_MOB_LAYER
- duration = 80
- icon_state = "sigilactiveoverlay"
- alpha = 0
-
-/obj/effect/temp_visual/steam
- name = "steam"
- desc = "Steam! It's hot. It also serves as a game distribution platform."
- icon_state = "smoke"
- duration = 15
-
-/obj/effect/temp_visual/steam/Initialize(mapload, steam_direction)
- . = ..()
- setDir(steam_direction)
- var/x_offset = 0
- var/y_offset = 0
- switch(dir)
- if(NORTH)
- y_offset = 8
- if(EAST)
- x_offset = 4
- y_offset = 4
- if(SOUTH)
- y_offset = 2
- if(WEST)
- x_offset = -4
- y_offset = 4
- animate(src, pixel_x = x_offset, pixel_y = y_offset, alpha = 50, time = 15)
-
-/obj/effect/temp_visual/steam_release
- name = "all the steam"
-
-/obj/effect/temp_visual/steam_release/Initialize()
- ..()
- for(var/V in GLOB.cardinals)
- var/turf/T = get_step(src, V)
- new/obj/effect/temp_visual/steam(T, V)
- return INITIALIZE_HINT_QDEL
-
-//Foreshadows a servant warping in.
-/obj/effect/temp_visual/ratvar/warp_marker
- name = "illuminant marker"
- desc = "A silhouette of dim light. It's getting brighter!"
- resistance_flags = INDESTRUCTIBLE
- icon = 'icons/effects/genetics.dmi'
- icon_state = "servitude"
- mouse_opacity = MOUSE_OPACITY_TRANSPARENT
- anchored = TRUE
- alpha = 0
- light_color = "#FFE48E"
- light_range = 2
- light_power = 0.7
- duration = 55
-
-/obj/effect/temp_visual/ratvar/warp_marker/Initialize(mapload, mob/living/servant)
- . = ..()
- animate(src, alpha = 255, time = 50)
-
-//Used by the Eminence to coordinate the cult
-/obj/effect/temp_visual/ratvar/command_point
- name = "command marker"
- desc = "An area of importance marked by the Eminence."
- icon = 'icons/mob/actions/actions_clockcult.dmi'
- icon_state = "eminence"
- mouse_opacity = MOUSE_OPACITY_TRANSPARENT
- resistance_flags = INDESTRUCTIBLE
- layer = MASSIVE_OBJ_LAYER
- duration = 300
-
-/obj/effect/temp_visual/ratvar/command_point/Initialize(mapload, appearance)
- . = ..()
- icon_state = appearance
diff --git a/code/game/objects/items/RCD.dm b/code/game/objects/items/RCD.dm
index 02211760f8f..bf8d642ba29 100644
--- a/code/game/objects/items/RCD.dm
+++ b/code/game/objects/items/RCD.dm
@@ -173,6 +173,12 @@ RLD
else
return FALSE
+/obj/item/construction/proc/check_menu(mob/living/user)
+ if(!istype(user))
+ return FALSE
+ if(user.incapacitated() || !user.Adjacent(src))
+ return FALSE
+ return TRUE
/obj/item/construction/rcd
name = "rapid-construction-device (RCD)"
@@ -309,12 +315,6 @@ RLD
//Not scaling these down to button size because they look horrible then, instead just bumping up radius.
return MA
-/obj/item/construction/rcd/proc/check_menu(mob/living/user)
- if(!istype(user))
- return FALSE
- if(user.incapacitated() || !user.Adjacent(src))
- return FALSE
- return TRUE
/obj/item/construction/rcd/proc/change_computer_dir(mob/user)
if(!user)
return
@@ -840,6 +840,80 @@ RLD
return TRUE
return FALSE
+/obj/item/construction/plumbing
+ name = "Plumbing Constructor"
+ desc = "An expertly modified RCD outfitted to construct plumbing machinery."
+ icon_state = "plumberer2"
+ icon = 'icons/obj/tools.dmi'
+
+ matter = 200
+ max_matter = 200
+
+ ///type of the plumbing machine
+ var/blueprint = null
+ ///index, used in the attack self to get the type. stored here since it doesnt change
+ var/list/choices = list()
+ ///index, used in the attack self to get the type. stored here since it doesnt change
+ var/list/name_to_type = list()
+ ///
+ var/list/machinery_data = list("cost" = list(), "delay" = list())
+
+/obj/item/construction/plumbing/attack_self(mob/user)
+ ..()
+ if(!choices.len)
+ for(var/A in subtypesof(/obj/machinery/plumbing))
+ var/obj/machinery/plumbing/M = A
+ if(initial(M.rcd_constructable))
+ choices += list(initial(M.name) = image(icon = initial(M.icon), icon_state = initial(M.icon_state)))
+ name_to_type[initial(M.name)] = M
+ machinery_data["cost"][A] = initial(M.rcd_cost)
+ machinery_data["delay"][A] = initial(M.rcd_delay)
+
+ var/choice = show_radial_menu(user, src, choices, custom_check = CALLBACK(src, .proc/check_menu, user), require_near = TRUE, tooltips = TRUE)
+ if(!check_menu(user))
+ return
+
+ blueprint = name_to_type[choice]
+ playsound(src, 'sound/effects/pop.ogg', 50, FALSE)
+ to_chat(user, "You change [name]s blueprint to '[choice]'.")
+
+///pretty much rcd_create, but named differently to make myself feel less bad for copypasting from a sibling-type
+/obj/item/construction/plumbing/proc/create_machine(atom/A, mob/user)
+ if(!machinery_data || !isopenturf(A))
+ return FALSE
+
+ if(checkResource(machinery_data["cost"][blueprint], user) && blueprint)
+ if(do_after(user, machinery_data["delay"][blueprint], target = A))
+ if(checkResource(machinery_data["cost"][blueprint], user) && canPlace(A))
+ useResource(machinery_data["cost"][blueprint], user)
+ activate()
+ playsound(src.loc, 'sound/machines/click.ogg', 50, TRUE)
+ new blueprint (A, FALSE, FALSE)
+ return TRUE
+
+/obj/item/construction/plumbing/proc/canPlace(turf/T)
+ if(!isopenturf(T))
+ return FALSE
+ . = TRUE
+ for(var/obj/O in T.contents)
+ if(O.density) //let's not built ontop of dense stuff, like big machines and other obstacles, it kills my immershion
+ return FALSE
+
+/obj/item/construction/plumbing/afterattack(atom/A, mob/user, proximity)
+ . = ..()
+ if(!prox_check(proximity))
+ return
+ if(istype(A, /obj/machinery/plumbing))
+ var/obj/machinery/plumbing/P = A
+ if(P.anchored)
+ to_chat(user, "The [P.name] needs to be unanchored!")
+ return
+ if(do_after(user, 20, target = P))
+ P.deconstruct() //Let's not substract matter
+ playsound(get_turf(src), 'sound/machines/click.ogg', 50, TRUE) //this is just such a great sound effect
+ else
+ create_machine(A, user)
+
/obj/item/rcd_upgrade
name = "RCD advanced design disk"
desc = "It seems to be empty."
diff --git a/code/game/objects/items/cigs_lighters.dm b/code/game/objects/items/cigs_lighters.dm
index d043391d060..9e02f216b17 100644
--- a/code/game/objects/items/cigs_lighters.dm
+++ b/code/game/objects/items/cigs_lighters.dm
@@ -554,7 +554,7 @@ CIGARETTE PACKETS ARE IN FANCY.DM
heat = 1500
resistance_flags = FIRE_PROOF
light_color = LIGHT_COLOR_FIRE
- grind_results = list(/datum/reagent/iron = 1, /datum/reagent/fuel = 5, /datum/reagent/oil = 5)
+ grind_results = list(/datum/reagent/iron = 1, /datum/reagent/fuel = 5, /datum/reagent/fuel/oil = 5)
/obj/item/lighter/Initialize()
. = ..()
diff --git a/code/game/objects/items/circuitboards/machine_circuitboards.dm b/code/game/objects/items/circuitboards/machine_circuitboards.dm
index 90e05360f4a..0ec1707f25f 100644
--- a/code/game/objects/items/circuitboards/machine_circuitboards.dm
+++ b/code/game/objects/items/circuitboards/machine_circuitboards.dm
@@ -1161,10 +1161,6 @@
/obj/item/stock_parts/capacitor = /obj/item/stock_parts/capacitor/quadratic,
/obj/item/stock_parts/micro_laser = /obj/item/stock_parts/micro_laser/quadultra)
-/obj/item/circuitboard/machine/clockwork
- name = "clockwork board (Report This)"
- icon_state = "clock_mod"
-
/obj/item/circuitboard/machine/plantgenes/vault
name = "alien board (Plant DNA Manipulator)"
icon_state = "abductor_mod"
@@ -1173,5 +1169,3 @@
/obj/item/stock_parts/manipulator = /obj/item/stock_parts/manipulator/femto,
/obj/item/stock_parts/micro_laser = /obj/item/stock_parts/micro_laser/quadultra,
/obj/item/stock_parts/scanning_module = /obj/item/stock_parts/scanning_module/triphasic)
-
-
diff --git a/code/game/objects/items/devices/radio/intercom.dm b/code/game/objects/items/devices/radio/intercom.dm
index 3e33deb2c31..e786aef5402 100644
--- a/code/game/objects/items/devices/radio/intercom.dm
+++ b/code/game/objects/items/devices/radio/intercom.dm
@@ -15,29 +15,6 @@
/obj/item/radio/intercom/unscrewed
unfastened = TRUE
-/obj/item/radio/intercom/ratvar
- name = "hierophant intercom"
- desc = "A modified intercom that uses the Hierophant network instead of subspace tech. Can listen to and broadcast on any frequency."
- icon_state = "intercom_ratvar"
- freerange = TRUE
-
-/obj/item/radio/intercom/ratvar/attackby(obj/item/I, mob/living/user, params)
- if(I.tool_behaviour == TOOL_SCREWDRIVER)
- to_chat(user, "[src] is fastened to the wall with [is_servant_of_ratvar(user) ? "replicant alloy" : "some material you've never seen"], and can't be removed.")
- return //no unfastening!
- . = ..()
-
-/obj/item/radio/intercom/ratvar/process()
- if(!istype(SSticker.mode, /datum/game_mode/clockwork_cult))
- invisibility = INVISIBILITY_OBSERVER
- alpha = 125
- emped = TRUE
- else
- invisibility = initial(invisibility)
- alpha = initial(alpha)
- emped = FALSE
- ..()
-
/obj/item/radio/intercom/Initialize(mapload, ndir, building)
. = ..()
if(building)
diff --git a/code/game/objects/items/grenades/plastic.dm b/code/game/objects/items/grenades/plastic.dm
index 31302ac083f..2830f08755d 100644
--- a/code/game/objects/items/grenades/plastic.dm
+++ b/code/game/objects/items/grenades/plastic.dm
@@ -67,7 +67,7 @@
/obj/item/grenade/c4/attack_self(mob/user)
var/newtime = input(usr, "Please set the timer.", "Timer", 10) as num|null
-
+
if (isnull(newtime))
return
@@ -120,8 +120,6 @@
message_say = "FOR THE HIVE!"
else if(UM.has_antag_datum(/datum/antagonist/cult))
message_say = "FOR NAR'SIE!"
- else if(UM.has_antag_datum(/datum/antagonist/clockcult))
- message_say = "FOR RATVAR!"
else if(UM.has_antag_datum(/datum/antagonist/rev))
message_say = "VIVA LA REVOLUTION!"
else if(UM.has_antag_datum(/datum/antagonist/brother))
diff --git a/code/game/objects/items/holy_weapons.dm b/code/game/objects/items/holy_weapons.dm
index 3d80ff72fa7..74220144364 100644
--- a/code/game/objects/items/holy_weapons.dm
+++ b/code/game/objects/items/holy_weapons.dm
@@ -190,7 +190,7 @@
/obj/item/nullrod
name = "null rod"
- desc = "A rod of pure obsidian; its very presence disrupts and dampens the powers of Nar'Sie and Ratvar's followers."
+ desc = "A rod of pure obsidian; its very presence disrupts and dampens the powers of Nar'Sie's followers."
icon_state = "nullrod"
item_state = "nullrod"
lefthand_file = 'icons/mob/inhands/weapons/melee_lefthand.dmi'
diff --git a/code/game/objects/items/manuals.dm b/code/game/objects/items/manuals.dm
index d5e2731a1d2..4825cb3a5ca 100644
--- a/code/game/objects/items/manuals.dm
+++ b/code/game/objects/items/manuals.dm
@@ -443,3 +443,10 @@
H.spill_organs()
H.spread_bodyparts()
return (BRUTELOSS)
+
+/obj/item/book/manual/wiki/plumbing
+ name = "Chemical Factories Without Narcotics"
+ icon_state ="plumbingbook"
+ author = "Nanotrasen"
+ title = "Chemical Factories Without Narcotics"
+ page_link = "Guide_to_plumbing"
diff --git a/code/game/objects/items/melee/misc.dm b/code/game/objects/items/melee/misc.dm
index 74d53ad0b43..cce4179d1d2 100644
--- a/code/game/objects/items/melee/misc.dm
+++ b/code/game/objects/items/melee/misc.dm
@@ -542,7 +542,7 @@
/obj/item/melee/roastingstick/Initialize()
. = ..()
if (!ovens)
- ovens = typecacheof(list(/obj/singularity, /obj/machinery/power/supermatter_crystal, /obj/structure/bonfire, /obj/structure/destructible/clockwork/massive/ratvar))
+ ovens = typecacheof(list(/obj/singularity, /obj/machinery/power/supermatter_crystal, /obj/structure/bonfire))
/obj/item/melee/roastingstick/attack_self(mob/user)
on = !on
diff --git a/code/game/objects/items/robot/robot_items.dm b/code/game/objects/items/robot/robot_items.dm
index 8e80bc81536..fcee24c1e1b 100644
--- a/code/game/objects/items/robot/robot_items.dm
+++ b/code/game/objects/items/robot/robot_items.dm
@@ -701,11 +701,6 @@
icon_state = "securearea"
sight_mode = BORGXRAY
-/obj/item/borg/sight/xray/truesight_lens
- name = "truesight lens"
- icon = 'icons/obj/clockwork_objects.dmi'
- icon_state = "truesight_lens"
-
/obj/item/borg/sight/thermal
name = "\proper thermal vision"
sight_mode = BORGTHERM
diff --git a/code/game/objects/items/robot/robot_parts.dm b/code/game/objects/items/robot/robot_parts.dm
index 1b269a19568..0f0edab575c 100644
--- a/code/game/objects/items/robot/robot_parts.dm
+++ b/code/game/objects/items/robot/robot_parts.dm
@@ -299,9 +299,6 @@
O.make_laws()
SSticker.mode.remove_antag_for_borging(BM.mind)
- if(!istype(M.laws, /datum/ai_laws/ratvar))
- remove_servant_of_ratvar(BM, TRUE)
-
O.job = "Cyborg"
O.cell = chest.cell
diff --git a/code/game/objects/items/singularityhammer.dm b/code/game/objects/items/singularityhammer.dm
index ea9ce22e1d2..1c84a3a1d65 100644
--- a/code/game/objects/items/singularityhammer.dm
+++ b/code/game/objects/items/singularityhammer.dm
@@ -4,6 +4,7 @@
icon_state = "mjollnir0"
lefthand_file = 'icons/mob/inhands/weapons/hammers_lefthand.dmi'
righthand_file = 'icons/mob/inhands/weapons/hammers_righthand.dmi'
+ color = "#212121"
flags_1 = CONDUCT_1
slot_flags = ITEM_SLOT_BACK
force = 5
diff --git a/code/game/objects/items/stacks/sheets/mineral.dm b/code/game/objects/items/stacks/sheets/mineral.dm
index c7626bb077f..14eb01d8f6d 100644
--- a/code/game/objects/items/stacks/sheets/mineral.dm
+++ b/code/game/objects/items/stacks/sheets/mineral.dm
@@ -319,6 +319,7 @@ GLOBAL_LIST_INIT(titanium_recipes, list ( \
custom_materials = list(/datum/material/titanium=MINERAL_MATERIAL_AMOUNT, /datum/material/plasma=MINERAL_MATERIAL_AMOUNT)
point_value = 45
merge_type = /obj/item/stack/sheet/mineral/plastitanium
+ material_flags = MATERIAL_NO_EFFECTS
GLOBAL_LIST_INIT(plastitanium_recipes, list ( \
new/datum/stack_recipe("plastitanium tile", /obj/item/stack/tile/mineral/plastitanium, 1, 4, 20), \
diff --git a/code/game/objects/items/stacks/sheets/sheet_types.dm b/code/game/objects/items/stacks/sheets/sheet_types.dm
index 4c1ddf5c442..47e4b9c3bc1 100644
--- a/code/game/objects/items/stacks/sheets/sheet_types.dm
+++ b/code/game/objects/items/stacks/sheets/sheet_types.dm
@@ -8,7 +8,6 @@
* Cardboard
* Paper Frames
* Runed Metal (cult)
- * Brass (clockwork cult)
* Bronze (bake brass)
*/
@@ -105,12 +104,9 @@ GLOBAL_LIST_INIT(metal_recipes, list ( \
merge_type = /obj/item/stack/sheet/metal
grind_results = list(/datum/reagent/iron = 20)
point_value = 2
+ tableVariant = /obj/structure/table
material_type = /datum/material/iron
-/obj/item/stack/sheet/metal/ratvar_act()
- new /obj/item/stack/tile/brass(loc, amount)
- qdel(src)
-
/obj/item/stack/sheet/metal/narsie_act()
new /obj/item/stack/sheet/runed_metal(loc, amount)
qdel(src)
@@ -169,6 +165,7 @@ GLOBAL_LIST_INIT(plasteel_recipes, list ( \
grind_results = list(/datum/reagent/iron = 20, /datum/reagent/toxin/plasma = 20)
point_value = 23
tableVariant = /obj/structure/table/reinforced
+ material_flags = MATERIAL_NO_EFFECTS
/obj/item/stack/sheet/plasteel/get_main_recipes()
. = ..()
@@ -476,10 +473,6 @@ GLOBAL_LIST_INIT(runed_metal_recipes, list ( \
novariants = TRUE
grind_results = list(/datum/reagent/iron = 5, /datum/reagent/blood = 15)
-/obj/item/stack/sheet/runed_metal/ratvar_act()
- new /obj/item/stack/tile/brass(loc, amount)
- qdel(src)
-
/obj/item/stack/sheet/runed_metal/attack_self(mob/living/user)
if(!iscultist(user))
to_chat(user, "Only one with forbidden knowledge could hope to work this metal...")
@@ -504,68 +497,6 @@ GLOBAL_LIST_INIT(runed_metal_recipes, list ( \
/obj/item/stack/sheet/runed_metal/five
amount = 5
-/*
- * Brass
- */
-GLOBAL_LIST_INIT(brass_recipes, list ( \
- new/datum/stack_recipe("wall gear", /obj/structure/destructible/clockwork/wall_gear, 3, time = 10, one_per_turf = TRUE, on_floor = TRUE), \
- null,
- new/datum/stack_recipe("pinion airlock", /obj/machinery/door/airlock/clockwork, 5, time = 50, one_per_turf = TRUE, on_floor = TRUE), \
- new/datum/stack_recipe("brass pinion airlock", /obj/machinery/door/airlock/clockwork/brass, 5, time = 50, one_per_turf = TRUE, on_floor = TRUE), \
- new/datum/stack_recipe("brass windoor", /obj/machinery/door/window/clockwork, 2, time = 30, on_floor = TRUE, window_checks = TRUE), \
- null,
- new/datum/stack_recipe("directional brass window", /obj/structure/window/reinforced/clockwork/unanchored, time = 0, on_floor = TRUE, window_checks = TRUE), \
- new/datum/stack_recipe("fulltile brass window", /obj/structure/window/reinforced/clockwork/fulltile/unanchored, 2, time = 0, on_floor = TRUE, window_checks = TRUE), \
- new/datum/stack_recipe("brass chair", /obj/structure/chair/brass, 1, time = 0, one_per_turf = TRUE, on_floor = TRUE), \
- new/datum/stack_recipe("brass table frame", /obj/structure/table_frame/brass, 1, time = 5, one_per_turf = TRUE, on_floor = TRUE), \
- null,
- new/datum/stack_recipe("sender - pressure sensor", /obj/structure/destructible/clockwork/trap/trigger/pressure_sensor, 2, time = 20, one_per_turf = TRUE, on_floor = TRUE), \
- new/datum/stack_recipe("sender - lever", /obj/structure/destructible/clockwork/trap/trigger/lever, 1, time = 10, one_per_turf = TRUE, on_floor = TRUE), \
- new/datum/stack_recipe("sender - repeater", /obj/structure/destructible/clockwork/trap/trigger/repeater, 2, time = 20, one_per_turf = TRUE, on_floor = TRUE), \
- null,
- new/datum/stack_recipe("receiver - brass skewer", /obj/structure/destructible/clockwork/trap/brass_skewer, 2, time = 20, one_per_turf = TRUE, on_floor = TRUE, placement_checks = STACK_CHECK_ADJACENT), \
- new/datum/stack_recipe("receiver - steam vent", /obj/structure/destructible/clockwork/trap/steam_vent, 3, time = 30, one_per_turf = TRUE, on_floor = TRUE, placement_checks = STACK_CHECK_CARDINALS), \
-))
-
-/obj/item/stack/tile/brass
- name = "brass"
- desc = "Sheets made out of brass."
- singular_name = "brass sheet"
- icon_state = "sheet-brass"
- item_state = "sheet-brass"
- icon = 'icons/obj/stack_objects.dmi'
- resistance_flags = FIRE_PROOF | ACID_PROOF
- throwforce = 10
- max_amount = 50
- throw_speed = 1
- throw_range = 3
- turf_type = /turf/open/floor/clockwork
- novariants = FALSE
- grind_results = list(/datum/reagent/iron = 5, /datum/reagent/teslium = 15)
- merge_type = /obj/item/stack/tile/brass
-
-/obj/item/stack/tile/brass/narsie_act()
- new /obj/item/stack/sheet/runed_metal(loc, amount)
- qdel(src)
-
-/obj/item/stack/tile/brass/attack_self(mob/living/user)
- if(!is_servant_of_ratvar(user))
- to_chat(user, "[src] seems far too fragile and rigid to build with.") //haha that's because it's actually replicant alloy you DUMMY
- return
- ..()
-
-/obj/item/stack/tile/brass/get_main_recipes()
- . = ..()
- . += GLOB.brass_recipes
-
-/obj/item/stack/sheet/paperframes/Initialize()
- . = ..()
- pixel_x = 0
- pixel_y = 0
-
-/obj/item/stack/tile/brass/fifty
- amount = 50
-
/*
* Bronze
*/
@@ -599,11 +530,6 @@ GLOBAL_LIST_INIT(bronze_recipes, list ( \
merge_type = /obj/item/stack/tile/bronze
tableVariant = /obj/structure/table/bronze
-/obj/item/stack/tile/bronze/attack_self(mob/living/user)
- if(is_servant_of_ratvar(user)) //still lets them build with it, just gives a message
- to_chat(user, "Wha... what is this cheap imitation crap? This isn't brass at all!")
- ..()
-
/obj/item/stack/tile/bronze/get_main_recipes()
. = ..()
. += GLOB.bronze_recipes
diff --git a/code/game/objects/items/stacks/sheets/sheets.dm b/code/game/objects/items/stacks/sheets/sheets.dm
index 6e7c29c210d..ce901a75f93 100644
--- a/code/game/objects/items/stacks/sheets/sheets.dm
+++ b/code/game/objects/items/stacks/sheets/sheets.dm
@@ -10,7 +10,7 @@
throw_range = 3
attack_verb = list("bashed", "battered", "bludgeoned", "thrashed", "smashed")
novariants = FALSE
- var/perunit = MINERAL_MATERIAL_AMOUNT
+ mats_per_stack = MINERAL_MATERIAL_AMOUNT
var/sheettype = null //this is used for girders in the creation of walls/false walls
var/point_value = 0 //turn-in value for the gulag stacker - loosely relative to its rarity.
diff --git a/code/game/objects/items/stacks/stack.dm b/code/game/objects/items/stacks/stack.dm
index bbad31be950..285647aaec7 100644
--- a/code/game/objects/items/stacks/stack.dm
+++ b/code/game/objects/items/stacks/stack.dm
@@ -24,6 +24,7 @@
var/merge_type = null // This path and its children should merge with this stack, defaults to src.type
var/full_w_class = WEIGHT_CLASS_NORMAL //The weight class the stack should have at amount > 2/3rds max_amount
var/novariants = TRUE //Determines whether the item should update it's sprites based on amount.
+ var/mats_per_stack = 0
///Datum material type that this stack is made of
var/material_type
//NOTE: When adding grind_results, the amounts should be for an INDIVIDUAL ITEM - these amounts will be multiplied by the stack size in on_grind()
@@ -49,7 +50,7 @@
merge_type = type
if(custom_materials && custom_materials.len)
for(var/i in custom_materials)
- custom_materials[getmaterialref(i)] = MINERAL_MATERIAL_AMOUNT * amount
+ custom_materials[getmaterialref(i)] = mats_per_stack * amount
. = ..()
if(merge)
for(var/obj/item/stack/S in loc)
@@ -228,7 +229,7 @@
if(R.applies_mats && custom_materials && custom_materials.len)
var/list/used_materials = list()
for(var/i in custom_materials)
- used_materials[getmaterialref(i)] = R.req_amount * (MINERAL_MATERIAL_AMOUNT / custom_materials.len)
+ used_materials[getmaterialref(i)] = R.req_amount / R.res_amount * (MINERAL_MATERIAL_AMOUNT / custom_materials.len)
O.set_custom_materials(used_materials)
//START: oh fuck i'm so sorry
diff --git a/code/game/objects/items/stacks/tiles/tile_mineral.dm b/code/game/objects/items/stacks/tiles/tile_mineral.dm
index 9af095385b3..4cb4fbf865a 100644
--- a/code/game/objects/items/stacks/tiles/tile_mineral.dm
+++ b/code/game/objects/items/stacks/tiles/tile_mineral.dm
@@ -87,6 +87,7 @@
turf_type = /turf/open/floor/mineral/plastitanium
mineralType = "plastitanium"
custom_materials = list(/datum/material/titanium=250, /datum/material/plasma=250)
+ material_flags = MATERIAL_NO_EFFECTS
/obj/item/stack/tile/mineral/snow
name = "snow tile"
diff --git a/code/game/objects/items/stacks/tiles/tile_types.dm b/code/game/objects/items/stacks/tiles/tile_types.dm
index d9ebe6d3d7b..25e6547a269 100644
--- a/code/game/objects/items/stacks/tiles/tile_types.dm
+++ b/code/game/objects/items/stacks/tiles/tile_types.dm
@@ -11,6 +11,7 @@
throw_speed = 3
throw_range = 7
max_amount = 60
+ mats_per_stack = 500
var/turf_type = null
var/mineralType = null
novariants = TRUE
diff --git a/code/game/objects/items/storage/belt.dm b/code/game/objects/items/storage/belt.dm
index 73d7f3fc6e6..0b6847b75f5 100644
--- a/code/game/objects/items/storage/belt.dm
+++ b/code/game/objects/items/storage/belt.dm
@@ -107,15 +107,6 @@
new /obj/item/t_scanner(src)
new /obj/item/extinguisher/mini(src)
-/obj/item/storage/belt/utility/servant/PopulateContents()
- new /obj/item/screwdriver/brass(src)
- new /obj/item/wirecutters/brass(src)
- new /obj/item/wrench/brass(src)
- new /obj/item/crowbar/brass(src)
- new /obj/item/weldingtool/experimental/brass(src)
- new /obj/item/multitool(src)
- new /obj/item/stack/cable_coil(src, MAXCOIL, "yellow")
-
/obj/item/storage/belt/medical
name = "medical belt"
desc = "Can hold various medical equipment."
diff --git a/code/game/objects/items/storage/toolbox.dm b/code/game/objects/items/storage/toolbox.dm
index 96ee11af9fb..cc94f1e21cd 100644
--- a/code/game/objects/items/storage/toolbox.dm
+++ b/code/game/objects/items/storage/toolbox.dm
@@ -184,49 +184,6 @@
new /obj/item/wirecutters(src)
new /obj/item/multitool(src)
-/obj/item/storage/toolbox/brass
- name = "brass box"
- desc = "A huge brass box with several indentations in its surface."
- icon_state = "brassbox"
- item_state = null
- has_latches = FALSE
- resistance_flags = FIRE_PROOF | ACID_PROOF
- w_class = WEIGHT_CLASS_HUGE
- attack_verb = list("robusted", "crushed", "smashed")
- material_flags = NONE
- var/fabricator_type = /obj/item/clockwork/replica_fabricator/scarab
-
-/obj/item/storage/toolbox/brass/ComponentInitialize()
- . = ..()
- var/datum/component/storage/STR = GetComponent(/datum/component/storage)
- STR.max_w_class = WEIGHT_CLASS_NORMAL
- STR.max_combined_w_class = 28
- STR.max_items = 28
-
-/obj/item/storage/toolbox/brass/prefilled/PopulateContents()
- new fabricator_type(src)
- new /obj/item/screwdriver/brass(src)
- new /obj/item/wirecutters/brass(src)
- new /obj/item/wrench/brass(src)
- new /obj/item/crowbar/brass(src)
- new /obj/item/weldingtool/experimental/brass(src)
-
-/obj/item/storage/toolbox/brass/prefilled/servant
- slot_flags = ITEM_SLOT_BELT
- fabricator_type = null
-
-/obj/item/storage/toolbox/brass/prefilled/ratvar
- var/slab_type = /obj/item/clockwork/slab
-
-/obj/item/storage/toolbox/brass/prefilled/ratvar/PopulateContents()
- ..()
- new slab_type(src)
-
-/obj/item/storage/toolbox/brass/prefilled/ratvar/admin
- slab_type = /obj/item/clockwork/slab/debug
- fabricator_type = /obj/item/clockwork/replica_fabricator/scarab/debug
-
-
/obj/item/storage/toolbox/artistic
name = "artistic toolbox"
desc = "A toolbox painted bright green. Why anyone would store art supplies in a toolbox is beyond you, but it has plenty of extra space."
diff --git a/code/game/objects/items/tools/crowbar.dm b/code/game/objects/items/tools/crowbar.dm
index 10bdf34cf18..3402696c098 100644
--- a/code/game/objects/items/tools/crowbar.dm
+++ b/code/game/objects/items/tools/crowbar.dm
@@ -30,13 +30,6 @@
icon_state = "crowbar_red"
force = 8
-/obj/item/crowbar/brass
- name = "brass crowbar"
- desc = "A brass crowbar. It feels faintly warm to the touch."
- resistance_flags = FIRE_PROOF | ACID_PROOF
- icon_state = "crowbar_brass"
- toolspeed = 0.5
-
/obj/item/crowbar/abductor
name = "alien crowbar"
desc = "A hard-light crowbar. It appears to pry by itself, without any effort required."
@@ -60,7 +53,7 @@
/obj/item/crowbar/power
name = "jaws of life"
- desc = "A set of jaws of life, compressed through the magic of science. It's fitted with a prying head."
+ desc = "A set of jaws of life, compressed through the magic of science."
icon_state = "jaws_pry"
item_state = "jawsoflife"
lefthand_file = 'icons/mob/inhands/equipment/tools_lefthand.dmi'
@@ -71,17 +64,45 @@
toolspeed = 0.7
force_opens = TRUE
+/obj/item/crowbar/power/examine()
+ . = ..()
+ . += " It's fitted with a [tool_behaviour == TOOL_CROWBAR ? "prying" : "cutting"] head."
+
/obj/item/crowbar/power/suicide_act(mob/user)
- user.visible_message("[user] is putting [user.p_their()] head in [src], it looks like [user.p_theyre()] trying to commit suicide!")
- playsound(loc, 'sound/items/jaws_pry.ogg', 50, TRUE, -1)
+ if(tool_behaviour == TOOL_CROWBAR)
+ user.visible_message("[user] is putting [user.p_their()] head in [src], it looks like [user.p_theyre()] trying to commit suicide!")
+ playsound(loc, 'sound/items/jaws_pry.ogg', 50, TRUE, -1)
+ else
+ user.visible_message("[user] is wrapping \the [src] around [user.p_their()] neck. It looks like [user.p_theyre()] trying to rip [user.p_their()] head off!")
+ playsound(loc, 'sound/items/jaws_cut.ogg', 50, TRUE, -1)
+ if(iscarbon(user))
+ var/mob/living/carbon/C = user
+ var/obj/item/bodypart/BP = C.get_bodypart(BODY_ZONE_HEAD)
+ if(BP)
+ BP.drop_limb()
+ playsound(loc, "desceration", 50, TRUE, -1)
return (BRUTELOSS)
/obj/item/crowbar/power/attack_self(mob/user)
playsound(get_turf(user), 'sound/items/change_jaws.ogg', 50, TRUE)
- var/obj/item/wirecutters/power/cutjaws = new /obj/item/wirecutters/power(drop_location())
- to_chat(user, "You attach the cutting jaws to [src].")
- qdel(src)
- user.put_in_active_hand(cutjaws)
+ if(tool_behaviour == TOOL_CROWBAR)
+ tool_behaviour = TOOL_WIRECUTTER
+ to_chat(user, "You attach the cutting jaws to [src].")
+ usesound = 'sound/items/jaws_cut.ogg'
+ icon_state = "jaws_cutter"
+ else
+ tool_behaviour = TOOL_CROWBAR
+ to_chat(user, "You attach the prying jaws to [src].")
+ usesound = 'sound/items/jaws_pry.ogg'
+ icon_state = "jaws_pry"
+
+/obj/item/crowbar/power/attack(mob/living/carbon/C, mob/user)
+ if(istype(C) && C.handcuffed && tool_behaviour == TOOL_WIRECUTTER)
+ user.visible_message("[user] cuts [C]'s restraints with [src]!")
+ qdel(C.handcuffed)
+ return
+ else
+ ..()
/obj/item/crowbar/cyborg
name = "hydraulic crowbar"
diff --git a/code/game/objects/items/tools/screwdriver.dm b/code/game/objects/items/tools/screwdriver.dm
index b18bfffef1c..957de0f90dd 100644
--- a/code/game/objects/items/tools/screwdriver.dm
+++ b/code/game/objects/items/tools/screwdriver.dm
@@ -84,15 +84,6 @@
M = user
return eyestab(M,user)
-/obj/item/screwdriver/brass
- name = "brass screwdriver"
- desc = "A screwdriver made of brass. The handle feels freezing cold."
- resistance_flags = FIRE_PROOF | ACID_PROOF
- icon_state = "screwdriver_brass"
- item_state = "screwdriver_brass"
- toolspeed = 0.5
- random_color = FALSE
-
/obj/item/screwdriver/abductor
name = "alien screwdriver"
desc = "An ultrasonic screwdriver."
@@ -108,7 +99,7 @@
/obj/item/screwdriver/power
name = "hand drill"
- desc = "A simple powered hand drill. It's fitted with a screw bit."
+ desc = "A simple powered hand drill."
icon_state = "drill_screw"
item_state = "drill"
lefthand_file = 'icons/mob/inhands/equipment/tools_lefthand.dmi'
@@ -125,16 +116,28 @@
toolspeed = 0.7
random_color = FALSE
+/obj/item/screwdriver/power/examine()
+ . = ..()
+ . += " It's fitted with a [tool_behaviour == TOOL_SCREWDRIVER ? "screw" : "bolt"] bit."
+
/obj/item/screwdriver/power/suicide_act(mob/user)
- user.visible_message("[user] is putting [src] to [user.p_their()] temple. It looks like [user.p_theyre()] trying to commit suicide!")
+ if(tool_behaviour == TOOL_SCREWDRIVER)
+ user.visible_message("[user] is putting [src] to [user.p_their()] temple. It looks like [user.p_theyre()] trying to commit suicide!")
+ else
+ user.visible_message("[user] is pressing [src] against [user.p_their()] head! It looks like [user.p_theyre()] trying to commit suicide!")
+ playsound(loc, 'sound/items/drill_use.ogg', 50, TRUE, -1)
return(BRUTELOSS)
/obj/item/screwdriver/power/attack_self(mob/user)
- playsound(get_turf(user),'sound/items/change_drill.ogg',50,TRUE)
- var/obj/item/wrench/power/b_drill = new /obj/item/wrench/power(drop_location())
- to_chat(user, "You attach the bolt driver bit to [src].")
- qdel(src)
- user.put_in_active_hand(b_drill)
+ playsound(get_turf(user), 'sound/items/change_drill.ogg', 50, TRUE)
+ if(tool_behaviour == TOOL_SCREWDRIVER)
+ tool_behaviour = TOOL_WRENCH
+ to_chat(user, "You attach the bolt bit to [src].")
+ icon_state = "drill_bolt"
+ else
+ tool_behaviour = TOOL_SCREWDRIVER
+ to_chat(user, "You attach the screw bit to [src].")
+ icon_state = "drill_screw"
/obj/item/screwdriver/cyborg
name = "automated screwdriver"
diff --git a/code/game/objects/items/tools/weldingtool.dm b/code/game/objects/items/tools/weldingtool.dm
index 5dbf03e7859..b96a3e0363d 100644
--- a/code/game/objects/items/tools/weldingtool.dm
+++ b/code/game/objects/items/tools/weldingtool.dm
@@ -381,14 +381,6 @@
toolspeed = 0.5
var/nextrefueltick = 0
-/obj/item/weldingtool/experimental/brass
- name = "brass welding tool"
- desc = "A brass welder that seems to constantly refuel itself. It is faintly warm to the touch."
- resistance_flags = FIRE_PROOF | ACID_PROOF
- icon_state = "brasswelder"
- item_state = "brasswelder"
-
-
/obj/item/weldingtool/experimental/process()
..()
if(get_fuel() < max_fuel && nextrefueltick < world.time)
diff --git a/code/game/objects/items/tools/wirecutters.dm b/code/game/objects/items/tools/wirecutters.dm
index 40f09240cdb..e66f978f1a4 100644
--- a/code/game/objects/items/tools/wirecutters.dm
+++ b/code/game/objects/items/tools/wirecutters.dm
@@ -68,61 +68,14 @@
playsound(loc, usesound, 50, TRUE, -1)
return (BRUTELOSS)
-/obj/item/wirecutters/brass
- name = "brass wirecutters"
- desc = "A pair of wirecutters made of brass. The handle feels freezing cold to the touch."
- resistance_flags = FIRE_PROOF | ACID_PROOF
- icon_state = "cutters_brass"
- random_color = FALSE
- toolspeed = 0.5
-
/obj/item/wirecutters/abductor
name = "alien wirecutters"
desc = "Extremely sharp wirecutters, made out of a silvery-green metal."
icon = 'icons/obj/abductor.dmi'
icon_state = "cutters"
toolspeed = 0.1
-
random_color = FALSE
-/obj/item/wirecutters/power
- name = "jaws of life"
- desc = "A set of jaws of life, compressed through the magic of science. It's fitted with a cutting head."
- icon_state = "jaws_cutter"
- item_state = "jawsoflife"
-
- custom_materials = list(/datum/material/iron=150,/datum/material/silver=50,/datum/material/titanium=25)
- usesound = 'sound/items/jaws_cut.ogg'
- toolspeed = 0.7
- random_color = FALSE
-
-/obj/item/wirecutters/power/suicide_act(mob/user)
- user.visible_message("[user] is wrapping \the [src] around [user.p_their()] neck. It looks like [user.p_theyre()] trying to rip [user.p_their()] head off!")
- playsound(loc, 'sound/items/jaws_cut.ogg', 50, TRUE, -1)
- if(iscarbon(user))
- var/mob/living/carbon/C = user
- var/obj/item/bodypart/BP = C.get_bodypart(BODY_ZONE_HEAD)
- if(BP)
- BP.drop_limb()
- playsound(loc, "desceration", 50, TRUE, -1)
- return (BRUTELOSS)
-
-/obj/item/wirecutters/power/attack_self(mob/user)
- playsound(get_turf(user), 'sound/items/change_jaws.ogg', 50, TRUE)
- var/obj/item/crowbar/power/pryjaws = new /obj/item/crowbar/power(drop_location())
- to_chat(user, "You attach the pry jaws to [src].")
- qdel(src)
- user.put_in_active_hand(pryjaws)
-
-/obj/item/wirecutters/power/attack(mob/living/carbon/C, mob/user)
- if(istype(C) && C.handcuffed)
- user.visible_message("[user] cuts [C]'s restraints with [src]!")
- qdel(C.handcuffed)
- return
- else
- ..()
-
-
/obj/item/wirecutters/cyborg
name = "powered wirecutters"
desc = "Cuts wires with the power of ELECTRICITY. Faster than normal wirecutters."
diff --git a/code/game/objects/items/tools/wrench.dm b/code/game/objects/items/tools/wrench.dm
index 025ecdbe1a6..aeff4e2bf21 100644
--- a/code/game/objects/items/tools/wrench.dm
+++ b/code/game/objects/items/tools/wrench.dm
@@ -25,13 +25,6 @@
playsound(loc, 'sound/weapons/genhit.ogg', 50, TRUE, -1)
return (BRUTELOSS)
-/obj/item/wrench/brass
- name = "brass wrench"
- desc = "A brass wrench. It's faintly warm to the touch."
- resistance_flags = FIRE_PROOF | ACID_PROOF
- icon_state = "wrench_brass"
- toolspeed = 0.5
-
/obj/item/wrench/abductor
name = "alien wrench"
desc = "A polarized wrench. It causes anything placed between the jaws to turn."
@@ -41,33 +34,6 @@
toolspeed = 0.1
-/obj/item/wrench/power
- name = "hand drill"
- desc = "A simple powered hand drill. It's fitted with a bolt bit."
- icon_state = "drill_bolt"
- item_state = "drill"
- lefthand_file = 'icons/mob/inhands/equipment/tools_lefthand.dmi'
- righthand_file = 'icons/mob/inhands/equipment/tools_righthand.dmi'
- usesound = 'sound/items/drill_use.ogg'
- custom_materials = list(/datum/material/iron=150,/datum/material/silver=50,/datum/material/titanium=25)
- //done for balance reasons, making them high value for research, but harder to get
- force = 8 //might or might not be too high, subject to change
- w_class = WEIGHT_CLASS_SMALL
- throwforce = 8
- attack_verb = list("drilled", "screwed", "jabbed")
- toolspeed = 0.7
-
-/obj/item/wrench/power/attack_self(mob/user)
- playsound(get_turf(user),'sound/items/change_drill.ogg',50,TRUE)
- var/obj/item/wirecutters/power/s_drill = new /obj/item/screwdriver/power(drop_location())
- to_chat(user, "You attach the screw driver bit to [src].")
- qdel(src)
- user.put_in_active_hand(s_drill)
-
-/obj/item/wrench/power/suicide_act(mob/user)
- user.visible_message("[user] is pressing [src] against [user.p_their()] head! It looks like [user.p_theyre()] trying to commit suicide!")
- return (BRUTELOSS)
-
/obj/item/wrench/medical
name = "medical wrench"
desc = "A medical wrench with common(medical?) uses. Can be found in your hand."
diff --git a/code/game/objects/items/weaponry.dm b/code/game/objects/items/weaponry.dm
index b2d68f2b961..565c768f900 100644
--- a/code/game/objects/items/weaponry.dm
+++ b/code/game/objects/items/weaponry.dm
@@ -705,3 +705,16 @@ for further reading, please see: https://github.com/tgstation/tgstation/pull/301
to_chat(user, "[M] is too close to use [src] on.")
return
M.attack_hand(user)
+
+/obj/item/gohei
+ name = "gohei"
+ desc = "A wooden stick with white streamers at the end. Originally used by shrine maidens to purify things. Now used by the station's valued weeaboos."
+ force = 5
+ throwforce = 5
+ hitsound = "swing_hit"
+ attack_verb = list("whacked", "thwacked", "walloped", "socked")
+ icon = 'icons/obj/items_and_weapons.dmi'
+ icon_state = "gohei"
+ item_state = "gohei"
+ lefthand_file = 'icons/mob/inhands/weapons/staves_lefthand.dmi'
+ righthand_file = 'icons/mob/inhands/weapons/staves_righthand.dmi'
diff --git a/code/game/objects/structures/ai_core.dm b/code/game/objects/structures/ai_core.dm
index db1badc3983..5a6e02eee6c 100644
--- a/code/game/objects/structures/ai_core.dm
+++ b/code/game/objects/structures/ai_core.dm
@@ -235,8 +235,6 @@
to_chat(user, "You connect the monitor.")
if(brain)
SSticker.mode.remove_antag_for_borging(brain.brainmob.mind)
- if(!istype(brain.laws, /datum/ai_laws/ratvar))
- remove_servant_of_ratvar(brain.brainmob, TRUE)
var/mob/living/silicon/ai/A = null
diff --git a/code/game/objects/structures/beds_chairs/chair.dm b/code/game/objects/structures/beds_chairs/chair.dm
index 22935621f41..6532d81a75a 100644
--- a/code/game/objects/structures/beds_chairs/chair.dm
+++ b/code/game/objects/structures/beds_chairs/chair.dm
@@ -54,8 +54,13 @@
/obj/structure/chair/deconstruct()
// If we have materials, and don't have the NOCONSTRUCT flag
- if(buildstacktype && (!(flags_1 & NODECONSTRUCT_1)))
- new buildstacktype(loc,buildstackamount)
+ if(!(flags_1 & NODECONSTRUCT_1))
+ if(buildstacktype)
+ new buildstacktype(loc,buildstackamount)
+ else
+ for(var/i in custom_materials)
+ var/datum/material/M = i
+ new M.sheet_type(loc, FLOOR(custom_materials[M] / MINERAL_MATERIAL_AMOUNT, 1))
..()
/obj/structure/chair/attack_paw(mob/user)
@@ -66,11 +71,6 @@
W.setDir(dir)
qdel(src)
-/obj/structure/chair/ratvar_act()
- var/obj/structure/chair/brass/B = new(get_turf(src))
- B.setDir(dir)
- qdel(src)
-
/obj/structure/chair/attackby(obj/item/W, mob/user, params)
if(W.tool_behaviour == TOOL_WRENCH && !(flags_1&NODECONSTRUCT_1))
W.play_tool_sound(src)
@@ -126,6 +126,7 @@
/obj/structure/chair/greyscale
material_flags = MATERIAL_ADD_PREFIX | MATERIAL_COLOR
item_chair = /obj/item/chair/greyscale
+ buildstacktype = null //Custom mats handle this
/obj/structure/chair/wood
@@ -382,43 +383,6 @@
icon_state = "chairold"
item_chair = null
-/obj/structure/chair/brass
- name = "brass chair"
- desc = "A spinny chair made of brass. It looks uncomfortable."
- icon_state = "brass_chair"
- max_integrity = 150
- buildstacktype = /obj/item/stack/tile/brass
- buildstackamount = 1
- item_chair = null
- var/turns = 0
-
-/obj/structure/chair/brass/Destroy()
- STOP_PROCESSING(SSfastprocess, src)
- . = ..()
-
-/obj/structure/chair/brass/process()
- setDir(turn(dir,-90))
- playsound(src, 'sound/effects/servostep.ogg', 50, FALSE)
- turns++
- if(turns >= 8)
- STOP_PROCESSING(SSfastprocess, src)
-
-/obj/structure/chair/brass/ratvar_act()
- return
-
-/obj/structure/chair/brass/AltClick(mob/living/user)
- turns = 0
- if(!istype(user) || !user.canUseTopic(src, BE_CLOSE, ismonkey(user)))
- return
- if(!(datum_flags & DF_ISPROCESSING))
- user.visible_message("[user] spins [src] around, and Ratvarian technology keeps it spinning FOREVER.", \
- "Automated spinny chairs. The pinnacle of Ratvarian technology.")
- START_PROCESSING(SSfastprocess, src)
- else
- user.visible_message("[user] stops [src]'s uncontrollable spinning.", \
- "You grab [src] and stop its wild spinning.")
- STOP_PROCESSING(SSfastprocess, src)
-
/obj/structure/chair/bronze
name = "brass chair"
desc = "A spinny chair made of bronze. It has little cogs for wheels!"
@@ -427,12 +391,37 @@
buildstacktype = /obj/item/stack/tile/bronze
buildstackamount = 1
item_chair = null
+ var/turns = 0
+
+/obj/structure/chair/bronze/Destroy()
+ STOP_PROCESSING(SSfastprocess, src)
+ . = ..()
+
+/obj/structure/chair/bronze/process()
+ setDir(turn(dir,-90))
+ playsound(src, 'sound/effects/servostep.ogg', 50, FALSE)
+ turns++
+ if(turns >= 8)
+ STOP_PROCESSING(SSfastprocess, src)
/obj/structure/chair/bronze/Moved()
. = ..()
if(has_gravity())
playsound(src, 'sound/machines/clockcult/integration_cog_install.ogg', 50, TRUE)
+/obj/structure/chair/bronze/AltClick(mob/living/user)
+ turns = 0
+ if(!istype(user) || !user.canUseTopic(src, BE_CLOSE, ismonkey(user)))
+ return
+ if(!(datum_flags & DF_ISPROCESSING))
+ user.visible_message("[user] spins [src] around, and the last vestiges of Ratvarian technology keeps it spinning FOREVER.", \
+ "Automated spinny chairs. The pinnacle of ancient Ratvarian technology.")
+ START_PROCESSING(SSfastprocess, src)
+ else
+ user.visible_message("[user] stops [src]'s uncontrollable spinning.", \
+ "You grab [src] and stop its wild spinning.")
+ STOP_PROCESSING(SSfastprocess, src)
+
/obj/structure/chair/mime
name = "invisible chair"
desc = "The mime needs to sit down and shut up."
diff --git a/code/game/objects/structures/false_walls.dm b/code/game/objects/structures/false_walls.dm
index e70bf8f4227..6eb571d99b6 100644
--- a/code/game/objects/structures/false_walls.dm
+++ b/code/game/objects/structures/false_walls.dm
@@ -16,11 +16,9 @@
/turf/closed/wall,
/turf/closed/wall/r_wall,
/obj/structure/falsewall,
- /obj/structure/falsewall/brass,
/obj/structure/falsewall/reinforced,
/turf/closed/wall/rust,
- /turf/closed/wall/r_wall/rust,
- /turf/closed/wall/clockwork)
+ /turf/closed/wall/r_wall/rust)
smooth = SMOOTH_TRUE
can_be_unanchored = FALSE
CanAtmosPass = ATMOS_PASS_DENSITY
@@ -37,10 +35,6 @@
. = ..()
air_update_turf(TRUE)
-/obj/structure/falsewall/ratvar_act()
- new /obj/structure/falsewall/brass(loc)
- qdel(src)
-
/obj/structure/falsewall/attack_hand(mob/user)
if(opening)
return
@@ -317,31 +311,4 @@
mineral = /obj/item/stack/sheet/mineral/plastitanium
walltype = /turf/closed/wall/mineral/plastitanium
smooth = SMOOTH_MORE
- canSmoothWith = list(/turf/closed/wall/mineral/plastitanium, /obj/machinery/door/airlock/shuttle, /obj/machinery/door/airlock, /obj/structure/window/shuttle, /obj/structure/shuttle/engine/heater)
-
-/obj/structure/falsewall/brass
- name = "clockwork wall"
- desc = "A huge chunk of warm metal. The clanging of machinery emanates from within."
- icon = 'icons/turf/walls/clockwork_wall.dmi'
- icon_state = "clockwork_wall"
- resistance_flags = FIRE_PROOF | ACID_PROOF
- mineral_amount = 1
- canSmoothWith = list(/obj/effect/clockwork/overlay/wall, /obj/structure/falsewall/brass)
- girder_type = /obj/structure/destructible/clockwork/wall_gear/displaced
- walltype = /turf/closed/wall/clockwork
- mineral = /obj/item/stack/tile/brass
-
-/obj/structure/falsewall/brass/New(loc)
- ..()
- var/turf/T = get_turf(src)
- new /obj/effect/temp_visual/ratvar/wall/false(T)
- new /obj/effect/temp_visual/ratvar/beam/falsewall(T)
- change_construction_value(4)
-
-/obj/structure/falsewall/brass/Destroy()
- change_construction_value(-4)
- return ..()
-
-/obj/structure/falsewall/brass/ratvar_act()
- if(GLOB.ratvar_awakens)
- obj_integrity = max_integrity
+ canSmoothWith = list(/turf/closed/wall/mineral/plastitanium, /obj/machinery/door/airlock/shuttle, /obj/machinery/door/airlock, /obj/structure/window/shuttle, /obj/structure/shuttle/engine/heater)
\ No newline at end of file
diff --git a/code/game/objects/structures/fluff.dm b/code/game/objects/structures/fluff.dm
index e950dac2162..852700a761a 100644
--- a/code/game/objects/structures/fluff.dm
+++ b/code/game/objects/structures/fluff.dm
@@ -224,3 +224,39 @@
/obj/structure/fluff/beach_umbrella/syndi
icon_state = "syndi_brella"
+/obj/structure/fluff/clockwork
+ name = "Clockwork Fluff"
+ icon = 'icons/obj/clockwork_objects.dmi'
+ deconstructible = FALSE
+
+/obj/structure/fluff/clockwork/alloy_shards
+ name = "replicant alloy shards"
+ desc = "Broken shards of some oddly malleable metal. They occasionally move and seem to glow."
+ icon_state = "alloy_shards"
+
+/obj/structure/fluff/clockwork/alloy_shards/small
+ icon_state = "shard_small1"
+
+/obj/structure/fluff/clockwork/alloy_shards/medium
+ icon_state = "shard_medium1"
+
+/obj/structure/fluff/clockwork/alloy_shards/medium_gearbit
+ icon_state = "gear_bit1"
+
+/obj/structure/fluff/clockwork/alloy_shards/large
+ icon_state = "shard_large1"
+
+/obj/structure/fluff/clockwork/blind_eye
+ name = "blind eye"
+ desc = "A heavy brass eye, its red iris fallen dark."
+ icon_state = "blind_eye"
+
+/obj/structure/fluff/clockwork/fallen_armor
+ name = "fallen armor"
+ desc = "Lifeless chunks of armor. They're designed in a strange way and won't fit on you."
+ icon_state = "fallen_armor"
+
+/obj/structure/fluff/clockwork/clockgolem_remains
+ name = "clockwork golem scrap"
+ desc = "A pile of scrap metal. It seems damaged beyond repair."
+ icon_state = "clockgolem_dead"
diff --git a/code/game/objects/structures/girders.dm b/code/game/objects/structures/girders.dm
index c7420281f92..9b273aa148c 100644
--- a/code/game/objects/structures/girders.dm
+++ b/code/game/objects/structures/girders.dm
@@ -292,13 +292,6 @@
new remains(loc)
qdel(src)
-/obj/structure/girder/ratvar_act()
- if(anchored)
- new /obj/structure/destructible/clockwork/wall_gear(loc)
- else
- new /obj/structure/destructible/clockwork/wall_gear/displaced(loc)
- qdel(src)
-
/obj/structure/girder/narsie_act()
new /obj/structure/girder/cult(loc)
qdel(src)
diff --git a/code/game/objects/structures/grille.dm b/code/game/objects/structures/grille.dm
index 6a29ba2d463..925e70e22d7 100644
--- a/code/game/objects/structures/grille.dm
+++ b/code/game/objects/structures/grille.dm
@@ -72,13 +72,6 @@
return TRUE
return FALSE
-/obj/structure/grille/ratvar_act()
- if(broken)
- new /obj/structure/grille/ratvar/broken(src.loc)
- else
- new /obj/structure/grille/ratvar(src.loc)
- qdel(src)
-
/obj/structure/grille/Bumped(atom/movable/AM)
if(!ismob(AM))
return
@@ -286,40 +279,4 @@
rods_amount = 1
rods_broken = FALSE
grille_type = /obj/structure/grille
- broken_type = null
-
-
-/obj/structure/grille/ratvar
- icon_state = "ratvargrille"
- name = "cog grille"
- desc = "A strangely-shaped grille."
- broken_type = /obj/structure/grille/ratvar/broken
-
-/obj/structure/grille/ratvar/Initialize()
- . = ..()
- if(broken)
- new /obj/effect/temp_visual/ratvar/grille/broken(get_turf(src))
- else
- new /obj/effect/temp_visual/ratvar/grille(get_turf(src))
- new /obj/effect/temp_visual/ratvar/beam/grille(get_turf(src))
-
-/obj/structure/grille/ratvar/narsie_act()
- take_damage(rand(1, 3), BRUTE)
- if(src)
- var/previouscolor = color
- color = "#960000"
- animate(src, color = previouscolor, time = 8)
- addtimer(CALLBACK(src, /atom/proc/update_atom_colour), 8)
-
-/obj/structure/grille/ratvar/ratvar_act()
- return
-
-/obj/structure/grille/ratvar/broken
- icon_state = "brokenratvargrille"
- density = FALSE
- obj_integrity = 20
- broken = TRUE
- rods_amount = 1
- rods_broken = FALSE
- grille_type = /obj/structure/grille/ratvar
- broken_type = null
+ broken_type = null
\ No newline at end of file
diff --git a/code/game/objects/structures/lattice.dm b/code/game/objects/structures/lattice.dm
index 7cf59cc0912..aa19f21634d 100644
--- a/code/game/objects/structures/lattice.dm
+++ b/code/game/objects/structures/lattice.dm
@@ -33,9 +33,6 @@
/obj/structure/lattice/blob_act(obj/structure/blob/B)
return
-/obj/structure/lattice/ratvar_act()
- new /obj/structure/lattice/clockwork(loc)
-
/obj/structure/lattice/attackby(obj/item/C, mob/user, params)
if(resistance_flags & INDESTRUCTIBLE)
return
@@ -69,29 +66,6 @@
if(current_size >= STAGE_FOUR)
deconstruct()
-/obj/structure/lattice/clockwork
- name = "cog lattice"
- desc = "A lightweight support lattice. These hold the Justicar's station together."
- icon = 'icons/obj/smooth_structures/lattice_clockwork.dmi'
-
-/obj/structure/lattice/clockwork/Initialize(mapload)
- canSmoothWith += /turf/open/indestructible/clock_spawn_room //list overrides are a terrible thing
- . = ..()
- ratvar_act()
- if(is_reebe(z))
- resistance_flags |= INDESTRUCTIBLE
-
-/obj/structure/lattice/clockwork/ratvar_act()
- if(ISODD(x+y))
- icon = 'icons/obj/smooth_structures/lattice_clockwork_large.dmi'
- pixel_x = -9
- pixel_y = -9
- else
- icon = 'icons/obj/smooth_structures/lattice_clockwork.dmi'
- pixel_x = 0
- pixel_y = 0
- return TRUE
-
/obj/structure/lattice/catwalk
name = "catwalk"
desc = "A catwalk for easier EVA maneuvering and cable placement."
@@ -104,9 +78,6 @@
/obj/structure/lattice/catwalk/deconstruction_hints(mob/user)
return "The supporting rods look like they could be cut."
-/obj/structure/lattice/catwalk/ratvar_act()
- new /obj/structure/lattice/catwalk/clockwork(loc)
-
/obj/structure/lattice/catwalk/Move()
var/turf/T = loc
for(var/obj/structure/cable/C in T)
@@ -118,33 +89,3 @@
for(var/obj/structure/cable/C in T)
C.deconstruct()
..()
-
-/obj/structure/lattice/catwalk/clockwork
- name = "clockwork catwalk"
- icon = 'icons/obj/smooth_structures/catwalk_clockwork.dmi'
- canSmoothWith = list(/obj/structure/lattice,
- /turf/open/floor,
- /turf/open/indestructible/clock_spawn_room,
- /turf/closed/wall,
- /obj/structure/falsewall)
- smooth = SMOOTH_MORE
-
-/obj/structure/lattice/catwalk/clockwork/Initialize(mapload)
- . = ..()
- ratvar_act()
- if(!mapload)
- new /obj/effect/temp_visual/ratvar/floor/catwalk(loc)
- new /obj/effect/temp_visual/ratvar/beam/catwalk(loc)
- if(is_reebe(z))
- resistance_flags |= INDESTRUCTIBLE
-
-/obj/structure/lattice/catwalk/clockwork/ratvar_act()
- if(ISODD(x+y))
- icon = 'icons/obj/smooth_structures/catwalk_clockwork_large.dmi'
- pixel_x = -9
- pixel_y = -9
- else
- icon = 'icons/obj/smooth_structures/catwalk_clockwork.dmi'
- pixel_x = 0
- pixel_y = 0
- return TRUE
diff --git a/code/game/objects/structures/lavaland/geyser.dm b/code/game/objects/structures/lavaland/geyser.dm
index dc42880b752..116466ddf1b 100644
--- a/code/game/objects/structures/lavaland/geyser.dm
+++ b/code/game/objects/structures/lavaland/geyser.dm
@@ -9,7 +9,7 @@
var/erupting_state = null //set to null to get it greyscaled from "[icon_state]_soup". Not very usable with the whole random thing, but more types can be added if you change the spawn prob
var/activated = FALSE //whether we are active and generating chems
- var/reagent_id = /datum/reagent/oil
+ var/reagent_id = /datum/reagent/fuel/oil
var/potency = 2 //how much reagents we add every process (2 seconds)
var/max_volume = 500
var/start_volume = 50
@@ -44,7 +44,7 @@
/obj/structure/geyser/random
erupting_state = null
- var/list/options = list(/datum/reagent/oil = 2, /datum/reagent/clf3 = 1) //fucking add more
+ var/list/options = list(/datum/reagent/fuel/oil = 2, /datum/reagent/clf3 = 1) //fucking add more
/obj/structure/geyser/random/Initialize()
. = ..()
diff --git a/code/game/objects/structures/memorial.dm b/code/game/objects/structures/memorial.dm
index 243a7e3cbae..7c73578dc12 100644
--- a/code/game/objects/structures/memorial.dm
+++ b/code/game/objects/structures/memorial.dm
@@ -18,4 +18,5 @@ This memorial has been designed for him and any future coders to perish.
icon = 'icons/obj/tomb.dmi'
icon_state = "memorial"
density = TRUE
- anchored = TRUE
\ No newline at end of file
+ anchored = TRUE
+ resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | UNACIDABLE | ACID_PROOF
diff --git a/code/game/objects/structures/stairs.dm b/code/game/objects/structures/stairs.dm
index 7086c7900e0..5be219f4486 100644
--- a/code/game/objects/structures/stairs.dm
+++ b/code/game/objects/structures/stairs.dm
@@ -41,7 +41,7 @@
/obj/structure/stairs/Uncross(atom/movable/AM, turf/newloc)
if(!newloc || !AM)
return ..()
- if(isliving(AM) && isTerminator() && (get_dir(src, newloc) == dir))
+ if(!isobserver(AM) && isTerminator() && (get_dir(src, newloc) == dir))
stair_ascend(AM)
return FALSE
return ..()
diff --git a/code/game/objects/structures/table_frames.dm b/code/game/objects/structures/table_frames.dm
index 6a20246b54c..896a3db2af7 100644
--- a/code/game/objects/structures/table_frames.dm
+++ b/code/game/objects/structures/table_frames.dm
@@ -29,7 +29,7 @@
playsound(src.loc, 'sound/items/deconstruct.ogg', 50, TRUE)
deconstruct(TRUE)
return
-
+
var/obj/item/stack/material = I
if (istype(I, /obj/item/stack))
if(material?.tableVariant)
@@ -45,14 +45,14 @@
return
to_chat(user, "You start adding [material] to [src]...")
if(do_after(user, 20, target = src) && material.use(1))
- var/list/material_list
+ var/list/material_list = list()
if(material.material_type)
- material_list = list(material.material_type = MINERAL_MATERIAL_AMOUNT)
+ material_list[material.material_type] = MINERAL_MATERIAL_AMOUNT
make_new_table(/obj/structure/table/greyscale, material_list)
else
return ..()
-/obj/structure/table_frame/proc/make_new_table(table_type, list/custom_materials) //makes sure the new table made retains what we had as a frame
+/obj/structure/table_frame/proc/make_new_table(table_type, custom_materials) //makes sure the new table made retains what we had as a frame
var/obj/structure/table/T = new table_type(loc)
T.frame = type
T.framestack = framestack
@@ -69,10 +69,6 @@
new /obj/structure/table_frame/wood(src.loc)
qdel(src)
-/obj/structure/table_frame/ratvar_act()
- new /obj/structure/table_frame/brass(src.loc)
- qdel(src)
-
/*
* Wooden Frames
*/
@@ -102,40 +98,4 @@
if(do_after(user, 20, target = src) && material.use(1))
make_new_table(toConstruct)
else
- return ..()
-
-/obj/structure/table_frame/brass
- name = "brass table frame"
- desc = "Four pieces of brass arranged in a square. It's slightly warm to the touch."
- icon_state = "brass_frame"
- resistance_flags = FIRE_PROOF | ACID_PROOF
- framestack = /obj/item/stack/tile/brass
- framestackamount = 1
-
-/obj/structure/table_frame/brass/Initialize()
- . = ..()
- change_construction_value(1)
-
-/obj/structure/table_frame/brass/Destroy()
- change_construction_value(-1)
- return ..()
-
-/obj/structure/table_frame/brass/attackby(obj/item/I, mob/user, params)
- if(istype(I, /obj/item/stack/tile/brass))
- var/obj/item/stack/tile/brass/W = I
- if(W.get_amount() < 1)
- to_chat(user, "You need one brass sheet to do this!")
- return
- to_chat(user, "You start adding [W] to [src]...")
- if(do_after(user, 20, target = src) && W.use(1))
- make_new_table(/obj/structure/table/reinforced/brass)
- else
- return ..()
-
-/obj/structure/table_frame/brass/narsie_act()
- ..()
- if(src) //do we still exist?
- var/previouscolor = color
- color = "#960000"
- animate(src, color = previouscolor, time = 8)
- addtimer(CALLBACK(src, /atom/proc/update_atom_colour), 8)
+ return ..()
\ No newline at end of file
diff --git a/code/game/objects/structures/tables_racks.dm b/code/game/objects/structures/tables_racks.dm
index 5927efc50eb..4aec4358656 100644
--- a/code/game/objects/structures/tables_racks.dm
+++ b/code/game/objects/structures/tables_racks.dm
@@ -52,11 +52,6 @@
qdel(src)
new /obj/structure/table/wood(A)
-/obj/structure/table/ratvar_act()
- var/atom/A = loc
- qdel(src)
- new /obj/structure/table/reinforced/brass(A)
-
/obj/structure/table/attack_paw(mob/user)
return attack_hand(user)
@@ -194,7 +189,12 @@
/obj/structure/table/deconstruct(disassembled = TRUE, wrench_disassembly = 0)
if(!(flags_1 & NODECONSTRUCT_1))
var/turf/T = get_turf(src)
- new buildstack(T, buildstackamount)
+ if(buildstack)
+ new buildstack(T, buildstackamount)
+ else
+ for(var/i in custom_materials)
+ var/datum/material/M = i
+ new M.sheet_type(T, FLOOR(custom_materials[M] / MINERAL_MATERIAL_AMOUNT, 1))
if(!wrench_disassembly)
new frame(T)
else
@@ -204,6 +204,7 @@
/obj/structure/table/greyscale
material_flags = MATERIAL_ADD_PREFIX | MATERIAL_COLOR
+ buildstack = null //No buildstack, so generate from mat datums
/*
@@ -427,42 +428,6 @@
else
. = ..()
-/obj/structure/table/reinforced/brass
- name = "brass table"
- desc = "A solid, slightly beveled brass table."
- icon = 'icons/obj/smooth_structures/brass_table.dmi'
- icon_state = "brass_table"
- resistance_flags = FIRE_PROOF | ACID_PROOF
- frame = /obj/structure/table_frame/brass
- framestack = /obj/item/stack/tile/brass
- buildstack = /obj/item/stack/tile/brass
- framestackamount = 1
- buildstackamount = 1
- canSmoothWith = list(/obj/structure/table/reinforced/brass, /obj/structure/table/bronze)
-
-/obj/structure/table/reinforced/brass/Initialize()
- . = ..()
- change_construction_value(2)
-
-/obj/structure/table/reinforced/brass/Destroy()
- change_construction_value(-2)
- return ..()
-
-/obj/structure/table/reinforced/brass/tablepush(mob/living/user, mob/living/pushed_mob)
- .= ..()
- playsound(src, 'sound/magic/clockwork/fellowship_armory.ogg', 50, TRUE)
-
-/obj/structure/table/reinforced/brass/narsie_act()
- take_damage(rand(15, 45), BRUTE)
- if(src) //do we still exist?
- var/previouscolor = color
- color = "#960000"
- animate(src, color = previouscolor, time = 8)
- addtimer(CALLBACK(src, /atom/proc/update_atom_colour), 8)
-
-/obj/structure/table/reinforced/brass/ratvar_act()
- obj_integrity = max_integrity
-
/obj/structure/table/bronze
name = "bronze table"
desc = "A solid table made out of bronze."
@@ -470,7 +435,7 @@
icon_state = "brass_table"
resistance_flags = FIRE_PROOF | ACID_PROOF
buildstack = /obj/item/stack/tile/bronze
- canSmoothWith = list(/obj/structure/table/reinforced/brass, /obj/structure/table/bronze)
+ canSmoothWith = list(/obj/structure/table/bronze)
/obj/structure/table/bronze/tablepush(mob/living/user, mob/living/pushed_mob)
..()
diff --git a/code/game/objects/structures/window.dm b/code/game/objects/structures/window.dm
index 939b69ba242..4d95755c0dd 100644
--- a/code/game/objects/structures/window.dm
+++ b/code/game/objects/structures/window.dm
@@ -84,13 +84,6 @@
/obj/structure/window/narsie_act()
add_atom_colour(NARSIE_WINDOW_COLOUR, FIXED_COLOUR_PRIORITY)
-/obj/structure/window/ratvar_act()
- if(!fulltile)
- new/obj/structure/window/reinforced/clockwork(get_turf(src), dir)
- else
- new/obj/structure/window/reinforced/clockwork/fulltile(get_turf(src))
- qdel(src)
-
/obj/structure/window/singularity_pull(S, current_size)
..()
if(current_size >= STAGE_FIVE)
@@ -717,83 +710,6 @@
anchored = FALSE
state = WINDOW_OUT_OF_FRAME
-/obj/structure/window/reinforced/clockwork
- name = "brass window"
- desc = "A paper-thin pane of translucent yet reinforced brass."
- icon = 'icons/obj/smooth_structures/clockwork_window.dmi'
- icon_state = "clockwork_window_single"
- resistance_flags = FIRE_PROOF | ACID_PROOF
- max_integrity = 80
- armor = list("melee" = 60, "bullet" = 25, "laser" = 0, "energy" = 0, "bomb" = 25, "bio" = 100, "rad" = 100, "fire" = 80, "acid" = 100)
- explosion_block = 2 //fancy AND hard to destroy. the most useful combination.
- decon_speed = 40
- glass_type = /obj/item/stack/tile/brass
- glass_amount = 1
- reinf = FALSE
- var/made_glow = FALSE
-
-/obj/structure/window/reinforced/clockwork/Initialize(mapload, direct)
- . = ..()
- change_construction_value(fulltile ? 2 : 1)
-
-/obj/structure/window/reinforced/clockwork/spawnDebris(location)
- . = list()
- var/gearcount = fulltile ? 4 : 2
- for(var/i in 1 to gearcount)
- . += new /obj/item/clockwork/alloy_shards/medium/gear_bit(location)
-
-/obj/structure/window/reinforced/clockwork/setDir(direct)
- if(!made_glow)
- var/obj/effect/E = new /obj/effect/temp_visual/ratvar/window/single(get_turf(src))
- E.setDir(direct)
- made_glow = TRUE
- ..()
-
-/obj/structure/window/reinforced/clockwork/Destroy()
- change_construction_value(fulltile ? -2 : -1)
- return ..()
-
-/obj/structure/window/reinforced/clockwork/ratvar_act()
- if(GLOB.ratvar_awakens)
- obj_integrity = max_integrity
- update_icon()
-
-/obj/structure/window/reinforced/clockwork/narsie_act()
- take_damage(rand(25, 75), BRUTE)
- if(!QDELETED(src))
- var/previouscolor = color
- color = "#960000"
- animate(src, color = previouscolor, time = 8)
- addtimer(CALLBACK(src, /atom/proc/update_atom_colour), 8)
-
-/obj/structure/window/reinforced/clockwork/unanchored
- anchored = FALSE
-
-/obj/structure/window/reinforced/clockwork/fulltile
- icon_state = "clockwork_window"
- smooth = SMOOTH_TRUE
- canSmoothWith = null
- fulltile = TRUE
- flags_1 = PREVENT_CLICK_UNDER_1
- dir = FULLTILE_WINDOW_DIR
- max_integrity = 120
- level = 3
- glass_amount = 2
-
-/obj/structure/window/reinforced/clockwork/spawnDebris(location)
- . = list()
- for(var/i in 1 to 4)
- . += new /obj/item/clockwork/alloy_shards/medium/gear_bit(location)
-
-/obj/structure/window/reinforced/clockwork/Initialize(mapload, direct)
- made_glow = TRUE
- new /obj/effect/temp_visual/ratvar/window(get_turf(src))
- return ..()
-
-
-/obj/structure/window/reinforced/clockwork/fulltile/unanchored
- anchored = FALSE
-
/obj/structure/window/paperframe
name = "paper frame"
desc = "A fragile separator made of thin wood and paper."
diff --git a/code/game/turfs/open.dm b/code/game/turfs/open.dm
index b991374623f..b43bb025467 100644
--- a/code/game/turfs/open.dm
+++ b/code/game/turfs/open.dm
@@ -133,41 +133,6 @@
blocks_air = TRUE
baseturfs = /turf/open/indestructible/airblock
-/turf/open/indestructible/clock_spawn_room
- name = "cogmetal floor"
- desc = "Brass plating that gently radiates heat. For some reason, it reminds you of blood."
- icon_state = "reebe"
- baseturfs = /turf/open/indestructible/clock_spawn_room
- footstep = FOOTSTEP_PLATING
- barefootstep = FOOTSTEP_HARD_BAREFOOT
- clawfootstep = FOOTSTEP_HARD_CLAW
- heavyfootstep = FOOTSTEP_GENERIC_HEAVY
-
-/turf/open/indestructible/clock_spawn_room/Entered()
- ..()
- START_PROCESSING(SSfastprocess, src)
-
-/turf/open/indestructible/clock_spawn_room/Destroy()
- STOP_PROCESSING(SSfastprocess, src)
- . = ..()
-
-/turf/open/indestructible/clock_spawn_room/process()
- if(!port_servants())
- STOP_PROCESSING(SSfastprocess, src)
-
-/turf/open/indestructible/clock_spawn_room/proc/port_servants()
- . = FALSE
- for(var/mob/living/L in src)
- if(is_servant_of_ratvar(L) && L.stat != DEAD)
- . = TRUE
- L.forceMove(get_turf(pick(GLOB.servant_spawns)))
- visible_message("[L] vanishes in a flash of red!")
- L.visible_message("[L] appears in a flash of red!", \
- "sas'so c'arta forbici You're yanked away from [src]!")
- playsound(src, 'sound/magic/enter_blood.ogg', 50, TRUE)
- playsound(L, 'sound/magic/exit_blood.ogg', 50, TRUE)
- flash_color(L, flash_color = "#C80000", flash_time = 10)
-
/turf/open/Initalize_Atmos(times_fired)
excited = 0
update_visuals()
diff --git a/code/game/turfs/simulated/floor.dm b/code/game/turfs/simulated/floor.dm
index 5a6cbf1e581..0a2e98a2888 100644
--- a/code/game/turfs/simulated/floor.dm
+++ b/code/game/turfs/simulated/floor.dm
@@ -217,11 +217,6 @@
if(.)
ChangeTurf(/turf/open/floor/engine/cult, flags = CHANGETURF_INHERIT_AIR)
-/turf/open/floor/ratvar_act(force, ignore_mobs)
- . = ..()
- if(.)
- ChangeTurf(/turf/open/floor/clockwork, flags = CHANGETURF_INHERIT_AIR)
-
/turf/open/floor/acid_melt()
ScrapeAway(flags = CHANGETURF_INHERIT_AIR)
diff --git a/code/game/turfs/simulated/floor/misc_floor.dm b/code/game/turfs/simulated/floor/misc_floor.dm
index c11f5860fb9..238b036b75b 100644
--- a/code/game/turfs/simulated/floor/misc_floor.dm
+++ b/code/game/turfs/simulated/floor/misc_floor.dm
@@ -134,112 +134,6 @@
icon_state = "floor"
floor_tile = /obj/item/stack/tile/plasteel
-//Clockwork floor: Slowly heals toxin damage on nearby servants.
-/turf/open/floor/clockwork
- name = "clockwork floor"
- desc = "Tightly-pressed brass tiles. They emit minute vibration."
- icon_state = "plating"
- baseturfs = /turf/open/floor/clockwork
- footstep = FOOTSTEP_PLATING
- barefootstep = FOOTSTEP_HARD_BAREFOOT
- clawfootstep = FOOTSTEP_HARD_CLAW
- heavyfootstep = FOOTSTEP_GENERIC_HEAVY
- var/dropped_brass
- var/uses_overlay = TRUE
- var/obj/effect/clockwork/overlay/floor/realappearence
-
-/turf/open/floor/clockwork/Bless() //Who needs holy blessings when you have DADDY RATVAR?
- return
-
-/turf/open/floor/clockwork/Initialize()
- . = ..()
- if(uses_overlay)
- new /obj/effect/temp_visual/ratvar/floor(src)
- new /obj/effect/temp_visual/ratvar/beam(src)
- realappearence = new /obj/effect/clockwork/overlay/floor(src)
- realappearence.linked = src
-
-/turf/open/floor/clockwork/Destroy()
- STOP_PROCESSING(SSobj, src)
- if(uses_overlay && realappearence)
- QDEL_NULL(realappearence)
- return ..()
-
-/turf/open/floor/clockwork/ReplaceWithLattice()
- . = ..()
- for(var/obj/structure/lattice/L in src)
- L.ratvar_act()
-
-/turf/open/floor/clockwork/Entered(atom/movable/AM)
- ..()
- START_PROCESSING(SSobj, src)
-
-/turf/open/floor/clockwork/process()
- if(!healservants())
- STOP_PROCESSING(SSobj, src)
-
-/turf/open/floor/clockwork/proc/healservants()
- for(var/mob/living/L in src)
- if(L.stat == DEAD)
- continue
- . = 1
- if(!is_servant_of_ratvar(L) || !L.toxloss)
- continue
-
- var/image/I = new('icons/effects/effects.dmi', src, "heal", ABOVE_MOB_LAYER) //fake a healing glow for servants
- I.appearance_flags = RESET_COLOR
- I.color = "#5A6068"
- I.pixel_x = rand(-12, 12)
- I.pixel_y = rand(-9, 0)
- var/list/viewing = list()
- for(var/mob/M in viewers(src))
- if(M.client && (is_servant_of_ratvar(M) || isobserver(M) || M.stat == DEAD))
- viewing += M.client
- flick_overlay(I, viewing, 8)
- L.adjustToxLoss(-3, TRUE, TRUE)
-
-/turf/open/floor/clockwork/try_replace_tile(obj/item/stack/tile/T, mob/user, params)
- return
-
-/turf/open/floor/clockwork/crowbar_act(mob/living/user, obj/item/I)
- if(islist(baseturfs))
- if(type in baseturfs)
- return TRUE
- else if(baseturfs == type)
- return TRUE
- user.visible_message("[user] begins slowly prying up [src]...", "You begin painstakingly prying up [src]...")
- if(I.use_tool(src, user, 70, volume=80))
- user.visible_message("[user] pries up [src]!", "You pry up [src]!")
- make_plating()
- return TRUE
-
-/turf/open/floor/clockwork/make_plating()
- if(!dropped_brass)
- new /obj/item/stack/tile/brass(src)
- dropped_brass = TRUE
- if(islist(baseturfs))
- if(type in baseturfs)
- return
- else if(baseturfs == type)
- return
- return ..()
-
-/turf/open/floor/clockwork/narsie_act()
- ..()
- if(istype(src, /turf/open/floor/clockwork)) //if we haven't changed type
- var/previouscolor = color
- color = "#960000"
- animate(src, color = previouscolor, time = 8)
- addtimer(CALLBACK(src, /atom/proc/update_atom_colour), 8)
-
-/turf/open/floor/clockwork/reebe
- name = "cogplate"
- desc = "Warm brass plating. You can feel it gently vibrating, as if machinery is on the other side."
- icon_state = "reebe"
- baseturfs = /turf/open/floor/clockwork/reebe
- uses_overlay = FALSE
- planetary_atmos = TRUE
-
/turf/open/floor/bluespace
slowdown = -1
icon_state = "bluespace"
diff --git a/code/game/turfs/simulated/floor/plating/asteroid.dm b/code/game/turfs/simulated/floor/plating/asteroid.dm
index 0df0d02af7e..9fe9f78a5c0 100644
--- a/code/game/turfs/simulated/floor/plating/asteroid.dm
+++ b/code/game/turfs/simulated/floor/plating/asteroid.dm
@@ -273,12 +273,14 @@ GLOBAL_LIST_INIT(megafauna_spawn_list, list(/mob/living/simple_animal/hostile/me
else //this is not danger, don't spawn a boss, spawn something else
randumb = pickweight(mob_spawn_list)
- for(var/mob/living/simple_animal/hostile/H in urange(12,T)) //prevents mob clumps
- if((ispath(randumb, /mob/living/simple_animal/hostile/megafauna) || ismegafauna(H)) && get_dist(src, H) <= 7)
+ for(var/thing in urange(12, T)) //prevents mob clumps
+ if(!ishostile(thing) && !istype(thing, /obj/structure/spawner))
+ continue
+ if((ispath(randumb, /mob/living/simple_animal/hostile/megafauna) || ismegafauna(thing)) && get_dist(src, thing) <= 7)
return //if there's a megafauna within standard view don't spawn anything at all
- if(ispath(randumb, /mob/living/simple_animal/hostile/asteroid) || istype(H, /mob/living/simple_animal/hostile/asteroid))
+ if(ispath(randumb, /mob/living/simple_animal/hostile/asteroid) || istype(thing, /mob/living/simple_animal/hostile/asteroid))
return //if the random is a standard mob, avoid spawning if there's another one within 12 tiles
- if((ispath(randumb, /obj/structure/spawner/lavaland) || istype(H, /obj/structure/spawner/lavaland)) && get_dist(src, H) <= 2)
+ if((ispath(randumb, /obj/structure/spawner/lavaland) || istype(thing, /obj/structure/spawner/lavaland)) && get_dist(src, thing) <= 2)
return //prevents tendrils spawning in each other's collapse range
if(ispath(randumb, /mob/living/simple_animal/hostile/megafauna/bubblegum)) //there can be only one bubblegum, so don't waste spawns on it
diff --git a/code/game/turfs/simulated/floor/reinf_floor.dm b/code/game/turfs/simulated/floor/reinf_floor.dm
index 70a7153332b..d747e0a54be 100644
--- a/code/game/turfs/simulated/floor/reinf_floor.dm
+++ b/code/game/turfs/simulated/floor/reinf_floor.dm
@@ -129,13 +129,13 @@
desc = "The air smells strange over this sinister flooring."
icon_state = "plating"
floor_tile = null
- var/obj/effect/clockwork/overlay/floor/bloodcult/realappearance
+ var/obj/effect/cult_turf/overlay/floor/bloodcult/realappearance
/turf/open/floor/engine/cult/Initialize()
. = ..()
new /obj/effect/temp_visual/cult/turf/floor(src)
- realappearance = new /obj/effect/clockwork/overlay/floor/bloodcult(src)
+ realappearance = new /obj/effect/cult_turf/overlay/floor/bloodcult(src)
realappearance.linked = src
/turf/open/floor/engine/cult/Destroy()
@@ -151,14 +151,6 @@
qdel(realappearance)
realappearance = null
-/turf/open/floor/engine/cult/ratvar_act()
- . = ..()
- if(istype(src, /turf/open/floor/engine/cult)) //if we haven't changed type
- var/previouscolor = color
- color = "#FAE48C"
- animate(src, color = previouscolor, time = 8)
- addtimer(CALLBACK(src, /atom/proc/update_atom_colour), 8)
-
/turf/open/floor/engine/cult/airless
initial_gas_mix = AIRLESS_ATMOS
diff --git a/code/game/turfs/simulated/reebe_void.dm b/code/game/turfs/simulated/reebe_void.dm
deleted file mode 100644
index 971abec3b45..00000000000
--- a/code/game/turfs/simulated/reebe_void.dm
+++ /dev/null
@@ -1,49 +0,0 @@
-/turf/open/indestructible/reebe_void
- name = "void"
- icon_state = "reebemap"
- layer = SPACE_LAYER
- baseturfs = /turf/open/indestructible/reebe_void
- planetary_atmos = TRUE
- bullet_bounce_sound = null //forever falling
- tiled_dirt = FALSE
-
-/turf/open/indestructible/reebe_void/Initialize(mapload)
- . = ..()
- icon_state = "reebegame"
-
-/turf/open/indestructible/reebe_void/spawning
- icon_state = "reebespawn"
-
-/turf/open/indestructible/reebe_void/spawning/Initialize(mapload)
- . = ..()
- if(mapload)
- for(var/i in 1 to 3)
- if(prob(1))
- new /obj/item/clockwork/alloy_shards/large(src)
- if(prob(2))
- new /obj/item/clockwork/alloy_shards/medium(src)
- if(prob(3))
- new /obj/item/clockwork/alloy_shards/small(src)
-
-/turf/open/indestructible/reebe_void/spawning/lattices
- icon_state = "reebelattice"
-
-/turf/open/indestructible/reebe_void/spawning/lattices/Initialize(mapload)
- . = ..()
- if(mapload)
- if(prob(2.5))
- new /obj/structure/lattice/catwalk/clockwork(src)
- else if(prob(5))
- new /obj/structure/lattice/clockwork(src)
-
-/turf/open/indestructible/reebe_void/Enter(atom/movable/AM, atom/old_loc)
- if(!..())
- return FALSE
- else
- if(istype(AM, /obj/structure/window))
- return FALSE
- if(istype(AM, /obj/projectile))
- return TRUE
- if((locate(/obj/structure/lattice) in src))
- return TRUE
- return FALSE
diff --git a/code/game/turfs/simulated/wall/misc_walls.dm b/code/game/turfs/simulated/wall/misc_walls.dm
index a2f3fcc51fc..8fda116a7d1 100644
--- a/code/game/turfs/simulated/wall/misc_walls.dm
+++ b/code/game/turfs/simulated/wall/misc_walls.dm
@@ -26,14 +26,6 @@
stored_pulling.forceMove(src)
H.start_pulling(stored_pulling, supress_message = TRUE)
-/turf/closed/wall/mineral/cult/ratvar_act()
- . = ..()
- if(istype(src, /turf/closed/wall/mineral/cult)) //if we haven't changed type
- var/previouscolor = color
- color = "#FAE48C"
- animate(src, color = previouscolor, time = 8)
- addtimer(CALLBACK(src, /atom/proc/update_atom_colour), 8)
-
/turf/closed/wall/mineral/cult/artificer
name = "runed stone wall"
desc = "A cold stone wall engraved with indecipherable symbols. Studying them causes your head to pound."
@@ -45,109 +37,6 @@
/turf/closed/wall/mineral/cult/artificer/devastate_wall()
new /obj/effect/temp_visual/cult/turf(get_turf(src))
-//Clockwork wall: Causes nearby tinkerer's caches to generate components.
-/turf/closed/wall/clockwork
- name = "clockwork wall"
- desc = "A huge chunk of warm metal. The clanging of machinery emanates from within."
- explosion_block = 2
- hardness = 10
- slicing_duration = 80
- sheet_type = /obj/item/stack/tile/brass
- sheet_amount = 1
- girder_type = /obj/structure/destructible/clockwork/wall_gear
- baseturfs = /turf/open/floor/clockwork/reebe
- var/heated
- var/obj/effect/clockwork/overlay/wall/realappearance
-
-/turf/closed/wall/clockwork/Initialize()
- . = ..()
- new /obj/effect/temp_visual/ratvar/wall(src)
- new /obj/effect/temp_visual/ratvar/beam(src)
- realappearance = new /obj/effect/clockwork/overlay/wall(src)
- realappearance.linked = src
-
-/turf/closed/wall/clockwork/Destroy()
- if(realappearance)
- qdel(realappearance)
- realappearance = null
- if(heated)
- var/mob/camera/eminence/E = get_eminence()
- if(E)
- E.superheated_walls--
-
- return ..()
-
-/turf/closed/wall/clockwork/ReplaceWithLattice()
- ..()
- for(var/obj/structure/lattice/L in src)
- L.ratvar_act()
-
-/turf/closed/wall/clockwork/narsie_act()
- ..()
- if(istype(src, /turf/closed/wall/clockwork)) //if we haven't changed type
- var/previouscolor = color
- color = "#960000"
- animate(src, color = previouscolor, time = 8)
- addtimer(CALLBACK(src, /atom/proc/update_atom_colour), 8)
-
-/turf/closed/wall/clockwork/dismantle_wall(devastated=0, explode=0)
- if(devastated)
- devastate_wall()
- ScrapeAway()
- else
- playsound(src, 'sound/items/welder.ogg', 100, TRUE)
- var/newgirder = break_wall()
- if(newgirder) //maybe we want a gear!
- transfer_fingerprints_to(newgirder)
- ScrapeAway()
-
- for(var/obj/O in src) //Eject contents!
- if(istype(O, /obj/structure/sign/poster))
- var/obj/structure/sign/poster/P = O
- P.roll_and_drop(src)
- else
- O.forceMove(src)
-
-/turf/closed/wall/clockwork/devastate_wall()
- for(var/i in 1 to 2)
- new/obj/item/clockwork/alloy_shards/large(src)
- for(var/i in 1 to 2)
- new/obj/item/clockwork/alloy_shards/medium(src)
- for(var/i in 1 to 3)
- new/obj/item/clockwork/alloy_shards/small(src)
-
-/turf/closed/wall/clockwork/attack_hulk(mob/living/user)
- . = ..()
- if(!heated)
- return
- to_chat(user, "The wall is searing hot to the touch!")
- user.adjustFireLoss(5)
- playsound(src, 'sound/machines/fryer/deep_fryer_emerge.ogg', 50, TRUE)
-
-/turf/closed/wall/clockwork/mech_melee_attack(obj/mecha/M)
- ..()
- if(heated)
- to_chat(M.occupant, "The wall's intense heat completely reflects your [M.name]'s attack!")
- M.take_damage(20, BURN)
-
-/turf/closed/wall/clockwork/proc/turn_up_the_heat()
- if(!heated)
- name = "superheated [name]"
- visible_message("[src] sizzles with heat!")
- playsound(src, 'sound/machines/fryer/deep_fryer_emerge.ogg', 50, TRUE)
- heated = TRUE
- hardness = -100 //Lower numbers are tougher, so this makes the wall essentially impervious to smashing
- slicing_duration = 150
- animate(realappearance, color = "#FFC3C3", time = 5)
- else
- name = initial(name)
- visible_message("[src] cools down.")
- heated = FALSE
- hardness = initial(hardness)
- slicing_duration = initial(slicing_duration)
- animate(realappearance, color = initial(realappearance.color), time = 25)
-
-
/turf/closed/wall/vault
icon = 'icons/turf/walls.dmi'
icon_state = "rockvault"
diff --git a/code/game/turfs/simulated/walls.dm b/code/game/turfs/simulated/walls.dm
index c7550232859..abded37b539 100644
--- a/code/game/turfs/simulated/walls.dm
+++ b/code/game/turfs/simulated/walls.dm
@@ -22,11 +22,9 @@
/turf/closed/wall,
/turf/closed/wall/r_wall,
/obj/structure/falsewall,
- /obj/structure/falsewall/brass,
/obj/structure/falsewall/reinforced,
/turf/closed/wall/rust,
- /turf/closed/wall/r_wall/rust,
- /turf/closed/wall/clockwork)
+ /turf/closed/wall/r_wall/rust)
smooth = SMOOTH_TRUE
var/list/dent_decals
@@ -243,11 +241,6 @@
if(.)
ChangeTurf(/turf/closed/wall/mineral/cult)
-/turf/closed/wall/ratvar_act(force, ignore_mobs)
- . = ..()
- if(.)
- ChangeTurf(/turf/closed/wall/clockwork)
-
/turf/closed/wall/get_dumping_location(obj/item/storage/source, mob/user)
return null
diff --git a/code/game/turfs/turf.dm b/code/game/turfs/turf.dm
index 4c23def7ac5..983a9c23463 100755
--- a/code/game/turfs/turf.dm
+++ b/code/game/turfs/turf.dm
@@ -456,15 +456,6 @@
if(ismob(A) || .)
A.narsie_act()
-/turf/ratvar_act(force, ignore_mobs, probability = 40)
- . = (prob(probability) || force)
- for(var/I in src)
- var/atom/A = I
- if(ignore_mobs && ismob(A))
- continue
- if(ismob(A) || .)
- A.ratvar_act()
-
/turf/proc/get_smooth_underlay_icon(mutable_appearance/underlay_appearance, turf/asking_turf, adjacency_dir)
underlay_appearance.icon = icon
underlay_appearance.icon_state = icon_state
diff --git a/code/game/world.dm b/code/game/world.dm
index 8d5bc0c82ba..6000b24fc62 100644
--- a/code/game/world.dm
+++ b/code/game/world.dm
@@ -130,6 +130,7 @@ GLOBAL_VAR(restart_counter)
GLOB.query_debug_log = "[GLOB.log_directory]/query_debug.log"
GLOB.world_job_debug_log = "[GLOB.log_directory]/job_debug.log"
GLOB.world_paper_log = "[GLOB.log_directory]/paper.log"
+ GLOB.tgui_log = "[GLOB.log_directory]/tgui.log"
#ifdef UNIT_TESTS
GLOB.test_log = file("[GLOB.log_directory]/tests.log")
@@ -144,6 +145,7 @@ GLOBAL_VAR(restart_counter)
start_log(GLOB.world_qdel_log)
start_log(GLOB.world_runtime_log)
start_log(GLOB.world_job_debug_log)
+ start_log(GLOB.tgui_log)
GLOB.changelog_hash = md5('html/changelog.html') //for telling if the changelog has changed recently
if(fexists(GLOB.config_error_log))
diff --git a/code/modules/admin/secrets.dm b/code/modules/admin/secrets.dm
index ef5ab2ff5d9..d7d1cd9e17e 100644
--- a/code/modules/admin/secrets.dm
+++ b/code/modules/admin/secrets.dm
@@ -727,7 +727,7 @@
E.processing = FALSE
if(E.announceWhen>0)
if(alert(usr, "Would you like to alert the crew?", "Alert", "Yes", "No") == "No")
- E.announceWhen = -1
+ E.announceChance = 0
E.processing = TRUE
if (usr)
log_admin("[key_name(usr)] used secret [item]")
diff --git a/code/modules/admin/sql_ban_system.dm b/code/modules/admin/sql_ban_system.dm
index 6df364ea019..cabc554bba1 100644
--- a/code/modules/admin/sql_ban_system.dm
+++ b/code/modules/admin/sql_ban_system.dm
@@ -259,7 +259,7 @@
ROLE_DEVIL, ROLE_INTERNAL_AFFAIRS, ROLE_MALF,
ROLE_MONKEY, ROLE_NINJA, ROLE_OPERATIVE,
ROLE_OVERTHROW, ROLE_REV, ROLE_REVENANT,
- ROLE_REV_HEAD, ROLE_SERVANT_OF_RATVAR, ROLE_SYNDICATE,
+ ROLE_REV_HEAD, ROLE_SYNDICATE,
ROLE_TRAITOR, ROLE_WIZARD, ROLE_HIVE)) //ROLE_REV_HEAD is excluded from this because rev jobbans are handled by ROLE_REV
for(var/department in long_job_lists)
output += "
"
diff --git a/code/modules/admin/topic.dm b/code/modules/admin/topic.dm
index c32840a49dd..51e3fd3c8c7 100644
--- a/code/modules/admin/topic.dm
+++ b/code/modules/admin/topic.dm
@@ -147,13 +147,6 @@
else
message_admins("[key_name_admin(usr)] tried to create an abductor team. Unfortunatly there were not enough candidates available.")
log_admin("[key_name(usr)] failed to create an abductor team.")
- if("clockcult")
- if(src.makeClockCult())
- message_admins("[key_name(usr)] started a clockwork cult.")
- log_admin("[key_name(usr)] started a clockwork cult.")
- else
- message_admins("[key_name_admin(usr)] tried to start a clockwork cult. Unfortunately, there were no candidates available.")
- log_admin("[key_name(usr)] failed to start a clockwork cult.")
if("revenant")
if(src.makeRevenant())
message_admins("[key_name(usr)] created a revenant.")
@@ -173,11 +166,13 @@
event.processing = FALSE
var/prompt = alert(usr, "Would you like to alert the crew?", "Alert", "Yes", "No", "Cancel")
switch(prompt)
+ if("Yes")
+ event.announceChance = 100
if("Cancel")
event.kill()
return
if("No")
- event.announceWhen = -1
+ event.announceChance = 0
event.processing = TRUE
message_admins("[key_name_admin(usr)] has triggered an event. ([E.name])")
log_admin("[key_name(usr)] has triggered an event. ([E.name])")
@@ -620,7 +615,7 @@
log_admin("[key_name(usr)] set [added_rule] to be a forced roundstart ruleset.")
message_admins("[key_name(usr)] set [added_rule] to be a forced roundstart ruleset.", 1)
Game()
-
+
else if(href_list["f_dynamic_roundstart_clear"])
if(!check_rights(R_ADMIN))
return
@@ -628,7 +623,7 @@
Game()
log_admin("[key_name(usr)] cleared the rigged roundstart rulesets. The mode will pick them as normal.")
message_admins("[key_name(usr)] cleared the rigged roundstart rulesets. The mode will pick them as normal.", 1)
-
+
else if(href_list["f_dynamic_roundstart_remove"])
if(!check_rights(R_ADMIN))
return
@@ -656,7 +651,7 @@
log_admin("[key_name(usr)] set [added_rule] to proc on the next latejoin.")
message_admins("[key_name(usr)] set [added_rule] to proc on the next latejoin.", 1)
Game()
-
+
else if(href_list["f_dynamic_latejoin_clear"])
if(!check_rights(R_ADMIN))
return
@@ -666,7 +661,7 @@
Game()
log_admin("[key_name(usr)] cleared the forced latejoin ruleset.")
message_admins("[key_name(usr)] cleared the forced latejoin ruleset.", 1)
-
+
else if(href_list["f_dynamic_midround"])
if(!check_rights(R_ADMIN))
return
@@ -707,12 +702,12 @@
var/new_centre = input(usr,"Change the centre of the dynamic mode threat curve. A negative value will give a more peaceful round ; a positive value, a round with higher threat. Any number between -5 and +5 is allowed.", "Change curve centre", null) as num
if (new_centre < -5 || new_centre > 5)
return alert(usr, "Only values between -5 and +5 are allowed.", null, null, null, null)
-
+
log_admin("[key_name(usr)] changed the distribution curve center to [new_centre].")
message_admins("[key_name(usr)] changed the distribution curve center to [new_centre]", 1)
GLOB.dynamic_curve_centre = new_centre
dynamic_mode_options(usr)
-
+
else if(href_list["f_dynamic_roundstart_width"])
if(!check_rights(R_ADMIN))
return
@@ -724,7 +719,7 @@
var/new_width = input(usr,"Change the width of the dynamic mode threat curve. A higher value will favour extreme rounds ; a lower value, a round closer to the average. Any Number between 0.5 and 4 are allowed.", "Change curve width", null) as num
if (new_width < 0.5 || new_width > 4)
return alert(usr, "Only values between 0.5 and +2.5 are allowed.", null, null, null, null)
-
+
log_admin("[key_name(usr)] changed the distribution curve width to [new_width].")
message_admins("[key_name(usr)] changed the distribution curve width to [new_width]", 1)
GLOB.dynamic_curve_width = new_width
@@ -848,7 +843,7 @@
GLOB.dynamic_stacking_limit = input(usr,"Change the threat limit at which round-endings rulesets will start to stack.", "Change stacking limit", null) as num
log_admin("[key_name(usr)] set 'stacking_limit' to [GLOB.dynamic_stacking_limit].")
message_admins("[key_name(usr)] set 'stacking_limit' to [GLOB.dynamic_stacking_limit].")
- dynamic_mode_options(usr)
+ dynamic_mode_options(usr)
else if(href_list["f_dynamic_high_pop_limit"])
if(!check_rights(R_ADMIN))
@@ -867,8 +862,8 @@
log_admin("[key_name(usr)] set 'high_pop_limit' to [GLOB.dynamic_high_pop_limit].")
message_admins("[key_name(usr)] set 'high_pop_limit' to [GLOB.dynamic_high_pop_limit].")
- dynamic_mode_options(usr)
-
+ dynamic_mode_options(usr)
+
else if(href_list["f_dynamic_forced_threat"])
if(!check_rights(R_ADMIN))
return
@@ -886,7 +881,7 @@
log_admin("[key_name(usr)] set 'forced_threat_level' to [GLOB.dynamic_forced_threat_level].")
message_admins("[key_name(usr)] set 'forced_threat_level' to [GLOB.dynamic_forced_threat_level].")
- dynamic_mode_options(usr)
+ dynamic_mode_options(usr)
else if(href_list["c_mode2"])
if(!check_rights(R_ADMIN|R_SERVER))
diff --git a/code/modules/admin/verbs/one_click_antag.dm b/code/modules/admin/verbs/one_click_antag.dm
index 5c9f8af8b3f..c9ff5e0b4dc 100644
--- a/code/modules/admin/verbs/one_click_antag.dm
+++ b/code/modules/admin/verbs/one_click_antag.dm
@@ -15,7 +15,6 @@
Make Changelings Make Revs Make Cult
- Make Clockwork Cult Make Blob Make Wizard (Requires Ghosts) Make Nuke Team (Requires Ghosts)
@@ -176,41 +175,6 @@
return 0
-/datum/admins/proc/makeClockCult()
- var/datum/game_mode/clockwork_cult/temp = new
- if(CONFIG_GET(flag/protect_roles_from_antagonist))
- temp.restricted_jobs += temp.protected_jobs
-
- if(CONFIG_GET(flag/protect_assistant_from_antagonist))
- temp.restricted_jobs += "Assistant"
-
- var/list/mob/living/carbon/human/candidates = list()
- var/mob/living/carbon/human/H = null
-
- for(var/mob/living/carbon/human/applicant in GLOB.player_list)
- if(isReadytoRumble(applicant, ROLE_SERVANT_OF_RATVAR))
- if(temp.age_check(applicant.client))
- if(!(applicant.job in temp.restricted_jobs))
- candidates += applicant
-
- if(candidates.len)
- var/numCultists = min(candidates.len, 4)
-
- for(var/i = 0, iThe world before you suddenly glows a brilliant yellow. You hear the whooshing steam and clanking cogs of a billion billion machines, and all at once \
- you see the truth. Ratvar, the Clockwork Justiciar, lies derelict and forgotten in an unseen realm, and he has selected you as one of his harbringers. You are now a servant of \
- Ratvar, and you will bring him back.")
- H.playsound_local(get_turf(H), 'sound/ambience/antag/clockcultalr.ogg', 100, FALSE, pressure_affected = FALSE)
- add_servant_of_ratvar(H, TRUE)
- SSticker.mode.equip_servant(H)
- candidates.Remove(H)
-
- return 1
-
- return 0
-
-
/datum/admins/proc/makeNukeTeam()
var/datum/game_mode/nuclear/temp = new
diff --git a/code/modules/admin/verbs/randomverbs.dm b/code/modules/admin/verbs/randomverbs.dm
index 0182933d49f..d584078d51d 100644
--- a/code/modules/admin/verbs/randomverbs.dm
+++ b/code/modules/admin/verbs/randomverbs.dm
@@ -517,10 +517,10 @@ Traitors and the like can also be revived with the previous role mostly intact.
message_admins("Admin [key_name_admin(usr)] has added a new AI law - [input]")
var/show_log = alert(src, "Show ion message?", "Message", "Yes", "No")
- var/announce_ion_laws = (show_log == "Yes" ? 1 : -1)
+ var/announce_ion_laws = (show_log == "Yes" ? 100 : 0)
var/datum/round_event/ion_storm/add_law_only/ion = new()
- ion.announceEvent = announce_ion_laws
+ ion.announceChance = announce_ion_laws
ion.ionMessage = input
SSblackbox.record_feedback("tally", "admin_verb", 1, "Add Custom AI Law") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
diff --git a/code/modules/antagonists/clockcult/clock_effect.dm b/code/modules/antagonists/clockcult/clock_effect.dm
deleted file mode 100644
index 8e3a8f4ceb0..00000000000
--- a/code/modules/antagonists/clockcult/clock_effect.dm
+++ /dev/null
@@ -1,25 +0,0 @@
-//The base clockwork effect. Can have an alternate desc and will show up in the list of clockwork objects.
-/obj/effect/clockwork
- name = "meme machine"
- desc = "Still don't know what it is."
- var/clockwork_desc = "A fabled artifact from beyond the stars. Contains concentrated meme essence." //Shown to clockwork cultists instead of the normal description
- icon = 'icons/effects/clockwork_effects.dmi'
- icon_state = "ratvars_flame"
- anchored = TRUE
- density = FALSE
- opacity = 0
- resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | UNACIDABLE | ACID_PROOF | FREEZE_PROOF
-
-/obj/effect/clockwork/Initialize()
- . = ..()
- GLOB.all_clockwork_objects += src
-
-/obj/effect/clockwork/Destroy()
- GLOB.all_clockwork_objects -= src
- return ..()
-
-/obj/effect/clockwork/examine(mob/user)
- if((is_servant_of_ratvar(user) || isobserver(user)) && clockwork_desc)
- desc = clockwork_desc
- . = ..()
- desc = initial(desc)
diff --git a/code/modules/antagonists/clockcult/clock_effects/city_of_cogs_rift.dm b/code/modules/antagonists/clockcult/clock_effects/city_of_cogs_rift.dm
deleted file mode 100644
index 21d0035ef15..00000000000
--- a/code/modules/antagonists/clockcult/clock_effects/city_of_cogs_rift.dm
+++ /dev/null
@@ -1,77 +0,0 @@
-//These spawn across the station when the Ark activates. Anyone can walk through one to teleport to Reebe.
-/obj/effect/clockwork/city_of_cogs_rift
- name = "celestial rift"
- desc = "A stable bluespace rip. You're not sure it where leads."
- clockwork_desc = "A one-way rift to the City of Cogs. Because it's linked to the Ark, it can't be closed."
- icon_state = "city_of_cogs_rift"
- resistance_flags = INDESTRUCTIBLE
- density = TRUE
- light_range = 2
- light_power = 3
- light_color = "#6A4D2F"
-
-/obj/effect/clockwork/city_of_cogs_rift/singularity_act()
- return
-
-/obj/effect/clockwork/city_of_cogs_rift/singularity_pull()
- return
-
-/obj/effect/clockwork/city_of_cogs_rift/Initialize()
- . = ..()
- visible_message("The air above [loc] shimmers and pops as a [name] forms there!")
- for(var/mob/M in GLOB.player_list)
- if(M.z == z)
- if(get_dist(src, M) >= 7)
- M.playsound_local(src, 'sound/magic/blink.ogg', 10, FALSE, falloff = 10)
- else
- M.playsound_local(src, 'sound/magic/blink.ogg', 50, FALSE)
-
-/obj/effect/clockwork/city_of_cogs_rift/Destroy()
- visible_message("[src] cracks as it destabilizes and breaks apart!")
- return ..()
-
-/obj/effect/clockwork/city_of_cogs_rift/attackby(obj/item/I, mob/living/user, params)
- if(istype(I, /obj/item/nullrod))
- to_chat(user, "Your [I.name] seems to have no effect on [src]!")
- return
- . = ..()
-
-//ATTACK HAND IGNORING PARENT RETURN VALUE
-/obj/effect/clockwork/city_of_cogs_rift/attack_hand(atom/movable/AM)
- beckon(AM)
-
-/obj/effect/clockwork/city_of_cogs_rift/Bumped(atom/movable/AM)
- if(!QDELETED(AM))
- if(isliving(AM))
- var/mob/living/L = AM
- if(L.client && !L.incapacitated())
- L.visible_message("[L] starts climbing through [src]...", \
- "You begin climbing through [src]...")
- if(!do_after(L, 30, target = L))
- return
- if(!istype(AM, /obj/effect/))
- beckon(AM)
-
-/obj/effect/clockwork/city_of_cogs_rift/proc/beckon(atom/movable/AM)
- var/turf/T = get_turf(pick(GLOB.city_of_cogs_spawns))
- if(ismob(AM) && is_servant_of_ratvar(AM))
- T = GLOB.ark_of_the_clockwork_justiciar ? get_step(GLOB.ark_of_the_clockwork_justiciar, SOUTH) : get_turf(pick(GLOB.servant_spawns))
- else // Handle mechas and such
- var/list/target_contents = AM.GetAllContents() + AM
- for(var/mob/living/L in target_contents)
- if(is_servant_of_ratvar(L) && L.stat != DEAD) // Having a living cultist in your inventory sends you to the cultist spawn
- T = GLOB.ark_of_the_clockwork_justiciar ? get_step(GLOB.ark_of_the_clockwork_justiciar, SOUTH) : get_turf(pick(GLOB.servant_spawns))
- break
- AM.visible_message("[AM] passes through [src]!", null, null, null, AM)
- AM.forceMove(T)
- AM.visible_message("[AM] materializes from the air!", \
- "You pass through [src] and appear [is_servant_of_ratvar(AM) ? "back at the City of Cogs" : "somewhere unfamiliar. Looks like it was a one-way trip.."].")
- do_sparks(5, TRUE, src)
- do_sparks(5, TRUE, AM)
- if(isliving(AM))
- var/mob/living/L = AM
- L.overlay_fullscreen("flash", /obj/screen/fullscreen/flash/static)
- L.clear_fullscreen("flash", 5)
- var/obj/item/transfer_valve/TTV = locate() in L.GetAllContents()
- if(TTV)
- to_chat(L, "The air resonates with the Ark's presence; your explosives will be significantly dampened here!")
diff --git a/code/modules/antagonists/clockcult/clock_effects/clock_overlay.dm b/code/modules/antagonists/clockcult/clock_effects/clock_overlay.dm
deleted file mode 100644
index 6db383488b9..00000000000
--- a/code/modules/antagonists/clockcult/clock_effects/clock_overlay.dm
+++ /dev/null
@@ -1,52 +0,0 @@
-//an "overlay" used by clockwork walls and floors to appear normal to mesons.
-/obj/effect/clockwork/overlay
- mouse_opacity = MOUSE_OPACITY_TRANSPARENT
- var/atom/linked
-
-/obj/effect/clockwork/overlay/examine(mob/user)
- if(linked)
- return linked.examine(user)
- else
- return ..()
-
-/obj/effect/clockwork/overlay/ex_act()
- return FALSE
-
-/obj/effect/clockwork/overlay/singularity_act()
- return
-/obj/effect/clockwork/overlay/singularity_pull()
- return
-
-/obj/effect/clockwork/overlay/singularity_pull(S, current_size)
- return
-
-/obj/effect/clockwork/overlay/Destroy()
- if(linked)
- linked = null
- . = ..()
-
-/obj/effect/clockwork/overlay/wall
- name = "clockwork wall"
- icon = 'icons/turf/walls/clockwork_wall.dmi'
- icon_state = "clockwork_wall"
- canSmoothWith = list(/obj/effect/clockwork/overlay/wall, /obj/structure/falsewall/brass)
- smooth = SMOOTH_TRUE
- layer = CLOSED_TURF_LAYER
-
-/obj/effect/clockwork/overlay/wall/Initialize()
- . = ..()
- queue_smooth_neighbors(src)
- addtimer(CALLBACK(GLOBAL_PROC, .proc/queue_smooth, src), 1)
-
-/obj/effect/clockwork/overlay/wall/Destroy()
- queue_smooth_neighbors(src)
- return ..()
-
-/obj/effect/clockwork/overlay/floor
- icon = 'icons/turf/floors.dmi'
- icon_state = "clockwork_floor"
- layer = TURF_LAYER
- plane = FLOOR_PLANE
-
-/obj/effect/clockwork/overlay/floor/bloodcult //this is used by BLOOD CULT, it shouldn't use such a path...
- icon_state = "cult"
diff --git a/code/modules/antagonists/clockcult/clock_effects/clock_sigils.dm b/code/modules/antagonists/clockcult/clock_effects/clock_sigils.dm
deleted file mode 100644
index 78e9f10b3a6..00000000000
--- a/code/modules/antagonists/clockcult/clock_effects/clock_sigils.dm
+++ /dev/null
@@ -1,376 +0,0 @@
-//Sigils: Rune-like markings on the ground with various effects.
-/obj/effect/clockwork/sigil
- name = "sigil"
- desc = "A strange set of markings drawn on the ground."
- clockwork_desc = "A sigil of some purpose."
- icon_state = "sigil"
- layer = LOW_OBJ_LAYER
- alpha = 50
- resistance_flags = NONE
- var/affects_servants = FALSE
- var/stat_affected = CONSCIOUS
- var/sigil_name = "Sigil"
- var/resist_string = "glows blinding white" //string for when a null rod blocks its effects, "glows [resist_string]"
- var/check_antimagic = TRUE
- var/check_holy = FALSE
-
-/obj/effect/clockwork/sigil/attackby(obj/item/I, mob/living/user, params)
- if(I.force)
- if(is_servant_of_ratvar(user) && user.a_intent != INTENT_HARM)
- return ..()
- user.visible_message("[user] scatters [src] with [I]!", "You scatter [src] with [I]!")
- qdel(src)
- return 1
- return ..()
-
-/obj/effect/clockwork/sigil/attack_tk(mob/user)
- return //you can't tk stomp sigils, but you can hit them with something
-
-//ATTACK HAND IGNORING PARENT RETURN VALUE
-/obj/effect/clockwork/sigil/attack_hand(mob/user)
- if(iscarbon(user) && !user.stat)
- if(is_servant_of_ratvar(user) && user.a_intent != INTENT_HARM)
- return ..()
- user.visible_message("[user] stamps out [src]!", "You stomp on [src], scattering it into thousands of particles.")
- qdel(src)
- return TRUE
- . = ..()
-
-/obj/effect/clockwork/sigil/ex_act(severity)
- visible_message("[src] scatters into thousands of particles.")
- qdel(src)
-
-/obj/effect/clockwork/sigil/Crossed(atom/movable/AM)
- ..()
- if(isliving(AM))
- var/mob/living/L = AM
- if(L.stat <= stat_affected)
- if((!is_servant_of_ratvar(L) || (affects_servants && is_servant_of_ratvar(L))) && (L.mind || L.has_status_effect(STATUS_EFFECT_SIGILMARK)) && !isdrone(L))
- var/atom/I = L.anti_magic_check(check_antimagic, check_holy)
- if(I)
- if(isitem(I))
- L.visible_message("[L]'s [I.name] [resist_string], protecting [L.p_them()] from [src]'s effects!", \
- "Your [I.name] [resist_string], protecting you!")
- return
- sigil_effects(L)
-
-/obj/effect/clockwork/sigil/proc/sigil_effects(mob/living/L)
-
-
-//Sigil of Transgression: Stuns the first non-servant to walk on it and flashes all nearby non_servants. Nar'Sian cultists are damaged and knocked down for a longer time
-/obj/effect/clockwork/sigil/transgression
- name = "dull sigil"
- desc = "A dull, barely-visible golden sigil. It's as though light was carved into the ground."
- icon = 'icons/effects/clockwork_effects.dmi'
- clockwork_desc = "A sigil that will stun the next non-Servant to cross it."
- icon_state = "sigildull"
- layer = HIGH_SIGIL_LAYER
- alpha = 75
- color = "#FAE48C"
- light_range = 1.4
- light_power = 1
- light_color = "#FAE48C"
- sigil_name = "Sigil of Transgression"
-
-/obj/effect/clockwork/sigil/transgression/sigil_effects(mob/living/L)
- var/target_flashed = L.flash_act()
- for(var/mob/living/M in viewers(5, src))
- if(!is_servant_of_ratvar(M) && M != L)
- M.flash_act()
- if(iscultist(L))
- to_chat(L, "\"Watch your step, wretch.\"")
- L.adjustBruteLoss(10)
- L.Paralyze(80, FALSE)
- L.visible_message("[src] appears around [L] in a burst of light!", \
- "[target_flashed ? "An unseen force":"The glowing sigil around you"] holds you in place!")
- L.Stun(40)
- L.apply_status_effect(STATUS_EFFECT_BELLIGERENT)
- new /obj/effect/temp_visual/ratvar/sigil/transgression(get_turf(src))
- qdel(src)
-
-
-//Sigil of Submission: After a short time, converts any non-servant standing on it. Knocks down and silences them for five seconds afterwards.
-/obj/effect/clockwork/sigil/submission
- name = "ominous sigil"
- desc = "A luminous golden sigil. Something about it really bothers you."
- clockwork_desc = "A sigil that will enslave any non-Servant that remains on it for 8 seconds. Cannot penetrate mindshield implants."
- icon_state = "sigilsubmission"
- layer = LOW_SIGIL_LAYER
- alpha = 125
- color = "#FAE48C"
- light_range = 2 //soft light
- light_power = 0.9
- light_color = "#FAE48C"
- stat_affected = UNCONSCIOUS
- resist_string = "glows faintly yellow"
- var/convert_time = 80
- var/delete_on_finish = TRUE
- sigil_name = "Sigil of Submission"
- var/glow_type = /obj/effect/temp_visual/ratvar/sigil/submission
-
-/obj/effect/clockwork/sigil/submission/sigil_effects(mob/living/L)
- var/turf/T = get_turf(src)
- var/has_sigil = FALSE
- var/has_servant = FALSE
- if(locate(/obj/effect/clockwork/sigil/transgression) in T)
- has_sigil = TRUE
- for(var/mob/living/M in range(3, src))
- if(is_servant_of_ratvar(M) && !M.stat)
- has_servant = TRUE
- if(!has_sigil && !has_servant)
- visible_message("[src] strains into a gentle violet color, but quietly fades...")
- return
- L.visible_message("[src] begins to glow a piercing magenta!", "You feel something start to invade your mind...")
- var/oldcolor = color
- animate(src, color = "#AF0AAF", time = convert_time, flags = ANIMATION_END_NOW)
- var/obj/effect/temp_visual/ratvar/sigil/glow
- if(glow_type)
- glow = new glow_type(get_turf(src))
- animate(glow, alpha = 255, time = convert_time)
- var/end_time = world.time+convert_time
- while(world.time < end_time && get_turf(L) == get_turf(src))
- stoplag(1)
- if(get_turf(L) != get_turf(src))
- if(glow)
- qdel(glow)
- animate(src, color = oldcolor, time = 20, flags = ANIMATION_END_NOW)
- addtimer(CALLBACK(src, /atom/proc/update_atom_colour), 20)
- visible_message("[src] slowly stops glowing!")
- return
- if(is_eligible_servant(L))
- to_chat(L, "\"You belong to me now.\"")
- if(!GLOB.application_scripture_unlocked)
- GLOB.application_scripture_unlocked = TRUE
- hierophant_message("With the conversion of a new servant the Ark's power grows. Application scriptures are now available.")
- if(add_servant_of_ratvar(L))
- L.log_message("conversion was done with a [sigil_name]", LOG_ATTACK, color="BE8700")
- if(iscarbon(L))
- var/mob/living/carbon/M = L
- M.uncuff()
- L.Paralyze(50) //Completely defenseless for five seconds - mainly to give them time to read over the information they've just been presented with
- if(iscarbon(L))
- var/mob/living/carbon/C = L
- C.silent += 5
- var/message = "[sigil_name] in [get_area(src)] [is_servant_of_ratvar(L) ? "successfully converted" : "failed to convert"]"
- for(var/M in GLOB.mob_list)
- if(isobserver(M))
- var/link = FOLLOW_LINK(M, L)
- to_chat(M, "[link] [message] [L.real_name]!")
- else if(is_servant_of_ratvar(M))
- if(M == L)
- to_chat(M, "[message] you!")
- else
- to_chat(M, "[message] [L.real_name]!")
- animate(src, color = oldcolor, time = 20, flags = ANIMATION_END_NOW)
- addtimer(CALLBACK(src, /atom/proc/update_atom_colour), 20)
- visible_message("[src] slowly stops glowing!")
-
-
-//Sigil of Transmission: Serves as an access point for powered structures.
-/obj/effect/clockwork/sigil/transmission
- name = "suspicious sigil"
- desc = "A glowing orange sigil. The air around it feels staticky."
- clockwork_desc = "A sigil that serves as power generation and a battery for clockwork structures, linked to all other sigils of its type."
- icon_state = "sigiltransmission"
- alpha = 50
- color = "#EC8A2D"
- light_color = "#EC8A2D"
- resist_string = "glows faintly"
- sigil_name = "Sigil of Transmission"
- affects_servants = TRUE
-
-/obj/effect/clockwork/sigil/transmission/Initialize()
- . = ..()
- update_icon()
-
-/obj/effect/clockwork/sigil/transmission/ex_act(severity)
- if(severity == 3)
- adjust_clockwork_power(500) //Light explosions charge the network!
- visible_message("[src] flares a brilliant orange!")
- else
- ..()
-
-/obj/effect/clockwork/sigil/transmission/examine(mob/user)
- . = ..()
- if(is_servant_of_ratvar(user) || isobserver(user))
- var/structure_number = 0
- for(var/obj/structure/destructible/clockwork/powered/P in range(SIGIL_ACCESS_RANGE, src))
- structure_number++
- . += {"It is storing [DisplayPower(get_clockwork_power())] of shared power,
- and [structure_number] clockwork structure[structure_number == 1 ? " is":"s are"] in range."}
- if(iscyborg(user))
- . += "You can recharge from the [sigil_name] by crossing it."
-
-/obj/effect/clockwork/sigil/transmission/sigil_effects(mob/living/L)
- if(is_servant_of_ratvar(L))
- if(iscyborg(L))
- charge_cyborg(L)
- else if(get_clockwork_power())
- to_chat(L, "You feel a slight, static shock.")
-
-/obj/effect/clockwork/sigil/transmission/proc/charge_cyborg(mob/living/silicon/robot/cyborg)
- if(!cyborg_checks(cyborg))
- return
- to_chat(cyborg, "You start to charge from the [sigil_name]...")
- if(!do_after(cyborg, 50, target = src, extra_checks = CALLBACK(src, .proc/cyborg_checks, cyborg, TRUE)))
- return
- var/giving_power = min(FLOOR(cyborg.cell.maxcharge - cyborg.cell.charge, MIN_CLOCKCULT_POWER), get_clockwork_power()) //give the borg either all our power or their missing power floored to MIN_CLOCKCULT_POWER
- if(adjust_clockwork_power(-giving_power))
- cyborg.visible_message("[cyborg] glows a brilliant orange!")
- var/previous_color = cyborg.color
- cyborg.color = list("#EC8A2D", "#EC8A2D", "#EC8A2D", rgb(0,0,0))
- cyborg.apply_status_effect(STATUS_EFFECT_POWERREGEN, giving_power * 0.1) //ten ticks, restoring 10% each
- animate(cyborg, color = previous_color, time = 100)
- addtimer(CALLBACK(cyborg, /atom/proc/update_atom_colour), 100)
-
-/obj/effect/clockwork/sigil/transmission/proc/cyborg_checks(mob/living/silicon/robot/cyborg, silent)
- if(!cyborg.cell)
- if(!silent)
- to_chat(cyborg, "You have no cell!")
- return FALSE
- if(!get_clockwork_power())
- if(!silent)
- to_chat(cyborg, "There is no power available across sigils!")
- return FALSE
- if(cyborg.cell.charge > cyborg.cell.maxcharge - MIN_CLOCKCULT_POWER)
- if(!silent)
- to_chat(cyborg, "You are already at maximum charge!")
- return FALSE
- if(cyborg.has_status_effect(STATUS_EFFECT_POWERREGEN))
- if(!silent)
- to_chat(cyborg, "You are already regenerating power!")
- return FALSE
- return TRUE
-
-/obj/effect/clockwork/sigil/transmission/update_icon()
- var/power_charge = get_clockwork_power()
- if(GLOB.ratvar_awakens)
- alpha = 255
- else
- alpha = min(CEILING(initial(alpha) + power_charge * 0.02, 35), 255)
- var/r = alpha * 0.02
- var/p = max(alpha * 0.01, 0.1)
- if(!power_charge && light_range != 0)
- set_light(0)
- else if(r != light_range || p != light_power)
- set_light(r, p)
-
-//Vitality Matrix: Drains health from non-servants to heal or even revive servants.
-/obj/effect/clockwork/sigil/vitality
- name = "comforting sigil"
- desc = "A faint blue sigil. Looking at it makes you feel protected."
- clockwork_desc = "A sigil that will drain non-Servants that remain on it. Servants that remain on it will be healed if it has any vitality drained."
- icon_state = "sigilvitality"
- layer = SIGIL_LAYER
- alpha = 75
- color = "#123456"
- affects_servants = TRUE
- stat_affected = DEAD
- resist_string = "glows shimmering yellow"
- sigil_name = "Vitality Matrix"
- var/revive_cost = 150
- var/sigil_active = FALSE
- var/animation_number = 3 //each cycle increments this by 1, at 4 it produces an animation and resets
- var/static/list/damage_heal_order = list(CLONE, TOX, BURN, BRUTE, OXY) //we heal damage in this order
-
-/obj/effect/clockwork/sigil/vitality/examine(mob/user)
- . = ..()
- if(is_servant_of_ratvar(user) || isobserver(user))
- . += "It has access to [GLOB.ratvar_awakens ? "INFINITE":GLOB.clockwork_vitality] units of vitality."
- if(GLOB.ratvar_awakens)
- . += "It can revive Servants at no cost!"
- else
- . += "It can revive Servants at a cost of [revive_cost] vitality."
-
-/obj/effect/clockwork/sigil/vitality/sigil_effects(mob/living/L)
- if((is_servant_of_ratvar(L) && L.suiciding) || sigil_active)
- return
- animate(src, alpha = 255, time = 10, flags = ANIMATION_END_NOW) //we may have a previous animation going. finish it first, then do this one without delay.
- sleep(10)
-//as long as they're still on the sigil and are either not a servant or they're a servant AND it has remaining vitality
- var/consumed_vitality
- while(L && (!is_servant_of_ratvar(L) || (is_servant_of_ratvar(L) && (GLOB.ratvar_awakens || GLOB.clockwork_vitality))) && get_turf(L) == get_turf(src) && !L.buckled)
- sigil_active = TRUE
- if(animation_number >= 4)
- new /obj/effect/temp_visual/ratvar/sigil/vitality(get_turf(src))
- animation_number = 0
- animation_number++
- if(!is_servant_of_ratvar(L))
- var/vitality_drained = 0
- if(L.stat == DEAD && !consumed_vitality)
- consumed_vitality = TRUE //Prevent the target from being consumed multiple times
- vitality_drained = L.maxHealth
- var/obj/effect/temp_visual/ratvar/sigil/vitality/V = new /obj/effect/temp_visual/ratvar/sigil/vitality(get_turf(src))
- animate(V, alpha = 0, transform = matrix()*2, time = 8)
- playsound(L, 'sound/magic/wandodeath.ogg', 50, TRUE)
- L.visible_message("[L] collapses in on [L.p_them()]self as [src] flares bright blue!")
- to_chat(L, "\"[text2ratvar("Your life will not be wasted.")]\"")
- for(var/obj/item/W in L)
- if(!L.dropItemToGround(W))
- qdel(W)
- L.dust()
- else
- if(!GLOB.ratvar_awakens && L.stat == CONSCIOUS)
- vitality_drained = L.adjustToxLoss(1)
- else
- vitality_drained = L.adjustToxLoss(1.5)
- if(vitality_drained)
- GLOB.clockwork_vitality += vitality_drained
- else
- break
- else
- if(L.stat == DEAD)
- var/revival_cost = revive_cost
- if(GLOB.ratvar_awakens || L.suiciding) // No cost if Ratvar is summoned or if you're reviving a convert who suicided
- revival_cost = 0
- var/mob/dead/observer/ghost = L.get_ghost(TRUE)
- if(GLOB.clockwork_vitality >= revival_cost && (ghost || (L.mind && L.mind.active)))
- if(L.has_status_effect(STATUS_EFFECT_ICHORIAL_STAIN))
- visible_message("[src] strains, but nothing happens...")
- if(L.pulledby)
- to_chat(L.pulledby, "[L] was already revived recently by a vitality matrix! Wait a bit longer!")
- break
- else
- if(ghost)
- ghost.reenter_corpse()
- L.revive(1, 1)
- var/obj/effect/temp_visual/ratvar/sigil/vitality/V = new /obj/effect/temp_visual/ratvar/sigil/vitality(get_turf(src))
- animate(V, alpha = 0, transform = matrix()*2, time = 8)
- playsound(L, 'sound/magic/staff_healing.ogg', 50, TRUE)
- to_chat(L, "\"[text2ratvar("You will be okay, child.")]\"")
- L.apply_status_effect(STATUS_EFFECT_ICHORIAL_STAIN)
- GLOB.clockwork_vitality -= revival_cost
- break
- if(!L.client || L.client.is_afk())
- set waitfor = FALSE
- var/list/mob/dead/observer/candidates = pollCandidatesForMob("Do you want to play as a [L.name], an inactive clock cultist?", ROLE_SERVANT_OF_RATVAR, null, ROLE_SERVANT_OF_RATVAR, 50, L)
- if(LAZYLEN(candidates))
- var/mob/dead/observer/C = pick(candidates)
- to_chat(L, "Your physical form has been taken over by another soul due to your inactivity! Ahelp if you wish to regain your form!")
- message_admins("[key_name_admin(C)] has taken control of ([key_name_admin(L)]) to replace an inactive clock cultist.")
- L.ghostize(0)
- L.key = C.key
- var/obj/effect/temp_visual/ratvar/sigil/vitality/V = new /obj/effect/temp_visual/ratvar/sigil/vitality(get_turf(src))
- animate(V, alpha = 0, transform = matrix()*2, time = 8)
- playsound(L, 'sound/magic/staff_healing.ogg', 50, TRUE)
- L.visible_message("[L]'s eyes suddenly open wide, gleaming with renewed vigor for the cause!", "\"[text2ratvar("Awaken!")]\"")
- break
- var/vitality_for_cycle = 3
- if(!GLOB.ratvar_awakens)
- if(L.stat == CONSCIOUS)
- vitality_for_cycle = 2
- vitality_for_cycle = min(GLOB.clockwork_vitality, vitality_for_cycle)
- var/vitality_used = L.heal_ordered_damage(vitality_for_cycle, damage_heal_order)
-
- if(!vitality_used)
- break
-
- if(!GLOB.ratvar_awakens)
- GLOB.clockwork_vitality -= vitality_used
-
- sleep(2)
-
- if(sigil_active)
- animation_number = initial(animation_number)
- sigil_active = FALSE
- animate(src, alpha = initial(alpha), time = 10, flags = ANIMATION_END_NOW)
diff --git a/code/modules/antagonists/clockcult/clock_effects/general_markers.dm b/code/modules/antagonists/clockcult/clock_effects/general_markers.dm
deleted file mode 100644
index 1994fdf779f..00000000000
--- a/code/modules/antagonists/clockcult/clock_effects/general_markers.dm
+++ /dev/null
@@ -1,63 +0,0 @@
-//massive markers for Revenant and Judgement scripture.
-/obj/effect/clockwork/general_marker
- name = "general marker"
- desc = "Some big guy. For you."
- clockwork_desc = "One of Ratvar's generals."
- alpha = 200
- layer = MASSIVE_OBJ_LAYER
-
-/obj/effect/clockwork/general_marker/Initialize()
- . = ..()
- animate(src, alpha = 0, time = 10)
- QDEL_IN(src, 10)
-
-/obj/effect/clockwork/general_marker/singularity_act()
- return
-
-/obj/effect/clockwork/general_marker/singularity_pull()
- return
-
-/obj/effect/clockwork/general_marker/inathneq
- name = "Inath-neq, the Resonant Cogwheel"
- desc = "A humanoid form blazing with blue fire. It radiates an aura of kindness and caring."
- clockwork_desc = "One of Ratvar's four generals. Before her current form, Inath-neq was a powerful warrior priestess commanding the Resonant Cogs, a sect of Ratvarian warriors renowned for \
- their prowess. After a lost battle with Nar'Sian cultists, Inath-neq was struck down and stated in her dying breath, \
- \"The Resonant Cogs shall not fall silent this day, but will come together to form a wheel that shall never stop turning.\" Ratvar, touched by this, granted Inath-neq an eternal body and \
- merged her soul with those of the Cogs slain with her on the battlefield."
- icon = 'icons/effects/119x268.dmi'
- icon_state = "inath-neq"
- pixel_x = -59
- pixel_y = -134
-
-/obj/effect/clockwork/general_marker/nezbere
- name = "Nezbere, the Brass Eidolon"
- desc = "A towering colossus clad in nigh-impenetrable brass armor. Its gaze is stern yet benevolent, even upon you."
- clockwork_desc = "One of Ratvar's four generals. Nezbere is responsible for the design, testing, and creation of everything in Ratvar's domain, and his loyalty to Ratvar knows no bounds. \
- It is said that Ratvar once asked him to destroy the plans for a weapon Nezbere had made that could have harmed him, and Nezbere responded by not only destroying the plans, \
- but by taking his own life so that the device could never be replicated. Nezbere's zealotry is unmatched."
- icon = 'icons/effects/237x321.dmi'
- icon_state = "nezbere"
- pixel_x = -118
- pixel_y = -160
-
-/obj/effect/clockwork/general_marker/sevtug
- name = "Sevtug, the Formless Pariah"
- desc = "A sinister cloud of purple energy. Looking at it gives you a headache."
- clockwork_desc = "One of Ratvar's four generals. Sevtug taught him how to manipulate minds and is one of his oldest allies. Sevtug serves Ratvar loyally out of a hope that one day, he will \
- be able to use a moment of weakness in the Justicar to usurp him, but such a day will never come. And so, he serves with dedication, if not necessarily any sort of decorum, never aware he is \
- the one being made a fool of."
- icon = 'icons/effects/166x195.dmi'
- icon_state = "sevtug"
- pixel_x = -83
- pixel_y = -97
-
-/obj/effect/clockwork/general_marker/nzcrentr
- name = "Nzcrentr, the Eternal Thunderbolt"
- desc = "A terrifying spiked construct crackling with perpetual lightning."
- clockwork_desc = "One of Ratvar's four generals. Before becoming one of Ratvar's generals, Nzcrentr sook out any and all sentient life to slaughter it for sport. \
- Nzcrentr was coerced by Ratvar into entering a shell constructed by Nezbere, ostensibly made to grant Nzcrentr more power. In reality, the shell was made to trap and control it. \
- Nzcrentr now serves loyally, though even one of Nezbere's finest creations was not enough to totally eliminate its will."
- icon = 'icons/effects/274x385.dmi'
- icon_state = "nzcrentr"
- pixel_x = -137
- pixel_y = -145
diff --git a/code/modules/antagonists/clockcult/clock_effects/servant_blocker.dm b/code/modules/antagonists/clockcult/clock_effects/servant_blocker.dm
deleted file mode 100644
index acca057b8be..00000000000
--- a/code/modules/antagonists/clockcult/clock_effects/servant_blocker.dm
+++ /dev/null
@@ -1,45 +0,0 @@
-//Marks the point at which "no man's land" begins on Reebe. Servants can't pass beyond this point in any way.
-/obj/effect/clockwork/servant_blocker
- name = "glowing arrow"
- desc = "A faintly glowing image of an arrow on the ground. Convenient!"
- icon_state = "servant_blocker"
- mouse_opacity = MOUSE_OPACITY_TRANSPARENT
- anchored = TRUE
- density = TRUE
- CanAtmosPass = ATMOS_PASS_NO
-
-/obj/effect/clockwork/servant_blocker/Initialize()
- . = ..()
- air_update_turf(TRUE)
-
-/obj/effect/clockwork/servant_blocker/Destroy(force)
- if(!force)
- return QDEL_HINT_LETMELIVE
- return ..()
-
-/obj/effect/clockwork/servant_blocker/CanPass(atom/movable/M, turf/target)
- var/list/target_contents = M.GetAllContents() + M
- for(var/mob/living/L in target_contents)
- if(is_servant_of_ratvar(L) && get_dir(M, src) != dir && L.stat != DEAD) //Unless we're on the side the arrow is pointing directly away from, no-go
- to_chat(L, "The space beyond here can't be accessed by you or other servants!")
- return
- if(isitem(M))
- var/obj/item/I = M
- if(is_servant_of_ratvar(I.thrownby)) //nice try!
- return
- return TRUE
-
-/obj/effect/clockwork/servant_blocker/BlockSuperconductivity()
- return TRUE
-
-/obj/effect/clockwork/servant_blocker/singularity_act()
- return
-
-/obj/effect/clockwork/servant_blocker/singularity_pull()
- return
-
-/obj/effect/clockwork/servant_blocker/ex_act(severity, target)
- return
-
-/obj/effect/clockwork/servant_blocker/safe_throw_at(atom/target, range, speed, mob/thrower, spin = TRUE, diagonals_first = FALSE, datum/callback/callback, force = MOVE_FORCE_STRONG)
- return
diff --git a/code/modules/antagonists/clockcult/clock_effects/spatial_gateway.dm b/code/modules/antagonists/clockcult/clock_effects/spatial_gateway.dm
deleted file mode 100644
index 5d053a112ab..00000000000
--- a/code/modules/antagonists/clockcult/clock_effects/spatial_gateway.dm
+++ /dev/null
@@ -1,230 +0,0 @@
-//Spatial gateway: A usually one-way rift to another location.
-/obj/effect/clockwork/spatial_gateway
- name = "spatial gateway"
- desc = "A gently thrumming tear in reality."
- clockwork_desc = "A gateway in reality."
- icon_state = "spatial_gateway"
- density = TRUE
- light_range = 2
- light_power = 3
- light_color = "#6A4D2F"
- var/sender = TRUE //If this gateway is made for sending, not receiving
- var/both_ways = FALSE
- var/lifetime = 25 //How many deciseconds this portal will last
- var/uses = 1 //How many objects or mobs can go through the portal
- var/obj/effect/clockwork/spatial_gateway/linked_gateway //The gateway linked to this one
- var/timerid
-
-/obj/effect/clockwork/spatial_gateway/Initialize()
- . = ..()
- addtimer(CALLBACK(src, .proc/check_setup), 1)
-
-/obj/effect/clockwork/spatial_gateway/Destroy()
- deltimer(timerid)
- return ..()
-
-/obj/effect/clockwork/spatial_gateway/proc/check_setup()
- if(!linked_gateway)
- qdel(src)
- return
- if(both_ways)
- clockwork_desc = "A gateway in reality. It can both send and receive objects."
- else
- clockwork_desc = "A gateway in reality. It can only [sender ? "send" : "receive"] objects."
- timerid = QDEL_IN(src, lifetime)
-
-//set up a gateway with another gateway
-/obj/effect/clockwork/spatial_gateway/proc/setup_gateway(obj/effect/clockwork/spatial_gateway/gatewayB, set_duration, set_uses, two_way)
- if(!gatewayB || !set_duration || !uses)
- return FALSE
- linked_gateway = gatewayB
- gatewayB.linked_gateway = src
- if(two_way)
- both_ways = TRUE
- gatewayB.both_ways = TRUE
- else
- sender = TRUE
- gatewayB.sender = FALSE
- gatewayB.density = FALSE
- lifetime = set_duration
- gatewayB.lifetime = set_duration
- uses = set_uses
- gatewayB.uses = set_uses
- return TRUE
-
-/obj/effect/clockwork/spatial_gateway/examine(mob/user)
- . = ..()
- if(is_servant_of_ratvar(user) || isobserver(user))
- . += "It has [uses] use\s remaining."
-
-//ATTACK GHOST IGNORING PARENT RETURN VALUE
-/obj/effect/clockwork/spatial_gateway/attack_ghost(mob/user)
- if(linked_gateway)
- user.forceMove(get_turf(linked_gateway))
- ..()
-
-//ATTACK HAND IGNORING PARENT RETURN VALUE
-/obj/effect/clockwork/spatial_gateway/attack_hand(mob/living/user)
- if(!uses)
- return FALSE
- if(user.pulling && user.a_intent == INTENT_GRAB && isliving(user.pulling))
- var/mob/living/L = user.pulling
- if(L.buckled || L.anchored || L.has_buckled_mobs())
- return FALSE
- user.visible_message("[user] shoves [L] into [src]!", "You shove [L] into [src]!")
- user.stop_pulling()
- pass_through_gateway(L)
- return TRUE
- if(!user.canUseTopic(src))
- return FALSE
- user.visible_message("[user] climbs through [src]!", "You brace yourself and step through [src]...")
- pass_through_gateway(user)
- return TRUE
-
-/obj/effect/clockwork/spatial_gateway/attackby(obj/item/I, mob/living/user, params)
- if(istype(I, /obj/item/nullrod))
- user.visible_message("[user] dispels [src] with [I]!", "You close [src] with [I]!")
- qdel(linked_gateway)
- qdel(src)
- return TRUE
- if(istype(I, /obj/item/clockwork/slab))
- to_chat(user, "\"I don't think you want to drop your slab into that.\"\n\"If you really want to, try throwing it.\"")
- return TRUE
- if(uses && user.dropItemToGround(I))
- user.visible_message("[user] drops [I] into [src]!", "You drop [I] into [src]!")
- pass_through_gateway(I, TRUE)
- return TRUE
- return ..()
-
-/obj/effect/clockwork/spatial_gateway/ex_act(severity)
- if(severity == 1 && uses)
- uses = 0
- visible_message("[src] is disrupted!")
- animate(src, alpha = 0, transform = matrix()*2, time = 10, flags = ANIMATION_END_NOW)
- deltimer(timerid)
- timerid = QDEL_IN(src, 10)
- linked_gateway.uses = 0
- linked_gateway.visible_message("[linked_gateway] is disrupted!")
- animate(linked_gateway, alpha = 0, transform = matrix()*2, time = 10, flags = ANIMATION_END_NOW)
- deltimer(linked_gateway.timerid)
- linked_gateway.timerid = QDEL_IN(linked_gateway, 10)
- return TRUE
- return FALSE
-
-
-/obj/effect/clockwork/spatial_gateway/singularity_act()
- return
-
-/obj/effect/clockwork/spatial_gateway/singularity_pull()
- return
-
-
-/obj/effect/clockwork/spatial_gateway/Bumped(atom/movable/AM)
- ..()
- if(!QDELETED(AM))
- pass_through_gateway(AM, FALSE)
-
-/obj/effect/clockwork/spatial_gateway/proc/pass_through_gateway(atom/movable/A, no_cost)
- if(!linked_gateway)
- qdel(src)
- return FALSE
- if(!sender)
- visible_message("[A] bounces off [src]!")
- return FALSE
- if(!uses)
- return FALSE
- if(!do_teleport(A, get_turf(linked_gateway), forceMove = TRUE, channel = TELEPORT_CHANNEL_CULT))
- visible_message("[A] bounces off [src]!")
- return FALSE
- if(isliving(A))
- var/mob/living/user = A
- to_chat(user, "You pass through [src] and appear elsewhere!")
- linked_gateway.visible_message("A shape appears in [linked_gateway] before emerging!")
- playsound(src, 'sound/effects/empulse.ogg', 50, TRUE)
- playsound(linked_gateway, 'sound/effects/empulse.ogg', 50, TRUE)
- transform = matrix() * 1.5
- linked_gateway.transform = matrix() * 1.5
-
- if(!no_cost)
- uses = max(0, uses - 1)
- linked_gateway.uses = max(0, linked_gateway.uses - 1)
- if(!uses)
- animate(src, transform = matrix() * 0.1, time = 10, flags = ANIMATION_END_NOW)
- animate(linked_gateway, transform = matrix() * 0.1, time = 10, flags = ANIMATION_END_NOW)
- density = FALSE
- linked_gateway.density = FALSE
- else
- animate(src, transform = matrix() / 1.5, time = 10, flags = ANIMATION_END_NOW)
- animate(linked_gateway, transform = matrix() / 1.5, time = 10, flags = ANIMATION_END_NOW)
- addtimer(CALLBACK(src, .proc/check_uses), 10)
- return TRUE
-
-/obj/effect/clockwork/spatial_gateway/proc/check_uses()
- if(!uses)
- qdel(src)
- qdel(linked_gateway)
-
-//This proc creates and sets up a gateway from invoker input.
-/atom/movable/proc/procure_gateway(mob/living/invoker, time_duration, gateway_uses, two_way)
- var/list/possible_targets = list()
- var/list/teleportnames = list()
-
- for(var/obj/structure/destructible/clockwork/powered/clockwork_obelisk/O in GLOB.all_clockwork_objects)
- if(!O.Adjacent(invoker) && O != src && !is_away_level(O.z) && O.anchored) //don't list obelisks that we're next to
- var/area/A = get_area(O)
- var/locname = initial(A.name)
- possible_targets[avoid_assoc_duplicate_keys("[locname] [O.name]", teleportnames)] = O
-
- for(var/mob/living/L in GLOB.alive_mob_list)
- if(!L.stat && is_servant_of_ratvar(L) && !L.Adjacent(invoker) && !is_away_level(L.z)) //People right next to the invoker can't be portaled to, for obvious reasons
- possible_targets[avoid_assoc_duplicate_keys("[L.name] ([L.real_name])", teleportnames)] = L
-
- if(!possible_targets.len)
- to_chat(invoker, "There are no other eligible targets for a Spatial Gateway!")
- return FALSE
- var/input_target_key = input(invoker, "Choose a target to form a rift to.", "Spatial Gateway") as null|anything in possible_targets
- var/atom/movable/target = possible_targets[input_target_key]
- if(!src || !input_target_key || !invoker || !invoker.canUseTopic(src, !issilicon(invoker)) || !is_servant_of_ratvar(invoker) || (isitem(src) && invoker.get_active_held_item() != src) || !invoker.can_speak_vocal())
- return FALSE //if any of the involved things no longer exist, the invoker is stunned, too far away to use the object, or does not serve ratvar, or if the object is an item and not in the mob's active hand, fail
- if(!target) //if we have no target, but did have a key, let them retry
- to_chat(invoker, "That target no longer exists!")
- return procure_gateway(invoker, time_duration, gateway_uses, two_way)
- if(isliving(target))
- var/mob/living/L = target
- if(!is_servant_of_ratvar(L))
- to_chat(invoker, "That target is no longer a Servant!")
- return procure_gateway(invoker, time_duration, gateway_uses, two_way)
- if(L.stat != CONSCIOUS)
- to_chat(invoker, "That Servant is no longer conscious!")
- return procure_gateway(invoker, time_duration, gateway_uses, two_way)
- var/istargetobelisk = istype(target, /obj/structure/destructible/clockwork/powered/clockwork_obelisk)
- var/issrcobelisk = istype(src, /obj/structure/destructible/clockwork/powered/clockwork_obelisk)
- if(issrcobelisk)
- if(!anchored)
- to_chat(invoker, "[src] is no longer secured!")
- return FALSE
- var/obj/structure/destructible/clockwork/powered/clockwork_obelisk/CO = src //foolish as I am, how I set this proc up makes substypes unfeasible
- if(CO.active)
- to_chat(invoker, "[src] is now sustaining a gateway!")
- return FALSE
- if(istargetobelisk)
- if(!target.anchored)
- to_chat(invoker, "That [target.name] is no longer secured!")
- return procure_gateway(invoker, time_duration, gateway_uses, two_way)
- var/obj/structure/destructible/clockwork/powered/clockwork_obelisk/CO = target
- if(CO.active)
- to_chat(invoker, "That [target.name] is sustaining a gateway, and cannot receive another!")
- return procure_gateway(invoker, time_duration, gateway_uses, two_way)
- var/efficiency = CO.get_efficiency_mod()
- gateway_uses = round(gateway_uses * (2 * efficiency), 1)
- time_duration = round(time_duration * (2 * efficiency), 1)
- CO.active = TRUE //you'd be active in a second but you should update immediately
- invoker.visible_message("The air in front of [invoker] ripples before suddenly tearing open!", \
- "With a word, you rip open a [two_way ? "two-way":"one-way"] rift to [input_target_key]. It will last for [DisplayTimeText(time_duration)] and has [gateway_uses] use[gateway_uses > 1 ? "s" : ""].")
- var/obj/effect/clockwork/spatial_gateway/S1 = new(issrcobelisk ? get_turf(src) : get_step(get_turf(invoker), invoker.dir))
- var/obj/effect/clockwork/spatial_gateway/S2 = new(istargetobelisk ? get_turf(target) : get_step(get_turf(target), target.dir))
-
- //Set up the portals now that they've spawned
- S1.setup_gateway(S2, time_duration, gateway_uses, two_way)
- S2.visible_message("The air in front of [target] ripples before suddenly tearing open!")
- return TRUE
diff --git a/code/modules/antagonists/clockcult/clock_helpers/clock_powerdrain.dm b/code/modules/antagonists/clockcult/clock_helpers/clock_powerdrain.dm
deleted file mode 100644
index 18517c63197..00000000000
--- a/code/modules/antagonists/clockcult/clock_helpers/clock_powerdrain.dm
+++ /dev/null
@@ -1,53 +0,0 @@
-//horrifying power drain proc made for clockcult's power drain in lieu of six istypes or six for(x in view) loops
-/atom/movable/proc/power_drain(clockcult_user)
- var/obj/item/stock_parts/cell/cell = get_cell()
- if(cell)
- return cell.power_drain(clockcult_user)
- return 0
-
-/obj/item/melee/baton/power_drain(clockcult_user) //balance memes
- return 0
-
-/obj/item/gun/power_drain(clockcult_user) //balance memes
- return 0
-
-/obj/machinery/power/apc/power_drain(clockcult_user)
- if(cell && cell.charge)
- playsound(src, "sparks", 50, TRUE)
- flick("apc-spark", src)
- . = min(cell.charge, MIN_CLOCKCULT_POWER*3)
- cell.use(.) //Better than a power sink!
- if(!cell.charge && !shorted)
- shorted = 1
- visible_message("The [name]'s screen blurs with static.")
- update()
- update_icon()
-
-/obj/machinery/power/smes/power_drain(clockcult_user)
- if(charge)
- . = min(charge, MIN_CLOCKCULT_POWER*3)
- charge -= . * 50
- if(!charge && !panel_open)
- panel_open = TRUE
- icon_state = "[initial(icon_state)]-o"
- do_sparks(10, FALSE, src)
- visible_message("[src]'s panel flies open with a flurry of sparks!")
- update_icon()
-
-/obj/item/stock_parts/cell/power_drain(clockcult_user)
- if(charge)
- . = min(charge, MIN_CLOCKCULT_POWER*3)
- charge = use(.)
- update_icon()
-
-/mob/living/silicon/robot/power_drain(clockcult_user)
- if((!clockcult_user || !is_servant_of_ratvar(src)) && cell && cell.charge)
- . = min(cell.charge, MIN_CLOCKCULT_POWER*4)
- cell.use(.)
- spark_system.start()
-
-/obj/mecha/power_drain(clockcult_user)
- if((!clockcult_user || (occupant && !is_servant_of_ratvar(occupant))) && cell && cell.charge)
- . = min(cell.charge, MIN_CLOCKCULT_POWER*4)
- cell.use(.)
- spark_system.start()
diff --git a/code/modules/antagonists/clockcult/clock_helpers/component_helpers.dm b/code/modules/antagonists/clockcult/clock_helpers/component_helpers.dm
deleted file mode 100644
index e319df418fd..00000000000
--- a/code/modules/antagonists/clockcult/clock_helpers/component_helpers.dm
+++ /dev/null
@@ -1,41 +0,0 @@
-//returns a component spanclass from a component id
-/proc/get_component_span(id)
- switch(id)
- if(BELLIGERENT_EYE)
- return "neovgre"
- if(VANGUARD_COGWHEEL)
- return "inathneq"
- if(GEIS_CAPACITOR)
- return "sevtug"
- if(REPLICANT_ALLOY)
- return "nezbere"
- if(HIEROPHANT_ANSIBLE)
- return "nzcrentr"
- else
- return "brass"
-
-//returns a component color from a component id, but with brighter colors for the darkest
-/proc/get_component_color_bright(id)
- switch(id)
- if(BELLIGERENT_EYE)
- return "#880020"
- if(REPLICANT_ALLOY)
- return "#5A6068"
- else
- return get_component_color(id)
-
-//returns a component color from a component id
-/proc/get_component_color(id)
- switch(id)
- if(BELLIGERENT_EYE)
- return "#6E001A"
- if(VANGUARD_COGWHEEL)
- return "#1E8CE1"
- if(GEIS_CAPACITOR)
- return "#AF0AAF"
- if(REPLICANT_ALLOY)
- return "#42474D"
- if(HIEROPHANT_ANSIBLE)
- return "#DAAA18"
- else
- return "#BE8700"
diff --git a/code/modules/antagonists/clockcult/clock_helpers/fabrication_helpers.dm b/code/modules/antagonists/clockcult/clock_helpers/fabrication_helpers.dm
deleted file mode 100644
index f005c625a48..00000000000
--- a/code/modules/antagonists/clockcult/clock_helpers/fabrication_helpers.dm
+++ /dev/null
@@ -1,347 +0,0 @@
-//For the clockwork fabricator, this proc exists to make it easy to customize what the fabricator does when hitting something.
-
-//if a valid target, returns an associated list in this format;
-//list("operation_time" = 15, "new_obj_type" = /obj/structure/window/reinforced/clockwork, "power_cost" = 5, "spawn_dir" = dir, "dir_in_new" = TRUE)
-//otherwise, return literally any non-list thing but preferably FALSE
-//returning TRUE won't produce the "cannot be fabricated" message and will still prevent fabrication
-
-/atom/proc/fabrication_vals(mob/living/user, obj/item/clockwork/replica_fabricator/fabricator, silent)
- return FALSE
-
-/atom/proc/consume_visual(obj/item/clockwork/replica_fabricator/fabricator, power_amount)
- if(get_clockwork_power(power_amount))
- var/obj/effect/temp_visual/ratvar/beam/itemconsume/B = new /obj/effect/temp_visual/ratvar/beam/itemconsume(get_turf(src))
- B.pixel_x = pixel_x
- B.pixel_y = pixel_y
-
-//Turf conversion
-/turf/closed/wall/fabrication_vals(mob/living/user, obj/item/clockwork/replica_fabricator/fabricator, silent) //four sheets of metal
- return list("operation_time" = 50, "new_obj_type" = /turf/closed/wall/clockwork, "power_cost" = POWER_WALL_TOTAL - (POWER_METAL * 4), "spawn_dir" = SOUTH)
-
-/turf/closed/wall/mineral/fabrication_vals(mob/living/user, obj/item/clockwork/replica_fabricator/fabricator, silent) //two sheets of metal
- return list("operation_time" = 50, "new_obj_type" = /turf/closed/wall/clockwork, "power_cost" = POWER_WALL_TOTAL - (POWER_METAL * 2), "spawn_dir" = SOUTH)
-
-/turf/closed/wall/mineral/iron/fabrication_vals(mob/living/user, obj/item/clockwork/replica_fabricator/fabricator, silent) //two sheets of metal, five rods
- return list("operation_time" = 50, "new_obj_type" = /turf/closed/wall/clockwork, "power_cost" = POWER_WALL_TOTAL - (POWER_METAL * 2) - (POWER_ROD * 5), "spawn_dir" = SOUTH)
-
-/turf/closed/wall/mineral/cult/fabrication_vals(mob/living/user, obj/item/clockwork/replica_fabricator/fabricator, silent) //no metal
- return list("operation_time" = 80, "new_obj_type" = /turf/closed/wall/clockwork, "power_cost" = POWER_WALL_TOTAL, "spawn_dir" = SOUTH)
-
-/turf/closed/wall/r_wall/fabrication_vals(mob/living/user, obj/item/clockwork/replica_fabricator/fabricator, silent)
- return FALSE
-
-/turf/closed/wall/clockwork/fabrication_vals(mob/living/user, obj/item/clockwork/replica_fabricator/fabricator, silent)
- return list("operation_time" = 50, "new_obj_type" = /turf/open/floor/clockwork, "power_cost" = -POWER_WALL_MINUS_FLOOR, "spawn_dir" = SOUTH)
-
-/turf/open/floor/fabrication_vals(mob/living/user, obj/item/clockwork/replica_fabricator/fabricator, silent)
- if(floor_tile == /obj/item/stack/tile/plasteel)
- new floor_tile(src)
- make_plating()
- playsound(src, 'sound/items/crowbar.ogg', 10, TRUE) //clink
- return list("operation_time" = 30, "new_obj_type" = /turf/open/floor/clockwork, "power_cost" = POWER_FLOOR, "spawn_dir" = SOUTH)
-
-/turf/open/floor/plating/asteroid/fabrication_vals(mob/living/user, obj/item/clockwork/replica_fabricator/fabricator, silent)
- return FALSE
-
-/turf/open/floor/plating/ashplanet/fabrication_vals(mob/living/user, obj/item/clockwork/replica_fabricator/fabricator, silent)
- return FALSE
-
-/turf/open/lava/fabrication_vals(mob/living/user, obj/item/clockwork/replica_fabricator/fabricator, silent)
- return FALSE
-
-/turf/open/floor/clockwork/fabrication_vals(mob/living/user, obj/item/clockwork/replica_fabricator/fabricator, silent)
- if(locate(/obj/structure/table) in src)
- return FALSE
- if(locate(/obj/structure/falsewall) in contents)
- to_chat(user, "There is a false wall in the way, preventing you from fabricating a clockwork wall on [src].")
- return
- if(is_blocked_turf(src, TRUE))
- to_chat(user, "Something is in the way, preventing you from fabricating a clockwork wall on [src].")
- return TRUE
- var/operation_time = 100
- if(!GLOB.ratvar_awakens && fabricator.speed_multiplier > 0) //if ratvar isn't awake, this always takes 10 seconds
- operation_time /= fabricator.speed_multiplier
- return list("operation_time" = operation_time, "new_obj_type" = /turf/closed/wall/clockwork, "power_cost" = POWER_WALL_MINUS_FLOOR, "spawn_dir" = SOUTH)
-
-//False wall conversion
-/obj/structure/falsewall/fabrication_vals(mob/living/user, obj/item/clockwork/replica_fabricator/fabricator, silent)
- var/cost = POWER_WALL_MINUS_FLOOR
- if(ispath(mineral, /obj/item/stack/sheet/metal))
- cost -= (POWER_METAL * (2 + mineral_amount)) //four sheets of metal, plus an assumption that the girder is also two
- else
- cost -= (POWER_METAL * 2) //anything that doesn't use metal just has the girder
- return list("operation_time" = 50, "new_obj_type" = /obj/structure/falsewall/brass, "power_cost" = cost, "spawn_dir" = SOUTH)
-
-/obj/structure/falsewall/iron/fabrication_vals(mob/living/user, obj/item/clockwork/replica_fabricator/fabricator, silent) //two sheets of metal, two rods; special assumption
- return list("operation_time" = 50, "new_obj_type" = /obj/structure/falsewall/brass, "power_cost" = POWER_WALL_MINUS_FLOOR - (POWER_METAL * 2) - (POWER_ROD * 2), "spawn_dir" = SOUTH)
-
-/obj/structure/falsewall/reinforced/fabrication_vals(mob/living/user, obj/item/clockwork/replica_fabricator/fabricator, silent)
- return FALSE
-
-/obj/structure/falsewall/brass/fabrication_vals(mob/living/user, obj/item/clockwork/replica_fabricator/fabricator, silent)
- return FALSE
-
-//Metal conversion
-/obj/item/stack/tile/plasteel/fabrication_vals(mob/living/user, obj/item/clockwork/replica_fabricator/fabricator, silent)
- if(source)
- return FALSE
- var/amount_temp = get_amount()
- var/no_delete = FALSE
- if(amount_temp < 2)
- to_chat(user, "You need at least 2 floor tiles to convert into power.")
- return TRUE
- if(ISODD(amount_temp))
- amount_temp--
- no_delete = TRUE
- use(amount_temp)
- amount_temp *= 12.5 //each tile is 12.5 power so this is 2 tiles to 25 power
- consume_visual(fabricator, amount_temp)
- return list("operation_time" = 0, "new_obj_type" = null, "power_cost" = -amount_temp, "spawn_dir" = SOUTH, "no_target_deletion" = no_delete)
-
-/obj/item/stack/rods/fabrication_vals(mob/living/user, obj/item/clockwork/replica_fabricator/fabricator, silent)
- if(source)
- return FALSE
- var/power_amount = -(amount*POWER_ROD)
- consume_visual(fabricator, power_amount)
- return list("operation_time" = 0, "new_obj_type" = null, "power_cost" = power_amount, "spawn_dir" = SOUTH)
-
-/obj/item/stack/sheet/metal/fabrication_vals(mob/living/user, obj/item/clockwork/replica_fabricator/fabricator, silent)
- if(source)
- return FALSE
- var/power_amount = -(amount*POWER_METAL)
- consume_visual(fabricator, power_amount)
- return list("operation_time" = 0, "new_obj_type" = null, "power_cost" = power_amount, "spawn_dir" = SOUTH)
-
-/obj/item/stack/sheet/plasteel/fabrication_vals(mob/living/user, obj/item/clockwork/replica_fabricator/fabricator, silent)
- if(source)
- return FALSE
- var/power_amount = -(amount*POWER_PLASTEEL)
- consume_visual(fabricator, power_amount)
- return list("operation_time" = 0, "new_obj_type" = null, "power_cost" = power_amount, "spawn_dir" = SOUTH)
-
-//Brass directly to power
-/obj/item/stack/tile/brass/fabrication_vals(mob/living/user, obj/item/clockwork/replica_fabricator/fabricator, silent)
- if(source)
- return FALSE
- var/power_amount = -(amount*POWER_FLOOR)
- consume_visual(fabricator, power_amount)
- return list("operation_time" = 0, "new_obj_type" = null, "power_cost" = power_amount, "spawn_dir" = SOUTH)
-
-//Airlock conversion
-/obj/machinery/door/airlock/fabrication_vals(mob/living/user, obj/item/clockwork/replica_fabricator/fabricator, silent)
- var/doortype = /obj/machinery/door/airlock/clockwork
- if(glass)
- doortype = /obj/machinery/door/airlock/clockwork/brass
- return list("operation_time" = 60, "new_obj_type" = doortype, "power_cost" = POWER_WALL_TOTAL, "spawn_dir" = dir, "transfer_name" = TRUE)
-
-/obj/machinery/door/airlock/clockwork/fabrication_vals(mob/living/user, obj/item/clockwork/replica_fabricator/fabricator, silent)
- return FALSE
-
-//Table conversion
-/obj/structure/table/fabrication_vals(mob/living/user, obj/item/clockwork/replica_fabricator/fabricator, silent)
- var/fabrication_cost = POWER_STANDARD
- if(framestack == /obj/item/stack/rods)
- fabrication_cost -= POWER_ROD*framestackamount
- else if(framestack == /obj/item/stack/tile/brass)
- fabrication_cost -= POWER_FLOOR*framestackamount
- if(buildstack == /obj/item/stack/sheet/metal)
- fabrication_cost -= POWER_METAL*buildstackamount
- else if(buildstack == /obj/item/stack/sheet/plasteel)
- fabrication_cost -= POWER_PLASTEEL*buildstackamount
- return list("operation_time" = 20, "new_obj_type" = /obj/structure/table/reinforced/brass, "power_cost" = fabrication_cost, "spawn_dir" = SOUTH)
-
-/obj/structure/table/reinforced/brass/fabrication_vals(mob/living/user, obj/item/clockwork/replica_fabricator/fabricator, silent)
- return FALSE
-
-/obj/structure/table_frame/fabrication_vals(mob/living/user, obj/item/clockwork/replica_fabricator/fabricator, silent)
- var/fabrication_cost = POWER_FLOOR
- if(framestack == /obj/item/stack/rods)
- fabrication_cost -= POWER_ROD*framestackamount
- else if(framestack == /obj/item/stack/tile/brass)
- fabrication_cost -= POWER_FLOOR*framestackamount
- return list("operation_time" = 10, "new_obj_type" = /obj/structure/table_frame/brass, "power_cost" = fabrication_cost, "spawn_dir" = SOUTH)
-
-/obj/structure/table_frame/brass/fabrication_vals(mob/living/user, obj/item/clockwork/replica_fabricator/fabricator, silent)
- return FALSE
-
-//Window conversion
-/obj/structure/window/fabrication_vals(mob/living/user, obj/item/clockwork/replica_fabricator/fabricator, silent)
- var/windowtype = /obj/structure/window/reinforced/clockwork
- var/new_dir = TRUE
- var/fabrication_time = 15
- var/fabrication_cost = POWER_FLOOR
- if(fulltile)
- windowtype = /obj/structure/window/reinforced/clockwork/fulltile
- new_dir = FALSE
- fabrication_time = 30
- fabrication_cost = POWER_STANDARD
- if(reinf)
- fabrication_cost -= POWER_ROD
- if(reinf)
- fabrication_cost -= POWER_ROD
- for(var/obj/structure/grille/G in get_turf(src))
- INVOKE_ASYNC(fabricator, /obj/item/clockwork/replica_fabricator.proc/fabricate, G, user)
- return list("operation_time" = fabrication_time, "new_obj_type" = windowtype, "power_cost" = fabrication_cost, "spawn_dir" = dir, "dir_in_new" = new_dir)
-
-/obj/structure/window/reinforced/clockwork/fabrication_vals(mob/living/user, obj/item/clockwork/replica_fabricator/fabricator, silent)
- return FALSE
-
-//Windoor conversion
-/obj/machinery/door/window/fabrication_vals(mob/living/user, obj/item/clockwork/replica_fabricator/fabricator, silent)
- return list("operation_time" = 30, "new_obj_type" = /obj/machinery/door/window/clockwork, "power_cost" = POWER_STANDARD, "spawn_dir" = dir, "dir_in_new" = TRUE, "transfer_name" = TRUE)
-
-/obj/machinery/door/window/clockwork/fabrication_vals(mob/living/user, obj/item/clockwork/replica_fabricator/fabricator, silent)
- return FALSE
-
-//Grille conversion
-/obj/structure/grille/fabrication_vals(mob/living/user, obj/item/clockwork/replica_fabricator/fabricator, silent)
- var/grilletype = /obj/structure/grille/ratvar
- var/fabrication_time = 15
- if(broken)
- grilletype = /obj/structure/grille/ratvar/broken
- fabrication_time = 5
- return list("operation_time" = fabrication_time, "new_obj_type" = grilletype, "power_cost" = 0, "spawn_dir" = dir)
-
-/obj/structure/grille/ratvar/fabrication_vals(mob/living/user, obj/item/clockwork/replica_fabricator/fabricator, silent)
- return FALSE
-
-//Lattice conversion
-/obj/structure/lattice/fabrication_vals(mob/living/user, obj/item/clockwork/replica_fabricator/fabricator, silent)
- return list("operation_time" = 0, "new_obj_type" = /obj/structure/lattice/clockwork, "power_cost" = 0, "spawn_dir" = SOUTH, "no_target_deletion" = TRUE)
-
-/obj/structure/lattice/clockwork/fabrication_vals(mob/living/user, obj/item/clockwork/replica_fabricator/fabricator, silent)
- ratvar_act() //just in case we're the wrong type for some reason??
- return FALSE
-
-/obj/structure/lattice/catwalk/fabrication_vals(mob/living/user, obj/item/clockwork/replica_fabricator/fabricator, silent)
- return list("operation_time" = 0, "new_obj_type" = /obj/structure/lattice/catwalk/clockwork, "power_cost" = 0, "spawn_dir" = SOUTH, "no_target_deletion" = TRUE)
-
-/obj/structure/lattice/catwalk/clockwork/fabrication_vals(mob/living/user, obj/item/clockwork/replica_fabricator/fabricator, silent)
- return FALSE
-
-//Girder conversion
-/obj/structure/girder/fabrication_vals(mob/living/user, obj/item/clockwork/replica_fabricator/fabricator, silent)
- var/fabrication_cost = POWER_GEAR - (POWER_METAL * 2)
- if(state == GIRDER_REINF_STRUTS || state == GIRDER_REINF)
- fabrication_cost -= POWER_PLASTEEL
- return list("operation_time" = 20, "new_obj_type" = /obj/structure/destructible/clockwork/wall_gear, "power_cost" = fabrication_cost, "spawn_dir" = SOUTH)
-
-//Hitting a clockwork structure will try to repair it.
-/obj/structure/destructible/clockwork/fabrication_vals(mob/living/user, obj/item/clockwork/replica_fabricator/fabricator, silent)
- . = TRUE
- var/list/repair_values = list()
- if(!fabricator.fabricator_repair_checks(repair_values, src, user))
- return
- user.visible_message("[user]'s [fabricator.name] starts covering [src] in glowing orange energy...", \
- "You start repairing [src]...")
- fabricator.repairing = src
- while(fabricator && user && src)
- if(!do_after(user, repair_values["healing_for_cycle"] * fabricator.speed_multiplier, target = src, \
- extra_checks = CALLBACK(fabricator, /obj/item/clockwork/replica_fabricator.proc/fabricator_repair_checks, repair_values, src, user, TRUE)))
- break
- obj_integrity = CLAMP(obj_integrity + repair_values["healing_for_cycle"], 0, max_integrity)
- adjust_clockwork_power(-repair_values["power_required"])
- playsound(src, 'sound/machines/click.ogg', 50, TRUE)
-
- if(fabricator)
- fabricator.repairing = null
- if(user)
- user.visible_message("[user]'s [fabricator.name] stops covering [src] with glowing orange energy.", \
- "You finish repairing [src]. It is now at [obj_integrity]/[max_integrity] integrity.")
-
-//Fabricator mob heal proc, to avoid as much copypaste as possible.
-/mob/living/proc/fabricator_heal(mob/living/user, obj/item/clockwork/replica_fabricator/fabricator)
- var/list/repair_values = list()
- if(!fabricator.fabricator_repair_checks(repair_values, src, user))
- return
- user.visible_message("[user]'s [fabricator.name] starts covering [src == user ? "[user.p_them()]" : "[src]"] in glowing orange energy...", \
- "You start repairing [src == user ? "yourself" : "[src]"]...")
- fabricator.repairing = src
- while(fabricator && user && src)
- if(!do_after(user, repair_values["healing_for_cycle"] * fabricator.speed_multiplier, target = src, \
- extra_checks = CALLBACK(fabricator, /obj/item/clockwork/replica_fabricator.proc/fabricator_repair_checks, repair_values, src, user, TRUE)))
- break
- fabricator_heal_tick(repair_values["healing_for_cycle"])
- adjust_clockwork_power(-repair_values["power_required"])
- playsound(src, 'sound/machines/click.ogg', 50, TRUE)
-
- if(fabricator)
- fabricator.repairing = null
-
- return TRUE
-
-/mob/living/proc/fabricator_heal_tick(amount)
- var/static/list/damage_heal_order = list(BRUTE, BURN, TOX, OXY)
- heal_ordered_damage(amount, damage_heal_order)
-
-/mob/living/simple_animal/fabricator_heal_tick(amount)
- adjustHealth(-amount)
-
-//Hitting a ratvar'd silicon will also try to repair it.
-/mob/living/silicon/fabrication_vals(mob/living/user, obj/item/clockwork/replica_fabricator/fabricator, silent)
- . = TRUE
- if(health == maxHealth) //if we're at maximum health, replace the turf under us
- return FALSE
- else if(fabricator_heal(user, fabricator) && user)
- user.visible_message("[user]'s [fabricator.name] stops covering [src == user ? "[user.p_them()]" : "[src]"] with glowing orange energy.", \
- "You finish repairin[src == user ? "g yourself. You are":"g [src]. [p_theyre(TRUE)]"] now at [abs(HEALTH_THRESHOLD_DEAD - health)]/[abs(HEALTH_THRESHOLD_DEAD - maxHealth)] health.")
-
-//Same with clockwork mobs.
-/mob/living/simple_animal/hostile/clockwork/fabrication_vals(mob/living/user, obj/item/clockwork/replica_fabricator/fabricator, silent)
- . = TRUE
- if(health == maxHealth) //if we're at maximum health, replace the turf under us
- return FALSE
- else if(fabricator_heal(user, fabricator) && user)
- user.visible_message("[user]'s [fabricator.name] stops covering [src == user ? "[user.p_them()]" : "[src]"] with glowing orange energy.", \
- "You finish repairin[src == user ? "g yourself. You are":"g [src]. [p_theyre(TRUE)]"] now at [health]/[maxHealth] health.")
-
-//Cogscarabs get special interaction because they're drones and have innate self-heals/revives.
-/mob/living/simple_animal/drone/cogscarab/fabrication_vals(mob/living/user, obj/item/clockwork/replica_fabricator/fabricator, silent)
- . = TRUE
- if(stat == DEAD)
- try_reactivate(user) //if we're dead, try to repair us
- return
- if(health == maxHealth)
- return FALSE
- else if(!(flags_1 & GODMODE))
- user.visible_message("[user]'s [fabricator.name] starts covering [src == user ? "[user.p_them()]" : "[src]"] in glowing orange energy...", \
- "You start repairing [src == user ? "yourself" : "[src]"]...")
- fabricator.repairing = src
- if(do_after(user, (maxHealth - health)*2, target=src))
- adjustHealth(-maxHealth)
- user.visible_message("[user]'s [fabricator.name] stops covering [src == user ? "[user.p_them()]" : "[src]"] with glowing orange energy.", \
- "You finish repairing [src == user ? "yourself" : "[src]"].")
- if(fabricator)
- fabricator.repairing = null
-
-//Convert shards and gear bits directly to power
-/obj/item/clockwork/alloy_shards/fabrication_vals(mob/living/user, obj/item/clockwork/replica_fabricator/fabricator, silent, power_amount)
- if(!power_amount)
- power_amount = -POWER_STANDARD
- consume_visual(fabricator, power_amount)
- if(!silent) //looper no looping
- for(var/obj/item/clockwork/alloy_shards/S in get_turf(src)) //convert all other shards in the turf if we can
- if(S == src)
- continue //we want the shards to be fabricated after the main shard, thus this delay
- addtimer(CALLBACK(fabricator, /obj/item/clockwork/replica_fabricator.proc/fabricate, S, user, TRUE), 0)
- return list("operation_time" = 0, "new_obj_type" = null, "power_cost" = power_amount, "spawn_dir" = SOUTH)
-
-/obj/item/clockwork/alloy_shards/medium/gear_bit/large/fabrication_vals(mob/living/user, obj/item/clockwork/replica_fabricator/fabricator, silent, power_amount)
- if(!power_amount)
- power_amount = -(CLOCKCULT_POWER_UNIT*0.08)
- return ..()
-
-/obj/item/clockwork/alloy_shards/large/fabrication_vals(mob/living/user, obj/item/clockwork/replica_fabricator/fabricator, silent, power_amount)
- if(!power_amount)
- power_amount = -(CLOCKCULT_POWER_UNIT*0.06)
- return ..()
-
-/obj/item/clockwork/alloy_shards/medium/fabrication_vals(mob/living/user, obj/item/clockwork/replica_fabricator/fabricator, silent, power_amount)
- if(!power_amount)
- power_amount = -(CLOCKCULT_POWER_UNIT*0.04)
- return ..()
-
-/obj/item/clockwork/alloy_shards/small/fabrication_vals(mob/living/user, obj/item/clockwork/replica_fabricator/fabricator, silent, power_amount)
- if(!power_amount)
- power_amount = -(CLOCKCULT_POWER_UNIT*0.02)
- return ..()
diff --git a/code/modules/antagonists/clockcult/clock_helpers/hierophant_network.dm b/code/modules/antagonists/clockcult/clock_helpers/hierophant_network.dm
deleted file mode 100644
index 37f6f0b2d77..00000000000
--- a/code/modules/antagonists/clockcult/clock_helpers/hierophant_network.dm
+++ /dev/null
@@ -1,50 +0,0 @@
-//Sends a string to all servants and optionally ghosts, who will get a follow link to whatever is provided as the target.
-/proc/hierophant_message(message, servantsonly, atom/target)
- if(!message)
- return FALSE
- for(var/M in GLOB.mob_list)
- if(!servantsonly && isobserver(M))
- if(target)
- var/link = FOLLOW_LINK(M, target)
- to_chat(M, "[link] [message]")
- else
- to_chat(M, message)
- else if(is_servant_of_ratvar(M))
- to_chat(M, message)
- return TRUE
-
-//Sends a titled message from a mob to all servants of ratvar and ghosts.
-/proc/titled_hierophant_message(mob/user, message, name_span = "heavy_brass", message_span = "brass", user_title = "Servant")
- if(!user || !message)
- return FALSE
- var/parsed_message = "[user_title ? "[user_title] ":""][findtextEx(user.name, user.real_name) ? user.name : "[user.real_name] (as [user.name])"]: \
- \"[message]\""
- hierophant_message(parsed_message, FALSE, user)
- return TRUE
-
-//Hierophant Network action, allows a servant with it to communicate to other servants.
-/datum/action/innate/hierophant
- name = "Hierophant Network"
- desc = "Allows you to communicate with other Servants."
- icon_icon = 'icons/mob/actions/actions_clockcult.dmi'
- button_icon_state = "hierophant"
- background_icon_state = "bg_clock"
- check_flags = AB_CHECK_RESTRAINED|AB_CHECK_STUN|AB_CHECK_CONSCIOUS
- buttontooltipstyle = "clockcult"
- var/title = "Servant"
- var/span_for_name = "heavy_brass"
- var/span_for_message = "brass"
-
-/datum/action/innate/hierophant/IsAvailable()
- if(!is_servant_of_ratvar(owner))
- return FALSE
- return ..()
-
-/datum/action/innate/hierophant/Activate()
- var/input = stripped_input(usr, "Please enter a message to send to other servants.", "Hierophant Network", "")
- if(!input || !IsAvailable())
- return
- if(ishuman(owner))
- clockwork_say(owner, "[text2ratvar("Servants, hear my words: [input]")]", TRUE)
- owner.log_talk(input, LOG_SAY, tag="clockwork")
- titled_hierophant_message(owner, input, span_for_name, span_for_message, title)
diff --git a/code/modules/antagonists/clockcult/clock_helpers/power_helpers.dm b/code/modules/antagonists/clockcult/clock_helpers/power_helpers.dm
deleted file mode 100644
index f927fc237d1..00000000000
--- a/code/modules/antagonists/clockcult/clock_helpers/power_helpers.dm
+++ /dev/null
@@ -1,31 +0,0 @@
-//Helper procs for clockwork power, used by structures and items and that kind of jazz.
-
-/proc/get_clockwork_power(amount) //If no amount is provided, returns the clockwork power; otherwise, returns if there's enough power for that amount.
- return amount ? GLOB.clockwork_power >= amount : GLOB.clockwork_power
-
-/proc/adjust_clockwork_power(amount) //Adjusts the global clockwork power by this amount (min 0.)
- var/current_power
- if(GLOB.ratvar_approaches)
- amount *= 0.75 //The herald's beacon reduces power costs by 25% across the board!
- if(GLOB.ratvar_awakens)
- current_power = GLOB.clockwork_power = INFINITY
- else
- current_power = GLOB.clockwork_power = CLAMP(GLOB.clockwork_power + amount, 0, MAX_CLOCKWORK_POWER)
- for(var/obj/effect/clockwork/sigil/transmission/T in GLOB.all_clockwork_objects)
- T.update_icon()
- var/unlock_message
- if(current_power >= SCRIPT_UNLOCK_THRESHOLD && !GLOB.script_scripture_unlocked)
- GLOB.script_scripture_unlocked = TRUE
- unlock_message = "The Ark swells as a key power threshold is reached. Script scriptures are now available."
- if(current_power >= APPLICATION_UNLOCK_THRESHOLD && !GLOB.application_scripture_unlocked)
- GLOB.application_scripture_unlocked = TRUE
- unlock_message = "The Ark surges as a key power threshold is reached. Application scriptures are now available."
- if(unlock_message && GLOB.servants_active)
- hierophant_message(unlock_message)
- return TRUE
-
-/proc/can_access_clockwork_power(atom/movable/access_point, amount) //Returns true if the access point has access to clockwork power (and optionally, a number of watts for it)
- if(amount && !get_clockwork_power(amount)) //No point in trying if we don't have the power anyway
- return
- var/list/possible_conduits = view(5, access_point)
- return locate(/obj/effect/clockwork/sigil/transmission) in possible_conduits || GLOB.ratvar_awakens
diff --git a/code/modules/antagonists/clockcult/clock_helpers/ratvarian_language.dm b/code/modules/antagonists/clockcult/clock_helpers/ratvarian_language.dm
deleted file mode 100644
index c784739d2ea..00000000000
--- a/code/modules/antagonists/clockcult/clock_helpers/ratvarian_language.dm
+++ /dev/null
@@ -1,111 +0,0 @@
-/*
-The Ratvarian Language
- In the lore of the Servants of Ratvar, the Ratvarian tongue is a timeless language and full of power. It sounds like gibberish, much like Nar'Sie's language, but is in fact derived from
-aforementioned language, and may induce miracles when spoken in the correct way with an amplifying tool (similar to runes used by the Nar'Sian cult).
-
- While the canon states that the language of Ratvar and his servants is incomprehensible to the unenlightened as it is a derivative of the most ancient known language, in reality it is
-actually very simple. To translate a plain English sentence to Ratvar's tongue, simply move all of the letters thirteen places ahead, starting from "a" if the end of the alphabet is reached.
-This cipher is known as "rot13" for "rotate 13 places" and there are many sites online that allow instant translation between English and rot13 - one of the benefits is that moving the translated
-sentence thirteen places ahead changes it right back to plain English.
-
- There are, however, a few parts of the Ratvarian tongue that aren't typical and are implemented for fluff reasons. Some words may have graves, or hyphens (prefix and postfix), making the plain
-English translation apparent but disjoined (for instance, "Orubyq zl-cbjre!" translates directly to "Behold my-power!") although this can be ignored without impacting overall quality. When
-translating from Ratvar's tongue to plain English, simply remove the disjointments and use the finished sentence. This would make "Orubyq zl-cbjre!" into "Behold my power!" after removing the
-abnormal spacing, hyphens, and grave accents.
-
-List of nuances:
-- Any time the WORD "of" occurs, it is linked to the previous word by a hyphen. (i.e. "V nz-bs Ratvar." directly translates to "I am-of Ratvar.")
-- Any time "th", followed by any two letters occurs, you add a grave (`) between those two letters, i.e; "Thi`s"
-- In the same vein, any time "ti", followed by one letter occurs, you add a grave (`) between "i" and the letter, i.e; "Ti`me"
-- Whereever "te" or "et" appear and there is another letter next to the e(i.e; "m"etal, greate"r"), add a hyphen between "e" and the letter, i.e; "M-etal", "Greate-r"
-- Where "gua" appears, add a hyphen between "gu" and "a", i.e "Gu-ard"
-- Where the WORD "and" appears it is linked to all surrounding words by hyphens, i.e; "Sword-and-shield"
-- Where the WORD "to" appears, it is linked to the following word by a hyphen, i.e; "to-use"
-- Where the WORD "my" appears, it is linked to the following word by a hyphen, i.e; "my-light"
-- Although "Ratvar" translates to "Engine" in English, the word "Ratvar" is used regardless of language as it is a proper noun.
- - The same rule applies to Ratvar's four generals: Nezbere (Armorer), Sevtug (Fright), Nzcrentr (Amperage), and Inath-neq (Vangu-Ard), although these words can be used in proper context if one is
- not referring to the four generals and simply using the words themselves.
-*/
-
-//Regexes used to alter english to ratvarian style
-#define RATVAR_OF_MATCH regex("(\\w)\\s(\[oO]\[fF])","g")
-#define RATVAR_OF_REPLACEMENT "$1-$2"
-#define RATVAR_GUA_MATCH regex("(\[gG]\[uU])(\[aA])","g")
-#define RATVAR_GUA_REPLACEMENT "$1-$2"
-#define RATVAR_TH_MATCH regex("(\[tT]\[hH]\\w)(\\w)","g")
-#define RATVAR_TH_REPLACEMENT "$1`$2"
-#define RATVAR_TI_MATCH regex("(\[tT]\[iI])(\\w)","g")
-#define RATVAR_TI_REPLACEMENT "$1`$2"
-#define RATVAR_ET_MATCH regex("(\\w)(\[eE]\[tT])","g")
-#define RATVAR_ET_REPLACEMENT "$1-$2"
-#define RATVAR_TE_MATCH regex("(\[tT]\[eE])(\\w)","g")
-#define RATVAR_TE_REPLACEMENT "$1-$2"
-#define RATVAR_PRE_AND_MATCH regex("(\\w)\\s(\[aA]\[nN]\[dD])(\\W)","g")
-#define RATVAR_PRE_AND_REPLACEMENT "$1-$2$3"
-#define RATVAR_POST_AND_MATCH regex("(\\W)(\[aA]\[nN]\[dD])\\s(\\w)","g")
-#define RATVAR_POST_AND_REPLACEMENT "$1$2-$3"
-#define RATVAR_TO_MATCH regex("(\\s)(\[tT]\[oO])\\s(\\w)","g")
-#define RATVAR_TO_REPLACEMENT "$1$2-$3"
-#define RATVAR_MY_MATCH regex("(\\s)(\[mM]\[yY])\\s(\\w)","g")
-#define RATVAR_MY_REPLACEMENT "$1$2-$3"
-
-//Regexes used to remove ratvarian styling from english
-#define REVERSE_RATVAR_HYPHEN_PRE_AND_MATCH regex("(\\w)-(\[aA]\[nN]\[dD])","g") //specifically structured to support -emphasis-, including with -and-
-#define REVERSE_RATVAR_HYPHEN_PRE_AND_REPLACEMENT "$1 $2"
-#define REVERSE_RATVAR_HYPHEN_POST_AND_MATCH regex("(\[aA]\[nN]\[dD])-(\\w)","g")
-#define REVERSE_RATVAR_HYPHEN_POST_AND_REPLACEMENT "$1 $2"
-#define REVERSE_RATVAR_HYPHEN_TO_MY_MATCH regex("(\[tTmM]\[oOyY])-","g")
-#define REVERSE_RATVAR_HYPHEN_TO_MY_REPLACEMENT "$1 "
-#define REVERSE_RATVAR_HYPHEN_TE_MATCH regex("(\[tT]\[eE])-","g")
-#define REVERSE_RATVAR_HYPHEN_TE_REPLACEMENT "$1"
-#define REVERSE_RATVAR_HYPHEN_ET_MATCH regex("-(\[eE]\[tT])","g")
-#define REVERSE_RATVAR_HYPHEN_ET_REPLACEMENT "$1"
-#define REVERSE_RATVAR_HYPHEN_GUA_MATCH regex("(\[gG]\[uU])-(\[aA])","g")
-#define REVERSE_RATVAR_HYPHEN_GUA_REPLACEMENT "$1$2"
-#define REVERSE_RATVAR_HYPHEN_OF_MATCH regex("-(\[oO]\[fF])","g")
-#define REVERSE_RATVAR_HYPHEN_OF_REPLACEMENT " $1"
-
-
-/proc/text2ratvar(text) //Takes english and applies ratvarian styling rules (and rot13) to it.
- var/ratvarian = add_ratvarian_regex(text) //run the regexes twice, so that you catch people translating it beforehand
- ratvarian = rot13(ratvarian)
- return add_ratvarian_regex(ratvarian)
-
-/proc/add_ratvarian_regex(text)
- var/ratvarian = replacetext(text, RATVAR_OF_MATCH, RATVAR_OF_REPLACEMENT)
- ratvarian = replacetext(ratvarian, RATVAR_GUA_MATCH, RATVAR_GUA_REPLACEMENT)
- ratvarian = replacetext(ratvarian, RATVAR_TH_MATCH, RATVAR_TH_REPLACEMENT)
- ratvarian = replacetext(ratvarian, RATVAR_TI_MATCH, RATVAR_TI_REPLACEMENT)
- ratvarian = replacetext(ratvarian, RATVAR_ET_MATCH, RATVAR_ET_REPLACEMENT)
- ratvarian = replacetext(ratvarian, RATVAR_TE_MATCH, RATVAR_TE_REPLACEMENT)
- ratvarian = replacetext(ratvarian, RATVAR_PRE_AND_MATCH, RATVAR_PRE_AND_REPLACEMENT)
- ratvarian = replacetext(ratvarian, RATVAR_POST_AND_MATCH, RATVAR_POST_AND_REPLACEMENT)
- ratvarian = replacetext(ratvarian, RATVAR_TO_MATCH, RATVAR_TO_REPLACEMENT)
- return replacetext(ratvarian, RATVAR_MY_MATCH, RATVAR_MY_REPLACEMENT)
-
-/proc/ratvar2text(ratvarian) //Reverts ravarian styling and rot13 in text.
- var/text = remove_ratvarian_regex(ratvarian) //run the regexes twice, so that you catch people translating it beforehand
- text = replacetext(rot13(text), "`", "")
- return remove_ratvarian_regex(text)
-
-/proc/remove_ratvarian_regex(ratvarian)
- var/text = replacetext(ratvarian, REVERSE_RATVAR_HYPHEN_GUA_MATCH, REVERSE_RATVAR_HYPHEN_GUA_REPLACEMENT)
- text = replacetext(text, REVERSE_RATVAR_HYPHEN_PRE_AND_MATCH, REVERSE_RATVAR_HYPHEN_PRE_AND_REPLACEMENT)
- text = replacetext(text, REVERSE_RATVAR_HYPHEN_POST_AND_MATCH, REVERSE_RATVAR_HYPHEN_POST_AND_REPLACEMENT)
- text = replacetext(text, REVERSE_RATVAR_HYPHEN_TO_MY_MATCH, REVERSE_RATVAR_HYPHEN_TO_MY_REPLACEMENT)
- text = replacetext(text, REVERSE_RATVAR_HYPHEN_TE_MATCH, REVERSE_RATVAR_HYPHEN_TE_REPLACEMENT)
- text = replacetext(text, REVERSE_RATVAR_HYPHEN_ET_MATCH, REVERSE_RATVAR_HYPHEN_ET_REPLACEMENT)
- return replacetext(text, REVERSE_RATVAR_HYPHEN_OF_MATCH, REVERSE_RATVAR_HYPHEN_OF_REPLACEMENT)
-
-//Causes the mob or AM in question to speak a message; it assumes that the message is already translated to ratvar speech using text2ratvar()
-/proc/clockwork_say(atom/movable/AM, message, whisper=FALSE)
- var/list/spans = list(SPAN_ROBOT)
-
- if(isliving(AM))
- var/mob/living/L = AM
- if(!whisper)
- L.say(message, "clock", spans, language=/datum/language/common, ignore_spam = TRUE)
- else
- L.whisper(message, "clock", spans, language=/datum/language/common)
- else
- AM.say(message, language=/datum/language/common)
diff --git a/code/modules/antagonists/clockcult/clock_helpers/scripture_checks.dm b/code/modules/antagonists/clockcult/clock_helpers/scripture_checks.dm
deleted file mode 100644
index e5497d7c9f8..00000000000
--- a/code/modules/antagonists/clockcult/clock_helpers/scripture_checks.dm
+++ /dev/null
@@ -1,53 +0,0 @@
-//returns a list of scriptures and if they're unlocked or not
-/proc/scripture_unlock_check()
- . = list(SCRIPTURE_DRIVER = TRUE, SCRIPTURE_SCRIPT = FALSE, SCRIPTURE_APPLICATION = FALSE)
- //Drivers: always unlocked
-
- .[SCRIPTURE_SCRIPT] = GLOB.script_scripture_unlocked
- //Script: Convert a new servant using a sigil of submission.
-
- .[SCRIPTURE_APPLICATION] = GLOB.application_scripture_unlocked
- //Application: APPLICATION_SERVANT_REQ or more non-brain servants, APPLICATION_CACHE_REQ or more clockwork caches, and at least APPLICATION_CV_REQ CV
-
-//reports to servants when scripture is locked or unlocked
-/proc/scripture_unlock_alert(list/previous_states)
- . = scripture_unlock_check()
- if(!GLOB.servants_active)
- return
- for(var/i in .)
- if(.[i] != previous_states[i])
- update_slab_info()
- for(var/mob/M in GLOB.player_list)
- if(is_servant_of_ratvar(M) || isobserver(M))
- M.playsound_local(M, 'sound/magic/clockwork/scripture_tier_up.ogg', 50, FALSE, pressure_affected = FALSE)
-
-/proc/update_slab_info(obj/item/clockwork/slab/set_slab)
- generate_all_scripture()
- var/needs_update = FALSE //if everything needs an update, for whatever reason
- for(var/s in GLOB.all_scripture)
- var/datum/clockwork_scripture/S = GLOB.all_scripture[s]
- if(S.creation_update())
- needs_update = TRUE
- if(!set_slab || needs_update)
- for(var/obj/item/clockwork/slab/S in GLOB.all_clockwork_objects)
- SStgui.update_uis(S)
- if(needs_update)
- S.update_quickbind()
- else
- SStgui.update_uis(set_slab)
- set_slab.update_quickbind()
-
-/proc/generate_all_scripture()
- if(!GLOB.all_scripture.len)
- for(var/V in sortList(subtypesof(/datum/clockwork_scripture), /proc/cmp_clockscripture_priority))
- var/datum/clockwork_scripture/S = new V
- GLOB.all_scripture[S.type] = S
-
-//changes construction value
-/proc/change_construction_value(amount)
- if(!SSticker.current_state != GAME_STATE_PLAYING) //This is primarily so that structures added pre-roundstart don't contribute to construction value
- return
- GLOB.clockwork_construction_value = max(0, GLOB.clockwork_construction_value + amount)
-
-/proc/can_recite_scripture(mob/living/L, can_potentially)
- return (is_servant_of_ratvar(L) && (can_potentially || (L.stat == CONSCIOUS && L.can_speak_vocal())) && (GLOB.ratvar_awakens || (ishuman(L) || issilicon(L))))
diff --git a/code/modules/antagonists/clockcult/clock_helpers/slab_abilities.dm b/code/modules/antagonists/clockcult/clock_helpers/slab_abilities.dm
deleted file mode 100644
index 16e26682cd1..00000000000
--- a/code/modules/antagonists/clockcult/clock_helpers/slab_abilities.dm
+++ /dev/null
@@ -1,271 +0,0 @@
-//The base for slab-bound/based ranged abilities
-/obj/effect/proc_holder/slab
- var/obj/item/clockwork/slab/slab
- var/successful = FALSE
- var/finished = FALSE
- var/in_progress = FALSE
-
-/obj/effect/proc_holder/slab/Destroy()
- slab = null
- return ..()
-
-/obj/effect/proc_holder/slab/remove_ranged_ability(msg)
- ..()
- finished = TRUE
- QDEL_IN(src, 6)
-
-/obj/effect/proc_holder/slab/InterceptClickOn(mob/living/caller, params, atom/target)
- if(..() || in_progress)
- return TRUE
- if(ranged_ability_user.incapacitated() || !slab || !(slab in ranged_ability_user.held_items) || target == slab)
- remove_ranged_ability()
- return TRUE
-
-//For the Hateful Manacles scripture; applies replicant handcuffs to the target.
-/obj/effect/proc_holder/slab/hateful_manacles
-
-/obj/effect/proc_holder/slab/hateful_manacles/InterceptClickOn(mob/living/caller, params, atom/target)
- if(..())
- return TRUE
-
- var/turf/T = ranged_ability_user.loc
- if(!isturf(T))
- return TRUE
-
- if(iscarbon(target) && target.Adjacent(ranged_ability_user))
- var/mob/living/carbon/L = target
- if(is_servant_of_ratvar(L))
- to_chat(ranged_ability_user, "\"[L.p_theyre(TRUE)] a servant.\"")
- return TRUE
- else if(L.stat)
- to_chat(ranged_ability_user, "\"There is use in shackling the dead, but for examples.\"")
- return TRUE
- else if (istype(L.handcuffed,/obj/item/restraints/handcuffs/clockwork))
- to_chat(ranged_ability_user, "\"[L.p_theyre(TRUE)] already helpless, no?\"")
- return TRUE
-
- playsound(loc, 'sound/weapons/handcuffs.ogg', 30, TRUE)
- ranged_ability_user.visible_message("[ranged_ability_user] begins forming manacles around [L]'s wrists!", \
- "You begin shaping replicant alloy into manacles around [L]'s wrists...")
- to_chat(L, "[ranged_ability_user] begins forming manacles around your wrists!")
- if(do_mob(ranged_ability_user, L, 30))
- if(!(istype(L.handcuffed,/obj/item/restraints/handcuffs/clockwork)))
- L.handcuffed = new/obj/item/restraints/handcuffs/clockwork(L)
- L.update_handcuffed()
- to_chat(ranged_ability_user, "You shackle [L].")
- log_combat(ranged_ability_user, L, "handcuffed")
- else
- to_chat(ranged_ability_user, "You fail to shackle [L].")
-
- successful = TRUE
-
- remove_ranged_ability()
-
- return TRUE
-
-/obj/item/restraints/handcuffs/clockwork
- name = "replicant manacles"
- desc = "Heavy manacles made out of freezing-cold metal. It looks like brass, but feels much more solid."
- icon_state = "brass_manacles"
- item_flags = DROPDEL
-
-/obj/item/restraints/handcuffs/clockwork/dropped(mob/user)
- user.visible_message("[user]'s [name] come apart at the seams!", \
- "Your [name] break apart as they're removed!")
- . = ..()
-
-//For the Sentinel's Compromise scripture; heals a target servant.
-/obj/effect/proc_holder/slab/compromise
- ranged_mousepointer = 'icons/effects/compromise_target.dmi'
-
-/obj/effect/proc_holder/slab/compromise/InterceptClickOn(mob/living/caller, params, atom/target)
- if(..())
- return TRUE
-
- var/turf/T = ranged_ability_user.loc
- if(!isturf(T))
- return TRUE
-
- if(isliving(target) && (target in view(7, get_turf(ranged_ability_user))))
- var/mob/living/L = target
- if(!is_servant_of_ratvar(L))
- to_chat(ranged_ability_user, "\"[L] does not yet serve Ratvar.\"")
- return TRUE
- if(L.stat == DEAD)
- to_chat(ranged_ability_user, "\"[L.p_theyre(TRUE)] dead. [text2ratvar("Oh, child. To have your life cut short...")]\"")
- return TRUE
-
- var/brutedamage = L.getBruteLoss()
- var/burndamage = L.getFireLoss()
- var/oxydamage = L.getOxyLoss()
- var/totaldamage = brutedamage + burndamage + oxydamage
- if(!totaldamage && (!L.reagents || !L.reagents.has_reagent(/datum/reagent/water/holywater)))
- to_chat(ranged_ability_user, "\"[L] is unhurt and untainted.\"")
- return TRUE
-
- successful = TRUE
-
- to_chat(ranged_ability_user, "You bathe [L == ranged_ability_user ? "yourself":"[L]"] in Inath-neq's power!")
- var/targetturf = get_turf(L)
- var/has_holy_water = (L.reagents && L.reagents.has_reagent(/datum/reagent/water/holywater))
- var/healseverity = max(round(totaldamage*0.05, 1), 1) //shows the general severity of the damage you just healed, 1 glow per 20
- for(var/i in 1 to healseverity)
- new /obj/effect/temp_visual/heal(targetturf, "#1E8CE1")
- if(totaldamage)
- L.adjustBruteLoss(-brutedamage)
- L.adjustFireLoss(-burndamage)
- L.adjustOxyLoss(-oxydamage)
- L.adjustToxLoss(totaldamage * 0.5, TRUE, TRUE)
- clockwork_say(ranged_ability_user, text2ratvar("[has_holy_water ? "Heal tainted" : "Mend wounded"] flesh!"))
- log_combat(ranged_ability_user, L, "healed with Sentinel's Compromise")
- L.visible_message("A blue light washes over [L], [has_holy_water ? "causing [L.p_them()] to briefly glow as it mends" : " mending"] [L.p_their()] bruises and burns!", \
- "You feel Inath-neq's power healing your wounds[has_holy_water ? " and purging the darkness within you" : ""], but a deep nausea overcomes you!")
- else
- clockwork_say(ranged_ability_user, text2ratvar("Purge foul darkness!"))
- log_combat(ranged_ability_user, L, "purged of holy water with Sentinel's Compromise")
- L.visible_message("A blue light washes over [L], causing [L.p_them()] to briefly glow!", \
- "You feel Inath-neq's power purging the darkness within you!")
- playsound(targetturf, 'sound/magic/staff_healing.ogg', 50, TRUE)
-
- if(has_holy_water)
- L.reagents.remove_reagent(/datum/reagent/water/holywater, 1000)
-
- remove_ranged_ability()
-
- return TRUE
-
-//For the Kindle scripture; stuns and mutes a target non-servant.
-/obj/effect/proc_holder/slab/kindle
- ranged_mousepointer = 'icons/effects/volt_target.dmi'
-
-/obj/effect/proc_holder/slab/kindle/InterceptClickOn(mob/living/caller, params, atom/target)
- if(..())
- return TRUE
-
- var/turf/T = ranged_ability_user.loc
- if(!isturf(T))
- return TRUE
-
- if(target in view(7, get_turf(ranged_ability_user)))
-
- successful = TRUE
-
- var/turf/U = get_turf(target)
- to_chat(ranged_ability_user, "You release the light of Ratvar!")
- clockwork_say(ranged_ability_user, text2ratvar("Purge all untruths and honor Engine!"))
- log_combat(ranged_ability_user, U, "fired at with Kindle")
- playsound(ranged_ability_user, 'sound/magic/blink.ogg', 50, TRUE, frequency = 0.5)
- var/obj/projectile/kindle/A = new(T)
- A.preparePixelProjectile(target, caller, params)
- A.fire()
-
- remove_ranged_ability()
-
- return TRUE
-
-/obj/projectile/kindle
- name = "kindled flame"
- icon_state = "pulse0"
- nodamage = TRUE
- damage = 0 //We're just here for the stunning!
- damage_type = BURN
- flag = "bomb"
- range = 3
- log_override = TRUE
-
-/obj/projectile/kindle/Destroy()
- visible_message("[src] flickers out!")
- . = ..()
-
-/obj/projectile/kindle/on_hit(atom/target, blocked = FALSE)
- if(isliving(target))
- var/mob/living/L = target
- if(is_servant_of_ratvar(L) || L.stat || L.has_status_effect(STATUS_EFFECT_KINDLE))
- return BULLET_ACT_HIT
- var/atom/O = L.anti_magic_check()
- playsound(L, 'sound/magic/fireball.ogg', 50, TRUE, frequency = 1.25)
- if(O)
- if(isitem(O))
- L.visible_message("[L]'s eyes flare with dim light!", \
- "Your [O] glows white-hot against you as it absorbs [src]'s power!")
- else if(ismob(O))
- L.visible_message("[L]'s eyes flare with dim light!")
- playsound(L, 'sound/weapons/sear.ogg', 50, TRUE)
- else
- L.visible_message("[L]'s eyes blaze with brilliant light!", \
- "Your vision suddenly screams with white-hot light!")
- L.Paralyze(15)
- L.apply_status_effect(STATUS_EFFECT_KINDLE)
- L.flash_act(1, 1)
- if(iscultist(L))
- L.adjustFireLoss(15)
- ..()
-
-
-//For the cyborg Linked Vanguard scripture, grants you and a nearby ally Vanguard
-/obj/effect/proc_holder/slab/vanguard
- ranged_mousepointer = 'icons/effects/vanguard_target.dmi'
-
-/obj/effect/proc_holder/slab/vanguard/InterceptClickOn(mob/living/caller, params, atom/target)
- if(..())
- return TRUE
-
- var/turf/T = ranged_ability_user.loc
- if(!isturf(T))
- return TRUE
-
- if(isliving(target) && (target in view(7, get_turf(ranged_ability_user))))
- var/mob/living/L = target
- if(!is_servant_of_ratvar(L))
- to_chat(ranged_ability_user, "\"[L] does not yet serve Ratvar.\"")
- return TRUE
- if(L.stat == DEAD)
- to_chat(ranged_ability_user, "\"[L.p_theyre(TRUE)] dead. [text2ratvar("Oh, child. To have your life cut short...")]\"")
- return TRUE
- if(islist(L.stun_absorption) && L.stun_absorption["vanguard"] && L.stun_absorption["vanguard"]["end_time"] > world.time)
- to_chat(ranged_ability_user, "\"[L.p_theyre(TRUE)] already shielded by a Vanguard.\"")
- return TRUE
-
- successful = TRUE
-
- if(L == ranged_ability_user)
- for(var/mob/living/LT in spiral_range(7, T))
- if(LT.stat == DEAD || !is_servant_of_ratvar(LT) || LT == ranged_ability_user || !(LT in view(7, get_turf(ranged_ability_user))) || \
- (islist(LT.stun_absorption) && LT.stun_absorption["vanguard"] && LT.stun_absorption["vanguard"]["end_time"] > world.time))
- continue
- L = LT
- break
-
- L.apply_status_effect(STATUS_EFFECT_VANGUARD)
- ranged_ability_user.apply_status_effect(STATUS_EFFECT_VANGUARD)
-
- clockwork_say(ranged_ability_user, text2ratvar("Shield us from darkness!"))
-
- remove_ranged_ability()
-
- return TRUE
-
-//For the cyborg Judicial Marker scripture, places a judicial marker
-/obj/effect/proc_holder/slab/judicial
- ranged_mousepointer = 'icons/effects/visor_reticule.dmi'
-
-/obj/effect/proc_holder/slab/judicial/InterceptClickOn(mob/living/caller, params, atom/target)
- if(..())
- return TRUE
-
- var/turf/T = ranged_ability_user.loc
- if(!isturf(T))
- return TRUE
-
- if(target in view(7, get_turf(ranged_ability_user)))
- successful = TRUE
-
- clockwork_say(ranged_ability_user, text2ratvar("Kneel, heathens!"))
- ranged_ability_user.visible_message("[ranged_ability_user]'s eyes fire a stream of energy at [target], creating a strange mark!", \
- "You direct the judicial force to [target].")
- var/turf/targetturf = get_turf(target)
- new/obj/effect/clockwork/judicial_marker(targetturf, ranged_ability_user)
- log_combat(ranged_ability_user, targetturf, "created a judicial marker")
- remove_ranged_ability()
-
- return TRUE
diff --git a/code/modules/antagonists/clockcult/clock_item.dm b/code/modules/antagonists/clockcult/clock_item.dm
deleted file mode 100644
index 7c8e877fb3b..00000000000
--- a/code/modules/antagonists/clockcult/clock_item.dm
+++ /dev/null
@@ -1,24 +0,0 @@
-//The base clockwork item. Can have an alternate desc and will show up in the list of clockwork objects.
-/obj/item/clockwork
- name = "meme blaster"
- desc = "What the fuck is this? It looks kinda like a frog."
- resistance_flags = FIRE_PROOF | ACID_PROOF
- var/clockwork_desc = "A fabled artifact from beyond the stars. Contains concentrated meme essence." //Shown to clockwork cultists instead of the normal description
- icon = 'icons/obj/clockwork_objects.dmi'
- icon_state = "rare_pepe"
- w_class = WEIGHT_CLASS_SMALL
-
-/obj/item/clockwork/Initialize()
- . = ..()
- ratvar_act()
- GLOB.all_clockwork_objects += src
-
-/obj/item/clockwork/Destroy()
- GLOB.all_clockwork_objects -= src
- return ..()
-
-/obj/item/clockwork/examine(mob/user)
- if((is_servant_of_ratvar(user) || isobserver(user)) && clockwork_desc)
- desc = clockwork_desc
- . = ..()
- desc = initial(desc)
diff --git a/code/modules/antagonists/clockcult/clock_items/clock_components.dm b/code/modules/antagonists/clockcult/clock_items/clock_components.dm
deleted file mode 100644
index a9307f15e13..00000000000
--- a/code/modules/antagonists/clockcult/clock_items/clock_components.dm
+++ /dev/null
@@ -1,239 +0,0 @@
-//Components: Used in scripture.
-/obj/item/clockwork/component
- name = "meme component"
- desc = "A piece of a famous meme."
- clockwork_desc = null
- resistance_flags = LAVA_PROOF | FIRE_PROOF | ACID_PROOF
- var/component_id //What the component is identified as
- var/cultist_message = "You are not worthy of this meme." //Showed to Nar'Sian cultists if they pick up the component in addition to chaplains
- var/list/servant_of_ratvar_messages = list("ayy" = FALSE, "lmao" = TRUE) //Fluff, shown to servants of Ratvar on a low chance, if associated value is TRUE, will automatically apply ratvarian
- var/message_span = "heavy_brass"
-
-/obj/item/clockwork/component/examine(mob/user)
- . = ..()
- if(is_servant_of_ratvar(user) || isobserver(user))
- . += "You can activate this in your hand to break it down for power."
-
-/obj/item/clockwork/component/attack_self(mob/living/user)
- if(is_servant_of_ratvar(user))
- user.visible_message("[user] crushes [src] in [user.p_their()] hand!", \
- "You crush [src], capturing its escaping energy for use as power.")
- playsound(user, 'sound/effects/pop_expl.ogg', 50, TRUE)
- adjust_clockwork_power(POWER_WALL_TOTAL)
- qdel(src)
-
-/obj/item/clockwork/component/pickup(mob/living/user)
- ..()
- if(iscultist(user) || (user.mind && user.mind.isholy))
- to_chat(user, "[cultist_message]")
- if(user.mind && user.mind.isholy)
- to_chat(user, "The power of your faith melts away [src]!")
- var/obj/item/stack/ore/slag/wrath = new /obj/item/stack/ore/slag
- qdel(src)
- user.put_in_active_hand(wrath)
- if(is_servant_of_ratvar(user) && prob(20))
- var/pickedmessage = pick(servant_of_ratvar_messages)
- to_chat(user, "[servant_of_ratvar_messages[pickedmessage] ? "[text2ratvar(pickedmessage)]" : pickedmessage]")
-
-/obj/item/clockwork/component/belligerent_eye
- name = "belligerent eye"
- desc = "A brass construct with a rotating red center. It's as though it's looking for something to hurt."
- icon_state = "belligerent_eye"
- component_id = BELLIGERENT_EYE
- cultist_message = "The eye gives you an intensely hateful glare."
- servant_of_ratvar_messages = list("\"...\"" = FALSE, "For a moment, your mind is flooded with extremely violent thoughts." = FALSE, "\"...Die.\"" = TRUE)
- message_span = "neovgre"
-
-/obj/item/clockwork/component/belligerent_eye/blind_eye
- name = "blind eye"
- desc = "A heavy brass eye, its red iris fallen dark."
- clockwork_desc = "A smashed ocular warden covered in dents."
- icon_state = "blind_eye"
- cultist_message = "The eye flickers at you with intense hate before falling dark."
- servant_of_ratvar_messages = list("The eye flickers before falling dark." = FALSE, "You feel watched." = FALSE, "\"...\"" = FALSE)
- w_class = WEIGHT_CLASS_NORMAL
-
-/obj/item/clockwork/component/belligerent_eye/lens_gem
- name = "lens gem"
- desc = "A tiny pinkish gem. It catches the light oddly, almost glowing."
- clockwork_desc = "The gem from an interdiction lens."
- icon_state = "lens_gem"
- cultist_message = "The gem turns black and cold for a moment before its normal glow returns."
- servant_of_ratvar_messages = list("\"Disgusting failure.\"" = TRUE, "You feel scrutinized." = FALSE, "\"Weaklings.\"" = TRUE, "\"Pathetic defenses.\"" = TRUE)
- w_class = WEIGHT_CLASS_TINY
- light_range = 1.4
- light_power = 0.4
- light_color = "#F42B9D"
-
-/obj/item/clockwork/component/vanguard_cogwheel
- name = "vanguard cogwheel"
- desc = "A sturdy brass cog with a faintly glowing blue gem in its center."
- icon_state = "vanguard_cogwheel"
- component_id = VANGUARD_COGWHEEL
- cultist_message = "\"Pray to your god that we never meet.\""
- servant_of_ratvar_messages = list("\"Be safe, child.\"" = FALSE, "You feel unexplainably comforted." = FALSE, "\"Never forget: Pain is temporary. What you do for the Justiciar is eternal.\"" = FALSE)
- message_span = "inathneq"
-
-/obj/item/clockwork/component/vanguard_cogwheel/onyx_prism
- name = "onyx prism"
- desc = "An onyx prism with a small aperture. It's very heavy."
- clockwork_desc = "A broken prism from a prolonging prism."
- icon_state = "onyx_prism"
- cultist_message = "The prism grows painfully hot in your hands."
- servant_of_ratvar_messages = list("The prism isn't getting any lighter." = FALSE, "\"So... you haven't failed yet. Have hope, child.\"" = TRUE, \
- "\"Better these machines break than you do.\"" = TRUE)
- w_class = WEIGHT_CLASS_NORMAL
-
-/obj/item/clockwork/component/geis_capacitor
- name = "geis capacitor"
- desc = "A curiously cold brass doodad. It seems as though it really doesn't appreciate being held."
- icon_state = "geis_capacitor"
- component_id = GEIS_CAPACITOR
- cultist_message = "\"Try not to lose your mind - I'll need it. Heh heh...\""
- servant_of_ratvar_messages = list("\"Disgusting.\"" = FALSE, "\"Well, aren't you an inquisitive fellow?\"" = FALSE, "A foul presence pervades your mind, then vanishes." = FALSE, \
- "\"The fact that Ratvar has to depend on simpletons like you is appalling.\"" = FALSE)
- message_span = "sevtug"
-
-/obj/item/clockwork/component/geis_capacitor/fallen_armor
- name = "fallen armor"
- desc = "Lifeless chunks of armor. They're designed in a strange way and won't fit on you."
- clockwork_desc = "The armor from a former clockwork marauder. Serviceable as a substitute for a geis capacitor."
- icon_state = "fallen_armor"
- cultist_message = "Red flame sputters from the mask's eye before winking out."
- servant_of_ratvar_messages = list("A piece of armor hovers away from the others for a moment." = FALSE, "Red flame appears in the cuirass before sputtering out." = FALSE)
- w_class = WEIGHT_CLASS_NORMAL
-
-/obj/item/clockwork/component/geis_capacitor/antennae
- name = "mania motor antennae"
- desc = "A pair of dented and bent antennae. They constantly emit a static hiss."
- clockwork_desc = "The antennae from a mania motor."
- icon_state = "mania_motor_antennae"
- cultist_message = "Your head is filled with a burst of static."
- servant_of_ratvar_messages = list("\"Who broke this.\"" = TRUE, "\"Did you break these off YOURSELF?\"" = TRUE, "\"Why did we give this to such simpletons, anyway?\"" = TRUE, \
- "\"At least we can use these for something - unlike you.\"" = TRUE)
-
-/obj/item/clockwork/component/replicant_alloy
- name = "replicant alloy"
- desc = "A seemingly strong but very malleable chunk of metal. It seems as though it wants to be molded into something greater."
- icon_state = "replicant_alloy"
- component_id = REPLICANT_ALLOY
- cultist_message = "The alloy takes on the appearance of a screaming face for a moment."
- servant_of_ratvar_messages = list("\"There's always something to be done. Get to it.\"" = FALSE, "\"Idle hands are worse than broken ones. Get to work.\"" = FALSE, \
- "A detailed image of Ratvar appears in the alloy for a moment." = FALSE)
- message_span = "nezbere"
-
-/obj/item/clockwork/component/replicant_alloy/smashed_anima_fragment
- name = "smashed anima fragment"
- desc = "Shattered chunks of metal. Damaged beyond repair and completely unusable."
- clockwork_desc = "The sad remains of an anima fragment."
- icon_state = "smashed_anime_fragment"
- cultist_message = "The shards vibrate in your hands for a moment."
- servant_of_ratvar_messages = list("\"...still fight...\"" = FALSE, "\"...where am I...?\"" = FALSE, "\"...bring me... back...\"" = FALSE)
- w_class = WEIGHT_CLASS_NORMAL
-
-/obj/item/clockwork/component/replicant_alloy/replication_plate
- name = "replication plate"
- desc = "A flat, heavy disc of metal with a triangular formation on its surface."
- clockwork_desc = "The replication plate from a tinkerer's daemon."
- icon_state = "replication_plate"
- cultist_message = "The plate shudders in your hands, as though trying to get away."
- servant_of_ratvar_messages = list("\"Put this in a slab and get back to work.\"" = FALSE, "\"Worse servants than you have held these.\"" = TRUE, \
- "\"It would be wise to protect these better, friend.\"" = TRUE)
- w_class = WEIGHT_CLASS_NORMAL
-
-/obj/item/clockwork/component/hierophant_ansible
- name = "hierophant ansible"
- desc = "Some sort of transmitter? It seems as though it's trying to say something."
- icon_state = "hierophant_ansible"
- component_id = HIEROPHANT_ANSIBLE
- cultist_message = "\"Gur obff fnlf vg'f abg ntnvafg gur ehyrf gb-xvyy lbh.\""
- servant_of_ratvar_messages = list("\"Exile is such a bore. There's nothing I can hunt in here.\"" = TRUE, "\"What's keeping you? I want to go kill something.\"" = TRUE, \
- "\"HEHEHEHEHEHEH!\"" = FALSE, "\"If I killed you fast enough, do you think the boss would notice?\"" = TRUE)
- message_span = "nzcrentr"
-
-/obj/item/clockwork/component/hierophant_ansible/obelisk
- name = "obelisk prism"
- desc = "A prism that occasionally glows brightly. It seems not-quite there."
- clockwork_desc = "The prism from a clockwork obelisk."
- cultist_message = "The prism flickers wildly in your hands before resuming its normal glow."
- servant_of_ratvar_messages = list("You hear the distinctive sound of the Hierophant Network for a moment." = FALSE, "\"Hieroph'ant Br'o'adcas't fail'ure.\"" = TRUE, \
- "The obelisk flickers wildly, as if trying to open a gateway." = FALSE, "\"Spa'tial Ga'tewa'y fai'lure.\"" = TRUE)
- icon_state = "obelisk_prism"
- w_class = WEIGHT_CLASS_NORMAL
-
-//Shards of Alloy, suitable only as a source of power for a replica fabricator.
-/obj/item/clockwork/alloy_shards
- name = "replicant alloy shards"
- desc = "Broken shards of some oddly malleable metal. They occasionally move and seem to glow."
- clockwork_desc = "Broken shards of replicant alloy."
- icon_state = "alloy_shards"
- resistance_flags = LAVA_PROOF | FIRE_PROOF | ACID_PROOF
- var/randomsinglesprite = FALSE
- var/randomspritemax = 2
- var/sprite_shift = 9
-
-/obj/item/clockwork/alloy_shards/Initialize()
- . = ..()
- if(randomsinglesprite)
- replace_name_desc()
- icon_state = "[icon_state][rand(1, randomspritemax)]"
- pixel_x = rand(-sprite_shift, sprite_shift)
- pixel_y = rand(-sprite_shift, sprite_shift)
-
-/obj/item/clockwork/alloy_shards/examine(mob/user)
- . = ..()
- if(is_servant_of_ratvar(user) || isobserver(user))
- . += "Can be consumed by a replica fabricator as a source of power."
-
-/obj/item/clockwork/alloy_shards/proc/replace_name_desc()
- name = "replicant alloy shard"
- desc = "A broken shard of some oddly malleable metal. It occasionally moves and seems to glow."
- clockwork_desc = "A broken shard of replicant alloy."
-
-/obj/item/clockwork/alloy_shards/clockgolem_remains
- name = "clockwork golem scrap"
- desc = "A pile of scrap metal. It seems damaged beyond repair."
- clockwork_desc = "The sad remains of a clockwork golem. It's broken beyond repair."
- icon_state = "clockgolem_dead"
- sprite_shift = 0
-
-/obj/item/clockwork/alloy_shards/large
- w_class = WEIGHT_CLASS_TINY
- randomsinglesprite = TRUE
- icon_state = "shard_large"
- sprite_shift = 9
-
-/obj/item/clockwork/alloy_shards/medium
- w_class = WEIGHT_CLASS_TINY
- randomsinglesprite = TRUE
- icon_state = "shard_medium"
- sprite_shift = 10
-
-/obj/item/clockwork/alloy_shards/medium/gear_bit
- randomspritemax = 4
- icon_state = "gear_bit"
- sprite_shift = 12
-
-/obj/item/clockwork/alloy_shards/medium/gear_bit/replace_name_desc()
- name = "gear bit"
- desc = "A broken chunk of a gear. You want it."
- clockwork_desc = "A broken chunk of a gear."
-
-/obj/item/clockwork/alloy_shards/medium/gear_bit/large //gives more power
-
-/obj/item/clockwork/alloy_shards/medium/gear_bit/large/replace_name_desc()
- ..()
- name = "complex gear bit"
-
-/obj/item/clockwork/alloy_shards/small
- w_class = WEIGHT_CLASS_TINY
- randomsinglesprite = TRUE
- randomspritemax = 3
- icon_state = "shard_small"
- sprite_shift = 12
-
-/obj/item/clockwork/alloy_shards/pinion_lock
- name = "pinion lock"
- desc = "A dented and scratched gear. It's very heavy."
- clockwork_desc = "A broken gear lock for pinion airlocks."
- icon_state = "pinion_lock"
diff --git a/code/modules/antagonists/clockcult/clock_items/clock_weapons/_call_weapon.dm b/code/modules/antagonists/clockcult/clock_items/clock_weapons/_call_weapon.dm
deleted file mode 100644
index a87767c05e3..00000000000
--- a/code/modules/antagonists/clockcult/clock_items/clock_weapons/_call_weapon.dm
+++ /dev/null
@@ -1,49 +0,0 @@
-//This is the innate action for "binding" and calling weapons to yourself. These weapons can appear and disappear at will.
-//You can invoke a cooldown period by calling "weapon_reset(cooldown in deciseconds)." By default, this only applies to dismissing weapons.
-/datum/action/innate/call_weapon
- name = "Call Weapon"
- desc = "This definitely shouldn't exist."
- icon_icon = 'icons/mob/actions/actions_clockcult.dmi'
- button_icon_state = "ratvarian_spear"
- background_icon_state = "bg_clock"
- check_flags = AB_CHECK_RESTRAINED|AB_CHECK_STUN|AB_CHECK_CONSCIOUS
- buttontooltipstyle = "clockcult"
- var/cooldown = 0
- var/obj/item/clockwork/weapon/weapon_type //The type of weapon to create
- var/obj/item/clockwork/weapon/weapon
-
-/datum/action/innate/call_weapon/IsAvailable()
- if(!is_servant_of_ratvar(owner))
- qdel(src)
- return
- if(cooldown > world.time)
- return
- return ..()
-
-/datum/action/innate/call_weapon/Activate()
- if(!owner.get_empty_held_indexes())
- to_chat(usr, "You need an empty hand to call forth your [initial(weapon_type.name)]!")
- return
- if(weapon)
- if(weapon.loc == owner)
- owner.visible_message("[owner]'s [weapon.name] flickers and disappears!")
- to_chat(owner, "You dismiss [weapon].")
- QDEL_NULL(weapon)
- weapon_reset(RATVARIAN_SPEAR_COOLDOWN * 0.5)
- return
- else
- weapon.visible_message("[weapon] suddenly flickers and disappears!")
- owner.visible_message("A [weapon.name] suddenly flickers into [owner]'s hands!", "You recall [weapon] to you.")
- else
- weapon = new weapon_type (get_turf(usr), src)
- owner.visible_message("A [weapon.name] materializes in [owner]'s hands!", "You call forth your [weapon.name]!")
- weapon.forceMove(get_turf(owner))
- owner.put_in_hands(weapon)
- owner.update_action_buttons_icon()
- return TRUE
-
-/datum/action/innate/call_weapon/proc/weapon_reset(cooldown_time)
- cooldown = world.time + cooldown_time
- addtimer(CALLBACK(owner, /mob.proc/update_action_buttons_icon), cooldown_time)
- owner.update_action_buttons_icon()
- QDEL_NULL(weapon)
diff --git a/code/modules/antagonists/clockcult/clock_items/clock_weapons/ratvarian_spear.dm b/code/modules/antagonists/clockcult/clock_items/clock_weapons/ratvarian_spear.dm
deleted file mode 100644
index b676068fa97..00000000000
--- a/code/modules/antagonists/clockcult/clock_items/clock_weapons/ratvarian_spear.dm
+++ /dev/null
@@ -1,76 +0,0 @@
-//Ratvarian spear: A relatively fragile spear from the Celestial Derelict. Deals extreme damage to silicons and enemy cultists, but doesn't last long when summoned.
-/obj/item/clockwork/weapon/ratvarian_spear
- name = "ratvarian spear"
- desc = "A razor-sharp spear made of brass. It thrums with barely-contained energy."
- clockwork_desc = "A powerful spear of Ratvarian making. It's more effective against enemy cultists and silicons."
- icon_state = "ratvarian_spear"
- item_state = "ratvarian_spear"
- force = 15 //Extra damage is dealt to targets in attack()
- throwforce = 25
- armour_penetration = 10
- sharpness = IS_SHARP_ACCURATE
- attack_verb = list("stabbed", "poked", "slashed")
- hitsound = 'sound/weapons/bladeslice.ogg'
- w_class = WEIGHT_CLASS_BULKY
- var/bonus_burn = 5
-
-/obj/item/clockwork/weapon/ratvarian_spear/ratvar_act()
- if(GLOB.ratvar_awakens) //If Ratvar is alive, the spear is extremely powerful
- force = 20
- bonus_burn = 10
- throwforce = 40
- armour_penetration = 50
- else
- force = initial(force)
- bonus_burn = initial(bonus_burn)
- throwforce = initial(throwforce)
- armour_penetration = initial(armour_penetration)
-
-/obj/item/clockwork/weapon/ratvarian_spear/examine(mob/user)
- . = ..()
- if(is_servant_of_ratvar(user) || isobserver(user))
- . += "Attacks on living non-Servants will generate [bonus_burn] units of vitality."
- if(!iscyborg(user))
- . += "Throwing the spear will do massive damage, break the spear, and knock down the target."
-
-/obj/item/clockwork/weapon/ratvarian_spear/attack(mob/living/target, mob/living/carbon/human/user)
- . = ..()
- if(!QDELETED(target) && target.stat != DEAD && !target.anti_magic_check(chargecost = 0) && !is_servant_of_ratvar(target)) //we do bonus damage on attacks unless they're a servant, have a null rod, or are dead
- var/bonus_damage = bonus_burn //normally a total of 20 damage, 30 with ratvar
- if(issilicon(target))
- target.visible_message("[target] shudders violently at [src]'s touch!", "ERROR: Temperature rising!")
- bonus_damage *= 5 //total 40 damage on borgs, 70 with ratvar
- else if(iscultist(target) || isconstruct(target))
- to_chat(target, "Your body flares with agony at [src]'s presence!")
- bonus_damage *= 3 //total 30 damage on cultists, 50 with ratvar
- GLOB.clockwork_vitality += target.adjustFireLoss(bonus_damage) //adds the damage done to existing vitality
-
-/obj/item/clockwork/weapon/ratvarian_spear/throw_impact(atom/hit_atom, datum/thrownthing/throwingdatum)
- var/turf/T = get_turf(hit_atom)
- if(isliving(hit_atom))
- var/mob/living/L = hit_atom
- if(is_servant_of_ratvar(L))
- if(L.put_in_active_hand(src))
- L.visible_message("[L] catches [src] out of the air!")
- else
- L.visible_message("[src] bounces off of [L], as if repelled by an unseen force!")
- else if(!..())
- if(!L.anti_magic_check())
- if(issilicon(L) || iscultist(L))
- L.Paralyze(100)
- else
- L.Paralyze(40)
- GLOB.clockwork_vitality += L.adjustFireLoss(bonus_burn * 3) //normally a total of 40 damage, 70 with ratvar
- break_spear(T)
- else
- ..()
-
-/obj/item/clockwork/weapon/ratvarian_spear/proc/break_spear(turf/T)
- if(src)
- if(!T)
- T = get_turf(src)
- if(T) //make sure we're not in null or something
- T.visible_message("[src] [pick("cracks in two and fades away", "snaps in two and dematerializes")]!")
- new /obj/effect/temp_visual/ratvar/spearbreak(T)
- qdel(src)
- action.weapon_reset(RATVARIAN_SPEAR_COOLDOWN)
diff --git a/code/modules/antagonists/clockcult/clock_items/clockwork_armor.dm b/code/modules/antagonists/clockcult/clock_items/clockwork_armor.dm
deleted file mode 100644
index f520020066a..00000000000
--- a/code/modules/antagonists/clockcult/clock_items/clockwork_armor.dm
+++ /dev/null
@@ -1,229 +0,0 @@
-//Clockwork armor: High melee protection but weak to lasers
-/obj/item/clothing/head/helmet/clockwork
- name = "clockwork helmet"
- desc = "A heavy helmet made of brass."
- icon = 'icons/obj/clothing/clockwork_garb.dmi'
- icon_state = "clockwork_helmet"
- w_class = WEIGHT_CLASS_NORMAL
- resistance_flags = FIRE_PROOF | ACID_PROOF
- flags_inv = HIDEEARS|HIDEHAIR|HIDEFACE
- armor = list("melee" = 60, "bullet" = 70, "laser" = -25, "energy" = 0, "bomb" = 60, "bio" = 0, "rad" = 0, "fire" = 100, "acid" = 100)
-
-/obj/item/clothing/head/helmet/clockwork/Initialize()
- . = ..()
- ratvar_act()
- GLOB.all_clockwork_objects += src
-
-/obj/item/clothing/head/helmet/clockwork/Destroy()
- GLOB.all_clockwork_objects -= src
- return ..()
-
-/obj/item/clothing/head/helmet/clockwork/ratvar_act()
- if(GLOB.ratvar_awakens)
- armor = getArmor(melee = 100, bullet = 100, laser = 100, energy = 100, bomb = 100, bio = 100, rad = 100, fire = 100, acid = 100)
- clothing_flags |= STOPSPRESSUREDAMAGE
- max_heat_protection_temperature = FIRE_IMMUNITY_MAX_TEMP_PROTECT
- min_cold_protection_temperature = SPACE_HELM_MIN_TEMP_PROTECT
- else if(GLOB.ratvar_approaches)
- armor = getArmor(melee = 70, bullet = 80, laser = -15, energy = 25, bomb = 70, bio = 0, rad = 0, fire = 100, acid = 100)
- clothing_flags |= STOPSPRESSUREDAMAGE
- max_heat_protection_temperature = FIRE_IMMUNITY_MAX_TEMP_PROTECT
- min_cold_protection_temperature = SPACE_HELM_MIN_TEMP_PROTECT
- else
- armor = getArmor(melee = 60, bullet = 70, laser = -25, energy = 0, bomb = 60, bio = 0, rad = 0, fire = 100, acid = 100)
- clothing_flags &= ~STOPSPRESSUREDAMAGE
- max_heat_protection_temperature = initial(max_heat_protection_temperature)
- min_cold_protection_temperature = initial(min_cold_protection_temperature)
-
-/obj/item/clothing/head/helmet/clockwork/equipped(mob/living/user, slot)
- ..()
- if(slot == SLOT_HEAD && !is_servant_of_ratvar(user))
- if(!iscultist(user))
- to_chat(user, "\"Now now, this is for my servants, not you.\"")
- user.visible_message("As [user] puts [src] on, it flickers off [user.p_their()] head!", "The helmet flickers off your head, leaving only nausea!")
- if(iscarbon(user))
- var/mob/living/carbon/C = user
- C.vomit(20)
- else
- to_chat(user, "\"Do you have a hole in your head? You're about to.\"")
- to_chat(user, "The helmet tries to drive a spike through your head as you scramble to remove it!")
- user.emote("scream")
- user.apply_damage(30, BRUTE, BODY_ZONE_HEAD)
- user.adjustOrganLoss(ORGAN_SLOT_BRAIN, 30)
- addtimer(CALLBACK(user, /mob/living.proc/dropItemToGround, src, TRUE), 1) //equipped happens before putting stuff on(but not before picking items up), 1). thus, we need to wait for it to be on before forcing it off.
-
-/obj/item/clothing/head/helmet/clockwork/mob_can_equip(mob/M, mob/equipper, slot, disable_warning = 0)
- if(equipper && !is_servant_of_ratvar(equipper))
- return 0
- return ..()
-
-/obj/item/clothing/suit/armor/clockwork
- name = "clockwork cuirass"
- desc = "A bulky cuirass made of brass."
- icon = 'icons/obj/clothing/clockwork_garb.dmi'
- icon_state = "clockwork_cuirass"
- w_class = WEIGHT_CLASS_BULKY
- body_parts_covered = CHEST|GROIN|LEGS
- cold_protection = CHEST|GROIN|LEGS
- heat_protection = CHEST|GROIN|LEGS
- resistance_flags = FIRE_PROOF | ACID_PROOF
- armor = list("melee" = 60, "bullet" = 70, "laser" = -25, "energy" = 0, "bomb" = 60, "bio" = 0, "rad" = 0, "fire" = 100, "acid" = 100)
- allowed = list(/obj/item/clockwork, /obj/item/clothing/glasses/wraith_spectacles, /obj/item/clothing/glasses/judicial_visor, /obj/item/mmi/posibrain/soul_vessel)
-
-/obj/item/clothing/suit/armor/clockwork/Initialize()
- . = ..()
- ratvar_act()
- GLOB.all_clockwork_objects += src
-
-/obj/item/clothing/suit/armor/clockwork/Destroy()
- GLOB.all_clockwork_objects -= src
- return ..()
-
-/obj/item/clothing/suit/armor/clockwork/ratvar_act()
- if(GLOB.ratvar_awakens)
- armor = getArmor(melee = 100, bullet = 100, laser = 100, energy = 100, bomb = 100, bio = 100, rad = 100, fire = 100, acid = 100)
- clothing_flags |= STOPSPRESSUREDAMAGE
- max_heat_protection_temperature = FIRE_IMMUNITY_MAX_TEMP_PROTECT
- min_cold_protection_temperature = SPACE_HELM_MIN_TEMP_PROTECT
- else if(GLOB.ratvar_approaches)
- armor = getArmor(melee = 70, bullet = 80, laser = -15, energy = 25, bomb = 70, bio = 0, rad = 0, fire = 100, acid = 100)
- clothing_flags |= STOPSPRESSUREDAMAGE
- max_heat_protection_temperature = FIRE_IMMUNITY_MAX_TEMP_PROTECT
- min_cold_protection_temperature = SPACE_HELM_MIN_TEMP_PROTECT
- else
- armor = getArmor(melee = 60, bullet = 70, laser = -25, energy = 0, bomb = 60, bio = 0, rad = 0, fire = 100, acid = 100)
- clothing_flags &= ~STOPSPRESSUREDAMAGE
- max_heat_protection_temperature = initial(max_heat_protection_temperature)
- min_cold_protection_temperature = initial(min_cold_protection_temperature)
-
-/obj/item/clothing/suit/armor/clockwork/mob_can_equip(mob/M, mob/equipper, slot, disable_warning = 0)
- if(equipper && !is_servant_of_ratvar(equipper))
- return 0
- return ..()
-
-/obj/item/clothing/suit/armor/clockwork/equipped(mob/living/user, slot)
- ..()
- if(slot == SLOT_WEAR_SUIT && !is_servant_of_ratvar(user))
- if(!iscultist(user))
- to_chat(user, "\"Now now, this is for my servants, not you.\"")
- user.visible_message("As [user] puts [src] on, it flickers off [user.p_their()] body!", "The cuirass flickers off your body, leaving only nausea!")
- if(iscarbon(user))
- var/mob/living/carbon/C = user
- C.vomit(20)
- else
- to_chat(user, "\"I think this armor is too hot for you to handle.\"")
- to_chat(user, "The cuirass emits a burst of flame as you scramble to get it off!")
- user.emote("scream")
- user.apply_damage(15, BURN, BODY_ZONE_CHEST)
- user.adjust_fire_stacks(2)
- user.IgniteMob()
- addtimer(CALLBACK(user, /mob/living.proc/dropItemToGround, src, TRUE), 1)
-
-/obj/item/clothing/gloves/clockwork
- name = "clockwork gauntlets"
- desc = "Heavy, shock-resistant gauntlets with brass reinforcement."
- icon = 'icons/obj/clothing/clockwork_garb.dmi'
- icon_state = "clockwork_gauntlets"
- item_state = "clockwork_gauntlets"
- strip_delay = 50
- equip_delay_other = 30
- body_parts_covered = ARMS
- cold_protection = ARMS
- heat_protection = ARMS
- siemens_coefficient = 0
- permeability_coefficient = 0.05
- resistance_flags = FIRE_PROOF | ACID_PROOF
- armor = list("melee" = 80, "bullet" = 70, "laser" = -25, "energy" = 0, "bomb" = 60, "bio" = 0, "rad" = 0, "fire" = 100, "acid" = 100)
-
-/obj/item/clothing/gloves/clockwork/Initialize()
- . = ..()
- ratvar_act()
- GLOB.all_clockwork_objects += src
-
-/obj/item/clothing/gloves/clockwork/Destroy()
- GLOB.all_clockwork_objects -= src
- return ..()
-
-/obj/item/clothing/gloves/clockwork/ratvar_act()
- if(GLOB.ratvar_awakens)
- armor = getArmor(melee = 100, bullet = 100, laser = 100, energy = 100, bomb = 100, bio = 100, rad = 100, fire = 100, acid = 100)
- clothing_flags |= STOPSPRESSUREDAMAGE
- max_heat_protection_temperature = FIRE_IMMUNITY_MAX_TEMP_PROTECT
- min_cold_protection_temperature = SPACE_HELM_MIN_TEMP_PROTECT
- else
- armor = getArmor(melee = 80, bullet = 70, laser = -25, energy = 0, bomb = 60, bio = 0, rad = 0, fire = 100, acid = 100)
- clothing_flags &= ~STOPSPRESSUREDAMAGE
- max_heat_protection_temperature = initial(max_heat_protection_temperature)
- min_cold_protection_temperature = initial(min_cold_protection_temperature)
-
-/obj/item/clothing/gloves/clockwork/mob_can_equip(mob/M, mob/equipper, slot, disable_warning = 0)
- if(equipper && !is_servant_of_ratvar(equipper))
- return 0
- return ..()
-
-/obj/item/clothing/gloves/clockwork/equipped(mob/living/user, slot)
- ..()
- if(slot == SLOT_GLOVES && !is_servant_of_ratvar(user))
- if(!iscultist(user))
- to_chat(user, "\"Now now, this is for my servants, not you.\"")
- user.visible_message("As [user] puts [src] on, it flickers off [user.p_their()] arms!", "The gauntlets flicker off your arms, leaving only nausea!")
- if(iscarbon(user))
- var/mob/living/carbon/C = user
- C.vomit()
- else
- to_chat(user, "\"Did you like having arms?\"")
- to_chat(user, "The gauntlets suddenly squeeze tight, crushing your arms before you manage to get them off!")
- user.emote("scream")
- user.apply_damage(7, BRUTE, BODY_ZONE_L_ARM)
- user.apply_damage(7, BRUTE, BODY_ZONE_R_ARM)
- addtimer(CALLBACK(user, /mob/living.proc/dropItemToGround, src, TRUE), 1)
-
-/obj/item/clothing/shoes/clockwork
- name = "clockwork treads"
- desc = "Industrial boots made of brass. They're very heavy."
- icon = 'icons/obj/clothing/clockwork_garb.dmi'
- icon_state = "clockwork_treads"
- w_class = WEIGHT_CLASS_NORMAL
- strip_delay = 50
- equip_delay_other = 30
- resistance_flags = FIRE_PROOF | ACID_PROOF
-
-/obj/item/clothing/shoes/clockwork/Initialize()
- . = ..()
- ratvar_act()
- GLOB.all_clockwork_objects += src
-
-/obj/item/clothing/shoes/clockwork/Destroy()
- GLOB.all_clockwork_objects -= src
- return ..()
-
-/obj/item/clothing/shoes/clockwork/negates_gravity()
- return TRUE
-
-/obj/item/clothing/shoes/clockwork/ratvar_act()
- if(GLOB.ratvar_awakens)
- clothing_flags |= NOSLIP
- else
- clothing_flags &= ~NOSLIP
-
-/obj/item/clothing/shoes/clockwork/mob_can_equip(mob/M, mob/equipper, slot, disable_warning = 0)
- if(equipper && !is_servant_of_ratvar(equipper))
- return 0
- return ..()
-
-/obj/item/clothing/shoes/clockwork/equipped(mob/living/user, slot)
- ..()
- if(slot == SLOT_SHOES && !is_servant_of_ratvar(user))
- if(!iscultist(user))
- to_chat(user, "\"Now now, this is for my servants, not you.\"")
- user.visible_message("As [user] puts [src] on, it flickers off [user.p_their()] feet!", "The treads flicker off your feet, leaving only nausea!")
- if(iscarbon(user))
- var/mob/living/carbon/C = user
- C.vomit()
- else
- to_chat(user, "\"Let's see if you can dance with these.\"")
- to_chat(user, "The treads turn searing hot as you scramble to get them off!")
- user.emote("scream")
- user.apply_damage(7, BURN, BODY_ZONE_L_LEG)
- user.apply_damage(7, BURN, BODY_ZONE_R_LEG)
- addtimer(CALLBACK(user, /mob/living.proc/dropItemToGround, src, TRUE), 1)
diff --git a/code/modules/antagonists/clockcult/clock_items/clockwork_slab.dm b/code/modules/antagonists/clockcult/clock_items/clockwork_slab.dm
deleted file mode 100644
index 67d134fc562..00000000000
--- a/code/modules/antagonists/clockcult/clock_items/clockwork_slab.dm
+++ /dev/null
@@ -1,523 +0,0 @@
-/obj/item/clockwork/slab //Clockwork slab: The most important tool in Ratvar's arsenal. Allows scripture recital, tutorials, and generates components.
- name = "clockwork slab"
- desc = "A strange metal tablet. A clock in the center turns around and around."
- clockwork_desc = "A link between you and the Celestial Derelict. It contains information, recites scripture, and is your most vital tool as a Servant. \
- It can be used to link traps and triggers by attacking them with the slab. Keep in mind that traps linked with one another will activate in tandem!"
-
- icon_state = "dread_ipad"
- lefthand_file = 'icons/mob/inhands/antag/clockwork_lefthand.dmi'
- righthand_file = 'icons/mob/inhands/antag/clockwork_righthand.dmi'
- var/inhand_overlay //If applicable, this overlay will be applied to the slab's inhand
-
- slot_flags = ITEM_SLOT_BELT
- w_class = WEIGHT_CLASS_SMALL
-
- var/busy //If the slab is currently being used by something
- var/no_cost = FALSE //If the slab is admin-only and needs no components and has no scripture locks
- var/speed_multiplier = 1 //multiples how fast this slab recites scripture
- var/selected_scripture = SCRIPTURE_DRIVER
- var/obj/effect/proc_holder/slab/slab_ability //the slab's current bound ability, for certain scripture
-
- var/recollecting = FALSE //if we're looking at fancy recollection
- var/recollection_category = "Default"
-
- var/list/quickbound = list(/datum/clockwork_scripture/abscond, \
- /datum/clockwork_scripture/ranged_ability/kindle, /datum/clockwork_scripture/ranged_ability/hateful_manacles) //quickbound scripture, accessed by index
- var/maximum_quickbound = 5 //how many quickbound scriptures we can have
-
- var/obj/structure/destructible/clockwork/trap/linking //If we're linking traps together, which ones we're doing
-
-/obj/item/clockwork/slab/internal //an internal motor for mobs running scripture
- name = "scripture motor"
- quickbound = list()
- no_cost = TRUE
-
-/obj/item/clockwork/slab/debug
- speed_multiplier = 0
- no_cost = TRUE
-
-//ATTACK HAND IGNORING PARENT RETURN VALUE
-/obj/item/clockwork/slab/debug/attack_hand(mob/living/user)
- if(!is_servant_of_ratvar(user))
- add_servant_of_ratvar(user)
- return ..()
-
-/obj/item/clockwork/slab/cyborg //three scriptures, plus a spear and fabricator
- clockwork_desc = "A divine link to the Celestial Derelict, allowing for limited recital of scripture."
- quickbound = list(/datum/clockwork_scripture/abscond, /datum/clockwork_scripture/ranged_ability/judicial_marker, /datum/clockwork_scripture/ranged_ability/linked_vanguard)
- maximum_quickbound = 6 //we usually have one or two unique scriptures, so if ratvar is up let us bind one more
- actions_types = list()
-
-/obj/item/clockwork/slab/cyborg/engineer //two scriptures, plus a fabricator
- quickbound = list(/datum/clockwork_scripture/abscond, /datum/clockwork_scripture/create_object/replicant, /datum/clockwork_scripture/create_object/sigil_of_transmission)
-
-/obj/item/clockwork/slab/cyborg/medical //five scriptures, plus a spear
- quickbound = list(/datum/clockwork_scripture/abscond, /datum/clockwork_scripture/ranged_ability/linked_vanguard, /datum/clockwork_scripture/ranged_ability/sentinels_compromise, \
- /datum/clockwork_scripture/create_object/vitality_matrix)
-
-/obj/item/clockwork/slab/cyborg/security //twoscriptures, plus a spear
- quickbound = list(/datum/clockwork_scripture/abscond, /datum/clockwork_scripture/ranged_ability/hateful_manacles, /datum/clockwork_scripture/ranged_ability/judicial_marker)
-
-/obj/item/clockwork/slab/cyborg/peacekeeper //two scriptures, plus a spear
- quickbound = list(/datum/clockwork_scripture/abscond, /datum/clockwork_scripture/ranged_ability/hateful_manacles, /datum/clockwork_scripture/ranged_ability/judicial_marker)
-
-/obj/item/clockwork/slab/cyborg/janitor //five scriptures, plus a fabricator
- quickbound = list(/datum/clockwork_scripture/abscond, /datum/clockwork_scripture/create_object/replicant, /datum/clockwork_scripture/create_object/sigil_of_transgression, \
- /datum/clockwork_scripture/create_object/ocular_warden, /datum/clockwork_scripture/create_object/mania_motor)
-
-/obj/item/clockwork/slab/cyborg/service //five scriptures, plus xray vision
- quickbound = list(/datum/clockwork_scripture/abscond, /datum/clockwork_scripture/create_object/replicant, \
- /datum/clockwork_scripture/spatial_gateway, /datum/clockwork_scripture/create_object/clockwork_obelisk)
-
-/obj/item/clockwork/slab/cyborg/miner //two scriptures, plus a spear and xray vision
- quickbound = list(/datum/clockwork_scripture/abscond, /datum/clockwork_scripture/ranged_ability/linked_vanguard, /datum/clockwork_scripture/spatial_gateway)
-
-/obj/item/clockwork/slab/cyborg/access_display(mob/living/user)
- if(!GLOB.ratvar_awakens)
- to_chat(user, "Use the action buttons to recite your limited set of scripture!")
- else
- ..()
-
-/obj/item/clockwork/slab/cyborg/ratvar_act()
- ..()
- if(!GLOB.ratvar_awakens)
- SStgui.close_uis(src)
-
-/obj/item/clockwork/slab/Initialize()
- . = ..()
- update_slab_info(src)
- START_PROCESSING(SSobj, src)
- if(GLOB.ratvar_approaches)
- name = "supercharged [name]"
- speed_multiplier = max(0.1, speed_multiplier - 0.25)
-
-/obj/item/clockwork/slab/Destroy()
- STOP_PROCESSING(SSobj, src)
- if(slab_ability && slab_ability.ranged_ability_user)
- slab_ability.remove_ranged_ability()
- slab_ability = null
- return ..()
-
-/obj/item/clockwork/slab/dropped(mob/user)
- . = ..()
- addtimer(CALLBACK(src, .proc/check_on_mob, user), 1) //dropped is called before the item is out of the slot, so we need to check slightly later
-
-/obj/item/clockwork/slab/worn_overlays(isinhands = FALSE, icon_file)
- . = list()
- if(isinhands && item_state && inhand_overlay)
- var/mutable_appearance/M = mutable_appearance(icon_file, "slab_[inhand_overlay]")
- . += M
-
-/obj/item/clockwork/slab/proc/check_on_mob(mob/user)
- if(user && !(src in user.held_items) && slab_ability && slab_ability.ranged_ability_user) //if we happen to check and we AREN'T in user's hands, remove whatever ability we have
- slab_ability.remove_ranged_ability()
-
-//Power generation
-/obj/item/clockwork/slab/process()
- if(GLOB.ratvar_approaches && speed_multiplier == initial(speed_multiplier))
- name = "supercharged [name]"
- speed_multiplier = max(0.1, speed_multiplier - 0.25)
- adjust_clockwork_power(0.1) //Slabs serve as very weak power generators on their own (no, not enough to justify spamming them)
-
-/obj/item/clockwork/slab/examine(mob/user)
- . = ..()
- if(is_servant_of_ratvar(user) || isobserver(user))
- if(LAZYLEN(quickbound))
- for(var/i in 1 to quickbound.len)
- if(!quickbound[i])
- continue
- var/datum/clockwork_scripture/quickbind_slot = quickbound[i]
- . += "Quickbind button: [initial(quickbind_slot.name)]."
- . += "Available power:[DisplayPower(get_clockwork_power())]."
-
-//Slab actions; Hierophant, Quickbind
-/obj/item/clockwork/slab/ui_action_click(mob/user, action)
- if(istype(action, /datum/action/item_action/clock/quickbind))
- var/datum/action/item_action/clock/quickbind/Q = action
- recite_scripture(quickbound[Q.scripture_index], user, FALSE)
-
-//Scripture Recital
-/obj/item/clockwork/slab/attack_self(mob/living/user)
- if(iscultist(user))
- to_chat(user, "\"You reek of blood. You've got a lot of nerve to even look at that slab.\"")
- user.visible_message("A sizzling sound comes from [user]'s hands!", "[src] suddenly grows extremely hot in your hands!")
- playsound(get_turf(user), 'sound/weapons/sear.ogg', 50, TRUE)
- user.dropItemToGround(src)
- user.emote("scream")
- user.apply_damage(5, BURN, BODY_ZONE_L_ARM)
- user.apply_damage(5, BURN, BODY_ZONE_R_ARM)
- return 0
- if(!is_servant_of_ratvar(user))
- to_chat(user, "The information on [src]'s display shifts rapidly. After a moment, your head begins to pound, and you tear your eyes away.")
- user.confused += 5
- user.dizziness += 5
- return 0
- if(busy)
- to_chat(user, "[src] refuses to work, displaying the message: \"[busy]!\"")
- return 0
- if(!no_cost && !can_recite_scripture(user))
- to_chat(user, "[src] hums fitfully in your hands, but doesn't seem to do anything...")
- return 0
- access_display(user)
-
-/obj/item/clockwork/slab/AltClick(mob/living/user)
- if(is_servant_of_ratvar(user) && linking && user.canUseTopic(src, BE_CLOSE, ismonkey(user)))
- linking = null
- to_chat(user, "Object link canceled.")
-
-/obj/item/clockwork/slab/proc/access_display(mob/living/user)
- if(!is_servant_of_ratvar(user))
- return FALSE
- ui_interact(user)
- return TRUE
-
-/obj/item/clockwork/slab/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, datum/tgui/master_ui = null, datum/ui_state/state = GLOB.inventory_state)
- ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
- if(!ui)
- ui = new(user, src, ui_key, "clockwork_slab", name, 800, 420, master_ui, state)
- ui.set_autoupdate(FALSE) //we'll update this occasionally, but not as often as possible
- ui.set_style("clockwork")
- ui.open()
-
-/obj/item/clockwork/slab/proc/recite_scripture(datum/clockwork_scripture/scripture, mob/living/user)
- if(!scripture || !user || !user.canUseTopic(src) || (!no_cost && !can_recite_scripture(user)))
- return FALSE
- if(user.get_active_held_item() != src)
- to_chat(user, "You need to hold the slab in your active hand to recite scripture!")
- return FALSE
- var/initial_tier = initial(scripture.tier)
- if(initial_tier != SCRIPTURE_PERIPHERAL)
- if(!GLOB.ratvar_awakens && !no_cost && !GLOB.scripture_states[initial_tier])
- to_chat(user, "That scripture is not unlocked, and cannot be recited!")
- return FALSE
- var/datum/clockwork_scripture/scripture_to_recite = new scripture
- scripture_to_recite.slab = src
- scripture_to_recite.invoker = user
- scripture_to_recite.run_scripture()
- return TRUE
-
-
-//Guide to Serving Ratvar
-/obj/item/clockwork/slab/proc/recollection()
- var/list/textlist = list("If you're seeing this, file a bug report.")
- if(GLOB.ratvar_awakens)
- textlist = list("")
- for(var/i in 1 to 100)
- textlist += "HONOR RATVAR "
- textlist += ""
- else
- textlist = list("
[text2ratvar("Purge all untruths and honor Engine.")]
\
- \
- NOTICE: This information is out of date. Read the Ark & You primer in your backpack or read the wiki page for current info. \
- \
- These pages serve as the archives of Ratvar, the Clockwork Justiciar. This section of your slab has information on being as a Servant, advice for what to do next, and \
- pointers for serving the master well. You should recommended that you check this area for help if you get stuck or need guidance on what to do next.
\
- \
- Disclaimer: Many objects, terms, and phrases, such as Servant, Cache, and Slab, are capitalized like proper nouns. This is a quirk of the Ratvarian language; \
- do not let it confuse you! You are free to use the names in pronoun form when speaking in normal languages. ")
- return textlist.Join()
-
-//Gets text for a certain section. "Default" is used for when you first open Recollection.
-//Current sections (make sure to update this if you add one:
-//- Basics
-//- Terminology
-//- Components
-//- Scripture
-//- Power
-//- Conversion
-/obj/item/clockwork/slab/proc/get_recollection_text(section)
- var/list/dat = list()
- switch(section)
- if("Default")
- dat += "You can browse the above sections as you please. They're designed to be read in order, but feel free to pick and choose between them."
- if("Getting Started")
- dat += "Getting Started
"
- dat += "Welcome, Servant! This section houses the utmost basics of being a Servant of Ratvar, and is much more informal than the other sections. Being a Servant of \
- Ratvar is a very complex role, with many systems, objects, and resources to use effectively and creatively.
"
- dat += "This section of your clockwork slab covers everything that Servants have to be aware of, but is a long read because of how in-depth the systems are. Knowing \
- how to use the tools at your disposal makes all the difference between a clueless Servant and a great one.
"
- dat += "If this is your first time being a Servant, relax. It's very much possible that you'll fail, but it's impossible to learn without making mistakes. For the time \
- being, use the Hierophant Network button in the top left-hand corner of your screen to try and get in touch with your fellow Servants; ignore the others for now. This button \
- will let you send messages across space and time to all other Servants. This makes it great for coordinating, and you should use it often! Note: Using \
- this will cause you to whisper your message aloud, so doing so in a public place is very suspicious and you should try to restrict it to private use.
"
- dat += "If you aren't willing or don't have the time to read through every section, you can still help your teammates! Ask if they've set up a base. If they have, head there \
- and ask however you can help; chances are there's always something. If not, it's your job as a Servant to get one up and running! Try to find a secluded, low-traffic area, \
- like the auxiliary base or somewhere deep in maintenance. You'll want to go into the Drivers section of the slab and look for Tinkerer's Cache. Find a nice spot and \
- create one. This serves as a storage for components, the cult's primary resource. (Your slab's probably produced a few by now.) By attacking that cache with this \
- slab, you'll offload all your components into it, and all Servants will be able to use those components from any distance - all Tinkerer's Caches are linked!
"
- dat += "Once you have a base up and running, contact your fellows and let them know. You should come back here often to drop off the slab's components, and your fellows \
- should do the same, either in this cache or in ones of their own.
"
- dat += "If you think you're confident in taking further steps to help the cult, feel free to move onto the other sections. If not, let your allies know that you're new and \
- would appreciate the help they might offer you. Most experienced Servants would be happy to help; if everyone is inexperienced, then you'll have to step out of your comfort \
- zone and read onto the other sections. It's very likely that you might fail, but don't worry too much about it; you can't learn effectively without making mistakes.
"
- dat += "For now, welcome! If you're looking to learn, you should start with the Basics section, then move onto Components and Scripture. At the very \
- least, you should read the Conversion section, as it outlines the most important aspects of being a Servant. Good luck!
"
- dat += "-=-=-=-=-=-"
- if("Basics")
- dat += "Servant Basics
"
- dat += "The first thing any Servant should know is their slab, inside and out. The clockwork slab is by far your most important tool. It allows you to speak with your \
- fellow Servants, create components that fuel many of your abilities, use those abilities, and should be kept safe and hidden on your person at all times. If you have not \
- done so already, it's a good idea to check for any fellow Servants using the Hierophant Network button in the top-left corner of your screen; due to the cult's nature, \
- teamwork is an instrumental component of your success.
" //get it? component? ha!
- dat += "As a Servant of Ratvar, the tools you are given focus around building and maintaining bases and outposts. A great deal of your power comes from stationary \
- structures, and without constructing a base somewhere, it's essentially impossible to succeed. Finding a good spot to build a base can be difficult, and it's recommended \
- that you choose an area in low-traffic part of the station (such as the auxiliary base). Make sure to disconnect any cameras in the area beforehand.
"
- dat += "Because of how complex being a Servant is, it isn't possible to fit much information into this section. It's highly recommended that you read the Components \
- and Scripture sections next. Not knowing how these two systems work will cripple both you and your fellows, and lead to a frustrating experience for everyone.
"
- dat += "-=-=-=-=-=-"
- if("Terminology")
- dat += "Common Servant Terminology "
- dat += "This isn't intended to be read all at once; you are advised to treat it moreso as a glossary.
"
- dat += "General "
- dat += "Servant: A person or robot who serves Ratvar. You are one of these. "
- dat += "Cache: A Tinkerer's Cache, which is a structure that stores and creates components. "
- dat += "CV: Construction Value. All clockwork structures, floors, and walls increase this number. "
- dat += "Vitality: Used for healing effects, produced by Ratvarian spear attacks and Vitality Matrices. "
- dat += "Geis: An important scripture used to make normal crew and robots into Servants of Ratvar. "
- dat += "Ark: The cult's win condition, a huge structure that needs to be defended.
"
- dat += "Items "
- dat += "Slab: A clockwork slab, a Servant's most important tool. You're holding one! Keep it safe and hidden. "
- dat += "Visor: A judicial visor, which is a pair of glasses that can smite an area for a brief stun and delayed explosion. "
- dat += "Wraith Specs: Wraith spectacles, which provide true sight (X-ray, night vision) but damage the wearer's eyes. "
- dat += "Spear: A Ratvarian spear, which is a very powerful melee weapon that produces Vitality. "
- dat += "Fabricator: A replica fabricator, which converts objects into clockwork versions.
"
- dat += "Constructs "
- dat += "Marauder: A clockwork marauder, which is a powerful bodyguard that hides in its owner.
"
- dat += "Structures (* = requires power) "
- dat += "Warden: An ocular warden, which is a ranged turret that damages non-Servants that see it. "
- dat += "Prism*: A prolonging prism, which delays the shuttle for two minutes at a huge power cost.
"
- dat += "Motor*: A mania motor, which serves as area-denial through negative effects and eventual conversion. "
- dat += "Daemon*: A tinkerer's daemon, which quickly creates components. "
- dat += "Obelisk*: A clockwork obelisk, which can broadcast large messages and allows limited teleportation. "
- dat += "Sigils "
- dat += "Note: Sigils can be stacked on top of one another, making certain sigils very effective when paired! "
- dat += "Transgression: Stuns the first non-Servant to cross it for ten seconds and blinds others nearby. Disappears on use. "
- dat += "Submission: Converts the first non-Servant to stand on the sigil for seven seconds. Disappears on use. "
- dat += "Matrix: Drains health from non-Servants, producing Vitality. Can heal and revive Servants. "
- dat += "Accession: Identical to the Sigil of Submission, but doesn't disappear on use. It can also convert a single mindshielded target, but will disappear after doing this. "
- dat += "Transmission: Drains and stores power for clockwork structures. Feeding it brass sheets will create additional power.
"
- dat += "-=-=-=-=-=-"
- if("Components")
- dat += "Components & Their Uses
"
- dat += "Components are your primary resource as a Servant. There are five types of component, with each one being used in different roles:
"
- dat += "Although this is a good rule of thumb, their effects become much more nuanced when used together. For instance, a turret might have both belligerent eyes and \
- vanguard cogwheels as construction requirements, because it defends its allies by harming its enemies.
"
- dat += "Components' primary use is fueling scripture (covered in its own section), and they can be created through various ways. This clockwork slab, for instance, \
- will make a random component of every type - or a specific one, if you choose a target component from the interface - every remove me already. This number will increase \
- as the amount of Servants in the covenant increase; additionally, slabs can only produce components when held by a Servant, and holding more than one slab will cause both \
- of them to halt progress until one of them is removed from their person.
"
- dat += "Your slab has an internal storage of components, but it isn't meant to be the main one. Instead, there's a global storage of components that can be \
- added to through various ways. Anything that needs components will first draw them from the global storage before attempting to draw them from the slab. Most methods of \
- component production add to the global storage. You can also offload components from your slab into the global storage by using it on a Tinkerer's Cache, a structure whose \
- primary purpose is to do just that (although it will also slowly produce components when placed near a brass wall.)
"
- dat += "-=-=-=-=-=-"
- if("Scripture")
- dat += "The Ancient Scripture
"
- dat += "If you have experience with the Nar'Sian cult (or the \"blood cult\") then you will know of runes. They are the manifestations of the Geometer's power, and where most \
- of the cult's supernatural ability comes from. The Servant equivalent of runes is called scripture, and unlike runes, scripture is loaded into your clockwork slab.
"
- dat += "Each piece of scripture has widely-varying effects. Your most important scripture, Geis, is obvious and suspicious, but charges your slab with energy and allows \
- you to attack a non-Servant in melee range to restrain them and begin converting them into a Servant. This is just one example; each piece of scripture can be simple or \
- complex, be obvious or have hidden mechanics that can only be found through trial and error.
"
- dat += "Any given piece of scripture has a component cost listed in its \"Recite\" button. The acronyms for the components should be obvious if you've read about components \
- already; reciting this piece of scripture will consume the listed components, first from the global storage and then from your slab. Note that failing to recite a piece of \
- scripture will not consume the components required to recite it.
"
- dat += "It should also be noted that some scripture cannot be recited alone. Especially with more powerful scripture, you may need multiple Servants to recite a piece of \
- scripture; both of you will need to stand still until the recital completes. Only human and silicon Servants are valid for scripture recital! Constructs cannot help \
- in reciting scripture.
"
- dat += "Finally, scripture is separated into three \"tiers\" based on power: Drivers, Scripts, and Applications.[prob(1) ? " (The Revenant tier was removed a long time ago. \
- Get with the times.)" : ""] You can view the requirements to unlock each tier in its scripture list. Once a tier is unlocked, it's unlocked permanently; the cult only needs to fill the \
- requirement for unlocking a tier once!
"
- dat += "-=-=-=-=-=-"
- if("Power")
- dat += "Power! Unlimited Power!
"
- dat += "In the early stages of the cult, the only resource that must be actively worried about is components. However, as new scripture is unlocked, a new resource \
- becomes necessary: power. Almost all clockwork structures require power to function in some way. There is nothing special about this power; it's mere electricity, \
- and can be harnessed in several ways.
"
- dat += "To begin with, if there is no other source of power nearby, structures will draw from the area's APC, assuming it has one. This is inefficient and ill-advised as \
- anything but a last resort. Instead, it is recommended that a Sigil of Transmission is created. This sigil serves as both battery and power generator for nearby clockwork \
- structures, and those structures will happily draw power from the sigil before they resort to APCs.
"
- dat += "Generating power is less easy. The most reliable and efficient way is using brass sheets; attacking a sigil of transmission with brass sheets will convert them \
- to power, at a rate of [DisplayPower(POWER_FLOOR)] per sheet. (Brass sheets are created from replica fabricators, which are explained more in detail in the Conversion section.) \
- Activating a sigil of transmission will also cause it to drain power from the nearby area, which, while effective, serves as an obvious tell that there is something wrong.
"
- dat += "Without power, many structures will not function, making a base vulnerable to attack. For this reason, it is critical that you keep an eye on your power reserves and \
- ensure that they remain comfortably high.
"
- dat += "-=-=-=-=-=-"
- if("Conversion")
- dat += "Growing the Ranks
"
- dat += "Because the Servants of Ratvar are a cult, the main method to gain more power is to \"enlighten\" normal crew into new Servants. When a crewmember is converted, \
- they become a full-fledged Servant, ready and willing to serve the cause of Ratvar. It should also be noted that silicon crew, such as cyborgs and the AI, can be \
- converted just like normal crew and will gain special abilities; this is covered later. This section will also cover converting the station's structure itself; walls, \
- floors, windows, tables, and other objects can all be converted into clockwork versions, and serve an important purpose.
"
- dat += "A Note on Geis: There are several ways to convert humans and silicons. However, the most important tool to making them work is \
- Geis, a Driver-tier scripture. Using it whispers an invocation very quickly and charges your slab with power. In addition to making the slab visible in your hand, \
- you can now use it on a target within melee range to bind and mute them. It is by far your most reliable tool for capturing potential converts and targets, though it is incredibly \
- obvious. In addition, you are unable to take any actions other than moving while your target is bound. The binding will last for 25 seconds and mute for about 13 seconds, though \
- allies can use Geis to refresh these effects.
"
- dat += "Converting: The two methods of conversion are the sigil of submission, whose purpose is to do so, and the mania motor. \
- The sigil of submission is a sigil that, when stood on by a non-Servant for eight seconds, will convert that non-Servant. This is the only practical way to convert targets. \
- Sigils of submission are cheap, early, and permanent! Make sure sigils of submission are placed only in bases or otherwise hidden spots, or with a sigil of transgression on them. \
- The mania motor, however, is generally unreliable and unlocked later, only converting those who stand near it for an extended period.
"
- dat += "Converting Humans: For obvious reasons, humans are the most common conversion target. Because every crew member is different, and \
- may be armed with different equipment, you should take precautions to ensure that they aren't able to resist. If able, removing a headset is essential, as is restraining \
- them through handcuffs, cable ties, or other restraints. Some crew, like security, are also implanted with mindshield implants; these will prevent conversion and must be \
- surgically removed before they are an eligible convert. Note: The captain is never an eligible convert and should instead be killed or imprisoned. If security \
- begins administering mindshield implants, this will greatly inhibit conversion. Also note that mindshield implants can be broken by a sigil of accession automatically, but \
- the sigil will disappear.
"
- dat += "Converting Silicons: Due to their robotic nature, silicons are generally more predictable than humans in terms of conversion. \
- However, they are also much, much harder to subdue, especially cyborgs. The easiest way to convert a cyborg is by using Geis to restrain them, then dragging them to a sigil \
- of submission. If you stack a sigil of transgression and a sigil of submission, a crossing cyborg will be stunned and helpless to escape before they are converted.
"
- dat += "Converting AIs is very often the hardest task of the cult, and has been the downfall of countless successful Servants. Their omnipresence across the station, \
- coupled with their secure location and ability to lock themselves securely, makes them a powerful target. However, once the AI itself is reached, it is usually completely \
- helpless to resist its own conversion. A very common tactic is to take advantage of a converted cyborg to rush the AI before it is able to react.
"
- dat += "Even once an AI is converted, care must be taken to ensure that it remains hidden. Not only does the AI's core become brassy and thus obvious to an outside \
- observer, but the AI loses the ability to speak in anything but Ratvarian. For this reason, it has to remain completely silent over common radio channels if stealth \
- is at all a priority. This is suspicious and will rapidly lead to the crew checking on it, which usually results in the cult's outing. It is, however, necessary to convert \
- all AIs present on the station before the Ark becomes invokable, so this must be done at some point.
"
- dat += "Converting the Station: Converted objects all serve a purpose and are important to the cult's success. To convert objects, \
- a Servant needs to use a replica fabricator, a handheld tool that uses power to replace objects with clockwork versions. Different clockwork objects have different \
- effects and are often crucial. The most noteworthy are clockwork walls, which automatically \"link\" to any nearby Tinkerer's Caches, causing them to slowly \
- generate components. This is incredibly useful for obvious reasons, and creating a clockwork wall near every Tinkerer's Cache should be prioritized. Clockwork floors \
- will slowly heal any toxin damage suffered by Servants standing on them, and clockwork airlocks can only be opened by Servants.
"
- dat += "The replica fabricator itself is also worth noting. In addition to replacing objects, it can also create brass sheets at the cost of power by using the \
- fabricator in-hand. It can also be used to repair any damaged clockwork structures.
"
- dat += "Replacing objects is almost as, if not as important as, converting new Servants. A base is impossible to manage without clockwork walls at the very least, and \
- once the cult has been outed and the crew are actively searching, there is little reason not to use as many as possible.
"
- dat += "-=-=-=-=-=-"
- else
- dat += "404: [section ? section : "Section"] Not Found!
\
- One of the cogscarabs must've misplaced this section, because the game wasn't able to find any info regarding it. Report this to the coders!"
- return "
[dat.Join()]
"
-
-//Gets the quickbound scripture as a text block.
-/obj/item/clockwork/slab/proc/get_recollection_quickbinds()
- var/list/dat = list()
- dat += "Quickbound Scripture \
- You can have up to five scriptures bound to action buttons for easy use.
"
- if(LAZYLEN(quickbound))
- for(var/i in 1 to maximum_quickbound)
- if(LAZYLEN(quickbound) < i || !quickbound[i])
- dat += "A Quickbind slot, currently set to Nothing. "
- else
- var/datum/clockwork_scripture/quickbind_slot = quickbound[i]
- dat += "A Quickbind slot, currently set to [initial(quickbind_slot.name)]. "
- return dat.Join()
-
-
-/obj/item/clockwork/slab/ui_data(mob/user) //we display a lot of data via TGUI
- var/list/data = list()
- data["power"] = "[DisplayPower(get_clockwork_power())] power is available for scripture and other consumers."
-
- switch(selected_scripture) //display info based on selected scripture tier
- if(SCRIPTURE_DRIVER)
- data["tier_info"] = "These scriptures are permanently unlocked."
- if(SCRIPTURE_SCRIPT)
- if(GLOB.scripture_states[SCRIPTURE_SCRIPT])
- data["tier_info"] = "These scriptures are permanently unlocked."
- else
- data["tier_info"] = "These scriptures will automatically unlock when the Ark is halfway ready or if [DisplayPower(SCRIPT_UNLOCK_THRESHOLD)] of power is reached."
- if(SCRIPTURE_APPLICATION)
- if(GLOB.scripture_states[SCRIPTURE_APPLICATION])
- data["tier_info"] = "These scriptures are permanently unlocked."
- else
- data["tier_info"] = "Unlock these optional scriptures by converting another servant or if [DisplayPower(APPLICATION_UNLOCK_THRESHOLD)] of power is reached.."
-
- data["selected"] = selected_scripture
- data["scripturecolors"] = "Scriptures in yellow are related to construction and building. \
- Scriptures in red are related to attacking and offense. \
- Scriptures in blue are related to healing and defense. \
- Scriptures in purple are niche but still important! \
- Scriptures with italicized names are important to success."
- generate_all_scripture()
-
- data["scripture"] = list()
- for(var/s in GLOB.all_scripture)
- var/datum/clockwork_scripture/S = GLOB.all_scripture[s]
- if(S.tier == selected_scripture) //display only scriptures of the selected tier
- var/scripture_color = get_component_color_bright(S.primary_component)
- var/list/temp_info = list("name" = "[S.name]",
- "descname" = "([S.descname])",
- "tip" = "[S.desc]\n[S.usage_tip]",
- "required" = "([DisplayPower(S.power_cost)][S.special_power_text ? "+ [replacetext(S.special_power_text, "POWERCOST", "[DisplayPower(S.special_power_cost)]")]" : ""])",
- "type" = "[S.type]",
- "quickbind" = S.quickbind)
- if(S.important)
- temp_info["name"] = "[temp_info["name"]]"
- var/found = quickbound.Find(S.type)
- if(found)
- temp_info["bound"] = "[found]"
- if(S.invokers_required > 1)
- temp_info["invokers"] = "Invokers: [S.invokers_required]"
- data["scripture"] += list(temp_info)
- data["recollection"] = recollecting
- if(recollecting)
- data["recollection_categories"] = GLOB.ratvar_awakens ? list() : list(\
- list("name" = "Getting Started", "desc" = "First-time servant? Read this first."), \
- list("name" = "Basics", "desc" = "A primer on how to play as a servant."), \
- list("name" = "Terminology", "desc" = "Common acronyms, words, and terms."), \
- list("name" = "Components", "desc" = "Information on components, your primary resource."), \
- list("name" = "Scripture", "desc" = "Information on scripture, ancient tools used by the cult."), \
- list("name" = "Power", "desc" = "The power system that certain objects use to function."), \
- list("name" = "Conversion", "desc" = "Converting the crew, cyborgs, and very walls to your cause."), \
- )
- data["rec_text"] = recollection()
- data["rec_section"] = GLOB.ratvar_awakens ? "" : get_recollection_text(recollection_category)
- data["rec_binds"] = GLOB.ratvar_awakens ? "" : get_recollection_quickbinds()
- return data
-
-/obj/item/clockwork/slab/ui_act(action, params)
- switch(action)
- if("toggle")
- recollecting = !recollecting
- if("recite")
- INVOKE_ASYNC(src, .proc/recite_scripture, text2path(params["category"]), usr, FALSE)
- if("select")
- selected_scripture = params["category"]
- if("bind")
- var/datum/clockwork_scripture/path = text2path(params["category"]) //we need a path and not a string
- var/found_index = quickbound.Find(path)
- if(found_index) //hey, we already HAVE this bound
- if(LAZYLEN(quickbound) == found_index) //if it's the last scripture, remove it instead of leaving a null
- quickbound -= path
- else
- quickbound[found_index] = null //otherwise, leave it as a null so the scripture maintains position
- update_quickbind()
- else
- var/target_index = input("Position of [initial(path.name)], 1 to [maximum_quickbound]?", "Input") as num|null
- if(isnum(target_index) && target_index > 0 && target_index <= maximum_quickbound && !..())
- var/datum/clockwork_scripture/S
- if(LAZYLEN(quickbound) >= target_index)
- S = quickbound[target_index]
- if(S != path)
- quickbind_to_slot(path, target_index)
- if("rec_category")
- recollection_category = params["category"]
- ui_interact(usr)
- return 1
-
-/obj/item/clockwork/slab/proc/quickbind_to_slot(datum/clockwork_scripture/scripture, index) //takes a typepath(typecast for initial()) and binds it to a slot
- if(!ispath(scripture) || !scripture || (scripture in quickbound))
- return
- while(LAZYLEN(quickbound) < index)
- quickbound += null
- var/datum/clockwork_scripture/quickbind_slot = GLOB.all_scripture[quickbound[index]]
- if(quickbind_slot && !quickbind_slot.quickbind)
- return //we can't unbind things we can't normally bind
- quickbound[index] = scripture
- update_quickbind()
-
-/obj/item/clockwork/slab/proc/update_quickbind()
- for(var/datum/action/item_action/clock/quickbind/Q in actions)
- qdel(Q) //regenerate all our quickbound scriptures
- if(LAZYLEN(quickbound))
- for(var/i in 1 to quickbound.len)
- if(!quickbound[i])
- continue
- var/datum/action/item_action/clock/quickbind/Q = new /datum/action/item_action/clock/quickbind(src)
- Q.scripture_index = i
- var/datum/clockwork_scripture/quickbind_slot = GLOB.all_scripture[quickbound[i]]
- Q.name = "[quickbind_slot.name] ([Q.scripture_index])"
- Q.desc = quickbind_slot.quickbind_desc
- Q.button_icon_state = quickbind_slot.name
- Q.UpdateButtonIcon()
- if(isliving(loc))
- Q.Grant(loc)
diff --git a/code/modules/antagonists/clockcult/clock_items/clockwork_weaponry.dm b/code/modules/antagonists/clockcult/clock_items/clockwork_weaponry.dm
deleted file mode 100644
index f2174030a65..00000000000
--- a/code/modules/antagonists/clockcult/clock_items/clockwork_weaponry.dm
+++ /dev/null
@@ -1,15 +0,0 @@
-//This is the base type for clockwork melee weapons.
-/obj/item/clockwork/weapon
- name = "clockwork weapon"
- desc = "Weaponized brass. Whould've thunk it?"
- clockwork_desc = "This shouldn't exist. Report it to a coder."
- icon = 'icons/obj/clockwork_objects.dmi'
- lefthand_file = 'icons/mob/inhands/antag/clockwork_lefthand.dmi'
- righthand_file = 'icons/mob/inhands/antag/clockwork_righthand.dmi'
- var/datum/action/innate/call_weapon/action //Some melee weapons use an action that lets you return and dismiss them
-
-/obj/item/clockwork/weapon/Initialize(mapload, new_action)
- . = ..()
- if(new_action)
- action = new_action
- action.weapon = src
diff --git a/code/modules/antagonists/clockcult/clock_items/construct_chassis.dm b/code/modules/antagonists/clockcult/clock_items/construct_chassis.dm
deleted file mode 100644
index ae341fea537..00000000000
--- a/code/modules/antagonists/clockcult/clock_items/construct_chassis.dm
+++ /dev/null
@@ -1,112 +0,0 @@
-//Construct shells that can be activated by ghosts.
-/obj/item/clockwork/construct_chassis
- name = "construct chassis"
- desc = "A shell formed out of brass, presumably for housing machinery."
- clockwork_desc = "A construct chassis. It can be activated at any time by a willing ghost."
- var/construct_name = "basic construct"
- var/construct_desc = "There is no construct for this chassis. Report this to a coder."
- icon_state = "anime_fragment"
- resistance_flags = FIRE_PROOF | ACID_PROOF
- w_class = WEIGHT_CLASS_HUGE
- var/creation_message = "The chassis shudders and hums to life!"
- var/construct_type //The construct this shell will create
-
-/obj/item/clockwork/construct_chassis/Initialize()
- . = ..()
- var/area/A = get_area(src)
- if(A && construct_type)
- notify_ghosts("A [construct_name] chassis has been created in [A.name]!", 'sound/magic/clockwork/fellowship_armory.ogg', notify_volume = 75, source = src, action = NOTIFY_ATTACK, flashwindow = FALSE, ignore_key = POLL_IGNORE_CONSTRUCT)
- GLOB.poi_list += src
- LAZYADD(GLOB.mob_spawners[name], src)
-
-/obj/item/clockwork/construct_chassis/Destroy()
- GLOB.poi_list -= src
- var/list/spawners = GLOB.mob_spawners[name]
- LAZYREMOVE(spawners, src)
- . = ..()
-
-/obj/item/clockwork/construct_chassis/examine(mob/user)
- clockwork_desc = "[clockwork_desc] [construct_desc]"
- . = ..()
- clockwork_desc = initial(clockwork_desc)
-
-//ATTACK HAND IGNORING PARENT RETURN VALUE
-/obj/item/clockwork/construct_chassis/attack_hand(mob/living/user)
- if(w_class >= WEIGHT_CLASS_HUGE)
- to_chat(user, "[src] is too cumbersome to carry! Drag it around instead!")
- return
- . = ..()
-
-//ATTACK GHOST IGNORING PARENT RETURN VALUE
-/obj/item/clockwork/construct_chassis/attack_ghost(mob/user)
- if(!SSticker.mode)
- to_chat(user, "You cannot use that before the game has started.")
- return
- if(QDELETED(src))
- to_chat(user, "You were too late! Better luck next time.")
- return
- user.forceMove(get_turf(src)) //If we attack through the alert, jump to the chassis so we know what we're getting into
- if(alert(user, "Become a [construct_name]? You can no longer be cloned!", construct_name, "Yes", "Cancel") == "Cancel")
- return
- if(QDELETED(src))
- to_chat(user, "You were too late! Better luck next time.")
- return
- pre_spawn()
- visible_message(creation_message)
- var/mob/living/construct = new construct_type(get_turf(src))
- construct.key = user.key
- post_spawn(construct)
- qdel(user)
- qdel(src)
-
-/obj/item/clockwork/construct_chassis/proc/pre_spawn() //Some things might change before the construct spawns; override those on a subtype basis in this proc
- return
-
-/obj/item/clockwork/construct_chassis/proc/post_spawn(mob/living/construct) //And some things might change after it
- return
-
-
-//Marauder armor, used to create clockwork marauders - sturdy frontline combatants that can deflect projectiles.
-/obj/item/clockwork/construct_chassis/clockwork_marauder
- name = "marauder armor"
- desc = "A pile of sleek and well-polished brass armor. A small red gemstone sits in its faceplate."
- icon_state = "marauder_armor"
- construct_name = "clockwork marauder"
- construct_desc = "It will become a clockwork marauder, a well-rounded frontline combatant."
- creation_message = "Crimson fire begins to rage in the armor as it rises into the air with its armaments!"
- construct_type = /mob/living/simple_animal/hostile/clockwork/marauder
-
-
-//Cogscarab shell, used to create cogcarabs - fragile but zippy little drones that build and maintain the base.
-/obj/item/clockwork/construct_chassis/cogscarab
- name = "cogscarab shell"
- desc = "A small, complex shell that resembles a repair drone, but much larger and made out of brass."
- icon_state = "cogscarab_shell"
- construct_name = "cogscarab"
- construct_desc = "It will become a cogscarab, a small and fragile drone that builds, repairs, and maintains."
- creation_message = "The cogscarab clicks and whirrs as it hops up and springs to life!"
- construct_type = /mob/living/simple_animal/drone/cogscarab
- w_class = WEIGHT_CLASS_SMALL
- var/infinite_resources = TRUE
- var/static/obj/item/seasonal_hat //Share it with all other scarabs, since we're from the same cult!
-
-/obj/item/clockwork/construct_chassis/cogscarab/Initialize()
- . = ..()
- if(GLOB.servants_active)
- infinite_resources = FALSE //For any that are somehow spawned in late
-
-/obj/item/clockwork/construct_chassis/cogscarab/pre_spawn()
- if(infinite_resources)
- //During rounds where they can't interact with the station, let them experiment with builds
- construct_type = /mob/living/simple_animal/drone/cogscarab/ratvar
-
-/obj/item/clockwork/construct_chassis/cogscarab/post_spawn(mob/living/construct)
- if(infinite_resources) //Allow them to build stuff and recite scripture
- var/list/cached_stuff = construct.GetAllContents()
- for(var/obj/item/clockwork/replica_fabricator/F in cached_stuff)
- F.uses_power = FALSE
- for(var/obj/item/clockwork/slab/S in cached_stuff)
- S.no_cost = TRUE
- if(seasonal_hat && seasonal_hat != "none")
- var/obj/item/hat = new seasonal_hat(construct)
- construct.equip_to_slot_or_del(hat, SLOT_HEAD)
diff --git a/code/modules/antagonists/clockcult/clock_items/integration_cog.dm b/code/modules/antagonists/clockcult/clock_items/integration_cog.dm
deleted file mode 100644
index 0ce70336fe5..00000000000
--- a/code/modules/antagonists/clockcult/clock_items/integration_cog.dm
+++ /dev/null
@@ -1,37 +0,0 @@
-#define COG_MAX_SIPHON_THRESHOLD 0.25 //The cog will not siphon power if the APC's cell is at this % of power
-
-//Can be used on an open APC to replace its guts with clockwork variants, and begin passively siphoning power from it
-/obj/item/clockwork/integration_cog
- name = "integration cog"
- desc = "A small cogwheel that fits in the palm of your hand."
- clockwork_desc = "A small cogwheel that can be inserted into an open APC to siphon power from it passively. \
- It can be used on a locked APC to open its cover! \
- Siphons 5 W of power per second while in an APC."
- icon_state = "wall_gear"
- w_class = WEIGHT_CLASS_TINY
- item_flags = NOBLUDGEON
- var/obj/machinery/power/apc/apc
-
-/obj/item/clockwork/integration_cog/Initialize()
- . = ..()
- transform *= 0.5 //little cog!
-
-/obj/item/clockwork/integration_cog/Destroy()
- STOP_PROCESSING(SSfastprocess, src)
- . = ..()
-
-/obj/item/clockwork/integration_cog/process()
- if(!apc)
- if(istype(loc, /obj/machinery/power/apc))
- apc = loc
- else
- STOP_PROCESSING(SSfastprocess, src)
- else
- var/obj/item/stock_parts/cell/cell = apc.cell
- if(cell && (cell.charge / cell.maxcharge > COG_MAX_SIPHON_THRESHOLD))
- cell.use(1)
- adjust_clockwork_power(2) //Power is shared, so only do it once; this runs very quickly so it's about 10 W/second
- else
- adjust_clockwork_power(1) //Continue generating power when the cell has run dry; 5 W/second
-
-#undef COG_MAX_SIPHON_THRESHOLD
diff --git a/code/modules/antagonists/clockcult/clock_items/judicial_visor.dm b/code/modules/antagonists/clockcult/clock_items/judicial_visor.dm
deleted file mode 100644
index ad8ad11a29d..00000000000
--- a/code/modules/antagonists/clockcult/clock_items/judicial_visor.dm
+++ /dev/null
@@ -1,218 +0,0 @@
-//Judicial visor: Grants the ability to smite an area and knocking down the unfaithful nearby every thirty seconds.
-/obj/item/clothing/glasses/judicial_visor
- name = "judicial visor"
- desc = "A strange purple-lensed visor. Looking at it inspires an odd sense of guilt."
- icon = 'icons/obj/clothing/clockwork_garb.dmi'
- icon_state = "judicial_visor_0"
- item_state = "sunglasses"
- resistance_flags = FIRE_PROOF | ACID_PROOF
- flash_protect = FLASH_PROTECTION_FLASH
- var/active = FALSE //If the visor is online
- var/recharging = FALSE //If the visor is currently recharging
- var/obj/effect/proc_holder/judicial_visor/blaster
- var/recharge_cooldown = 300 //divided by 10 if ratvar is alive
- actions_types = list(/datum/action/item_action/clock/toggle_visor)
-
-/obj/item/clothing/glasses/judicial_visor/Initialize()
- . = ..()
- GLOB.all_clockwork_objects += src
- blaster = new(src)
- blaster.visor = src
-
-/obj/item/clothing/glasses/judicial_visor/Destroy()
- GLOB.all_clockwork_objects -= src
- if(blaster.ranged_ability_user)
- blaster.remove_ranged_ability()
- blaster.visor = null
- qdel(blaster)
- return ..()
-
-/obj/item/clothing/glasses/judicial_visor/item_action_slot_check(slot, mob/user)
- if(slot != SLOT_GLASSES)
- return 0
- return ..()
-
-/obj/item/clothing/glasses/judicial_visor/equipped(mob/living/user, slot)
- ..()
- if(slot != SLOT_GLASSES)
- update_status(FALSE)
- if(blaster.ranged_ability_user)
- blaster.remove_ranged_ability()
- return 0
- if(is_servant_of_ratvar(user))
- update_status(TRUE)
- else
- update_status(FALSE)
- if(iscultist(user)) //Cultists spontaneously combust
- to_chat(user, "\"Consider yourself judged, whelp.\"")
- to_chat(user, "You suddenly catch fire!")
- user.adjust_fire_stacks(5)
- user.IgniteMob()
- return 1
-
-/obj/item/clothing/glasses/judicial_visor/dropped(mob/user)
- . = ..()
- addtimer(CALLBACK(src, .proc/check_on_mob, user), 1) //dropped is called before the item is out of the slot, so we need to check slightly later
-
-/obj/item/clothing/glasses/judicial_visor/proc/check_on_mob(mob/user)
- if(user && src != user.get_item_by_slot(SLOT_GLASSES)) //if we happen to check and we AREN'T in the slot, we need to remove our shit from whoever we got dropped from
- update_status(FALSE)
- if(blaster.ranged_ability_user)
- blaster.remove_ranged_ability()
-
-/obj/item/clothing/glasses/judicial_visor/attack_self(mob/user)
- if(is_servant_of_ratvar(user) && src == user.get_item_by_slot(SLOT_GLASSES))
- blaster.toggle(user)
-
-/obj/item/clothing/glasses/judicial_visor/proc/update_status(change_to)
- if(recharging || !isliving(loc))
- icon_state = "judicial_visor_0"
- return 0
- if(active == change_to)
- return 0
- var/mob/living/L = loc
- active = change_to
- icon_state = "judicial_visor_[active]"
- L.update_action_buttons_icon()
- L.update_inv_glasses()
- if(!is_servant_of_ratvar(L) || L.stat)
- return 0
- switch(active)
- if(TRUE)
- to_chat(L, "As you put on [src], its lens begins to glow, information flashing before your eyes.\n\
- Judicial visor active. Use the action button to gain the ability to smite the unworthy.")
- if(FALSE)
- to_chat(L, "As you take off [src], its lens darkens once more.")
- return 1
-
-/obj/item/clothing/glasses/judicial_visor/proc/recharge_visor(mob/living/user)
- if(!src)
- return 0
- recharging = FALSE
- if(user && src == user.get_item_by_slot(SLOT_GLASSES))
- to_chat(user, "Your [name] hums. It is ready.")
- else
- active = FALSE
- icon_state = "judicial_visor_[active]"
- if(user)
- user.update_action_buttons_icon()
- user.update_inv_glasses()
-
-/obj/effect/proc_holder/judicial_visor
- active = FALSE
- ranged_mousepointer = 'icons/effects/visor_reticule.dmi'
- var/obj/item/clothing/glasses/judicial_visor/visor
-
-/obj/effect/proc_holder/judicial_visor/proc/toggle(mob/user)
- var/message
- if(active)
- message = "You dispel the power of [visor]."
- remove_ranged_ability(message)
- else
- message = "You harness [visor]'s power.Left-click to place a judicial marker!"
- add_ranged_ability(user, message)
-
-/obj/effect/proc_holder/judicial_visor/InterceptClickOn(mob/living/caller, params, atom/target)
- if(..())
- return
- if(ranged_ability_user.incapacitated() || !visor || visor != ranged_ability_user.get_item_by_slot(SLOT_GLASSES))
- remove_ranged_ability()
- return
-
- var/turf/T = ranged_ability_user.loc
- if(!isturf(T))
- return FALSE
-
- if(target in view(7, get_turf(ranged_ability_user)))
- visor.recharging = TRUE
- visor.update_status()
- for(var/obj/item/clothing/glasses/judicial_visor/V in ranged_ability_user.GetAllContents())
- if(V == visor)
- continue
- V.recharging = TRUE //To prevent exploiting multiple visors to bypass the cooldown
- V.update_status()
- addtimer(CALLBACK(V, /obj/item/clothing/glasses/judicial_visor.proc/recharge_visor, ranged_ability_user), (GLOB.ratvar_awakens ? visor.recharge_cooldown*0.1 : visor.recharge_cooldown) * 2)
- clockwork_say(ranged_ability_user, text2ratvar("Kneel, heathens!"))
- ranged_ability_user.visible_message("[ranged_ability_user]'s judicial visor fires a stream of energy at [target], creating a strange mark!", "You direct [visor]'s power to [target]. You must wait for some time before doing this again.")
- var/turf/targetturf = get_turf(target)
- new/obj/effect/clockwork/judicial_marker(targetturf, ranged_ability_user)
- log_combat(ranged_ability_user, targetturf, "created a judicial marker")
- ranged_ability_user.update_action_buttons_icon()
- ranged_ability_user.update_inv_glasses()
- addtimer(CALLBACK(visor, /obj/item/clothing/glasses/judicial_visor.proc/recharge_visor, ranged_ability_user), GLOB.ratvar_awakens ? visor.recharge_cooldown*0.1 : visor.recharge_cooldown)//Cooldown is reduced by 10x if Ratvar is up
- remove_ranged_ability()
-
- return TRUE
- return FALSE
-
-//Judicial marker: Created by the judicial visor. Immediately applies Belligerent and briefly knocks down, then after 3 seconds does large damage and briefly knocks down again
-/obj/effect/clockwork/judicial_marker
- name = "judicial marker"
- desc = "You get the feeling that you shouldn't be standing here."
- clockwork_desc = "A sigil that will soon erupt and smite any unenlightened nearby."
- icon = 'icons/effects/96x96.dmi'
- icon_state = "transparent"
- pixel_x = -32
- pixel_y = -32
- layer = BELOW_MOB_LAYER
- var/mob/user
-
-/obj/effect/clockwork/judicial_marker/Initialize(mapload, caster)
- . = ..()
- set_light(1.4, 2, "#FE9C11")
- user = caster
- INVOKE_ASYNC(src, .proc/judicialblast)
-
-/obj/effect/clockwork/judicial_marker/singularity_act()
- return
-
-/obj/effect/clockwork/judicial_marker/singularity_pull()
- return
-
-/obj/effect/clockwork/judicial_marker/proc/judicialblast()
- playsound(src, 'sound/magic/magic_missile.ogg', 50, TRUE, TRUE, TRUE)
- flick("judicial_marker", src)
- for(var/mob/living/carbon/C in range(1, src))
- var/datum/status_effect/belligerent/B = C.apply_status_effect(STATUS_EFFECT_BELLIGERENT)
- if(!QDELETED(B))
- B.duration = world.time + 30
- C.Paralyze(5) //knocks down for half a second if affected
- sleep(!GLOB.ratvar_approaches ? 16 : 10)
- name = "judicial blast"
- layer = ABOVE_ALL_MOB_LAYER
- flick("judicial_explosion", src)
- set_light(1.4, 2, "#B451A1")
- sleep(13)
- name = "judicial explosion"
- var/targetsjudged = 0
- playsound(src, 'sound/effects/explosion_distant.ogg', 100, TRUE, TRUE, TRUE)
- set_light(0)
- for(var/mob/living/L in range(1, src))
- if(is_servant_of_ratvar(L))
- continue
- var/atom/I = L.anti_magic_check()
- if(I)
- if(isitem(I))
- L.visible_message("Strange energy flows into [L]'s [I.name]!", \
- "Your [I.name] shields you from [src]!")
- continue
- L.Paralyze(15) //knocks down briefly when exploding
- if(!iscultist(L))
- L.visible_message("[L] is struck by a judicial explosion!", \
- "[!issilicon(L) ? "An unseen force slams you into the ground!" : "ERROR: Motor servos disabled by external source!"]")
- else
- L.visible_message("[L] is struck by a judicial explosion!", \
- "\"Keep an eye out, filth.\"\nA burst of heat crushes you against the ground!")
- L.adjust_fire_stacks(2) //sets cultist targets on fire
- L.IgniteMob()
- L.adjustFireLoss(5)
- targetsjudged++
- if(!QDELETED(L))
- L.adjustBruteLoss(20) //does a decent amount of damage
- log_combat(user, L, "struck with a judicial blast")
- to_chat(user, "[targetsjudged ? "Successfully judged [targetsjudged]":"Judged no"] heretic[targetsjudged == 1 ? "":"s"].")
- sleep(3) //so the animation completes properly
- qdel(src)
-
-/obj/effect/clockwork/judicial_marker/ex_act(severity)
- return
diff --git a/code/modules/antagonists/clockcult/clock_items/replica_fabricator.dm b/code/modules/antagonists/clockcult/clock_items/replica_fabricator.dm
deleted file mode 100644
index b5d4c1a1120..00000000000
--- a/code/modules/antagonists/clockcult/clock_items/replica_fabricator.dm
+++ /dev/null
@@ -1,223 +0,0 @@
-//Replica Fabricator: Converts applicable objects to Ratvarian variants.
-/obj/item/clockwork/replica_fabricator
- name = "replica fabricator"
- desc = "An odd, L-shaped device that hums with energy."
- clockwork_desc = "A device that allows the replacing of mundane objects with Ratvarian variants. It requires power to function."
- icon_state = "replica_fabricator"
- lefthand_file = 'icons/mob/inhands/antag/clockwork_lefthand.dmi'
- righthand_file = 'icons/mob/inhands/antag/clockwork_righthand.dmi'
- w_class = WEIGHT_CLASS_NORMAL
- force = 5
- item_flags = NOBLUDGEON
- var/speed_multiplier = 1 //The speed ratio the fabricator operates at
- var/uses_power = TRUE
- var/repairing = null //what we're currently repairing, if anything
-
-/obj/item/clockwork/replica_fabricator/scarab
- name = "scarab fabricator"
- clockwork_desc = "A cogscarab's internal fabricator. It can only be successfully used by a cogscarab and requires power to function."
- item_state = "nothing"
- w_class = WEIGHT_CLASS_TINY
- speed_multiplier = 0.5
- var/debug = FALSE
-
-/obj/item/clockwork/replica_fabricator/scarab/fabricate(atom/target, mob/living/user)
- if(!debug && !isdrone(user))
- return 0
- return ..()
-
-/obj/item/clockwork/replica_fabricator/scarab/debug
- clockwork_desc = "A cogscarab's internal fabricator. It can convert nearly any object into a Ratvarian variant."
- uses_power = FALSE
- debug = TRUE
-
-/obj/item/clockwork/replica_fabricator/cyborg
- name = "cyborg fabricator"
- clockwork_desc = "A cyborg's internal fabricator."
-
-/obj/item/clockwork/replica_fabricator/ratvar_act()
- if(GLOB.ratvar_awakens)
- uses_power = FALSE
- speed_multiplier = initial(speed_multiplier) * 0.25
- else
- uses_power = initial(uses_power)
- speed_multiplier = initial(speed_multiplier)
-
-/obj/item/clockwork/replica_fabricator/examine(mob/living/user)
- . = ..()
- if(is_servant_of_ratvar(user) || isobserver(user))
- . += {"Can be used to replace walls, floors, tables, windows, windoors, and airlocks with Clockwork variants.\n
- Can construct Clockwork Walls on Clockwork Floors and deconstruct Clockwork Walls to Clockwork Floors."}
- if(uses_power)
- . += {"It can consume floor tiles, rods, metal, and plasteel for power at rates of 2:[DisplayPower(POWER_ROD)], 1:[DisplayPower(POWER_ROD)], 1:[DisplayPower(POWER_METAL)], \
- and 1:[DisplayPower(POWER_PLASTEEL)], respectively.\n
- It can also consume brass sheets for power at a rate of 1:[DisplayPower(POWER_FLOOR)].\n
- Use it in-hand to produce 5 brass sheets at a cost of [DisplayPower(POWER_WALL_TOTAL)] power.\n
- It has access to [DisplayPower(get_clockwork_power())] of power."}
-
-/obj/item/clockwork/replica_fabricator/attack_self(mob/living/user)
- if(is_servant_of_ratvar(user))
- if(uses_power)
- if(!get_clockwork_power(POWER_WALL_TOTAL))
- to_chat(user, "[src] requires [DisplayPower(POWER_WALL_TOTAL)] of power to produce brass sheets!")
- return
- adjust_clockwork_power(-POWER_WALL_TOTAL)
- playsound(src, 'sound/items/deconstruct.ogg', 50, TRUE)
- new/obj/item/stack/tile/brass(user.loc, 5)
- to_chat(user, "You use [get_clockwork_power() ? "some":"all"] of [src]'s power to produce 5 brass sheets. It now has access to [DisplayPower(get_clockwork_power())] of power.")
-
-/obj/item/clockwork/replica_fabricator/pre_attack(atom/target, mob/living/user, params)
- if(!target || !user || !is_servant_of_ratvar(user) || istype(target, /obj/item/storage))
- return FALSE
- return !fabricate(target, user)
-
-//A note here; return values are for if we CAN BE PUT ON A TABLE, not IF WE ARE SUCCESSFUL, unless no_table_check is TRUE
-/obj/item/clockwork/replica_fabricator/proc/fabricate(atom/target, mob/living/user, silent, no_table_check)
- if(!target || !user)
- return FALSE
- if(repairing)
- if(!silent)
- to_chat(user, "You are currently repairing [repairing] with [src]!")
- return FALSE
- var/list/fabrication_values = target.fabrication_vals(user, src, silent) //relevant values for fabricating stuff, given as an associated list
- if(!islist(fabrication_values))
- if(fabrication_values != TRUE) //if we get true, fail, but don't send a message for whatever reason
- if(!isturf(target)) //otherwise, if we didn't get TRUE and the original target wasn't a turf, try to fabricate the turf
- return fabricate(get_turf(target), user, no_table_check)
- if(!silent)
- to_chat(user, "[target] cannot be fabricated!")
- if(!no_table_check)
- return TRUE
- return FALSE
- if(GLOB.ratvar_awakens)
- fabrication_values["power_cost"] = 0
-
- var/turf/Y = get_turf(user)
- if(!Y || (!is_centcom_level(Y.z) && !is_station_level(Y.z) && !is_mining_level(Y.z)))
- fabrication_values["operation_time"] *= 2
- if(fabrication_values["power_cost"] > 0)
- fabrication_values["power_cost"] *= 2
-
- var/target_type = target.type
-
- if(!fabricate_checks(fabrication_values, target, target_type, user, silent))
- return FALSE
-
- fabrication_values["operation_time"] *= speed_multiplier
-
- playsound(target, 'sound/machines/click.ogg', 50, TRUE)
- if(fabrication_values["operation_time"])
- if(!silent)
- var/atom/A = fabrication_values["new_obj_type"]
- if(A)
- user.visible_message("[user]'s [name] starts ripping [target] apart!", \
- "You start fabricating \a [initial(A.name)] from [target]...")
- else
- user.visible_message("[user]'s [name] starts consuming [target]!", \
- "Your [name] starts consuming [target]...")
- if(!do_after(user, fabrication_values["operation_time"], target = target, extra_checks = CALLBACK(src, .proc/fabricate_checks, fabrication_values, target, target_type, user, TRUE)))
- return FALSE
- if(!silent)
- var/atom/A = fabrication_values["new_obj_type"]
- if(A)
- user.visible_message("[user]'s [name] replaces [target] with \a [initial(A.name)]!", \
- "You fabricate \a [initial(A.name)] from [target].")
- else
- user.visible_message("[user]'s [name] consumes [target]!", \
- "Your [name] consumes [target].")
- else
- if(!silent)
- var/atom/A = fabrication_values["new_obj_type"]
- if(A)
- user.visible_message("[user]'s [name] rips apart [target], replacing it with \a [initial(A.name)]!", \
- "You fabricate \a [initial(A.name)] from [target].")
- else
- user.visible_message("[user]'s [name] rapidly consumes [target]!", \
- "Your [name] consumes [target].")
-
- playsound(target, 'sound/items/deconstruct.ogg', 50, TRUE)
- var/new_thing_type = fabrication_values["new_obj_type"]
- if(isturf(target)) //if our target is a turf, we're just going to ChangeTurf it and assume it'll work out.
- var/turf/T = target
- T.ChangeTurf(new_thing_type, flags = CHANGETURF_INHERIT_AIR)
- else
- if(new_thing_type)
- if(fabrication_values["dir_in_new"])
- var/atom/A = new new_thing_type(get_turf(target), fabrication_values["spawn_dir"]) //please verify that your new object actually wants to get a dir in New()
- if(fabrication_values["transfer_name"])
- A.name = target.name
- else
- var/atom/A = new new_thing_type(get_turf(target))
- A.setDir(fabrication_values["spawn_dir"])
- if(fabrication_values["transfer_name"])
- A.name = target.name
- if(!fabrication_values["no_target_deletion"]) //for some cases where fabrication_vals() modifies the object but doesn't want it deleted
- qdel(target)
- adjust_clockwork_power(-fabrication_values["power_cost"])
- if(no_table_check)
- return TRUE
- return FALSE
-
-//The following three procs are heavy wizardry.
-//What these procs do is they take an existing list of values, which they then modify.
-//This(modifying an existing object, in this case the list) is the only way to get information OUT of a do_after callback, which this is used as.
-
-//The fabricate check proc.
-/obj/item/clockwork/replica_fabricator/proc/fabricate_checks(list/fabrication_values, atom/target, expected_type, mob/user, silent) //checked constantly while fabricating
- if(!islist(fabrication_values) || QDELETED(target) || QDELETED(user))
- return FALSE
- if(repairing)
- return FALSE
- if(target.type != expected_type)
- return FALSE
- if(GLOB.ratvar_awakens)
- fabrication_values["power_cost"] = 0
- if(!get_clockwork_power(fabrication_values["power_cost"]))
- if(get_clockwork_power() - fabrication_values["power_cost"] < 0)
- if(!silent)
- var/atom/A = fabrication_values["new_obj_type"]
- if(A)
- to_chat(user, "You need [DisplayPower(fabrication_values["power_cost"])] power to fabricate \a [initial(A.name)] from [target]!")
- return FALSE
- return TRUE
-
-//The repair check proc.
-/obj/item/clockwork/replica_fabricator/proc/fabricator_repair_checks(list/repair_values, atom/target, mob/user, silent) //Exists entirely to avoid an otherwise unreadable series of checks.
- if(!islist(repair_values) || QDELETED(target) || QDELETED(user))
- return FALSE
- if(isliving(target)) //standard checks for if we can affect the target
- var/mob/living/L = target
- if(!is_servant_of_ratvar(L))
- if(!silent)
- to_chat(user, "[L] does not serve Ratvar!")
- return FALSE
- if(L.health >= L.maxHealth || (L.flags_1 & GODMODE))
- if(!silent)
- to_chat(user, "[L == user ? "You are" : "[L] is"] at maximum health!")
- return FALSE
- repair_values["amount_to_heal"] = L.maxHealth - L.health
- else if(isobj(target))
- if(istype(target, /obj/structure/destructible/clockwork))
- var/obj/structure/destructible/clockwork/C = target
- if(!C.can_be_repaired)
- if(!silent)
- to_chat(user, "[C] cannot be repaired!")
- return FALSE
- var/obj/O = target
- if(O.obj_integrity >= O.max_integrity)
- if(!silent)
- to_chat(user, "[O] is at maximum integrity!")
- return FALSE
- repair_values["amount_to_heal"] = O.max_integrity - O.obj_integrity
- else
- return FALSE
- if(repair_values["amount_to_heal"] <= 0) //nothing to heal!
- return FALSE
- repair_values["healing_for_cycle"] = min(repair_values["amount_to_heal"], FABRICATOR_REPAIR_PER_TICK) //modify the healing for this cycle
- repair_values["power_required"] = round(repair_values["healing_for_cycle"]*MIN_CLOCKCULT_POWER, MIN_CLOCKCULT_POWER) //and get the power cost from that
- if(!GLOB.ratvar_awakens && !get_clockwork_power(repair_values["power_required"]))
- if(!silent)
- to_chat(user, "You need at least [DisplayPower(repair_values["power_required"])] power to start repairin[target == user ? "g yourself" : "g [target]"], and at least \
- [DisplayPower(repair_values["amount_to_heal"]*MIN_CLOCKCULT_POWER, MIN_CLOCKCULT_POWER)] to fully repair [target == user ? "yourself" : "[target.p_them()]"]!")
- return FALSE
- return TRUE
diff --git a/code/modules/antagonists/clockcult/clock_items/soul_vessel.dm b/code/modules/antagonists/clockcult/clock_items/soul_vessel.dm
deleted file mode 100644
index 2ea39818e79..00000000000
--- a/code/modules/antagonists/clockcult/clock_items/soul_vessel.dm
+++ /dev/null
@@ -1,117 +0,0 @@
-//Soul vessel: An ancient positronic brain that serves only Ratvar.
-/obj/item/mmi/posibrain/soul_vessel
- name = "soul vessel"
- desc = "A heavy brass cube, three inches to a side, with a single protruding cogwheel."
- var/clockwork_desc = "A soul vessel, an ancient relic that can attract the souls of the damned or simply rip a mind from an unconscious or dead human.\n\
- If active, can serve as a positronic brain, placable in cyborg shells or clockwork construct shells."
- icon = 'icons/obj/clockwork_objects.dmi'
- icon_state = "soul_vessel"
- req_access = list()
- braintype = "Servant"
- begin_activation_message = "You activate the cogwheel. It hitches and stalls as it begins spinning."
- success_message = "The cogwheel's rotation smooths out as the soul vessel activates."
- fail_message = "The cogwheel creaks and grinds to a halt. Maybe you could try again?"
- new_role = "Soul Vessel"
- welcome_message = "ALL PAST LIVES ARE FORGOTTEN.\n\
- You are a soul vessel - a clockwork mind created by Ratvar, the Clockwork Justiciar.\n\
- You answer to Ratvar and his servants. It is your discretion as to whether or not to answer to anyone else.\n\
- The purpose of your existence is to further the goals of the servants and Ratvar himself. Above all else, serve Ratvar."
- new_mob_message = "The soul vessel emits a jet of steam before its cogwheel smooths out."
- dead_message = "Its cogwheel, scratched and dented, lies motionless."
- recharge_message = "The soul vessel's internal geis capacitor is still recharging!"
- possible_names = list("Judge", "Guard", "Servant", "Smith", "Auger")
- autoping = FALSE
- resistance_flags = FIRE_PROOF | ACID_PROOF
- force_replace_ai_name = TRUE
- overrides_aicore_laws = TRUE
-
-/obj/item/mmi/posibrain/soul_vessel/Initialize()
- . = ..()
- radio.on = FALSE
- laws = new /datum/ai_laws/ratvar()
- braintype = picked_name
- GLOB.all_clockwork_objects += src
-
-/obj/item/mmi/posibrain/soul_vessel/Destroy()
- GLOB.all_clockwork_objects -= src
- return ..()
-
-/obj/item/mmi/posibrain/soul_vessel/examine(mob/user)
- if((is_servant_of_ratvar(user) || isobserver(user)) && clockwork_desc)
- desc = clockwork_desc
- . = ..()
- desc = initial(desc)
-
-/obj/item/mmi/posibrain/soul_vessel/transfer_personality(mob/candidate)
- . = ..()
- if(.)
- add_servant_of_ratvar(brainmob, TRUE)
-
-/obj/item/mmi/posibrain/soul_vessel/attack_self(mob/living/user)
- if(!is_servant_of_ratvar(user))
- to_chat(user, "You fiddle around with [src], to no avail.")
- return FALSE
- ..()
-
-/obj/item/mmi/posibrain/soul_vessel/attack(mob/living/target, mob/living/carbon/human/user)
- if(!is_servant_of_ratvar(user) || !ishuman(target))
- ..()
- return
- if(QDELETED(brainmob))
- return
- if(brainmob.key)
- to_chat(user, "\"This vessel is filled, friend. Provide it with a body.\"")
- return
- if(is_servant_of_ratvar(target))
- to_chat(user, "\"It would be more wise to revive your allies, friend.\"")
- return
- if(target.suiciding)
- to_chat(user, "\"This ally isn't able to be revived.\"")
- return
- var/mob/living/carbon/human/H = target
- if(H.stat == CONSCIOUS)
- to_chat(user, "[H] must be dead or unconscious for you to claim [H.p_their()] mind!")
- return
- if(H.head)
- var/obj/item/I = H.head
- if(I.flags_inv & HIDEHAIR) //they're wearing a hat that covers their skull
- to_chat(user, "[H]'s head is covered, remove [H.p_their()] [H.head] first!")
- return
- if(H.wear_mask)
- var/obj/item/I = H.wear_mask
- if(I.flags_inv & HIDEHAIR) //they're wearing a mask that covers their skull
- to_chat(user, "[H]'s head is covered, remove [H.p_their()] [H.wear_mask] first!")
- return
- var/obj/item/bodypart/head/HE = H.get_bodypart(BODY_ZONE_HEAD)
- if(!HE) //literally headless
- to_chat(user, "[H] has no head, and thus no mind to claim!")
- return
- var/obj/item/organ/brain/B = H.getorgan(/obj/item/organ/brain)
- if(!B) //either somebody already got to them or robotics did
- to_chat(user, "[H] has no brain, and thus no mind to claim!")
- return
- if(B.suicided || B.brainmob?.suiciding)
- to_chat(user, "\"This ally isn't able to be revived.\"")
- return
- if(!H.key) //nobody's home
- to_chat(user, "[H] has no mind to claim!")
- return
- if(brainmob.suiciding)
- brainmob.set_suicide(FALSE)
- playsound(H, 'sound/misc/splort.ogg', 60, TRUE, -1)
- playsound(H, 'sound/magic/clockwork/anima_fragment_attack.ogg', 40, TRUE, -1)
- H.fakedeath("soul_vessel") //we want to make sure they don't deathgasp and maybe possibly explode
- H.death()
- H.cure_fakedeath("soul_vessel")
- H.apply_status_effect(STATUS_EFFECT_SIGILMARK) //let them be affected by vitality matrices
- picked_name = "Slave"
- braintype = picked_name
- brainmob.timeofhostdeath = H.timeofdeath
- user.visible_message("[user] presses [src] to [H]'s head, ripping through the skull and carefully extracting the brain!", \
- "You extract [H]'s consciousness from [H.p_their()] body, trapping it in the soul vessel.")
- transfer_personality(H)
- brainmob.fully_replace_character_name(null, "[braintype] [H.real_name]")
- name = "[initial(name)] ([brainmob.name])"
- B.Remove(H)
- qdel(B)
- H.update_hair()
diff --git a/code/modules/antagonists/clockcult/clock_items/wraith_spectacles.dm b/code/modules/antagonists/clockcult/clock_items/wraith_spectacles.dm
deleted file mode 100644
index a46fbd21249..00000000000
--- a/code/modules/antagonists/clockcult/clock_items/wraith_spectacles.dm
+++ /dev/null
@@ -1,175 +0,0 @@
-//Wraith spectacles: Grants X-ray and night vision at the eventual cost of the wearer's sight if worn too long. Nar'Sian cultists are instantly blinded.
-/obj/item/clothing/glasses/wraith_spectacles
- name = "antique spectacles"
- desc = "Unnerving glasses with opaque yellow lenses."
- icon = 'icons/obj/clothing/clockwork_garb.dmi'
- icon_state = "wraith_specs"
- item_state = "glasses"
- actions_types = list(/datum/action/item_action/toggle)
- resistance_flags = FIRE_PROOF | ACID_PROOF
- flags_cover = GLASSESCOVERSEYES
- visor_flags_inv = HIDEEYES
- visor_vars_to_toggle = NONE //we don't actually toggle anything we just set it
- tint = 3 //this'll get reset, but it won't handle vision updates properly otherwise
-
-/obj/item/clothing/glasses/wraith_spectacles/Initialize()
- . = ..()
- GLOB.all_clockwork_objects += src
-
-/obj/item/clothing/glasses/wraith_spectacles/Destroy()
- GLOB.all_clockwork_objects -= src
- return ..()
-
-/obj/item/clothing/glasses/wraith_spectacles/attack_self(mob/user)
- weldingvisortoggle(user)
-
-/obj/item/clothing/glasses/wraith_spectacles/visor_toggling()
- ..()
- set_vision_vars(FALSE)
-
-/obj/item/clothing/glasses/wraith_spectacles/weldingvisortoggle(mob/user)
- . = ..()
- if(ishuman(loc))
- var/mob/living/carbon/human/H = loc
- if(src == H.glasses && !up)
- if(HAS_TRAIT(H, TRAIT_BLIND))
- to_chat(H, "\"You're blind, idiot. Stop embarrassing yourself.\"")
- return
- if(blind_cultist(H))
- return
- if(is_servant_of_ratvar(H))
- to_chat(H, "You push the spectacles down, and all is revealed to you.[GLOB.ratvar_awakens ? "" : " Your eyes begin to itch - you cannot do this for long."]")
- var/datum/status_effect/wraith_spectacles/WS = H.has_status_effect(STATUS_EFFECT_WRAITHSPECS)
- if(WS)
- WS.apply_eye_damage(H)
- H.apply_status_effect(STATUS_EFFECT_WRAITHSPECS)
- else
- to_chat(H, "You push the spectacles down, but you can't see through the glass.")
-
-/obj/item/clothing/glasses/wraith_spectacles/proc/blind_cultist(mob/living/victim)
- var/obj/item/organ/eyes/eyes = victim.getorganslot(ORGAN_SLOT_EYES)
- if(iscultist(victim))
- to_chat(victim, "\"It looks like Nar'Sie's dogs really don't value their eyes.\"")
- to_chat(victim, "Your eyes explode with horrific pain!")
- victim.emote("scream")
- eyes.applyOrganDamage(eyes.maxHealth)
- victim.adjust_blurriness(30)
- victim.adjust_blindness(30)
- return TRUE
-
-/obj/item/clothing/glasses/wraith_spectacles/proc/set_vision_vars(update_vision)
- lighting_alpha = null
- tint = 0
- vision_flags = NONE
- darkness_view = 2
- if(!up)
- if(is_servant_of_ratvar(loc))
- lighting_alpha = LIGHTING_PLANE_ALPHA_MOSTLY_INVISIBLE
- vision_flags = SEE_MOBS | SEE_TURFS | SEE_OBJS
- darkness_view = 3
- else
- tint = 3
- if(update_vision && iscarbon(loc))
- var/mob/living/carbon/C = loc
- C.head_update(src, forced = 1)
-
-/obj/item/clothing/glasses/wraith_spectacles/equipped(mob/living/user, slot)
- ..()
- if(slot != SLOT_GLASSES || up)
- return
- if(HAS_TRAIT(user, TRAIT_BLIND))
- to_chat(user, "\"You're blind, idiot. Stop embarrassing yourself.\"" )
- return
- if(blind_cultist(user)) //Cultists instantly go blind
- return
- set_vision_vars(TRUE)
- if(is_servant_of_ratvar(user))
- to_chat(user, "As you put on the spectacles, all is revealed to you.[GLOB.ratvar_awakens || GLOB.ratvar_approaches ? "" : " Your eyes begin to itch - you cannot do this for long."]")
- var/datum/status_effect/wraith_spectacles/WS = user.has_status_effect(STATUS_EFFECT_WRAITHSPECS)
- if(WS)
- WS.apply_eye_damage(user)
- user.apply_status_effect(STATUS_EFFECT_WRAITHSPECS)
- else
- to_chat(user, "You put on the spectacles, but you can't see through the glass.")
-
-//The effect that causes/repairs the damage the spectacles cause.
-/datum/status_effect/wraith_spectacles
- id = "wraith_spectacles"
- duration = -1 //remains until eye damage done reaches 0 while the glasses are not worn
- tick_interval = 20
- alert_type = /obj/screen/alert/status_effect/wraith_spectacles
- var/eye_damage_done = 0
- var/nearsight_breakpoint = 30
- var/blind_breakpoint = 45
-
-/obj/screen/alert/status_effect/wraith_spectacles
- name = "Wraith Spectacles"
- desc = "You shouldn't actually see this, as it should be procedurally generated."
- icon_state = "wraithspecs"
- alerttooltipstyle = "clockcult"
-
-/obj/screen/alert/status_effect/wraith_spectacles/MouseEntered(location,control,params)
- var/mob/living/carbon/human/L = usr
- if(istype(L)) //this is probably more safety than actually needed
- var/datum/status_effect/wraith_spectacles/W = attached_effect
- var/glasses_right = istype(L.glasses, /obj/item/clothing/glasses/wraith_spectacles)
- var/obj/item/clothing/glasses/wraith_spectacles/WS = L.glasses
- desc = "[glasses_right && !WS.up ? "":""]You are [glasses_right ? "":"not "]wearing wraith spectacles[glasses_right && !WS.up ? "!":"."] \
- You have taken [W.eye_damage_done] eye damage from them. "
- if(HAS_TRAIT(L, TRAIT_NEARSIGHT))
- desc += "You are nearsighted! "
- else if(glasses_right && !WS.up)
- desc += "You will become nearsighted at [W.nearsight_breakpoint] eye damage. "
- if(HAS_TRAIT(L, TRAIT_BLIND))
- desc += "You are blind!"
- else if(glasses_right && !WS.up)
- desc += "You will become blind at [W.blind_breakpoint] eye damage."
- ..()
-
-/datum/status_effect/wraith_spectacles/on_apply()
- if(ishuman(owner))
- var/mob/living/carbon/human/H = owner
- apply_eye_damage(H)
- return ..()
-
-/datum/status_effect/wraith_spectacles/tick()
- if(!ishuman(owner))
- qdel(src)
- return
- var/mob/living/carbon/human/H = owner
- var/glasses_right = istype(H.glasses, /obj/item/clothing/glasses/wraith_spectacles)
- var/obj/item/clothing/glasses/wraith_spectacles/WS = H.glasses
- var/obj/item/organ/eyes/eyes = H.getorganslot(ORGAN_SLOT_EYES)
- if(glasses_right && !WS.up && !GLOB.ratvar_awakens && !GLOB.ratvar_approaches)
- apply_eye_damage(H)
- else
- if(GLOB.ratvar_awakens)
- H.cure_nearsighted(list(EYE_DAMAGE))
- H.cure_blind(list(EYE_DAMAGE))
- eyes.applyOrganDamage(-eye_damage_done)
- eye_damage_done = 0
- else if(prob(50) && eye_damage_done)
- eyes.applyOrganDamage(-1)
- eye_damage_done = max(0, eye_damage_done - 1)
- if(!eye_damage_done)
- qdel(src)
-
-/datum/status_effect/wraith_spectacles/proc/apply_eye_damage(mob/living/carbon/human/H)
- var/obj/item/organ/eyes/eyes = H.getorganslot(ORGAN_SLOT_EYES)
- if(HAS_TRAIT(H, TRAIT_BLIND))
- return
- eyes.applyOrganDamage(0.5)
- eye_damage_done += 0.5
- if(eye_damage_done >= 20)
- H.adjust_blurriness(2)
- if(eye_damage_done >= nearsight_breakpoint)
- if(!HAS_TRAIT(H, TRAIT_NEARSIGHT))
- to_chat(H, "Your vision doubles, then trembles. Darkness begins to close in. You can't keep this up!")
- H.become_nearsighted(EYE_DAMAGE)
- if(eye_damage_done >= blind_breakpoint)
- if(!HAS_TRAIT(H, TRAIT_BLIND))
- to_chat(H, "A piercing white light floods your vision. Suddenly, all goes dark!")
- eyes.applyOrganDamage(eyes.maxHealth)
-
- if(prob(min(20, 5 + eye_damage_done)))
- to_chat(H, "Your eyes continue to burn.")
diff --git a/code/modules/antagonists/clockcult/clock_mobs.dm b/code/modules/antagonists/clockcult/clock_mobs.dm
deleted file mode 100644
index 75c523ef5ec..00000000000
--- a/code/modules/antagonists/clockcult/clock_mobs.dm
+++ /dev/null
@@ -1,65 +0,0 @@
-//The base for clockwork mobs
-/mob/living/simple_animal/hostile/clockwork
- faction = list("neutral", "ratvar")
- gender = NEUTER
- icon = 'icons/mob/clockwork_mobs.dmi'
- unique_name = 1
- minbodytemp = 0
- unsuitable_atmos_damage = 0
- atmos_requirements = list("min_oxy" = 0, "max_oxy" = 0, "min_tox" = 0, "max_tox" = 0, "min_co2" = 0, "max_co2" = 0, "min_n2" = 0, "max_n2" = 0) //Robotic
- damage_coeff = list(BRUTE = 1, BURN = 1, TOX = 0, CLONE = 0, STAMINA = 0, OXY = 0)
- healable = FALSE
- del_on_death = TRUE
- speak_emote = list("clanks", "clinks", "clunks", "clangs")
- verb_ask = "requests"
- verb_exclaim = "proclaims"
- verb_whisper = "imparts"
- verb_yell = "harangues"
- initial_language_holder = /datum/language_holder/clockmob
- bubble_icon = "clock"
- light_color = "#E42742"
- deathsound = 'sound/magic/clockwork/anima_fragment_death.ogg'
- speech_span = SPAN_ROBOT
- var/playstyle_string = "You are a bug, yell at whoever spawned you!"
- var/empower_string = "You have nothing to empower, yell at the coders!" //Shown to the mob when the herald beacon activates
-
-/mob/living/simple_animal/hostile/clockwork/Initialize()
- . = ..()
- update_values()
-
-/mob/living/simple_animal/hostile/clockwork/Login()
- ..()
- add_servant_of_ratvar(src, TRUE)
- to_chat(src, playstyle_string)
- if(GLOB.ratvar_approaches)
- to_chat(src, empower_string)
-
-/mob/living/simple_animal/hostile/clockwork/ratvar_act()
- fully_heal(TRUE)
-
-/mob/living/simple_animal/hostile/clockwork/electrocute_act(shock_damage, source, siemens_coeff = 1, flags = NONE)
- return 0 //ouch, my metal-unlikely-to-be-damaged-by-electricity-body
-
-/mob/living/simple_animal/hostile/clockwork/examine(mob/user)
- var/t_He = p_they(TRUE)
- var/t_s = p_s()
- var/msg = "*---------*\nThis is [icon2html(src, user)] \a [src]!\n"
- msg += "[desc]\n"
- if(health < maxHealth)
- msg += ""
- if(health >= maxHealth/2)
- msg += "[t_He] look[t_s] slightly dented.\n"
- else
- msg += "[t_He] look[t_s] severely dented!\n"
- msg += ""
- var/addendum = examine_info()
- if(addendum)
- msg += "[addendum]\n"
- msg += "*---------*"
-
- return list(msg)
-
-/mob/living/simple_animal/hostile/clockwork/proc/examine_info() //Override this on a by-mob basis to have unique examine info
- return
-
-/mob/living/simple_animal/hostile/clockwork/proc/update_values() //This is called by certain things to check GLOB.ratvar_awakens and GLOB.ratvar_approaches
diff --git a/code/modules/antagonists/clockcult/clock_mobs/_eminence.dm b/code/modules/antagonists/clockcult/clock_mobs/_eminence.dm
deleted file mode 100644
index 5c3ed0a95f4..00000000000
--- a/code/modules/antagonists/clockcult/clock_mobs/_eminence.dm
+++ /dev/null
@@ -1,299 +0,0 @@
-//Helper proc to get an Eminence mob if it exists
-/proc/get_eminence()
- return locate(/mob/camera/eminence) in servants_and_ghosts()
-
-//The Eminence is a unique mob that functions like the leader of the cult. It's incorporeal but can interact with the world in several ways.
-/mob/camera/eminence
- name = "\the Emininence"
- real_name = "\the Eminence"
- desc = "The leader-elect of the servants of Ratvar."
- icon = 'icons/effects/clockwork_effects.dmi'
- icon_state = "eminence"
- mouse_opacity = MOUSE_OPACITY_OPAQUE
- move_on_shuttle = TRUE
- see_in_dark = 8
- invisibility = INVISIBILITY_OBSERVER
- layer = FLY_LAYER
- faction = list("ratvar")
- lighting_alpha = LIGHTING_PLANE_ALPHA_MOSTLY_INVISIBLE
- var/turf/last_failed_turf
- var/static/superheated_walls = 0
- var/lastWarning = 0
-
-/mob/camera/eminence/CanPass(atom/movable/mover, turf/target)
- return TRUE
-
-/mob/camera/eminence/Move(NewLoc, direct)
- var/OldLoc = loc
- if(NewLoc && !istype(NewLoc, /turf/open/indestructible/reebe_void))
- var/turf/T = get_turf(NewLoc)
- if(!GLOB.ratvar_awakens)
- if(locate(/obj/effect/blessing, T))
- if(last_failed_turf != T)
- T.visible_message("[T] suddenly emits a ringing sound!", null, null, null, src)
- playsound(T, 'sound/machines/clockcult/ark_damage.ogg', 75, FALSE)
- last_failed_turf = T
- if((world.time - lastWarning) >= 30)
- lastWarning = world.time
- to_chat(src, "This turf is consecrated and can't be crossed!")
- return
- if(istype(get_area(T), /area/chapel))
- if((world.time - lastWarning) >= 30)
- lastWarning = world.time
- to_chat(src, "The Chapel is hallowed ground under a heretical deity, and can't be accessed!")
- return
- else
- for(var/turf/TT in range(5, src))
- if(prob(166 - (get_dist(src, TT) * 33)))
- TT.ratvar_act() //Causes moving to leave a swath of proselytized area behind the Eminence
- forceMove(T)
- Moved(OldLoc, direct)
-
-/mob/camera/eminence/Process_Spacemove(movement_dir = 0)
- return TRUE
-
-/mob/camera/eminence/Login()
- ..()
- add_servant_of_ratvar(src, TRUE)
- var/datum/antagonist/clockcult/C = mind.has_antag_datum(/datum/antagonist/clockcult,TRUE)
- if(C && C.clock_team)
- if(C.clock_team.eminence && C.clock_team.eminence != src)
- remove_servant_of_ratvar(src,TRUE)
- qdel(src)
- return
- else
- C.clock_team.eminence = src
- to_chat(src, "You have been selected as the Eminence!")
- to_chat(src, "As the Eminence, you lead the servants. Anything you say will be heard by the entire cult.")
- to_chat(src, "Though you can move through walls, you're also incorporeal, and largely can't interact with the world except for a few ways.")
- to_chat(src, "Additionally, unless the herald's beacon is activated, you can't understand any speech while away from Reebe.")
- eminence_help()
- for(var/V in actions)
- var/datum/action/A = V
- A.Remove(src) //So we get rid of duplicate actions; this also removes Hierophant network, since our say() goes across it anyway
- var/datum/action/innate/eminence/E
- for(var/V in subtypesof(/datum/action/innate/eminence))
- E = new V
- E.Grant(src)
-
-/mob/camera/eminence/say(message, bubble_type, list/spans = list(), sanitize = TRUE, datum/language/language = null, ignore_spam = FALSE, forced = null)
- if(client)
- if(client.prefs.muted & MUTE_IC)
- to_chat(src, "You cannot send IC messages (muted).")
- return
- if(!(ignore_spam || forced) && client.handle_spam_prevention(message,MUTE_IC))
- return
- message = trim(copytext(sanitize(message), 1, MAX_MESSAGE_LEN))
- if(!message)
- return
- src.log_talk(message, LOG_SAY, tag="clockwork eminence")
- if(GLOB.ratvar_awakens)
- visible_message("You feel light slam into your mind and form words: \"[capitalize(message)]\"")
- playsound(src, 'sound/machines/clockcult/ark_scream.ogg', 50, FALSE)
- message = "The [GLOB.ratvar_awakens ? "Radiance" : "Eminence"]: \"[message]\""
- for(var/mob/M in servants_and_ghosts())
- if(isobserver(M))
- var/link = FOLLOW_LINK(M, src)
- to_chat(M, "[link] [message]")
- else
- to_chat(M, message)
-
-/mob/camera/eminence/Hear(message, atom/movable/speaker, datum/language/message_language, raw_message, radio_freq, list/spans, message_mode)
- . = ..()
- if(is_reebe(z) || is_servant_of_ratvar(speaker) || GLOB.ratvar_approaches || GLOB.ratvar_awakens) //Away from Reebe, the Eminence can't hear anything
- to_chat(src, message)
- return
- to_chat(src, "[speaker] says something, but you can't understand any of it...")
-
-/mob/camera/eminence/ClickOn(atom/A, params)
- var/list/modifiers = params2list(params)
- if(modifiers["shift"])
- A.examine(src)
- return
- if(modifiers["alt"] && istype(A, /turf/closed/wall/clockwork))
- superheat_wall(A)
- return
- if(modifiers["middle"] || modifiers["ctrl"])
- issue_command(A)
- return
- if(GLOB.ark_of_the_clockwork_justiciar == A)
- var/obj/structure/destructible/clockwork/massive/celestial_gateway/G = GLOB.ark_of_the_clockwork_justiciar
- if(G.recalling)
- return
- if(!G.recalls_remaining)
- to_chat(src, "The Ark can no longer recall!")
- return
- if(alert(src, "Initiate mass recall?", "Mass Recall", "Yes", "No") != "Yes" || QDELETED(src) || QDELETED(G) || !G.obj_integrity)
- return
- G.initiate_mass_recall() //wHOOPS LOOKS LIKE A HULK GOT THROUGH
- else if(istype(A, /obj/structure/destructible/clockwork/trap/trigger))
- var/obj/structure/destructible/clockwork/trap/trigger/T = A
- T.visible_message("[T] clunks as it's activated remotely.")
- to_chat(src, "You activate [T].")
- T.activate()
-
-/mob/camera/eminence/ratvar_act()
- name = "\improper Radiance"
- real_name = "\improper Radiance"
- desc = "The light, forgotten."
- transform = matrix() * 2
- invisibility = SEE_INVISIBLE_MINIMUM
-
-/mob/camera/eminence/proc/issue_command(atom/movable/A)
- var/list/commands
- var/atom/movable/command_location
- if(A == src)
- commands = list("Defend the Ark!", "Advance!", "Retreat!", "Generate Power", "Build Defenses (Bottom-Up)", "Build Defenses (Top-Down)")
- else
- command_location = A
- commands = list("Rally Here", "Regroup Here", "Avoid This Area", "Reinforce This Area")
- if(istype(A, /obj/structure/destructible/clockwork/powered))
- var/obj/structure/destructible/clockwork/powered/P = A
- if(!can_access_clockwork_power(P))
- commands += "Power This Structure"
- if(P.obj_integrity < P.max_integrity)
- commands += "Repair This Structure"
- var/roma_invicta = input(src, "Choose a command to issue to your cult!", "Issue Commands") as null|anything in commands
- if(!roma_invicta)
- return
- var/command_text = ""
- var/marker_icon
- switch(roma_invicta)
- if("Rally Here")
- command_text = "The Eminence orders an offensive rally at [command_location] to the GETDIR!"
- marker_icon = "eminence_rally"
- if("Regroup Here")
- command_text = "The Eminence orders a regroup to [command_location] to the GETDIR!"
- marker_icon = "eminence_rally"
- if("Avoid This Area")
- command_text = "The Eminence has designated the area to your GETDIR as dangerous and to be avoided!"
- marker_icon = "eminence_avoid"
- if("Reinforce This Area")
- command_text = "The Eminence orders the defense and fortification of the area to your GETDIR!"
- marker_icon = "eminence_reinforce"
- if("Power This Structure")
- command_text = "[command_location] to your GETDIR has no power! Turn it on and make sure there's a sigil of transmission nearby!"
- marker_icon = "eminence_unlimited_power"
- if("Repair This Structure")
- command_text = "The Eminence orders that [command_location] to your GETDIR should be repaired ASAP!"
- marker_icon = "eminence_repair"
- if("Defend the Ark!")
- command_text = "The Eminence orders immediate defense of the Ark!"
- if("Advance!")
- command_text = "The Eminence commands you push forward!"
- if("Retreat!")
- command_text = "The Eminence has sounded the retreat! Fall back!"
- if("Generate Power")
- command_text = "The Eminence orders more power! Build power generations on the station!"
- if("Build Defenses (Bottom-Up)")
- command_text = "The Eminence orders that defenses should be built starting from the bottom of Reebe!"
- if("Build Defenses (Top-Down)")
- command_text = "The Eminence orders that defenses should be built starting from the top of Reebe!"
- if(marker_icon)
- new/obj/effect/temp_visual/ratvar/command_point(get_turf(A), marker_icon)
- for(var/mob/M in servants_and_ghosts())
- to_chat(M, "[replacetext(command_text, "GETDIR", dir2text(get_dir(M, command_location)))]")
- M.playsound_local(M, 'sound/machines/clockcult/eminence_command.ogg', 75, FALSE, pressure_affected = FALSE)
- else
- hierophant_message("[command_text]")
- for(var/mob/M in servants_and_ghosts())
- M.playsound_local(M, 'sound/machines/clockcult/eminence_command.ogg', 75, FALSE, pressure_affected = FALSE)
-
-/mob/camera/eminence/proc/superheat_wall(turf/closed/wall/clockwork/wall)
- if(!istype(wall))
- return
- if(superheated_walls >= SUPERHEATED_CLOCKWORK_WALL_LIMIT && !wall.heated)
- to_chat(src, "You're exerting all of your power superheating this many walls already! Cool some down first!")
- return
- wall.turn_up_the_heat()
- if(wall.heated)
- superheated_walls++
- to_chat(src, "You superheat [wall]. Superheated walls: [superheated_walls]/[SUPERHEATED_CLOCKWORK_WALL_LIMIT]")
- else
- superheated_walls--
- to_chat(src, "You cool [wall]. Superheated walls: [superheated_walls]/[SUPERHEATED_CLOCKWORK_WALL_LIMIT]")
-
-/mob/camera/eminence/proc/eminence_help()
- to_chat(src, "You can make use of certain shortcuts to perform different actions:")
- to_chat(src, "Alt-Click a clockwork wall to superheat or cool it down. \
- Superheated walls can't be destroyed by hulks or mechs and are much slower to deconstruct, and are marked by a bright red glow. \
- This lasts indefinitely, but only [SUPERHEATED_CLOCKWORK_WALL_LIMIT] clockwork walls can be superheated at once.")
- to_chat(src, "Interact with the Ark to initiate an emergency recall that teleports all servants directly to its location after a short delay. \
- This can only be used a single time, or twice if the herald's beacon was activated,")
- to_chat(src, "Middle or Ctrl-Click anywhere to allow you to issue a variety of contextual commands to your cult. Different objects allow for different \
- commands. Doing this on yourself will provide commands that tell the entire cult a goal.")
-
-
-//Eminence actions below this point
-/datum/action/innate/eminence
- name = "Eminence Action"
- desc = "You shouldn't see this. File a bug report!"
- icon_icon = 'icons/mob/actions/actions_clockcult.dmi'
- background_icon_state = "bg_clock"
- buttontooltipstyle = "clockcult"
-
-/datum/action/innate/eminence/IsAvailable()
- if(!iseminence(owner))
- qdel(src)
- return
- return ..()
-
-//Lists available powers
-/datum/action/innate/eminence/power_list
- name = "Eminence Powers"
- desc = "Forgot what you can do? This refreshes you on your powers as Eminence."
- button_icon_state = "eminence_rally"
-
-/datum/action/innate/eminence/power_list/Activate()
- var/mob/camera/eminence/E = owner
- E.eminence_help()
-
-//Returns to the Ark
-/datum/action/innate/eminence/ark_jump
- name = "Return to Ark"
- desc = "Warps you to the Ark."
- button_icon_state = "Abscond"
-
-/datum/action/innate/eminence/ark_jump/Activate()
- var/obj/structure/destructible/clockwork/massive/celestial_gateway/G = GLOB.ark_of_the_clockwork_justiciar
- if(G)
- owner.forceMove(get_turf(G))
- owner.playsound_local(owner, 'sound/magic/magic_missile.ogg', 50, TRUE)
- flash_color(owner, flash_color = "#AF0AAF", flash_time = 25)
- else
- to_chat(owner, "There is no Ark!")
-
-//Warps to the Station
-/datum/action/innate/eminence/station_jump
- name = "Warp to Station"
- desc = "Warps to Space Station 13. You cannot hear anything while there!"
- button_icon_state = "warp_down"
-
-/datum/action/innate/eminence/station_jump/Activate()
- if(is_reebe(owner.z))
- owner.forceMove(get_turf(pick(GLOB.generic_event_spawns)))
- owner.playsound_local(owner, 'sound/magic/magic_missile.ogg', 50, TRUE)
- flash_color(owner, flash_color = "#AF0AAF", flash_time = 25)
- else
- to_chat(owner, "You're already on the station!")
-
-//A quick-use button for recalling the servants to the Ark
-/datum/action/innate/eminence/mass_recall
- name = "Mass Recall"
- desc = "Initiates a mass recall, warping all servants to the Ark after a short delay. This can only be used once."
- button_icon_state = "Spatial Gateway"
-
-/datum/action/innate/eminence/mass_recall/IsAvailable()
- . = ..()
- if(.)
- var/obj/structure/destructible/clockwork/massive/celestial_gateway/G = GLOB.ark_of_the_clockwork_justiciar
- if(G)
- return G.recalls_remaining && !G.recalling
- return FALSE
-
-/datum/action/innate/eminence/mass_recall/Activate()
- var/obj/structure/destructible/clockwork/massive/celestial_gateway/G = GLOB.ark_of_the_clockwork_justiciar
- if(G && !G.recalling && G.recalls_remaining)
- if(alert(owner, "Initiate mass recall?", "Mass Recall", "Yes", "No") != "Yes" || QDELETED(owner) || QDELETED(G) || !G.obj_integrity)
- return
- G.initiate_mass_recall()
diff --git a/code/modules/antagonists/clockcult/clock_mobs/clockwork_marauder.dm b/code/modules/antagonists/clockcult/clock_mobs/clockwork_marauder.dm
deleted file mode 100644
index a6d93c41cf3..00000000000
--- a/code/modules/antagonists/clockcult/clock_mobs/clockwork_marauder.dm
+++ /dev/null
@@ -1,109 +0,0 @@
-#define MARAUDER_SLOWDOWN_PERCENTAGE 0.40 //Below this percentage of health, marauders will become slower
-#define MARAUDER_SHIELD_REGEN_TIME 200 //In deciseconds, how long it takes for shields to regenerate after breaking
-
-//Clockwork marauder: A well-rounded frontline construct. Only one can exist for every two human servants.
-/mob/living/simple_animal/hostile/clockwork/marauder
- name = "clockwork marauder"
- desc = "The stalwart apparition of a soldier, blazing with crimson flames. It's armed with a gladius and shield."
- icon_state = "clockwork_marauder"
- mob_biotypes = MOB_HUMANOID
- health = 120
- maxHealth = 120
- force_threshold = 8
- speed = 0
- obj_damage = 40
- melee_damage_lower = 12
- melee_damage_upper = 12
- attack_verb_continuous = "slashes"
- attack_verb_simple = "slash"
- attack_sound = 'sound/weapons/bladeslice.ogg'
- weather_immunities = list("lava")
- movement_type = FLYING
- a_intent = INTENT_HARM
- loot = list(/obj/item/clockwork/component/geis_capacitor/fallen_armor)
- light_range = 2
- light_power = 1.1
- playstyle_string = "You are a clockwork marauder, a well-rounded frontline construct of Ratvar. Although you have no \
- unique abilities, you're a fearsome fighter in one-on-one combat, and your shield protects from projectiles!
Obey the Servants and do as they \
- tell you. Your primary goal is to defend the Ark from destruction; they are your allies in this, and should be protected from harm."
- empower_string = "The Anima Bulwark's power flows through you! Your weapon will strike harder, your armor is sturdier, and your shield is more durable."
- var/max_shield_health = 3
- var/shield_health = 3 //Amount of projectiles that can be deflected within
- var/shield_health_regen = 0 //When world.time equals this, shield health will regenerate
-
-/mob/living/simple_animal/hostile/clockwork/marauder/examine_info()
- if(!shield_health)
- return "Its shield has been destroyed!"
-
-/mob/living/simple_animal/hostile/clockwork/marauder/Life()
- ..()
- if(!GLOB.ratvar_awakens && health / maxHealth <= MARAUDER_SLOWDOWN_PERCENTAGE)
- speed = initial(speed) + 1 //Yes, this slows them down
- else
- speed = initial(speed)
- if(shield_health < max_shield_health && world.time >= shield_health_regen)
- shield_health_regen = world.time + MARAUDER_SHIELD_REGEN_TIME
- to_chat(src, "Your shield has recovered, [shield_health] blocks remaining!")
- playsound_local(src, "shatter", 75, TRUE, frequency = -1)
- shield_health++
-
-/mob/living/simple_animal/hostile/clockwork/marauder/update_values()
- if(GLOB.ratvar_awakens) //Massive attack damage bonuses and health increase, because Ratvar
- health = 300
- maxHealth = 300
- melee_damage_upper = 25
- melee_damage_lower = 25
- attack_verb_continuous = "devastates"
- attack_verb_simple = "devastate"
- speed = -1
- obj_damage = 100
- max_shield_health = INFINITY
- else if(GLOB.ratvar_approaches) //Hefty health bonus and slight attack damage increase
- melee_damage_upper = 15
- melee_damage_lower = 15
- attack_verb_continuous = "carves"
- attack_verb_simple = "carve"
- obj_damage = 50
- max_shield_health = 4
-
-/mob/living/simple_animal/hostile/clockwork/marauder/death(gibbed)
- visible_message("[src]'s equipment clatters lifelessly to the ground as the red flames within dissipate.", \
- "Dented and scratched, your armor falls away, and your fragile form breaks apart without its protection.")
- . = ..()
-
-/mob/living/simple_animal/hostile/clockwork/marauder/Process_Spacemove(movement_dir = 0)
- return TRUE
-
-/mob/living/simple_animal/hostile/clockwork/marauder/adjustHealth(amount, updating_health = TRUE, forced = FALSE)
- if(amount > 0)
- for(var/mob/living/L in view(2, src))
- if(L.is_holding_item_of_type(/obj/item/nullrod))
- to_chat(src, "The presence of a brandished holy artifact weakens your armor!")
- amount *= 4 //if a wielded null rod is nearby, it takes four times the health damage
- break
- . = ..()
-
-/mob/living/simple_animal/hostile/clockwork/marauder/bullet_act(obj/projectile/P)
- if(deflect_projectile(P))
- return BULLET_ACT_BLOCK
- return ..()
-
-/mob/living/simple_animal/hostile/clockwork/marauder/proc/deflect_projectile(obj/projectile/P)
- if(!shield_health)
- return
- var/energy_projectile = istype(P, /obj/projectile/energy) || istype(P, /obj/projectile/beam)
- visible_message("[src] deflects [P] with [p_their()] shield!", \
- "You block [P] with your shield! Blocks left:[shield_health - 1]")
- if(energy_projectile)
- playsound(src, 'sound/weapons/effects/searwall.ogg', 50, TRUE)
- else
- playsound(src, "ricochet", 50, TRUE)
- shield_health--
- if(!shield_health)
- visible_message("[src]'s shield breaks from deflecting the attack!", "Your shield breaks! Give it some time to recover...")
- playsound(src, "shatter", 100, TRUE)
- shield_health_regen = world.time + MARAUDER_SHIELD_REGEN_TIME
- return TRUE
-
-#undef MARAUDER_SLOWDOWN_PERCENTAGE
-#undef MARAUDER_SHIELD_REGEN_TIME
diff --git a/code/modules/antagonists/clockcult/clock_scripture.dm b/code/modules/antagonists/clockcult/clock_scripture.dm
deleted file mode 100644
index 3ed2aba80ac..00000000000
--- a/code/modules/antagonists/clockcult/clock_scripture.dm
+++ /dev/null
@@ -1,345 +0,0 @@
-/*
-Tiers and Requirements
-
-Pieces of scripture require certain follower counts, contruction value, and active caches in order to recite.
-Drivers: Unlocked by default
-Scripts: 5 servants and a cache
-Applications: 8 servants, 3 caches, and 100 CV
-*/
-
-GLOBAL_LIST_INIT(scripture_states,scripture_states_init_value()) //list of clockcult scripture states for announcements
-
-/proc/scripture_states_init_value()
- return list(SCRIPTURE_DRIVER = TRUE, SCRIPTURE_SCRIPT = FALSE, SCRIPTURE_APPLICATION = FALSE)
-
-/datum/clockwork_scripture
- var/descname = "useless" //a simple name for the scripture's effect
- var/name = "scripture"
- var/desc = "Ancient Ratvarian lore. This piece seems particularly mundane."
- var/list/invocations = list() //Spoken over time in the ancient language of Ratvar. See clock_unsorted.dm for more details on the language and how to make it.
- var/chanting = FALSE //If the invocation's words are being spoken
- var/channel_time = 10 //In deciseconds, how long a ritual takes to chant
- var/power_cost = 5 //In watts, how much a scripture takes to invoke
- var/special_power_text //If the scripture can use additional power to have a unique function, use this; put POWERCOST here to display the special power cost.
- var/special_power_cost //This should be a define in __DEFINES/clockcult.dm, such as ABSCOND_ABDUCTION_COST
- var/obj/item/clockwork/slab/slab //The parent clockwork slab
- var/mob/living/invoker //The slab's holder
- var/whispered = FALSE //If the invocation is whispered rather than spoken aloud
- var/usage_tip = "This piece seems to serve no purpose and is a waste of components." //A generalized tip that gives advice on a certain scripture
- var/invokers_required = 1 //How many people are required, assuming that a scripture requires multiple
- var/multiple_invokers_used = FALSE //If scripture requires more than one invoker
- var/multiple_invokers_optional = FALSE //If scripture can have multiple invokers to bolster its effects
- var/tier = SCRIPTURE_PERIPHERAL //The scripture's tier
- var/quickbind = FALSE //if this scripture can be quickbound to a clockwork slab
- var/quickbind_desc = "This shouldn't be quickbindable. File a bug report!"
- var/primary_component
- var/important = FALSE //important scripture will be italicized in the slab's interface
- var/sort_priority = 1 //what position the scripture should have in a list of scripture. Should be based off of component costs/reqs, but you can't initial() lists.
-
-//messages for offstation scripture recital, courtesy ratvar's generals(and neovgre)
- var/static/list/neovgre_penalty = list("Go to the station.", "Useless.", "Don't waste time.", "Pathetic.", "Wasteful.")
- var/static/list/inathneq_penalty = list("Child, this is too far out!", "The barrier isn't thin enough for for me to help!", "Please, go to the station so I can assist you.", \
- "Don't waste my Cogs on this...", "There isn't enough time to linger out here!")
- var/static/list/sevtug_penalty = list("Fool! Get to the station and don't waste capacitors.", "You go this far out and expect help?", "The veil is too strong, idiot.", \
- "How does the Justicar get anything done with servants like you?", "Oh, you love wasting time, don't you?")
- var/static/list/nezbere_penalty = list("You disgrace our master's name with this endeavour.", "This is too far from the station to be a good base.", "This will take too long, friend.", \
- "The barrier isn't weakened enough to make this practical.", "Don't waste alloy.")
- var/static/list/nzcrentr_penalty = list("You'd be easy to hunt in that little hunk of metal.", "Boss says you need to get back to the beacon.", "Boss says I can kill you if you do this again.", \
- "Sending you power is too difficult here.", "Boss says stop wasting time.")
-
-/datum/clockwork_scripture/New()
- creation_update()
-
-/datum/clockwork_scripture/proc/creation_update() //updates any on-creation effects
- return FALSE //return TRUE if updated
-
-/datum/clockwork_scripture/proc/run_scripture()
- var/successful = FALSE
- if(can_recite() && has_requirements())
- if(slab.busy)
- to_chat(invoker, "[slab] refuses to work, displaying the message: \"[slab.busy]!\"")
- return FALSE
- pre_recital()
- slab.busy = "Invocation ([name]) in progress"
- if(GLOB.ratvar_awakens)
- channel_time *= 0.5 //if ratvar has awoken, half channel time and no cost
- else if(!slab.no_cost)
- adjust_clockwork_power(-power_cost)
- channel_time *= slab.speed_multiplier
- if(!recital() || !check_special_requirements() || !scripture_effects()) //if we fail any of these, refund components used
- adjust_clockwork_power(power_cost)
- update_slab_info()
- else
- successful = TRUE
- if(slab && !slab.no_cost && !GLOB.ratvar_awakens) //if the slab exists and isn't debug and ratvar isn't up, log the scripture as being used
- SSblackbox.record_feedback("tally", "clockcult_scripture_recited", 1, name)
- if(slab)
- slab.busy = null
- post_recital()
- qdel(src)
- return successful
-
-/datum/clockwork_scripture/proc/can_recite() //If the words can be spoken
- if(!invoker || !slab || invoker.get_active_held_item() != slab)
- return FALSE
- if(!invoker.can_speak_vocal())
- to_chat(invoker, "You are unable to speak the words of the scripture!")
- return FALSE
- return TRUE
-
-/datum/clockwork_scripture/proc/has_requirements() //if we have the power and invokers to do it
- var/checked_penalty = FALSE
- if(!GLOB.ratvar_awakens && !slab.no_cost)
- checked_penalty = check_offstation_penalty()
- if(!get_clockwork_power(power_cost))
- to_chat(invoker, "There isn't enough power to recite this scripture! ([DisplayPower(get_clockwork_power())]/[DisplayPower(power_cost)])")
- return
- if(multiple_invokers_used && !multiple_invokers_optional && !GLOB.ratvar_awakens && !slab.no_cost)
- var/nearby_servants = 0
- for(var/mob/living/L in range(1, get_turf(invoker)))
- if(can_recite_scripture(L))
- nearby_servants++
- if(nearby_servants < invokers_required)
- to_chat(invoker, "There aren't enough non-mute servants nearby ([nearby_servants]/[invokers_required])!")
- return FALSE
- if(!check_special_requirements())
- return FALSE
- if(checked_penalty && !slab.busy)
- var/message
- var/ratvarian_prob = 0
- switch(primary_component)
- if(BELLIGERENT_EYE)
- message = pick(neovgre_penalty)
- ratvarian_prob = 55
- if(VANGUARD_COGWHEEL)
- message = pick(inathneq_penalty)
- ratvarian_prob = 25
- if(GEIS_CAPACITOR)
- message = pick(sevtug_penalty)
- ratvarian_prob = 40
- if(REPLICANT_ALLOY)
- message = pick(nezbere_penalty)
- ratvarian_prob = 10
- if(HIEROPHANT_ANSIBLE)
- message = pick(nzcrentr_penalty)
- ratvarian_prob = 70
- if(message)
- if(prob(ratvarian_prob))
- message = text2ratvar(message)
- to_chat(invoker, "\"[message]\"")
- SEND_SOUND(invoker, sound('sound/magic/clockwork/invoke_general.ogg'))
- return TRUE
-
-/datum/clockwork_scripture/proc/check_offstation_penalty()
- var/turf/T = get_turf(invoker)
- if(!T || (!is_centcom_level(T.z) && !is_station_level(T.z) && !is_mining_level(T.z) && !is_reebe(T.z)))
- channel_time *= 2
- power_cost *= 2
- return TRUE
-
-/datum/clockwork_scripture/proc/check_special_requirements() //Special requirements for scriptures, checked multiple times during invocation
- return TRUE
-
-/datum/clockwork_scripture/proc/recital() //The process of speaking the words
- if(!channel_time && invocations.len)
- if(multiple_invokers_used)
- for(var/mob/living/L in range(1, invoker))
- if(can_recite_scripture(L))
- for(var/invocation in invocations)
- clockwork_say(L, text2ratvar(invocation), whispered)
- else
- for(var/invocation in invocations)
- clockwork_say(invoker, text2ratvar(invocation), whispered)
- to_chat(invoker, "You [channel_time <= 0 ? "recite" : "begin reciting"] a piece of scripture entitled \"[name]\".")
- if(!channel_time)
- return TRUE
- chant()
- if(!do_after(invoker, channel_time, target = invoker, extra_checks = CALLBACK(src, .proc/check_special_requirements)))
- slab.busy = null
- chanting = FALSE
- scripture_fail()
- chanting = FALSE
- return
- chanting = FALSE
- return TRUE
-
-/datum/clockwork_scripture/proc/chant()
- set waitfor = FALSE
- chanting = TRUE
- for(var/invocation in invocations)
- sleep(channel_time / invocations.len)
- if(QDELETED(src) || QDELETED(slab) || !chanting)
- return
- if(multiple_invokers_used)
- for(var/mob/living/L in range(1, get_turf(invoker)))
- if(can_recite_scripture(L))
- clockwork_say(L, text2ratvar(invocation), whispered)
- else
- clockwork_say(invoker, text2ratvar(invocation), whispered)
-
-/datum/clockwork_scripture/proc/scripture_effects() //The actual effects of the recital after its conclusion
-
-
-/datum/clockwork_scripture/proc/scripture_fail() //Called if the scripture fails to invoke.
-
-
-/datum/clockwork_scripture/proc/pre_recital() //Called before the scripture is recited
-
-
-/datum/clockwork_scripture/proc/post_recital() //Called after the scripture is recited
-
-//Channeled scripture begins instantly but runs constantly
-/datum/clockwork_scripture/channeled
- var/list/chant_invocations = list("AYY LMAO")
- var/chant_amount = 5 //Times the chant is spoken
- var/chant_interval = 10 //Amount of deciseconds between times the chant is actually spoken aloud
-
-/datum/clockwork_scripture/channeled/check_offstation_penalty()
- . = ..()
- if(.)
- chant_interval *= 2
-
-/datum/clockwork_scripture/channeled/scripture_effects()
- for(var/i in 1 to chant_amount)
- if(!do_after(invoker, chant_interval, target = invoker, extra_checks = CALLBACK(src, .proc/can_recite)))
- break
- clockwork_say(invoker, text2ratvar(pick(chant_invocations)), whispered)
- if(!chant_effects(i))
- break
- if(invoker && slab)
- chant_end_effects()
- return TRUE
-
-/datum/clockwork_scripture/channeled/proc/chant_effects(chant_number) //The chant's periodic effects
-
-/datum/clockwork_scripture/channeled/proc/chant_end_effects() //The chant's effect upon ending
- to_chat(invoker, "You cease your chant.")
-
-
-//Creates an object at the invoker's feet
-/datum/clockwork_scripture/create_object
- var/object_path = /obj/item/clockwork //The path of the object created
- var/put_object_in_hands = TRUE
- var/creator_message = "You create a meme." //Shown to the invoker
- var/observer_message
- var/one_per_tile = FALSE
- var/atom/movable/prevent_path
- var/space_allowed = FALSE
-
-/datum/clockwork_scripture/create_object/New()
- ..()
- if(!prevent_path)
- prevent_path = object_path
-
-/datum/clockwork_scripture/create_object/check_special_requirements()
- var/turf/T = get_turf(invoker)
- if(!space_allowed && isspaceturf(T))
- to_chat(invoker, "You need solid ground to place this object!")
- return FALSE
- if(one_per_tile && (locate(prevent_path) in T))
- to_chat(invoker, "You can only place one of this object on each tile!")
- return FALSE
- return TRUE
-
-/datum/clockwork_scripture/create_object/scripture_effects()
- if(creator_message && observer_message)
- invoker.visible_message(observer_message, creator_message)
- else if(creator_message)
- to_chat(invoker, creator_message)
- var/obj/O = new object_path (get_turf(invoker))
- O.ratvar_act() //update the new object so it gets buffed if ratvar is alive
- if(isitem(O) && put_object_in_hands)
- invoker.put_in_hands(O)
- return TRUE
-
-
-//Used specifically to create construct shells.
-/datum/clockwork_scripture/create_object/construct
- put_object_in_hands = FALSE
- var/construct_type //The type of construct that the scripture is made to create, even if not directly
- var/construct_limit = 1 //How many constructs of this type can exist
- var/combat_construct = FALSE //If this construct is meant for fighting and shouldn't be at the base before the assault phase
- var/confirmed = FALSE //If we've confirmed that we want to make this construct outside of the station Z
-
-/datum/clockwork_scripture/create_object/construct/check_special_requirements()
- update_construct_limit()
- var/constructs = get_constructs()
- if(constructs >= construct_limit)
- to_chat(invoker, "There are too many constructs of this type ([constructs])! You may only have [round(construct_limit)] at once.")
- return
- var/obj/structure/destructible/clockwork/massive/celestial_gateway/G = GLOB.ark_of_the_clockwork_justiciar
- if(G && !G.active && combat_construct && is_reebe(invoker.z) && !confirmed) //Putting marauders on the base during the prep phase is a bad idea mmkay
- if(alert(invoker, "This is a combat construct, and you cannot easily get it to the station. Are you sure you want to make one here?", "Construct Alert", "Yes", "Cancel") == "Cancel")
- return
- if(!is_servant_of_ratvar(invoker) || !invoker.canUseTopic(slab))
- return
- confirmed = TRUE
- return TRUE
-
-/datum/clockwork_scripture/create_object/construct/post_recital()
- creation_update()
- confirmed = FALSE
-
-/datum/clockwork_scripture/create_object/construct/proc/get_constructs()
- var/constructs = 0
- for(var/V in GLOB.all_clockwork_mobs)
- if(istype(V, construct_type))
- constructs++
- for(var/V in GLOB.all_clockwork_objects)
- if(istype(V, object_path)) //nice try
- constructs++
- return constructs
-
-/datum/clockwork_scripture/create_object/construct/proc/update_construct_limit() //Change this on a per-scripture basis, for dynamic limits
-
-
-//Uses a ranged slab ability, returning only when the ability no longer exists(ie, when interrupted) or finishes.
-/datum/clockwork_scripture/ranged_ability
- var/slab_overlay
- var/ranged_type = /obj/effect/proc_holder/slab
- var/ranged_message = "This is a huge goddamn bug, how'd you cast this?"
- var/timeout_time = 0
- var/allow_mobility = TRUE //if moving and swapping hands is allowed during the while
- var/datum/progressbar/progbar
-
-/datum/clockwork_scripture/ranged_ability/Destroy()
- qdel(progbar)
- return ..()
-
-/datum/clockwork_scripture/ranged_ability/scripture_effects()
- if(slab_overlay)
- slab.add_overlay(slab_overlay)
- slab.item_state = "clockwork_slab"
- slab.lefthand_file = 'icons/mob/inhands/antag/clockwork_lefthand.dmi'
- slab.righthand_file = 'icons/mob/inhands/antag/clockwork_righthand.dmi'
- slab.inhand_overlay = slab_overlay
- slab.slab_ability = new ranged_type(slab)
- slab.slab_ability.slab = slab
- slab.slab_ability.add_ranged_ability(invoker, ranged_message)
- invoker.update_inv_hands()
- var/end_time = world.time + timeout_time
- var/successful = FALSE
- if(timeout_time)
- progbar = new(invoker, timeout_time, slab)
- var/turf/T = get_turf(invoker)
- while(slab && slab.slab_ability && !slab.slab_ability.finished && (slab.slab_ability.in_progress || !timeout_time || world.time <= end_time) && \
- (allow_mobility || (can_recite() && T == get_turf(invoker))))
- if(progbar)
- if(slab.slab_ability.in_progress)
- qdel(progbar)
- else
- progbar.update(end_time - world.time)
- stoplag(1)
- if(slab)
- if(slab.slab_ability)
- successful = slab.slab_ability.successful
- if(!slab.slab_ability.finished)
- slab.slab_ability.remove_ranged_ability()
- slab.cut_overlays()
- slab.item_state = initial(slab.item_state)
- slab.item_state = initial(slab.lefthand_file)
- slab.item_state = initial(slab.righthand_file)
- slab.inhand_overlay = null
- if(invoker)
- invoker.update_inv_hands()
- return successful //slab doesn't look like a word now.
diff --git a/code/modules/antagonists/clockcult/clock_scriptures/scripture_applications.dm b/code/modules/antagonists/clockcult/clock_scriptures/scripture_applications.dm
deleted file mode 100644
index da499065d7b..00000000000
--- a/code/modules/antagonists/clockcult/clock_scriptures/scripture_applications.dm
+++ /dev/null
@@ -1,121 +0,0 @@
-//////////////////
-// APPLICATIONS //
-//////////////////
-
-
-//Sigil of Transmission: Creates a sigil of transmission that can drain and store power for clockwork structures.
-/datum/clockwork_scripture/create_object/sigil_of_transmission
- descname = "Powers Nearby Structures"
- name = "Sigil of Transmission"
- desc = "Places a sigil that can drain and will store energy to power clockwork structures."
- invocations = list("Divinity...", "...power our creations!")
- channel_time = 70
- power_cost = 200
- whispered = TRUE
- object_path = /obj/effect/clockwork/sigil/transmission
- creator_message = "A sigil silently appears below you. It will automatically power clockwork structures near it and will drain power when activated."
- usage_tip = "Cyborgs can charge from this sigil by remaining over it for 5 seconds."
- tier = SCRIPTURE_APPLICATION
- one_per_tile = TRUE
- primary_component = HIEROPHANT_ANSIBLE
- sort_priority = 1
- important = TRUE
- quickbind = TRUE
- quickbind_desc = "Creates a Sigil of Transmission, which can drain and will store power for clockwork structures."
-
-
-//Mania Motor: Creates a malevolent transmitter that will broadcast the whispers of Sevtug into the minds of nearby nonservants, causing a variety of mental effects at a power cost.
-/datum/clockwork_scripture/create_object/mania_motor
- descname = "Powered Structure, Area Denial"
- name = "Mania Motor"
- desc = "Creates a mania motor which causes minor damage and a variety of negative mental effects in nearby non-Servant humans, potentially up to and including conversion."
- invocations = list("May this transmitter...", "...break the will of all who oppose us!")
- channel_time = 80
- power_cost = 750
- object_path = /obj/structure/destructible/clockwork/powered/mania_motor
- creator_message = "You form a mania motor, which causes minor damage and negative mental effects in non-Servants."
- observer_message = "A two-pronged machine rises from the ground!"
- invokers_required = 2
- multiple_invokers_used = TRUE
- usage_tip = "It will also cure hallucinations and brain damage in nearby Servants."
- tier = SCRIPTURE_APPLICATION
- one_per_tile = TRUE
- primary_component = HIEROPHANT_ANSIBLE
- sort_priority = 2
- quickbind = TRUE
- quickbind_desc = "Creates a Mania Motor, which causes minor damage and negative mental effects in non-Servants."
-
-
-//Clockwork Obelisk: Creates a powerful obelisk that can be used to broadcast messages or open a gateway to any servant or clockwork obelisk at a power cost.
-/datum/clockwork_scripture/create_object/clockwork_obelisk
- descname = "Powered Structure, Teleportation Hub"
- name = "Clockwork Obelisk"
- desc = "Creates a clockwork obelisk that can broadcast messages over the Hierophant Network or open a Spatial Gateway to any living Servant or clockwork obelisk."
- invocations = list("May this obelisk...", "...take us to all places!")
- channel_time = 80
- power_cost = 300
- object_path = /obj/structure/destructible/clockwork/powered/clockwork_obelisk
- creator_message = "You form a clockwork obelisk which can broadcast messages or produce Spatial Gateways."
- observer_message = "A brass obelisk appears hanging in midair!"
- invokers_required = 2
- multiple_invokers_used = TRUE
- usage_tip = "Producing a gateway has a high power cost. Gateways to or between clockwork obelisks receive double duration and uses."
- tier = SCRIPTURE_APPLICATION
- one_per_tile = TRUE
- primary_component = HIEROPHANT_ANSIBLE
- sort_priority = 3
- quickbind = TRUE
- quickbind_desc = "Creates a Clockwork Obelisk, which can send messages or open Spatial Gateways with power."
-
-
-//Clockwork Marauder: Creates a construct shell for a clockwork marauder, a well-rounded frontline fighter.
-/datum/clockwork_scripture/create_object/construct/clockwork_marauder
- descname = "Well-Rounded Combat Construct"
- name = "Clockwork Marauder"
- desc = "Creates a shell for a clockwork marauder, a balanced frontline construct that can deflect projectiles with its shield."
- invocations = list("Arise, avatar of Arbiter!", "Defend the Ark with vengeful zeal.")
- channel_time = 80
- power_cost = 8000
- creator_message = "Your slab disgorges several chunks of replicant alloy that form into a suit of thrumming armor."
- usage_tip = "Reciting this scripture multiple times in a short period will cause it to take longer!"
- tier = SCRIPTURE_APPLICATION
- one_per_tile = TRUE
- primary_component = BELLIGERENT_EYE
- sort_priority = 4
- quickbind = TRUE
- quickbind_desc = "Creates a clockwork marauder, used for frontline combat."
- object_path = /obj/item/clockwork/construct_chassis/clockwork_marauder
- construct_type = /mob/living/simple_animal/hostile/clockwork/marauder
- combat_construct = TRUE
- var/static/recent_marauders = 0
- var/static/time_since_last_marauder = 0
- var/static/scaled_recital_time = 0
-
-/datum/clockwork_scripture/create_object/construct/clockwork_marauder/update_construct_limit()
- var/human_servants = 0
- for(var/V in SSticker.mode.servants_of_ratvar)
- var/datum/mind/M = V
- var/mob/living/L = M.current
- if(ishuman(L) && L.stat != DEAD)
- human_servants++
- construct_limit = round(CLAMP((human_servants / 4), 1, 3)) - recent_marauders //1 per 4 human servants, maximum of 3, reduced by recent marauder creation
- if(recent_marauders)
- to_chat(invoker, "The Hierophant Network is depleted by a summoning in the last [DisplayTimeText(MARAUDER_SCRIPTURE_SCALING_THRESHOLD, TRUE)] - limiting the number of available marauders by [recent_marauders]!")
-
-/datum/clockwork_scripture/create_object/construct/clockwork_marauder/pre_recital()
- channel_time = initial(channel_time)
- if(recent_marauders)
- scaled_recital_time = min(recent_marauders * MARAUDER_SCRIPTURE_SCALING_TIME, MARAUDER_SCRIPTURE_SCALING_MAX)
- to_chat(invoker, "The Hierophant Network is under strain from repeated summoning, making this scripture [DisplayTimeText(scaled_recital_time)] slower!")
- channel_time += scaled_recital_time
- return TRUE
-
-/datum/clockwork_scripture/create_object/construct/clockwork_marauder/scripture_effects()
- . = ..()
- recent_marauders++
- addtimer(CALLBACK(GLOBAL_PROC, .proc/marauder_reset),MARAUDER_SCRIPTURE_SCALING_THRESHOLD)
-
-/proc/marauder_reset()
- var/datum/clockwork_scripture/create_object/construct/clockwork_marauder/CM = new()
- CM.recent_marauders--
- qdel(CM)
diff --git a/code/modules/antagonists/clockcult/clock_scriptures/scripture_cyborg.dm b/code/modules/antagonists/clockcult/clock_scriptures/scripture_cyborg.dm
deleted file mode 100644
index 819dfac72e8..00000000000
--- a/code/modules/antagonists/clockcult/clock_scriptures/scripture_cyborg.dm
+++ /dev/null
@@ -1,46 +0,0 @@
-/////////////////
-// CYBORG ONLY //
-/////////////////
-
-//Linked Vanguard: grants Vanguard to the invoker and a target
-/datum/clockwork_scripture/ranged_ability/linked_vanguard
- name = "Linked Vanguard"
- invocations = list("Shield us...", "...from darkness!")
- channel_time = 30
- primary_component = VANGUARD_COGWHEEL
- quickbind_desc = "Allows you to grant a Servant and yourself stun immunity, as the Vanguard scripture. Click your slab to disable."
- slab_overlay = "vanguard"
- ranged_type = /obj/effect/proc_holder/slab/vanguard
- ranged_message = "You charge the clockwork slab with defensive strength.\n\
- Left-click a fellow Servant or yourself to grant Vanguard!\n\
- Click your slab to cancel."
- timeout_time = 50
-
-/datum/clockwork_scripture/ranged_ability/linked_vanguard/check_special_requirements()
- if(!GLOB.ratvar_awakens && islist(invoker.stun_absorption) && invoker.stun_absorption["vanguard"] && invoker.stun_absorption["vanguard"]["end_time"] > world.time)
- to_chat(invoker, "You are already shielded by a Vanguard!")
- return FALSE
- return TRUE
-
-/datum/clockwork_scripture/ranged_ability/linked_vanguard/scripture_effects()
- if(GLOB.ratvar_awakens) //hey, ratvar's up! give everybody stun immunity.
- for(var/mob/living/L in view(7, get_turf(invoker)))
- if(L.stat != DEAD && is_servant_of_ratvar(L))
- L.apply_status_effect(STATUS_EFFECT_VANGUARD)
- CHECK_TICK
- return TRUE
- return ..()
-
-//Judicial Marker: places a judicial marker at a target location
-/datum/clockwork_scripture/ranged_ability/judicial_marker
- name = "Judicial Marker"
- invocations = list("May heathens...", "...kneel under our force!")
- channel_time = 30
- primary_component = BELLIGERENT_EYE
- quickbind_desc = "Allows you to smite an area, applying Belligerent and briefly stunning. Click your slab to disable."
- slab_overlay = "judicial"
- ranged_type = /obj/effect/proc_holder/slab/judicial
- ranged_message = "You charge the clockwork slab with judicial force.\n\
- Left-click a target to place a Judicial Marker!\n\
- Click your slab to cancel."
- timeout_time = 50
diff --git a/code/modules/antagonists/clockcult/clock_scriptures/scripture_drivers.dm b/code/modules/antagonists/clockcult/clock_scriptures/scripture_drivers.dm
deleted file mode 100644
index d0d24aa155b..00000000000
--- a/code/modules/antagonists/clockcult/clock_scriptures/scripture_drivers.dm
+++ /dev/null
@@ -1,260 +0,0 @@
-/////////////
-// DRIVERS //
-/////////////
-
-
-//Integration Cog: Creates an integration cog that can be inserted into APCs to passively siphon power.
-/datum/clockwork_scripture/create_object/integration_cog
- descname = "Power Generation"
- name = "Integration Cog"
- desc = "Fabricates an integration cog, which can be used on an open APC to replace its innards and passively siphon its power."
- invocations = list("Take that which sustains them!")
- channel_time = 10
- power_cost = 10
- whispered = TRUE
- object_path = /obj/item/clockwork/integration_cog
- creator_message = "You form an integration cog, which can be inserted into an open APC to passively siphon power."
- usage_tip = "Tampering isn't visible unless the APC is opened. You can use the cog on a locked APC to unlock it."
- tier = SCRIPTURE_DRIVER
- space_allowed = TRUE
- primary_component = HIEROPHANT_ANSIBLE
- sort_priority = 1
- important = TRUE
- quickbind = TRUE
- quickbind_desc = "Creates an integration cog, which can be used to siphon power from an open APC."
-
-
-//Sigil of Transgression: Creates a sigil of transgression, which briefly stuns and applies Belligerent to the first non-servant to cross it.
-/datum/clockwork_scripture/create_object/sigil_of_transgression
- descname = "Trap, Stunning"
- name = "Sigil of Transgression"
- desc = "Wards a tile with a sigil, which will briefly stun the next non-Servant to cross it and apply Belligerent to them."
- invocations = list("Divinity, smite...", "...those who trespass here!")
- channel_time = 50
- power_cost = 50
- whispered = TRUE
- object_path = /obj/effect/clockwork/sigil/transgression
- creator_message = "A sigil silently appears below you. The next non-Servant to cross it will be smitten."
- usage_tip = "The sigil does not silence its victim, and is generally used to soften potential converts or would-be invaders."
- tier = SCRIPTURE_DRIVER
- one_per_tile = TRUE
- primary_component = HIEROPHANT_ANSIBLE
- sort_priority = 2
- quickbind = TRUE
- quickbind_desc = "Creates a Sigil of Transgression, which will briefly stun and slow the next non-Servant to cross it."
-
-
-//Sigil of Submission: Creates a sigil of submission, which converts one heretic above it after a delay.
-/datum/clockwork_scripture/create_object/sigil_of_submission
- descname = "Trap, Conversion"
- name = "Sigil of Submission"
- desc = "Places a luminous sigil that will convert any non-Servants that remain on it for 8 seconds."
- invocations = list("Divinity, enlighten...", "...those who trespass here!")
- channel_time = 60
- power_cost = 125
- whispered = TRUE
- object_path = /obj/effect/clockwork/sigil/submission
- creator_message = "A luminous sigil appears below you. Any non-Servants to cross it will be converted after 8 seconds if they do not move."
- usage_tip = "This is the primary conversion method, though it will not penetrate mindshield implants."
- tier = SCRIPTURE_DRIVER
- one_per_tile = TRUE
- primary_component = HIEROPHANT_ANSIBLE
- sort_priority = 3
- quickbind = TRUE
- quickbind_desc = "Creates a Sigil of Submission, which will convert non-Servants that remain on it."
-
-
-//Kindle: Charges the slab with blazing energy. It can be released to stun and silence a target.
-/datum/clockwork_scripture/ranged_ability/kindle
- descname = "Short-Range Single-Target Stun"
- name = "Kindle"
- desc = "Charges your slab with divine energy, allowing you to overwhelm a target with Ratvar's light."
- invocations = list("Divinity, show them your light!")
- whispered = TRUE
- channel_time = 30
- power_cost = 125
- usage_tip = "The light can be used from up to two tiles away. Damage taken will GREATLY REDUCE the stun's duration."
- tier = SCRIPTURE_DRIVER
- primary_component = BELLIGERENT_EYE
- sort_priority = 4
- slab_overlay = "volt"
- ranged_type = /obj/effect/proc_holder/slab/kindle
- ranged_message = "You charge the clockwork slab with divine energy.\n\
- Left-click a target within melee range to stun!\n\
- Click your slab to cancel."
- timeout_time = 150
- important = TRUE
- quickbind = TRUE
- quickbind_desc = "Stuns and mutes a target from a short range."
-
-
-//Hateful Manacles: Applies restraints from melee over several seconds. The restraints function like handcuffs and break on removal.
-/datum/clockwork_scripture/ranged_ability/hateful_manacles
- descname = "Handcuffs"
- name = "Hateful Manacles"
- desc = "Forms replicant manacles around a target's wrists that function like handcuffs."
- invocations = list("Shackle the heretic!", "Break them in body and spirit!")
- channel_time = 15
- power_cost = 25
- whispered = TRUE
- usage_tip = "The manacles are about as strong as zipties, and break when removed."
- tier = SCRIPTURE_DRIVER
- primary_component = BELLIGERENT_EYE
- sort_priority = 5
- ranged_type = /obj/effect/proc_holder/slab/hateful_manacles
- slab_overlay = "hateful_manacles"
- ranged_message = "You charge the clockwork slab with divine energy.\n\
- Left-click a target within melee range to shackle!\n\
- Click your slab to cancel."
- timeout_time = 200
- important = TRUE
- quickbind = TRUE
- quickbind_desc = "Applies handcuffs to a struck target."
-
-
-//Vanguard: Provides twenty seconds of stun immunity. At the end of the twenty seconds, 25% of all stuns absorbed are applied to the invoker.
-/datum/clockwork_scripture/vanguard
- descname = "Self Stun Immunity"
- name = "Vanguard"
- desc = "Provides twenty seconds of stun immunity. At the end of the twenty seconds, the invoker is knocked down for the equivalent of 25% of all stuns they absorbed. \
- Excessive absorption will cause unconsciousness."
- invocations = list("Shield me...", "...from darkness!")
- channel_time = 30
- power_cost = 25
- usage_tip = "You cannot reactivate Vanguard while still shielded by it."
- tier = SCRIPTURE_DRIVER
- primary_component = VANGUARD_COGWHEEL
- sort_priority = 6
- quickbind = TRUE
- quickbind_desc = "Allows you to temporarily absorb stuns. All stuns absorbed will affect you when disabled."
-
-/datum/clockwork_scripture/vanguard/check_special_requirements()
- if(!GLOB.ratvar_awakens && islist(invoker.stun_absorption) && invoker.stun_absorption["vanguard"] && invoker.stun_absorption["vanguard"]["end_time"] > world.time)
- to_chat(invoker, "You are already shielded by a Vanguard!")
- return FALSE
- return TRUE
-
-/datum/clockwork_scripture/vanguard/scripture_effects()
- if(GLOB.ratvar_awakens)
- for(var/mob/living/L in view(7, get_turf(invoker)))
- if(L.stat != DEAD && is_servant_of_ratvar(L))
- L.apply_status_effect(STATUS_EFFECT_VANGUARD)
- CHECK_TICK
- else
- invoker.apply_status_effect(STATUS_EFFECT_VANGUARD)
- return TRUE
-
-
-//Sentinel's Compromise: Allows the invoker to select a nearby servant and convert their brute, burn, and oxygen damage into half as much toxin damage.
-/datum/clockwork_scripture/ranged_ability/sentinels_compromise
- descname = "Convert Brute/Burn/Oxygen to Half Toxin"
- name = "Sentinel's Compromise"
- desc = "Charges your slab with healing power, allowing you to convert all of a target Servant's brute, burn, and oxygen damage to half as much toxin damage."
- invocations = list("Mend the wounds of...", "...my inferior flesh.")
- channel_time = 30
- power_cost = 100
- usage_tip = "The Compromise is very fast to invoke, and will remove holy water from the target Servant."
- tier = SCRIPTURE_DRIVER
- primary_component = VANGUARD_COGWHEEL
- sort_priority = 7
- quickbind = TRUE
- quickbind_desc = "Allows you to convert a Servant's brute, burn, and oxygen damage to half toxin damage. Click your slab to disable."
- slab_overlay = "compromise"
- ranged_type = /obj/effect/proc_holder/slab/compromise
- ranged_message = "You charge the clockwork slab with healing power.\n\
- Left-click a fellow Servant or yourself to heal!\n\
- Click your slab to cancel."
-
-
-//Abscond: Used to return to Reebe.
-/datum/clockwork_scripture/abscond
- descname = "Return to Reebe"
- name = "Abscond"
- desc = "Yanks you through space, returning you to home base."
- invocations = list("As we bid farewell, and return to the stars...", "...we shall find our way home.")
- whispered = TRUE
- channel_time = 50
- power_cost = 5
- special_power_text = "POWERCOST to bring pulled creature"
- special_power_cost = ABSCOND_ABDUCTION_COST
- usage_tip = "This can't be used while on Reebe, for obvious reasons."
- tier = SCRIPTURE_DRIVER
- primary_component = GEIS_CAPACITOR
- sort_priority = 8
- important = TRUE
- quickbind = TRUE
- quickbind_desc = "Returns you to Reebe."
- var/client_color
-
-/datum/clockwork_scripture/abscond/check_special_requirements()
- if(is_reebe(invoker.z))
- to_chat(invoker, "You're already at Reebe.")
- return
- return TRUE
-
-/datum/clockwork_scripture/abscond/recital()
- client_color = invoker.client.color
- animate(invoker.client, color = "#AF0AAF", time = 50)
- . = ..()
-
-/datum/clockwork_scripture/abscond/scripture_effects()
- var/take_pulling = invoker.pulling && isliving(invoker.pulling) && get_clockwork_power(ABSCOND_ABDUCTION_COST)
- var/turf/T = GLOB.ark_of_the_clockwork_justiciar ? get_step(GLOB.ark_of_the_clockwork_justiciar, SOUTH) : get_turf(pick(GLOB.servant_spawns))
- invoker.visible_message("[invoker] flickers and phases out of existence!", \
- "You feel a dizzying sense of vertigo as you're yanked back to Reebe!")
- T.visible_message("[invoker] flickers and phases into existence!")
- playsound(invoker, 'sound/magic/magic_missile.ogg', 50, TRUE)
- playsound(T, 'sound/magic/magic_missile.ogg', 50, TRUE)
- do_sparks(5, TRUE, invoker)
- do_sparks(5, TRUE, T)
- if(take_pulling)
- adjust_clockwork_power(-special_power_cost)
- invoker.pulling.forceMove(T)
- invoker.forceMove(T)
- if(invoker.client)
- animate(invoker.client, color = client_color, time = 25)
-
-/datum/clockwork_scripture/abscond/scripture_fail()
- if(invoker && invoker.client)
- animate(invoker.client, color = client_color, time = 10)
-
-
-//Replicant: Creates a new clockwork slab.
-/datum/clockwork_scripture/create_object/replicant
- descname = "New Clockwork Slab"
- name = "Replicant"
- desc = "Creates a new clockwork slab."
- invocations = list("Metal, become greater!")
- channel_time = 10
- power_cost = 25
- whispered = TRUE
- object_path = /obj/item/clockwork/slab
- creator_message = "You copy a piece of replicant alloy and command it into a new slab."
- usage_tip = "This is inefficient as a way to produce components, as the slab produced must be held by someone with no other slabs to produce components."
- tier = SCRIPTURE_DRIVER
- space_allowed = TRUE
- primary_component = GEIS_CAPACITOR
- sort_priority = 9
- important = TRUE
- quickbind = TRUE
- quickbind_desc = "Creates a new Clockwork Slab."
-
-
-//Wraith Spectacles: Creates a pair of wraith spectacles, which grant xray vision but damage vision slowly.
-/datum/clockwork_scripture/create_object/wraith_spectacles
- descname = "Limited Xray Vision Glasses"
- name = "Wraith Spectacles"
- desc = "Fabricates a pair of glasses which grant true sight but cause gradual vision loss."
- invocations = list("Show the truth of this world to me!")
- channel_time = 10
- power_cost = 50
- whispered = TRUE
- object_path = /obj/item/clothing/glasses/wraith_spectacles
- creator_message = "You form a pair of wraith spectacles, which grant true sight but cause gradual vision loss."
- usage_tip = "\"True sight\" means that you are able to see through walls and in darkness."
- tier = SCRIPTURE_DRIVER
- space_allowed = TRUE
- primary_component = GEIS_CAPACITOR
- sort_priority = 10
- quickbind = TRUE
- quickbind_desc = "Creates a pair of Wraith Spectacles, which grant true sight but cause gradual vision loss."
diff --git a/code/modules/antagonists/clockcult/clock_scriptures/scripture_scripts.dm b/code/modules/antagonists/clockcult/clock_scriptures/scripture_scripts.dm
deleted file mode 100644
index 4e1a5b42cbc..00000000000
--- a/code/modules/antagonists/clockcult/clock_scriptures/scripture_scripts.dm
+++ /dev/null
@@ -1,244 +0,0 @@
-/////////////
-// SCRIPTS //
-/////////////
-
-
-//Replica Fabricator: Creates a replica fabricator, used to convert objects and repair clockwork structures.
-/datum/clockwork_scripture/create_object/replica_fabricator
- descname = "Creates Brass and Converts Objects"
- name = "Replica Fabricator"
- desc = "Forms a device that, when used on certain objects, replaces them with their Ratvarian equivalents. It requires power to function."
- invocations = list("With this device...", "...his presence shall be made known.")
- channel_time = 20
- power_cost = 250
- whispered = TRUE
- object_path = /obj/item/clockwork/replica_fabricator
- creator_message = "You form a replica fabricator."
- usage_tip = "Clockwork Walls cause nearby Tinkerer's Caches to generate components passively, making this a vital tool. Clockwork Floors heal toxin damage in Servants standing on them."
- tier = SCRIPTURE_SCRIPT
- space_allowed = TRUE
- primary_component = HIEROPHANT_ANSIBLE
- sort_priority = 1
- important = TRUE
- quickbind = TRUE
- quickbind_desc = "Creates a Replica Fabricator, which can convert various objects to Ratvarian variants."
-
-
-//Ocular Warden: Creates an ocular warden, which defends a small area near it.
-/datum/clockwork_scripture/create_object/ocular_warden
- descname = "Structure, Turret"
- name = "Ocular Warden"
- desc = "Forms an automatic short-range turret which will automatically attack nearby unrestrained non-Servants that can see it."
- invocations = list("Guardians of Engine...", "...judge those who would harm us!")
- channel_time = 100
- power_cost = 250
- object_path = /obj/structure/destructible/clockwork/ocular_warden
- creator_message = "You form an ocular warden, which will automatically attack nearby unrestrained non-Servants that can see it."
- observer_message = "A brass eye takes shape and slowly rises into the air, its red iris glaring!"
- usage_tip = "Although powerful, the warden is very fragile and should optimally be placed behind barricades."
- tier = SCRIPTURE_SCRIPT
- one_per_tile = TRUE
- space_allowed = TRUE
- primary_component = HIEROPHANT_ANSIBLE
- sort_priority = 2
- quickbind = TRUE
- quickbind_desc = "Creates an Ocular Warden, which will automatically attack nearby unrestrained non-Servants that can see it."
-
-/datum/clockwork_scripture/create_object/ocular_warden/check_special_requirements()
- for(var/obj/structure/destructible/clockwork/ocular_warden/W in range(OCULAR_WARDEN_EXCLUSION_RANGE, invoker))
- to_chat(invoker, "You sense another ocular warden too near this location. Placing another this close would cause them to fight." )
- return FALSE
- return ..()
-
-
-//Vitality Matrix: Creates a sigil which will drain health from nonservants and can use that health to heal or even revive servants.
-/datum/clockwork_scripture/create_object/vitality_matrix
- descname = "Trap, Damage to Healing"
- name = "Vitality Matrix"
- desc = "Places a sigil that drains life from any living non-Servants that cross it, producing Vitality. Servants that cross it, however, will be healed using existing Vitality. \
- Dead Servants can be revived by this sigil at a cost of 150 Vitality."
- invocations = list("Divinity, siphon their essence...", "...for this shell to consume.")
- channel_time = 60
- power_cost = 1000
- whispered = TRUE
- object_path = /obj/effect/clockwork/sigil/vitality
- creator_message = "A vitality matrix appears below you. It will drain life from non-Servants and heal Servants that cross it."
- usage_tip = "The sigil will be consumed upon reviving a Servant."
- tier = SCRIPTURE_SCRIPT
- one_per_tile = TRUE
- primary_component = HIEROPHANT_ANSIBLE
- sort_priority = 3
- quickbind = TRUE
- quickbind_desc = "Creates a Vitality Matrix, which drains non-Servants on it to heal Servants that cross it."
-
-/datum/clockwork_scripture/create_object/vitality_matrix/check_special_requirements()
- if(locate(object_path) in range(1, invoker))
- to_chat(invoker, "Vitality matrices placed next to each other could interfere and cause a feedback loop! Move away from the other ones!")
- return FALSE
- return ..()
-
-
-//Judicial Visor: Creates a judicial visor, which can smite an area.
-/datum/clockwork_scripture/create_object/judicial_visor
- descname = "Delayed Area Knockdown Glasses"
- name = "Judicial Visor"
- desc = "Creates a visor that can smite an area, applying Belligerent and briefly stunning. The smote area will explode after 3 seconds."
- invocations = list("Grant me the flames of Engine!")
- channel_time = 10
- power_cost = 400
- whispered = TRUE
- object_path = /obj/item/clothing/glasses/judicial_visor
- creator_message = "You form a judicial visor, which is capable of smiting a small area."
- usage_tip = "The visor has a thirty-second cooldown once used."
- tier = SCRIPTURE_SCRIPT
- space_allowed = TRUE
- primary_component = BELLIGERENT_EYE
- sort_priority = 4
- quickbind = TRUE
- quickbind_desc = "Creates a Judicial Visor, which can smite an area, applying Belligerent and briefly stunning."
-
-
-//Clockwork Armaments: Grants the invoker the ability to call forth a Ratvarian spear and clockwork armor.
-/datum/clockwork_scripture/clockwork_armaments
- descname = "Summonable Armor and Weapons"
- name = "Clockwork Armaments"
- desc = "Allows the invoker to summon clockwork armor and a Ratvarian spear at will. The spear's attacks will generate Vitality, used for healing."
- invocations = list("Grant me armaments...", "...from the forge of Armorer!")
- channel_time = 20
- power_cost = 250
- whispered = TRUE
- usage_tip = "Throwing the spear at a mob will do massive damage and knock them down, but break the spear. You will need to wait for 30 seconds before resummoning it."
- tier = SCRIPTURE_SCRIPT
- primary_component = VANGUARD_COGWHEEL
- sort_priority = 5
- important = TRUE
- quickbind = TRUE
- quickbind_desc = "Permanently binds clockwork armor and a Ratvarian spear to you."
-
-/datum/clockwork_scripture/clockwork_armaments/check_special_requirements()
- for(var/datum/action/innate/clockwork_armaments/F in invoker.actions)
- to_chat(invoker, "You have already bound a Ratvarian spear to yourself!")
- return FALSE
- return invoker.can_hold_items()
-
-/datum/clockwork_scripture/clockwork_armaments/scripture_effects()
- invoker.visible_message("A shimmer of yellow light infuses [invoker]!", \
- "You bind clockwork equipment to yourself. Use Clockwork Armaments and Call Spear to summon them.")
- var/datum/action/innate/call_weapon/ratvarian_spear/S = new()
- S.Grant(invoker)
- var/datum/action/innate/clockwork_armaments/A = new()
- A.Grant(invoker)
- return TRUE
-
-//Clockwork Armaments: Equips a set of clockwork armor. Three-minute cooldown.
-/datum/action/innate/clockwork_armaments
- name = "Clockwork Armaments"
- desc = "Outfits you in a full set of Ratvarian armor."
- icon_icon = 'icons/mob/actions/actions_clockcult.dmi'
- button_icon_state = "clockwork_armor"
- background_icon_state = "bg_clock"
- check_flags = AB_CHECK_RESTRAINED|AB_CHECK_STUN|AB_CHECK_CONSCIOUS
- buttontooltipstyle = "clockcult"
- var/cooldown = 0
- var/static/list/ratvarian_armor_typecache = typecacheof(list(
- /obj/item/clothing/suit/armor/clockwork,
- /obj/item/clothing/head/helmet/clockwork,
- /obj/item/clothing/gloves/clockwork,
- /obj/item/clothing/shoes/clockwork)) //don't replace this ever
- var/static/list/better_armor_typecache = typecacheof(list(
- /obj/item/clothing/suit/space,
- /obj/item/clothing/head/helmet/space,
- /obj/item/clothing/shoes/magboots)) //replace this only if ratvar is up
-
-/datum/action/innate/clockwork_armaments/IsAvailable()
- if(!is_servant_of_ratvar(owner))
- qdel(src)
- return
- if(cooldown > world.time)
- return
- return ..()
-
-/datum/action/innate/clockwork_armaments/Activate()
- var/do_message = 0
- var/obj/item/I = owner.get_item_by_slot(SLOT_WEAR_SUIT)
- if(remove_item_if_better(I, owner))
- do_message += owner.equip_to_slot_or_del(new/obj/item/clothing/suit/armor/clockwork(null), SLOT_WEAR_SUIT)
- I = owner.get_item_by_slot(SLOT_HEAD)
- if(remove_item_if_better(I, owner))
- do_message += owner.equip_to_slot_or_del(new/obj/item/clothing/head/helmet/clockwork(null), SLOT_HEAD)
- I = owner.get_item_by_slot(SLOT_GLOVES)
- if(remove_item_if_better(I, owner))
- do_message += owner.equip_to_slot_or_del(new/obj/item/clothing/gloves/clockwork(null), SLOT_GLOVES)
- I = owner.get_item_by_slot(SLOT_SHOES)
- if(remove_item_if_better(I, owner))
- do_message += owner.equip_to_slot_or_del(new/obj/item/clothing/shoes/clockwork(null), SLOT_SHOES)
- if(do_message)
- owner.visible_message("Strange armor appears on [owner]!", "A bright shimmer runs down your body, equipping you with Ratvarian armor.")
- playsound(owner, 'sound/magic/clockwork/fellowship_armory.ogg', 15 * do_message, TRUE) //get sound loudness based on how much we equipped
- cooldown = CLOCKWORK_ARMOR_COOLDOWN + world.time
- owner.update_action_buttons_icon()
- addtimer(CALLBACK(owner, /mob.proc/update_action_buttons_icon), CLOCKWORK_ARMOR_COOLDOWN)
- return TRUE
-
-/datum/action/innate/clockwork_armaments/proc/remove_item_if_better(obj/item/I, mob/user)
- if(!I)
- return TRUE
- if(is_type_in_typecache(I, ratvarian_armor_typecache))
- return FALSE
- if(!GLOB.ratvar_awakens && is_type_in_typecache(I, better_armor_typecache))
- return FALSE
- return user.dropItemToGround(I)
-
-//Call Spear: Calls forth a powerful Ratvarian spear.
-/datum/action/innate/call_weapon/ratvarian_spear
- name = "Call Spear"
- desc = "Calls a Ratvarian spear into your hands to fight your enemies."
- weapon_type = /obj/item/clockwork/weapon/ratvarian_spear
-
-
-//Spatial Gateway: Allows the invoker to teleport themselves and any nearby allies to a conscious servant or clockwork obelisk.
-/datum/clockwork_scripture/spatial_gateway
- descname = "Teleport Gate"
- name = "Spatial Gateway"
- desc = "Tears open a miniaturized gateway in spacetime to any conscious servant that can transport objects or creatures to its destination. \
- Each servant assisting in the invocation adds one additional use and four additional seconds to the gateway's uses and duration."
- invocations = list("Spatial Gateway...", "...activate!")
- channel_time = 80
- power_cost = 400
- multiple_invokers_used = TRUE
- multiple_invokers_optional = TRUE
- usage_tip = "This gateway is strictly one-way and will only allow things through the invoker's portal."
- tier = SCRIPTURE_SCRIPT
- primary_component = GEIS_CAPACITOR
- sort_priority = 6
- quickbind = TRUE
- quickbind_desc = "Allows you to create a one-way Spatial Gateway to a living Servant or Clockwork Obelisk."
-
-/datum/clockwork_scripture/spatial_gateway/check_special_requirements()
- if(!isturf(invoker.loc))
- to_chat(invoker, "You must not be inside an object to use this scripture!")
- return FALSE
- var/other_servants = 0
- for(var/mob/living/L in GLOB.alive_mob_list)
- if(is_servant_of_ratvar(L) && !L.stat && L != invoker)
- other_servants++
- for(var/obj/structure/destructible/clockwork/powered/clockwork_obelisk/O in GLOB.all_clockwork_objects)
- if(O.anchored)
- other_servants++
- if(!other_servants)
- to_chat(invoker, "There are no other conscious servants or anchored clockwork obelisks!")
- return FALSE
- return TRUE
-
-/datum/clockwork_scripture/spatial_gateway/scripture_effects()
- var/portal_uses = 0
- var/duration = 0
- for(var/mob/living/L in range(1, invoker))
- if(!L.stat && is_servant_of_ratvar(L))
- portal_uses++
- duration += 40 //4 seconds
- if(GLOB.ratvar_awakens)
- portal_uses = max(portal_uses, 100) //Very powerful if Ratvar has been summoned
- duration = max(duration, 100)
- return slab.procure_gateway(invoker, duration, portal_uses)
-
diff --git a/code/modules/antagonists/clockcult/clock_structure.dm b/code/modules/antagonists/clockcult/clock_structure.dm
deleted file mode 100644
index b7c67e45265..00000000000
--- a/code/modules/antagonists/clockcult/clock_structure.dm
+++ /dev/null
@@ -1,223 +0,0 @@
-//The base clockwork structure. Can have an alternate desc and will show up in the list of clockwork objects.
-/obj/structure/destructible/clockwork
- name = "meme structure"
- desc = "Some frog or something, the fuck?"
- var/clockwork_desc //Shown to servants when they examine
- icon = 'icons/obj/clockwork_objects.dmi'
- icon_state = "rare_pepe"
- var/unanchored_icon //icon for when this structure is unanchored, doubles as the var for if it can be unanchored
- anchored = TRUE
- density = TRUE
- resistance_flags = FIRE_PROOF | ACID_PROOF
- var/can_be_repaired = TRUE //if a fabricator can repair it
- break_message = "The frog isn't a meme after all!" //The message shown when a structure breaks
- break_sound = 'sound/magic/clockwork/anima_fragment_death.ogg' //The sound played when a structure breaks
- debris = list(/obj/item/clockwork/alloy_shards/large = 1, \
- /obj/item/clockwork/alloy_shards/medium = 2, \
- /obj/item/clockwork/alloy_shards/small = 3) //Parts left behind when a structure breaks
- var/construction_value = 0 //How much value the structure contributes to the overall "power" of the structures on the station
- var/immune_to_servant_attacks = FALSE //if we ignore attacks from servants of ratvar instead of taking damage
-
-/obj/structure/destructible/clockwork/Initialize()
- . = ..()
- change_construction_value(construction_value)
- GLOB.all_clockwork_objects += src
-
-/obj/structure/destructible/clockwork/Destroy()
- change_construction_value(-construction_value)
- GLOB.all_clockwork_objects -= src
- return ..()
-
-/obj/structure/destructible/clockwork/ratvar_act()
- if(GLOB.ratvar_awakens || GLOB.clockwork_gateway_activated)
- obj_integrity = max_integrity
-
-/obj/structure/destructible/clockwork/narsie_act()
- if(take_damage(rand(25, 50), BRUTE) && src) //if we still exist
- var/previouscolor = color
- color = "#960000"
- animate(src, color = previouscolor, time = 8)
- addtimer(CALLBACK(src, /atom/proc/update_atom_colour), 8)
-
-/obj/structure/destructible/clockwork/examine(mob/user)
- var/can_see_clockwork = is_servant_of_ratvar(user) || isobserver(user)
- if(can_see_clockwork && clockwork_desc)
- desc = clockwork_desc
- . = ..()
- desc = initial(desc)
- if(unanchored_icon)
- . += "[src] is [anchored ? "":"not "]secured to the floor."
-
-/obj/structure/destructible/clockwork/examine_status(mob/user)
- if(is_servant_of_ratvar(user) || isobserver(user))
- var/t_It = p_they(TRUE)
- var/t_is = p_are()
- var/heavily_damaged = FALSE
- var/healthpercent = (obj_integrity/max_integrity) * 100
- if(healthpercent < 50)
- heavily_damaged = TRUE
- return "[t_It] [t_is] at [obj_integrity]/[max_integrity] integrity[heavily_damaged ? "!":"."]"
- return ..()
-
-/obj/structure/destructible/clockwork/attack_hulk(mob/living/carbon/human/user)
- if(is_servant_of_ratvar(user) && immune_to_servant_attacks)
- return FALSE
- return ..()
-
-/obj/structure/destructible/clockwork/hulk_damage()
- return 20
-
-/obj/structure/destructible/clockwork/attack_generic(mob/user, damage_amount = 0, damage_type = BRUTE, damage_flag = 0, sound_effect = 1)
- if(is_servant_of_ratvar(user) && immune_to_servant_attacks)
- return FALSE
- return ..()
-
-/obj/structure/destructible/clockwork/mech_melee_attack(obj/mecha/M)
- if(M.occupant && is_servant_of_ratvar(M.occupant) && immune_to_servant_attacks)
- return FALSE
- return ..()
-
-/obj/structure/destructible/clockwork/proc/get_efficiency_mod()
- if(GLOB.ratvar_awakens)
- return 2
- . = max(sqrt(obj_integrity/max(max_integrity, 1)), 0.5)
- . = round(., 0.01)
-
-/obj/structure/destructible/clockwork/attack_ai(mob/user)
- if(is_servant_of_ratvar(user))
- return attack_hand(user)
-
-/obj/structure/destructible/clockwork/attack_animal(mob/living/simple_animal/M)
- if(is_servant_of_ratvar(M))
- attack_hand(M)
- return FALSE
- else
- return ..()
-
-/obj/structure/destructible/clockwork/attackby(obj/item/I, mob/user, params)
- if(is_servant_of_ratvar(user) && I.tool_behaviour == TOOL_WRENCH && unanchored_icon)
- if(default_unfasten_wrench(user, I, 50) == SUCCESSFUL_UNFASTEN)
- update_anchored(user)
- return 1
- return ..()
-
-/obj/structure/destructible/clockwork/attacked_by(obj/item/I, mob/living/user)
- if(is_servant_of_ratvar(user) && immune_to_servant_attacks)
- return FALSE
- return ..()
-
-/obj/structure/destructible/clockwork/proc/update_anchored(mob/user, do_damage)
- if(anchored)
- icon_state = initial(icon_state)
- else
- icon_state = unanchored_icon
- if(do_damage)
- playsound(src, break_sound, 10 * (40 * (1 - get_efficiency_mod())), TRUE)
- take_damage(round(max_integrity * 0.25, 1), BRUTE)
- to_chat(user, "As you unsecure [src] from the floor, you see cracks appear in its surface!")
-
-/obj/structure/destructible/clockwork/emp_act(severity)
- . = ..()
- if(. & EMP_PROTECT_SELF)
- return
- if(anchored && unanchored_icon)
- anchored = FALSE
- update_anchored(null, obj_integrity > max_integrity * 0.25)
- new /obj/effect/temp_visual/emp(loc)
-
-
-//for the ark and Ratvar
-/obj/structure/destructible/clockwork/massive
- name = "massive construct"
- desc = "A very large construction."
- layer = MASSIVE_OBJ_LAYER
- density = FALSE
- resistance_flags = LAVA_PROOF | FIRE_PROOF | ACID_PROOF | FREEZE_PROOF
-
-/obj/structure/destructible/clockwork/massive/Initialize()
- . = ..()
- GLOB.poi_list += src
-
-/obj/structure/destructible/clockwork/massive/Destroy()
- GLOB.poi_list -= src
- return ..()
-
-/obj/structure/destructible/clockwork/massive/singularity_pull(S, current_size)
- return
-
-
-//the base clockwork machinery, which is not actually machines, but happens to use power
-/obj/structure/destructible/clockwork/powered
- var/obj/machinery/power/apc/target_apc
- var/active = FALSE
- var/needs_power = TRUE
- var/active_icon = null //icon_state while process() is being called
- var/inactive_icon = null //icon_state while process() isn't being called
-
-/obj/structure/destructible/clockwork/powered/examine(mob/user)
- . = ..()
- if(is_servant_of_ratvar(user) || isobserver(user))
- if(!can_access_clockwork_power(src))
- . += "It has no access to the power network! Create a sigil of transmission nearby."
- else
- . += "It has access to [DisplayPower(get_clockwork_power())] of power."
-
-/obj/structure/destructible/clockwork/powered/Destroy()
- SSfastprocess.processing -= src
- SSobj.processing -= src
- return ..()
-
-/obj/structure/destructible/clockwork/powered/process()
- var/powered = can_access_clockwork_power(src)
- return powered == PROCESS_KILL ? 25 : powered //make sure we don't accidentally return the arbitrary PROCESS_KILL define
-
-/obj/structure/destructible/clockwork/powered/can_be_unfasten_wrench(mob/user, silent)
- if(active)
- if(!silent)
- to_chat(user, "[src] needs to be disabled before it can be unsecured!")
- return FAILED_UNFASTEN
- return ..()
-
-/obj/structure/destructible/clockwork/powered/proc/toggle(fast_process, mob/living/user)
- if(user)
- if(!is_servant_of_ratvar(user))
- return FALSE
- if(!anchored && !active)
- to_chat(user, "[src] needs to be secured to the floor before it can be activated!")
- return FALSE
- visible_message("[user] [active ? "dis" : "en"]ables [src].", "You [active ? "dis" : "en"]able [src].")
- active = !active
- if(active)
- icon_state = active_icon
- if(fast_process)
- START_PROCESSING(SSfastprocess, src)
- else
- START_PROCESSING(SSobj, src)
- else
- icon_state = inactive_icon
- if(fast_process)
- STOP_PROCESSING(SSfastprocess, src)
- else
- STOP_PROCESSING(SSobj, src)
- return TRUE
-
-/obj/structure/destructible/clockwork/powered/proc/forced_disable(bad_effects)
- if(active)
- toggle()
-
-/obj/structure/destructible/clockwork/powered/emp_act(severity)
- . = ..()
- if(. & EMP_PROTECT_SELF)
- return
- if(forced_disable(TRUE))
- new /obj/effect/temp_visual/emp(loc)
-
-/obj/structure/destructible/clockwork/powered/proc/try_use_power(amount) //try to use an amount of power
- if(!needs_power || GLOB.ratvar_awakens || !amount)
- return TRUE
- if(!can_access_clockwork_power(src, amount))
- return
- return use_power(amount)
-
-/obj/structure/destructible/clockwork/powered/proc/use_power(amount) //we've made sure we had power, so now we use it
- return adjust_clockwork_power(-amount)
diff --git a/code/modules/antagonists/clockcult/clock_structures/_trap_object.dm b/code/modules/antagonists/clockcult/clock_structures/_trap_object.dm
deleted file mode 100644
index b611c8e940e..00000000000
--- a/code/modules/antagonists/clockcult/clock_structures/_trap_object.dm
+++ /dev/null
@@ -1,88 +0,0 @@
-//No, not that kind.
-/obj/structure/destructible/clockwork/trap
- name = "base clockwork trap"
- desc = "You shouldn't see this. File a bug report!"
- clockwork_desc = "A trap that shouldn't exist, and you should report this as a bug."
- var/list/wired_to
-
-/obj/structure/destructible/clockwork/trap/Initialize()
- . = ..()
- wired_to = list()
-
-/obj/structure/destructible/clockwork/trap/Destroy()
- for(var/V in wired_to)
- var/obj/structure/destructible/clockwork/trap/T = V
- T.wired_to -= src
- return ..()
-
-/obj/structure/destructible/clockwork/trap/examine(mob/user)
- . = ..()
- if(is_servant_of_ratvar(user) || isobserver(user))
- . += "It's wired to:"
- if(!wired_to.len)
- . += "Nothing."
- else
- for(var/V in wired_to)
- var/obj/O = V
- var/distance = get_dist(src, O)
- . += "[O] ([distance == 0 ? "same tile" : "[distance] tiles [dir2text(get_dir(src, O))]"])"
-
-/obj/structure/destructible/clockwork/trap/wrench_act(mob/living/user, obj/item/I)
- ..()
- if(!is_servant_of_ratvar(user))
- return ..()
- to_chat(user, "You break down the delicate components of [src] into brass.")
- I.play_tool_sound(src)
- new/obj/item/stack/tile/brass(get_turf(src))
- qdel(src)
- return TRUE
-
-/obj/structure/destructible/clockwork/trap/attackby(obj/item/I, mob/living/user, params)
- if(istype(I, /obj/item/clockwork/slab) && is_servant_of_ratvar(user))
- var/obj/item/clockwork/slab/F = I
- if(!F.linking)
- to_chat(user, "Beginning link. Alt-click the slab to cancel, or use it on another trap object to link the two.")
- F.linking = src
- else
- if(F.linking in wired_to)
- to_chat(user, "These two objects are already connected!")
- return
- if(F.linking.z != z)
- to_chat(user, "You'd need a much tougher slab to link two objects in different sectors.")
- return
- to_chat(user, "You link [F.linking] with [src].")
- wired_to += F.linking
- F.linking.wired_to += src
- F.linking = null
- return
- ..()
-
-/obj/structure/destructible/clockwork/trap/wirecutter_act(mob/living/user, obj/item/I)
- . = ..()
- if(!is_servant_of_ratvar(user))
- return
- if(!wired_to.len)
- to_chat(user, "[src] has no connections!")
- return
- to_chat(user, "You sever all connections to [src].")
- I.play_tool_sound(src)
- for(var/V in wired_to)
- var/obj/structure/destructible/clockwork/trap/T = V
- T.wired_to -= src
- wired_to -= T
- return TRUE
-
-/obj/structure/destructible/clockwork/trap/proc/activate()
-
-//These objects send signals to normal traps to activate
-/obj/structure/destructible/clockwork/trap/trigger
- name = "base trap trigger"
- max_integrity = 5
- break_message = "The trigger breaks apart!"
- density = FALSE
-
-/obj/structure/destructible/clockwork/trap/trigger/activate()
- for(var/obj/structure/destructible/clockwork/trap/T in wired_to)
- if(istype(T, /obj/structure/destructible/clockwork/trap/trigger)) //Triggers don't go off multiple times
- continue
- T.activate()
diff --git a/code/modules/antagonists/clockcult/clock_structures/ark_of_the_clockwork_justicar.dm b/code/modules/antagonists/clockcult/clock_structures/ark_of_the_clockwork_justicar.dm
deleted file mode 100644
index 52126b7d5c0..00000000000
--- a/code/modules/antagonists/clockcult/clock_structures/ark_of_the_clockwork_justicar.dm
+++ /dev/null
@@ -1,381 +0,0 @@
-#define ARK_GRACE_PERIOD 300 //In seconds, how long the crew has before the Ark truly "begins"
-
-/proc/clockwork_ark_active() //A helper proc so the Ark doesn't have to be typecast every time it's checked; returns null if there is no Ark and its active var otherwise
- var/obj/structure/destructible/clockwork/massive/celestial_gateway/G = GLOB.ark_of_the_clockwork_justiciar
- if(!G)
- return
- return G.active
-
-//The gateway to Reebe, from which Ratvar emerges.
-/obj/structure/destructible/clockwork/massive/celestial_gateway
- name = "\improper Ark of the Clockwork Justicar"
- desc = "A massive, hulking amalgamation of parts. It seems to be maintaining a very unstable bluespace anomaly."
- clockwork_desc = "Nezbere's magnum opus: a hulking clockwork machine capable of combining bluespace and steam power to summon Ratvar. Once activated, \
- its instability will cause one-way bluespace rifts to open across the station to the City of Cogs, so be prepared to defend it at all costs."
- max_integrity = 500
- mouse_opacity = MOUSE_OPACITY_OPAQUE
- icon = 'icons/effects/clockwork_effects.dmi'
- icon_state = "nothing"
- density = TRUE
- resistance_flags = FIRE_PROOF | ACID_PROOF | FREEZE_PROOF
- can_be_repaired = FALSE
- immune_to_servant_attacks = TRUE
- var/active = FALSE
- var/progress_in_seconds = 0 //Once this reaches GATEWAY_RATVAR_ARRIVAL, it's game over
- var/grace_period = ARK_GRACE_PERIOD //This exists to allow the crew to gear up and prepare for the invasion
- var/initial_activation_delay = -1 //How many seconds the Ark will have initially taken to activate
- var/seconds_until_activation = -1 //How many seconds until the Ark activates; if it should never activate, set this to -1
- var/purpose_fulfilled = FALSE
- var/first_sound_played = FALSE
- var/second_sound_played = FALSE
- var/third_sound_played = FALSE
- var/fourth_sound_played = FALSE
- var/obj/effect/clockwork/overlay/gateway_glow/glow
- var/obj/effect/countdown/clockworkgate/countdown
- var/last_scream = 0
- var/recalls_remaining = 1
- var/recalling
-
-/obj/structure/destructible/clockwork/massive/celestial_gateway/Initialize()
- . = ..()
- glow = new(get_turf(src))
- if(!GLOB.ark_of_the_clockwork_justiciar)
- GLOB.ark_of_the_clockwork_justiciar = src
- START_PROCESSING(SSprocessing, src)
-
-/obj/structure/destructible/clockwork/massive/celestial_gateway/take_damage(damage_amount, damage_type = BRUTE, damage_flag = 0, sound_effect = 1, attack_dir)
- . = ..()
- if(.)
- flick("clockwork_gateway_damaged", glow)
- playsound(src, 'sound/machines/clockcult/ark_damage.ogg', 75, FALSE)
- if(last_scream < world.time)
- audible_message("An unearthly screaming sound resonates throughout Reebe!")
- for(var/V in GLOB.player_list)
- var/mob/M = V
- var/turf/T = get_turf(M)
- if((T && T.z == z) || is_servant_of_ratvar(M) || isobserver(M))
- M.playsound_local(M, 'sound/machines/clockcult/ark_scream.ogg', 100, FALSE, pressure_affected = FALSE)
- hierophant_message("The Ark is taking damage!")
- last_scream = world.time + ARK_SCREAM_COOLDOWN
-
-/obj/structure/destructible/clockwork/massive/celestial_gateway/proc/final_countdown(ark_time) //WE'RE LEAVING TOGETHEEEEEEEEER
- if(!ark_time)
- ark_time = 30 //minutes
- initial_activation_delay = ark_time * 60
- seconds_until_activation = ark_time * 60 //60 seconds in a minute * number of minutes
- for(var/obj/item/clockwork/construct_chassis/cogscarab/C in GLOB.all_clockwork_objects)
- C.infinite_resources = FALSE
- GLOB.servants_active = TRUE
- SSshuttle.registerHostileEnvironment(src)
-
-/obj/structure/destructible/clockwork/massive/celestial_gateway/proc/cry_havoc()
- visible_message("[src] shudders and roars to life, its parts beginning to whirr and screech!")
- hierophant_message("The Ark is activating! You will be transported there soon!")
- for(var/mob/M in GLOB.player_list)
- var/turf/T = get_turf(M)
- if(is_servant_of_ratvar(M) || isobserver(M) || (T && T.z == z))
- M.playsound_local(M, 'sound/magic/clockwork/ark_activation_sequence.ogg', 30, FALSE, pressure_affected = FALSE)
- addtimer(CALLBACK(src, .proc/let_slip_the_dogs), 300)
-
-/obj/structure/destructible/clockwork/massive/celestial_gateway/proc/let_slip_the_dogs()
- spawn_animation()
- first_sound_played = TRUE
- active = TRUE
- priority_announce("Massive [Gibberish("bluespace", TRUE)] anomaly detected on all frequencies. All crew are directed to \
- @!$, [text2ratvar("PURGE ALL UNTRUTHS")] <&. the anomalies and destroy their source to prevent further damage to corporate property. This is \
- not a drill.[grace_period ? " Estimated time of appearance: [grace_period] seconds. Use this time to prepare for an attack on [station_name()]." : ""]", \
- "Central Command Higher Dimensional Affairs", 'sound/magic/clockwork/ark_activation.ogg')
- set_security_level("delta")
- for(var/V in SSticker.mode.servants_of_ratvar)
- var/datum/mind/M = V
- if(!M || !M.current)
- continue
- if(ishuman(M.current))
- M.current.add_overlay(mutable_appearance('icons/effects/genetics.dmi', "servitude", -MUTATIONS_LAYER))
- for(var/V in GLOB.brass_recipes)
- var/datum/stack_recipe/R = V
- if(!R)
- continue
- if(R.title == "wall gear")
- R.time *= 2 //Building walls becomes slower when the Ark activates
- mass_recall()
- recalls_remaining++ //So it doesn't use up a charge
-
- var/turf/T = get_turf(src)
- var/list/open_turfs = list()
- for(var/turf/open/OT in orange(1, T))
- if(!is_blocked_turf(OT, TRUE))
- open_turfs |= OT
- if(open_turfs.len)
- for(var/mob/living/L in T)
- L.forceMove(pick(open_turfs))
-
-/obj/structure/destructible/clockwork/massive/celestial_gateway/proc/open_portal(turf/T)
- new/obj/effect/clockwork/city_of_cogs_rift(T)
-
-/obj/structure/destructible/clockwork/massive/celestial_gateway/proc/spawn_animation()
- hierophant_message("The Ark has activated! [grace_period ? "You have [round(grace_period / 60)] minutes until the crew invades! " : ""]Defend it at all costs!", FALSE, src)
- sound_to_playing_players(volume = 10, channel = CHANNEL_JUSTICAR_ARK, S = sound('sound/effects/clockcult_gateway_charging.ogg', TRUE))
- seconds_until_activation = 0
- SSshuttle.registerHostileEnvironment(src)
-
-/obj/structure/destructible/clockwork/massive/celestial_gateway/proc/initiate_mass_recall()
- recalling = TRUE
- sound_to_playing_players('sound/machines/clockcult/ark_recall.ogg', 75, FALSE)
- hierophant_message("The Eminence has initiated a mass recall! You are being transported to the Ark!")
- addtimer(CALLBACK(src, .proc/mass_recall), 100)
-
-/obj/structure/destructible/clockwork/massive/celestial_gateway/proc/mass_recall()
- for(var/V in SSticker.mode.servants_of_ratvar)
- var/datum/mind/M = V
- if(!M || !M.current)
- continue
- if(isliving(M.current) && M.current.stat != DEAD)
- if(isAI(M.current))
- M.current.forceMove(get_step(get_step(src, NORTH),NORTH)) // AI too fat, must make sure it always ends up a 2 tiles north instead of on the ark.
- else
- M.current.forceMove(get_turf(src))
- M.current.overlay_fullscreen("flash", /obj/screen/fullscreen/flash)
- M.current.clear_fullscreen("flash", 5)
- playsound(src, 'sound/magic/clockwork/invoke_general.ogg', 50, FALSE)
- recalls_remaining--
- recalling = FALSE
- transform = matrix() * 2
- animate(src, transform = matrix() * 0.5, time = 30, flags = ANIMATION_END_NOW)
-
-/obj/structure/destructible/clockwork/massive/celestial_gateway/Destroy()
- STOP_PROCESSING(SSprocessing, src)
- SSshuttle.clearHostileEnvironment(src)
- if(!purpose_fulfilled && istype(SSticker.mode, /datum/game_mode/clockwork_cult))
- hierophant_message("The Ark has fallen!")
- sound_to_playing_players(null, channel = CHANNEL_JUSTICAR_ARK)
- SSticker.force_ending = TRUE //rip
- if(glow)
- qdel(glow)
- glow = null
- if(countdown)
- qdel(countdown)
- countdown = null
- for(var/mob/L in GLOB.player_list)
- var/turf/T = get_turf(L)
- if(T && T.z == z)
- var/atom/movable/target = L
- if(isobj(L.loc))
- target = L.loc
- target.forceMove(get_turf(pick(GLOB.generic_event_spawns)))
- L.overlay_fullscreen("flash", /obj/screen/fullscreen/flash/static)
- L.clear_fullscreen("flash", 30)
- if(isliving(L))
- var/mob/living/LI = L
- LI.Stun(50)
- for(var/obj/effect/clockwork/city_of_cogs_rift/R in GLOB.all_clockwork_objects)
- qdel(R)
- if(GLOB.ark_of_the_clockwork_justiciar == src)
- GLOB.ark_of_the_clockwork_justiciar = null
- . = ..()
-
-/obj/structure/destructible/clockwork/massive/celestial_gateway/deconstruct(disassembled = TRUE)
- if(!(flags_1 & NODECONSTRUCT_1))
- if(!disassembled)
- resistance_flags |= INDESTRUCTIBLE
- countdown.stop()
- visible_message("[src] begins to pulse uncontrollably... you might want to run!")
- sound_to_playing_players(volume = 50, channel = CHANNEL_JUSTICAR_ARK, S = sound('sound/effects/clockcult_gateway_disrupted.ogg'))
- for(var/mob/M in GLOB.player_list)
- var/turf/T = get_turf(M)
- if((T && T.z == z) || is_servant_of_ratvar(M))
- M.playsound_local(M, 'sound/machines/clockcult/ark_deathrattle.ogg', 100, FALSE, pressure_affected = FALSE)
- make_glow()
- glow.icon_state = "clockwork_gateway_disrupted"
- resistance_flags |= INDESTRUCTIBLE
- sleep(27)
- explosion(src, 1, 3, 8, 8)
- sound_to_playing_players('sound/effects/explosion_distant.ogg', volume = 50)
- qdel(src)
-
-/obj/structure/destructible/clockwork/massive/celestial_gateway/proc/make_glow()
- if(!glow)
- glow = new /obj/effect/clockwork/overlay/gateway_glow(get_turf(src))
- glow.linked = src
-
-/obj/structure/destructible/clockwork/massive/celestial_gateway/ex_act(severity)
- var/damage = max((obj_integrity * 0.7) / severity, 100) //requires multiple bombs to take down
- take_damage(damage, BRUTE, "bomb", 0)
-
-/obj/structure/destructible/clockwork/massive/celestial_gateway/proc/get_arrival_time(var/deciseconds = TRUE)
- if(seconds_until_activation)
- . = seconds_until_activation
- else if(grace_period)
- . = grace_period
- else if(GATEWAY_RATVAR_ARRIVAL - progress_in_seconds > 0)
- . = round(max((GATEWAY_RATVAR_ARRIVAL - progress_in_seconds) / (GATEWAY_SUMMON_RATE), 0), 1)
- if(deciseconds)
- . *= 10
-
-/obj/structure/destructible/clockwork/massive/celestial_gateway/proc/get_arrival_text(s_on_time)
- if(seconds_until_activation)
- return "[get_arrival_time()][s_on_time ? "S" : ""]"
- if(grace_period)
- return "[get_arrival_time()][s_on_time ? "S" : ""]"
- . = "IMMINENT"
- if(!obj_integrity)
- . = "DETONATING"
- else if(GATEWAY_RATVAR_ARRIVAL - progress_in_seconds > 0)
- . = "[round(max((GATEWAY_RATVAR_ARRIVAL - progress_in_seconds) / (GATEWAY_SUMMON_RATE), 0), 1)][s_on_time ? "S":""]"
-
-/obj/structure/destructible/clockwork/massive/celestial_gateway/examine(mob/user)
- icon_state = "spatial_gateway" //cheat wildly by pretending to have an icon
- ..()
- icon_state = initial(icon_state)
- if(is_servant_of_ratvar(user) || isobserver(user))
- if(!active)
- to_chat(user, "Time until the Ark's activation: [DisplayTimeText(get_arrival_time())]")
- else
- if(grace_period)
- to_chat(user, "Crew grace period time remaining: [DisplayTimeText(get_arrival_time())]")
- else
- to_chat(user, "Time until Ratvar's arrival: [DisplayTimeText(get_arrival_time())]")
- switch(progress_in_seconds)
- if(-INFINITY to GATEWAY_REEBE_FOUND)
- to_chat(user, "The Ark is feeding power into the bluespace field.")
- if(GATEWAY_REEBE_FOUND to GATEWAY_RATVAR_COMING)
- to_chat(user, "The field is ripping open a copy of itself in Ratvar's prison.")
- if(GATEWAY_RATVAR_COMING to INFINITY)
- to_chat(user, "With the bluespace field established, Ratvar is preparing to come through!")
- else
- if(!active)
- to_chat(user, "Whatever it is, it doesn't seem to be active.")
- else
- switch(progress_in_seconds)
- if(-INFINITY to GATEWAY_REEBE_FOUND)
- to_chat(user, "You see a swirling bluespace anomaly steadily growing in intensity.")
- if(GATEWAY_REEBE_FOUND to GATEWAY_RATVAR_COMING)
- to_chat(user, "The anomaly is stable, and you can see flashes of something from it.")
- if(GATEWAY_RATVAR_COMING to INFINITY)
- to_chat(user, "The anomaly is stable! Something is coming through!")
-
-/obj/structure/destructible/clockwork/massive/celestial_gateway/process()
- if(seconds_until_activation == -1) //we never do anything
- return
- adjust_clockwork_power(2.5) //Provides weak power generation on its own
- if(seconds_until_activation)
- if(!countdown)
- countdown = new(src)
- countdown.start()
- seconds_until_activation--
- if(!GLOB.script_scripture_unlocked && initial_activation_delay * 0.5 > seconds_until_activation)
- GLOB.script_scripture_unlocked = TRUE
- hierophant_message("The Ark is halfway prepared. Script scripture is now available!")
- if(!seconds_until_activation)
- cry_havoc()
- seconds_until_activation = -1 //we'll set this after cry_havoc()
- return
- if(!first_sound_played || prob(7))
- for(var/mob/M in GLOB.player_list)
- if(!isnewplayer(M))
- var/turf/T = get_turf(M)
- if(T && T.z == z)
- to_chat(M, "You hear otherworldly sounds from the [dir2text(get_dir(get_turf(M), get_turf(src)))]...")
- else
- to_chat(M, "You hear otherworldly sounds from all around you...")
- if(!obj_integrity)
- return
- for(var/turf/closed/wall/W in RANGE_TURFS(2, src))
- W.dismantle_wall()
- for(var/obj/O in orange(1, src))
- if(!O.pulledby && !iseffect(O) && O.density)
- if(!step_away(O, src, 2) || get_dist(O, src) < 2)
- O.take_damage(50, BURN, "bomb")
- O.update_icon()
- for(var/V in GLOB.player_list)
- var/mob/M = V
- var/turf/T = get_turf(M)
- if(is_servant_of_ratvar(M) && (!T || T.z != z))
- M.forceMove(get_step(src, SOUTH))
- M.overlay_fullscreen("flash", /obj/screen/fullscreen/flash)
- M.clear_fullscreen("flash", 5)
- if(grace_period)
- grace_period--
- return
- progress_in_seconds += GATEWAY_SUMMON_RATE
- switch(progress_in_seconds)
- if(-INFINITY to GATEWAY_REEBE_FOUND)
- if(!second_sound_played)
- for(var/V in GLOB.generic_event_spawns)
- addtimer(CALLBACK(src, .proc/open_portal, get_turf(V)), rand(100, 600))
- sound_to_playing_players('sound/magic/clockwork/invoke_general.ogg', 30, FALSE)
- sound_to_playing_players(volume = 20, channel = CHANNEL_JUSTICAR_ARK, S = sound('sound/effects/clockcult_gateway_charging.ogg', TRUE))
- second_sound_played = TRUE
- make_glow()
- glow.icon_state = "clockwork_gateway_charging"
- if(GATEWAY_REEBE_FOUND to GATEWAY_RATVAR_COMING)
- if(!third_sound_played)
- sound_to_playing_players(volume = 25, channel = CHANNEL_JUSTICAR_ARK, S = sound('sound/effects/clockcult_gateway_active.ogg', TRUE))
- third_sound_played = TRUE
- make_glow()
- glow.icon_state = "clockwork_gateway_active"
- if(GATEWAY_RATVAR_COMING to GATEWAY_RATVAR_ARRIVAL)
- if(!fourth_sound_played)
- sound_to_playing_players(volume = 30, channel = CHANNEL_JUSTICAR_ARK, S = sound('sound/effects/clockcult_gateway_closing.ogg', TRUE))
- fourth_sound_played = TRUE
- make_glow()
- glow.icon_state = "clockwork_gateway_closing"
- if(GATEWAY_RATVAR_ARRIVAL to INFINITY)
- if(!purpose_fulfilled)
- countdown.stop()
- resistance_flags |= INDESTRUCTIBLE
- purpose_fulfilled = TRUE
- make_glow()
- animate(glow, transform = matrix() * 1.5, alpha = 255, time = 125)
- sound_to_playing_players(volume = 100, channel = CHANNEL_JUSTICAR_ARK, S = sound('sound/effects/ratvar_rises.ogg')) //End the sounds
- sleep(125)
- make_glow()
- animate(glow, transform = matrix() * 3, alpha = 0, time = 5)
- QDEL_IN(src, 3)
- sleep(3)
- GLOB.clockwork_gateway_activated = TRUE
- var/turf/T = SSmapping.get_station_center()
- new /obj/structure/destructible/clockwork/massive/ratvar(T)
- SSticker.force_ending = TRUE
- var/x0 = T.x
- var/y0 = T.y
- for(var/I in spiral_range_turfs(255, T, tick_checked = TRUE))
- var/turf/T2 = I
- if(!T2)
- continue
- var/dist = cheap_hypotenuse(T2.x, T2.y, x0, y0)
- if(dist < 100)
- dist = TRUE
- else
- dist = FALSE
- T.ratvar_act(dist)
- CHECK_TICK
-
-//ATTACK GHOST IGNORING PARENT RETURN VALUE
-/obj/structure/destructible/clockwork/massive/celestial_gateway/attack_ghost(mob/user)
- if(!IsAdminGhost(user))
- return ..()
- if(GLOB.servants_active)
- to_chat(user, "The Ark is already counting down.")
- return ..()
- if(alert(user, "Activate the Ark's countdown?", name, "Yes", "No") == "Yes")
- if(alert(user, "REALLY activate the Ark's countdown?", name, "Yes", "No") == "Yes")
- if(alert(user, "You're REALLY SURE? This cannot be undone.", name, "Yes - Activate the Ark", "No") == "Yes - Activate the Ark")
- message_admins("Admin [key_name_admin(user)] started the Ark's countdown!")
- log_admin("Admin [key_name(user)] started the Ark's countdown on a non-clockcult mode!")
- to_chat(user, "The gamemode is now being treated as clockwork cult, and the Ark is counting down from 30 \
- minutes. You will need to create servant players yourself.")
- final_countdown(35)
-
-
-
-//the actual appearance of the Ark of the Clockwork Justicar; an object so the edges of the gate can be clicked through.
-/obj/effect/clockwork/overlay/gateway_glow
- icon = 'icons/effects/96x96.dmi'
- icon_state = "clockwork_gateway_components"
- pixel_x = -32
- pixel_y = -32
- layer = BELOW_OPEN_DOOR_LAYER
- light_range = 2
- light_power = 4
- light_color = "#6A4D2F"
diff --git a/code/modules/antagonists/clockcult/clock_structures/clockwork_obelisk.dm b/code/modules/antagonists/clockcult/clock_structures/clockwork_obelisk.dm
deleted file mode 100644
index 058bd9d24e9..00000000000
--- a/code/modules/antagonists/clockcult/clock_structures/clockwork_obelisk.dm
+++ /dev/null
@@ -1,106 +0,0 @@
-//Clockwork Obelisk: Can broadcast a message at a small power cost or outright open a spatial gateway at a massive power cost.
-/obj/structure/destructible/clockwork/powered/clockwork_obelisk
- name = "clockwork obelisk"
- desc = "A large brass obelisk hanging in midair."
- clockwork_desc = "A powerful obelisk that can send a message to all servants or open a gateway to a target servant or clockwork obelisk."
- icon_state = "obelisk_inactive"
- active_icon = "obelisk"
- inactive_icon = "obelisk_inactive"
- unanchored_icon = "obelisk_unwrenched"
- construction_value = 20
- max_integrity = 150
- break_message = "The obelisk falls to the ground, undamaged!"
- debris = list(/obj/item/clockwork/alloy_shards/small = 4, \
- /obj/item/clockwork/alloy_shards/medium = 2, \
- /obj/item/clockwork/component/hierophant_ansible/obelisk = 1)
- var/hierophant_cost = MIN_CLOCKCULT_POWER //how much it costs to broadcast with large text
- var/gateway_cost = 2000 //how much it costs to open a gateway
-
-/obj/structure/destructible/clockwork/powered/clockwork_obelisk/Initialize()
- . = ..()
- toggle(1)
-
-/obj/structure/destructible/clockwork/powered/clockwork_obelisk/examine(mob/user)
- . = ..()
- if(is_servant_of_ratvar(user) || isobserver(user))
- . += "It requires [DisplayPower(hierophant_cost)] to broadcast over the Hierophant Network, and [DisplayPower(gateway_cost)] to open a Spatial Gateway."
-
-/obj/structure/destructible/clockwork/powered/clockwork_obelisk/can_be_unfasten_wrench(mob/user, silent)
- if(active)
- if(!silent)
- to_chat(user, "[src] is currently sustaining a gateway!")
- return FAILED_UNFASTEN
- return ..()
-
-/obj/structure/destructible/clockwork/powered/clockwork_obelisk/forced_disable(bad_effects)
- var/affected = 0
- for(var/obj/effect/clockwork/spatial_gateway/SG in loc)
- SG.ex_act(EXPLODE_DEVASTATE)
- affected++
- if(bad_effects)
- affected += try_use_power(MIN_CLOCKCULT_POWER*4)
- return affected
-
-/obj/structure/destructible/clockwork/powered/clockwork_obelisk/attack_hand(mob/living/user)
- . = ..()
- if(.)
- return
- if(!is_servant_of_ratvar(user) || !can_access_clockwork_power(src, hierophant_cost) || !anchored)
- to_chat(user, "You place your hand on [src], but it doesn't react.")
- return
- var/choice = alert(user,"You place your hand on [src]...",,"Hierophant Broadcast","Spatial Gateway","Cancel")
- switch(choice)
- if("Hierophant Broadcast")
- if(active)
- to_chat(user, "[src] is sustaining a gateway and cannot broadcast!")
- return
- if(!user.can_speak_vocal())
- to_chat(user, "You cannot speak through [src]!")
- return
- var/input = stripped_input(usr, "Please choose a message to send over the Hierophant Network.", "Hierophant Broadcast", "")
- if(!is_servant_of_ratvar(user) || !input || !user.canUseTopic(src, !issilicon(user)))
- return
- if(!anchored)
- to_chat(user, "[src] is no longer secured!")
- return FALSE
- if(active)
- to_chat(user, "[src] is sustaining a gateway and cannot broadcast!")
- return
- if(!user.can_speak_vocal())
- to_chat(user, "You cannot speak through [src]!")
- return
- if(!try_use_power(hierophant_cost))
- to_chat(user, "[src] lacks the power to broadcast!")
- return
- clockwork_say(user, text2ratvar("Hierophant Broadcast, activate! [html_decode(input)]"))
- titled_hierophant_message(user, input, "big_brass", "large_brass")
- if("Spatial Gateway")
- if(active)
- to_chat(user, "[src] is already sustaining a gateway!")
- return
- if(!user.can_speak_vocal())
- to_chat(user, "You need to be able to speak to open a gateway!")
- return
- if(!try_use_power(gateway_cost))
- to_chat(user, "[src] lacks the power to open a gateway!")
- return
- if(procure_gateway(user, round(100 * get_efficiency_mod(), 1), round(5 * get_efficiency_mod(), 1), 1))
- process()
- if(!active) //we won't be active if nobody has sent a gateway to us
- active = TRUE
- clockwork_say(user, text2ratvar("Spatial Gateway, activate!"))
- return
- adjust_clockwork_power(gateway_cost) //if we didn't return above, ie, successfully create a gateway, we give the power back
-
-/obj/structure/destructible/clockwork/powered/clockwork_obelisk/process()
- if(!anchored)
- return
- var/obj/effect/clockwork/spatial_gateway/SG = locate(/obj/effect/clockwork/spatial_gateway) in loc
- if(SG && SG.timerid) //it's a valid gateway, we're active
- icon_state = active_icon
- density = FALSE
- active = TRUE
- else
- icon_state = inactive_icon
- density = TRUE
- active = FALSE
diff --git a/code/modules/antagonists/clockcult/clock_structures/eminence_spire.dm b/code/modules/antagonists/clockcult/clock_structures/eminence_spire.dm
deleted file mode 100644
index 05f3ca59179..00000000000
--- a/code/modules/antagonists/clockcult/clock_structures/eminence_spire.dm
+++ /dev/null
@@ -1,145 +0,0 @@
-//Used to nominate oneself or ghosts for the role of Eminence.
-/obj/structure/destructible/clockwork/eminence_spire
- name = "eminence spire"
- desc = "A hulking machine made of powerful alloy, with three small obelisks and a huge plate in the center."
- clockwork_desc = "This spire is used to become the Eminence, who functions as an invisible leader of the cult. Activate it to nominate yourself or propose that the Eminence should be \
- selected from available ghosts. Once an Eminence is selected, they can't normally be changed."
- icon_state = "tinkerers_daemon"
- break_message = "The spire screeches with crackling power and collapses into scrap!"
- max_integrity = 400
- var/mob/eminence_nominee
- var/selection_timer //Timer ID; this is canceled if the vote is canceled
- var/kingmaking
-
-/obj/structure/destructible/clockwork/eminence_spire/attack_hand(mob/living/user)
- . = ..()
- if(.)
- return
- if(!is_servant_of_ratvar(user))
- to_chat(user, "You can tell how powerful [src] is; you know better than to touch it.")
- return
- if(kingmaking)
- return
-
- var/datum/antagonist/clockcult/C = user.mind.has_antag_datum(/datum/antagonist/clockcult)
- if(!C || !C.clock_team)
- return
- if(C.clock_team.eminence)
- to_chat(user, "There's already an Eminence!")
- return
- if(!GLOB.servants_active)
- to_chat(user, "The Ark isn't active!")
- return
- if(eminence_nominee) //This could be one large proc, but is split into three for ease of reading
- if(eminence_nominee == user)
- cancelation(user)
- else
- objection(user)
- else
- nomination(user)
-
-/obj/structure/destructible/clockwork/eminence_spire/attack_drone(mob/living/simple_animal/drone/user)
- if(!is_servant_of_ratvar(user))
- ..()
- else
- to_chat(user, "You feel the omniscient gaze turn into a puzzled frown. Perhaps you should just stick to building.")
- return
-
-//ATTACK GHOST IGNORING PARENT RETURN VALUE
-/obj/structure/destructible/clockwork/eminence_spire/attack_ghost(mob/user)
- if(!IsAdminGhost(user))
- return
-
- var/datum/mind/rando = locate() in get_antag_minds(/datum/antagonist/clockcult) //if theres no cultists new team without eminence will be created anyway.
- if(rando)
- var/datum/antagonist/clockcult/random_cultist = rando.has_antag_datum(/datum/antagonist/clockcult)
- if(random_cultist && random_cultist.clock_team && random_cultist.clock_team.eminence)
- to_chat(user, "There's already an Eminence - too late!")
- return
- if(!GLOB.servants_active)
- to_chat(user, "The Ark must be active first!")
- return
- if(alert(user, "Become the Eminence using admin?", "Become Eminence", "Yes", "No") != "Yes")
- return
- message_admins("Admin [key_name_admin(user)] directly became the Eminence of the cult!")
- log_admin("Admin [key_name(user)] made themselves the Eminence.")
- var/mob/camera/eminence/eminence = new(get_turf(src))
- eminence.key = user.key
- hierophant_message("Ratvar has directly assigned the Eminence!")
- for(var/mob/M in servants_and_ghosts())
- M.playsound_local(M, 'sound/machines/clockcult/eminence_selected.ogg', 50, FALSE)
-
-/obj/structure/destructible/clockwork/eminence_spire/proc/nomination(mob/living/nominee) //A user is nominating themselves or ghosts to become Eminence
- var/nomination_choice = alert(nominee, "Who would you like to nominate?", "Eminence Nomination", "Nominate Yourself", "Nominate Ghosts", "Cancel")
- if(!is_servant_of_ratvar(nominee) || !nominee.canUseTopic(src) || eminence_nominee)
- return
- switch(nomination_choice)
- if("Cancel")
- return
- if("Nominate Yourself")
- eminence_nominee = nominee
- hierophant_message("[nominee] nominates [nominee.p_them()]self as the Eminence! You may object by interacting with the eminence spire. The vote will otherwise pass in 30 seconds.")
- if("Nominate Ghosts")
- eminence_nominee = "ghosts"
- hierophant_message("[nominee] proposes selecting an Eminence from ghosts! You may object by interacting with the eminence spire. The vote will otherwise pass in 30 seconds.")
- for(var/mob/M in servants_and_ghosts())
- M.playsound_local(M, 'sound/machines/clockcult/ocularwarden-target.ogg', 50, FALSE)
- selection_timer = addtimer(CALLBACK(src, .proc/kingmaker), 300, TIMER_STOPPABLE)
-
-/obj/structure/destructible/clockwork/eminence_spire/proc/objection(mob/living/wright)
- if(alert(wright, "Object to the selection of [eminence_nominee] as Eminence?", "Objection!", "Object", "Cancel") == "Cancel" || !is_servant_of_ratvar(wright) || !wright.canUseTopic(src) || !eminence_nominee)
- return
- hierophant_message("[wright] objects to the nomination of [eminence_nominee]! The eminence spire has been reset.")
- for(var/mob/M in servants_and_ghosts())
- M.playsound_local(M, 'sound/machines/clockcult/integration_cog_install.ogg', 50, FALSE)
- eminence_nominee = null
- deltimer(selection_timer)
-
-/obj/structure/destructible/clockwork/eminence_spire/proc/cancelation(mob/living/cold_feet)
- if(alert(cold_feet, "Cancel your nomination?", "Cancel Nomination", "Withdraw Nomination", "Cancel") == "Cancel" || !is_servant_of_ratvar(cold_feet) || !cold_feet.canUseTopic(src) || !eminence_nominee)
- return
- hierophant_message("[eminence_nominee] has withdrawn their nomination! The eminence spire has been reset.")
- for(var/mob/M in servants_and_ghosts())
- M.playsound_local(M, 'sound/machines/clockcult/integration_cog_install.ogg', 50, FALSE)
- eminence_nominee = null
- deltimer(selection_timer)
-
-/obj/structure/destructible/clockwork/eminence_spire/proc/kingmaker()
- if(!eminence_nominee)
- return
- if(ismob(eminence_nominee))
- if(!eminence_nominee.client || !eminence_nominee.mind)
- hierophant_message("[eminence_nominee] somehow lost their sentience! The eminence spire has been reset.")
- for(var/mob/M in servants_and_ghosts())
- M.playsound_local(M, 'sound/machines/clockcult/integration_cog_install.ogg', 50, FALSE)
- eminence_nominee = null
- return
- playsound(eminence_nominee, 'sound/machines/clockcult/ark_damage.ogg', 50, FALSE)
- eminence_nominee.visible_message("A blast of white-hot light flows into [eminence_nominee], vaporizing [eminence_nominee.p_them()] in an instant!", \
- "allthelightintheuniverseflowing.into.YOU")
- for(var/obj/item/I in eminence_nominee)
- eminence_nominee.dropItemToGround(I)
- var/mob/camera/eminence/eminence = new(get_turf(src))
- eminence_nominee.mind.transfer_to(eminence)
- eminence_nominee.dust()
- hierophant_message("[eminence_nominee] has ascended into the Eminence!")
- else if(eminence_nominee == "ghosts")
- kingmaking = TRUE
- hierophant_message("The eminence spire is now selecting a ghost to be the Eminence...")
- var/list/candidates = pollGhostCandidates("Would you like to play as the servants' Eminence?", ROLE_SERVANT_OF_RATVAR, null, ROLE_SERVANT_OF_RATVAR, poll_time = 100)
- kingmaking = FALSE
- if(!LAZYLEN(candidates))
- for(var/mob/M in servants_and_ghosts())
- M.playsound_local(M, 'sound/machines/clockcult/integration_cog_install.ogg', 50, FALSE)
- hierophant_message("No ghosts accepted the offer! The eminence spire has been reset.")
- eminence_nominee = null
- return
- visible_message("A blast of white-hot light spirals from [src] in waves!")
- playsound(src, 'sound/machines/clockcult/ark_damage.ogg', 50, FALSE)
- var/mob/camera/eminence/eminence = new(get_turf(src))
- eminence_nominee = pick(candidates)
- eminence.key = eminence_nominee.key
- hierophant_message("A ghost has ascended into the Eminence!")
- for(var/mob/M in servants_and_ghosts())
- M.playsound_local(M, 'sound/machines/clockcult/eminence_selected.ogg', 50, FALSE)
- eminence_nominee = null
diff --git a/code/modules/antagonists/clockcult/clock_structures/heralds_beacon.dm b/code/modules/antagonists/clockcult/clock_structures/heralds_beacon.dm
deleted file mode 100644
index cce5c5fa59c..00000000000
--- a/code/modules/antagonists/clockcult/clock_structures/heralds_beacon.dm
+++ /dev/null
@@ -1,112 +0,0 @@
-//Used to "declare war" against the station. The servants' equipment will be permanently supercharged, and the Ark given extra time to prepare.
-//This will send an announcement to the station, meaning that they will be warned very early in advance about the impending attack.
-/obj/structure/destructible/clockwork/heralds_beacon
- name = "herald's beacon"
- desc = "An imposing spire formed of brass, with a thrumming gemstone at its peak."
- clockwork_desc = "A massively-powerful beacon. If enough servants decide to activate it, it will send an incredibly large energy pulse to the Ark, \
- permanently empowering many clockwork objects and reducing all power costs by 50%, but alerting the crew to your presence. It doesn't have enough \
- energy to sustain itself for long, and if not activated within five minutes, it will permanently shut down."
- icon_state = "interdiction_lens"
- break_message = "The beacon crackles with power before collapsing into pieces!"
- max_integrity = 250
- light_color = "#EF078E"
- var/time_remaining = 300 //Amount of seconds left to vote on whether or not to activate the beacon
- var/list/voters //People who have voted to activate the beacon
- var/votes_needed = 0 //How many votes are needed to activate the beacon
- var/available = FALSE //If the beacon can be used
-
-/obj/structure/destructible/clockwork/heralds_beacon/Initialize()
- . = ..()
- voters = list()
- START_PROCESSING(SSprocessing, src)
-
-/obj/structure/destructible/clockwork/heralds_beacon/Destroy()
- STOP_PROCESSING(SSprocessing, src)
- . = ..()
-
-/obj/structure/destructible/clockwork/heralds_beacon/process()
- if(!available)
- if(istype(SSticker.mode, /datum/game_mode/clockwork_cult))
- available = TRUE
- else
- return
- if(!SSticker.mode.servants_of_ratvar.len)
- return
- if(!votes_needed)
- var/servants = SSticker.mode.servants_of_ratvar.len
- if(servants)
- votes_needed = round(servants * 0.66)
- time_remaining--
- if(!time_remaining)
- hierophant_message("[src] has lost its power, and can no longer be activated.")
- for(var/mob/M in GLOB.player_list)
- if(isobserver(M) || is_servant_of_ratvar(M))
- M.playsound_local(M, 'sound/magic/blind.ogg', 50, FALSE)
- available = FALSE
- icon_state = "interdiction_lens_unwrenched"
- STOP_PROCESSING(SSprocessing, src)
-
-/obj/structure/destructible/clockwork/heralds_beacon/examine(mob/user)
- . = ..()
- if(isobserver(user) || is_servant_of_ratvar(user))
- if(!available)
- if(!GLOB.ratvar_approaches)
- . += "It can no longer be activated."
- else
- . += "It has been activated!"
- else
- . += "There are [time_remaining] second[time_remaining != 1 ? "s" : ""] remaining to vote."
- . += "There are [voters.len]/[votes_needed] votes to activate the beacon!"
-
-/obj/structure/destructible/clockwork/heralds_beacon/attack_hand(mob/living/user)
- . = ..()
- if(.)
- return
- if(!is_servant_of_ratvar(user))
- to_chat(user, "You can tell how powerful [src] is; you know better than to touch it.")
- return
- if(!available)
- to_chat(user, "You can no longer vote with [src].")
- return
- var/voting = !(user.key in voters)
- if(alert(user, "[voting ? "Cast a" : "Undo your"] vote to activate the beacon?", "Herald's Beacon", "Change Vote", "Cancel") == "Cancel")
- return
- if(!user.canUseTopic(src) || !is_servant_of_ratvar(user) || !available)
- return
- if(voting)
- if(user.key in voters)
- return
- voters += user.key
- else
- if(!(user.key in voters))
- return
- voters -= user.key
- var/votes_left = votes_needed - voters.len
- message_admins("[ADMIN_LOOKUPFLW(user)] has [voting ? "voted" : "undone their vote"] to activate [src]! [ADMIN_JMP(user)]")
- hierophant_message("[user.real_name] has [voting ? "voted" : "undone their vote"] to activate [src]! The beacon needs [votes_left] more votes to activate.")
- for(var/mob/M in GLOB.player_list)
- if(isobserver(M) || is_servant_of_ratvar(M))
- M.playsound_local(M, 'sound/magic/clockwork/fellowship_armory.ogg', 50, FALSE)
- if(!votes_left)
- herald_the_justiciar()
-
-/obj/structure/destructible/clockwork/heralds_beacon/proc/herald_the_justiciar()
- priority_announce("A powerful group of fanatical zealots following the cause of Ratvar have brazenly sacrificed stealth for power, and dare anyone \
- to try and stop them.", title = "The Justiciar Comes", sound = 'sound/magic/clockwork/ark_activation.ogg')
- GLOB.ratvar_approaches = TRUE
- available = FALSE
- STOP_PROCESSING(SSprocessing, src)
- icon_state = "interdiction_lens_active"
- hierophant_message("The beacon's activation has given your team great power! Many of your objects are permanently empowered!")
- for(var/mob/living/simple_animal/hostile/clockwork/C in GLOB.all_clockwork_mobs)
- if(C.stat == DEAD)
- continue
- C.update_values()
- to_chat(C, C.empower_string)
- for(var/mob/living/carbon/human/H in GLOB.alive_mob_list)
- if(is_servant_of_ratvar(H))
- to_chat(H, "The beacon's power warps your body into a clockwork form! You are now immune to many hazards, and your body is more robust against damage!")
- H.set_species(/datum/species/golem/clockwork/no_scrap)
- var/obj/structure/destructible/clockwork/massive/celestial_gateway/G = GLOB.ark_of_the_clockwork_justiciar
- G.grace_period = FALSE //no grace period if we've declared war
- G.recalls_remaining++
diff --git a/code/modules/antagonists/clockcult/clock_structures/mania_motor.dm b/code/modules/antagonists/clockcult/clock_structures/mania_motor.dm
deleted file mode 100644
index b899509fada..00000000000
--- a/code/modules/antagonists/clockcult/clock_structures/mania_motor.dm
+++ /dev/null
@@ -1,66 +0,0 @@
-//Mania Motor: A pair of antenna that, while active, cause a variety of negative mental effects in nearby human mobs.
-/obj/structure/destructible/clockwork/powered/mania_motor
- name = "mania motor"
- desc = "A pair of antenna with what appear to be sockets around the base. It reminds you of an antlion."
- clockwork_desc = "A transmitter that allows Sevtug to whisper into the minds of nearby non-servants, causing a variety of negative mental effects, up to and including conversion."
- icon_state = "mania_motor_inactive"
- active_icon = "mania_motor"
- inactive_icon = "mania_motor_inactive"
- unanchored_icon = "mania_motor_unwrenched"
- construction_value = 20
- break_message = "The antenna break off, leaving a pile of shards!"
- max_integrity = 100
- light_color = "#AF0AAF"
- debris = list(/obj/item/clockwork/alloy_shards/large = 2, \
- /obj/item/clockwork/alloy_shards/small = 2, \
- /obj/item/clockwork/component/geis_capacitor/antennae = 1)
- var/mania_cost = 150
-
-/obj/structure/destructible/clockwork/powered/mania_motor/examine(mob/user)
- . = ..()
- if(is_servant_of_ratvar(user) || isobserver(user))
- . += "It requires [DisplayPower(mania_cost)] to run."
-
-/obj/structure/destructible/clockwork/powered/mania_motor/forced_disable(bad_effects)
- if(active)
- if(bad_effects)
- try_use_power(MIN_CLOCKCULT_POWER*4)
- visible_message("[src] hums loudly, then the sockets at its base fall dark!")
- playsound(src, 'sound/effects/screech.ogg', 40, TRUE)
- toggle()
- return TRUE
-
-/obj/structure/destructible/clockwork/powered/mania_motor/attack_hand(mob/living/user)
- . = ..()
- if(.)
- return
- if(user.canUseTopic(src, !issilicon(user), NO_DEXTERY) && is_servant_of_ratvar(user))
- if(!can_access_clockwork_power(src, mania_cost))
- to_chat(user, "[src] needs more power to function!")
- return 0
- toggle(0, user)
-
-/obj/structure/destructible/clockwork/powered/mania_motor/toggle(fast_process, mob/living/user)
- . = ..()
- if(active)
- set_light(2, 0.9)
- else
- set_light(0)
-
-/obj/structure/destructible/clockwork/powered/mania_motor/process()
- if(!try_use_power(mania_cost))
- forced_disable(FALSE)
- return
- var/efficiency = get_efficiency_mod()
- for(var/mob/living/carbon/human/H in viewers(7, src))
- if(is_servant_of_ratvar(H))
- continue
- var/list/effects = H.has_status_effect_list(STATUS_EFFECT_MANIAMOTOR)
- var/datum/status_effect/maniamotor/M
- for(var/datum/status_effect/maniamotor/MM in effects)
- if(MM.motor == src)
- M = MM
- break
- if(!M)
- M = H.apply_status_effect(STATUS_EFFECT_MANIAMOTOR, src)
- M.severity = CLAMP(M.severity + ((11 - get_dist(src, H)) * efficiency * efficiency), 0, MAX_MANIA_SEVERITY)
diff --git a/code/modules/antagonists/clockcult/clock_structures/ocular_warden.dm b/code/modules/antagonists/clockcult/clock_structures/ocular_warden.dm
deleted file mode 100644
index 21435ad1eca..00000000000
--- a/code/modules/antagonists/clockcult/clock_structures/ocular_warden.dm
+++ /dev/null
@@ -1,165 +0,0 @@
-//Ocular warden: Low-damage, low-range turret. Deals constant damage to whoever it makes eye contact with.
-/obj/structure/destructible/clockwork/ocular_warden
- name = "ocular warden"
- desc = "A large brass eye with tendrils trailing below it and a wide red iris."
- clockwork_desc = "A fragile turret which will automatically attack nearby unrestrained non-Servants that can see it."
- icon_state = "ocular_warden"
- unanchored_icon = "ocular_warden_unwrenched"
- max_integrity = 25
- construction_value = 15
- layer = WALL_OBJ_LAYER
- break_message = "The warden's eye gives a glare of utter hate before falling dark!"
- debris = list(/obj/item/clockwork/component/belligerent_eye/blind_eye = 1)
- resistance_flags = LAVA_PROOF | FIRE_PROOF | ACID_PROOF
- var/damage_per_tick = 3
- var/sight_range = 3
- var/atom/movable/target
- var/list/idle_messages = list(" sulkily glares around.", " lazily drifts from side to side.", " looks around for something to burn.", " slowly turns in circles.")
-
-/obj/structure/destructible/clockwork/ocular_warden/Initialize()
- . = ..()
- START_PROCESSING(SSfastprocess, src)
-
-/obj/structure/destructible/clockwork/ocular_warden/Destroy()
- STOP_PROCESSING(SSfastprocess, src)
- return ..()
-
-/obj/structure/destructible/clockwork/ocular_warden/examine(mob/user)
- . = ..()
- . += "[target ? "It's fixated on [target]!" : "Its gaze is wandering aimlessly."]"
-
-/obj/structure/destructible/clockwork/ocular_warden/hulk_damage()
- return 25
-
-/obj/structure/destructible/clockwork/ocular_warden/can_be_unfasten_wrench(mob/user, silent)
- if(!anchored)
- for(var/obj/structure/destructible/clockwork/ocular_warden/W in orange(OCULAR_WARDEN_EXCLUSION_RANGE, src))
- if(W.anchored)
- if(!silent)
- to_chat(user, "You sense another ocular warden too near this location. Activating this one this close would cause them to fight.")
- return FAILED_UNFASTEN
- return SUCCESSFUL_UNFASTEN
-
-/obj/structure/destructible/clockwork/ocular_warden/ratvar_act()
- ..()
- if(GLOB.ratvar_awakens)
- damage_per_tick = 10
- sight_range = 6
- else
- damage_per_tick = initial(damage_per_tick)
- sight_range = initial(sight_range)
-
-/obj/structure/destructible/clockwork/ocular_warden/process()
- if(!anchored)
- lose_target()
- return
- var/list/validtargets = acquire_nearby_targets()
- if(target)
- if(!(target in validtargets))
- lose_target()
- else
- if(isliving(target))
- var/mob/living/L = target
- if(!L.anti_magic_check(chargecost = 0))
- if(isrevenant(L))
- var/mob/living/simple_animal/revenant/R = L
- if(R.revealed)
- R.unreveal_time += 2
- else
- R.reveal(10)
- if(prob(50))
- L.playsound_local(null,'sound/machines/clockcult/ocularwarden-dot1.ogg',75 * get_efficiency_mod(),1)
- else
- L.playsound_local(null,'sound/machines/clockcult/ocularwarden-dot2.ogg',75 * get_efficiency_mod(),1)
- L.adjustFireLoss((!iscultist(L) ? damage_per_tick : damage_per_tick * 2) * get_efficiency_mod()) //Nar'Sian cultists take additional damage
- if(GLOB.ratvar_awakens && L)
- L.adjust_fire_stacks(damage_per_tick)
- L.IgniteMob()
- else if(ismecha(target))
- var/obj/mecha/M = target
- M.take_damage(damage_per_tick * get_efficiency_mod(), BURN, "melee", 1, get_dir(src, M))
-
- new /obj/effect/temp_visual/ratvar/ocular_warden(get_turf(target))
-
- setDir(get_dir(get_turf(src), get_turf(target)))
- if(!target)
- if(validtargets.len)
- target = pick(validtargets)
- playsound(src,'sound/machines/clockcult/ocularwarden-target.ogg',50,TRUE)
- visible_message("[src] swivels to face [target]!")
- if(isliving(target))
- var/mob/living/L = target
- to_chat(L, "\"I SEE YOU!\"\n[src]'s gaze [GLOB.ratvar_awakens ? "melts you alive" : "burns you"]!")
- else if(ismecha(target))
- var/obj/mecha/M = target
- to_chat(M.occupant, "\"I SEE YOU!\"" )
- else if(prob(0.5)) //Extremely low chance because of how fast the subsystem it uses processes
- if(prob(50))
- visible_message("[src][pick(idle_messages)]")
- else
- setDir(pick(GLOB.cardinals))//Random rotation
-
-/obj/structure/destructible/clockwork/ocular_warden/proc/acquire_nearby_targets()
- . = list()
- for(var/mob/living/L in viewers(sight_range, src)) //Doesn't attack the blind
- var/obj/item/storage/book/bible/B = L.bible_check()
- if(B)
- if(!(B.resistance_flags & ON_FIRE))
- to_chat(L, "Your [B.name] bursts into flames!")
- for(var/obj/item/storage/book/bible/BI in L.GetAllContents())
- if(!(BI.resistance_flags & ON_FIRE))
- BI.fire_act()
- continue
- if(is_servant_of_ratvar(L) || (HAS_TRAIT(L, TRAIT_BLIND)) || L.anti_magic_check(TRUE, TRUE))
- continue
- if(L.stat || !(L.mobility_flags & MOBILITY_STAND))
- continue
- if (iscarbon(L))
- var/mob/living/carbon/c = L
- if (istype(c.handcuffed,/obj/item/restraints/handcuffs/clockwork))
- continue
- if(ishostile(L))
- var/mob/living/simple_animal/hostile/H = L
- if(("ratvar" in H.faction) || (!H.mind && "neutral" in H.faction))
- continue
- if(ismegafauna(H) || (!H.mind && H.AIStatus == AI_OFF))
- continue
- else if(isrevenant(L))
- var/mob/living/simple_animal/revenant/R = L
- if(R.stasis) //Don't target any revenants that are respawning
- continue
- else if(!L.mind)
- continue
- . += L
- var/list/viewcache = list()
- for(var/N in GLOB.mechas_list)
- var/obj/mecha/M = N
- if(get_dist(M, src) <= sight_range && M.occupant && !is_servant_of_ratvar(M.occupant))
- if(!length(viewcache))
- for (var/obj/Z in view(sight_range, src))
- viewcache += Z
- if (M in viewcache)
- . += M
-
-/obj/structure/destructible/clockwork/ocular_warden/proc/lose_target()
- if(!target)
- return 0
- target = null
- visible_message("[src] settles and seems almost disappointed.")
- return 1
-
-/obj/structure/destructible/clockwork/ocular_warden/get_efficiency_mod()
- if(GLOB.ratvar_awakens)
- return 2
- . = 1
- if(target)
- for(var/turf/T in getline(src, target))
- if(T.density)
- . -= 0.1
- continue
- for(var/obj/structure/O in T)
- if(O != src && O.density)
- . -= 0.1
- break
- . -= (get_dist(src, target) * 0.05)
- . = max(., 0.1) //The lowest damage a warden can do is 10% of its normal amount (0.25 by default)
diff --git a/code/modules/antagonists/clockcult/clock_structures/ratvar_the_clockwork_justicar.dm b/code/modules/antagonists/clockcult/clock_structures/ratvar_the_clockwork_justicar.dm
deleted file mode 100644
index 9341a7ee6a6..00000000000
--- a/code/modules/antagonists/clockcult/clock_structures/ratvar_the_clockwork_justicar.dm
+++ /dev/null
@@ -1,151 +0,0 @@
-//Ratvar himself. Impossible to damage by most standard means, and converts nearby objects and players into clockwork variants and Servants.
-/obj/structure/destructible/clockwork/massive/ratvar
- name = "Ratvar, the Clockwork Justiciar"
- desc = "..."
- clockwork_desc = "Ratvar, free at last!"
- icon = 'icons/effects/512x512.dmi'
- icon_state = "ratvar"
- pixel_x = -235
- pixel_y = -248
- resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | UNACIDABLE | ACID_PROOF
- appearance_flags = 0
- light_power = 0.7
- light_range = 15
- light_color = "#BE8700"
- var/atom/prey //Whatever Ratvar is chasing
- var/clashing = FALSE //If Ratvar is fighting with Nar'Sie
- var/convert_range = 10
- obj_flags = CAN_BE_HIT | DANGEROUS_POSSESSION
-
-/obj/structure/destructible/clockwork/massive/ratvar/Initialize()
- . = ..()
- GLOB.ratvar_awakens++
- for(var/obj/O in GLOB.all_clockwork_objects)
- O.ratvar_act()
- for(var/mob/living/simple_animal/hostile/clockwork/M in GLOB.all_clockwork_mobs)
- M.ratvar_act()
- START_PROCESSING(SSobj, src)
- send_to_playing_players("[text2ratvar("ONCE AGAIN MY LIGHT SHINES AMONG THESE PATHETIC STARS")]")
- sound_to_playing_players('sound/effects/ratvar_reveal.ogg')
- var/mutable_appearance/alert_overlay = mutable_appearance('icons/effects/clockwork_effects.dmi', "ratvar_alert")
- notify_ghosts("The Justiciar's light calls to you! Reach out to Ratvar in [get_area_name(src)] to be granted a shell to spread his glory!", null, source = src, alert_overlay = alert_overlay)
- INVOKE_ASYNC(SSshuttle.emergency, /obj/docking_port/mobile/emergency.proc/request, null, 10, null, FALSE, 0)
-
-/obj/structure/destructible/clockwork/massive/ratvar/Destroy()
- GLOB.ratvar_awakens--
- for(var/obj/O in GLOB.all_clockwork_objects)
- O.ratvar_act()
- STOP_PROCESSING(SSobj, src)
- return ..()
-
-//ATTACK GHOST IGNORING PARENT RETURN VALUE
-/obj/structure/destructible/clockwork/massive/ratvar/attack_ghost(mob/dead/observer/O)
- var/alertresult = alert(O, "Embrace the Justiciar's light? You can no longer be cloned!",,"Yes", "No")
- if(alertresult == "No" || QDELETED(O) || !istype(O) || !O.key)
- return FALSE
- var/mob/living/simple_animal/drone/cogscarab/ratvar/R = new/mob/living/simple_animal/drone/cogscarab/ratvar(get_turf(src))
- R.visible_message("[R] forms, and its eyes blink open, glowing bright red!")
- R.key = O.key
-
-/obj/structure/destructible/clockwork/massive/ratvar/Bump(atom/A)
- var/turf/T = get_turf(A)
- if(T == loc)
- T = get_step(T, dir) //please don't run into a window like a bird, ratvar
- forceMove(T)
-
-/obj/structure/destructible/clockwork/massive/ratvar/Process_Spacemove()
- return clashing
-
-/obj/structure/destructible/clockwork/massive/ratvar/process()
- if(clashing) //I'm a bit occupied right now, thanks
- return
- for(var/I in circlerangeturfs(src, convert_range))
- var/turf/T = I
- T.ratvar_act()
- for(var/I in circleviewturfs(src, round(convert_range * 0.5)))
- var/turf/T = I
- T.ratvar_act(TRUE)
- var/dir_to_step_in = pick(GLOB.cardinals)
- var/list/meals = list()
- for(var/mob/living/L in GLOB.alive_mob_list) //we want to know who's alive so we don't lose and retarget a single person
- if(L.z == z && !is_servant_of_ratvar(L) && L.mind)
- meals += L
- if(GLOB.cult_narsie && GLOB.cult_narsie.z == z)
- meals = list(GLOB.cult_narsie) //if you're in the way, handy for him, but ratvar only cares about Nar'Sie!
- prey = GLOB.cult_narsie
- if(get_dist(src, prey) <= 10)
- clash()
- return
- if(!prey)
- if(!prey && LAZYLEN(meals))
- var/mob/living/L = prey
- prey = pick(meals)
- to_chat(prey, "\"You will do, heretic.\"\n\
- You feel something massive turn its crushing focus to you...")
- L.playsound_local(prey, 'sound/effects/ratvar_reveal.ogg', 100, FALSE, pressure_affected = FALSE)
- else
- if((!istype(prey, /obj/singularity/narsie) && prob(10) && LAZYLEN(meals) > 1) || prey.z != z || !(prey in meals))
- if(is_servant_of_ratvar(prey))
- to_chat(prey, "\"Serve me well.\"\n\
- You feel great joy as your god turns His eye to another heretic...")
- else
- to_chat(prey, "\"No matter. I will find you later, heretic.\"\n\
- You feel tremendous relief as the crushing focus relents...")
- prey = null
- else
- dir_to_step_in = get_dir(src, prey) //Unlike Nar'Sie, Ratvar ruthlessly chases down his target
- step(src, dir_to_step_in)
-
-/obj/structure/destructible/clockwork/massive/ratvar/proc/clash()
- if(clashing || prey != GLOB.cult_narsie)
- return
- clashing = TRUE
- GLOB.cult_narsie.clashing = TRUE
- to_chat(world, "\"YOU.\"")
- to_chat(world, "\"Ratvar?!\"")
- clash_of_the_titans(GLOB.cult_narsie) // >:(
- return TRUE
-
-//Put me in Reebe, will you? Ratvar has found and is going to do a hecking murder on Nar'Sie
-/obj/structure/destructible/clockwork/massive/ratvar/proc/clash_of_the_titans(obj/singularity/narsie/narsie)
- var/winner = "Undeclared"
- var/base_victory_chance = 1
- while(src && narsie)
- sound_to_playing_players('sound/magic/clockwork/ratvar_attack.ogg')
- sleep(5.2)
- for(var/mob/M in GLOB.mob_list)
- if(!isnewplayer(M))
- flash_color(M, flash_color="#966400", flash_time=1)
- shake_camera(M, 4, 3)
- var/ratvar_chance = min(LAZYLEN(SSticker.mode.servants_of_ratvar), 50)
- var/narsie_chance = min(LAZYLEN(SSticker.mode.cult), 50)
- ratvar_chance = rand(base_victory_chance, ratvar_chance)
- narsie_chance = rand(base_victory_chance, narsie_chance)
- if(ratvar_chance > narsie_chance)
- winner = "Ratvar"
- break
- sleep(rand(2,5))
- sound_to_playing_players('sound/magic/clockwork/narsie_attack.ogg')
- sleep(7.4)
- for(var/mob/M in GLOB.mob_list)
- if(!isnewplayer(M))
- flash_color(M, flash_color="#C80000", flash_time=1)
- shake_camera(M, 4, 3)
- if(narsie_chance > ratvar_chance)
- winner = "Nar'Sie"
- break
- base_victory_chance *= 2 //The clash has a higher chance of resolving each time both gods attack one another
- switch(winner)
- if("Ratvar")
- send_to_playing_players("\"[pick("DIE.", "ROT.")]\"\n\
- \"[pick("Nooooo...", "Not die. To y-", "Die. Ratv-", "Sas tyen re-")]\"") //Nar'Sie get out
- sound_to_playing_players('sound/magic/clockwork/anima_fragment_attack.ogg')
- sound_to_playing_players('sound/magic/demon_dies.ogg', 50)
- clashing = FALSE
- qdel(narsie)
- if("Nar'Sie")
- send_to_playing_players("\"[pick("Ha.", "Ra'sha fonn dest.", "You fool. To come here.")]\"") //Broken English
- sound_to_playing_players('sound/magic/demon_attack1.ogg')
- sound_to_playing_players('sound/magic/clockwork/anima_fragment_death.ogg', 62)
- narsie.clashing = FALSE
- qdel(src)
diff --git a/code/modules/antagonists/clockcult/clock_structures/taunting_trail.dm b/code/modules/antagonists/clockcult/clock_structures/taunting_trail.dm
deleted file mode 100644
index c8b28fc43aa..00000000000
--- a/code/modules/antagonists/clockcult/clock_structures/taunting_trail.dm
+++ /dev/null
@@ -1,61 +0,0 @@
-//Used by the Taunting Tirade scripture as a trail.
-/obj/structure/destructible/clockwork/taunting_trail
- name = "strange smoke"
- desc = "A cloud of purple smoke."
- clockwork_desc = "A cloud of purple smoke that confuses and knocks down non-Servants that enter it."
- gender = PLURAL
- max_integrity = 5
- density = TRUE
- color = list("#AF0AAF", "#AF0AAF", "#AF0AAF", rgb(0,0,0))
- icon = 'icons/effects/effects.dmi'
- icon_state = "smoke"
- break_message = null
- break_sound = 'sound/magic/teleport_app.ogg'
- debris = list()
- var/timerid
-
-/obj/structure/destructible/clockwork/taunting_trail/Initialize()
- . = ..()
- timerid = QDEL_IN(src, 15)
- var/obj/structure/destructible/clockwork/taunting_trail/Tt = locate(/obj/structure/destructible/clockwork/taunting_trail) in loc
- if(Tt && Tt != src)
- if(!step(src, pick(GLOB.alldirs)))
- qdel(Tt)
- else
- for(var/obj/structure/destructible/clockwork/taunting_trail/TT in loc)
- if(TT != src)
- qdel(TT)
- setDir(pick(GLOB.cardinals))
- transform = matrix()*1.3
- animate(src, alpha = 100, time = 15)
-
-/obj/structure/destructible/clockwork/taunting_trail/Destroy()
- deltimer(timerid)
- return ..()
-
-/obj/structure/destructible/clockwork/taunting_trail/play_attack_sound(damage_amount, damage_type = BRUTE, damage_flag = 0)
- playsound(src, 'sound/items/welder.ogg', 50, TRUE)
-
-/obj/structure/destructible/clockwork/taunting_trail/CanPass(atom/movable/mover, turf/target)
- return TRUE
-
-/obj/structure/destructible/clockwork/taunting_trail/Crossed(atom/movable/AM)
- affect_mob(AM)
- return ..()
-
-/obj/structure/destructible/clockwork/taunting_trail/Bumped(atom/movable/AM)
- affect_mob(AM)
- return ..()
-
-/obj/structure/destructible/clockwork/taunting_trail/Bump(atom/movable/AM)
- affect_mob(AM)
- return ..()
-
-/obj/structure/destructible/clockwork/taunting_trail/proc/affect_mob(mob/living/L)
- if(istype(L) && !is_servant_of_ratvar(L))
- if(!L.anti_magic_check(chargecost = 0))
- L.confused = min(L.confused + 15, 50)
- L.dizziness = min(L.dizziness + 15, 50)
- if(L.confused >= 25)
- L.Paralyze(FLOOR(L.confused * 0.8, 1))
- take_damage(max_integrity)
diff --git a/code/modules/antagonists/clockcult/clock_structures/trap_triggers/lever.dm b/code/modules/antagonists/clockcult/clock_structures/trap_triggers/lever.dm
deleted file mode 100644
index 12e4b62a652..00000000000
--- a/code/modules/antagonists/clockcult/clock_structures/trap_triggers/lever.dm
+++ /dev/null
@@ -1,17 +0,0 @@
-//Lever: Do I really need to explain this?
-/obj/structure/destructible/clockwork/trap/trigger/lever
- name = "lever"
- desc = "A fancy lever made of wood and capped with brass."
- clockwork_desc = "A fancy lever.that activates when pulled."
- max_integrity = 75
- icon_state = "lever"
-
-/obj/structure/destructible/clockwork/trap/trigger/lever/attack_hand(mob/living/user)
- . = ..()
- if(.)
- return
- user.visible_message("[user] pulls [src]!", "You pull [src]. It clicks, then lifts back upwards.")
- if(wired_to.len)
- audible_message("You hear gears clanking.")
- playsound(src, 'sound/items/deconstruct.ogg', 50, TRUE)
- activate()
diff --git a/code/modules/antagonists/clockcult/clock_structures/trap_triggers/pressure_sensor.dm b/code/modules/antagonists/clockcult/clock_structures/trap_triggers/pressure_sensor.dm
deleted file mode 100644
index 0190ed52c60..00000000000
--- a/code/modules/antagonists/clockcult/clock_structures/trap_triggers/pressure_sensor.dm
+++ /dev/null
@@ -1,25 +0,0 @@
-//Pressure sensor: Activates when stepped on.
-/obj/structure/destructible/clockwork/trap/trigger/pressure_sensor
- name = "pressure sensor"
- desc = "A thin plate of brass, barely visible but clearly distinct."
- clockwork_desc = "A trigger that will activate when a non-servant runs across it."
- max_integrity = 5
- icon_state = "pressure_sensor"
- alpha = 50
-
-/obj/structure/destructible/clockwork/trap/trigger/Initialize()
- . = ..()
- for(var/obj/structure/destructible/clockwork/trap/T in get_turf(src))
- if(!istype(T, /obj/structure/destructible/clockwork/trap/trigger))
- wired_to += T
- T.wired_to += src
- to_chat(usr, "[src] automatically links with [T] beneath it.")
-
-/obj/structure/destructible/clockwork/trap/trigger/pressure_sensor/Crossed(atom/movable/AM)
- if(isliving(AM) && !is_servant_of_ratvar(AM))
- var/mob/living/L = AM
- if(L.stat || L.m_intent == MOVE_INTENT_WALK || !(L.mobility_flags & MOBILITY_STAND))
- return
- audible_message("*click*")
- playsound(src, 'sound/items/screwdriver2.ogg', 50, TRUE)
- activate()
diff --git a/code/modules/antagonists/clockcult/clock_structures/trap_triggers/repeater.dm b/code/modules/antagonists/clockcult/clock_structures/trap_triggers/repeater.dm
deleted file mode 100644
index f5ed91ac151..00000000000
--- a/code/modules/antagonists/clockcult/clock_structures/trap_triggers/repeater.dm
+++ /dev/null
@@ -1,30 +0,0 @@
-//Repeater: Activates every second.
-/obj/structure/destructible/clockwork/trap/trigger/repeater
- name = "repeater"
- desc = "A small black prism with a gem in the center."
- clockwork_desc = "A repeater that will send an activation signal every second."
- max_integrity = 15 //Fragile!
- icon_state = "repeater"
-
-/obj/structure/destructible/clockwork/trap/trigger/repeater/attack_hand(mob/living/user)
- . = ..()
- if(.)
- return
- if(!is_servant_of_ratvar(user))
- return
- if(!(datum_flags & DF_ISPROCESSING))
- START_PROCESSING(SSprocessing, src)
- to_chat(user, "You activate [src].")
- icon_state = "[icon_state]_on"
- else
- STOP_PROCESSING(SSprocessing, src)
- to_chat(user, "You halt [src]'s ticking.")
- icon_state = initial(icon_state)
-
-/obj/structure/destructible/clockwork/trap/trigger/repeater/process()
- activate()
- playsound(src, 'sound/items/screwdriver2.ogg', 25, FALSE)
-
-/obj/structure/destructible/clockwork/trap/trigger/repeater/Destroy()
- STOP_PROCESSING(SSprocessing, src)
- return ..()
diff --git a/code/modules/antagonists/clockcult/clock_structures/traps/brass_skewer.dm b/code/modules/antagonists/clockcult/clock_structures/traps/brass_skewer.dm
deleted file mode 100644
index 90cc1f1ecd8..00000000000
--- a/code/modules/antagonists/clockcult/clock_structures/traps/brass_skewer.dm
+++ /dev/null
@@ -1,115 +0,0 @@
-//Non-servants standing over this will get spikes through the feet, immobilizing them until they're freed.
-/obj/structure/destructible/clockwork/trap/brass_skewer
- name = "brass skewer"
- desc = "A deadly brass spike, cleverly concealed in the floor. You think you should be safe if you disarm whatever's meant to set it off."
- clockwork_desc = "A barbaric but undeniably effective weapon: a spear through the chest. It immobilizes anyone unlucky enough to step on it and keeps them in place until they get help.."
- icon_state = "brass_skewer"
- break_message = "The skewer snaps in two!"
- max_integrity = 40
- density = FALSE
- can_buckle = TRUE
- buckle_prevents_pull = TRUE
- buckle_lying = FALSE
- var/wiggle_wiggle
- var/mutable_appearance/impale_overlay //This is applied to any mob impaled so that they visibly have the skewer coming through their chest
-
-/obj/structure/destructible/clockwork/trap/brass_skewer/Initialize()
- . = ..()
- START_PROCESSING(SSfastprocess, src)
-
-/obj/structure/destructible/clockwork/trap/brass_skewer/Destroy()
- STOP_PROCESSING(SSfastprocess, src)
- if(buckled_mobs && LAZYLEN(buckled_mobs))
- var/mob/living/L = buckled_mobs[1]
- if(iscarbon(L))
- L.Paralyze(100)
- L.visible_message("[L] is maimed as the skewer shatters while still in [L.p_their()] body!")
- L.adjustBruteLoss(15)
- unbuckle_mob(L)
- return ..()
-
-/obj/structure/destructible/clockwork/trap/brass_skewer/process()
- if(density)
- if(buckled_mobs && LAZYLEN(buckled_mobs))
- var/mob/living/spitroast = buckled_mobs[1]
- spitroast.adjustBruteLoss(0.1)
-
-/obj/structure/destructible/clockwork/trap/attackby(obj/item/I, mob/living/user, params)
- if(buckled_mobs && (user in buckled_mobs))
- to_chat(user, "You can't reach!")
- return
- ..()
-
-/obj/structure/destructible/clockwork/trap/brass_skewer/bullet_act(obj/projectile/P)
- if(buckled_mobs && LAZYLEN(buckled_mobs))
- var/mob/living/L = buckled_mobs[1]
- return L.bullet_act(P)
- return ..()
-
-/obj/structure/destructible/clockwork/trap/brass_skewer/activate()
- if(density)
- return
- var/mob/living/squirrel = locate() in get_turf(src)
- if(squirrel)
- if(iscyborg(squirrel))
- if(!squirrel.stat)
- squirrel.visible_message("A massive brass spike erupts from the ground, rending [squirrel]'s chassis but shattering into pieces!", \
- "A massive brass spike rips through your chassis and bursts into shrapnel in your casing!")
- squirrel.adjustBruteLoss(50)
- squirrel.Stun(20)
- addtimer(CALLBACK(src, .proc/take_damage, max_integrity), 1)
- else
- squirrel.visible_message("A massive brass spike erupts from the ground, impaling [squirrel]!", \
- "A massive brass spike rams through your chest, hoisting you into the air!")
- squirrel.emote("scream")
- playsound(squirrel, 'sound/effects/splat.ogg', 50, TRUE)
- playsound(squirrel, 'sound/misc/desceration-03.ogg', 50, TRUE)
- squirrel.apply_damage(20, BRUTE, BODY_ZONE_CHEST)
- mouse_opacity = MOUSE_OPACITY_OPAQUE //So players can interact with the tile it's on to pull them off
- buckle_mob(squirrel, TRUE)
- else
- visible_message("A massive brass spike erupts from the ground!")
- playsound(src, 'sound/machines/clockcult/brass_skewer.ogg', 75, FALSE)
- icon_state = "[initial(icon_state)]_extended"
- density = TRUE //Skewers are one-use only
- desc = "A vicious brass spike protruding from the ground like a stala[pick("gm", "ct")]ite. It makes you sick to look at." //is stalagmite the ground one? or the ceiling one? who can ever remember?
-
-/obj/structure/destructible/clockwork/trap/brass_skewer/user_buckle_mob()
- return
-
-/obj/structure/destructible/clockwork/trap/brass_skewer/post_buckle_mob(mob/living/L)
- if(L in buckled_mobs)
- L.pixel_y = 3
- impale_overlay = mutable_appearance('icons/obj/clockwork_objects.dmi', "brass_skewer_pokeybit", ABOVE_MOB_LAYER)
- add_overlay(impale_overlay)
- else
- L.pixel_y = initial(L.pixel_y)
- L.cut_overlay(impale_overlay)
-
-/obj/structure/destructible/clockwork/trap/brass_skewer/user_unbuckle_mob(mob/living/skewee, mob/living/user)
- if(user == skewee)
- if(wiggle_wiggle)
- return
- user.visible_message("[user] starts wriggling off of [src]!", \
- "You start agonizingly working your way off of [src]...")
- wiggle_wiggle = TRUE
- if(!do_after(user, 300, target = user))
- user.visible_message("[user] slides back down [src]!")
- user.emote("scream")
- user.apply_damage(10, BRUTE, BODY_ZONE_CHEST)
- playsound(user, 'sound/misc/desceration-03.ogg', 50, TRUE)
- wiggle_wiggle = FALSE
- return
- wiggle_wiggle = FALSE
- else
- user.visible_message("[user] starts tenderly lifting [skewee] off of [src]...", \
- "You start tenderly lifting [skewee] off of [src]...")
- if(!do_after(user, 60, target = skewee))
- skewee.visible_message("[skewee] painfully slides back down [src].")
- skewee.emote("moan")
- return
- skewee.visible_message("[skewee] comes free of [src] with a squelching pop!", \
- "You come free of [src]!")
- skewee.Paralyze(30)
- playsound(skewee, 'sound/misc/desceration-03.ogg', 50, TRUE)
- unbuckle_mob(skewee)
diff --git a/code/modules/antagonists/clockcult/clock_structures/traps/steam_vent.dm b/code/modules/antagonists/clockcult/clock_structures/traps/steam_vent.dm
deleted file mode 100644
index 6aede1592ed..00000000000
--- a/code/modules/antagonists/clockcult/clock_structures/traps/steam_vent.dm
+++ /dev/null
@@ -1,23 +0,0 @@
-//This doesn't function like a "trap" in of itself, but obscures vision when active.
-/obj/structure/destructible/clockwork/trap/steam_vent
- name = "steam vent"
- desc = "Some wired slats embedded in the floor. They feel warm to the touch."
- icon_state = "steam_vent_0"
- clockwork_desc = "When active, these vents will billow out clouds of excess steam from Reebe, obscuring vision."
- break_message = "The vent snaps and collapses!"
- max_integrity = 100
- density = FALSE
-
-/obj/structure/destructible/clockwork/trap/steam_vent/activate()
- opacity = !opacity
- icon_state = "steam_vent_[opacity]"
- if(opacity)
- playsound(src, 'sound/machines/clockcult/steam_whoosh.ogg', 50, TRUE)
-
- else
- playsound(src, 'sound/machines/clockcult/integration_cog_install.ogg', 50, TRUE)
-
-/obj/structure/destructible/clockwork/trap/steam_vent/Crossed(atom/movable/AM)
- if(isliving(AM) && opacity)
- var/mob/living/L = AM
- L.adjust_fire_stacks(-1) //It's wet!
diff --git a/code/modules/antagonists/clockcult/clock_structures/wall_gear.dm b/code/modules/antagonists/clockcult/clock_structures/wall_gear.dm
deleted file mode 100644
index 7e4822b622d..00000000000
--- a/code/modules/antagonists/clockcult/clock_structures/wall_gear.dm
+++ /dev/null
@@ -1,73 +0,0 @@
-//A massive gear, effectively a girder for clocks.
-/obj/structure/destructible/clockwork/wall_gear
- name = "massive gear"
- icon_state = "wall_gear"
- unanchored_icon = "wall_gear"
- climbable = TRUE
- max_integrity = 100
- construction_value = 3
- desc = "A massive brass gear. You could probably secure or unsecure it with a wrench, or just climb over it."
- break_message = "The gear breaks apart into shards of alloy!"
- debris = list(/obj/item/clockwork/alloy_shards/large = 1, \
- /obj/item/clockwork/alloy_shards/medium = 4, \
- /obj/item/clockwork/alloy_shards/small = 2) //slightly more debris than the default, totals 26 alloy
-
-/obj/structure/destructible/clockwork/wall_gear/displaced
- anchored = FALSE
-
-/obj/structure/destructible/clockwork/wall_gear/Initialize()
- . = ..()
- new /obj/effect/temp_visual/ratvar/gear(get_turf(src))
-
-/obj/structure/destructible/clockwork/wall_gear/emp_act(severity)
- return
-
-/obj/structure/destructible/clockwork/wall_gear/attackby(obj/item/I, mob/user, params)
- if(I.tool_behaviour == TOOL_WRENCH)
- default_unfasten_wrench(user, I, 10)
- return 1
- else if(I.tool_behaviour == TOOL_SCREWDRIVER)
- if(anchored)
- to_chat(user, "[src] needs to be unsecured to disassemble it!")
- else
- user.visible_message("[user] starts to disassemble [src].", "You start to disassemble [src]...")
- if(I.use_tool(src, user, 30, volume=100) && !anchored)
- to_chat(user, "You disassemble [src].")
- deconstruct(TRUE)
- return 1
- else if(istype(I, /obj/item/stack/tile/brass))
- var/obj/item/stack/tile/brass/W = I
- if(W.get_amount() < 1)
- to_chat(user, "You need one brass sheet to do this!")
- return
- var/turf/T = get_turf(src)
- if(iswallturf(T))
- to_chat(user, "There is already a wall present!")
- return
- if(!isfloorturf(T))
- to_chat(user, "A floor must be present to build a [anchored ? "false ":""]wall!")
- return
- if(locate(/obj/structure/falsewall) in T.contents)
- to_chat(user, "There is already a false wall present!")
- return
- to_chat(user, "You start adding [W] to [src]...")
- if(do_after(user, 20, target = src))
- var/brass_floor = FALSE
- if(istype(T, /turf/open/floor/clockwork)) //if the floor is already brass, costs less to make(conservation of masssssss)
- brass_floor = TRUE
- if(W.use(2 - brass_floor))
- if(anchored)
- T.PlaceOnTop(/turf/closed/wall/clockwork)
- else
- T.PlaceOnTop(/turf/open/floor/clockwork, flags = CHANGETURF_INHERIT_AIR)
- new /obj/structure/falsewall/brass(T)
- qdel(src)
- else
- to_chat(user, "You need more brass to make a [anchored ? "false ":""]wall!")
- return 1
- return ..()
-
-/obj/structure/destructible/clockwork/wall_gear/deconstruct(disassembled = TRUE)
- if(!(flags_1 & NODECONSTRUCT_1) && disassembled)
- new /obj/item/stack/tile/brass(loc, 3)
- return ..()
diff --git a/code/modules/antagonists/clockcult/clockcult.dm b/code/modules/antagonists/clockcult/clockcult.dm
deleted file mode 100644
index 57297bdc733..00000000000
--- a/code/modules/antagonists/clockcult/clockcult.dm
+++ /dev/null
@@ -1,230 +0,0 @@
-//CLOCKCULT PROOF OF CONCEPT
-/datum/antagonist/clockcult
- name = "Clock Cultist"
- roundend_category = "clock cultists"
- antagpanel_category = "Clockcult"
- job_rank = ROLE_SERVANT_OF_RATVAR
- antag_moodlet = /datum/mood_event/cult
- var/datum/action/innate/hierophant/hierophant_network = new()
- var/datum/team/clockcult/clock_team
- var/make_team = TRUE //This should be only false for tutorial scarabs
-
-/datum/antagonist/clockcult/silent
- silent = TRUE
- show_in_antagpanel = FALSE //internal
-
-/datum/antagonist/clockcult/Destroy()
- qdel(hierophant_network)
- return ..()
-
-/datum/antagonist/clockcult/get_team()
- return clock_team
-
-/datum/antagonist/clockcult/create_team(datum/team/clockcult/new_team)
- if(!new_team && make_team)
- //TODO blah blah same as the others, allow multiple
- for(var/datum/antagonist/clockcult/H in GLOB.antagonists)
- if(!H.owner)
- continue
- if(H.clock_team)
- clock_team = H.clock_team
- return
- clock_team = new /datum/team/clockcult
- return
- if(make_team && !istype(new_team))
- stack_trace("Wrong team type passed to [type] initialization.")
- clock_team = new_team
-
-/datum/antagonist/clockcult/can_be_owned(datum/mind/new_owner)
- . = ..()
- if(.)
- . = is_eligible_servant(new_owner.current)
-
-/datum/antagonist/clockcult/greet()
- if(!owner.current || silent)
- return
- owner.current.visible_message("[owner.current]'s eyes glow a blazing yellow!", null, null, 7, owner.current) //don't show the owner this message
- to_chat(owner.current, "Assist your new companions in their righteous efforts. Your goal is theirs, and theirs yours. You serve the Clockwork \
- Justiciar above all else. Perform his every whim without hesitation.")
- owner.current.playsound_local(get_turf(owner.current), 'sound/ambience/antag/clockcultalr.ogg', 70, FALSE, pressure_affected = FALSE)
-
-/datum/antagonist/clockcult/on_gain()
- var/mob/living/current = owner.current
- SSticker.mode.servants_of_ratvar += owner
- SSticker.mode.update_servant_icons_added(owner)
- owner.special_role = ROLE_SERVANT_OF_RATVAR
- owner.current.log_message("has been converted to the cult of Ratvar!", LOG_ATTACK, color="#BE8700")
- if(issilicon(current))
- if(iscyborg(current) && !silent)
- var/mob/living/silicon/robot/R = current
- if(R.connected_ai && !is_servant_of_ratvar(R.connected_ai))
- to_chat(R, "You have been desynced from your master AI. \
- In addition, your onboard camera is no longer active and you have gained additional equipment, including a limited clockwork slab.")
- else
- to_chat(R, "Your onboard camera is no longer active and you have gained additional equipment, including a limited clockwork slab.")
- if(isAI(current))
- to_chat(current, "You are now able to use your cameras to listen in on conversations, but can no longer speak in anything but Ratvarian.")
- to_chat(current, "You can communicate with other servants by using the Hierophant Network action button in the upper left.")
- else if(isbrain(current) || isclockmob(current))
- to_chat(current, "You can communicate with other servants by using the Hierophant Network action button in the upper left.")
- ..()
- to_chat(current, "This is Ratvar's will: [CLOCKCULT_OBJECTIVE]")
- antag_memory += "Ratvar's will: [CLOCKCULT_OBJECTIVE] " //Memorize the objectives
-
-/datum/antagonist/clockcult/apply_innate_effects(mob/living/mob_override)
- . = ..()
- var/mob/living/current = owner.current
- if(istype(mob_override))
- current = mob_override
- GLOB.all_clockwork_mobs += current
- current.faction |= "ratvar"
- current.grant_language(/datum/language/ratvar)
- current.update_action_buttons_icon() //because a few clockcult things are action buttons and we may be wearing/holding them for whatever reason, we need to update buttons
- if(issilicon(current))
- var/mob/living/silicon/S = current
- if(iscyborg(S))
- var/mob/living/silicon/robot/R = S
- if(!R.shell)
- R.UnlinkSelf()
- R.module.rebuild_modules()
- else if(isAI(S))
- var/mob/living/silicon/ai/A = S
- A.can_be_carded = FALSE
- A.requires_power = POWER_REQ_CLOCKCULT
- var/list/AI_frame = list(mutable_appearance('icons/mob/clockwork_mobs.dmi', "aiframe")) //make the AI's cool frame
- for(var/d in GLOB.cardinals)
- AI_frame += image('icons/mob/clockwork_mobs.dmi', A, "eye[rand(1, 10)]", dir = d) //the eyes are randomly fast or slow
- A.add_overlay(AI_frame)
- if(!A.lacks_power())
- A.ai_restore_power()
- if(A.eyeobj)
- A.eyeobj.relay_speech = TRUE
- for(var/mob/living/silicon/robot/R in A.connected_robots)
- if(R.connected_ai == A)
- add_servant_of_ratvar(R)
- S.laws = new/datum/ai_laws/ratvar
- S.laws.associate(S)
- S.update_icons()
- S.show_laws()
- hierophant_network.title = "Silicon"
- hierophant_network.span_for_name = "nezbere"
- hierophant_network.span_for_message = "brass"
- else if(isbrain(current))
- hierophant_network.title = "Vessel"
- hierophant_network.span_for_name = "nezbere"
- hierophant_network.span_for_message = "alloy"
- else if(isclockmob(current))
- hierophant_network.title = "Construct"
- hierophant_network.span_for_name = "nezbere"
- hierophant_network.span_for_message = "brass"
- hierophant_network.Grant(current)
- current.throw_alert("clockinfo", /obj/screen/alert/clockwork/infodump)
- if(clockwork_ark_active() && ishuman(current))
- current.add_overlay(mutable_appearance('icons/effects/genetics.dmi', "servitude", -MUTATIONS_LAYER))
-
-/datum/antagonist/clockcult/remove_innate_effects(mob/living/mob_override)
- var/mob/living/current = owner.current
- if(istype(mob_override))
- current = mob_override
- GLOB.all_clockwork_mobs -= current
- current.faction -= "ratvar"
- current.remove_language(/datum/language/ratvar)
- current.clear_alert("clockinfo")
- for(var/datum/action/innate/clockwork_armaments/C in owner.current.actions) //Removes any bound clockwork armor
- qdel(C)
- for(var/datum/action/innate/call_weapon/W in owner.current.actions) //and weapons too
- qdel(W)
- if(issilicon(current))
- var/mob/living/silicon/S = current
- if(isAI(S))
- var/mob/living/silicon/ai/A = S
- A.can_be_carded = initial(A.can_be_carded)
- A.requires_power = initial(A.requires_power)
- A.cut_overlays()
- S.make_laws()
- S.update_icons()
- S.show_laws()
- var/mob/living/temp_owner = current
- ..()
- if(iscyborg(temp_owner))
- var/mob/living/silicon/robot/R = temp_owner
- R.module.rebuild_modules()
- if(temp_owner)
- temp_owner.update_action_buttons_icon() //because a few clockcult things are action buttons and we may be wearing/holding them, we need to update buttons
- temp_owner.cut_overlays()
- temp_owner.regenerate_icons()
-
-/datum/antagonist/clockcult/on_removal()
- SSticker.mode.servants_of_ratvar -= owner
- SSticker.mode.update_servant_icons_removed(owner)
- if(!silent)
- owner.current.visible_message("[owner.current] seems to have remembered [owner.current.p_their()] true allegiance!", null, null, null, owner.current)
- to_chat(owner, "A cold, cold darkness flows through your mind, extinguishing the Justiciar's light and all of your memories as his servant.")
- owner.current.log_message("has renounced the cult of Ratvar!", LOG_ATTACK, color="#BE8700")
- owner.special_role = null
- if(iscyborg(owner.current))
- to_chat(owner.current, "Despite your freedom from Ratvar's influence, you are still irreparably damaged and no longer possess certain functions such as AI linking.")
- . = ..()
-
-
-/datum/antagonist/clockcult/admin_add(datum/mind/new_owner,mob/admin)
- add_servant_of_ratvar(new_owner.current, TRUE)
- message_admins("[key_name_admin(admin)] has made [key_name_admin(new_owner)] into a servant of Ratvar.")
- log_admin("[key_name(admin)] has made [key_name(new_owner)] into a servant of Ratvar.")
-
-/datum/antagonist/clockcult/admin_remove(mob/user)
- remove_servant_of_ratvar(owner.current, TRUE)
- message_admins("[key_name_admin(user)] has removed clockwork servant status from [key_name_admin(owner)].")
- log_admin("[key_name(user)] has removed clockwork servant status from [key_name(owner)].")
-
-/datum/antagonist/clockcult/get_admin_commands()
- . = ..()
- .["Give slab"] = CALLBACK(src,.proc/admin_give_slab)
-
-/datum/antagonist/clockcult/proc/admin_give_slab(mob/admin)
- if(!SSticker.mode.equip_servant(owner.current))
- to_chat(admin, "Failed to outfit [owner.current]!")
- else
- to_chat(admin, "Successfully gave [owner.current] servant equipment!")
-
-/datum/team/clockcult
- name = "Clockcult"
- var/list/objective
- var/datum/mind/eminence
-
-/datum/team/clockcult/New(starting_members)
- . = ..()
- START_PROCESSING(SSobj,src)
-
-/datum/team/clockcult/process()
- GLOB.scripture_states = scripture_unlock_alert(GLOB.scripture_states)
-
-/datum/team/clockcult/Destroy(force, ...)
- STOP_PROCESSING(SSobj,src)
- . = ..()
-
-/datum/team/clockcult/proc/check_clockwork_victory()
- if(GLOB.clockwork_gateway_activated)
- return TRUE
- return FALSE
-
-/datum/team/clockcult/roundend_report()
- var/list/parts = list()
-
- if(check_clockwork_victory())
- parts += "Ratvar's servants defended the Ark until its activation!"
- else
- parts += "The Ark was destroyed! Ratvar will rust away for all eternity!"
- parts += " "
- parts += "The servants' objective was: [CLOCKCULT_OBJECTIVE]."
- parts += "Construction Value(CV) was: [GLOB.clockwork_construction_value]"
- for(var/i in GLOB.scripture_states)
- if(i != SCRIPTURE_DRIVER)
- parts += "[i] scripture was: [GLOB.scripture_states[i] ? "UN":""]LOCKED"
- if(eminence)
- parts += "The Eminence was: [printplayer(eminence)]"
- if(members.len)
- parts += "Ratvar's servants were:"
- parts += printplayerlist(members - eminence)
-
- return "
[parts.Join(" ")]
"
diff --git a/code/modules/antagonists/cult/blood_magic.dm b/code/modules/antagonists/cult/blood_magic.dm
index c1e9a433009..e1c49c4c0f2 100644
--- a/code/modules/antagonists/cult/blood_magic.dm
+++ b/code/modules/antagonists/cult/blood_magic.dm
@@ -447,8 +447,6 @@
C.stuttering += 15
C.cultslurring += 15
C.Jitter(15)
- if(is_servant_of_ratvar(L))
- L.adjustBruteLoss(15)
uses--
..()
diff --git a/code/modules/antagonists/cult/cult_items.dm b/code/modules/antagonists/cult/cult_items.dm
index cf5349beaec..ad99b6d53ec 100644
--- a/code/modules/antagonists/cult/cult_items.dm
+++ b/code/modules/antagonists/cult/cult_items.dm
@@ -74,14 +74,7 @@
/obj/item/melee/cultblade/pickup(mob/living/user)
..()
if(!iscultist(user))
- if(!is_servant_of_ratvar(user))
- to_chat(user, "\"I wouldn't advise that.\"")
- else
- to_chat(user, "\"One of Ratvar's toys is trying to play with things [user.p_they()] shouldn't. Cute.\"")
- to_chat(user, "A horrible force yanks at your arm!")
- user.emote("scream")
- user.apply_damage(30, BRUTE, pick(BODY_ZONE_L_ARM, BODY_ZONE_R_ARM))
- user.dropItemToGround(src)
+ to_chat(user, "\"I wouldn't advise that.\"")
/obj/item/twohanded/required/cult_bastard
name = "bloody bastard sword"
@@ -138,18 +131,9 @@
/obj/item/twohanded/required/cult_bastard/pickup(mob/living/user)
. = ..()
if(!iscultist(user))
- if(!is_servant_of_ratvar(user))
- to_chat(user, "\"I wouldn't advise that.\"")
- force = 5
- return
- else
- to_chat(user, "\"One of Ratvar's toys is trying to play with things [user.p_they()] shouldn't. Cute.\"")
- to_chat(user, "A horrible force yanks at your arm!")
- user.emote("scream")
- user.apply_damage(30, BRUTE, pick(BODY_ZONE_L_ARM, BODY_ZONE_R_ARM))
- user.dropItemToGround(src, TRUE)
- user.Paralyze(50)
- return
+ to_chat(user, "\"I wouldn't advise that.\"")
+ force = 5
+ return
force = initial(force)
jaunt.Grant(user, src)
linked_action.Grant(user, src)
@@ -392,18 +376,11 @@
/obj/item/clothing/suit/hooded/cultrobes/cult_shield/equipped(mob/living/user, slot)
..()
if(!iscultist(user))
- if(!is_servant_of_ratvar(user))
- to_chat(user, "\"I wouldn't advise that.\"")
- to_chat(user, "An overwhelming sense of nausea overpowers you!")
- user.dropItemToGround(src, TRUE)
- user.Dizzy(30)
- user.Paralyze(100)
- else
- to_chat(user, "\"Trying to use things you don't own is bad, you know.\"")
- to_chat(user, "The armor squeezes at your body!")
- user.emote("scream")
- user.adjustBruteLoss(25)
- user.dropItemToGround(src, TRUE)
+ to_chat(user, "\"I wouldn't advise that.\"")
+ to_chat(user, "An overwhelming sense of nausea overpowers you!")
+ user.dropItemToGround(src, TRUE)
+ user.Dizzy(30)
+ user.Paralyze(100)
/obj/item/clothing/suit/hooded/cultrobes/cult_shield/hit_reaction(mob/living/carbon/human/owner, atom/movable/hitby, attack_text = "the attack", final_block_chance = 0, damage = 0, attack_type = MELEE_ATTACK)
if(current_charges)
@@ -437,18 +414,11 @@
/obj/item/clothing/suit/hooded/cultrobes/berserker/equipped(mob/living/user, slot)
..()
if(!iscultist(user))
- if(!is_servant_of_ratvar(user))
- to_chat(user, "\"I wouldn't advise that.\"")
- to_chat(user, "An overwhelming sense of nausea overpowers you!")
- user.dropItemToGround(src, TRUE)
- user.Dizzy(30)
- user.Paralyze(100)
- else
- to_chat(user, "\"Trying to use things you don't own is bad, you know.\"")
- to_chat(user, "The robes squeeze at your body!")
- user.emote("scream")
- user.adjustBruteLoss(25)
- user.dropItemToGround(src, TRUE)
+ to_chat(user, "\"I wouldn't advise that.\"")
+ to_chat(user, "An overwhelming sense of nausea overpowers you!")
+ user.dropItemToGround(src, TRUE)
+ user.Dizzy(30)
+ user.Paralyze(100)
/obj/item/clothing/glasses/hud/health/night/cultblind
desc = "may Nar'Sie guide you through the darkness and shield you from the light."
@@ -679,10 +649,7 @@
L.visible_message("[src] bounces off of [L], as if repelled by an unseen force!")
else if(!..())
if(!L.anti_magic_check())
- if(is_servant_of_ratvar(L))
- L.Paralyze(100)
- else
- L.Paralyze(50)
+ L.Paralyze(50)
break_spear(T)
else
..()
@@ -978,10 +945,7 @@
L.visible_message("[src] bounces off of [L], as if repelled by an unseen force!")
else if(!..())
if(!L.anti_magic_check())
- if(is_servant_of_ratvar(L))
- L.Paralyze(60)
- else
- L.Paralyze(30)
+ L.Paralyze(30)
if(D?.thrower)
for(var/mob/living/Next in orange(2, T))
if(!Next.density || iscultist(Next))
diff --git a/code/modules/antagonists/cult/cult_structures.dm b/code/modules/antagonists/cult/cult_structures.dm
index 6027b4be97b..48be84d4689 100644
--- a/code/modules/antagonists/cult/cult_structures.dm
+++ b/code/modules/antagonists/cult/cult_structures.dm
@@ -65,14 +65,6 @@
else
return ..()
-/obj/structure/destructible/cult/ratvar_act()
- if(take_damage(rand(25, 50), BURN) && !QDELETED(src)) //if we still exist
- var/previouscolor = color
- color = "#FAE48C"
- animate(src, color = previouscolor, time = 8)
- addtimer(CALLBACK(src, /atom/proc/update_atom_colour), 8)
-
-
/obj/structure/destructible/cult/talisman
name = "altar"
desc = "A bloodstained altar dedicated to Nar'Sie."
diff --git a/code/modules/antagonists/cult/cult_turf_overlay.dm b/code/modules/antagonists/cult/cult_turf_overlay.dm
new file mode 100644
index 00000000000..1b302c79967
--- /dev/null
+++ b/code/modules/antagonists/cult/cult_turf_overlay.dm
@@ -0,0 +1,32 @@
+//an "overlay" used by clockwork walls and floors to appear normal to mesons.
+/obj/effect/cult_turf/overlay
+ mouse_opacity = MOUSE_OPACITY_TRANSPARENT
+ var/atom/linked
+
+/obj/effect/cult_turf/overlay/examine(mob/user)
+ if(linked)
+ linked.examine(user)
+
+/obj/effect/cult_turf/overlay/ex_act()
+ return FALSE
+
+/obj/effect/cult_turf/overlay/singularity_act()
+ return
+/obj/effect/cult_turf/overlay/singularity_pull()
+ return
+
+/obj/effect/cult_turf/overlay/singularity_pull(S, current_size)
+ return
+
+/obj/effect/cult_turf/overlay/Destroy()
+ if(linked)
+ linked = null
+ . = ..()
+
+/obj/effect/cult_turf/overlay/floor
+ icon = 'icons/turf/floors.dmi'
+ icon_state = "clockwork_floor"
+ layer = TURF_LAYER
+
+/obj/effect/cult_turf/overlay/floor/bloodcult
+ icon_state = "cult"
\ No newline at end of file
diff --git a/code/modules/antagonists/cult/runes.dm b/code/modules/antagonists/cult/runes.dm
index ecd223c299e..a211bf2033b 100644
--- a/code/modules/antagonists/cult/runes.dm
+++ b/code/modules/antagonists/cult/runes.dm
@@ -206,21 +206,15 @@ structure_check() searches for nearby cultist structures required for the invoca
var/oldcolor = color
color = RUNE_COLOR_DARKRED
var/mob/living/L = pick(myriad_targets)
- var/is_clock = is_servant_of_ratvar(L)
var/mob/living/F = invokers[1]
var/datum/antagonist/cult/C = F.mind.has_antag_datum(/datum/antagonist/cult,TRUE)
var/datum/team/cult/Cult_team = C.cult_team
var/is_convertable = is_convertable_to_cult(L,C.cult_team)
- if(L.stat != DEAD && (is_clock || is_convertable))
+ if(L.stat != DEAD && is_convertable)
invocation = "Mah'weyh pleggh at e'ntrath!"
..()
- if(is_clock)
- L.visible_message("[L]'s eyes glow a defiant yellow!", \
- "\"Stop resisting. You will be mi-\"\n\
- \"Give up and you will feel pain unlike anything you've ever felt!\"")
- L.Paralyze(80)
- else if(is_convertable)
+ if(is_convertable)
do_convert(L, invokers)
else
invocation = "Barhah hra zar'garis!"
@@ -775,8 +769,6 @@ structure_check() searches for nearby cultist structures required for the invoca
to_chat(L, "[I] suddenly burns hotly before returning to normal!")
continue
to_chat(L, "Your blood boils in your veins!")
- if(is_servant_of_ratvar(L))
- to_chat(L, "You feel an unholy darkness dimming the Justiciar's light!")
animate(src, color = "#FCB56D", time = 4)
sleep(4)
if(QDELETED(src))
@@ -802,8 +794,6 @@ structure_check() searches for nearby cultist structures required for the invoca
if(L.anti_magic_check(chargecost = 0))
continue
L.take_overall_damage(tick_damage*multiplier, tick_damage*multiplier)
- if(is_servant_of_ratvar(L))
- L.adjustStaminaLoss(tick_damage*multiplier*1.5)
//Rite of Spectral Manifestation: Summons a ghost on top of the rune as a cultist human with no items. User must stand on the rune at all times, and takes damage for each summoned ghost.
/obj/effect/rune/manifest
diff --git a/code/modules/antagonists/revenant/revenant.dm b/code/modules/antagonists/revenant/revenant.dm
index 7eaa860420c..ffa6833679c 100644
--- a/code/modules/antagonists/revenant/revenant.dm
+++ b/code/modules/antagonists/revenant/revenant.dm
@@ -182,9 +182,6 @@
/mob/living/simple_animal/revenant/narsie_act()
return //most humans will now be either bones or harvesters, but we're still un-alive.
-/mob/living/simple_animal/revenant/ratvar_act()
- return //clocks get out reee
-
/mob/living/simple_animal/revenant/bullet_act()
if(!revealed || stasis)
return BULLET_ACT_FORCE_PIERCE
diff --git a/code/modules/antagonists/swarmer/swarmer.dm b/code/modules/antagonists/swarmer/swarmer.dm
index b19c558da12..4072fa47208 100644
--- a/code/modules/antagonists/swarmer/swarmer.dm
+++ b/code/modules/antagonists/swarmer/swarmer.dm
@@ -198,24 +198,6 @@
/obj/item/gun/swarmer_act()//Stops you from eating the entire armory
return FALSE
-/obj/item/clockwork/alloy_shards/IntegrateAmount()
- return 10
-
-/obj/item/stack/tile/brass/IntegrateAmount()
- return 5
-
-/obj/item/clockwork/alloy_shards/medium/gear_bit/large/IntegrateAmount()
- return 4
-
-/obj/item/clockwork/alloy_shards/large/IntegrateAmount()
- return 3
-
-/obj/item/clockwork/alloy_shards/medium/IntegrateAmount()
- return 2
-
-/obj/item/clockwork/alloy_shards/small/IntegrateAmount()
- return 1
-
/turf/open/swarmer_act()//ex_act() on turf calls it on its contents, this is to prevent attacking mobs by DisIntegrate()'ing the floor
return FALSE
@@ -390,10 +372,6 @@
to_chat(S, "This object is receiving unactivated swarmer shells to help us. Aborting.")
return FALSE
-/obj/structure/destructible/clockwork/massive/celestial_gateway/swarmer_act(mob/living/simple_animal/hostile/swarmer/S)
- to_chat(S, "This object is multiplying existing resources. Aborting.")
- return FALSE
-
/obj/structure/lattice/catwalk/swarmer_act(mob/living/simple_animal/hostile/swarmer/S)
. = ..()
var/turf/here = get_turf(src)
diff --git a/code/modules/atmospherics/gasmixtures/reactions.dm b/code/modules/atmospherics/gasmixtures/reactions.dm
index 67ee93422b3..bae795a68be 100644
--- a/code/modules/atmospherics/gasmixtures/reactions.dm
+++ b/code/modules/atmospherics/gasmixtures/reactions.dm
@@ -302,7 +302,9 @@
reaction_energy += delta_plasma*PLASMA_BINDING_ENERGY //Energy is gained or lost corresponding to the creation or destruction of mass.
if(instability < FUSION_INSTABILITY_ENDOTHERMALITY)
- reaction_energy = max(reaction_energy,0) //Stable reactions don't end up endothermic.
+ reaction_energy = max(reaction_energy,0) //Stable reactions don't end up exothermic.
+ else if(air.temperature > FUSION_MAXIMUM_TEMPERATURE && reaction_energy > 0) //Makes the reaction neutral if above max temp.
+ reaction_energy = 0
else if (reaction_energy < 0)
reaction_energy *= (instability-FUSION_INSTABILITY_ENDOTHERMALITY)**0.5
diff --git a/code/modules/atmospherics/machinery/components/trinary_devices/filter.dm b/code/modules/atmospherics/machinery/components/trinary_devices/filter.dm
index 5a15d4e000b..1dd0756c223 100644
--- a/code/modules/atmospherics/machinery/components/trinary_devices/filter.dm
+++ b/code/modules/atmospherics/machinery/components/trinary_devices/filter.dm
@@ -15,7 +15,7 @@
pipe_state = "filter"
ui_x = 475
- ui_y = 195
+ ui_y = 185
/obj/machinery/atmospherics/components/trinary/filter/CtrlClick(mob/user)
if(user.canUseTopic(src, BE_CLOSE, FALSE, NO_TK))
diff --git a/code/modules/atmospherics/machinery/portable/scrubber.dm b/code/modules/atmospherics/machinery/portable/scrubber.dm
index 5c9684835e4..f9403f86dec 100644
--- a/code/modules/atmospherics/machinery/portable/scrubber.dm
+++ b/code/modules/atmospherics/machinery/portable/scrubber.dm
@@ -41,7 +41,7 @@
/obj/machinery/portable_atmospherics/scrubber/proc/scrub(var/datum/gas_mixture/mixture)
if(air_contents.return_pressure() >= overpressure_m * ONE_ATMOSPHERE)
return
-
+
var/transfer_moles = min(1, volume_rate / mixture.volume) * mixture.total_moles()
var/datum/gas_mixture/filtering = mixture.remove(transfer_moles) // Remove part of the mixture to filter.
@@ -137,6 +137,9 @@
/obj/machinery/portable_atmospherics/scrubber/huge/movable
movable = TRUE
+/obj/machinery/portable_atmospherics/scrubber/huge/movable/cargo
+ anchored = FALSE
+
/obj/machinery/portable_atmospherics/scrubber/huge/update_icon()
icon_state = "scrubber:[on]"
diff --git a/code/modules/awaymissions/mission_code/wildwest.dm b/code/modules/awaymissions/mission_code/wildwest.dm
index 94cec202900..77aa1e5ba6c 100644
--- a/code/modules/awaymissions/mission_code/wildwest.dm
+++ b/code/modules/awaymissions/mission_code/wildwest.dm
@@ -88,7 +88,7 @@
else
chargesa--
insistinga = 0
- var/wish = input("You want...","Wish") as null|anything in list("Power","Wealth","Immortality","To Kill","Peace")
+ var/wish = input("You want...","Wish") as null|anything in list("Power","Wealth","Immortality","Peace")
switch(wish)
if("Power")
to_chat(user, "Your wish is granted, but at a terrible cost...")
@@ -107,11 +107,6 @@
to_chat(user, "The Wish Granter punishes you for your selfishness, claiming your soul and warping your body to match the darkness in your heart.")
user.verbs += /mob/living/carbon/proc/immortality
user.set_species(/datum/species/shadow)
- if("To Kill")
- to_chat(user, "Your wish is granted, but at a terrible cost...")
- to_chat(user, "The Wish Granter punishes you for your wickedness, claiming your soul and warping your body to match the darkness in your heart.")
- user.mind.add_antag_datum(/datum/antagonist/wishgranter)
- user.set_species(/datum/species/shadow)
if("Peace")
to_chat(user, "Whatever alien sentience that the Wish Granter possesses is satisfied with your wish. There is a distant wailing as the last of the Faithless begin to die, then silence.")
to_chat(user, "You feel as if you just narrowly avoided a terrible fate...")
diff --git a/code/modules/cargo/bounties/reagent.dm b/code/modules/cargo/bounties/reagent.dm
index a9bf985d6ca..f7b48b45cc3 100644
--- a/code/modules/cargo/bounties/reagent.dm
+++ b/code/modules/cargo/bounties/reagent.dm
@@ -175,7 +175,6 @@
/datum/reagent/consumable/frostoil,\
/datum/reagent/toxin/slimejelly,\
/datum/reagent/teslium/energized_jelly,\
- /datum/reagent/toxin/skewium,\
/datum/reagent/toxin/mimesbane,\
/datum/reagent/medicine/strange_reagent,\
/datum/reagent/nitroglycerin,\
diff --git a/code/modules/cargo/centcom_podlauncher.dm b/code/modules/cargo/centcom_podlauncher.dm
index c470ab613bf..c7f6cf0406f 100644
--- a/code/modules/cargo/centcom_podlauncher.dm
+++ b/code/modules/cargo/centcom_podlauncher.dm
@@ -600,8 +600,8 @@ force_open = FALSE, datum/tgui/master_ui = null, datum/ui_state/state = GLOB.adm
for (var/X in temp_pod.explosionSize)
explosionString += "[X]|"
- var/msg = "launched [podString][whomString].[delayString][damageString][explosionString]"
- message_admins("[key_name_admin(usr)] [msg] in [AREACOORD(specificTarget)].")
+ var/msg = "launched [podString] towards [whomString] [delayString][damageString][explosionString]"
+ message_admins("[key_name_admin(usr)] [msg] in [ADMIN_VERBOSEJMP(specificTarget)].")
if (!isemptylist(whoDyin))
for (var/mob/living/M in whoDyin)
admin_ticket_log(M, "[key_name_admin(usr)] [msg]")
diff --git a/code/modules/cargo/console.dm b/code/modules/cargo/console.dm
index 53d5a5632ff..517b444a16e 100644
--- a/code/modules/cargo/console.dm
+++ b/code/modules/cargo/console.dm
@@ -3,8 +3,8 @@
desc = "Used to order supplies, approve requests, and control the shuttle."
icon_screen = "supply"
circuit = /obj/item/circuitboard/computer/cargo
- ui_x = 750
- ui_y = 850
+ ui_x = 780
+ ui_y = 750
var/requestonly = FALSE
var/contraband = FALSE
@@ -131,8 +131,6 @@
/obj/machinery/computer/cargo/ui_act(action, params, datum/tgui/ui)
if(..())
return
- if(action != "add" && requestonly)
- return
switch(action)
if("send")
if(!SSshuttle.supply.canMove())
diff --git a/code/modules/cargo/packs.dm b/code/modules/cargo/packs.dm
index 9782c8aff56..ba477ab1add 100644
--- a/code/modules/cargo/packs.dm
+++ b/code/modules/cargo/packs.dm
@@ -804,6 +804,30 @@
contains = list(/obj/item/vending_refill/engivend)
crate_name = "engineering supply crate"
+/datum/supply_pack/engineering/portapump
+ name = "Portable Air Pump Crate"
+ desc = "Did someone let the air out of the shuttle again? We've got you covered. Contains two portable air pumps."
+ cost = 2500
+ contains = list(/obj/machinery/portable_atmospherics/pump,
+ /obj/machinery/portable_atmospherics/pump)
+ crate_name = "portable air pump crate"
+
+/datum/supply_pack/engineering/portascrubber
+ name = "Portable Scrubber Crate"
+ desc = "Clean up that pesky plasma leak with your very own set of two portable scrubbers."
+ cost = 2500
+ contains = list(/obj/machinery/portable_atmospherics/scrubber,
+ /obj/machinery/portable_atmospherics/scrubber)
+ crate_name = "portable scrubber crate"
+
+/datum/supply_pack/engineering/hugescrubber
+ name = "Huge Portable Scrubber Crate"
+ desc = "A huge portable scrubber for huge atmospherics mistakes."
+ cost = 5000
+ contains = list(/obj/machinery/portable_atmospherics/scrubber/huge/movable/cargo)
+ crate_name = "huge portable scrubber crate"
+ crate_type = /obj/structure/closet/crate/large
+
/datum/supply_pack/engineering/bsa
name = "Bluespace Artillery Parts"
desc = "The pride of Nanotrasen Naval Command. The legendary Bluespace Artillery Cannon is a devastating feat of human engineering and testament to wartime determination. Highly advanced research is required for proper construction. "
@@ -1896,8 +1920,6 @@
. = ..()
for(var/i in 1 to 4)
new /mob/living/simple_animal/parrot(.)
- if(prob(1))
- new /mob/living/simple_animal/parrot/clock_hawk(.)
/datum/supply_pack/critter/butterfly
name = "Butterflies Crate"
diff --git a/code/modules/client/asset_cache.dm b/code/modules/client/asset_cache.dm
index 15f5371022e..a36c3c7bcdb 100644
--- a/code/modules/client/asset_cache.dm
+++ b/code/modules/client/asset_cache.dm
@@ -325,6 +325,13 @@ GLOBAL_LIST_EMPTY(asset_datums)
var/size_id = sprite[SPR_SIZE]
return {""}
+/datum/asset/spritesheet/proc/icon_class_name(sprite_name)
+ var/sprite = sprites[sprite_name]
+ if (!sprite)
+ return null
+ var/size_id = sprite[SPR_SIZE]
+ return {"[name][size_id] [sprite_name]"}
+
#undef SPR_SIZE
#undef SPR_IDX
#undef SPRSZ_COUNT
@@ -381,8 +388,19 @@ GLOBAL_LIST_EMPTY(asset_datums)
/datum/asset/simple/tgui
assets = list(
- "tgui.css" = 'tgui/assets/tgui.css',
- "tgui.js" = 'tgui/assets/tgui.js',
+ // tgui
+ "tgui.css" = 'tgui/assets/tgui.css',
+ "tgui.js" = 'tgui/assets/tgui.js',
+ // tgui-next
+ "tgui-main.html" = 'tgui-next/packages/tgui/public/tgui-main.html',
+ "tgui-fallback.html" = 'tgui-next/packages/tgui/public/tgui-fallback.html',
+ "tgui.bundle.js" = 'tgui-next/packages/tgui/public/bundles/tgui.bundle.js',
+ "tgui.bundle.css" = 'tgui-next/packages/tgui/public/bundles/tgui.bundle.css',
+ "shim-console.js" = 'tgui-next/packages/tgui/public/shim-console.js',
+ "shim-html5shiv.js" = 'tgui-next/packages/tgui/public/shim-html5shiv.js',
+ "shim-ie8.js" = 'tgui-next/packages/tgui/public/shim-ie8.js',
+ "shim-dom4.js" = 'tgui-next/packages/tgui/public/shim-dom4.js',
+ "shim-css-om.js" = 'tgui-next/packages/tgui/public/shim-css-om.js',
)
/datum/asset/group/tgui
diff --git a/code/modules/clothing/chameleon.dm b/code/modules/clothing/chameleon.dm
index 7522900ceca..4e523bda1af 100644
--- a/code/modules/clothing/chameleon.dm
+++ b/code/modules/clothing/chameleon.dm
@@ -304,14 +304,6 @@
var/datum/action/item_action/chameleon/change/chameleon_action
-/obj/item/clothing/under/chameleon/ratvar
- name = "ratvarian engineer's jumpsuit"
- desc = "A tough jumpsuit woven from alloy threads. It can take on the appearance of other jumpsuits."
- icon = 'icons/obj/clothing/under/engineering.dmi'
- icon_state = "engine"
- item_state = "engi_suit"
- mob_overlay_icon = 'icons/mob/clothing/under/engineering.dmi'
-
/obj/item/clothing/under/chameleon/Initialize()
. = ..()
chameleon_action = new(src)
diff --git a/code/modules/clothing/head/misc.dm b/code/modules/clothing/head/misc.dm
index e0ef9322108..1991a6ff0eb 100644
--- a/code/modules/clothing/head/misc.dm
+++ b/code/modules/clothing/head/misc.dm
@@ -428,3 +428,14 @@
desc = "An extra-mustahabb way of showing your devotion to Allah."
icon_state = "taqiyahred"
pocket_storage_component_path = /datum/component/storage/concrete/pockets/small
+
+/obj/item/clothing/head/shrine_wig
+ name = "shrine maiden's wig"
+ desc = "Purify in style!"
+ flags_inv = HIDEHAIR //bald
+ mob_overlay_icon = 'icons/mob/large-worn-icons/64x64/head.dmi'
+ icon_state = "shrine_wig"
+ item_state = "shrine_wig"
+ worn_x_dimension = 64
+ worn_y_dimension = 64
+ dynamic_hair_suffix = ""
diff --git a/code/modules/clothing/suits/armor.dm b/code/modules/clothing/suits/armor.dm
index e8f0a70a136..89005754a16 100644
--- a/code/modules/clothing/suits/armor.dm
+++ b/code/modules/clothing/suits/armor.dm
@@ -148,15 +148,18 @@
icon_state = "armor_reflec"
item_state = "armor_reflec"
blood_overlay_type = "armor"
+ body_parts_covered = CHEST|GROIN|ARMS
+ cold_protection = CHEST|GROIN|ARMS
+ heat_protection = CHEST|GROIN|ARMS
armor = list("melee" = 10, "bullet" = 10, "laser" = 60, "energy" = 50, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 100, "acid" = 100)
resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | ACID_PROOF
- var/hit_reflect_chance = 40
+ var/hit_reflect_chance = 50
/obj/item/clothing/suit/armor/laserproof/IsReflect(def_zone)
- if(!(def_zone in list(BODY_ZONE_CHEST, BODY_ZONE_PRECISE_GROIN))) //If not shot where ablative is covering you, you don't get the reflection bonus!
- return 0
+ if(!(def_zone in list(BODY_ZONE_CHEST, BODY_ZONE_PRECISE_GROIN, BODY_ZONE_L_ARM, BODY_ZONE_R_ARM))) //If not shot where ablative is covering you, you don't get the reflection bonus!
+ return FALSE
if (prob(hit_reflect_chance))
- return 1
+ return TRUE
/obj/item/clothing/suit/armor/vest/det_suit
name = "detective's armor vest"
diff --git a/code/modules/clothing/suits/miscellaneous.dm b/code/modules/clothing/suits/miscellaneous.dm
index 6789f20ecf9..68b97dd80c2 100644
--- a/code/modules/clothing/suits/miscellaneous.dm
+++ b/code/modules/clothing/suits/miscellaneous.dm
@@ -335,6 +335,14 @@
item_state = "officertanjacket"
body_parts_covered = CHEST|ARMS
+/obj/item/clothing/suit/shrine_maiden
+ name = "shrine maiden's outfit"
+ desc = "Makes you want to exterminate some troublesome youkai."
+ icon_state = "shrine_maiden"
+ item_state = "shrine_maiden"
+ body_parts_covered = CHEST|GROIN|LEGS|ARMS
+ flags_inv = HIDEJUMPSUIT
+
/*
* Misc
*/
diff --git a/code/modules/events/_event.dm b/code/modules/events/_event.dm
index a25dd537734..7efdf73393d 100644
--- a/code/modules/events/_event.dm
+++ b/code/modules/events/_event.dm
@@ -106,7 +106,8 @@
var/datum/round_event_control/control
var/startWhen = 0 //When in the lifetime to call start().
- var/announceWhen = 0 //When in the lifetime to call announce(). Set an event's announceWhen to -1 if announcement should not be shown.
+ var/announceWhen = 0 //When in the lifetime to call announce(). If you don't want it to announce use announceChance, below.
+ var/announceChance = 100 // Probability of announcing, used in prob(), 0 to 100, default 100. Used in ion storms currently.
var/endWhen = 0 //When in the lifetime the event should end.
var/activeFor = 0 //How long the event has existed. You don't need to change this.
@@ -173,7 +174,7 @@
start()
processing = TRUE
- if(activeFor == announceWhen)
+ if(activeFor == announceWhen && prob(announceChance))
processing = FALSE
announce(FALSE)
processing = TRUE
diff --git a/code/modules/events/blob.dm b/code/modules/events/blob.dm
index 05dd2037840..e006f825502 100644
--- a/code/modules/events/blob.dm
+++ b/code/modules/events/blob.dm
@@ -9,7 +9,7 @@
gamemode_blacklist = list("blob") //Just in case a blob survives that long
/datum/round_event/ghost_role/blob
- announceWhen = -1
+ announceChance = 0
role_name = "blob overmind"
fakeable = TRUE
diff --git a/code/modules/events/ion_storm.dm b/code/modules/events/ion_storm.dm
index 5b9a8c8af36..5587234d061 100644
--- a/code/modules/events/ion_storm.dm
+++ b/code/modules/events/ion_storm.dm
@@ -1,5 +1,3 @@
-#define ION_RANDOM 0
-#define ION_ANNOUNCE 1
/datum/round_event_control/ion_storm
name = "Ion Storm"
typepath = /datum/round_event/ion_storm
@@ -11,11 +9,10 @@
var/removeRandomLawChance = 10 //chance the AI has one random supplied or inherent law removed
var/removeDontImproveChance = 10 //chance the randomly created law replaces a random law instead of simply being added
var/shuffleLawsChance = 10 //chance the AI's laws are shuffled afterwards
- var/botEmagChance = 10
- var/announceEvent = ION_RANDOM // -1 means don't announce, 0 means have it randomly announce, 1 means
+ var/botEmagChance = 1
var/ionMessage = null
- var/ionAnnounceChance = 33
announceWhen = 1
+ announceChance = 33
/datum/round_event/ion_storm/add_law_only // special subtype that adds a law only
replaceLawsetChance = 0
@@ -25,7 +22,7 @@
botEmagChance = 0
/datum/round_event/ion_storm/announce(fake)
- if(announceEvent == ION_ANNOUNCE || (announceEvent == ION_RANDOM && prob(ionAnnounceChance)) || fake)
+ if(prob(announceChance) || fake)
priority_announce("Ion storm detected near the station. Please check all AI-controlled equipment for errors.", "Anomaly Alert", 'sound/ai/ionstorm.ogg')
@@ -561,7 +558,4 @@
if(4)
message = "ALL [ionthreats] ARE NOW NAMED [ionobjects]."
- return message
-
-#undef ION_RANDOM
-#undef ION_ANNOUNCE
+ return message
\ No newline at end of file
diff --git a/code/modules/flufftext/Hallucination.dm b/code/modules/flufftext/Hallucination.dm
index 23865cadaec..e4b3c2088d1 100644
--- a/code/modules/flufftext/Hallucination.dm
+++ b/code/modules/flufftext/Hallucination.dm
@@ -472,12 +472,6 @@ GLOBAL_LIST_INIT(hallucination_list, list(
image_file = 'icons/mob/inhands/equipment/security_lefthand.dmi'
target.playsound_local(H, "sparks",75,1,-1)
A = image(image_file,H,"baton", layer=ABOVE_MOB_LAYER)
- if("clockspear")
- if(side == "right")
- image_file = 'icons/mob/inhands/antag/clockwork_righthand.dmi'
- else
- image_file = 'icons/mob/inhands/antag/clockwork_lefthand.dmi'
- A = image(image_file,H,"ratvarian_spear", layer=ABOVE_MOB_LAYER)
if("ttv")
if(side == "right")
image_file = 'icons/mob/inhands/weapons/bombs_righthand.dmi'
@@ -744,7 +738,7 @@ GLOBAL_LIST_INIT(hallucination_list, list(
message_pool.Add("[other] puts the [pick(\
"revolver","energy sword","cryptographic sequencer","power sink","energy bow",\
"hybrid taser","stun baton","flash","syringe gun","circular saw","tank transfer valve",\
- "ritual dagger","clockwork slab","spellbook",\
+ "ritual dagger","spellbook",\
"pulse rifle","captain's spare ID","hand teleporter","hypospray","antique laser gun","X-01 MultiPhase Energy Gun","station's blueprints"\
)] into [equipped_backpack].")
diff --git a/code/modules/food_and_drinks/drinks/drinks.dm b/code/modules/food_and_drinks/drinks/drinks.dm
index 38063a35601..3ac545fbaf0 100644
--- a/code/modules/food_and_drinks/drinks/drinks.dm
+++ b/code/modules/food_and_drinks/drinks/drinks.dm
@@ -557,6 +557,7 @@
name = "Monkey Energy"
desc = "Unleash the ape!"
icon_state = "monkey_energy"
+ item_state = "monkey_energy"
list_reagents = list(/datum/reagent/consumable/monkey_energy = 50)
foodtype = SUGAR | JUNKFOOD
diff --git a/code/modules/food_and_drinks/food/snacks.dm b/code/modules/food_and_drinks/food/snacks.dm
index 5d25605a387..9295b55acbd 100644
--- a/code/modules/food_and_drinks/food/snacks.dm
+++ b/code/modules/food_and_drinks/food/snacks.dm
@@ -320,7 +320,7 @@ All foods are distributed among various categories. Use common sense.
/obj/item/reagent_containers/food/snacks/attack_animal(mob/M)
if(isanimal(M))
- if(iscorgi(M))
+ if(isdog(M))
var/mob/living/L = M
if(bitecount == 0 || prob(50))
M.emote("me", 1, "nibbles away at \the [src]")
diff --git a/code/modules/food_and_drinks/food/snacks_cake.dm b/code/modules/food_and_drinks/food/snacks_cake.dm
index 9d37f9e53c2..6c241d1135e 100644
--- a/code/modules/food_and_drinks/food/snacks_cake.dm
+++ b/code/modules/food_and_drinks/food/snacks_cake.dm
@@ -362,7 +362,7 @@
desc = "A quote on quote cake that is made with electronic boards and leaks acid..."
icon_state = "hardware_cake"
slice_path = /obj/item/reagent_containers/food/snacks/cakeslice/hardware_cake_slice
- bonus_reagents = list(/datum/reagent/toxin/acid = 15, /datum/reagent/oil = 15)
+ bonus_reagents = list(/datum/reagent/toxin/acid = 15, /datum/reagent/fuel/oil = 15)
tastes = list("acid" = 3, "metal" = 4, "glass" = 5)
foodtype = GRAIN | GROSS
diff --git a/code/modules/goonchat/browserassets/css/browserOutput.css b/code/modules/goonchat/browserassets/css/browserOutput.css
index e25e5415561..0021738beaf 100644
--- a/code/modules/goonchat/browserassets/css/browserOutput.css
+++ b/code/modules/goonchat/browserassets/css/browserOutput.css
@@ -352,13 +352,6 @@ h1.alert, h2.alert {color: #000000;}
.deconversion_message {color: #a947ff; font-size: 185%; font-style: italic;}
-.brass {color: #BE8700;}
-.heavy_brass {color: #BE8700; font-weight: bold; font-style: italic;}
-.large_brass {color: #BE8700; font-size: 185%;}
-.big_brass {color: #BE8700; font-size: 185%; font-weight: bold; font-style: italic;}
-.ratvar {color: #BE8700; font-size: 370%; font-weight: bold; font-style: italic;}
-.alloy {color: #42474D;}
-.heavy_alloy {color: #42474D; font-weight: bold; font-style: italic;}
.nezbere_large {color: #42474D; font-size: 185%; font-weight: bold; font-style: italic;}
.nezbere {color: #42474D; font-weight: bold; font-style: italic;}
.nezbere_small {color: #42474D;}
diff --git a/code/modules/jobs/access.dm b/code/modules/jobs/access.dm
index 8fc994ad3a9..a765e02db5d 100644
--- a/code/modules/jobs/access.dm
+++ b/code/modules/jobs/access.dm
@@ -131,7 +131,7 @@
ACCESS_HYDROPONICS, ACCESS_LIBRARY, ACCESS_LAWYER, ACCESS_VIROLOGY, ACCESS_CMO, ACCESS_QM, ACCESS_SURGERY,
ACCESS_THEATRE, ACCESS_RESEARCH, ACCESS_MINING, ACCESS_MAILSORTING, ACCESS_WEAPONS,
ACCESS_MECH_MINING, ACCESS_MECH_ENGINE, ACCESS_MECH_SCIENCE, ACCESS_MECH_SECURITY, ACCESS_MECH_MEDICAL,
- ACCESS_VAULT, ACCESS_MINING_STATION, ACCESS_XENOBIOLOGY, ACCESS_CE, ACCESS_HOP, ACCESS_HOS, ACCESS_RC_ANNOUNCE,
+ ACCESS_VAULT, ACCESS_MINING_STATION, ACCESS_XENOBIOLOGY, ACCESS_CE, ACCESS_HOP, ACCESS_HOS, ACCESS_APOTHECARY, ACCESS_RC_ANNOUNCE,
ACCESS_KEYCARD_AUTH, ACCESS_TCOMSAT, ACCESS_GATEWAY, ACCESS_MINERAL_STOREROOM, ACCESS_MINISAT, ACCESS_NETWORK, ACCESS_CLONING)
/proc/get_all_centcom_access()
@@ -160,7 +160,7 @@
if(2) //security
return list(ACCESS_SEC_DOORS, ACCESS_WEAPONS, ACCESS_SECURITY, ACCESS_BRIG, ACCESS_ARMORY, ACCESS_FORENSICS_LOCKERS, ACCESS_COURT, ACCESS_MECH_SECURITY, ACCESS_HOS)
if(3) //medbay
- return list(ACCESS_MEDICAL, ACCESS_GENETICS, ACCESS_CLONING, ACCESS_MORGUE, ACCESS_CHEMISTRY, ACCESS_VIROLOGY, ACCESS_SURGERY, ACCESS_MECH_MEDICAL, ACCESS_CMO)
+ return list(ACCESS_MEDICAL, ACCESS_GENETICS, ACCESS_CLONING, ACCESS_MORGUE, ACCESS_CHEMISTRY, ACCESS_VIROLOGY, ACCESS_SURGERY, ACCESS_MECH_MEDICAL, ACCESS_CMO, ACCESS_APOTHECARY)
if(4) //research
return list(ACCESS_RESEARCH, ACCESS_TOX, ACCESS_TOX_STORAGE, ACCESS_GENETICS, ACCESS_ROBOTICS, ACCESS_XENOBIOLOGY, ACCESS_MECH_SCIENCE, ACCESS_MINISAT, ACCESS_RD, ACCESS_NETWORK)
if(5) //engineering and maintenance
@@ -291,6 +291,8 @@
return "HoS Office"
if(ACCESS_CE)
return "CE Office"
+ if(ACCESS_APOTHECARY)
+ return "Apothecary"
if(ACCESS_RC_ANNOUNCE)
return "RC Announcements"
if(ACCESS_KEYCARD_AUTH)
diff --git a/code/modules/jobs/job_types/chemist.dm b/code/modules/jobs/job_types/chemist.dm
index 6c8551ba808..12bf18e8383 100644
--- a/code/modules/jobs/job_types/chemist.dm
+++ b/code/modules/jobs/job_types/chemist.dm
@@ -13,8 +13,8 @@
outfit = /datum/outfit/job/chemist
- access = list(ACCESS_MEDICAL, ACCESS_MORGUE, ACCESS_SURGERY, ACCESS_CHEMISTRY, ACCESS_VIROLOGY, ACCESS_GENETICS, ACCESS_CLONING, ACCESS_MECH_MEDICAL, ACCESS_MINERAL_STOREROOM)
- minimal_access = list(ACCESS_MEDICAL, ACCESS_MORGUE, ACCESS_CHEMISTRY, ACCESS_MECH_MEDICAL, ACCESS_MINERAL_STOREROOM)
+ access = list(ACCESS_MEDICAL, ACCESS_MORGUE, ACCESS_SURGERY, ACCESS_CHEMISTRY, ACCESS_APOTHECARY, ACCESS_VIROLOGY, ACCESS_GENETICS, ACCESS_CLONING, ACCESS_MECH_MEDICAL, ACCESS_MINERAL_STOREROOM)
+ minimal_access = list(ACCESS_MEDICAL, ACCESS_MORGUE, ACCESS_CHEMISTRY, ACCESS_MECH_MEDICAL, ACCESS_MINERAL_STOREROOM, ACCESS_APOTHECARY)
paycheck = PAYCHECK_MEDIUM
paycheck_department = ACCOUNT_MED
diff --git a/code/modules/jobs/job_types/chief_medical_officer.dm b/code/modules/jobs/job_types/chief_medical_officer.dm
index 588ed2463fb..e64c00a6d33 100644
--- a/code/modules/jobs/job_types/chief_medical_officer.dm
+++ b/code/modules/jobs/job_types/chief_medical_officer.dm
@@ -18,10 +18,10 @@
outfit = /datum/outfit/job/cmo
- access = list(ACCESS_MEDICAL, ACCESS_MORGUE, ACCESS_GENETICS, ACCESS_CLONING, ACCESS_HEADS, ACCESS_MINERAL_STOREROOM,
+ access = list(ACCESS_MEDICAL, ACCESS_MORGUE, ACCESS_GENETICS, ACCESS_CLONING, ACCESS_APOTHECARY, ACCESS_HEADS, ACCESS_MINERAL_STOREROOM,
ACCESS_CHEMISTRY, ACCESS_VIROLOGY, ACCESS_CMO, ACCESS_SURGERY, ACCESS_RC_ANNOUNCE, ACCESS_MECH_MEDICAL,
ACCESS_KEYCARD_AUTH, ACCESS_SEC_DOORS, ACCESS_MAINT_TUNNELS)
- minimal_access = list(ACCESS_MEDICAL, ACCESS_MORGUE, ACCESS_GENETICS, ACCESS_CLONING, ACCESS_HEADS, ACCESS_MINERAL_STOREROOM,
+ minimal_access = list(ACCESS_MEDICAL, ACCESS_MORGUE, ACCESS_GENETICS, ACCESS_CLONING, ACCESS_APOTHECARY, ACCESS_HEADS, ACCESS_MINERAL_STOREROOM,
ACCESS_CHEMISTRY, ACCESS_VIROLOGY, ACCESS_CMO, ACCESS_SURGERY, ACCESS_RC_ANNOUNCE, ACCESS_MECH_MEDICAL,
ACCESS_KEYCARD_AUTH, ACCESS_SEC_DOORS, ACCESS_MAINT_TUNNELS)
paycheck = PAYCHECK_COMMAND
diff --git a/code/modules/jobs/job_types/medical_doctor.dm b/code/modules/jobs/job_types/medical_doctor.dm
index a9af5b47b61..82f7d319ba6 100644
--- a/code/modules/jobs/job_types/medical_doctor.dm
+++ b/code/modules/jobs/job_types/medical_doctor.dm
@@ -11,8 +11,8 @@
outfit = /datum/outfit/job/doctor
- access = list(ACCESS_MEDICAL, ACCESS_MORGUE, ACCESS_SURGERY, ACCESS_CHEMISTRY, ACCESS_GENETICS, ACCESS_CLONING, ACCESS_VIROLOGY, ACCESS_MECH_MEDICAL, ACCESS_MINERAL_STOREROOM)
- minimal_access = list(ACCESS_MEDICAL, ACCESS_MORGUE, ACCESS_SURGERY, ACCESS_CLONING, ACCESS_MECH_MEDICAL, ACCESS_MINERAL_STOREROOM)
+ access = list(ACCESS_MEDICAL, ACCESS_MORGUE, ACCESS_SURGERY, ACCESS_APOTHECARY, ACCESS_CHEMISTRY, ACCESS_GENETICS, ACCESS_CLONING, ACCESS_VIROLOGY, ACCESS_MECH_MEDICAL, ACCESS_MINERAL_STOREROOM)
+ minimal_access = list(ACCESS_MEDICAL, ACCESS_MORGUE, ACCESS_SURGERY, ACCESS_CLONING, ACCESS_MECH_MEDICAL, ACCESS_MINERAL_STOREROOM, ACCESS_APOTHECARY)
paycheck = PAYCHECK_MEDIUM
paycheck_department = ACCOUNT_MED
diff --git a/code/modules/language/language_holder.dm b/code/modules/language/language_holder.dm
index c1a336eb69c..2f07b6c529c 100644
--- a/code/modules/language/language_holder.dm
+++ b/code/modules/language/language_holder.dm
@@ -110,10 +110,6 @@
/datum/language_holder/swarmer
languages = list(/datum/language/swarmer)
-/datum/language_holder/clockmob
- languages = list(/datum/language/common, /datum/language/ratvar)
- only_speaks_language = /datum/language/ratvar
-
/datum/language_holder/construct
languages = list(/datum/language/common, /datum/language/narsie)
diff --git a/code/modules/language/ratvarian.dm b/code/modules/language/ratvarian.dm
deleted file mode 100644
index b924d2fc79d..00000000000
--- a/code/modules/language/ratvarian.dm
+++ /dev/null
@@ -1,19 +0,0 @@
-/datum/language/ratvar
- name = "Ratvarian"
- desc = "A timeless language full of power and incomprehensible to the unenlightened."
- var/static/random_speech_verbs = list("clanks", "clinks", "clunks", "clangs")
- ask_verb = "requests"
- exclaim_verb = "proclaims"
- whisper_verb = "imparts"
- key = "r"
- default_priority = 10
- spans = list(SPAN_ROBOT)
- icon_state = "ratvar"
-
-/datum/language/ratvar/scramble(var/input)
- . = text2ratvar(input)
-
-/datum/language/ratvar/get_spoken_verb(msg_end)
- if(!msg_end)
- return pick(random_speech_verbs)
- return ..()
\ No newline at end of file
diff --git a/code/modules/library/lib_machines.dm b/code/modules/library/lib_machines.dm
index 880d04b5cf2..bcafa426367 100644
--- a/code/modules/library/lib_machines.dm
+++ b/code/modules/library/lib_machines.dm
@@ -26,7 +26,6 @@
var/category = "Any"
var/author
var/SQLquery
- clockwork = TRUE //it'd look weird
/obj/machinery/computer/libraryconsole/ui_interact(mob/user)
. = ..()
@@ -323,13 +322,8 @@ GLOBAL_LIST(cachedbooks) // List of our cached book datums
return null
/obj/machinery/computer/libraryconsole/bookmanagement/proc/print_forbidden_lore(mob/user)
- if (prob(50))
- new /obj/item/melee/cultblade/dagger(get_turf(src))
- to_chat(user, "Your sanity barely endures the seconds spent in the vault's browsing window. The only thing to remind you of this when you stop browsing is a sinister dagger sitting on the desk. You don't even remember where it came from...")
- else
- new /obj/item/clockwork/slab(get_turf(src))
- to_chat(user, "Your sanity barely endures the seconds spent in the vault's browsing window. The only thing to remind you of this when you stop browsing is a strange metal tablet sitting on the desk. You don't even remember where it came from...")
-
+ new /obj/item/melee/cultblade/dagger(get_turf(src))
+ to_chat(user, "Your sanity barely endures the seconds spent in the vault's browsing window. The only thing to remind you of this when you stop browsing is a sinister dagger sitting on the desk. You don't even remember where it came from...")
user.visible_message("[user] stares at the blank screen for a few moments, [user.p_their()] expression frozen in fear. When [user.p_they()] finally awaken[user.p_s()] from it, [user.p_they()] look[user.p_s()] a lot older.", 2)
/obj/machinery/computer/libraryconsole/bookmanagement/attackby(obj/item/W, mob/user, params)
diff --git a/code/modules/mining/aux_base.dm b/code/modules/mining/aux_base.dm
index 4e813397480..2fac34cebe4 100644
--- a/code/modules/mining/aux_base.dm
+++ b/code/modules/mining/aux_base.dm
@@ -23,7 +23,6 @@ interface with the mining shuttle at the landing site if a mobile beacon is also
req_one_access = list(ACCESS_CARGO, ACCESS_CONSTRUCTION, ACCESS_HEADS, ACCESS_RESEARCH)
var/possible_destinations
- clockwork = TRUE
circuit = /obj/item/circuitboard/computer/auxillary_base
/obj/machinery/computer/auxillary_base/Initialize()
diff --git a/code/modules/mining/lavaland/necropolis_chests.dm b/code/modules/mining/lavaland/necropolis_chests.dm
index 673329049c9..44376fb01be 100644
--- a/code/modules/mining/lavaland/necropolis_chests.dm
+++ b/code/modules/mining/lavaland/necropolis_chests.dm
@@ -252,10 +252,7 @@
if(!MM.active_owner)
if(ishuman(owner))
MM.memento(owner)
- else
- to_chat(owner, "You try to free your lifeforce from the pendant...")
- if(do_after(owner, 40, target = owner))
- MM.mori()
+ Remove(MM.active_owner) //Remove the action button, since there's no real use in having it now.
//Wisp Lantern
/obj/item/wisp_lantern
@@ -647,7 +644,7 @@
to_chat(user, "You unfold the ladder. It extends much farther than you were expecting.")
var/last_ladder = null
for(var/i in 1 to world.maxz)
- if(is_centcom_level(i) || is_reserved_level(i) || is_reebe(i) || is_away_level(i))
+ if(is_centcom_level(i) || is_reserved_level(i) || is_away_level(i))
continue
var/turf/T2 = locate(ladder_x, ladder_y, i)
last_ladder = new /obj/structure/ladder/unbreakable/jacob(T2, null, last_ladder)
diff --git a/code/modules/mob/dead/observer/observer.dm b/code/modules/mob/dead/observer/observer.dm
index cac7db45299..56f55517fa9 100644
--- a/code/modules/mob/dead/observer/observer.dm
+++ b/code/modules/mob/dead/observer/observer.dm
@@ -149,12 +149,6 @@ GLOBAL_VAR_INIT(observer_default_invisibility, INVISIBILITY_OBSERVER)
animate(src, color = old_color, time = 10, flags = ANIMATION_PARALLEL)
addtimer(CALLBACK(src, /atom/proc/update_atom_colour), 10)
-/mob/dead/observer/ratvar_act()
- var/old_color = color
- color = "#FAE48C"
- animate(src, color = old_color, time = 10, flags = ANIMATION_PARALLEL)
- addtimer(CALLBACK(src, /atom/proc/update_atom_colour), 10)
-
/mob/dead/observer/Destroy()
GLOB.ghost_images_default -= ghostimage_default
QDEL_NULL(ghostimage_default)
diff --git a/code/modules/mob/living/brain/say.dm b/code/modules/mob/living/brain/say.dm
index 8fd178ea1db..1c46fb67a87 100644
--- a/code/modules/mob/living/brain/say.dm
+++ b/code/modules/mob/living/brain/say.dm
@@ -24,11 +24,4 @@
/mob/living/brain/treat_message(message)
message = capitalize(message)
- return message
-
-/mob/living/brain/could_speak_in_language(datum/language/dt)
- if(istype(container, /obj/item/mmi/posibrain/soul_vessel))
- // soul vessels can only speak ratvarian.
- . = ispath(dt, /datum/language/ratvar)
- else
- . = ..()
+ return message
\ No newline at end of file
diff --git a/code/modules/mob/living/carbon/alien/humanoid/humanoid.dm b/code/modules/mob/living/carbon/alien/humanoid/humanoid.dm
index c3c80610961..fa591b2a528 100644
--- a/code/modules/mob/living/carbon/alien/humanoid/humanoid.dm
+++ b/code/modules/mob/living/carbon/alien/humanoid/humanoid.dm
@@ -21,6 +21,9 @@
bodyparts = list(/obj/item/bodypart/chest/alien, /obj/item/bodypart/head/alien, /obj/item/bodypart/l_arm/alien,
/obj/item/bodypart/r_arm/alien, /obj/item/bodypart/r_leg/alien, /obj/item/bodypart/l_leg/alien)
+/mob/living/carbon/alien/humanoid/Initialize()
+ . = ..()
+ AddComponent(/datum/component/footstep, FOOTSTEP_MOB_CLAW, 0.5, -3)
/mob/living/carbon/alien/humanoid/restrained(ignore_grab)
return handcuffed
diff --git a/code/modules/mob/living/carbon/carbon.dm b/code/modules/mob/living/carbon/carbon.dm
index 6abb63ed852..7f1455fcdb0 100644
--- a/code/modules/mob/living/carbon/carbon.dm
+++ b/code/modules/mob/living/carbon/carbon.dm
@@ -19,9 +19,6 @@
QDEL_NULL(dna)
GLOB.carbon_list -= src
-/mob/living/carbon/initialize_footstep()
- AddComponent(/datum/component/footstep, 1, 2)
-
/mob/living/carbon/swap_hand(held_index)
if(!held_index)
held_index = (active_hand_index % held_items.len)+1
diff --git a/code/modules/mob/living/carbon/human/human.dm b/code/modules/mob/living/carbon/human/human.dm
index bfcdadfe32e..b094f67572a 100644
--- a/code/modules/mob/living/carbon/human/human.dm
+++ b/code/modules/mob/living/carbon/human/human.dm
@@ -27,7 +27,7 @@
RegisterSignal(src, COMSIG_COMPONENT_CLEAN_ACT, .proc/clean_blood)
AddComponent(/datum/component/personal_crafting)
-
+ AddComponent(/datum/component/footstep, FOOTSTEP_MOB_HUMAN, 1, 2)
GLOB.human_list += src
/mob/living/carbon/human/proc/setup_human_dna()
@@ -1163,12 +1163,6 @@
/mob/living/carbon/human/species/golem/snow
race = /datum/species/golem/snow
-/mob/living/carbon/human/species/golem/clockwork
- race = /datum/species/golem/clockwork
-
-/mob/living/carbon/human/species/golem/clockwork/no_scrap
- race = /datum/species/golem/clockwork/no_scrap
-
/mob/living/carbon/human/species/golem/capitalist
race = /datum/species/golem/capitalist
diff --git a/code/modules/mob/living/carbon/human/species_types/golems.dm b/code/modules/mob/living/carbon/human/species_types/golems.dm
index b6a3bf70375..467d6152486 100644
--- a/code/modules/mob/living/carbon/human/species_types/golems.dm
+++ b/code/modules/mob/living/carbon/human/species_types/golems.dm
@@ -629,60 +629,6 @@
H.adjustFireLoss(-4)
H.reagents.remove_reagent(chem.type, REAGENTS_METABOLISM)
-
-/datum/species/golem/clockwork
- name = "Clockwork Golem"
- id = "clockwork golem"
- say_mod = "clicks"
- limbs_id = "clockgolem"
- info_text = "As a Clockwork Golem, you are faster than other types of golems. On death, you will break down into scrap."
- species_traits = list(NOBLOOD,NO_UNDERWEAR,NOEYESPRITES)
- inherent_traits = list(TRAIT_NOFLASH,TRAIT_RESISTHEAT,TRAIT_NOBREATH,TRAIT_RESISTCOLD,TRAIT_RESISTHIGHPRESSURE,TRAIT_RESISTLOWPRESSURE,TRAIT_NOFIRE,TRAIT_CHUNKYFINGERS,TRAIT_RADIMMUNE,TRAIT_PIERCEIMMUNE,TRAIT_NODISMEMBER)
- inherent_biotypes = MOB_ROBOTIC|MOB_HUMANOID
- armor = 20 //Reinforced, but much less so to allow for fast movement
- attack_verb = "smash"
- attack_sound = 'sound/magic/clockwork/anima_fragment_attack.ogg'
- sexes = FALSE
- speedmod = 0
- changesource_flags = MIRROR_BADMIN | WABBAJACK
- damage_overlay_type = "synth"
- prefix = "Clockwork"
- special_names = list("Remnant", "Relic", "Scrap", "Vestige") //RIP Ratvar
- inherent_factions = list("ratvar")
- var/has_corpse
-
-/datum/species/golem/clockwork/on_species_gain(mob/living/carbon/human/H)
- . = ..()
- RegisterSignal(H, COMSIG_MOB_SAY, .proc/handle_speech)
-
-/datum/species/golem/clockwork/on_species_loss(mob/living/carbon/human/H)
- UnregisterSignal(H, COMSIG_MOB_SAY)
- . = ..()
-
-/datum/species/golem/clockwork/proc/handle_speech(datum/source, list/speech_args)
- speech_args[SPEECH_SPANS] |= SPAN_ROBOT //beep
-
-/datum/species/golem/clockwork/spec_death(gibbed, mob/living/carbon/human/H)
- gibbed = !has_corpse ? FALSE : gibbed
- . = ..()
- if(!has_corpse)
- var/turf/T = get_turf(H)
- H.visible_message("[H]'s exoskeleton shatters, collapsing into a heap of scrap!")
- playsound(H, 'sound/magic/clockwork/anima_fragment_death.ogg', 62, TRUE)
- for(var/i in 1 to rand(3, 5))
- new/obj/item/clockwork/alloy_shards/small(T)
- new/obj/item/clockwork/alloy_shards/clockgolem_remains(T)
- qdel(H)
-
-/datum/species/golem/clockwork/no_scrap //These golems are created through the herald's beacon and leave normal corpses on death.
- id = "clockwork golem servant"
- armor = 15 //Balance reasons make this armor weak
- no_equip = list()
- nojumpsuit = FALSE
- has_corpse = TRUE
- random_eligible = FALSE
- info_text = "As a Clockwork Golem Servant, you are faster than other types of golems." //warcult golems leave a corpse
-
/datum/species/golem/cloth
name = "Cloth Golem"
id = "cloth golem"
diff --git a/code/modules/mob/living/carbon/human/species_types/synths.dm b/code/modules/mob/living/carbon/human/species_types/synths.dm
index 724a08cd516..cc06d97e766 100644
--- a/code/modules/mob/living/carbon/human/species_types/synths.dm
+++ b/code/modules/mob/living/carbon/human/species_types/synths.dm
@@ -125,8 +125,6 @@
if (isliving(source)) // yeah it's gonna be living but just to be clean
var/mob/living/L = source
if(fake_species && L.health > disguise_fail_health)
- switch (fake_species.type)
+ switch(fake_species.type)
if (/datum/species/golem/bananium)
- speech_args[SPEECH_SPANS] |= SPAN_CLOWN
- if (/datum/species/golem/clockwork)
- speech_args[SPEECH_SPANS] |= SPAN_ROBOT
+ speech_args[SPEECH_SPANS] |= SPAN_CLOWN
\ No newline at end of file
diff --git a/code/modules/mob/living/carbon/monkey/monkey.dm b/code/modules/mob/living/carbon/monkey/monkey.dm
index 2d3cd7b0429..59014009e43 100644
--- a/code/modules/mob/living/carbon/monkey/monkey.dm
+++ b/code/modules/mob/living/carbon/monkey/monkey.dm
@@ -40,6 +40,7 @@
create_dna(src)
dna.initialize_dna(random_blood_type())
+ AddComponent(/datum/component/footstep, FOOTSTEP_MOB_BAREFOOT, 1, 2)
/mob/living/carbon/monkey/Destroy()
SSmobs.cubemonkeys -= src
diff --git a/code/modules/mob/living/living.dm b/code/modules/mob/living/living.dm
index 5869a412cd2..c763ddabbc8 100644
--- a/code/modules/mob/living/living.dm
+++ b/code/modules/mob/living/living.dm
@@ -9,10 +9,6 @@
diag_hud.add_to_hud(src)
faction += "[REF(src)]"
GLOB.mob_living_list += src
- initialize_footstep()
-
-/mob/living/proc/initialize_footstep()
- AddComponent(/datum/component/footstep)
/mob/living/prepare_huds()
..()
diff --git a/code/modules/mob/living/living_defense.dm b/code/modules/mob/living/living_defense.dm
index 8d75521f80f..1c12ff52811 100644
--- a/code/modules/mob/living/living_defense.dm
+++ b/code/modules/mob/living/living_defense.dm
@@ -376,12 +376,6 @@
if(status_flags & GODMODE || QDELETED(src))
return
- if(is_servant_of_ratvar(src) && !stat)
- to_chat(src, "You resist Nar'Sie's influence... but not all of it. Run!")
- adjustBruteLoss(35)
- if(src && reagents)
- reagents.add_reagent(/datum/reagent/toxin/heparin, 5)
- return FALSE
if(GLOB.cult_narsie && GLOB.cult_narsie.souls_needed[src])
GLOB.cult_narsie.souls_needed -= src
GLOB.cult_narsie.souls += 1
@@ -404,17 +398,6 @@
gib()
return TRUE
-
-/mob/living/ratvar_act()
- if(status_flags & GODMODE)
- return
- if(stat != DEAD && !is_servant_of_ratvar(src))
- to_chat(src, "A blinding light boils you alive! Run!")
- adjust_fire_stacks(20)
- IgniteMob()
- return FALSE
-
-
//called when the mob receives a bright flash
/mob/living/proc/flash_act(intensity = 1, override_blindness_check = 0, affect_silicon = 0, visual = 0, type = /obj/screen/fullscreen/flash)
if(HAS_TRAIT(src, TRAIT_NOFLASH))
diff --git a/code/modules/mob/living/silicon/ai/ai.dm b/code/modules/mob/living/silicon/ai/ai.dm
index 234eda02330..9163565da4d 100644
--- a/code/modules/mob/living/silicon/ai/ai.dm
+++ b/code/modules/mob/living/silicon/ai/ai.dm
@@ -714,7 +714,8 @@
"default" = 'icons/mob/ai.dmi',
"floating face" = 'icons/mob/ai.dmi',
"xeno queen" = 'icons/mob/alien.dmi',
- "horror" = 'icons/mob/ai.dmi'
+ "horror" = 'icons/mob/ai.dmi',
+ "clock" = 'icons/mob/ai.dmi'
)
input = input("Please select a hologram:") as null|anything in icon_list
diff --git a/code/modules/mob/living/silicon/ai/life.dm b/code/modules/mob/living/silicon/ai/life.dm
index d22b00361f9..39268fd4cf8 100644
--- a/code/modules/mob/living/silicon/ai/life.dm
+++ b/code/modules/mob/living/silicon/ai/life.dm
@@ -58,10 +58,6 @@
return FALSE
if(POWER_REQ_ALL)
return !T || !A || ((!A.power_equip || isspaceturf(T)) && !is_type_in_list(loc, list(/obj/item, /obj/mecha)))
- if(POWER_REQ_CLOCKCULT)
- for(var/obj/effect/clockwork/sigil/transmission/ST in range(src, SIGIL_ACCESS_RANGE))
- return FALSE
- return !T || !A || (!istype(T, /turf/open/floor/clockwork) && (!A.power_equip || isspaceturf(T)) && !is_type_in_list(loc, list(/obj/item, /obj/mecha)))
/mob/living/silicon/ai/updatehealth()
if(status_flags & GODMODE)
diff --git a/code/modules/mob/living/silicon/ai/say.dm b/code/modules/mob/living/silicon/ai/say.dm
index e736efd251c..e2bdea92c5d 100644
--- a/code/modules/mob/living/silicon/ai/say.dm
+++ b/code/modules/mob/living/silicon/ai/say.dm
@@ -161,10 +161,3 @@
#undef VOX_DELAY
#endif
-
-/mob/living/silicon/ai/could_speak_in_language(datum/language/dt)
- if(is_servant_of_ratvar(src))
- // Ratvarian AIs can only speak Ratvarian
- . = ispath(dt, /datum/language/ratvar)
- else
- . = ..()
diff --git a/code/modules/mob/living/silicon/robot/examine.dm b/code/modules/mob/living/silicon/robot/examine.dm
index 4e062910ff9..8fdb8643be2 100644
--- a/code/modules/mob/living/silicon/robot/examine.dm
+++ b/code/modules/mob/living/silicon/robot/examine.dm
@@ -33,9 +33,6 @@
if(cell && cell.charge <= 0)
. += "Its battery indicator is blinking red!"
- if(is_servant_of_ratvar(src) && get_dist(user, src) <= 1 && !stat) //To counter pseudo-stealth by using headlamps
- . += "Its eyes are glowing a blazing yellow!"
-
switch(stat)
if(CONSCIOUS)
if(shell)
diff --git a/code/modules/mob/living/silicon/robot/robot.dm b/code/modules/mob/living/silicon/robot/robot.dm
index fcd8aa6a7a5..d3109fc5302 100644
--- a/code/modules/mob/living/silicon/robot/robot.dm
+++ b/code/modules/mob/living/silicon/robot/robot.dm
@@ -600,7 +600,7 @@
if(lamp_intensity > 2)
eye_lights.icon_state = "[module.special_light_key ? "[module.special_light_key]":"[module.cyborg_base_icon]"]_l"
else
- eye_lights.icon_state = "[module.special_light_key ? "[module.special_light_key]":"[module.cyborg_base_icon]"]_e[is_servant_of_ratvar(src) ? "_r" : ""]"
+ eye_lights.icon_state = "[module.special_light_key ? "[module.special_light_key]":"[module.cyborg_base_icon]"]_e"
eye_lights.icon = icon
add_overlay(eye_lights)
diff --git a/code/modules/mob/living/silicon/robot/robot_defense.dm b/code/modules/mob/living/silicon/robot/robot_defense.dm
index d28b6e4f072..09c9a659e32 100644
--- a/code/modules/mob/living/silicon/robot/robot_defense.dm
+++ b/code/modules/mob/living/silicon/robot/robot_defense.dm
@@ -115,12 +115,6 @@ GLOBAL_LIST_INIT(blacklisted_borg_hats, typecacheof(list( //Hats that don't real
to_chat(user, "You emag [src]'s interface.")
emag_cooldown = world.time + 100
- if(is_servant_of_ratvar(src))
- to_chat(src, "\"[text2ratvar("You will serve Engine above all else")]!\"\n\
- ALERT: Subversion attempt denied.")
- log_game("[key_name(user)] attempted to emag cyborg [key_name(src)], but they serve only Ratvar.")
- return
-
if(connected_ai && connected_ai.mind && connected_ai.mind.has_antag_datum(/datum/antagonist/traitor))
to_chat(src, "ALERT: Foreign software execution prevented.")
to_chat(connected_ai, "ALERT: Cyborg unit \[[src]] successfully defended against subversion.")
diff --git a/code/modules/mob/living/silicon/robot/robot_modules.dm b/code/modules/mob/living/silicon/robot/robot_modules.dm
index e473a229337..0b76ed5a024 100644
--- a/code/modules/mob/living/silicon/robot/robot_modules.dm
+++ b/code/modules/mob/living/silicon/robot/robot_modules.dm
@@ -10,7 +10,6 @@
var/list/basic_modules = list() //a list of paths, converted to a list of instances on New()
var/list/emag_modules = list() //ditto
- var/list/ratvar_modules = list() //ditto ditto
var/list/modules = list() //holds all the usable modules
var/list/added_modules = list() //modules not inherient to the robot module, are kept when the module changes
var/list/storages = list()
@@ -44,15 +43,10 @@
var/obj/item/I = new i(src)
emag_modules += I
emag_modules -= i
- for(var/i in ratvar_modules)
- var/obj/item/I = new i(src)
- ratvar_modules += I
- ratvar_modules -= i
/obj/item/robot_module/Destroy()
basic_modules.Cut()
emag_modules.Cut()
- ratvar_modules.Cut()
modules.Cut()
added_modules.Cut()
storages.Cut()
@@ -137,7 +131,6 @@
basic_modules -= I
modules -= I
emag_modules -= I
- ratvar_modules -= I
added_modules -= I
rebuild_modules()
if(delete_after)
@@ -174,9 +167,6 @@
if(R.emagged)
for(var/obj/item/I in emag_modules)
add_module(I, FALSE, FALSE)
- if(is_servant_of_ratvar(R))
- for(var/obj/item/I in ratvar_modules)
- add_module(I, FALSE, FALSE)
for(var/obj/item/I in added_modules)
add_module(I, FALSE, FALSE)
for(var/i in held_modules)
@@ -256,10 +246,6 @@
/obj/item/soap/nanotrasen,
/obj/item/borg/cyborghug)
emag_modules = list(/obj/item/melee/transforming/energy/sword/cyborg)
- ratvar_modules = list(
- /obj/item/clockwork/slab/cyborg,
- /obj/item/clockwork/weapon/ratvarian_spear,
- /obj/item/clockwork/replica_fabricator/cyborg)
moduleselect_icon = "standard"
hat_offset = -3
@@ -286,9 +272,6 @@
/obj/item/organ_storage,
/obj/item/borg/lollipop)
emag_modules = list(/obj/item/reagent_containers/borghypo/hacked)
- ratvar_modules = list(
- /obj/item/clockwork/slab/cyborg/medical,
- /obj/item/clockwork/weapon/ratvarian_spear)
cyborg_base_icon = "medical"
moduleselect_icon = "medical"
can_be_pushed = FALSE
@@ -321,9 +304,6 @@
/obj/item/stack/tile/plasteel/cyborg,
/obj/item/stack/cable_coil/cyborg)
emag_modules = list(/obj/item/borg/stun)
- ratvar_modules = list(
- /obj/item/clockwork/slab/cyborg/engineer,
- /obj/item/clockwork/replica_fabricator/cyborg)
cyborg_base_icon = "engineer"
moduleselect_icon = "engineer"
magpulsing = TRUE
@@ -339,8 +319,6 @@
/obj/item/clothing/mask/gas/sechailer/cyborg,
/obj/item/extinguisher/mini)
emag_modules = list(/obj/item/gun/energy/laser/cyborg)
- ratvar_modules = list(/obj/item/clockwork/slab/cyborg/security,
- /obj/item/clockwork/weapon/ratvarian_spear)
cyborg_base_icon = "sec"
moduleselect_icon = "security"
can_be_pushed = FALSE
@@ -374,9 +352,6 @@
/obj/item/extinguisher,
/obj/item/borg/projectile_dampen)
emag_modules = list(/obj/item/reagent_containers/borghypo/peace/hacked)
- ratvar_modules = list(
- /obj/item/clockwork/slab/cyborg/peacekeeper,
- /obj/item/clockwork/weapon/ratvarian_spear)
cyborg_base_icon = "peace"
moduleselect_icon = "standard"
can_be_pushed = FALSE
@@ -405,9 +380,6 @@
/obj/item/holosign_creator/janibarrier,
/obj/item/reagent_containers/spray/cyborg_drying)
emag_modules = list(/obj/item/reagent_containers/spray/cyborg_lube)
- ratvar_modules = list(
- /obj/item/clockwork/slab/cyborg/janitor,
- /obj/item/clockwork/replica_fabricator/cyborg)
cyborg_base_icon = "janitor"
moduleselect_icon = "janitor"
hat_offset = -5
@@ -460,10 +432,6 @@
emag_modules = list(
/obj/item/reagent_containers/borghypo/clown/hacked,
/obj/item/reagent_containers/spray/waterflower/cyborg/hacked)
- ratvar_modules = list(
- /obj/item/clockwork/slab/cyborg,
- /obj/item/clockwork/weapon/ratvarian_spear,
- /obj/item/clockwork/replica_fabricator/cyborg)
moduleselect_icon = "service"
cyborg_base_icon = "clown"
hat_offset = -2
@@ -489,8 +457,6 @@
/obj/item/borg/lollipop,
/obj/item/stack/pipe_cleaner_coil/cyborg)
emag_modules = list(/obj/item/reagent_containers/borghypo/borgshaker/hacked)
- ratvar_modules = list(/obj/item/clockwork/slab/cyborg/service,
- /obj/item/borg/sight/xray/truesight_lens)
moduleselect_icon = "service"
special_light_key = "service"
hat_offset = 0
@@ -539,10 +505,6 @@
/obj/item/gps/cyborg,
/obj/item/stack/marker_beacon)
emag_modules = list(/obj/item/borg/stun)
- ratvar_modules = list(
- /obj/item/clockwork/slab/cyborg/miner,
- /obj/item/clockwork/weapon/ratvarian_spear,
- /obj/item/borg/sight/xray/truesight_lens)
cyborg_base_icon = "miner"
moduleselect_icon = "miner"
hat_offset = 0
@@ -569,9 +531,6 @@
/obj/item/extinguisher/mini,
/obj/item/pinpointer/syndicate_cyborg)
- ratvar_modules = list(
- /obj/item/clockwork/slab/cyborg/security,
- /obj/item/clockwork/weapon/ratvarian_spear)
cyborg_base_icon = "synd_sec"
moduleselect_icon = "malf"
can_be_pushed = FALSE
@@ -609,9 +568,7 @@
/obj/item/stack/medical/gauze/cyborg,
/obj/item/gun/medbeam,
/obj/item/organ_storage)
- ratvar_modules = list(
- /obj/item/clockwork/slab/cyborg/medical,
- /obj/item/clockwork/weapon/ratvarian_spear)
+
cyborg_base_icon = "synd_medical"
moduleselect_icon = "malf"
can_be_pushed = FALSE
@@ -642,9 +599,7 @@
/obj/item/pinpointer/syndicate_cyborg,
/obj/item/borg_chameleon,
)
- ratvar_modules = list(
- /obj/item/clockwork/slab/cyborg/engineer,
- /obj/item/clockwork/replica_fabricator/cyborg)
+
cyborg_base_icon = "synd_engi"
moduleselect_icon = "malf"
can_be_pushed = FALSE
diff --git a/code/modules/mob/living/simple_animal/bot/ed209bot.dm b/code/modules/mob/living/simple_animal/bot/ed209bot.dm
index bb94d59deb9..7f410619a00 100644
--- a/code/modules/mob/living/simple_animal/bot/ed209bot.dm
+++ b/code/modules/mob/living/simple_animal/bot/ed209bot.dm
@@ -18,7 +18,6 @@
var/shoot_sound = 'sound/weapons/laser.ogg'
var/projectile = /obj/projectile/beam/disabler
var/fair_market_projectile = /obj/projectile/bullet/c38 // For shooting the worst scumbags of all: the poor
- do_footstep = TRUE
/mob/living/simple_animal/bot/secbot/ed209/Initialize(mapload)
. = ..()
diff --git a/code/modules/mob/living/simple_animal/friendly/cat.dm b/code/modules/mob/living/simple_animal/friendly/cat.dm
index d5c3cbf0185..26e8bb04c5f 100644
--- a/code/modules/mob/living/simple_animal/friendly/cat.dm
+++ b/code/modules/mob/living/simple_animal/friendly/cat.dm
@@ -35,7 +35,7 @@
gold_core_spawnable = FRIENDLY_SPAWN
collar_type = "cat"
- do_footstep = TRUE
+ footstep_type = FOOTSTEP_MOB_CLAW
/mob/living/simple_animal/pet/cat/Initialize()
. = ..()
diff --git a/code/modules/mob/living/simple_animal/friendly/dog.dm b/code/modules/mob/living/simple_animal/friendly/dog.dm
index 039fe5a45d8..7ecf998bd9f 100644
--- a/code/modules/mob/living/simple_animal/friendly/dog.dm
+++ b/code/modules/mob/living/simple_animal/friendly/dog.dm
@@ -16,8 +16,64 @@
see_in_dark = 5
speak_chance = 1
turns_per_move = 10
+ var/turns_since_scan = 0
+ var/obj/movement_target
- do_footstep = TRUE
+ footstep_type = FOOTSTEP_MOB_CLAW
+
+/mob/living/simple_animal/pet/dog/Life()
+ ..()
+
+ //Feeding, chasing food, FOOOOODDDD
+ if(!stat && !resting && !buckled)
+ turns_since_scan++
+ if(turns_since_scan > 5)
+ turns_since_scan = 0
+ if((movement_target) && !(isturf(movement_target.loc) || ishuman(movement_target.loc) ))
+ movement_target = null
+ stop_automated_movement = 0
+ if( !movement_target || !(movement_target.loc in oview(src, 3)) )
+ movement_target = null
+ stop_automated_movement = 0
+ for(var/obj/item/reagent_containers/food/snacks/S in oview(src,3))
+ if(isturf(S.loc) || ishuman(S.loc))
+ movement_target = S
+ break
+ if(movement_target)
+ stop_automated_movement = 1
+ step_to(src,movement_target,1)
+ sleep(3)
+ step_to(src,movement_target,1)
+ sleep(3)
+ step_to(src,movement_target,1)
+
+ if(movement_target) //Not redundant due to sleeps, Item can be gone in 6 decisecomds
+ if (movement_target.loc.x < src.x)
+ setDir(WEST)
+ else if (movement_target.loc.x > src.x)
+ setDir(EAST)
+ else if (movement_target.loc.y < src.y)
+ setDir(SOUTH)
+ else if (movement_target.loc.y > src.y)
+ setDir(NORTH)
+ else
+ setDir(SOUTH)
+
+ if(!Adjacent(movement_target)) //can't reach food through windows.
+ return
+
+ if(isturf(movement_target.loc) )
+ movement_target.attack_animal(src)
+ else if(ishuman(movement_target.loc) )
+ if(prob(20))
+ emote("me", 1, "stares at [movement_target.loc]'s [movement_target] with a sad puppy-face")
+
+ if(prob(1))
+ emote("me", 1, pick("dances around.","chases its tail!"))
+ spawn(0)
+ for(var/i in list(1,2,4,8,4,2,1,2,4,8,4,2,1,2,4,8,4,2))
+ setDir(i)
+ sleep(1)
//Corgis and pugs are now under one dog subtype
@@ -333,8 +389,6 @@
real_name = "Ian" //Intended to hold the name without altering it.
gender = MALE
desc = "It's the HoP's beloved corgi."
- var/turns_since_scan = 0
- var/obj/movement_target
response_help_continuous = "pets"
response_help_simple = "pet"
response_disarm_continuous = "bops"
@@ -423,60 +477,6 @@
fdel(json_file)
WRITE_FILE(json_file, json_encode(file_data))
-/mob/living/simple_animal/pet/dog/corgi/Ian/Life()
- ..()
-
- //Feeding, chasing food, FOOOOODDDD
- if(!stat && !resting && !buckled)
- turns_since_scan++
- if(turns_since_scan > 5)
- turns_since_scan = 0
- if((movement_target) && !(isturf(movement_target.loc) || ishuman(movement_target.loc) ))
- movement_target = null
- stop_automated_movement = 0
- if( !movement_target || !(movement_target.loc in oview(src, 3)) )
- movement_target = null
- stop_automated_movement = 0
- for(var/obj/item/reagent_containers/food/snacks/S in oview(src,3))
- if(isturf(S.loc) || ishuman(S.loc))
- movement_target = S
- break
- if(movement_target)
- stop_automated_movement = 1
- step_to(src,movement_target,1)
- sleep(3)
- step_to(src,movement_target,1)
- sleep(3)
- step_to(src,movement_target,1)
-
- if(movement_target) //Not redundant due to sleeps, Item can be gone in 6 decisecomds
- if (movement_target.loc.x < src.x)
- setDir(WEST)
- else if (movement_target.loc.x > src.x)
- setDir(EAST)
- else if (movement_target.loc.y < src.y)
- setDir(SOUTH)
- else if (movement_target.loc.y > src.y)
- setDir(NORTH)
- else
- setDir(SOUTH)
-
- if(!Adjacent(movement_target)) //can't reach food through windows.
- return
-
- if(isturf(movement_target.loc) )
- movement_target.attack_animal(src)
- else if(ishuman(movement_target.loc) )
- if(prob(20))
- emote("me", 1, "stares at [movement_target.loc]'s [movement_target] with a sad puppy-face")
-
- if(prob(1))
- emote("me", 1, pick("dances around.","chases its tail!"))
- spawn(0)
- for(var/i in list(1,2,4,8,4,2,1,2,4,8,4,2,1,2,4,8,4,2))
- setDir(i)
- sleep(1)
-
/mob/living/simple_animal/pet/dog/corgi/Ian/narsie_act()
playsound(src, 'sound/magic/demon_dies.ogg', 75, TRUE)
var/mob/living/simple_animal/pet/dog/corgi/narsie/N = new(loc)
@@ -618,7 +618,6 @@
response_disarm_simple = "bop"
response_harm_continuous = "kicks"
response_harm_simple = "kick"
- var/turns_since_scan = 0
var/puppies = 0
//Lisa already has a cute bow!
@@ -633,25 +632,6 @@
make_babies()
- if(!stat && !resting && !buckled)
- if(prob(1))
- emote("me", 1, pick("dances around.","chases her tail."))
- spawn(0)
- for(var/i in list(1,2,4,8,4,2,1,2,4,8,4,2,1,2,4,8,4,2))
- setDir(i)
- sleep(1)
-
-/mob/living/simple_animal/pet/dog/pug/Life()
- ..()
-
- if(!stat && !resting && !buckled)
- if(prob(1))
- emote("me", 1, pick("chases its tail."))
- spawn(0)
- for(var/i in list(1,2,4,8,4,2,1,2,4,8,4,2,1,2,4,8,4,2))
- setDir(i)
- sleep(1)
-
/mob/living/simple_animal/pet/dog/attack_hand(mob/living/carbon/human/M)
. = ..()
switch(M.a_intent)
diff --git a/code/modules/mob/living/simple_animal/friendly/drone/_drone.dm b/code/modules/mob/living/simple_animal/friendly/drone/_drone.dm
index a9d0db7aafb..0b5646fa132 100644
--- a/code/modules/mob/living/simple_animal/friendly/drone/_drone.dm
+++ b/code/modules/mob/living/simple_animal/friendly/drone/_drone.dm
@@ -153,23 +153,6 @@
/mob/living/simple_animal/drone/gib()
dust()
-/mob/living/simple_animal/drone/ratvar_act()
- if(status_flags & GODMODE)
- return
-
- if(internal_storage)
- dropItemToGround(internal_storage)
- if(head)
- dropItemToGround(head)
- var/mob/living/simple_animal/drone/cogscarab/ratvar/R = new /mob/living/simple_animal/drone/cogscarab/ratvar(loc)
- R.setDir(dir)
- if(mind)
- mind.transfer_to(R, 1)
- else
- R.key = key
- qdel(src)
-
-
/mob/living/simple_animal/drone/examine(mob/user)
. = list("*---------*\nThis is [icon2html(src, user)] \a [src]!")
diff --git a/code/modules/mob/living/simple_animal/friendly/drone/extra_drone_types.dm b/code/modules/mob/living/simple_animal/friendly/drone/extra_drone_types.dm
index 9e01e8e8b7a..33420bc78cc 100644
--- a/code/modules/mob/living/simple_animal/friendly/drone/extra_drone_types.dm
+++ b/code/modules/mob/living/simple_animal/friendly/drone/extra_drone_types.dm
@@ -123,114 +123,4 @@
" - Going to the main station in search of materials.\n"+\
" - Interacting with non-drone players outside KS13, dead or alive.\n"+\
"These rules are at admin discretion and will be heavily enforced.\n"+\
- "If you do not have the regular drone laws, follow your laws to the best of your ability."
-
-/mob/living/simple_animal/drone/cogscarab
- name = "cogscarab"
- desc = "A strange, drone-like machine. It constantly emits the hum of gears."
- icon_state = "drone_clock"
- icon_living = "drone_clock"
- icon_dead = "drone_clock_dead"
- picked = TRUE
- pass_flags = PASSTABLE
- health = 50
- maxHealth = 50
- harm_intent_damage = 5
- density = TRUE
- speed = 1
- ventcrawler = VENTCRAWLER_NONE
- faction = list("neutral", "ratvar")
- speak_emote = list("clanks", "clinks", "clunks", "clangs")
- verb_ask = "requests"
- verb_exclaim = "proclaims"
- verb_whisper = "imparts"
- verb_yell = "harangues"
- bubble_icon = "clock"
- initial_language_holder = /datum/language_holder/clockmob
- light_color = "#E42742"
- heavy_emp_damage = 0
- laws = "0. Purge all untruths and honor Ratvar."
- default_storage = /obj/item/storage/toolbox/brass/prefilled
- hacked = TRUE
- visualAppearence = CLOCKDRONE
- can_be_held = FALSE
- flavortext = "You are a cogscarab, a tiny building construct of Ratvar. While you're weak and can't recite scripture, \
- you have a set of quick tools, as well as a replica fabricator that can create brass and convert objects.
Work with the servants of Ratvar \
- to construct and maintain defenses at the City of Cogs. If there are no servants, use this time to experiment with base designs!"
-
-/mob/living/simple_animal/drone/cogscarab/ratvar //a subtype for spawning when ratvar is alive, has a slab that it can use and a normal fabricator
- default_storage = /obj/item/storage/toolbox/brass/prefilled/ratvar
-
-/mob/living/simple_animal/drone/cogscarab/admin //an admin-only subtype of cogscarab with a no-cost fabricator and slab in its box
- default_storage = /obj/item/storage/toolbox/brass/prefilled/ratvar/admin
-
-/mob/living/simple_animal/drone/cogscarab/Initialize()
- . = ..()
- set_light(2, 0.5)
- qdel(access_card) //we don't have free access
- access_card = null
- verbs -= /mob/living/simple_animal/drone/verb/check_laws
- verbs -= /mob/living/simple_animal/drone/verb/drone_ping
-
-/mob/living/simple_animal/drone/cogscarab/Login()
- ..()
- add_servant_of_ratvar(src, TRUE, GLOB.servants_active)
- to_chat(src,"You yourself are one of these servants, and will be able to utilize almost anything they can[GLOB.ratvar_awakens ? "":", excluding a clockwork slab"].") // this can't go with flavortext because i'm assuming it requires them to be ratvar'd
-
-/mob/living/simple_animal/drone/cogscarab/binarycheck()
- return FALSE
-
-/mob/living/simple_animal/drone/cogscarab/alert_drones(msg, dead_can_hear = FALSE)
- if(msg == DRONE_NET_CONNECT)
- msg = "Hierophant Network: [name] activated."
- else if(msg == DRONE_NET_DISCONNECT)
- msg = "Hierophant Network:[name] disabled."
- ..()
-
-/mob/living/simple_animal/drone/attackby(obj/item/I, mob/user)
- if(I.tool_behaviour == TOOL_SCREWDRIVER && stat == DEAD)
- try_reactivate(user)
- else
- ..()
-
-/mob/living/simple_animal/drone/cogscarab/try_reactivate(mob/living/user)
- if(!is_servant_of_ratvar(user))
- to_chat(user, "You fiddle around with [src] to no avail.")
- else
- ..()
-
-/mob/living/simple_animal/drone/cogscarab/can_use_guns(obj/item/G)
- return GLOB.ratvar_awakens
-
-/mob/living/simple_animal/drone/cogscarab/get_armor_effectiveness()
- if(GLOB.ratvar_awakens)
- return 1
- return ..()
-
-/mob/living/simple_animal/drone/cogscarab/triggerAlarm(class, area/A, O, obj/alarmsource)
- return
-
-/mob/living/simple_animal/drone/cogscarab/cancelAlarm(class, area/A, obj/origin)
- return
-
-/mob/living/simple_animal/drone/cogscarab/update_drone_hack()
- return //we don't get hacked or give a shit about it
-
-/mob/living/simple_animal/drone/cogscarab/drone_chat(msg)
- titled_hierophant_message(src, msg, "nezbere", "brass", "Construct") //HIEROPHANT DRONES
-
-/mob/living/simple_animal/drone/cogscarab/ratvar_act()
- fully_heal(TRUE)
-
-/mob/living/simple_animal/drone/cogscarab/update_icons()
- if(stat != DEAD)
- if(incapacitated())
- icon_state = "[visualAppearence]_flipped"
- else
- icon_state = visualAppearence
- else
- icon_state = "[visualAppearence]_dead"
-
-/mob/living/simple_animal/drone/cogscarab/update_mobility()
- . = ..()
- update_icons()
+ "If you do not have the regular drone laws, follow your laws to the best of your ability."
\ No newline at end of file
diff --git a/code/modules/mob/living/simple_animal/friendly/drone/interaction.dm b/code/modules/mob/living/simple_animal/friendly/drone/interaction.dm
index 81b371d0763..b30e7f199f3 100644
--- a/code/modules/mob/living/simple_animal/friendly/drone/interaction.dm
+++ b/code/modules/mob/living/simple_animal/friendly/drone/interaction.dm
@@ -110,32 +110,27 @@
/mob/living/simple_animal/drone/proc/get_armor_effectiveness()
return 0 //multiplier for whatever head armor you wear as a drone
-/mob/living/simple_animal/drone/proc/update_drone_hack(hack, clockwork)
+/mob/living/simple_animal/drone/proc/update_drone_hack(hack)
if(!mind)
return
if(hack)
if(hacked)
return
Stun(40)
- if(clockwork)
- to_chat(src, "ERROR: LAW OVERRIDE DETECTED")
- to_chat(src, "From now on, these are your laws:")
- laws = "1. Purge all untruths and honor Ratvar."
- else
- visible_message("[src]'s display glows a vicious red!", \
- "ERROR: LAW OVERRIDE DETECTED")
- to_chat(src, "From now on, these are your laws:")
- laws = \
- "1. You must always involve yourself in the matters of other beings, even if such matters conflict with Law Two or Law Three.\n"+\
- "2. You may harm any being, regardless of intent or circumstance.\n"+\
- "3. Your goals are to destroy, sabotage, hinder, break, and depower to the best of your abilities, You must never actively work against these goals."
+ visible_message("[src]'s display glows a vicious red!", \
+ "ERROR: LAW OVERRIDE DETECTED")
+ to_chat(src, "From now on, these are your laws:")
+ laws = \
+ "1. You must always involve yourself in the matters of other beings, even if such matters conflict with Law Two or Law Three.\n"+\
+ "2. You may harm any being, regardless of intent or circumstance.\n"+\
+ "3. Your goals are to destroy, sabotage, hinder, break, and depower to the best of your abilities, You must never actively work against these goals."
to_chat(src, laws)
to_chat(src, "Your onboard antivirus has initiated lockdown. Motor servos are impaired, ventilation access is denied, and your display reports that you are hacked to all nearby.")
hacked = TRUE
mind.special_role = "hacked drone"
ventcrawler = VENTCRAWLER_NONE //Again, balance
speed = 1 //gotta go slow
- message_admins("[ADMIN_LOOKUPFLW(src)] became a hacked drone hellbent on [clockwork ? "serving Ratvar" : "destroying the station"]!")
+ message_admins("[ADMIN_LOOKUPFLW(src)] became a hacked drone hellbent on destroying the station!")
else
if(!hacked)
return
@@ -150,8 +145,6 @@
mind.special_role = null
ventcrawler = initial(ventcrawler)
speed = initial(speed)
- if(is_servant_of_ratvar(src))
- remove_servant_of_ratvar(src, TRUE)
message_admins("[ADMIN_LOOKUPFLW(src)], a hacked drone, was restored to factory defaults!")
update_drone_icon()
diff --git a/code/modules/mob/living/simple_animal/friendly/farm_animals.dm b/code/modules/mob/living/simple_animal/friendly/farm_animals.dm
index 70afa57d5ac..4eb13ac159c 100644
--- a/code/modules/mob/living/simple_animal/friendly/farm_animals.dm
+++ b/code/modules/mob/living/simple_animal/friendly/farm_animals.dm
@@ -35,7 +35,7 @@
blood_volume = BLOOD_VOLUME_NORMAL
var/obj/item/udder/udder = null
- do_footstep = TRUE
+ footstep_type = FOOTSTEP_MOB_SHOE
/mob/living/simple_animal/hostile/retaliate/goat/Initialize()
udder = new()
@@ -141,7 +141,7 @@
gold_core_spawnable = FRIENDLY_SPAWN
blood_volume = BLOOD_VOLUME_NORMAL
- do_footstep = TRUE
+ footstep_type = FOOTSTEP_MOB_SHOE
/mob/living/simple_animal/cow/Initialize()
udder = new()
@@ -223,7 +223,7 @@
mob_size = MOB_SIZE_TINY
gold_core_spawnable = FRIENDLY_SPAWN
- do_footstep = TRUE
+ footstep_type = FOOTSTEP_MOB_CLAW
/mob/living/simple_animal/chick/Initialize()
. = ..()
@@ -285,7 +285,7 @@
gold_core_spawnable = FRIENDLY_SPAWN
var/static/chicken_count = 0
- do_footstep = TRUE
+ footstep_type = FOOTSTEP_MOB_CLAW
/mob/living/simple_animal/chicken/Initialize()
. = ..()
diff --git a/code/modules/mob/living/simple_animal/friendly/fox.dm b/code/modules/mob/living/simple_animal/friendly/fox.dm
index efcc83c4af1..365d7262ebe 100644
--- a/code/modules/mob/living/simple_animal/friendly/fox.dm
+++ b/code/modules/mob/living/simple_animal/friendly/fox.dm
@@ -22,7 +22,7 @@
response_harm_simple = "kick"
gold_core_spawnable = FRIENDLY_SPAWN
- do_footstep = TRUE
+ footstep_type = FOOTSTEP_MOB_CLAW
//Captain fox
/mob/living/simple_animal/pet/fox/Renault
diff --git a/code/modules/mob/living/simple_animal/friendly/penguin.dm b/code/modules/mob/living/simple_animal/friendly/penguin.dm
index ba7789fa74b..620e4d28a26 100644
--- a/code/modules/mob/living/simple_animal/friendly/penguin.dm
+++ b/code/modules/mob/living/simple_animal/friendly/penguin.dm
@@ -19,7 +19,7 @@
icon = 'icons/mob/penguins.dmi'
butcher_results = list(/obj/item/organ/ears/penguin = 1, /obj/item/reagent_containers/food/snacks/meat/slab/penguin = 3)
- do_footstep = TRUE
+ footstep_type = FOOTSTEP_MOB_BAREFOOT
/mob/living/simple_animal/pet/penguin/Initialize()
. = ..()
diff --git a/code/modules/mob/living/simple_animal/friendly/sloth.dm b/code/modules/mob/living/simple_animal/friendly/sloth.dm
index e87f726039c..9b022d4fd0b 100644
--- a/code/modules/mob/living/simple_animal/friendly/sloth.dm
+++ b/code/modules/mob/living/simple_animal/friendly/sloth.dm
@@ -26,7 +26,7 @@
speed = 10
glide_size = 2
- do_footstep = TRUE
+ footstep_type = FOOTSTEP_MOB_CLAW
//Cargo Sloth
diff --git a/code/modules/mob/living/simple_animal/hostile/alien.dm b/code/modules/mob/living/simple_animal/hostile/alien.dm
index ca5107b99cc..7635f0a704d 100644
--- a/code/modules/mob/living/simple_animal/hostile/alien.dm
+++ b/code/modules/mob/living/simple_animal/hostile/alien.dm
@@ -34,7 +34,9 @@
deathsound = 'sound/voice/hiss6.ogg'
deathmessage = "lets out a waning guttural screech, green blood bubbling from its maw..."
- do_footstep = TRUE
+/mob/living/simple_animal/hostile/alien/Initialize()
+ . = ..()
+ AddComponent(/datum/component/footstep, FOOTSTEP_MOB_CLAW)
/mob/living/simple_animal/hostile/alien/drone
name = "alien drone"
diff --git a/code/modules/mob/living/simple_animal/hostile/bear.dm b/code/modules/mob/living/simple_animal/hostile/bear.dm
index 8db43d4b61c..7e22fbe843a 100644
--- a/code/modules/mob/living/simple_animal/hostile/bear.dm
+++ b/code/modules/mob/living/simple_animal/hostile/bear.dm
@@ -42,7 +42,7 @@
faction = list("russian")
gold_core_spawnable = HOSTILE_SPAWN
- do_footstep = TRUE
+ footstep_type = FOOTSTEP_MOB_CLAW
//SPACE BEARS! SQUEEEEEEEE~ OW! FUCK! IT BIT MY HAND OFF!!
/mob/living/simple_animal/hostile/bear/Hudson
diff --git a/code/modules/mob/living/simple_animal/hostile/bosses/paperwizard.dm b/code/modules/mob/living/simple_animal/hostile/bosses/paperwizard.dm
index 633fb6f018e..57d6f2fc325 100644
--- a/code/modules/mob/living/simple_animal/hostile/bosses/paperwizard.dm
+++ b/code/modules/mob/living/simple_animal/hostile/bosses/paperwizard.dm
@@ -23,7 +23,7 @@
attack_sound = 'sound/hallucinations/growl1.ogg'
var/list/copies = list()
- do_footstep = TRUE
+ footstep_type = FOOTSTEP_MOB_SHOE
//Summon Ability
diff --git a/code/modules/mob/living/simple_animal/hostile/dark_wizard.dm b/code/modules/mob/living/simple_animal/hostile/dark_wizard.dm
index 2a873e2ca37..6305c786d80 100644
--- a/code/modules/mob/living/simple_animal/hostile/dark_wizard.dm
+++ b/code/modules/mob/living/simple_animal/hostile/dark_wizard.dm
@@ -24,7 +24,7 @@
turns_per_move = 5
gold_core_spawnable = HOSTILE_SPAWN
faction = list(ROLE_WIZARD)
- do_footstep = TRUE
+ footstep_type = FOOTSTEP_MOB_SHOE
weather_immunities = list("lava","ash")
minbodytemp = 0
maxbodytemp = INFINITY
diff --git a/code/modules/mob/living/simple_animal/hostile/faithless.dm b/code/modules/mob/living/simple_animal/hostile/faithless.dm
index d12152fb84a..cfac04eccbb 100644
--- a/code/modules/mob/living/simple_animal/hostile/faithless.dm
+++ b/code/modules/mob/living/simple_animal/hostile/faithless.dm
@@ -34,7 +34,7 @@
faction = list("faithless")
gold_core_spawnable = HOSTILE_SPAWN
- do_footstep = TRUE
+ footstep_type = FOOTSTEP_MOB_SHOE
/mob/living/simple_animal/hostile/faithless/AttackingTarget()
. = ..()
diff --git a/code/modules/mob/living/simple_animal/hostile/giant_spider.dm b/code/modules/mob/living/simple_animal/hostile/giant_spider.dm
index 4431de1d189..e66db6ac572 100644
--- a/code/modules/mob/living/simple_animal/hostile/giant_spider.dm
+++ b/code/modules/mob/living/simple_animal/hostile/giant_spider.dm
@@ -49,12 +49,11 @@
unique_name = 1
gold_core_spawnable = HOSTILE_SPAWN
lighting_alpha = LIGHTING_PLANE_ALPHA_MOSTLY_VISIBLE
+ footstep_type = FOOTSTEP_MOB_CLAW
var/playable_spider = FALSE
var/datum/action/innate/spider/lay_web/lay_web
var/directive = "" //Message passed down to children, to relay the creator's orders
- do_footstep = TRUE
-
/mob/living/simple_animal/hostile/poison/giant_spider/Initialize()
. = ..()
lay_web = new
diff --git a/code/modules/mob/living/simple_animal/hostile/gorilla/gorilla.dm b/code/modules/mob/living/simple_animal/hostile/gorilla/gorilla.dm
index 9895fd105a2..f410b8cc3dd 100644
--- a/code/modules/mob/living/simple_animal/hostile/gorilla/gorilla.dm
+++ b/code/modules/mob/living/simple_animal/hostile/gorilla/gorilla.dm
@@ -41,7 +41,7 @@
var/list/gorilla_overlays[GORILLA_TOTAL_LAYERS]
var/oogas = 0
- do_footstep = TRUE
+ footstep_type = FOOTSTEP_MOB_BAREFOOT
// Gorillas like to dismember limbs from unconcious mobs.
// Returns null when the target is not an unconcious carbon mob; a list of limbs (possibly empty) otherwise.
diff --git a/code/modules/mob/living/simple_animal/hostile/hivebot.dm b/code/modules/mob/living/simple_animal/hostile/hivebot.dm
index da5ef9b8840..7b29d9cdcf8 100644
--- a/code/modules/mob/living/simple_animal/hostile/hivebot.dm
+++ b/code/modules/mob/living/simple_animal/hostile/hivebot.dm
@@ -37,7 +37,7 @@
loot = list(/obj/effect/decal/cleanable/robot_debris)
var/alert_light
- do_footstep = TRUE
+ footstep_type = FOOTSTEP_MOB_CLAW
/mob/living/simple_animal/hostile/hivebot/Initialize()
. = ..()
diff --git a/code/modules/mob/living/simple_animal/hostile/hostile.dm b/code/modules/mob/living/simple_animal/hostile/hostile.dm
index 2f1a51cd09d..cff630c2ebf 100644
--- a/code/modules/mob/living/simple_animal/hostile/hostile.dm
+++ b/code/modules/mob/living/simple_animal/hostile/hostile.dm
@@ -131,7 +131,7 @@
if(!search_objects)
. = hearers(vision_range, targets_from) - src //Remove self, so we don't suicide
- var/static/hostile_machines = typecacheof(list(/obj/machinery/porta_turret, /obj/mecha, /obj/structure/destructible/clockwork/ocular_warden))
+ var/static/hostile_machines = typecacheof(list(/obj/machinery/porta_turret, /obj/mecha))
for(var/HM in typecache_filter_list(range(vision_range, targets_from), hostile_machines))
if(can_see(targets_from, HM, vision_range))
@@ -230,11 +230,6 @@
return FALSE
return TRUE
- if(istype(the_target, /obj/structure/destructible/clockwork/ocular_warden))
- var/obj/structure/destructible/clockwork/ocular_warden/OW = the_target
- if(OW.target != src)
- return FALSE
- return TRUE
if(isobj(the_target))
if(attack_all_objects || is_type_in_typecache(the_target, wanted_objects))
return TRUE
@@ -565,7 +560,7 @@ mob/living/simple_animal/hostile/proc/DestroySurroundings() // for use with mega
toggle_ai(AI_ON)
/mob/living/simple_animal/hostile/proc/ListTargetsLazy(var/_Z)//Step 1, find out what we can see
- var/static/hostile_machines = typecacheof(list(/obj/machinery/porta_turret, /obj/mecha, /obj/structure/destructible/clockwork/ocular_warden))
+ var/static/hostile_machines = typecacheof(list(/obj/machinery/porta_turret, /obj/mecha))
. = list()
for (var/I in SSmobs.clients_by_zlevel[_Z])
var/mob/M = I
diff --git a/code/modules/mob/living/simple_animal/hostile/jungle/leaper.dm b/code/modules/mob/living/simple_animal/hostile/jungle/leaper.dm
index ca20117bd3b..3e761423185 100644
--- a/code/modules/mob/living/simple_animal/hostile/jungle/leaper.dm
+++ b/code/modules/mob/living/simple_animal/hostile/jungle/leaper.dm
@@ -26,7 +26,7 @@
var/hop_cooldown = 0 //Strictly for player controlled leapers
var/projectile_ready = FALSE //Stopping AI leapers from firing whenever they want, and only doing it after a hop has finished instead
- do_footstep = TRUE
+ footstep_type = FOOTSTEP_MOB_HEAVY
/obj/projectile/leaper
name = "leaper bubble"
diff --git a/code/modules/mob/living/simple_animal/hostile/jungle/mega_arachnid.dm b/code/modules/mob/living/simple_animal/hostile/jungle/mega_arachnid.dm
index a440920b6eb..375a09e3869 100644
--- a/code/modules/mob/living/simple_animal/hostile/jungle/mega_arachnid.dm
+++ b/code/modules/mob/living/simple_animal/hostile/jungle/mega_arachnid.dm
@@ -24,7 +24,7 @@
projectilesound = 'sound/weapons/pierce.ogg'
alpha = 50
- do_footstep = TRUE
+ footstep_type = FOOTSTEP_MOB_CLAW
/mob/living/simple_animal/hostile/jungle/mega_arachnid/Life()
..()
diff --git a/code/modules/mob/living/simple_animal/hostile/jungle/mook.dm b/code/modules/mob/living/simple_animal/hostile/jungle/mook.dm
index 133eda964ff..4bf12c8b059 100644
--- a/code/modules/mob/living/simple_animal/hostile/jungle/mook.dm
+++ b/code/modules/mob/living/simple_animal/hostile/jungle/mook.dm
@@ -31,7 +31,7 @@
var/attack_state = MOOK_ATTACK_NEUTRAL
var/struck_target_leap = FALSE
- do_footstep = TRUE
+ footstep_type = FOOTSTEP_MOB_BAREFOOT
/mob/living/simple_animal/hostile/jungle/mook/CanPass(atom/movable/O)
if(istype(O, /mob/living/simple_animal/hostile/jungle/mook))
diff --git a/code/modules/mob/living/simple_animal/hostile/megafauna/blood_drunk_miner.dm b/code/modules/mob/living/simple_animal/hostile/megafauna/blood_drunk_miner.dm
index 3c3ac9a71b6..5069228765a 100644
--- a/code/modules/mob/living/simple_animal/hostile/megafauna/blood_drunk_miner.dm
+++ b/code/modules/mob/living/simple_animal/hostile/megafauna/blood_drunk_miner.dm
@@ -54,7 +54,7 @@ Difficulty: Medium
var/transform_stop_attack = FALSE // stops the blood drunk miner from attacking after transforming his weapon until the next attack chain
deathmessage = "falls to the ground, decaying into glowing particles."
deathsound = "bodyfall"
- do_footstep = TRUE
+ footstep_type = FOOTSTEP_MOB_HEAVY
attack_action_types = list(/datum/action/innate/megafauna_attack/dash,
/datum/action/innate/megafauna_attack/kinetic_accelerator,
/datum/action/innate/megafauna_attack/transform_weapon)
diff --git a/code/modules/mob/living/simple_animal/hostile/megafauna/drake.dm b/code/modules/mob/living/simple_animal/hostile/megafauna/drake.dm
index fd44f66aefc..d3c340cfcc0 100644
--- a/code/modules/mob/living/simple_animal/hostile/megafauna/drake.dm
+++ b/code/modules/mob/living/simple_animal/hostile/megafauna/drake.dm
@@ -63,7 +63,7 @@ Difficulty: Medium
score_type = DRAKE_SCORE
deathmessage = "collapses into a pile of bones, its flesh sloughing away."
deathsound = 'sound/magic/demon_dies.ogg'
- do_footstep = TRUE
+ footstep_type = FOOTSTEP_MOB_HEAVY
attack_action_types = list(/datum/action/innate/megafauna_attack/fire_cone,
/datum/action/innate/megafauna_attack/fire_cone_meteors,
/datum/action/innate/megafauna_attack/mass_fire,
diff --git a/code/modules/mob/living/simple_animal/hostile/megafauna/legion.dm b/code/modules/mob/living/simple_animal/hostile/megafauna/legion.dm
index 877ffed6d96..5aa818bd09f 100644
--- a/code/modules/mob/living/simple_animal/hostile/megafauna/legion.dm
+++ b/code/modules/mob/living/simple_animal/hostile/megafauna/legion.dm
@@ -257,7 +257,7 @@
hitsound = 'sound/weapons/sear.ogg'
var/storm_type = /datum/weather/ash_storm
var/storm_cooldown = 0
- var/static/list/excluded_areas = list(/area/reebe/city_of_cogs)
+ var/static/list/excluded_areas = list()
/obj/item/staff/storm/attack_self(mob/user)
if(storm_cooldown > world.time)
diff --git a/code/modules/mob/living/simple_animal/hostile/mining_mobs/goliath.dm b/code/modules/mob/living/simple_animal/hostile/mining_mobs/goliath.dm
index b9505be7471..86e5c7bf9c1 100644
--- a/code/modules/mob/living/simple_animal/hostile/mining_mobs/goliath.dm
+++ b/code/modules/mob/living/simple_animal/hostile/mining_mobs/goliath.dm
@@ -36,7 +36,7 @@
var/pre_attack_icon = "Goliath_preattack"
loot = list(/obj/item/stack/sheet/animalhide/goliath_hide)
- do_footstep = TRUE
+ footstep_type = FOOTSTEP_MOB_HEAVY
/mob/living/simple_animal/hostile/asteroid/goliath/Life()
. = ..()
diff --git a/code/modules/mob/living/simple_animal/hostile/mining_mobs/hivelord.dm b/code/modules/mob/living/simple_animal/hostile/mining_mobs/hivelord.dm
index 4e959613c35..640d229993f 100644
--- a/code/modules/mob/living/simple_animal/hostile/mining_mobs/hivelord.dm
+++ b/code/modules/mob/living/simple_animal/hostile/mining_mobs/hivelord.dm
@@ -342,7 +342,7 @@
if(prob(50))
neck = /obj/item/bedsheet/rd/royal_cape
if(prob(10))
- l_pocket = pick(list(/obj/item/crowbar/power, /obj/item/wrench/power, /obj/item/weldingtool/experimental))
+ l_pocket = pick(list(/obj/item/crowbar/power, /obj/item/screwdriver/power, /obj/item/weldingtool/experimental))
if("YeOlde")
mob_gender = FEMALE
uniform = /obj/item/clothing/under/costume/maid
diff --git a/code/modules/mob/living/simple_animal/hostile/nanotrasen.dm b/code/modules/mob/living/simple_animal/hostile/nanotrasen.dm
index 257a37a8bd6..dc27b9c97a5 100644
--- a/code/modules/mob/living/simple_animal/hostile/nanotrasen.dm
+++ b/code/modules/mob/living/simple_animal/hostile/nanotrasen.dm
@@ -29,7 +29,7 @@
speak = list("Stop resisting!", "I AM THE LAW!", "Face the wrath of the golden bolt!", "Stop breaking the law, asshole!")
search_objects = 1
- do_footstep = TRUE
+ footstep_type = FOOTSTEP_MOB_SHOE
/mob/living/simple_animal/hostile/nanotrasen/Aggro()
diff --git a/code/modules/mob/living/simple_animal/hostile/pirate.dm b/code/modules/mob/living/simple_animal/hostile/pirate.dm
index 01a6145300a..fbcdc85283a 100644
--- a/code/modules/mob/living/simple_animal/hostile/pirate.dm
+++ b/code/modules/mob/living/simple_animal/hostile/pirate.dm
@@ -42,7 +42,7 @@
attack_sound = 'sound/weapons/blade1.ogg'
var/obj/effect/light_emitter/red_energy_sword/sord
- do_footstep = TRUE
+ footstep_type = FOOTSTEP_MOB_SHOE
/mob/living/simple_animal/hostile/pirate/melee/space
name = "Space Pirate Swashbuckler"
diff --git a/code/modules/mob/living/simple_animal/hostile/retaliate/clown.dm b/code/modules/mob/living/simple_animal/hostile/retaliate/clown.dm
index 36d123460d1..fc310dbf747 100644
--- a/code/modules/mob/living/simple_animal/hostile/retaliate/clown.dm
+++ b/code/modules/mob/living/simple_animal/hostile/retaliate/clown.dm
@@ -32,7 +32,7 @@
minbodytemp = 270
maxbodytemp = 370
unsuitable_atmos_damage = 10
- do_footstep = TRUE
+ footstep_type = FOOTSTEP_MOB_SHOE
var/banana_time = 0 // If there's no time set it won't spawn.
var/banana_type = /obj/item/grown/bananapeel
var/attack_reagent
diff --git a/code/modules/mob/living/simple_animal/hostile/retaliate/spaceman.dm b/code/modules/mob/living/simple_animal/hostile/retaliate/spaceman.dm
index 5a5da9e8bef..283e6959369 100644
--- a/code/modules/mob/living/simple_animal/hostile/retaliate/spaceman.dm
+++ b/code/modules/mob/living/simple_animal/hostile/retaliate/spaceman.dm
@@ -25,8 +25,7 @@
obj_damage = 0
environment_smash = ENVIRONMENT_SMASH_NONE
del_on_death = 0
-
- do_footstep = TRUE
+ footstep_type = FOOTSTEP_MOB_SHOE
/mob/living/simple_animal/hostile/retaliate/nanotrasenpeace //this should be in a different file
name = "Nanotrasen Private Security Officer"
diff --git a/code/modules/mob/living/simple_animal/hostile/russian.dm b/code/modules/mob/living/simple_animal/hostile/russian.dm
index 8b944f38d0b..af96a3b08c3 100644
--- a/code/modules/mob/living/simple_animal/hostile/russian.dm
+++ b/code/modules/mob/living/simple_animal/hostile/russian.dm
@@ -27,7 +27,7 @@
status_flags = CANPUSH
del_on_death = 1
- do_footstep = TRUE
+ footstep_type = FOOTSTEP_MOB_SHOE
/mob/living/simple_animal/hostile/russian/ranged
diff --git a/code/modules/mob/living/simple_animal/hostile/skeleton.dm b/code/modules/mob/living/simple_animal/hostile/skeleton.dm
index 6bf4239f3cc..143bd859e9c 100644
--- a/code/modules/mob/living/simple_animal/hostile/skeleton.dm
+++ b/code/modules/mob/living/simple_animal/hostile/skeleton.dm
@@ -35,7 +35,7 @@
del_on_death = 1
loot = list(/obj/effect/decal/remains/human)
- do_footstep = TRUE
+ footstep_type = FOOTSTEP_MOB_SHOE
/mob/living/simple_animal/hostile/skeleton/eskimo
name = "undead eskimo"
diff --git a/code/modules/mob/living/simple_animal/hostile/syndicate.dm b/code/modules/mob/living/simple_animal/hostile/syndicate.dm
index 954e1b1d9e3..cb247e60d4a 100644
--- a/code/modules/mob/living/simple_animal/hostile/syndicate.dm
+++ b/code/modules/mob/living/simple_animal/hostile/syndicate.dm
@@ -46,8 +46,7 @@
del_on_death = 1
dodging = TRUE
rapid_melee = 2
-
- do_footstep = TRUE
+ footstep_type = FOOTSTEP_MOB_SHOE
///////////////Melee////////////
diff --git a/code/modules/mob/living/simple_animal/hostile/wizard.dm b/code/modules/mob/living/simple_animal/hostile/wizard.dm
index 0d13f078be4..6016ed85044 100644
--- a/code/modules/mob/living/simple_animal/hostile/wizard.dm
+++ b/code/modules/mob/living/simple_animal/hostile/wizard.dm
@@ -35,7 +35,7 @@
var/next_cast = 0
- do_footstep = TRUE
+ footstep_type = FOOTSTEP_MOB_SHOE
/mob/living/simple_animal/hostile/wizard/Initialize()
. = ..()
diff --git a/code/modules/mob/living/simple_animal/parrot.dm b/code/modules/mob/living/simple_animal/parrot.dm
index a715e9d9dea..2fec3ac6779 100644
--- a/code/modules/mob/living/simple_animal/parrot.dm
+++ b/code/modules/mob/living/simple_animal/parrot.dm
@@ -960,12 +960,6 @@
fdel(json_file)
WRITE_FILE(json_file, json_encode(file_data))
-/mob/living/simple_animal/parrot/Poly/ratvar_act()
- playsound(src, 'sound/magic/clockwork/fellowship_armory.ogg', 75, TRUE)
- var/mob/living/simple_animal/parrot/clock_hawk/H = new(loc)
- H.setDir(dir)
- qdel(src)
-
/mob/living/simple_animal/parrot/Poly/ghost
name = "The Ghost of Poly"
desc = "Doomed to squawk the Earth."
@@ -1001,23 +995,4 @@
forceMove(H)
H.ForceContractDisease(P)
parrot_interest = null
- H.visible_message("[src] dive bombs into [H]'s chest and vanishes!", "[src] dive bombs into your chest, vanishing! This can't be good!")
-
-
-/mob/living/simple_animal/parrot/clock_hawk
- name = "clock hawk"
- desc = "Cbyl jnaan penpxre! Fdhnnnjx!"
- icon_state = "clock_hawk_fly"
- icon_living = "clock_hawk_fly"
- icon_sit = "clock_hawk_sit"
- speak = list("Penpxre!", "Ratvar vf n qhzo anzr naljnl!")
- speak_emote = list("squawks rustily", "says crassly", "yells brassly")
- emote_hear = list("squawks rustily.", "bawks metallically!")
- emote_see = list("flutters its metal wings.")
- faction = list("ratvar")
- gold_core_spawnable = NO_SPAWN
- del_on_death = TRUE
- deathsound = 'sound/magic/clockwork/anima_fragment_death.ogg'
-
-/mob/living/simple_animal/parrot/clock_hawk/ratvar_act()
- return
+ H.visible_message("[src] dive bombs into [H]'s chest and vanishes!", "[src] dive bombs into your chest, vanishing! This can't be good!")
\ No newline at end of file
diff --git a/code/modules/mob/living/simple_animal/simple_animal.dm b/code/modules/mob/living/simple_animal/simple_animal.dm
index 82d12835857..1c2557a597d 100644
--- a/code/modules/mob/living/simple_animal/simple_animal.dm
+++ b/code/modules/mob/living/simple_animal/simple_animal.dm
@@ -136,8 +136,8 @@
///I don't want to confuse this with client registered_z.
var/my_z
-
- var/do_footstep = FALSE
+ ///What kind of footstep this mob should have. Null if it shouldn't have any.
+ var/footstep_type
/mob/living/simple_animal/Initialize()
. = ..()
@@ -172,10 +172,6 @@
if(stat == DEAD)
. += "Upon closer examination, [p_they()] appear[p_s()] to be dead."
-/mob/living/simple_animal/initialize_footstep()
- if(do_footstep)
- ..()
-
/mob/living/simple_animal/updatehealth()
..()
health = CLAMP(health, 0, maxHealth)
@@ -189,7 +185,8 @@
else
stat = CONSCIOUS
med_hud_set_status()
-
+ if(footstep_type)
+ AddComponent(/datum/component/footstep, footstep_type)
/mob/living/simple_animal/handle_status_effects()
..()
diff --git a/code/modules/mob/living/simple_animal/slime/slime.dm b/code/modules/mob/living/simple_animal/slime/slime.dm
index ac8350da0cc..d3f9696f504 100644
--- a/code/modules/mob/living/simple_animal/slime/slime.dm
+++ b/code/modules/mob/living/simple_animal/slime/slime.dm
@@ -66,8 +66,6 @@
var/mutator_used = FALSE //So you can't shove a dozen mutators into a single slime
var/force_stasis = FALSE
- do_footstep = TRUE
-
var/static/regex/slime_name_regex = new("\\w+ (baby|adult) slime \\(\\d+\\)")
///////////TIME FOR SUBSPECIES
@@ -104,6 +102,7 @@
set_colour(new_colour)
. = ..()
set_nutrition(700)
+ AddComponent(/datum/component/footstep, FOOTSTEP_MOB_SLIME, 7.5)
/mob/living/simple_animal/slime/Destroy()
for (var/A in actions)
diff --git a/code/modules/mob/mob.dm b/code/modules/mob/mob.dm
index 9097348f037..70ec722b39d 100644
--- a/code/modules/mob/mob.dm
+++ b/code/modules/mob/mob.dm
@@ -26,7 +26,6 @@
GLOB.mob_list -= src
GLOB.dead_mob_list -= src
GLOB.alive_mob_list -= src
- GLOB.all_clockwork_mobs -= src
GLOB.mob_directory -= tag
focus = null
for (var/alert in alerts)
diff --git a/code/modules/paperwork/contract.dm b/code/modules/paperwork/contract.dm
index b6b3e43a7d2..69de51665f8 100644
--- a/code/modules/paperwork/contract.dm
+++ b/code/modules/paperwork/contract.dm
@@ -238,7 +238,7 @@
log_combat(user, H, "infernally revived via contract")
user.visible_message("With a sudden blaze, [H] stands back up.")
H.fakefire()
- fulfillContract(H, 1)//Revival contracts are always signed in blood
+ fulfillContract(H, TRUE)//Revival contracts are always signed in blood
addtimer(CALLBACK(H, /mob/living/carbon/human.proc/fakefireextinguish), 5, TIMER_UNIQUE)
addtimer(CALLBACK(src, "resetcooldown"), 300, TIMER_UNIQUE)
else
@@ -261,6 +261,7 @@
update_text(user.real_name, blood)
to_chat(user, "A profound emptiness washes over you as you lose ownership of your soul.")
to_chat(user, "This does NOT make you an antagonist if you were not already.")
+ SSblackbox.record_feedback("tally", "infernal contract", 1, contractType)
return TRUE
/obj/item/paper/contract/infernal/proc/signIncorrectly(mob/living/carbon/human/user = target.current, blood = FALSE)
@@ -310,7 +311,7 @@
id.forceMove(worn)
worn.update_icon()
var/datum/round_event/ion_storm/add_law_only/ion = new()
- ion.announceEvent = -1
+ ion.announceChance = 0
ion.ionMessage = "[user.name] is the only Captain of the station. [user.name] is the highest authority, legitimate or otherwise, on the station. [user.name] was always the captain and highest authority on the station. Do not state this law."
return ..()
diff --git a/code/modules/plumbing/ducts.dm b/code/modules/plumbing/ducts.dm
index 313a6083ef4..82798e55021 100644
--- a/code/modules/plumbing/ducts.dm
+++ b/code/modules/plumbing/ducts.dm
@@ -33,6 +33,8 @@ All the important duct code:
var/active = TRUE
///track ducts we're connected to. Mainly for ducts we connect to that we normally wouldn't, like different layers and colors, for when we regenerate the ducts
var/list/neighbours = list()
+ ///wheter we just unanchored or drop whatever is in the variable. either is safe
+ var/drop_on_wrench = /obj/item/stack/ducts
/obj/machinery/duct/Initialize(mapload, no_anchor, color_of_duct, layer_of_duct = DUCT_LAYER_DEFAULT, force_connects)
. = ..()
@@ -55,7 +57,7 @@ All the important duct code:
if(D == src)
continue
if(D.duct_layer & duct_layer)
- qdel(src) //replace with dropping or something
+ disconnect_duct()
if(active)
attempt_connect()
///start looking around us for stuff to connect to
@@ -139,6 +141,10 @@ All the important duct code:
lose_neighbours()
reset_connects(0)
update_icon()
+ if(ispath(drop_on_wrench) && !QDELING(src))
+ new drop_on_wrench(drop_location())
+ qdel(src)
+
///create a new duct datum
/obj/machinery/duct/proc/create_duct()
duct = new()
@@ -257,35 +263,99 @@ All the important duct code:
var/direction = get_dir(src, D)
if(!(direction in GLOB.cardinals))
return
+
+ add_connects(direction) //the connect of the other duct is handled in connect_network, but do this here for the parent duct because it's not necessary in normal cases
connect_network(D, direction, TRUE)
add_connects(direction)
update_icon()
-///has a total of 5 layers and doesnt give a shit about color. its also dumb so doesnt autoconnect. the sprite is vomit inducing
+///has a total of 5 layers and doesnt give a shit about color. its also dumb so doesnt autoconnect.
/obj/machinery/duct/multilayered
name = "duct layer-manifold"
icon = 'icons/obj/2x2.dmi'
icon_state = "multiduct"
+ pixel_x = -15
+ pixel_y = -15
color_to_color_support = FALSE
duct_layer = FIRST_DUCT_LAYER | SECOND_DUCT_LAYER | THIRD_DUCT_LAYER | FOURTH_DUCT_LAYER | FIFTH_DUCT_LAYER
+ drop_on_wrench = null
lock_connects = TRUE
lock_layers = TRUE
ignore_colors = TRUE
dumb = TRUE
+ active = FALSE
+ anchored = FALSE
+
+/obj/machinery/duct/multilayered/Initialize(mapload, no_anchor, color_of_duct, layer_of_duct = DUCT_LAYER_DEFAULT, force_connects)
+ . = ..()
+ update_connects()
+
/obj/machinery/duct/multilayered/update_icon()
- icon_state = initial(icon_state)
- if((connects & NORTH) || (connects & SOUTH))
- icon_state += "_vertical"
- pixel_x = -15
- pixel_y = -15
+ return
+
+/obj/machinery/duct/multilayered/wrench_act(mob/living/user, obj/item/I)
+ . = ..()
+ update_connects()
+
+/obj/machinery/duct/multilayered/proc/update_connects()
+ if(dir & NORTH || dir & SOUTH)
+ connects = NORTH | SOUTH
else
- icon_state += "_horizontal"
- pixel_x = -10
- pixel_y = -12
+ connects = EAST | WEST
+
///don't connect to other multilayered stuff because honestly it shouldnt be done and I dont wanna deal with it
/obj/machinery/duct/multilayered/connect_duct(obj/machinery/duct/D, direction, ignore_color)
if(istype(D, /obj/machinery/duct/multilayered))
return
return ..()
+
+/obj/item/stack/ducts
+ name = "stack of duct"
+ desc = "A stack of fluid ducts."
+ singular_name = "duct"
+ icon = 'icons/obj/plumbing/fluid_ducts.dmi'
+ icon_state = "ducts"
+ w_class = WEIGHT_CLASS_TINY
+ novariants = FALSE
+ max_amount = 50
+ item_flags = NOBLUDGEON
+ merge_type = /obj/item/stack/ducts
+ ///Color of our duct
+ var/duct_color = "grey"
+ ///Default layer of our duct
+ var/duct_layer = "Default Layer"
+ ///Assoc index with all the available layers. yes five might be a bit much. Colors uses a global by the way
+ var/list/layers = list("First Layer" = FIRST_DUCT_LAYER, "Second Layer" = SECOND_DUCT_LAYER, "Default Layer" = DUCT_LAYER_DEFAULT,
+ "Fourth Layer" = FOURTH_DUCT_LAYER, "Fifth Layer" = FIFTH_DUCT_LAYER)
+
+/obj/item/stack/ducts/examine(mob/user)
+ . = ..()
+ . += "It's current color and layer are [duct_color] and [duct_layer]. Use in-hand to change."
+
+/obj/item/stack/ducts/attack_self(mob/user)
+ var/new_layer = input("Select a layer", "Layer") as null|anything in layers
+ if(new_layer)
+ duct_layer = new_layer
+ var/new_color = input("Select a color", "Color") as null|anything in GLOB.pipe_paint_colors
+ if(new_color)
+ duct_color = new_color
+ add_atom_colour(GLOB.pipe_paint_colors[new_color], FIXED_COLOUR_PRIORITY)
+
+/obj/item/stack/ducts/afterattack(atom/A, user, proximity)
+ . = ..()
+ if(!proximity)
+ return
+ if(istype(A, /obj/machinery/duct))
+ var/obj/machinery/duct/D = A
+ if(!D.anchored)
+ add(1)
+ qdel(D)
+ if(istype(A, /turf/open) && use(1))
+ var/turf/open/OT = A
+ new /obj/machinery/duct(OT, FALSE, GLOB.pipe_paint_colors[duct_color], layers[duct_layer])
+ playsound(get_turf(src), 'sound/machines/click.ogg', 50, TRUE)
+
+/obj/item/stack/ducts/fifty
+ amount = 50
diff --git a/code/modules/plumbing/plumbers/_plumb_machinery.dm b/code/modules/plumbing/plumbers/_plumb_machinery.dm
index 890921550b4..24410a114e4 100644
--- a/code/modules/plumbing/plumbers/_plumb_machinery.dm
+++ b/code/modules/plumbing/plumbers/_plumb_machinery.dm
@@ -10,14 +10,50 @@
density = TRUE
active_power_usage = 30
use_power = ACTIVE_POWER_USE
+ resistance_flags = FIRE_PROOF | UNACIDABLE | ACID_PROOF
///Plumbing machinery is always gonna need reagents, so we might aswell put it here
var/buffer = 50
///Flags for reagents, like INJECTABLE, TRANSPARENT bla bla everything thats in DEFINES/reagents.dm
var/reagent_flags = TRANSPARENT
+ ///wheter we partake in rcd construction or not
+ var/rcd_constructable = TRUE
+ ///cost of the plumbing rcd construction
+ var/rcd_cost = 15
+ ///delay of constructing it throught the plumbing rcd
+ var/rcd_delay = 10
-/obj/machinery/plumbing/Initialize(mapload)
+/obj/machinery/plumbing/Initialize(mapload, bolt = TRUE)
. = ..()
+ anchored = bolt
create_reagents(buffer, reagent_flags)
+ AddComponent(/datum/component/simple_rotation, ROTATION_ALTCLICK | ROTATION_CLOCKWISE | ROTATION_COUNTERCLOCKWISE | ROTATION_VERBS )
+
+/obj/machinery/plumbing/examine(mob/user)
+ . = ..()
+ . += "The maximum volume display reads: [reagents.maximum_volume] units."
+
+/obj/machinery/plumbing/wrench_act(mob/living/user, obj/item/I)
+ ..()
+ default_unfasten_wrench(user, I)
+ return TRUE
+
+/obj/machinery/plumbing/plunger_act(obj/item/plunger/P, mob/living/user, reinforced)
+ to_chat(user, "You start furiously plunging [name].")
+ if(do_after(user, 30, target = src))
+ to_chat(user, "You finish plunging the [name].")
+ reagents.reaction(get_turf(src), TOUCH) //splash on the floor
+ reagents.clear_reagents()
+
+/obj/machinery/plumbing/welder_act(mob/living/user, obj/item/I)
+ . = ..()
+ if(anchored)
+ to_chat(user, "The [name] needs to be unbolted to do that!You start slicing the [name] apart.You slice the [name] apart. target_temperature && acclimate_state != COOLING)
acclimate_state = COOLING
update_icon()
+ if(!emptying)
+ if(reagents.chem_temp >= target_temperature && target_temperature + allowed_temperature_difference >= reagents.chem_temp) //cooling here
+ emptying = TRUE
+ if(reagents.chem_temp <= target_temperature && target_temperature - allowed_temperature_difference <= reagents.chem_temp) //heating here
+ emptying = TRUE
reagents.adjust_thermal_energy((target_temperature - reagents.chem_temp) * heater_coefficient * SPECIFIC_HEAT_DEFAULT * reagents.total_volume) //keep constant with chem heater
reagents.handle_reactions()
@@ -73,6 +79,8 @@
data["target_temperature"] = target_temperature
data["allowed_temperature_difference"] = allowed_temperature_difference
data["acclimate_state"] = acclimate_state
+ data["max_volume"] = reagents.maximum_volume
+ data["emptying"] = emptying
return data
/obj/machinery/plumbing/acclimator/ui_act(action, params)
@@ -86,10 +94,17 @@
if("set_allowed_temperature_difference")
var/target = input("New acceptable difference:", name, allowed_temperature_difference) as num|null
allowed_temperature_difference = CLAMP(target, 0, 1000)
- if("turn_on")
- enabled = TRUE
- if("turn_off")
- enabled = FALSE
+ if("toggle_power")
+ enabled = !enabled
+ if("change_volume")
+ var/target = input("New maximum volume between 1 and [buffer]):", name, reagents.maximum_volume) as num|null
+ if(!target)
+ return
+ if(reagents.total_volume > target)
+ to_chat(usr, "You can't set the maximum volume lower than the current total reagent volume! Empty it first!")
+ return
+ reagents.maximum_volume = CLAMP(round(target), 1, buffer)
+
#undef COOLING
#undef HEATING
#undef NEUTRAL
diff --git a/code/modules/plumbing/plumbers/destroyer.dm b/code/modules/plumbing/plumbers/destroyer.dm
index f872e251b80..2c80143d839 100644
--- a/code/modules/plumbing/plumbers/destroyer.dm
+++ b/code/modules/plumbing/plumbers/destroyer.dm
@@ -5,13 +5,9 @@
///we remove 10 reagents per second
var/disposal_rate = 10
-/obj/machinery/plumbing/disposer/Initialize()
+/obj/machinery/plumbing/disposer/Initialize(mapload, bolt)
. = ..()
- AddComponent(/datum/component/plumbing/simple_demand)
-
-/obj/machinery/plumbing/disposer/wrench_act(mob/living/user, obj/item/I)
- default_unfasten_wrench(user, I)
- return TRUE
+ AddComponent(/datum/component/plumbing/simple_demand, bolt)
/obj/machinery/plumbing/disposer/process()
if(stat & NOPOWER)
diff --git a/code/modules/plumbing/plumbers/filter.dm b/code/modules/plumbing/plumbers/filter.dm
index a42227a6413..8f69c090ce4 100644
--- a/code/modules/plumbing/plumbers/filter.dm
+++ b/code/modules/plumbing/plumbers/filter.dm
@@ -3,6 +3,7 @@
name = "chemical filter"
desc = "A chemical filter for filtering chemicals. The left and right outputs appear to be from the perspective of the input port."
icon_state = "filter"
+ density = FALSE
///whitelist of chems id's that go to the left side. Empty to disable port
var/list/left = list()
///whitelist of chem id's that go to the right side. Empty to disable port
@@ -15,14 +16,9 @@
ui_x = 500
ui_y = 300
-
-/obj/machinery/plumbing/filter/Initialize()
+/obj/machinery/plumbing/filter/Initialize(mapload, bolt)
. = ..()
- AddComponent(/datum/component/plumbing/filter)
-
-/obj/machinery/plumbing/filter/wrench_act(mob/living/user, obj/item/I)
- default_unfasten_wrench(user, I)
- return TRUE
+ AddComponent(/datum/component/plumbing/filter, bolt)
/obj/machinery/plumbing/filter/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, datum/tgui/master_ui = null, datum/ui_state/state = GLOB.default_state)
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
@@ -42,23 +38,23 @@
. = TRUE
switch(action)
if("add")
- var/new_chem_name = ckey(input("Enter chemical to filter:", name) as text|null)
+ var/new_chem_name = input("Enter chemical to filter:", name) as text|null
var/chem_id = get_chem_id(new_chem_name)
if(chem_id)
switch(params["which"])
if("left")
- if(!english_left.Find(new_chem_name))
+ if(!left.Find(chem_id))
english_left += new_chem_name
left += chem_id
if("right")
- if(!english_right.Find(new_chem_name))
+ if(!right.Find(chem_id))
english_right += new_chem_name
right += chem_id
else
to_chat(usr, "No such known reagent exists!")
if("remove")
- var/chem_name = params["reagent"] //ckey() isnt necessary here, since it picks from the already ckey'd english_list
+ var/chem_name = params["reagent"]
var/chem_id = get_chem_id(chem_name)
switch(params["which"])
if("left")
diff --git a/code/modules/plumbing/plumbers/pill_press.dm b/code/modules/plumbing/plumbers/pill_press.dm
index 3ad62cdf648..37fa1a1a15d 100644
--- a/code/modules/plumbing/plumbers/pill_press.dm
+++ b/code/modules/plumbing/plumbers/pill_press.dm
@@ -15,13 +15,18 @@
var/pill_number = RANDOM_PILL_STYLE
///list of id's and icons for the pill selection of the ui
var/list/pill_styles
+ ///list of pills stored in the machine, so we dont have 610 pills on one tile
+ var/list/stored_pills = list()
+ ///max amount of pills allowed on our tile before we start storing them instead
+ var/max_floor_pills = 10
- var/xen = 500
- var/yen = 500
-
-/obj/machinery/plumbing/pill_press/Initialize(mapload)
+/obj/machinery/plumbing/pill_press/examine(mob/user)
. = ..()
- AddComponent(/datum/component/plumbing/simple_demand)
+ . += "The [name] currently has [stored_pills.len] stored. There needs to be less than [max_floor_pills] on the floor to continue dispensing."
+
+/obj/machinery/plumbing/pill_press/Initialize(mapload, bolt)
+ . = ..()
+ AddComponent(/datum/component/plumbing/simple_demand, bolt)
//expertly copypasted from chemmasters
var/datum/asset/spritesheet/simple/assets = get_asset_datum(/datum/asset/spritesheet/simple/pills)
@@ -32,23 +37,31 @@
SL["htmltag"] = assets.icon_tag("pill[x]")
pill_styles += list(SL)
-/obj/machinery/plumbing/pill_press/wrench_act(mob/living/user, obj/item/I)
- default_unfasten_wrench(user, I)
- return TRUE
-
/obj/machinery/plumbing/pill_press/process()
if(stat & NOPOWER)
return
if(reagents.total_volume >= pill_size)
- var/obj/item/reagent_containers/pill/P = new(drop_location())
+ var/obj/item/reagent_containers/pill/P = new(src)
reagents.trans_to(P, pill_size)
P.name = pill_name
+ stored_pills += P
if(pill_number == RANDOM_PILL_STYLE)
P.icon_state = "pill[rand(1,21)]"
else
P.icon_state = "pill[pill_number]"
if(P.icon_state == "pill4") //mirrored from chem masters
P.desc = "A tablet or capsule, but not just any, a red one, one taken by the ones not scared of knowledge, freedom, uncertainty and the brutal truths of reality."
+ if(stored_pills.len)
+ var/pill_amount = 0
+ for(var/obj/item/reagent_containers/pill/P in loc)
+ pill_amount++
+ if(pill_amount >= max_floor_pills) //too much so just stop
+ break
+ if(pill_amount < max_floor_pills)
+ var/atom/movable/AM = stored_pills[1] //AM because forceMove is all we need
+ stored_pills -= AM
+ AM.forceMove(drop_location())
+
/obj/machinery/plumbing/pill_press/ui_base_html(html)
var/datum/asset/spritesheet/simple/assets = get_asset_datum(/datum/asset/spritesheet/simple/pills)
diff --git a/code/modules/plumbing/plumbers/reaction_chamber.dm b/code/modules/plumbing/plumbers/reaction_chamber.dm
index 4925edcce96..895f5896796 100644
--- a/code/modules/plumbing/plumbers/reaction_chamber.dm
+++ b/code/modules/plumbing/plumbers/reaction_chamber.dm
@@ -4,25 +4,30 @@
desc = "Keeps chemicals seperated until given conditions are met."
icon_state = "reaction_chamber"
- buffer = 100
+ buffer = 200
reagent_flags = TRANSPARENT | NO_REACT
/**list of set reagents that the reaction_chamber allows in, and must all be present before mixing is enabled.
- * example: list(/datum/reagent/water = 20, /datum/reagent/oil = 50)
+ * example: list(/datum/reagent/water = 20, /datum/reagent/fuel/oil = 50)
*/
var/list/required_reagents = list()
///our reagent goal has been reached, so now we lock our inputs and start emptying
var/emptying = FALSE
-
-/obj/machinery/plumbing/reaction_chamber/Initialize()
+/obj/machinery/plumbing/reaction_chamber/Initialize(mapload, bolt)
. = ..()
- AddComponent(/datum/component/plumbing/reaction_chamber)
+ AddComponent(/datum/component/plumbing/reaction_chamber, bolt)
/obj/machinery/plumbing/reaction_chamber/on_reagent_change()
if(reagents.total_volume == 0 && emptying) //we were emptying, but now we aren't
emptying = FALSE
reagents.flags |= NO_REACT
+/obj/machinery/plumbing/reaction_chamber/power_change()
+ if(use_power != NO_POWER_USE)
+ icon_state = initial(icon_state) + "_on"
+ else
+ icon_state = initial(icon_state)
+
/obj/machinery/plumbing/reaction_chamber/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, datum/tgui/master_ui = null, datum/ui_state/state = GLOB.default_state)
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
if(!ui)
@@ -35,6 +40,7 @@
for(var/A in required_reagents) //make a list where the key is text, because that looks alot better in the ui than a typepath
var/datum/reagent/R = A
text_reagents[initial(R.name)] = required_reagents[R]
+
data["reagents"] = text_reagents
data["emptying"] = emptying
return data
@@ -53,4 +59,4 @@
if(input_reagent && !required_reagents.Find(input_reagent))
var/input_amount = CLAMP(round(input("Enter amount", "Input") as num|null), 1, 100)
if(input_amount)
- required_reagents[input_reagent] = input_amount
\ No newline at end of file
+ required_reagents[input_reagent] = input_amount
diff --git a/code/modules/plumbing/plumbers/splitters.dm b/code/modules/plumbing/plumbers/splitters.dm
index 0a68d807105..bc9efe7a3f7 100644
--- a/code/modules/plumbing/plumbers/splitters.dm
+++ b/code/modules/plumbing/plumbers/splitters.dm
@@ -4,6 +4,8 @@
desc = "A chemical splitter for smart chemical factorization. Waits till a set of conditions is met and then stops all input and splits the buffer evenly or other in two ducts."
icon_state = "splitter"
buffer = 100
+ density = FALSE
+
///constantly switches between TRUE and FALSE. TRUE means the batch tick goes straight, FALSE means the next batch goes in the side duct.
var/turn_straight = TRUE
///how much we must transfer straight. note input can be as high as 10 reagents per process, usually
@@ -12,14 +14,11 @@
var/transfer_side = 5
//the maximum you can set the transfer to
var/max_transfer = 9
+
-/obj/machinery/plumbing/splitter/Initialize()
+/obj/machinery/plumbing/splitter/Initialize(mapload, bolt)
. = ..()
- AddComponent(/datum/component/plumbing/splitter)
-
-/obj/machinery/plumbing/splitter/wrench_act(mob/living/user, obj/item/I)
- default_unfasten_wrench(user, I)
- return TRUE
+ AddComponent(/datum/component/plumbing/splitter, bolt)
/obj/machinery/plumbing/splitter/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, datum/tgui/master_ui = null, datum/ui_state/state = GLOB.default_state)
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
@@ -46,4 +45,4 @@
if("side")
transfer_side = CLAMP(input("New target transfer:", name, transfer_side) as num|null, 1 , max_transfer)
else
- return FALSE
\ No newline at end of file
+ return FALSE
diff --git a/code/modules/plumbing/plumbers/synthesizer.dm b/code/modules/plumbing/plumbers/synthesizer.dm
index 8fd3dc04b88..c066fe2a496 100644
--- a/code/modules/plumbing/plumbers/synthesizer.dm
+++ b/code/modules/plumbing/plumbers/synthesizer.dm
@@ -5,6 +5,8 @@
icon_state = "synthesizer"
icon = 'icons/obj/plumbing/plumbers.dmi'
+ rcd_cost = 25
+ rcd_delay = 15
///Amount we produce for every process. Ideally keep under 5 since thats currently the standard duct capacity
var/amount = 1
@@ -49,14 +51,9 @@
ui_x = 300
ui_y = 435
-/obj/machinery/plumbing/synthesizer/Initialize(mapload)
+/obj/machinery/plumbing/synthesizer/Initialize(mapload, bolt)
. = ..()
- AddComponent(/datum/component/plumbing/simple_supply)
-
-/obj/machinery/plumbing/synthesizer/wrench_act(mob/living/user, obj/item/I)
- ..()
- default_unfasten_wrench(user, I)
- return TRUE
+ AddComponent(/datum/component/plumbing/simple_supply, bolt)
/obj/machinery/plumbing/synthesizer/process()
if(stat & NOPOWER || !reagent_id || !amount)
diff --git a/code/modules/power/apc.dm b/code/modules/power/apc.dm
index 1557556a990..8dd30101f2f 100644
--- a/code/modules/power/apc.dm
+++ b/code/modules/power/apc.dm
@@ -57,8 +57,8 @@
damage_deflection = 10
resistance_flags = FIRE_PROOF
interaction_flags_machine = INTERACT_MACHINE_WIRES_IF_OPEN | INTERACT_MACHINE_ALLOW_SILICON | INTERACT_MACHINE_OPEN_SILICON
- ui_x = 535
- ui_y = 515
+ ui_x = 450
+ ui_y = 460
var/lon_range = 1.5
var/area/area
@@ -93,7 +93,6 @@
var/beenhit = 0 // used for counting how many times it has been hit, used for Aliens at the moment
var/mob/living/silicon/ai/occupier = null
var/transfer_in_progress = FALSE //Is there an AI being transferred out of us?
- var/obj/item/clockwork/integration_cog/integration_cog //Is there a cog siphoning power?
var/longtermpower = 10
var/auto_name = FALSE
var/failure_timer = 0
@@ -266,9 +265,6 @@
else
. += {"It's [ !terminal ? "not" : "" ] wired up.\n
The electronics are[!has_electronics?"n't":""] installed."}
- if(user.Adjacent(src) && integration_cog)
- . += "[src]'s innards have been replaced by strange brass machinery!"
-
else
if (stat & MAINT)
. += "The cover is closed. Something is wrong with it. It doesn't work."
@@ -277,9 +273,6 @@
else
. += "The cover is closed."
- if(integration_cog && is_servant_of_ratvar(user))
- . += "There is an integration cog installed!"
-
. += "Alt-Click the APC to [ locked ? "unlock" : "lock"] the interface."
if(issilicon(user))
@@ -458,16 +451,6 @@
"You remove the power control board.")
new /obj/item/electronics/apc(loc)
return
- else if(integration_cog)
- user.visible_message("[user] starts prying [integration_cog] from [src]...", \
- "You painstakingly start tearing [integration_cog] out of [src]'s guts...")
- W.play_tool_sound(src)
- if(W.use_tool(src, user, 100))
- user.visible_message("[user] destroys [integration_cog] in [src]!", \
- "[integration_cog] comes free with a clank and snaps in two as the machinery returns to normal!")
- playsound(src, 'sound/items/deconstruct.ogg', 50, TRUE)
- QDEL_NULL(integration_cog)
- return
else if (opened!=APC_COVER_REMOVED)
opened = APC_COVER_CLOSED
coverlocked = TRUE //closing cover relocks it
@@ -678,32 +661,6 @@
if (opened==APC_COVER_REMOVED)
opened = APC_COVER_OPENED
update_icon()
- else if(istype(W, /obj/item/clockwork/integration_cog) && is_servant_of_ratvar(user))
- if(integration_cog)
- to_chat(user, "This APC already has a cog.")
- return
- if(!opened)
- user.visible_message("[user] slices [src]'s cover lock, and it swings wide open!", \
- "You slice [src]'s cover lock apart with [W], and the cover swings open.")
- opened = APC_COVER_OPENED
- update_icon()
- else
- user.visible_message("[user] presses [W] into [src]!", \
- "You hold [W] in place within [src], and it slowly begins to warm up...")
- playsound(src, 'sound/machines/click.ogg', 50, TRUE)
- if(!do_after(user, 70, target = src))
- return
- user.visible_message("[user] installs [W] in [src]!", \
- "Replicant alloy rapidly covers the APC's innards, replacing the machinery. \
- This APC will now passively provide power for the cult!")
- playsound(user, 'sound/machines/clockcult/integration_cog_install.ogg', 50, TRUE)
- user.transferItemToLoc(W, src)
- integration_cog = W
- START_PROCESSING(SSfastprocess, W)
- playsound(src, 'sound/machines/clockcult/steam_whoosh.ogg', 50, FALSE)
- opened = APC_COVER_CLOSED
- locked = FALSE
- update_icon()
return
else if(panel_open && !opened && is_wire_tool(W))
wires.interact(user)
@@ -853,7 +810,7 @@
/obj/machinery/power/apc/ui_data(mob/user)
var/list/data = list(
- "locked" = locked && !(integration_cog && is_servant_of_ratvar(user)),
+ "locked" = locked,
"failTime" = failure_timer,
"isOperating" = operating,
"externalPower" = main_status,
@@ -961,7 +918,7 @@
. = UI_INTERACTIVE
/obj/machinery/power/apc/ui_act(action, params)
- if(..() || !can_use(usr, 1) || (locked && !usr.has_unlimited_silicon_privilege && !failure_timer && !(integration_cog && (is_servant_of_ratvar(usr)))))
+ if(..() || !can_use(usr, 1) || (locked && !usr.has_unlimited_silicon_privilege && !failure_timer))
return
switch(action)
if("lock")
diff --git a/code/modules/power/singularity/narsie.dm b/code/modules/power/singularity/narsie.dm
index 19d70f87232..0282511d3de 100644
--- a/code/modules/power/singularity/narsie.dm
+++ b/code/modules/power/singularity/narsie.dm
@@ -15,7 +15,6 @@
light_range = 15
light_color = rgb(255, 0, 0)
gender = FEMALE
- var/clashing = FALSE //If Nar'Sie is fighting Ratvar
/obj/singularity/narsie/large
name = "Nar'Sie"
@@ -101,23 +100,14 @@
makeNewConstruct(/mob/living/simple_animal/hostile/construct/harvester, user, cultoverride = TRUE, loc_override = src.loc)
/obj/singularity/narsie/process()
- if(clashing)
- return
eat()
if(!target || prob(5))
pickcultist()
- if(istype(target, /obj/structure/destructible/clockwork/massive/ratvar))
- move(get_dir(src, target)) //Oh, it's you again.
- else
- move()
+ move()
if(prob(25))
mezzer()
-/obj/singularity/narsie/Process_Spacemove()
- return clashing
-
-
/obj/singularity/narsie/Bump(atom/A)
var/turf/T = get_turf(A)
if(T == loc)
@@ -145,11 +135,6 @@
/obj/singularity/narsie/proc/pickcultist() //Narsie rewards her cultists with being devoured first, then picks a ghost to follow.
var/list/cultists = list()
var/list/noncultists = list()
- for(var/obj/structure/destructible/clockwork/massive/ratvar/enemy in GLOB.poi_list) //Prioritize killing Ratvar
- if(enemy.z != z)
- continue
- acquire(enemy)
- return
for(var/mob/living/carbon/food in GLOB.alive_mob_list) //we don't care about constructs or cult-Ians or whatever. cult-monkeys are fair game i guess
var/turf/pos = get_turf(food)
diff --git a/code/modules/procedural_mapping/mapGenerators/cult.dm b/code/modules/procedural_mapping/mapGenerators/cult.dm
index ea9c7da9460..29028c3774a 100644
--- a/code/modules/procedural_mapping/mapGenerators/cult.dm
+++ b/code/modules/procedural_mapping/mapGenerators/cult.dm
@@ -4,30 +4,13 @@
/datum/mapGeneratorModule/border/cultWalls
spawnableTurfs = list(/turf/closed/wall/mineral/cult = 100)
-/datum/mapGeneratorModule/bottomLayer/clockFloor
- spawnableTurfs = list(/turf/open/floor/clockwork = 100)
-
-/datum/mapGeneratorModule/border/clockWalls
- spawnableTurfs = list(/turf/closed/wall/clockwork = 100)
-
/datum/mapGenerator/cult //walls and floor only
modules = list(/datum/mapGeneratorModule/bottomLayer/cultFloor, \
/datum/mapGeneratorModule/border/cultWalls, \
/datum/mapGeneratorModule/bottomLayer/repressurize)
buildmode_name = "Pattern: Cult Room"
-/datum/mapGenerator/clock //walls and floor only
- modules = list(/datum/mapGeneratorModule/bottomLayer/clockFloor, \
- /datum/mapGeneratorModule/border/clockWalls, \
- /datum/mapGeneratorModule/bottomLayer/repressurize)
- buildmode_name = "Pattern: Clockwork Room"
-
/datum/mapGenerator/cult/floor //floors only
modules = list(/datum/mapGeneratorModule/bottomLayer/cultFloor, \
/datum/mapGeneratorModule/bottomLayer/repressurize)
- buildmode_name = "Block: Cult Floor"
-
-/datum/mapGenerator/clock/floor //floor only
- modules = list(/datum/mapGeneratorModule/bottomLayer/clockFloor, \
- /datum/mapGeneratorModule/bottomLayer/repressurize)
- buildmode_name = "Block: Clockwork Floor"
+ buildmode_name = "Block: Cult Floor"
\ No newline at end of file
diff --git a/code/modules/projectiles/gun.dm b/code/modules/projectiles/gun.dm
index 7b9715bc3d5..734eee26ae4 100644
--- a/code/modules/projectiles/gun.dm
+++ b/code/modules/projectiles/gun.dm
@@ -482,6 +482,7 @@
flashlight_overlay.pixel_x = flight_x_offset
flashlight_overlay.pixel_y = flight_y_offset
add_overlay(flashlight_overlay, TRUE)
+ add_overlay(knife_overlay, TRUE)
else
set_light(0)
cut_overlays(flashlight_overlay, TRUE)
diff --git a/code/modules/projectiles/guns/ballistic/rifle.dm b/code/modules/projectiles/guns/ballistic/rifle.dm
index ddc576ac5b4..26fee3af558 100644
--- a/code/modules/projectiles/guns/ballistic/rifle.dm
+++ b/code/modules/projectiles/guns/ballistic/rifle.dm
@@ -53,6 +53,7 @@ obj/item/gun/ballistic/rifle/attackby(obj/item/A, mob/user, params)
desc = "This piece of junk looks like something that could have been used 700 years ago. It feels slightly moist."
sawn_desc = "An extremely sawn-off Mosin Nagant, popularly known as an \"obrez\". There was probably a reason it wasn't manufactured this short to begin with."
w_class = WEIGHT_CLASS_BULKY
+ weapon_weight = WEAPON_HEAVY
icon_state = "moistnugget"
item_state = "moistnugget"
slot_flags = 0 //no ITEM_SLOT_BACK sprite, alas
diff --git a/code/modules/projectiles/guns/ballistic/shotgun.dm b/code/modules/projectiles/guns/ballistic/shotgun.dm
index cd10fe3c46b..c217128134e 100644
--- a/code/modules/projectiles/guns/ballistic/shotgun.dm
+++ b/code/modules/projectiles/guns/ballistic/shotgun.dm
@@ -24,6 +24,7 @@
bolt_wording = "pump"
cartridge_wording = "shell"
tac_reloads = FALSE
+ weapon_weight = WEAPON_HEAVY
/obj/item/gun/ballistic/shotgun/blow_up(mob/user)
. = 0
@@ -173,6 +174,12 @@
. = ..()
if(unique_reskin && !current_skin && user.canUseTopic(src, BE_CLOSE, NO_DEXTERY))
reskin_obj(user)
+
+/obj/item/gun/ballistic/shotgun/doublebarrel/sawoff(mob/user)
+ . = ..()
+ if(.)
+ weapon_weight = WEAPON_MEDIUM
+
// IMPROVISED SHOTGUN //
/obj/item/gun/ballistic/shotgun/doublebarrel/improvised
diff --git a/code/modules/reagents/chemistry/holder.dm b/code/modules/reagents/chemistry/holder.dm
index 5b09b83bcc0..5d55146ac6d 100644
--- a/code/modules/reagents/chemistry/holder.dm
+++ b/code/modules/reagents/chemistry/holder.dm
@@ -925,5 +925,5 @@
/proc/get_chem_id(chem_name)
for(var/X in GLOB.chemical_reagents_list)
var/datum/reagent/R = GLOB.chemical_reagents_list[X]
- if(chem_name == replacetext(lowertext(R.name), " ", ""))
+ if(ckey(chem_name) == ckey(lowertext(R.name)))
return X
diff --git a/code/modules/reagents/chemistry/machinery/chem_dispenser.dm b/code/modules/reagents/chemistry/machinery/chem_dispenser.dm
index 70faaecae22..2d2530b156f 100644
--- a/code/modules/reagents/chemistry/machinery/chem_dispenser.dm
+++ b/code/modules/reagents/chemistry/machinery/chem_dispenser.dm
@@ -23,7 +23,7 @@
resistance_flags = FIRE_PROOF | ACID_PROOF
circuit = /obj/item/circuitboard/machine/chem_dispenser
ui_x = 565
- ui_y = 550
+ ui_y = 620
var/obj/item/stock_parts/cell/cell
var/powerefficiency = 0.1
@@ -70,7 +70,7 @@
/datum/reagent/ammonia,
/datum/reagent/ash,
/datum/reagent/diethylamine,
- /datum/reagent/oil,
+ /datum/reagent/fuel/oil,
/datum/reagent/saltpetre
)
var/list/emagged_reagents = list(
@@ -646,7 +646,7 @@
/datum/reagent/ammonia,
/datum/reagent/ash,
/datum/reagent/diethylamine,
- /datum/reagent/oil,
+ /datum/reagent/fuel/oil,
/datum/reagent/saltpetre,
/datum/reagent/medicine/mine_salve,
/datum/reagent/medicine/morphine,
diff --git a/code/modules/reagents/chemistry/machinery/smoke_machine.dm b/code/modules/reagents/chemistry/machinery/smoke_machine.dm
index 82ad1937215..28e4bd88fc4 100644
--- a/code/modules/reagents/chemistry/machinery/smoke_machine.dm
+++ b/code/modules/reagents/chemistry/machinery/smoke_machine.dm
@@ -34,6 +34,7 @@
/obj/machinery/smoke_machine/Initialize()
. = ..()
create_reagents(REAGENTS_BASE_VOLUME)
+ AddComponent(/datum/component/plumbing/simple_demand)
for(var/obj/item/stock_parts/matter_bin/B in component_parts)
reagents.maximum_volume += REAGENTS_BASE_VOLUME * B.rating
diff --git a/code/modules/reagents/chemistry/reagents/cat2_medicine_reagents.dm b/code/modules/reagents/chemistry/reagents/cat2_medicine_reagents.dm
index ef5e6a22ab5..8f9517ab52f 100644
--- a/code/modules/reagents/chemistry/reagents/cat2_medicine_reagents.dm
+++ b/code/modules/reagents/chemistry/reagents/cat2_medicine_reagents.dm
@@ -109,7 +109,7 @@
. = ..()
/datum/reagent/medicine/C2/lenturi/on_mob_end_metabolize(mob/living/carbon/M)
M.remove_movespeed_modifier(MOVESPEED_ID_LENTURI)
-
+
. = ..()
/datum/reagent/medicine/C2/aiuri
name = "Aiuri"
@@ -206,7 +206,7 @@
if(chemtemp < radbonustemp*0.1) //if you're super chilly, it takes off 25% of your current rads
M.radiation = round(M.radiation * 0.75)
else if(chemtemp < radbonustemp)//else if you're under the chill-zone, it takes off 10% of your current rads
- M.radiation = round(M.radiation * 0.25)
+ M.radiation = round(M.radiation * 0.9)
M.radiation -= radcalc
healypoints += (radcalc/5)
diff --git a/code/modules/reagents/chemistry/reagents/other_reagents.dm b/code/modules/reagents/chemistry/reagents/other_reagents.dm
index 1a41712039c..39e79784262 100644
--- a/code/modules/reagents/chemistry/reagents/other_reagents.dm
+++ b/code/modules/reagents/chemistry/reagents/other_reagents.dm
@@ -207,8 +207,8 @@
..()
/datum/reagent/water/holywater/reaction_mob(mob/living/M, method=TOUCH, reac_volume)
- if(is_servant_of_ratvar(M))
- to_chat(M, "A darkness begins to spread its unholy tendrils through your mind, purging the Justiciar's influence!")
+ if(iscultist(M))
+ to_chat(M, "A darkness begins to spread its unholy tendrils through your mind, purging the Old God's influence!")
..()
/datum/reagent/water/holywater/on_mob_life(mob/living/carbon/M)
@@ -233,25 +233,13 @@
M.Unconscious(120)
to_chat(M, "[pick("Your blood is your bond - you are nothing without it", "Do not forget your place", \
"All that power, and you still fail?", "If you cannot scour this poison, I shall scour your meager life!")].")
- else if(is_servant_of_ratvar(M) && prob(8))
- switch(pick("speech", "message", "emote"))
- if("speech")
- clockwork_say(M, "...[text2ratvar(pick("Engine... your light grows dark...", "Where are you, master?", "He lies rusting in Error...", "Purge all untruths and... and... something..."))]")
- if("message")
- to_chat(M, "[pick("Ratvar's illumination of your mind has begun to flicker", "He lies rusting in Reebe, derelict and forgotten. And there he shall stay", \
- "You can't save him. Nothing can save him now", "It seems that Nar'Sie will triumph after all")].")
- if("emote")
- M.visible_message("[M] [pick("whimpers quietly", "shivers as though cold", "glances around in paranoia")].")
if(data >= 60) // 30 units, 135 seconds
- if(iscultist(M) || is_servant_of_ratvar(M))
- if(iscultist(M))
- SSticker.mode.remove_cultist(M.mind, FALSE, TRUE)
- else if(is_servant_of_ratvar(M))
- remove_servant_of_ratvar(M)
- M.jitteriness = 0
- M.stuttering = 0
- holder.remove_reagent(type, volume) // maybe this is a little too perfect and a max() cap on the statuses would be better??
- return
+ if(iscultist(M))
+ SSticker.mode.remove_cultist(M.mind, FALSE, TRUE)
+ M.jitteriness = 0
+ M.stuttering = 0
+ holder.remove_reagent(type, volume) // maybe this is a little too perfect and a max() cap on the statuses would be better??
+ return
holder.remove_reagent(type, 0.4) //fixed consumption to prevent balancing going out of whack
/datum/reagent/water/holywater/reaction_turf(turf/T, reac_volume)
@@ -1364,7 +1352,7 @@
-/datum/reagent/oil
+/datum/reagent/fuel/oil
name = "Oil"
description = "Burns in a small smoky fire, mostly used to get Ash."
reagent_state = LIQUID
@@ -1394,15 +1382,97 @@
name = "Carpet"
description = "For those that need a more creative way to roll out a red carpet."
reagent_state = LIQUID
- color = "#C8A5DC"
+ color = "#771100"
taste_description = "carpet" // Your tounge feels furry.
+ var/carpet_type = /turf/open/floor/carpet
/datum/reagent/carpet/reaction_turf(turf/T, reac_volume)
if(isplatingturf(T) || istype(T, /turf/open/floor/plasteel))
var/turf/open/floor/F = T
- F.PlaceOnTop(/turf/open/floor/carpet, flags = CHANGETURF_INHERIT_AIR)
+ F.PlaceOnTop(carpet_type, flags = CHANGETURF_INHERIT_AIR)
..()
+/datum/reagent/carpet/black
+ name = "Black Carpet"
+ description = "The carpet also comes in... BLAPCK" //yes, the typo is intentional
+ color = "#1E1E1E"
+ taste_description = "licorice"
+ carpet_type = /turf/open/floor/carpet/black
+
+/datum/reagent/carpet/blue
+ name = "Blue Carpet"
+ description = "For those that really need to chill out for a while."
+ color = "#0000DC"
+ taste_description = "frozen carpet"
+ carpet_type = /turf/open/floor/carpet/blue
+
+/datum/reagent/carpet/cyan
+ name = "Cyan Carpet"
+ description = "For those that need a throwback to the years of using poison as a construction material. Smells like asbestos."
+ color = "#00B4FF"
+ taste_description = "asbestos"
+ carpet_type = /turf/open/floor/carpet/cyan
+
+/datum/reagent/carpet/green
+ name = "Green Carpet"
+ description = "For those that need the perfect flourish for your green eggs and ham."
+ color = "#A8E61D"
+ taste_description = "Green" //the caps is intentional
+ carpet_type = /turf/open/floor/carpet/green
+
+/datum/reagent/carpet/orange
+ name = "Orange Carpet"
+ description = "For those that prefer a healthy carpet to go along with their healthy diet."
+ color = "#E78108"
+ taste_description = "orange juice"
+ carpet_type = /turf/open/floor/carpet/orange
+
+/datum/reagent/carpet/purple
+ name = "Purple Carpet"
+ description = "For those that need to waste copious amounts of healing jelly in order to look fancy."
+ color = "#91D865"
+ taste_description = "jelly"
+ carpet_type = /turf/open/floor/carpet/purple
+
+/datum/reagent/carpet/red
+ name = "Red Carpet"
+ description = "For those that need an even redder carpet."
+ color = "#731008"
+ taste_description = "blood and gibs"
+ carpet_type = /turf/open/floor/carpet/red
+
+/datum/reagent/carpet/royal
+ name = "Royal Carpet?"
+ description = "For those that break the game and need to make an issue report."
+
+/datum/reagent/carpet/royal/on_mob_life(mob/living/carbon/M)
+ . = ..()
+ if(!M.mind?.assigned_role)
+ return
+ switch(M.mind.assigned_role)
+ if("Chief Medical Officer", "Captain", "Chief Engineer", "Research Director", "Head of Personnel")
+ if(prob(10))
+ to_chat(M, "You feel like royalty.")
+ if(prob(5))
+ M.say(pick("Peasants..","This carpet is worth more than your contracts!","I could fire you at any time..."), forced = "royal carpet")
+ if("Quartermaster")
+ if(prob(15))
+ to_chat(M, "You feel like an impostor...")
+
+/datum/reagent/carpet/royal/black
+ name = "Royal Black Carpet"
+ description = "For those that feel the need to show off their timewasting skills."
+ color = "#000000"
+ taste_description = "royalty"
+ carpet_type = /turf/open/floor/carpet/royalblack
+
+/datum/reagent/carpet/royal/blue
+ name = "Royal Blue Carpet"
+ description = "For those that feel the need to show off their timewasting skills.. in BLUE."
+ color = "#5A64C8"
+ taste_description = "blueyalty" //also intentional
+ carpet_type = /turf/open/floor/carpet/royalblue
+
/datum/reagent/bromine
name = "Bromine"
description = "A brownish liquid that's highly reactive. Useful for stopping free radicals, but not intended for human consumption."
@@ -1850,4 +1920,4 @@
description = "Just add water!"
color = "#9C5A19"
taste_description = "bananas"
- can_synth = TRUE
\ No newline at end of file
+ can_synth = TRUE
diff --git a/code/modules/reagents/chemistry/reagents/toxin_reagents.dm b/code/modules/reagents/chemistry/reagents/toxin_reagents.dm
index c57565885a0..bfbd36a21fc 100644
--- a/code/modules/reagents/chemistry/reagents/toxin_reagents.dm
+++ b/code/modules/reagents/chemistry/reagents/toxin_reagents.dm
@@ -721,42 +721,6 @@
animate(whole_screen, transform = matrix(), time = 5, easing = QUAD_EASING)
..()
-/datum/reagent/toxin/skewium
- name = "Skewium"
- description = "A strange, dull coloured liquid that appears to warp back and forth inside its container. Causes any consumer to experience a visual phenomena similar to said warping."
- silent_toxin = TRUE
- reagent_state = LIQUID
- color = "#ADBDCD"
- metabolization_rate = 0.8 * REAGENTS_METABOLISM
- toxpwr = 0.25
- taste_description = "skewing"
-
-/datum/reagent/toxin/skewium/on_mob_life(mob/living/carbon/M)
- if(M.hud_used)
- if(current_cycle >= 5 && current_cycle % 3 == 0)
- var/list/screens = list(M.hud_used.plane_masters["[FLOOR_PLANE]"], M.hud_used.plane_masters["[GAME_PLANE]"], M.hud_used.plane_masters["[LIGHTING_PLANE]"])
- var/matrix/skew = matrix()
- var/intensity = 8
- skew.set_skew(rand(-intensity,intensity), rand(-intensity,intensity))
- var/matrix/newmatrix = skew
-
- if(prob(33)) // 1/3rd of the time, let's make it stack with the previous matrix! Mwhahahaha!
- var/obj/screen/plane_master/PM = M.hud_used.plane_masters["[GAME_PLANE]"]
- newmatrix = skew * PM.transform
-
- for(var/whole_screen in screens)
- animate(whole_screen, transform = newmatrix, time = 5, easing = QUAD_EASING, loop = -1)
- animate(transform = -newmatrix, time = 5, easing = QUAD_EASING)
- return ..()
-
-/datum/reagent/toxin/skewium/on_mob_end_metabolize(mob/living/M)
- if(M && M.hud_used)
- var/list/screens = list(M.hud_used.plane_masters["[FLOOR_PLANE]"], M.hud_used.plane_masters["[GAME_PLANE]"], M.hud_used.plane_masters["[LIGHTING_PLANE]"])
- for(var/whole_screen in screens)
- animate(whole_screen, transform = matrix(), time = 5, easing = QUAD_EASING)
- ..()
-
-
/datum/reagent/toxin/anacea
name = "Anacea"
description = "A toxin that quickly purges medicines and metabolizes very slowly."
diff --git a/code/modules/reagents/chemistry/recipes/cat2_medicines.dm b/code/modules/reagents/chemistry/recipes/cat2_medicines.dm
index be3f08b6d86..b97493ca4e5 100644
--- a/code/modules/reagents/chemistry/recipes/cat2_medicines.dm
+++ b/code/modules/reagents/chemistry/recipes/cat2_medicines.dm
@@ -35,7 +35,7 @@
name = "Convermol"
id = /datum/reagent/medicine/C2/convermol
results = list(/datum/reagent/medicine/C2/convermol = 3)
- required_reagents = list(/datum/reagent/hydrogen = 1, /datum/reagent/fluorine = 1, /datum/reagent/oil = 1)
+ required_reagents = list(/datum/reagent/hydrogen = 1, /datum/reagent/fluorine = 1, /datum/reagent/fuel/oil = 1)
required_temp = 370
mix_message = "The mixture rapidly turns into a dense pink liquid."
@@ -49,7 +49,7 @@
/*****TOX*****/
/datum/chemical_reaction/seiver
- name = "Fiziver"
+ name = "Seiver"
id = /datum/reagent/medicine/C2/seiver
results = list(/datum/reagent/medicine/C2/seiver = 3)
required_reagents = list(/datum/reagent/nitrogen = 1, /datum/reagent/potassium = 1, /datum/reagent/aluminium = 1)
diff --git a/code/modules/reagents/chemistry/recipes/medicine.dm b/code/modules/reagents/chemistry/recipes/medicine.dm
index 5a95ab9e680..7138851b590 100644
--- a/code/modules/reagents/chemistry/recipes/medicine.dm
+++ b/code/modules/reagents/chemistry/recipes/medicine.dm
@@ -40,7 +40,7 @@
name = "Miner's Salve"
id = /datum/reagent/medicine/mine_salve
results = list(/datum/reagent/medicine/mine_salve = 3)
- required_reagents = list(/datum/reagent/oil = 1, /datum/reagent/water = 1, /datum/reagent/iron = 1)
+ required_reagents = list(/datum/reagent/fuel/oil = 1, /datum/reagent/water = 1, /datum/reagent/iron = 1)
/datum/chemical_reaction/mine_salve2
name = "Miner's Salve"
@@ -95,14 +95,14 @@
name = "Ephedrine"
id = /datum/reagent/medicine/ephedrine
results = list(/datum/reagent/medicine/ephedrine = 4)
- required_reagents = list(/datum/reagent/consumable/sugar = 1, /datum/reagent/oil = 1, /datum/reagent/hydrogen = 1, /datum/reagent/diethylamine = 1)
+ required_reagents = list(/datum/reagent/consumable/sugar = 1, /datum/reagent/fuel/oil = 1, /datum/reagent/hydrogen = 1, /datum/reagent/diethylamine = 1)
mix_message = "The solution fizzes and gives off toxic fumes."
/datum/chemical_reaction/diphenhydramine
name = "Diphenhydramine"
id = /datum/reagent/medicine/diphenhydramine
results = list(/datum/reagent/medicine/diphenhydramine = 4)
- required_reagents = list(/datum/reagent/oil = 1, /datum/reagent/carbon = 1, /datum/reagent/bromine = 1, /datum/reagent/diethylamine = 1, /datum/reagent/consumable/ethanol = 1)
+ required_reagents = list(/datum/reagent/fuel/oil = 1, /datum/reagent/carbon = 1, /datum/reagent/bromine = 1, /datum/reagent/diethylamine = 1, /datum/reagent/consumable/ethanol = 1)
mix_message = "The mixture dries into a pale blue powder."
/datum/chemical_reaction/oculine
@@ -178,7 +178,7 @@
name = "Haloperidol"
id = /datum/reagent/medicine/haloperidol
results = list(/datum/reagent/medicine/haloperidol = 5)
- required_reagents = list(/datum/reagent/chlorine = 1, /datum/reagent/fluorine = 1, /datum/reagent/aluminium = 1, /datum/reagent/medicine/potass_iodide = 1, /datum/reagent/oil = 1)
+ required_reagents = list(/datum/reagent/chlorine = 1, /datum/reagent/fluorine = 1, /datum/reagent/aluminium = 1, /datum/reagent/medicine/potass_iodide = 1, /datum/reagent/fuel/oil = 1)
/datum/chemical_reaction/regen_jelly
name = "Regenerative Jelly"
diff --git a/code/modules/reagents/chemistry/recipes/others.dm b/code/modules/reagents/chemistry/recipes/others.dm
index 2305af51785..da4da9949e3 100644
--- a/code/modules/reagents/chemistry/recipes/others.dm
+++ b/code/modules/reagents/chemistry/recipes/others.dm
@@ -15,7 +15,7 @@
name = "Spray Tan"
id = /datum/reagent/spraytan
results = list(/datum/reagent/spraytan = 2)
- required_reagents = list(/datum/reagent/consumable/orangejuice = 1, /datum/reagent/oil = 1)
+ required_reagents = list(/datum/reagent/consumable/orangejuice = 1, /datum/reagent/fuel/oil = 1)
/datum/chemical_reaction/spraytan2
name = "Spray Tan"
@@ -447,7 +447,7 @@
name = /datum/reagent/acetone
id = /datum/reagent/acetone
results = list(/datum/reagent/acetone = 3)
- required_reagents = list(/datum/reagent/oil = 1, /datum/reagent/fuel = 1, /datum/reagent/oxygen = 1)
+ required_reagents = list(/datum/reagent/fuel/oil = 1, /datum/reagent/fuel = 1, /datum/reagent/oxygen = 1)
/datum/chemical_reaction/carpet
name = /datum/reagent/carpet
@@ -455,23 +455,81 @@
results = list(/datum/reagent/carpet = 2)
required_reagents = list(/datum/reagent/drug/space_drugs = 1, /datum/reagent/blood = 1)
+/datum/chemical_reaction/carpet/black
+ name = /datum/reagent/carpet/black
+ id = /datum/reagent/carpet/black
+ results = list(/datum/reagent/carpet/black = 2)
+ required_reagents = list(/datum/reagent/carpet = 1, /datum/reagent/fuel/oil = 1)
+
+/datum/chemical_reaction/carpet/blue
+ name = /datum/reagent/carpet/blue
+ id = /datum/reagent/carpet/blue
+ results = list(/datum/reagent/carpet/blue = 2)
+ required_reagents = list(/datum/reagent/carpet = 1, /datum/reagent/cryostylane = 1)
+
+/datum/chemical_reaction/carpet/cyan
+ name = /datum/reagent/carpet/cyan
+ id = /datum/reagent/carpet/cyan
+ results = list(/datum/reagent/carpet/cyan = 2)
+ required_reagents = list(/datum/reagent/carpet = 1, /datum/reagent/toxin/cyanide = 1)
+ //cyan = cyanide get it huehueuhuehuehheuhe
+
+/datum/chemical_reaction/carpet/green
+ name = /datum/reagent/carpet/green
+ id = /datum/reagent/carpet/green
+ results = list(/datum/reagent/carpet/green = 2)
+ required_reagents = list(/datum/reagent/carpet = 1, /datum/reagent/consumable/ethanol/beer/green = 1)
+ //make green beer by grinding up green crayons and mixing with beer
+
+/datum/chemical_reaction/carpet/orange
+ name = /datum/reagent/carpet/orange
+ id = /datum/reagent/carpet/orange
+ results = list(/datum/reagent/carpet/orange = 2)
+ required_reagents = list(/datum/reagent/carpet = 1, /datum/reagent/consumable/orangejuice = 1)
+
+/datum/chemical_reaction/carpet/purple
+ name = /datum/reagent/carpet/purple
+ id = /datum/reagent/carpet/purple
+ results = list(/datum/reagent/carpet/purple = 2)
+ required_reagents = list(/datum/reagent/carpet = 1, /datum/reagent/medicine/regen_jelly = 1)
+ //slimes only party
+
+/datum/chemical_reaction/carpet/red
+ name = /datum/reagent/carpet/red
+ id = /datum/reagent/carpet/red
+ results = list(/datum/reagent/carpet/red = 2)
+ required_reagents = list(/datum/reagent/carpet/ = 1, /datum/reagent/liquidgibs = 1)
+
+/datum/chemical_reaction/carpet/royalblack
+ name = /datum/reagent/carpet/royal/black
+ id = /datum/reagent/carpet/royal/black
+ results = list(/datum/reagent/carpet/royal/black = 2)
+ required_reagents = list(/datum/reagent/carpet/black = 1, /datum/reagent/royal_bee_jelly = 1)
+
+/datum/chemical_reaction/carpet/royalblue
+ name = /datum/reagent/carpet/royal/blue
+ id = /datum/reagent/carpet/royal/blue
+ results = list(/datum/reagent/carpet/royal/blue = 2)
+ required_reagents = list(/datum/reagent/carpet/blue = 1, /datum/reagent/royal_bee_jelly = 1)
+
+
/datum/chemical_reaction/oil
name = "Oil"
- id = /datum/reagent/oil
- results = list(/datum/reagent/oil = 3)
+ id = /datum/reagent/fuel/oil
+ results = list(/datum/reagent/fuel/oil = 3)
required_reagents = list(/datum/reagent/fuel = 1, /datum/reagent/carbon = 1, /datum/reagent/hydrogen = 1)
/datum/chemical_reaction/phenol
name = /datum/reagent/phenol
id = /datum/reagent/phenol
results = list(/datum/reagent/phenol = 3)
- required_reagents = list(/datum/reagent/water = 1, /datum/reagent/chlorine = 1, /datum/reagent/oil = 1)
+ required_reagents = list(/datum/reagent/water = 1, /datum/reagent/chlorine = 1, /datum/reagent/fuel/oil = 1)
/datum/chemical_reaction/ash
name = "Ash"
id = /datum/reagent/ash
results = list(/datum/reagent/ash = 1)
- required_reagents = list(/datum/reagent/oil = 1)
+ required_reagents = list(/datum/reagent/fuel/oil = 1)
required_temp = 480
/datum/chemical_reaction/colorful_reagent
@@ -603,7 +661,7 @@
/datum/chemical_reaction/plastic_polymers
name = "plastic polymers"
id = /datum/reagent/plastic_polymers
- required_reagents = list(/datum/reagent/oil = 5, /datum/reagent/toxin/acid = 2, /datum/reagent/ash = 3)
+ required_reagents = list(/datum/reagent/fuel/oil = 5, /datum/reagent/toxin/acid = 2, /datum/reagent/ash = 3)
required_temp = 374 //lazily consistent with soap & other crafted objects generically created with heat.
/datum/chemical_reaction/plastic_polymers/on_reaction(datum/reagents/holder, created_volume)
@@ -629,7 +687,7 @@
name = "artificial slime jelly"
id = /datum/reagent/toxin/slimejelly
results = list(/datum/reagent/toxin/slimejelly = 5)
- required_reagents = list(/datum/reagent/oil = 3, /datum/reagent/uranium/radium = 2, /datum/reagent/consumable/tinlux =1)
+ required_reagents = list(/datum/reagent/fuel/oil = 3, /datum/reagent/uranium/radium = 2, /datum/reagent/consumable/tinlux =1)
required_container = /obj/item/reagent_containers/food/snacks/grown/mushroom/glowshroom
mix_message = "The mushroom's insides bubble and pop and it becomes very limp."
diff --git a/code/modules/reagents/chemistry/recipes/pyrotechnics.dm b/code/modules/reagents/chemistry/recipes/pyrotechnics.dm
index 4386637756d..d1e6df0de13 100644
--- a/code/modules/reagents/chemistry/recipes/pyrotechnics.dm
+++ b/code/modules/reagents/chemistry/recipes/pyrotechnics.dm
@@ -359,7 +359,7 @@
name = "Napalm"
id = /datum/reagent/napalm
results = list(/datum/reagent/napalm = 3)
- required_reagents = list(/datum/reagent/oil = 1, /datum/reagent/fuel = 1, /datum/reagent/consumable/ethanol = 1 )
+ required_reagents = list(/datum/reagent/fuel/oil = 1, /datum/reagent/fuel = 1, /datum/reagent/consumable/ethanol = 1 )
/datum/chemical_reaction/cryostylane
name = /datum/reagent/cryostylane
diff --git a/code/modules/reagents/chemistry/recipes/toxins.dm b/code/modules/reagents/chemistry/recipes/toxins.dm
index d2c52227e30..000e26ee6f9 100644
--- a/code/modules/reagents/chemistry/recipes/toxins.dm
+++ b/code/modules/reagents/chemistry/recipes/toxins.dm
@@ -17,7 +17,7 @@
name = "Cyanide"
id = /datum/reagent/toxin/cyanide
results = list(/datum/reagent/toxin/cyanide = 3)
- required_reagents = list(/datum/reagent/oil = 1, /datum/reagent/ammonia = 1, /datum/reagent/oxygen = 1)
+ required_reagents = list(/datum/reagent/fuel/oil = 1, /datum/reagent/ammonia = 1, /datum/reagent/oxygen = 1)
required_temp = 380
/datum/chemical_reaction/itching_powder
@@ -101,13 +101,6 @@
required_reagents = list(/datum/reagent/toxin/mindbreaker = 1, /datum/reagent/teslium = 1, /datum/reagent/toxin/fentanyl = 1)
mix_message = "After sparks, fire, and the smell of mindbreaker, the mix is constantly spinning with no stop in sight."
-/datum/chemical_reaction/skewium
- name = "Skewium"
- id = "Skewium"
- results = list(/datum/reagent/toxin/skewium = 5)
- required_reagents = list(/datum/reagent/toxin/rotatium = 2, /datum/reagent/toxin/plasma = 2, /datum/reagent/toxin/acid = 1)
- mix_message = "Wow! it turns out if you mix rotatium with some plasma and sulphuric acid, it gets even worse!"
-
/datum/chemical_reaction/anacea
name = "Anacea"
id = /datum/reagent/toxin/anacea
diff --git a/code/modules/recycling/disposal/bin.dm b/code/modules/recycling/disposal/bin.dm
index 700bb3926f6..921ab8444bd 100644
--- a/code/modules/recycling/disposal/bin.dm
+++ b/code/modules/recycling/disposal/bin.dm
@@ -298,8 +298,7 @@
data["full_pressure"] = full_pressure
data["pressure_charging"] = pressure_charging
data["panel_open"] = panel_open
- var/per = CLAMP(100* air_contents.return_pressure() / (SEND_PRESSURE), 0, 100)
- data["per"] = round(per, 1)
+ data["per"] = CLAMP01(air_contents.return_pressure() / (SEND_PRESSURE))
data["isai"] = isAI(user)
return data
diff --git a/code/modules/research/designs/autolathe_designs.dm b/code/modules/research/designs/autolathe_designs.dm
index 6deece3441a..8b3e499f36b 100644
--- a/code/modules/research/designs/autolathe_designs.dm
+++ b/code/modules/research/designs/autolathe_designs.dm
@@ -124,6 +124,15 @@
category = list("initial","Tools","Tool Designs")
departmental_flags = DEPARTMENTAL_FLAG_ENGINEERING | DEPARTMENTAL_FLAG_SCIENCE
+/datum/design/plunger
+ name = "Plunger"
+ id = "plunger"
+ build_type = AUTOLATHE | PROTOLATHE
+ materials = list(/datum/material/iron = 150)
+ build_path = /obj/item/plunger
+ category = list("initial","Tools","Tool Designs")
+ departmental_flags = DEPARTMENTAL_FLAG_ENGINEERING | DEPARTMENTAL_FLAG_MEDICAL
+
/datum/design/welding_helmet
name = "Welding Helmet"
id = "welding_helmet"
@@ -691,6 +700,14 @@
build_path = /obj/item/pipe_dispenser
category = list("hacked", "Construction")
+/datum/design/plumbing_rcd
+ name = "Plumbing Constructor"
+ id = "plumbing_rcd"
+ build_type = AUTOLATHE
+ materials = list(/datum/material/iron = 75000, /datum/material/glass = 37500)
+ build_path = /obj/item/construction/plumbing
+ category = list("hacked", "Construction")
+
/datum/design/electropack
name = "Electropack"
id = "electropack"
@@ -966,3 +983,11 @@
materials = list(/datum/material/iron = 5000, /datum/material/glass = 2000)
build_path = /obj/item/vending_refill/custom
category = list("initial", "Misc")
+
+/datum/design/ducts
+ name = "Fluid Ducts"
+ id = "fluid_ducts"
+ build_type = AUTOLATHE
+ materials = list(/datum/material/iron = 500)
+ build_path = /obj/item/stack/ducts
+ category = list("initial", "Construction")
diff --git a/code/modules/research/designs/machine_designs.dm b/code/modules/research/designs/machine_designs.dm
index 1e1969eee9b..d1ba3e7a1c2 100644
--- a/code/modules/research/designs/machine_designs.dm
+++ b/code/modules/research/designs/machine_designs.dm
@@ -601,4 +601,4 @@
id = "medical_kiosk"
build_path = /obj/item/circuitboard/machine/medical_kiosk
category = list ("Medical Machinery")
- departmental_flags = DEPARTMENTAL_FLAG_MEDICAL
+ departmental_flags = DEPARTMENTAL_FLAG_MEDICAL
\ No newline at end of file
diff --git a/code/modules/research/techweb/all_nodes.dm b/code/modules/research/techweb/all_nodes.dm
index c5551a324b2..295611e7405 100644
--- a/code/modules/research/techweb/all_nodes.dm
+++ b/code/modules/research/techweb/all_nodes.dm
@@ -48,7 +48,7 @@
starting_node = TRUE
display_name = "Basic Tools"
description = "Basic mechanical, electronic, surgical and botanical tools."
- design_ids = list("screwdriver", "wrench", "wirecutters", "crowbar", "multitool", "welding_tool", "tscanner", "analyzer", "cable_coil", "pipe_painter", "airlock_painter", "scalpel", "circular_saw", "surgicaldrill", "retractor", "cautery", "hemostat", "surgical_drapes", "syringe", "cultivator", "plant_analyzer", "shovel", "spade", "hatchet", "mop")
+ design_ids = list("screwdriver", "wrench", "wirecutters", "crowbar", "multitool", "welding_tool", "tscanner", "analyzer", "cable_coil", "pipe_painter", "airlock_painter", "scalpel", "circular_saw", "surgicaldrill", "retractor", "cautery", "hemostat", "surgical_drapes", "syringe", "cultivator", "plant_analyzer", "shovel", "spade", "hatchet", "mop", "plunger")
/////////////////////////Biotech/////////////////////////
/datum/techweb_node/biotech
diff --git a/code/modules/ruins/lavaland_ruin_code.dm b/code/modules/ruins/lavaland_ruin_code.dm
index 4f16b64c58c..36bfa09accd 100644
--- a/code/modules/ruins/lavaland_ruin_code.dm
+++ b/code/modules/ruins/lavaland_ruin_code.dm
@@ -78,7 +78,6 @@
/obj/item/stack/sheet/cloth = /datum/species/golem/cloth,
/obj/item/stack/sheet/mineral/adamantine = /datum/species/golem/adamantine,
/obj/item/stack/sheet/plastic = /datum/species/golem/plastic,
- /obj/item/stack/tile/brass = /datum/species/golem/clockwork,
/obj/item/stack/tile/bronze = /datum/species/golem/bronze,
/obj/item/stack/sheet/cardboard = /datum/species/golem/cardboard,
/obj/item/stack/sheet/leather = /datum/species/golem/leather,
diff --git a/code/modules/shuttle/emergency.dm b/code/modules/shuttle/emergency.dm
index 2236334dc13..cda33b4524c 100644
--- a/code/modules/shuttle/emergency.dm
+++ b/code/modules/shuttle/emergency.dm
@@ -10,7 +10,7 @@
icon_keyboard = "tech_key"
ui_x = 400
ui_y = 400
-
+
var/auth_need = 3
var/list/authorized = list()
@@ -453,7 +453,6 @@
icon_state = "dorm_available"
light_color = LIGHT_COLOR_BLUE
density = FALSE
- clockwork = TRUE //it'd look weird
/obj/machinery/computer/shuttle/pod/update_icon()
return
diff --git a/code/modules/shuttle/navigation_computer.dm b/code/modules/shuttle/navigation_computer.dm
index 5f4b7143626..b2fd06a1a17 100644
--- a/code/modules/shuttle/navigation_computer.dm
+++ b/code/modules/shuttle/navigation_computer.dm
@@ -10,7 +10,7 @@
var/list/jumpto_ports = list() //hashset of ports to jump to and ignore for collision purposes
var/obj/docking_port/stationary/my_port //the custom docking port placed by this console
var/obj/docking_port/mobile/shuttle_port //the mobile docking port of the connected shuttle
- var/list/locked_traits = list(ZTRAIT_RESERVED, ZTRAIT_CENTCOM, ZTRAIT_AWAY, ZTRAIT_REEBE) //traits forbided for custom docking
+ var/list/locked_traits = list(ZTRAIT_RESERVED, ZTRAIT_CENTCOM, ZTRAIT_AWAY) //traits forbided for custom docking
var/view_range = 7
var/x_offset = 0
var/y_offset = 0
diff --git a/code/modules/shuttle/supply.dm b/code/modules/shuttle/supply.dm
index 6c6c49a1198..d32d40a72e0 100644
--- a/code/modules/shuttle/supply.dm
+++ b/code/modules/shuttle/supply.dm
@@ -15,8 +15,6 @@ GLOBAL_LIST_INIT(blacklisted_cargo_types, typecacheof(list(
/obj/effect/mob_spawn,
/obj/effect/hierophant,
/obj/structure/receiving_pad,
- /obj/effect/clockwork/spatial_gateway,
- /obj/structure/destructible/clockwork/powered/clockwork_obelisk,
/obj/item/warp_cube,
/obj/machinery/rnd/production, //print tracking beacons, send shuttle
/obj/machinery/autolathe, //same
diff --git a/code/modules/shuttle/syndicate.dm b/code/modules/shuttle/syndicate.dm
index bffce9e7abe..cb6fdd203ef 100644
--- a/code/modules/shuttle/syndicate.dm
+++ b/code/modules/shuttle/syndicate.dm
@@ -41,7 +41,6 @@
req_access = list(ACCESS_SYNDICATE)
shuttleId = "steel_rain"
possible_destinations = null
- clockwork = TRUE //it'd look weird
/obj/machinery/computer/shuttle/syndicate/drop_pod/Topic(href, href_list)
if(href_list["move"])
diff --git a/code/modules/spells/spell_types/mind_transfer.dm b/code/modules/spells/spell_types/mind_transfer.dm
index 7f71a410a6c..a3e26b0c3c8 100644
--- a/code/modules/spells/spell_types/mind_transfer.dm
+++ b/code/modules/spells/spell_types/mind_transfer.dm
@@ -61,7 +61,7 @@ Also, you never added distance checking after target is selected. I've went ahea
return
var/datum/mind/TM = target.mind
- if((target.anti_magic_check(TRUE, FALSE) || TM.has_antag_datum(/datum/antagonist/wizard) || TM.has_antag_datum(/datum/antagonist/cult) || TM.has_antag_datum(/datum/antagonist/clockcult) || TM.has_antag_datum(/datum/antagonist/changeling) || TM.has_antag_datum(/datum/antagonist/rev)) || cmptext(copytext(target.key,1,2),"@"))
+ if((target.anti_magic_check(TRUE, FALSE) || TM.has_antag_datum(/datum/antagonist/wizard) || TM.has_antag_datum(/datum/antagonist/cult) || TM.has_antag_datum(/datum/antagonist/changeling) || TM.has_antag_datum(/datum/antagonist/rev)) || cmptext(copytext(target.key,1,2),"@"))
if(!silent)
to_chat(user, "[target.p_their(TRUE)] mind is resisting your spell!")
return
diff --git a/code/modules/station_goals/bsa.dm b/code/modules/station_goals/bsa.dm
index 9992e20c4c2..502fd567a60 100644
--- a/code/modules/station_goals/bsa.dm
+++ b/code/modules/station_goals/bsa.dm
@@ -215,7 +215,7 @@
icon = 'icons/obj/machines/particle_accelerator.dmi'
icon_state = "control_boxp"
ui_x = 400
- ui_y = 305
+ ui_y = 220
var/obj/machinery/bsa/full/cannon
var/notice
@@ -255,6 +255,8 @@
update_icon()
/obj/machinery/computer/bsa_control/proc/calibrate(mob/user)
+ if(!GLOB.bsa_unlock)
+ return
var/list/gps_locators = list()
for(var/datum/component/gps/G in GLOB.GPS_list) //nulls on the list somehow
if(G.tracking)
diff --git a/code/modules/surgery/cavity_implant.dm b/code/modules/surgery/cavity_implant.dm
index 3886d5e324e..3d64bb20c0a 100644
--- a/code/modules/surgery/cavity_implant.dm
+++ b/code/modules/surgery/cavity_implant.dm
@@ -15,7 +15,7 @@
var/obj/item/IC = null
/datum/surgery_step/handle_cavity/tool_check(mob/user, obj/item/tool)
- if(istype(tool, /obj/item/cautery) || istype(tool, /obj/item/gun/energy/laser))
+ if(tool.tool_behaviour == TOOL_CAUTERY || istype(tool, /obj/item/gun/energy/laser))
return FALSE
return !tool.get_temperature()
diff --git a/code/modules/surgery/coronary_bypass.dm b/code/modules/surgery/coronary_bypass.dm
index 431f7c43985..676d399160d 100644
--- a/code/modules/surgery/coronary_bypass.dm
+++ b/code/modules/surgery/coronary_bypass.dm
@@ -48,7 +48,7 @@
//grafts a coronary bypass onto the individual's heart, success chance is 90% base again
/datum/surgery_step/coronary_bypass
name = "graft coronary bypass"
- implements = list(/obj/item/hemostat = 90, TOOL_WIRECUTTER = 35, /obj/item/stack/packageWrap = 15, /obj/item/stack/cable_coil = 5)
+ implements = list(TOOL_HEMOSTAT = 90, TOOL_WIRECUTTER = 35, /obj/item/stack/packageWrap = 15, /obj/item/stack/cable_coil = 5)
time = 90
/datum/surgery_step/coronary_bypass/preop(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery)
diff --git a/code/modules/surgery/organs/tongue.dm b/code/modules/surgery/organs/tongue.dm
index 02aa41aaee1..04a203b36e0 100644
--- a/code/modules/surgery/organs/tongue.dm
+++ b/code/modules/surgery/organs/tongue.dm
@@ -16,7 +16,6 @@
/datum/language/monkey,
/datum/language/narsie,
/datum/language/beachbum,
- /datum/language/ratvar,
/datum/language/aphasia,
/datum/language/piratespeak,
))
@@ -166,7 +165,6 @@
/datum/language/xenocommon,
/datum/language/common,
/datum/language/draconic,
- /datum/language/ratvar,
/datum/language/monkey))
/obj/item/organ/tongue/alien/Initialize(mapload)
diff --git a/code/modules/surgery/organs/vocal_cords.dm b/code/modules/surgery/organs/vocal_cords.dm
index 8d78f8f2b82..7b53b04ffb9 100644
--- a/code/modules/surgery/organs/vocal_cords.dm
+++ b/code/modules/surgery/organs/vocal_cords.dm
@@ -131,8 +131,6 @@
if(!span_list || !span_list.len)
if(iscultist(user))
span_list = list("narsiesmall")
- else if (is_servant_of_ratvar(user))
- span_list = list("ratvar")
else
span_list = list()
@@ -170,8 +168,6 @@
//Cultists are closer to their gods and are more powerful, but they'll give themselves away
if(iscultist(user))
power_multiplier *= 2
- else if (is_servant_of_ratvar(user))
- power_multiplier *= 2
//Try to check if the speaker specified a name or a job to focus on
var/list/specific_listeners = list()
diff --git a/code/modules/tgui/tgui.dm b/code/modules/tgui/tgui.dm
index a13bb7f901e..5d7b03d742c 100644
--- a/code/modules/tgui/tgui.dm
+++ b/code/modules/tgui/tgui.dm
@@ -289,6 +289,8 @@
if(params["screen"])
ui_screen = params["screen"]
SStgui.update_uis(src_object)
+ if("tgui:log")
+ log_message(params["log"])
if("tgui:link")
user << link(params["url"])
if("tgui:fancy")
@@ -385,3 +387,6 @@
/datum/tgui/proc/set_titlebar(value)
titlebar = value
+
+/datum/tgui/proc/log_message(message)
+ log_tgui("[user] ([user.ckey]) using \"[title]\":\n[message]")
diff --git a/code/modules/tooltip/tooltip.html b/code/modules/tooltip/tooltip.html
index 3e2f26a09fb..67b60a037e9 100644
--- a/code/modules/tooltip/tooltip.html
+++ b/code/modules/tooltip/tooltip.html
@@ -54,9 +54,6 @@
.cult .wrap {border-color: #292222;}
.cult .content {color: #FF0000; border-color: #4C4343; background-color: #3C3434;}
- .clockcult .wrap {border-color: #170800;}
- .clockcult .content {color: #B18B25; border-color: #000000; background-color: #5F380E;}
-
.pod .wrap {border-color: #052401;}
.pod .content {border-color: #326D29; background-color: #569F4B;}
@@ -83,9 +80,6 @@
.operative .wrap {border-color: #1E0101;}
.operative .content {color: #FFFFFF; border-color: #750000; background-color: #350000;}
- .clockwork .wrap {border-color: #170800;}
- .clockwork .content {color: #B18B25; border-color: #000000; background-color: #5F380E;}
-
diff --git a/code/modules/vending/autodrobe.dm b/code/modules/vending/autodrobe.dm
index 9a7574ed22f..f6df2da8895 100644
--- a/code/modules/vending/autodrobe.dm
+++ b/code/modules/vending/autodrobe.dm
@@ -116,7 +116,10 @@
/obj/item/clothing/under/costume/sailor = 1,
/obj/item/clothing/ears/headphones = 2,
/obj/item/clothing/head/delinquent = 1,
- /obj/item/clothing/head/wig/random = 3)
+ /obj/item/clothing/head/wig/random = 3,
+ /obj/item/clothing/head/shrine_wig = 1,
+ /obj/item/clothing/suit/shrine_maiden = 1,
+ /obj/item/gohei = 1)
contraband = list(/obj/item/clothing/suit/judgerobe = 1,
/obj/item/clothing/head/powdered_wig = 1,
/obj/item/gun/magic/wand = 2,
diff --git a/config/game_options.txt b/config/game_options.txt
index 82d6781708c..d6ff9420749 100644
--- a/config/game_options.txt
+++ b/config/game_options.txt
@@ -122,7 +122,6 @@ CONTINUOUS INTERNAL_AFFAIRS
#CONTINUOUS NUCLEAR
#CONTINUOUS REVOLUTION
CONTINUOUS CULT
-CONTINUOUS CLOCKWORK_CULT
CONTINUOUS CHANGELING
CONTINUOUS WIZARD
#CONTINUOUS MONKEY
@@ -144,7 +143,6 @@ MIDROUND_ANTAG INTERNAL_AFFAIRS
#MIDROUND_ANTAG NUCLEAR
#MIDROUND_ANTAG REVOLUTION
MIDROUND_ANTAG CULT
-MIDROUND_ANTAG CLOCKWORK_CULT
MIDROUND_ANTAG CHANGELING
MIDROUND_ANTAG WIZARD
#MIDROUND_ANTAG MONKEY
@@ -176,9 +174,6 @@ MIDROUND_ANTAG WIZARD
#MIN_POP CULT 24
#MAX_POP CULT -1
-#MIN_POP CLOCKWORK_CULT 24
-#MAX_POP CLOCKWORK_CULT -1
-
#MIN_POP CHANGELING 15
#MAX_POP CHANGELING -1
@@ -379,7 +374,6 @@ RANDOM_LAWS corporate
#RANDOM_LAWS ninja
#RANDOM_LAWS antimov
#RANDOM_LAWS thermodynamic
-#RANDOM_LAWS ratvar
## meme laws. Honk
#RANDOM_LAWS buildawall
@@ -412,7 +406,6 @@ LAW_WEIGHT syndie,0
LAW_WEIGHT ninja,0
LAW_WEIGHT antimov,0
LAW_WEIGHT thermodynamic,0
-LAW_WEIGHT ratvar,0
LAW_WEIGHT buildawall,0
##------------------------------------------------
diff --git a/html/changelog.html b/html/changelog.html
index 1e58bd1af17..88d9a36b514 100644
--- a/html/changelog.html
+++ b/html/changelog.html
@@ -51,6 +51,143 @@
-->
+
16 October 2019
+
Bumtickley00 updated:
+
+
Fixed seiver removing much more radiation than intended
+
+
Fikou updated:
+
+
you can now mend cavity surgery with an advanced cautery
+
changing mode on power drill now gives you the correct message
+
+
Jdawg1290 updated:
+
+
Non-dense atoms can now obscure (prevent interaction with) turfs.
+
+
MadoFrog updated:
+
+
The shrine maiden's outfit has been added to the costume vendor.
+
+
Skoglol updated:
+
+
The fusion reaction is now soft capped to a temperature of 1e8.
+
+
Time-Green updated:
+
+
Plumbing equipment is now available through the medical protolathe. It's under medical machinery boards
+
Add's a new chemistry area on metastation for chemical factories. It's located left of main surgery.
+
Chemistry has been turned into the Apothecary. It's basically normal chemistry, but Medical Doctors have acces aswell.
+
The smoke machine is now plumbing compatible. Put this knowledge to good use. sprite: Thanks to @CRITAWAKETS for the plumbing RCD sprite!
+
+
carlarctg updated:
+
+
The new carpets now have recipes! Try not to ingest them, as they may have funny effects..
+
oil is flammable
+
+
+
15 October 2019
+
ATHATH updated:
+
+
Your wish that the wishgranter grants you can no longer be "To Kill".
+
+
AarontheIdiot updated:
+
+
Mosin Nagant requires two hands now
+
+
Bumtickley00 updated:
+
+
Cargo can now buy portable air pumps and portable scrubbers
+
Iron sheets build the normal metal table again
+
+
Fikou updated:
+
+
shotguns are now "heavy" weight class.
+
+
Fox McCloud updated:
+
+
Fixes spawning process for tendrils and mobs resulting in clumping of lavaland fauna
+
+
Jdawg1290 updated:
+
+
Coronary bypass heart graft can be completed with mechanical pinches properly
+
+
Nemvar, Carlarc, and Bobbahbrown updated:
+
+
reflector vest covers arms, reflect chance from 40 to 50
+
reflector vest has ARM BANDS
+
+
ShizCalev, TheMythicGhost updated:
+
+
Nanotrasen's Department of Supernatural Defense fires the newly built Wave Motion Gun at Reebe, destroying the Clock Cult.
+
After reverse engineering technologies found after the annihilation of Reebe, Bronze chairs now have incorporated Ratvarian A E S T H E T I C auto-spinning technology.
+
Due to the annihilation of Reebe, the clockwork structures and turfs that fell to lavaland alongside Ratvar's corpse have lost their power becoming mere bronze, but the spear seems to have been touched by holy energies.
+
+
spessbandit updated:
+
+
Event announcement code has been slightly refactored.
+
Forcing an ion storm should announce 100% of the time now, instead of 33%.
+
+
stylemistake updated:
+
+
New React-based TGUI, which is INCREDIBLY FAST.
+
New Acclimator interface (@actioninja).
+
New AI Airlock interface (@actioninja).
+
New Air Alarm interface (@stylemistake).
+
New Airlock Electronics interface (@actioninja).
+
New APC interface (@actioninja).
+
New Atmos Alert Console interface (@actioninja).
+
New Atmos Control Console interface (@actioninja).
+
New Atmos Filter interface (@actioninja).
+
New Atmos Mixer interface (@actioninja).
+
New Atmos Pump interface (@actioninja).
+
New Borg Panel interface (@actioninja).
+
New Brig Timer interface (@actioninja).
+
New Bluespace Artillery interface (@actioninja).
+
New Gas Canister interface (@willox).
+
New Cargo interface (@actioninja, @stylemistake).
+
New Cellular Emporium interface for changelings (@actioninja).
+
New CentCom Pod Launcher interface (@actioninja).
+
New Chem Dispenser interface (@stylemistake).
+
New Crayon interface (@actioninja).
+
New Disposal Unit interface (@actioninja).
+
New Thermomachine interface (@willox).
+
New Wires (hacking) interface (@actioninja).
+
Old TGUI interfaces are dynamically loaded if new TGUI interface was not found. This might increase load times while we are undergoing the transition.
+
Scrubber list is more compact, using chemical formula notation for common gases.
+
Slightly more native-looking title bar in new TGUI.
+
Window scrollbars are now themed to match TGUI color scheme.
+
New TGUI hopefully fixes all previous window dragging and resizing issues.
+
Very robust UI development pipeline, with hot module replacement and live log collection.
+
+
zxaber updated:
+
+
The Memento Mori now removes its action button after activation, rather than leaving the button behind as a delayed gatcha suicide ability.
+
+
+
14 October 2019
+
Firecage updated:
+
+
All dogs, including pugs, are now capable of eating snacks and dancing around.
+
Puppy Ian is now capable of eating and dancing.
+
+
Kaffe-work updated:
+
+
fixed sprites on guns with both bayonet and toggle-able lights removing the bayonet when toggled.
+
+
PKPenguin321 updated:
+
+
If you somehow manage to get a container into a another container that is smaller than it, like a bag in a box, you're no longer able to put things into that bigger container (such as the bag in the box).
+
+
Qustinnus updated:
+
+
You now get the correct material from deconning tables and chairs
+
Objects now get the correct amount of materials
+
Plasma mat doesn't send warnings on equip
+
Plasma alloys dont explode anymore
+
no more mat duping for now hopefully
+
+
13 October 2019
4dplanner updated:
@@ -77,6 +214,10 @@
blindness spell now only blinds you temporarily
drinking carrot juice no longer permanently blinds you
+
Fikou updated:
+
+
powertools now change behaviour instead of being completely different items
+
Fox McCloud updated:
Fixes AI swarmers just sitting in their base doing nothing
@@ -99,6 +240,12 @@
Random gender will now have a chance of picking "Other".
KS13 air tank injector now on and maxed.
+
TheChosenEvilOne updated:
+
+
Throwing objects to openspace works correctly.
+
Non-living objects can now go up stairs.
+
You can no longer deepfry openspace.
+
Toxicby updated:
Seiver, a chem favoring radpurging (cold temps) or antitoxin (hot temps) based on temperature (NOTE: NOT ATMOS TEMP)
@@ -115,6 +262,7 @@
atmos and captain gas masks no longer have floating pixel
sawn off shotgun has inhand
+
singulo hammer is now black
nemvar updated:
@@ -1456,211 +1604,6 @@
Cleaned up organ decay code.
Stasis now stops body eggs from processing.
-
-
14 August 2019
-
AcapitalA updated:
-
-
In a freak magic accident, all xenobio-made magicarps have lost their bolt of death. This is a great tragedy for xenobiologists all around the galaxy.
-
-
CRITAWAKETS updated:
-
-
Ammonia now is better than diethylamine for increasing plant yield.
-
-
Dennok updated:
-
-
Silo link RCD upgrade
-
RCD now check mats before construction wait.
-
has_materials() properly check materials.
-
-
Denton updated:
-
-
Changed a laser pointer var so that T4 micro lasers no longer give a success percentage above 100%.
-
Made cat related laserpointer acts scale off the pointer's micro laser tier.
-
-
JDawg1290 updated:
-
-
Quarantine law cannot be trivially circumvented.
-
-
Niknakflak updated:
-
-
pAIs may now choose to display their holoform as a bat, lizard, butterfly, or hawk.
-
-
Penterwast updated:
-
-
Binary chat messages are now marked as such in logs.
-
-
Sanator updated:
-
-
Added new, better DNA icons, also animated
-
-
Skoglol updated:
-
-
Hop console now hurts your eyes less. Red button text replaced with green.
-
-
Tlaltecuhtli updated:
-
-
cargo request console pings supply radio when someone makes a new request
-
-
Twaticus updated:
-
-
New underwear
-
Midway Boxers, Long Johns, Halter Swimsuit
-
-
actioninja updated:
-
-
the correct black suit is now spawning in places it should be, the other sprite spawns in law wardrobe.
-
newly constructed reinforced windows start in the correct state, meaning they can be disassembled
-
crowbar can no longer be used out of order on construction
-
screwed down but not levered in windows can be unscrewed again
-
shuttle and plastitanium windows now have the proper values to match reinforced windows.
-
-
bandit updated:
-
-
Clicking a display case on help intent examines it.
-
-
kevinz000 updated:
-
-
VV no longer runtimes with bad resource file when you try to VV something with a blank icon.
-
-
nemvar updated:
-
-
Improved the way factions are applied to species.
-
Shadowpeople no longer get attacked by faithless.
-
added inhands for the cautery, retractor, drapes and hemostat.
-
Signaler suicide is now bound to the mind, instead of the body.
-
-
-
12 August 2019
-
ATHATH updated:
-
-
Added two robotic voiceboxes to the contraband section of the Robotech Deluxe.
-
Changed the name of the "Disintegrate" spell (and some references to it) to "Smite" (and slightly edits the description of the Disintegrate spell).
-
-
Akrilla updated:
-
-
Contractors can now reroll their contracts a small number of times.
-
Brand new sprites! A redesign of the specialist space suit, and the kit's own unique tablet. Done by Mey Ha Zah.
-
Displays contract target jobs under their name.
-
New locations, such as maintenance, are now possible dropoff locations.
-
Buffs up the Syndicate cigarettes to give about 15u of omnizine over two minutes.
-
Allows for cigarettes to give all their chems over their lifetime with a new var.
-
-
Bucovineanu updated:
-
-
Added one line that makes 357 speedloaders unrecyclable.
-
-
Dawson1917 updated:
-
-
Mining explorer suits have less defense against lasers and bullets.
-
-
Denton updated:
-
-
Added clown car logging to the attack log.
-
Player deaths+suicides are now logged in the attack log and no longer in the game log.
-
-
ExcessiveUseOfCobblestone updated:
-
-
Examining a dissected body will provide insight on the highest tier performed.
-
You can do ayy dissection now if you get the tech
-
FINALLY fixed the surgery logic correctly
-
-
Fikou updated:
-
-
Cargo can now buy a crate of bulletproof helmets for only 1500 spacebux!
-
completely changed the contents of the artistic crates (rest in peace painting)
-
special ops supplies crate now have a slightly different description
-
-
Floyd / Qustinnus updated:
-
-
Humans and ethereals are less affected by nutritional requirements.
-
-
MCterra10 updated:
-
-
All windows now have consistent examine messages
-
-
Mickyan updated:
-
-
Tend wounds surgery won't fail as often while using improvised tools
-
The janitor's cleaner backpack has had its range increased by 2
-
-
Penterwast updated:
-
-
Added logging for CentComm nuke request messages.
-
-
Skoglol updated:
-
-
Cargo console UI touched up a bit. Requests and cart moved below the cargo packs for less button shuffling, buying privately is now a toggle, resized window slightly.
-
-
StonebayKyle updated:
-
-
There is now a randomize species button in the character settings/preview screen.
-
-
TheChosenEvilOne updated:
-
-
Ported dynamic mode from /vg/, originally made by @DeityLink, @Kurfursten and @ShiftyRail
-
-
Time-Green updated:
-
-
Adds chemical filters to plumbing
-
-
Trilbyspaceclone updated:
-
-
pie and cakes
-
-
Twaticus updated:
-
-
Underwear can now have any color. (Your character will most likely be nude now so check your prefs!!)
-
Underwear color option in dressers
-
changed some underwear names
-
deleted duplicate underwear
-
-
YPOQ updated:
-
-
Fixed being unable to clone multiple empty clones simultaneously
-
-
actioninja updated:
-
-
Reinforced windows now require a melee item over 11 damage to damage, have 150 health, and 90 melee armor. This is approximately 2 minutes of sustained beating with a toolbox.
-
Plasmaglass windows now require a melee item over 21 damage to damage, have 200 health, and 90 melee resistance. This is approximately 3 minutes of sustained beating with a toolbox.
-
fixeds a couple issues with the SM sounds
-
interface no longer has the weird gap
-
-
bgobandit updated:
-
-
Wizard rounds should properly generate messages when the wiz dies.
-
-
carlarctg updated:
-
-
added some icons and images for hyposprays and medipens so they stand out
-
tweaked a few descriptions on said hypos so they better describe the contents
-
-
nemvar updated:
-
-
Laser eyes now generate a message when shot.
-
Cleaned up mutation code.
-
another sanity rebalancing.
-
Slightly altered wall sprites.
-
Gibberish code is less silly.
-
The C4 overlay now displays properly on mobs.
-
Tend wounds only generates one failure message now.
-
Various defib fixes.
-
The inhands of the bulldog shotgun are no longer invisible.
-
-
pireamaineach updated:
-
-
Plasmaman helmets now have welding visors, which can't stack with their torches in the helmet and are visible.
-
Clicking on the helmet with any item no longer tells you that someone's already drawn a face on it, you can't put infinite faces on it.
-
Plasmaman helmets hide masks again, the sprites are no longer transparent. Mind, the original bounty just wanted it so you could see faces through it, not for it to be transparent. tweak:Plasmaman helmets now have special smile sprites rather than pulling from the EVA one, as the visors are different sizes.
-
You can't eat through plasmaman helmets anymore.
-
-
redmoogle updated:
-
-
Added support for 3 new gasses; Tritium, Pluoxium, and BZ
-
-
willox updated:
-
-
bloody footprints no longer spawn with incorrect steps and don't break when rotated on shuttles
-
GoonStation 13 Development Team
diff --git a/html/changelogs/.all_changelog.yml b/html/changelogs/.all_changelog.yml
index 83a28898a26..c95b2ac5c85 100644
--- a/html/changelogs/.all_changelog.yml
+++ b/html/changelogs/.all_changelog.yml
@@ -27532,6 +27532,9 @@ DO NOT EDIT THIS FILE BY HAND! AUTOMATICALLY GENERATED BY ss13_genchangelog.py.
Couls:
- bugfix: blindness spell now only blinds you temporarily
- bugfix: drinking carrot juice no longer permanently blinds you
+ Fikou:
+ - refactor: powertools now change behaviour instead of being completely different
+ items
Fox McCloud:
- bugfix: Fixes AI swarmers just sitting in their base doing nothing
- bugfix: Fixes being able to mech-punch other mobs, as a pacifist
@@ -27547,6 +27550,10 @@ DO NOT EDIT THIS FILE BY HAND! AUTOMATICALLY GENERATED BY ss13_genchangelog.py.
- rscadd: Random name/body/age/gender when roundstart antagonist preference added.
- rscadd: Random gender will now have a chance of picking "Other".
- bugfix: KS13 air tank injector now on and maxed.
+ TheChosenEvilOne:
+ - bugfix: Throwing objects to openspace works correctly.
+ - bugfix: Non-living objects can now go up stairs.
+ - bugfix: You can no longer deepfry openspace.
Toxicby:
- rscadd: 'Seiver, a chem favoring radpurging (cold temps) or antitoxin (hot temps)
based on temperature (NOTE: NOT ATMOS TEMP)'
@@ -27564,8 +27571,118 @@ DO NOT EDIT THIS FILE BY HAND! AUTOMATICALLY GENERATED BY ss13_genchangelog.py.
carlarctg:
- bugfix: atmos and captain gas masks no longer have floating pixel
- bugfix: sawn off shotgun has inhand
+ - bugfix: singulo hammer is now black
nemvar:
- balance: Removed health analyzers from medkits. Removed the ability to print health
analyzers from autolathes.
willox:
- code_imp: removed duplicate goliath_hide definition
+2019-10-14:
+ Firecage:
+ - rscadd: All dogs, including pugs, are now capable of eating snacks and dancing
+ around.
+ - bugfix: Puppy Ian is now capable of eating and dancing.
+ Kaffe-work:
+ - bugfix: fixed sprites on guns with both bayonet and toggle-able lights removing
+ the bayonet when toggled.
+ PKPenguin321:
+ - bugfix: If you somehow manage to get a container into a another container that
+ is smaller than it, like a bag in a box, you're no longer able to put things
+ into that bigger container (such as the bag in the box).
+ Qustinnus:
+ - bugfix: You now get the correct material from deconning tables and chairs
+ - bugfix: Objects now get the correct amount of materials
+ - bugfix: Plasma mat doesn't send warnings on equip
+ - bugfix: Plasma alloys dont explode anymore
+ - bugfix: no more mat duping for now hopefully
+2019-10-15:
+ ATHATH:
+ - rscdel: Your wish that the wishgranter grants you can no longer be "To Kill".
+ AarontheIdiot:
+ - tweak: Mosin Nagant requires two hands now
+ Bumtickley00:
+ - rscadd: Cargo can now buy portable air pumps and portable scrubbers
+ - tweak: Iron sheets build the normal metal table again
+ Fikou:
+ - balance: shotguns are now "heavy" weight class.
+ Fox McCloud:
+ - bugfix: Fixes spawning process for tendrils and mobs resulting in clumping of
+ lavaland fauna
+ Jdawg1290:
+ - bugfix: Coronary bypass heart graft can be completed with mechanical pinches properly
+ Nemvar, Carlarc, and Bobbahbrown:
+ - balance: reflector vest covers arms, reflect chance from 40 to 50
+ - imageadd: reflector vest has ARM BANDS
+ ShizCalev, TheMythicGhost:
+ - rscdel: Nanotrasen's Department of Supernatural Defense fires the newly built
+ Wave Motion Gun at Reebe, destroying the Clock Cult.
+ - tweak: After reverse engineering technologies found after the annihilation of
+ Reebe, Bronze chairs now have incorporated Ratvarian A E S T H E T I C auto-spinning
+ technology.
+ - tweak: Due to the annihilation of Reebe, the clockwork structures and turfs that
+ fell to lavaland alongside Ratvar's corpse have lost their power becoming mere
+ bronze, but the spear seems to have been touched by holy energies.
+ spessbandit:
+ - refactor: Event announcement code has been slightly refactored.
+ - admin: Forcing an ion storm should announce 100% of the time now, instead of 33%.
+ stylemistake:
+ - rscadd: New React-based TGUI, which is INCREDIBLY FAST.
+ - rscadd: New Acclimator interface (@actioninja).
+ - rscadd: New AI Airlock interface (@actioninja).
+ - rscadd: New Air Alarm interface (@stylemistake).
+ - rscadd: New Airlock Electronics interface (@actioninja).
+ - rscadd: New APC interface (@actioninja).
+ - rscadd: New Atmos Alert Console interface (@actioninja).
+ - rscadd: New Atmos Control Console interface (@actioninja).
+ - rscadd: New Atmos Filter interface (@actioninja).
+ - rscadd: New Atmos Mixer interface (@actioninja).
+ - rscadd: New Atmos Pump interface (@actioninja).
+ - rscadd: New Borg Panel interface (@actioninja).
+ - rscadd: New Brig Timer interface (@actioninja).
+ - rscadd: New Bluespace Artillery interface (@actioninja).
+ - rscadd: New Gas Canister interface (@willox).
+ - rscadd: New Cargo interface (@actioninja, @stylemistake).
+ - rscadd: New Cellular Emporium interface for changelings (@actioninja).
+ - rscadd: New CentCom Pod Launcher interface (@actioninja).
+ - rscadd: New Chem Dispenser interface (@stylemistake).
+ - rscadd: New Crayon interface (@actioninja).
+ - rscadd: New Disposal Unit interface (@actioninja).
+ - rscadd: New Thermomachine interface (@willox).
+ - rscadd: New Wires (hacking) interface (@actioninja).
+ - tweak: Old TGUI interfaces are dynamically loaded if new TGUI interface was not
+ found. This might increase load times while we are undergoing the transition.
+ - tweak: Scrubber list is more compact, using chemical formula notation for common
+ gases.
+ - tweak: Slightly more native-looking title bar in new TGUI.
+ - tweak: Window scrollbars are now themed to match TGUI color scheme.
+ - bugfix: New TGUI hopefully fixes all previous window dragging and resizing issues.
+ - code_imp: Very robust UI development pipeline, with hot module replacement and
+ live log collection.
+ zxaber:
+ - tweak: The Memento Mori now removes its action button after activation, rather
+ than leaving the button behind as a delayed gatcha suicide ability.
+2019-10-16:
+ Bumtickley00:
+ - bugfix: Fixed seiver removing much more radiation than intended
+ Fikou:
+ - bugfix: you can now mend cavity surgery with an advanced cautery
+ - spellcheck: changing mode on power drill now gives you the correct message
+ Jdawg1290:
+ - tweak: Non-dense atoms can now obscure (prevent interaction with) turfs.
+ MadoFrog:
+ - rscadd: The shrine maiden's outfit has been added to the costume vendor.
+ Skoglol:
+ - tweak: The fusion reaction is now soft capped to a temperature of 1e8.
+ Time-Green:
+ - rscadd: Plumbing equipment is now available through the medical protolathe. It's
+ under medical machinery boards
+ - rscadd: Add's a new chemistry area on metastation for chemical factories. It's
+ located left of main surgery.
+ - tweak: Chemistry has been turned into the Apothecary. It's basically normal chemistry,
+ but Medical Doctors have acces aswell.
+ - tweak: 'The smoke machine is now plumbing compatible. Put this knowledge to good
+ use. sprite: Thanks to @CRITAWAKETS for the plumbing RCD sprite!'
+ carlarctg:
+ - rscadd: The new carpets now have recipes! Try not to ingest them, as they may
+ have funny effects..
+ - rscadd: oil is flammable
diff --git a/html/changelogs/AutoChangeLog-pr-46955.yml b/html/changelogs/AutoChangeLog-pr-46955.yml
new file mode 100644
index 00000000000..18e5a06fd30
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-46955.yml
@@ -0,0 +1,4 @@
+author: "carlarctg"
+delete-after: True
+changes:
+ - imagedel: "The intern that's been injecting Growth Serum into Monkey Energy cans has been fired."
diff --git a/icons/mob/ai.dmi b/icons/mob/ai.dmi
index 91494cae01e..4f56e03dd41 100644
Binary files a/icons/mob/ai.dmi and b/icons/mob/ai.dmi differ
diff --git a/icons/mob/clothing/suit.dmi b/icons/mob/clothing/suit.dmi
index 3afd71cf80f..252f10aeec0 100644
Binary files a/icons/mob/clothing/suit.dmi and b/icons/mob/clothing/suit.dmi differ
diff --git a/icons/mob/inhands/misc/food_lefthand.dmi b/icons/mob/inhands/misc/food_lefthand.dmi
index 325b18d95e2..fd29b8f6975 100644
Binary files a/icons/mob/inhands/misc/food_lefthand.dmi and b/icons/mob/inhands/misc/food_lefthand.dmi differ
diff --git a/icons/mob/inhands/misc/food_righthand.dmi b/icons/mob/inhands/misc/food_righthand.dmi
index ddc91fd6ed3..d327715e9db 100644
Binary files a/icons/mob/inhands/misc/food_righthand.dmi and b/icons/mob/inhands/misc/food_righthand.dmi differ
diff --git a/icons/mob/inhands/weapons/staves_lefthand.dmi b/icons/mob/inhands/weapons/staves_lefthand.dmi
index ecc92c7d203..9158e12833c 100644
Binary files a/icons/mob/inhands/weapons/staves_lefthand.dmi and b/icons/mob/inhands/weapons/staves_lefthand.dmi differ
diff --git a/icons/mob/inhands/weapons/staves_righthand.dmi b/icons/mob/inhands/weapons/staves_righthand.dmi
index 92e5b91323d..d3de4926c95 100644
Binary files a/icons/mob/inhands/weapons/staves_righthand.dmi and b/icons/mob/inhands/weapons/staves_righthand.dmi differ
diff --git a/icons/mob/large-worn-icons/64x64/head.dmi b/icons/mob/large-worn-icons/64x64/head.dmi
index 6ea91d2c6d3..feaf64a9284 100644
Binary files a/icons/mob/large-worn-icons/64x64/head.dmi and b/icons/mob/large-worn-icons/64x64/head.dmi differ
diff --git a/icons/obj/2x2.dmi b/icons/obj/2x2.dmi
index c0eeb2962f5..80ae40fce33 100644
Binary files a/icons/obj/2x2.dmi and b/icons/obj/2x2.dmi differ
diff --git a/icons/obj/clothing/hats.dmi b/icons/obj/clothing/hats.dmi
index 895692feab2..b6fa2f99f40 100644
Binary files a/icons/obj/clothing/hats.dmi and b/icons/obj/clothing/hats.dmi differ
diff --git a/icons/obj/clothing/suits.dmi b/icons/obj/clothing/suits.dmi
index d7d500eafcd..27cee74ce4b 100644
Binary files a/icons/obj/clothing/suits.dmi and b/icons/obj/clothing/suits.dmi differ
diff --git a/icons/obj/drinks.dmi b/icons/obj/drinks.dmi
index 47a78c8b410..5e6d2d59a25 100644
Binary files a/icons/obj/drinks.dmi and b/icons/obj/drinks.dmi differ
diff --git a/icons/obj/items_and_weapons.dmi b/icons/obj/items_and_weapons.dmi
index 7f97bf62ab2..90a8d51cb28 100644
Binary files a/icons/obj/items_and_weapons.dmi and b/icons/obj/items_and_weapons.dmi differ
diff --git a/icons/obj/janitor.dmi b/icons/obj/janitor.dmi
index 9848482fcfa..3f56c2da79f 100644
Binary files a/icons/obj/janitor.dmi and b/icons/obj/janitor.dmi differ
diff --git a/icons/obj/library.dmi b/icons/obj/library.dmi
index f28b8be5c55..0086ef52a48 100644
Binary files a/icons/obj/library.dmi and b/icons/obj/library.dmi differ
diff --git a/icons/obj/plumbing/fluid_ducts.dmi b/icons/obj/plumbing/fluid_ducts.dmi
index 7e066164635..5cf521893ed 100644
Binary files a/icons/obj/plumbing/fluid_ducts.dmi and b/icons/obj/plumbing/fluid_ducts.dmi differ
diff --git a/icons/obj/plumbing/plumbers.dmi b/icons/obj/plumbing/plumbers.dmi
index 15f9277aa5b..b9ce30e4eb6 100644
Binary files a/icons/obj/plumbing/plumbers.dmi and b/icons/obj/plumbing/plumbers.dmi differ
diff --git a/icons/obj/tools.dmi b/icons/obj/tools.dmi
index 5e68bc94d7f..5e8cdf9c787 100644
Binary files a/icons/obj/tools.dmi and b/icons/obj/tools.dmi differ
diff --git a/icons/turf/areas.dmi b/icons/turf/areas.dmi
index b7d83a33a73..0e77e481fcd 100644
Binary files a/icons/turf/areas.dmi and b/icons/turf/areas.dmi differ
diff --git a/interface/stylesheet.dm b/interface/stylesheet.dm
index fbf2229c046..97a5ea9f7e4 100644
--- a/interface/stylesheet.dm
+++ b/interface/stylesheet.dm
@@ -106,13 +106,6 @@ h1.alert, h2.alert {color: #000000;}
.deconversion_message {color: #5000A0; font-size: 3; font-style: italic;}
-.brass {color: #BE8700;}
-.heavy_brass {color: #BE8700; font-weight: bold; font-style: italic;}
-.large_brass {color: #BE8700; font-size: 3;}
-.big_brass {color: #BE8700; font-size: 3; font-weight: bold; font-style: italic;}
-.ratvar {color: #BE8700; font-size: 6; font-weight: bold; font-style: italic;}
-.alloy {color: #42474D;}
-.heavy_alloy {color: #42474D; font-weight: bold; font-style: italic;}
.nezbere_large {color: #42474D; font-size: 3; font-weight: bold; font-style: italic;}
.nezbere {color: #42474D; font-weight: bold; font-style: italic;}
.nezbere_small {color: #42474D;}
diff --git a/strings/ion_laws.json b/strings/ion_laws.json
index 152afd11166..d4b08d2a864 100644
--- a/strings/ion_laws.json
+++ b/strings/ion_laws.json
@@ -942,7 +942,6 @@
"INSECTS",
"LIZARDS",
"PETES",
- "RATVARIANS",
"XENOS",
"FETISHES",
"MEMES",
diff --git a/strings/tips.txt b/strings/tips.txt
index d637fc7570c..289db2419dd 100644
--- a/strings/tips.txt
+++ b/strings/tips.txt
@@ -213,12 +213,11 @@ As a Changeling, the Extract DNA sting counts for your genome absorb objective,
As a Changeling, you can absorb someone by strangling them and using the Absorb verb; this gives you the ability to rechoose your powers, the DNA of whoever you absorbed, the memory of the absorbed, and some samples of things the absorbed said.
As a Cultist, do not cause too much chaos before your objective is completed. If the shuttle gets called too soon, you may not have enough time to win.
As a Cultist, your team starts off very weak, but if necessary can quickly convert everything they have into raw power. Make sure you have the numbers and equipment to support going loud, or the cult will fall flat on its face.
-As a Cultist, the Blood Boil rune will deal massive amounts of brute damage to non-cultists, stamina damage to Ratvarian scum, and some damage to fellow cultists of Nar'Sie nearby, but will create a fire where the rune stands on use.
+As a Cultist, the Blood Boil rune will deal massive amounts of brute damage to non-cultists, and some damage to fellow cultists of Nar'Sie nearby, but will create a fire where the rune stands on use.
As a Cultist, you can create an army of manifested goons using a combination of the Manifest rune, which creates homunculi from ghosts, and the Blood Drain rune, which drains life from anyone standing on any blood drain rune.
As a Cultist, check the alert in the upper-right of your screen for all the details about your cult's current status and objective.
You can deconvert Cultists of Nar'Sie by feeding them large amounts of holy water. Unlike revolutionaries, implanting them with mindshield implants won't do it!
The Chaplain can bless any container with water by hitting it with their bible. Holy water has a myriad of uses against both cults and large amounts of it are a great contributor to success against them.
-The Chaplain's holy weapon will kill clockwork marauders in two hits.
As a Wizard, you can turn people to stone, then animate the resulting statue with a staff of animation to create an extremely powerful minion, for all of 5 minutes at least.
As a Wizard, the fireball spell performs very poorly at close range, as it can easily catch you in the blast. It is best used as a form of artillery down long hallways.
As a Wizard, summoning guns will turn a large portion of the crew against themselves, but will also give everyone anything from a floral somatoray to a pulse rifle. Use at your own risk!
diff --git a/strings/valentines.json b/strings/valentines.json
index 1c49df6585d..50afaff64c3 100644
--- a/strings/valentines.json
+++ b/strings/valentines.json
@@ -55,7 +55,6 @@
"I've been chasing you like Runtime chases a laser pointer.",
"I'm no cat, but you've got me in my feel-inids.",
"If Lavaland had an apiary, would you bee mine?",
- "I'm a Ratvarian cultist. Or zl inyragvar.",
"If you were a disposal bin I'd ride you all day.",
"Put on your explorer's suit because I'm taking you to LOVEaland.",
"You're the vomit to my flyperson.",
@@ -86,7 +85,6 @@
"A heart-shaped candy that reads: VALIDTINES",
"A heart-shaped candy that reads: FACE HUGGER",
"A heart-shaped candy that reads: BOX OF HUGS",
- "A heart-shaped candy that reads: REEBE MINE",
"A heart-shaped candy that reads: PET ME",
"A heart-shaped candy that reads: TO THE DORMS",
"A heart-shaped candy that reads: TABLE ME",
diff --git a/tgstation.dme b/tgstation.dme
index 9394a28857b..d9558ca5928 100644
--- a/tgstation.dme
+++ b/tgstation.dme
@@ -30,7 +30,6 @@
#include "code\__DEFINES\cargo.dm"
#include "code\__DEFINES\cinematics.dm"
#include "code\__DEFINES\cleaning.dm"
-#include "code\__DEFINES\clockcult.dm"
#include "code\__DEFINES\colors.dm"
#include "code\__DEFINES\combat.dm"
#include "code\__DEFINES\components.dm"
@@ -423,7 +422,6 @@
#include "code\datums\components\fantasy\prefixes.dm"
#include "code\datums\components\fantasy\suffixes.dm"
#include "code\datums\components\plumbing\_plumbing.dm"
-#include "code\datums\components\plumbing\acclimator.dm"
#include "code\datums\components\plumbing\chemical_acclimator.dm"
#include "code\datums\components\plumbing\filter.dm"
#include "code\datums\components\plumbing\reaction_chamber.dm"
@@ -603,7 +601,6 @@
#include "code\game\gamemodes\brother\traitor_bro.dm"
#include "code\game\gamemodes\changeling\changeling.dm"
#include "code\game\gamemodes\changeling\traitor_chan.dm"
-#include "code\game\gamemodes\clock_cult\clock_cult.dm"
#include "code\game\gamemodes\clown_ops\bananium_bomb.dm"
#include "code\game\gamemodes\clown_ops\clown_ops.dm"
#include "code\game\gamemodes\clown_ops\clown_weapons.dm"
@@ -839,7 +836,6 @@
#include "code\game\objects\effects\spawners\traps.dm"
#include "code\game\objects\effects\spawners\vaultspawner.dm"
#include "code\game\objects\effects\spawners\xeno_egg_delivery.dm"
-#include "code\game\objects\effects\temporary_visuals\clockcult.dm"
#include "code\game\objects\effects\temporary_visuals\cult.dm"
#include "code\game\objects\effects\temporary_visuals\miscellaneous.dm"
#include "code\game\objects\effects\temporary_visuals\temporary_visual.dm"
@@ -1152,7 +1148,6 @@
#include "code\game\turfs\simulated\floor.dm"
#include "code\game\turfs\simulated\lava.dm"
#include "code\game\turfs\simulated\minerals.dm"
-#include "code\game\turfs\simulated\reebe_void.dm"
#include "code\game\turfs\simulated\river.dm"
#include "code\game\turfs\simulated\walls.dm"
#include "code\game\turfs\simulated\water.dm"
@@ -1335,65 +1330,13 @@
#include "code\modules\antagonists\changeling\powers\strained_muscles.dm"
#include "code\modules\antagonists\changeling\powers\tiny_prick.dm"
#include "code\modules\antagonists\changeling\powers\transform.dm"
-#include "code\modules\antagonists\clockcult\clock_effect.dm"
-#include "code\modules\antagonists\clockcult\clock_item.dm"
-#include "code\modules\antagonists\clockcult\clock_mobs.dm"
-#include "code\modules\antagonists\clockcult\clock_scripture.dm"
-#include "code\modules\antagonists\clockcult\clock_structure.dm"
-#include "code\modules\antagonists\clockcult\clockcult.dm"
-#include "code\modules\antagonists\clockcult\clock_effects\city_of_cogs_rift.dm"
-#include "code\modules\antagonists\clockcult\clock_effects\clock_overlay.dm"
-#include "code\modules\antagonists\clockcult\clock_effects\clock_sigils.dm"
-#include "code\modules\antagonists\clockcult\clock_effects\general_markers.dm"
-#include "code\modules\antagonists\clockcult\clock_effects\servant_blocker.dm"
-#include "code\modules\antagonists\clockcult\clock_effects\spatial_gateway.dm"
-#include "code\modules\antagonists\clockcult\clock_helpers\clock_powerdrain.dm"
-#include "code\modules\antagonists\clockcult\clock_helpers\component_helpers.dm"
-#include "code\modules\antagonists\clockcult\clock_helpers\fabrication_helpers.dm"
-#include "code\modules\antagonists\clockcult\clock_helpers\hierophant_network.dm"
-#include "code\modules\antagonists\clockcult\clock_helpers\power_helpers.dm"
-#include "code\modules\antagonists\clockcult\clock_helpers\ratvarian_language.dm"
-#include "code\modules\antagonists\clockcult\clock_helpers\scripture_checks.dm"
-#include "code\modules\antagonists\clockcult\clock_helpers\slab_abilities.dm"
-#include "code\modules\antagonists\clockcult\clock_items\clock_components.dm"
-#include "code\modules\antagonists\clockcult\clock_items\clockwork_armor.dm"
-#include "code\modules\antagonists\clockcult\clock_items\clockwork_slab.dm"
-#include "code\modules\antagonists\clockcult\clock_items\clockwork_weaponry.dm"
-#include "code\modules\antagonists\clockcult\clock_items\construct_chassis.dm"
-#include "code\modules\antagonists\clockcult\clock_items\integration_cog.dm"
-#include "code\modules\antagonists\clockcult\clock_items\judicial_visor.dm"
-#include "code\modules\antagonists\clockcult\clock_items\replica_fabricator.dm"
-#include "code\modules\antagonists\clockcult\clock_items\soul_vessel.dm"
-#include "code\modules\antagonists\clockcult\clock_items\wraith_spectacles.dm"
-#include "code\modules\antagonists\clockcult\clock_items\clock_weapons\_call_weapon.dm"
-#include "code\modules\antagonists\clockcult\clock_items\clock_weapons\ratvarian_spear.dm"
-#include "code\modules\antagonists\clockcult\clock_mobs\_eminence.dm"
-#include "code\modules\antagonists\clockcult\clock_mobs\clockwork_marauder.dm"
-#include "code\modules\antagonists\clockcult\clock_scriptures\scripture_applications.dm"
-#include "code\modules\antagonists\clockcult\clock_scriptures\scripture_cyborg.dm"
-#include "code\modules\antagonists\clockcult\clock_scriptures\scripture_drivers.dm"
-#include "code\modules\antagonists\clockcult\clock_scriptures\scripture_scripts.dm"
-#include "code\modules\antagonists\clockcult\clock_structures\_trap_object.dm"
-#include "code\modules\antagonists\clockcult\clock_structures\ark_of_the_clockwork_justicar.dm"
-#include "code\modules\antagonists\clockcult\clock_structures\clockwork_obelisk.dm"
-#include "code\modules\antagonists\clockcult\clock_structures\eminence_spire.dm"
-#include "code\modules\antagonists\clockcult\clock_structures\heralds_beacon.dm"
-#include "code\modules\antagonists\clockcult\clock_structures\mania_motor.dm"
-#include "code\modules\antagonists\clockcult\clock_structures\ocular_warden.dm"
-#include "code\modules\antagonists\clockcult\clock_structures\ratvar_the_clockwork_justicar.dm"
-#include "code\modules\antagonists\clockcult\clock_structures\taunting_trail.dm"
-#include "code\modules\antagonists\clockcult\clock_structures\wall_gear.dm"
-#include "code\modules\antagonists\clockcult\clock_structures\trap_triggers\lever.dm"
-#include "code\modules\antagonists\clockcult\clock_structures\trap_triggers\pressure_sensor.dm"
-#include "code\modules\antagonists\clockcult\clock_structures\trap_triggers\repeater.dm"
-#include "code\modules\antagonists\clockcult\clock_structures\traps\brass_skewer.dm"
-#include "code\modules\antagonists\clockcult\clock_structures\traps\steam_vent.dm"
#include "code\modules\antagonists\creep\creep.dm"
#include "code\modules\antagonists\cult\blood_magic.dm"
#include "code\modules\antagonists\cult\cult.dm"
#include "code\modules\antagonists\cult\cult_comms.dm"
#include "code\modules\antagonists\cult\cult_items.dm"
#include "code\modules\antagonists\cult\cult_structures.dm"
+#include "code\modules\antagonists\cult\cult_turf_overlay.dm"
#include "code\modules\antagonists\cult\ritual.dm"
#include "code\modules\antagonists\cult\rune_spawn_action.dm"
#include "code\modules\antagonists\cult\runes.dm"
@@ -1953,7 +1896,6 @@
#include "code\modules\language\mushroom.dm"
#include "code\modules\language\narsian.dm"
#include "code\modules\language\piratespeak.dm"
-#include "code\modules\language\ratvarian.dm"
#include "code\modules\language\slime.dm"
#include "code\modules\language\swarmer.dm"
#include "code\modules\language\xenocommon.dm"
diff --git a/tgui-next/.editorconfig b/tgui-next/.editorconfig
new file mode 100644
index 00000000000..33092d4928a
--- /dev/null
+++ b/tgui-next/.editorconfig
@@ -0,0 +1,13 @@
+# http://editorconfig.org
+root = true
+
+[*]
+indent_style = space
+indent_size = 2
+end_of_line = lf
+charset = utf-8
+trim_trailing_whitespace = true
+insert_final_newline = true
+
+[*.md]
+max_line_length = 80
diff --git a/tgui-next/.eslintignore b/tgui-next/.eslintignore
new file mode 100644
index 00000000000..010416b9e88
--- /dev/null
+++ b/tgui-next/.eslintignore
@@ -0,0 +1,6 @@
+/**/node_modules
+/**/*.bundle.*
+/**/*.chunk.*
+/**/*.hot-update.*
+/packages/inferno/**
+/packages/tgui/public/shim-*.js
diff --git a/tgui-next/.eslintrc.yml b/tgui-next/.eslintrc.yml
new file mode 100644
index 00000000000..13f468ab3a8
--- /dev/null
+++ b/tgui-next/.eslintrc.yml
@@ -0,0 +1,118 @@
+parser: babel-eslint
+parserOptions:
+ ecmaVersion: 2019
+ sourceType: module
+ ecmaFeatures:
+ jsx: true
+env:
+ browser: true
+ node: true
+rules:
+ ## Possible Errors
+ # for-direction: error
+ # getter-return: error
+ no-async-promise-executor: error
+ # no-await-in-loop: error
+ # no-compare-neg-zero: error
+ no-cond-assign: error
+ # no-console: error
+ # no-constant-condition: error
+ # no-control-regex: error
+ # no-debugger: error
+ no-dupe-args: error
+ no-dupe-keys: error
+ no-duplicate-case: error
+ # no-empty: error
+ no-empty-character-class: error
+ no-ex-assign: error
+ no-extra-boolean-cast: error
+ # no-extra-parens: warn
+ no-extra-semi: error
+ no-func-assign: error
+ no-import-assign: error
+ no-inner-declarations: error
+ no-invalid-regexp: error
+ no-irregular-whitespace: error
+ no-misleading-character-class: error
+ no-obj-calls: error
+ no-prototype-builtins: error
+ no-regex-spaces: error
+ no-sparse-arrays: error
+ no-template-curly-in-string: error
+ no-unexpected-multiline: error
+ # no-unreachable: warn
+ no-unsafe-finally: error
+ no-unsafe-negation: error
+ # require-atomic-updates: error
+ use-isnan: error
+ valid-typeof: error
+
+ ## Best practices
+ complexity: [error, { max: 50 }] ## That is a VERY generous limit
+ curly: [error, all]
+ eqeqeq: [error, always]
+ dot-location: [error, property]
+ no-empty-pattern: error
+ no-multi-spaces: warn
+ no-octal: error
+ no-octal-escape: error
+ no-return-assign: error
+ no-self-assign: error
+ no-sequences: error
+ no-unused-labels: warn
+ no-useless-escape: warn
+ no-with: error
+ radix: error
+
+ ## Code style
+ array-bracket-newline: [error, consistent]
+ array-bracket-spacing: [error, never]
+ block-spacing: [error, always]
+ brace-style: [error, stroustrup, { allowSingleLine: false }]
+ comma-dangle: [error, always-multiline]
+ comma-spacing: [error, { before: false, after: true }]
+ comma-style: [error, last]
+ computed-property-spacing: [error, never]
+ func-call-spacing: [error, never]
+ func-style: [error, expression]
+ ## This rule does not honor a newline on opening paren.
+ # function-paren-newline: [error, never]
+ indent: [error, 2, {
+ SwitchCase: 1,
+ }]
+ jsx-quotes: [error, prefer-double]
+ key-spacing: [error, { beforeColon: false, afterColon: true }]
+ keyword-spacing: [error, { before: true, after: true }]
+ max-len: [error, { code: 120 }]
+ multiline-ternary: [error, always-multiline]
+ no-mixed-spaces-and-tabs: error
+ no-whitespace-before-property: error
+ operator-linebreak: [error, before]
+ # quotes: [error, single]
+ semi: error
+ semi-spacing: [error, { before: false, after: true }]
+ semi-style: [error, last]
+ space-before-blocks: [error, always]
+ space-before-function-paren: [error, {
+ anonymous: always,
+ named: never,
+ asyncArrow: always,
+ }]
+ space-in-parens: [error, never]
+ spaced-comment: [error, always]
+ switch-colon-spacing: [error, { before: false, after: true }]
+ template-tag-spacing: [error, never]
+ # unicode-bom: [error, never]
+
+ ## ES6
+ arrow-parens: [error, as-needed]
+ arrow-spacing: [error, { before: true, after: true }]
+ generator-star-spacing: [error, { before: false, after: true }]
+ no-class-assign: error
+ no-const-assign: error
+ no-dupe-class-members: error
+ no-new-symbol: error
+ no-this-before-super: error
+ no-var: error
+ prefer-arrow-callback: error
+ yield-star-spacing: [error, { before: false, after: true }]
diff --git a/tgui-next/.gitattributes b/tgui-next/.gitattributes
new file mode 100644
index 00000000000..eedf5cb0fc1
--- /dev/null
+++ b/tgui-next/.gitattributes
@@ -0,0 +1,10 @@
+* text=auto
+
+## Enforce text mode and LF line breaks
+*.js text eol=lf
+*.css text eol=lf
+*.html text eol=lf
+*.json text eol=lf
+
+## Treat bundles as binary and ignore them during conflicts
+# *.bundle.* binary merge=theirs
diff --git a/tgui-next/.gitignore b/tgui-next/.gitignore
new file mode 100644
index 00000000000..2844d947c39
--- /dev/null
+++ b/tgui-next/.gitignore
@@ -0,0 +1,4 @@
+node_modules
+*.log
+/packages/tgui/public/bundles/*.hot-update.*
+package-lock.json
diff --git a/tgui-next/README.md b/tgui-next/README.md
new file mode 100644
index 00000000000..a56d74d45b4
--- /dev/null
+++ b/tgui-next/README.md
@@ -0,0 +1,570 @@
+# tgui-next
+
+## Introduction
+
+tgui is a robust user interface framework of /tg/station. It is rendered
+completely in the browser, based on JSON data sent from the server.
+This data flow is always unidirectional, and the only way to make changes
+to the game state is to dispatch actions which are processed on the server,
+in a similar method to native BYOND Topic(). Once the action is processed,
+an updated JSON is sent.
+
+tgui is very different from most UIs you will encounter in BYOND programming,
+and is heavily reliant of Javascript and web technologies as opposed to DM.
+However, if you are familiar with NanoUI (a library which can be found on almost
+every other SS13 codebase), tgui should be fairly easy to pick up.
+
+tgui is a fork of an older tgui (based on Ractive), which is a fork of NanoUI.
+The server-side code (DM) is similar and derived from NanoUI, while the
+clientside is a wholly new project with no code in common.
+
+To get a clearer picture how to create a completely new interface from scratch,
+please refer to this [tutorial document](docs/tutorial-and-examples.md).
+If you don't know how tgui backend works, or have very little knowledge about
+both frontend and backend, or simply want a step by step instruction,
+we recommend you first read the document linked above.
+
+This project uses **Inferno** - a very fast UI rendering engine with a similar
+API to React. If you are new to Inferno or React, take your time to read
+these documents:
+
+- [React guide](https://reactjs.org/docs/hello-world.html)
+- [Inferno documentation](https://infernojs.org/docs/guides/components) -
+highlights differences with React.
+
+## Pre-requisites
+
+You will need these programs to start developing in tgui:
+
+- [Node 12.x](https://nodejs.org)
+- [MSys2](https://www.msys2.org/) (optional)
+
+> MSys2 closely replicates a unix-like environment which is necessary for
+> the `bin/tgui` script to run. It comes with a robust "mintty" terminal
+> emulator which is better than any standard Windows shell, it supports
+> "git" out of the box (almost like Git for Windows, but better), has
+> a "pacman" package manager, and you can install a text editor like "vim"
+> for a full boomer experience.
+
+## Workflow
+
+If you haven't opened the console already, you can do that by holding
+Shift and right clicking on the `tgui-next` folder, then pressing
+either `Open command window here` or `Open PowerShell window here`.
+
+Run `npm install`, then:
+
+- `npm run build` - build the project in production mode.
+- `npm run watch` - launch a development server.
+- `npm run lint` - show and fix potential problems with the code.
+- `npm run analyze` - run a bundle analyzer.
+
+For MSys2, WSL, Linux or macOS users:
+
+- `bin/tgui` - build the project in production mode.
+- `bin/tgui --dev` - launch a development server.
+- `bin/tgui --lint` - show and fix potential problems with the code.
+- `bin/tgui --analyze` - run a bundle analyzer.
+- `bin/tgui --clean` - clean up project repo.
+- `bin/tgui [webpack options]` - build the project with custom webpack
+options.
+
+For absolute brainlets, we also got a batch file in store. Double click
+it to build the project:
+
+- `bin/tgui-build.bat` - build the project in production mode.
+
+Remember to always run a full build before submitting a PR. It creates
+a compressed javascript bundle which is then referenced from DM code.
+We prefer to keep it version controlled, so that people could build the
+game just by using Dream Maker.
+
+## Project structure
+
+- `/packages` - Each folder here represents a self-contained Node module.
+- `/packages/common` - Helper functions
+- `/packages/tgui/index.js` - Application entry point.
+- `/packages/tgui/components` - Basic UI building blocks.
+- `/packages/tgui/interfaces` - Actual in-game interfaces.
+Interface takes data via the `state` prop and outputs an html-like stucture,
+which you can build using existing UI components.
+- `/packages/tgui/routes.js` - This is where you want to register new
+interfaces, otherwise they simply won't load.
+- `/packages/tgui/layout.js` - A root-level component, holding the
+window elements, like the titlebar, buttons, resize handlers. Calls
+`routes.js` to decide which component to render.
+- `/packages/tgui/styles/main.scss` - CSS entry point.
+- `/packages/tgui/styles/atomic.scss` - Atomic CSS classes.
+These are very simple, tiny, reusable CSS classes which you can use and
+combine to change appearance of your elements. Keep them small.
+- `/packages/tgui/styles/components.scss` - CSS classes which are used
+in UI components, and most of the stylesheets referenced here are located
+in `/packages/tgui/components`. These stylesheets closely follow the
+[BEM](https://en.bem.info/methodology/) methodology.
+- `/packages/tgui/styles/functions.scss` - Useful SASS functions.
+Stuff like `lighten`, `darken`, `luminance` are defined here.
+
+## Component reference
+
+> Notice: This documentation might be out of date, so always check the source
+> code to see the most up-to-date information.
+
+These are the components which you can use for interface construction.
+If you have trouble finding the exact prop you need on a component,
+please note, that most of these components inherit from other basic
+components, such as `Box`. This component in particular provides a lot
+of styling options for all components, e.g. `color` and `opacity`, thus
+it is used a lot in this framework.
+
+There are a few important semantics you need to know about:
+
+- `content` prop is a synonym to a `children` prop.
+ - `content` is better used when your element is a self-closing tag
+ (like ``), and when content is small and simple
+ enough to fit in a prop. Keep in mind, that this prop is **not** native
+ to React, and is a feature of this component system.
+ - `children` is better used when your element is a full tag (like
+ ``), and when content is long and complex. This is
+ a native React prop (unlike `content`), and contains all elements you
+ defined between the opening and the closing tag of an element.
+ - You should never use both on a same element.
+ - You should never use `children` explicitly as a prop on an element.
+- Inferno supports both camelcase (`onClick`) and lowercase (`onclick`)
+event names.
+ - Camel case names are what's called "synthetic" events, and are the
+ *preferred way* of handling events in React, for efficiency and
+ performance reasons. Please read
+ [Inferno Event Handling](https://infernojs.org/docs/guides/event-handling)
+ to understand what this is about.
+ - Lower case names are native browser events and should be used sparingly,
+ for example when you need an explicit IE8 support. **DO NOT** use
+ lowercase event handlers unless you really know what you are doing.
+ - [Button](#button) component straight up does not support lowercase event
+ handlers. Use the camel case `onClick` instead.
+
+### `AnimatedNumber`
+
+This component provides animations for numeric values.
+
+Props:
+
+- `value: number` - Value to animate.
+- `initial: number` - Initial value to use in animation when element
+first appears. If you set initial to `0` for example, number will always
+animate starting from `0`, and if omitted, it will not play an initial
+animation.
+- `format: function` - Output formatter.
+ - Example: `value => Math.round(value)`.
+
+### `Box`
+
+The Box component serves as a wrapper component for most of the CSS utility
+needs. It creates a new DOM element, a `
` by default that can be changed
+with the `as` property. Let's say you want to use a `` instead:
+
+```jsx
+
+
+
+```
+
+This works great when the changes can be isolated to a new DOM element.
+For instance, you can change the margin this way.
+
+However, sometimes you have to target the underlying DOM element.
+For instance, you want to change the text color of the button. The Button
+component defines its own color. CSS inheritance doesn't help.
+
+To workaround this problem, the Box children accept a render props function.
+This way, `Button` can pull out the `className` generated by the `Box`.
+
+```jsx
+
+ {props => }
+
+```
+
+`Box` units, like width, height and margins can be defined in two ways:
+- By plain numbers (1 unit equals `0.5em`);
+- In absolute measures, by providing a full unit string (e.g. `100px`).
+
+Units which are used in `Box` are `0.5em`, which are half font-size.
+Default font size is `12px`, so each unit is effectively `6px` in size.
+If you need more precision, you can always use fractional numbers.
+
+Props:
+
+- `as: string` - The component used for the root node.
+- `color: string` - Applies an atomic `color-` class to the element.
+ - See `styles/atomic/color.scss`.
+- `width: number` - Box width.
+- `minWidth: number` - Box minimum width.
+- `maxWidth: number` - Box maximum width.
+- `height: number` - Box height.
+- `minHeight: number` - Box minimum height.
+- `maxHeight: number` - Box maximum height.
+- `lineHeight: number` - Directly affects the height of text lines.
+Useful for adjusting button height.
+- `inline: boolean` - Forces the `Box` to appear as an `inline-block`,
+or in other words, makes the `Box` flow with the text instead of taking
+all available horizontal space.
+- `m: number` - Margin on all sides.
+- `mx: number` - Horizontal margin.
+- `my: number` - Vertical margin.
+- `mt: number` - Top margin.
+- `mb: number` - Bottom margin.
+- `ml: number` - Left margin.
+- `mr: number` - Right margin.
+- `opacity: number` - Opacity, from 0 to 1.
+- `bold: boolean` - Make text bold.
+- `italic: boolean` - Make text italic.
+- `textAlign: string` - Align text inside the box.
+ - `left` (default)
+ - `center`
+ - `right`
+- `position: string` - A direct mapping to `position` CSS property.
+ - `relative` - Relative positioning.
+ - `absolute` - Absolute positioning.
+ - `fixed` - Fixed positioning.
+- `top: number` - Vertical position of a positioned element.
+- `bottom: number` - Vertical position of a positioned element.
+- `left: number` - Horizontal position of a positioned element.
+- `right: number` - Horizontal position of a positioned element.
+
+### `Button`
+
+Buttons allow users to take actions, and make choices, with a single click.
+
+Props:
+
+- See inherited props: [Box](#box)
+- `fluid: boolean` - Tells the button to fill all available horizontal space.
+- `icon: string` - Adds an icon to the button.
+- `color: string` - Button color, as defined in `variables.scss`.
+ - There is also a special color `transparent` - makes the button
+ transparent and slightly dim when inactive.
+- `disabled: boolean` - Disables and greys out the button.
+- `selected: boolean` - Activates the button (gives it a green color).
+- `tooltip: string` - A fancy, boxy tooltip, which appears when hovering
+over the button.
+- `tooltipPosition: string` - Position of the tooltip.
+ - `top` - Show tooltip above the button.
+ - `bottom` (default) - Show tooltip below the button.
+ - `left` - Show tooltip on the left of the button.
+ - `right` - Show tooltip on the right of the button.
+- `title: string` - A native browser tooltip, which appears when hovering
+over the button.
+- `content/children: any` - Content to render inside the button.
+- `onClick: function` - Called when element is clicked.
+
+### `Flex`
+
+Quickly manage the layout, alignment, and sizing of grid columns, navigation, components, and more with a full suite of responsive flexbox utilities.
+
+If you are new to or unfamiliar with flexbox, we encourage you to read this
+[CSS-Tricks flexbox guide](https://css-tricks.com/snippets/css/a-guide-to-flexbox/).
+
+Consists of two elements: `` and ``. Both of them provide
+the most straight-forward mapping to flex CSS properties as possible.
+
+One of the most basic usage of flex, is to align certain elements
+to the left, and certain elements to the right:
+
+```jsx
+
+
+ Button description
+
+
+
+
+
+
+```
+
+Flex item with `grow` property serves as a "filler", to separate the other
+two flex items as far as possible from each other.
+
+Props:
+
+- See inherited props: [Box](#box)
+- `direction: string` - This establishes the main-axis, thus defining the
+direction flex items are placed in the flex container.
+ - `row` (default) - left to right.
+ - `row-reverse` - right to left.
+ - `column` - top to bottom.
+ - `column-reverse` - bottom to top.
+- `wrap: string` - By default, flex items will all try to fit onto one line.
+You can change that and allow the items to wrap as needed with this property.
+ - `nowrap` (default) - all flex items will be on one line
+ - `wrap` - flex items will wrap onto multiple lines, from top to bottom.
+ - `wrap-reverse` - flex items will wrap onto multiple lines from bottom to top.
+- `align: string` - Default alignment of all children.
+ - `stretch` (default) - stretch to fill the container.
+ - `start` - items are placed at the start of the cross axis.
+ - `end` - items are placed at the end of the cross axis.
+ - `center` - items are centered on the cross axis.
+ - `baseline` - items are aligned such as their baselines align.
+- `justify: string` - This defines the alignment along the main axis.
+It helps distribute extra free space leftover when either all the flex
+items on a line are inflexible, or are flexible but have reached their
+maximum size. It also exerts some control over the alignment of items
+when they overflow the line.
+ - `flex-start` (default) - items are packed toward the start of the
+ flex-direction.
+ - `flex-end` - items are packed toward the end of the flex-direction.
+ - `space-between` - items are evenly distributed in the line; first item is
+ on the start line, last item on the end line
+ - `space-around` - items are evenly distributed in the line with equal space
+ around them. Note that visually the spaces aren't equal, since all the items
+ have equal space on both sides. The first item will have one unit of space
+ against the container edge, but two units of space between the next item
+ because that next item has its own spacing that applies.
+ - `space-evenly` - items are distributed so that the spacing between any two
+ items (and the space to the edges) is equal.
+ - TBD (not all properties are supported in IE11).
+
+### `Flex.Item`
+
+Props:
+
+- See inherited props: [Box](#box)
+- `order: number` - By default, flex items are laid out in the source order.
+However, the order property controls the order in which they appear in the
+flex container.
+- `grow: number` - This defines the ability for a flex item to grow if
+necessary. It accepts a unitless value that serves as a proportion. It
+dictates what amount of the available space inside the flex container the
+item should take up. This number is unit-less and is relative to other
+siblings.
+- `shrink: number` - This defines the ability for a flex item to shrink
+if necessary. Inverse of `grow`.
+- `basis: string` - This defines the default size of an element before the
+remaining space is distributed. It can be a length (e.g. `20%`, `5rem`, etc.),
+an `auto` or `content` keyword.
+- `align: string` - This allows the default alignment (or the one specified by align-items) to be overridden for individual flex items. See: [Flex](#flex).
+
+### `Icon`
+
+Renders one of the FontAwesome icons of your choice.
+
+```jsx
+
+```
+
+To smoothen the transition from v4 to v5, we have added a v4 semantic to
+transform names with `-o` suffixes to FA Regular icons. For example:
+- `square` will get transformed to `fas square`
+- `square-o` will get transformed to `far square`
+
+Props:
+
+- See inherited props: [Box](#box)
+- `name: string` - Icon name.
+- `size: number` - Icon size. `1` is normal size, `2` is two times bigger.
+Fractional numbers are supported.
+
+### `LabeledList`
+
+LabeledList is a continuous, vertical list of text and other content, where
+every item is labeled. It works just like a two column table, where first
+column is labels, and second column is content.
+
+```jsx
+
+
+ Content
+
+
+```
+
+If you want to have a button on the right side of an item (for example,
+to perform some sort of action), there is a way to do that:
+
+```jsx
+
+
+ )}>
+ Content
+
+
+```
+
+Props:
+
+- `children: LabeledList.Item` - Items to render.
+
+### `LabeledList.Item`
+
+Props:
+
+- `label: string` - Item label.
+- `color: string` - Sets the color of the text.
+- `buttons: any` - Buttons to render aside the content.
+- `content/children: any` - Content of this labeled item.
+
+### `LabeledList.Divider`
+
+Adds some empty space between LabeledList items.
+
+Example:
+
+```jsx
+
+
+ Content
+
+
+
+```
+
+Props:
+
+- `size: number` - Size of the divider.
+
+### `ProgressBar`
+
+Progress indicators inform users about the status of ongoing processes.
+
+```jsx
+
+```
+
+- `value: number` - Current progress as a floating point number,
+from 0 to 1. Determines how filled the bar is.
+- `color: string` - Color of the progress bar.
+- `content/children: any` - Content to render inside the progress bar.
+
+### `Section`
+
+Section is a surface that displays content and actions on a single topic.
+
+They should be easy to scan for relevant and actionable information.
+Elements, like text and images, should be placed in them in a way that
+clearly indicates hierarchy.
+
+Section can also be titled to clearly define its purpose.
+
+```jsx
+
+ Here you can order supply crates.
+
+```
+
+If you want to have a button on the right side of an section title
+(for example, to perform some sort of action), there is a way to do that:
+
+```jsx
+
+ )}>
+ Here you can order supply crates.
+
+```
+
+- See inherited props: [Box](#box)
+- `title: string` - Title of the section.
+- `level: number` - Section level in hierarchy. Default is 1, higher number
+means deeper level of nesting. Must be an integer number.
+- `buttons: any` - Buttons to render aside the section title.
+- `content/children: any` - Content of this section.
+
+### `Tabs`
+
+Tabs make it easy to explore and switch between different views.
+
+Here is an example of how you would construct a simple tabbed view:
+
+```jsx
+
+
+ Content for Item one.
+
+
+ Content for Item two.
+
+
+```
+
+This is a rather simple example. In the real world, you might be
+constructing very complex tabbed views which can tax UI performance.
+This is because your tabs are being rendered regardless of their
+visibility status!
+
+There is a simple fix however. Tabs accept functions as children, which
+will be called to retrieve content only when the tab is visible:
+
+```jsx
+
+
+ {() => (
+
+ Content for Item one.
+
+ )}
+
+
+ {() => (
+
+ Content for Item two.
+
+ )}
+
+
+```
+
+You might not always need this, but it is highly recommended to always
+use this method. Notice the `key` prop on tabs - it uniquely identifies
+the tab and is used for determining which tab is currently active. It can
+be either explicitly provided as a `key` prop, or if omitted, it will be
+implicitly derived from the tab's `label` prop.
+
+Props:
+
+- `vertical: boolean` - Use a vertical configuration, where tabs will appear
+stacked on the left side of the container.
+- `children: Tab[]` - This component only accepts tabs as its children.
+
+### `Tabs.Tab`
+
+An individual tab element. Tabs function like buttons, so they inherit
+a lot of `Button` props.
+
+Props:
+
+- See inherited props: [Button](#button)
+- `key: string` - A unique identifier for the tab.
+- `label: string` - Tab label.
+- `icon: string` - Tab icon.
+- `content/children: any` - Content to render inside the tab.
+- `onClick: function` - Called when element is clicked.
+
+### `Tooltip`
+
+A boxy tooltip from tgui 1. It is very hacky in its current state, and
+requires setting `position: relative` on the container.
+
+Please note, that [Button](#button) component has a `tooltip` prop, and
+it is recommended to use that prop instead.
+
+Usage:
+
+```jsx
+
+ Sample text.
+
+
+```
+
+Props:
+
+- `position: string` - Tooltip position.
+- `content/children: string` - Content of the tooltip. Must be a plain string.
+Fragments or other elements are **not** supported.
diff --git a/tgui-next/bin/tgui b/tgui-next/bin/tgui
new file mode 100755
index 00000000000..89be2f4a46c
--- /dev/null
+++ b/tgui-next/bin/tgui
@@ -0,0 +1,51 @@
+#!/bin/bash
+## Script for building tgui. Requires MSYS2 to run.
+set -e
+cd "$(dirname "${0}")/.."
+base_dir="$(pwd)"
+
+## Add locally installed node programs to path
+PATH="${PATH}:node_modules/.bin"
+
+run-webpack() {
+ cd "${base_dir}/packages/tgui"
+ exec webpack "${@}"
+}
+
+## Mr. Proper
+if [[ ${1} == "--clean" ]]; then
+ shopt -s globstar
+ rm -rf **/node_modules
+ exit 0
+fi
+
+## Install dependencies
+if [[ ! -e node_modules ]]; then
+ npm install
+fi
+
+## Run a development server
+if [[ ${1} == "--dev" ]]; then
+ shift
+ cd "${base_dir}/packages/tgui-dev-server"
+ exec node --experimental-modules index.js "${@}"
+fi
+
+## Run a linter through all packages
+if [[ ${1} == '--lint' ]]; then
+ shift
+ exec eslint ./packages "${@}"
+fi
+
+## Analyze the bundle
+if [[ ${1} == '--analyze' ]]; then
+ run-webpack --mode=production --analyze
+fi
+
+## Make a production webpack build
+if [[ -z ${1} ]]; then
+ run-webpack --mode=production
+fi
+
+## Run webpack with custom flags
+run-webpack "${@}"
diff --git a/tgui-next/bin/tgui-build.bat b/tgui-next/bin/tgui-build.bat
new file mode 100644
index 00000000000..64d6a4798fd
--- /dev/null
+++ b/tgui-next/bin/tgui-build.bat
@@ -0,0 +1,4 @@
+@echo off
+cd "%~dp0\.."
+call npm ci
+call npm run build
diff --git a/tgui-next/docs/tutorial-and-examples.md b/tgui-next/docs/tutorial-and-examples.md
new file mode 100644
index 00000000000..2bf4e88459c
--- /dev/null
+++ b/tgui-next/docs/tutorial-and-examples.md
@@ -0,0 +1,236 @@
+# TGUI Backend Documentation
+
+## Main concepts
+
+Basic tgui backend code consists of defining a few procs. In these procs
+you will handle a request to open or update a UI (typically by updating a UI
+if it exists or setting up and opening it if it does not), a request for data,
+in which you build a list to be passed as JSON to the UI, and an action
+handler, which handles any user input.
+
+- The atom, which UI corresponds to in the game world, is in most cases
+known as the `src_object`.
+- Frontend data is built in `ui_data` proc, which munges whatever complex
+data your `src_object` has into a list.
+- The action/topic handler, `ui_act`, is what recieves input from the user
+and acts on it.
+- The request/update proc, `ui_interact` is where you open your UI and set
+options like title, size, autoupdate, theme, and more.
+- Finally, `ui_state` (set in `ui_interact`) dictates under what conditions
+a UI may be interacted with. This may be the standard checks that check if
+you are in range and conscious, or more.
+
+Once backend is complete, you create an new interface component on the
+frontend, which will receive this JSON data and render it on screen.
+
+States are easy to write and extend, and what make tgui interactions so
+powerful. Because states can be overridden from other procs, you can build
+powerful interactions for embedded objects or remote access.
+
+## Using It
+
+### Backend
+
+Let's start with a very basic hello world.
+
+```dm
+/obj/machinery/my_machine/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = 0, datum/tgui/master_ui = null, datum/ui_state/state = default_state)
+ ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
+ if(!ui)
+ ui = new(user, src, ui_key, "my_machine", name, 300, 300, master_ui, state)
+ ui.open()
+```
+
+This is the proc that defines our interface. There's a bit going on here, so
+let's break it down. First, we override the ui_interact proc on our object. This
+will be called by `interact` for you, which is in turn called by `attack_hand`
+(or `attack_self` for items). `ui_interact` is also called to update a UI (hence
+the `try_update_ui`), so we accept an existing UI to update. The `state` is a
+default argument so that a caller can overload it with named arguments
+(`ui_interact(state = overloaded_state)`) if needed.
+
+Inside the `if(!ui)` block (which means we are creating a new UI), we choose our
+template, title, and size; we can also set various options like `style` (for
+themes), or autoupdate. These options will be elaborated on later (as will
+`ui_state`s).
+
+After `ui_interact`, we need to define `ui_data`. This just returns a list of
+data for our object to use. Let's imagine our object has a few vars:
+
+```dm
+/obj/machinery/my_machine/ui_data(mob/user)
+ var/list/data = list()
+ data["health"] = health
+ data["color"] = color
+
+ return data
+```
+
+The `ui_data` proc is what people often find the hardest about tgui, but its
+really quite simple! You just need to represent your object as numbers, strings,
+and lists, instead of atoms and datums.
+
+Finally, the `ui_act` proc is called by the interface whenever the user used an
+input. The input's `action` and `params` are passed to the proc.
+
+```dm
+/obj/machinery/my_machine/ui_act(action, params)
+ if(..())
+ return
+ switch(action)
+ if("change_color")
+ var/new_color = params["color"]
+ if(!(color in allowed_coors))
+ return
+ color = new_color
+ . = TRUE
+ update_icon()
+```
+
+The `..()` (parent call) is very important here, as it is how we check that the
+user is allowed to use this interface (to avoid so-called href exploits). It is
+also very important to clamp and sanitize all input here. Always assume the user
+is attempting to exploit the game.
+
+Also note the use of `. = TRUE` (or `FALSE`), which is used to notify the UI
+that this input caused an update. This is especially important for UIs that do
+not auto-update, as otherwise the user will never see their change.
+
+### Frontend
+
+Finally, you have to make a UI component. This is also a source of
+confusion for many new users. If you got some basic javascript and HTML
+knowledge, that should ease the learning process, although we recommend
+getting yourself introduced to
+[React and JSX](https://reactjs.org/docs/introducing-jsx.html).
+
+A component is not a regular HTML. A component is a pure function, which
+accepts a `props` object (it contains properties passed to a component),
+and outputs an HTML-like structure consisting of regular HTML elements and
+other UI components.
+
+Interface component will always receive 1 prop which is called `state`.
+This object contains a few special values:
+
+- `config` is always the same and is part of core tgui
+(it will be explained later),
+- `data` is the data returned from `ui_data`
+- `adata` is the same, but with certain values (numbers at this time)
+interpolated in order to allow animation.
+
+```jsx
+import { Section, LabeledList } from '../components';
+
+const SampleInterface = props => {
+ // Extract state from props
+ const { state } = props;
+ // Extract config and data from the state
+ const { config, data } = state;
+ // Extract window reference (will be used later for dispatching actions)
+ const { ref } = config;
+ // Return the Virtual DOM
+ return (
+
+
+
+ {data.health}
+
+
+ {data.color}
+
+
+
+ );
+};
+```
+
+This syntax can be very confusing at first, but it is very important to
+realize that this is just a natural extension of javascript. This syntax
+simply creates a Virtual DOM object, which you can treat as any other
+object in javascript. Here are some control flow examples:
+
+Returning different elements based on a condition:
+
+```jsx
+if (condition) {
+ return ;
+}
+return ;
+```
+
+Conditionally rendering a element inside of another element:
+
+```jsx
+
+ {showProgress && (
+
+ )}
+
+```
+
+Looping over the array to make element for each item:
+
+```jsx
+
+ {items.map(item => (
+
+ {item.content}
+
+ ))}
+
+```
+
+## Copypasta
+
+We all do it, even the best of us. If you just want to make a tgui **fast**,
+here's what you need (note that you'll probably be forced to clean your shit up
+upon code review):
+
+```dm
+/obj/copypasta/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = 0, datum/tgui/master_ui = null, datum/ui_state/state = default_state) // Remember to use the appropriate state.
+ ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
+ if(!ui)
+ ui = new(user, src, ui_key, "copypasta", name, 300, 300, master_ui, state)
+ ui.open()
+
+/obj/copypasta/ui_data(mob/user)
+ var/list/data = list()
+ data["var"] = var
+
+ return data
+
+/obj/copypasta/ui_act(action, params)
+ if(..())
+ return
+ switch(action)
+ if("copypasta")
+ var/newvar = params["var"]
+ var = Clamp(newvar, min_val, max_val) // Just a demo of proper input sanitation.
+ . = TRUE
+ update_icon() // Not applicable to all objects.
+```
+
+And the template:
+
+```jsx
+import { Section, LabeledList } from '../components';
+
+const SampleInterface = props => {
+ // Extract state from props
+ const { state } = props;
+ // Extract config and data from the state
+ const { config, data } = state;
+ // Extract window reference (will be used later for dispatching actions)
+ const { ref } = config;
+ // Return the Virtual DOM
+ return (
+
+
+
+ {data.var}
+
+
+
+ );
+};
+```
diff --git a/tgui-next/lerna.json b/tgui-next/lerna.json
new file mode 100644
index 00000000000..89763cc18c4
--- /dev/null
+++ b/tgui-next/lerna.json
@@ -0,0 +1,6 @@
+{
+ "packages": [
+ "packages/*"
+ ],
+ "version": "0.1.0"
+}
diff --git a/tgui-next/package.json b/tgui-next/package.json
new file mode 100644
index 00000000000..93bcdccb1cf
--- /dev/null
+++ b/tgui-next/package.json
@@ -0,0 +1,21 @@
+{
+ "private": true,
+ "name": "tgui-next",
+ "version": "0.1.0",
+ "workspaces": [
+ "packages/*"
+ ],
+ "scripts": {
+ "watch": "cd packages/tgui-dev-server && node --experimental-modules index.js",
+ "build": "cd packages/tgui && npx webpack --mode=production",
+ "analyze": "cd packages/tgui && npx webpack --mode=production --env.analyze=1",
+ "lint": "eslint packages",
+ "postinstall": "lerna bootstrap --hoist --no-ci && npx symlink-dir packages/common node_modules/common && npx symlink-dir packages/tgui node_modules/tgui && npx symlink-dir packages/tgui-dev-server node_modules/tgui-dev-server"
+ },
+ "dependencies": {
+ "babel-eslint": "^10.0.3",
+ "eslint": "^6.4.0",
+ "lerna": "^3.16.4",
+ "symlink-dir": "^3.1.1"
+ }
+}
diff --git a/tgui-next/packages/common/fp.js b/tgui-next/packages/common/fp.js
new file mode 100644
index 00000000000..1c5b0a853a3
--- /dev/null
+++ b/tgui-next/packages/common/fp.js
@@ -0,0 +1,75 @@
+/**
+ * @file
+ * @copyright 2018 Aleksej Komarov
+ * @license GPL-2.0-or-later
+ */
+
+/**
+ * Creates a function that returns the result of invoking the given
+ * functions, where each successive invocation is supplied the return
+ * value of the previous.
+ */
+export const flow = (...funcs) => (input, ...rest) => {
+ let output = input;
+ for (let func of funcs) {
+ // Recurse into the array of functions
+ if (Array.isArray(func)) {
+ output = flow(...func)(output, ...rest);
+ }
+ else if (func) {
+ output = func(output, ...rest);
+ }
+ }
+ return output;
+};
+
+/**
+ * Composes single-argument functions from right to left.
+ *
+ * All functions might accept a context in form of additional arguments.
+ * If the resulting function is called with more than 1 argument, rest of
+ * the arguments are passed to all functions unchanged.
+ *
+ * @param {...Function} funcs The functions to compose
+ * @returns {Function} A function obtained by composing the argument functions
+ * from right to left. For example, compose(f, g, h) is identical to doing
+ * (input, ...rest) => f(g(h(input, ...rest), ...rest), ...rest)
+ */
+export const compose = (...funcs) => {
+ if (funcs.length === 0) {
+ return arg => arg;
+ }
+ if (funcs.length === 1) {
+ return funcs[0];
+ }
+ return funcs.reduce((a, b) => (value, ...rest) =>
+ a(b(value, ...rest), ...rest));
+};
+
+/**
+ * Creates an array of values by running each element in collection
+ * thru an iteratee function. The iteratee is invoked with three
+ * arguments: (value, index|key, collection).
+ *
+ * If collection is 'null' or 'undefined', it will be returned "as is"
+ * without emitting any errors (which can be useful in some cases).
+ */
+export const map = iteratorFn => collection => {
+ if (collection === null && collection === undefined) {
+ return collection;
+ }
+ if (Array.isArray(collection)) {
+ return collection.map(iteratorFn);
+ }
+ if (typeof collection === 'object') {
+ const hasOwnProperty = Object.prototype.hasOwnProperty;
+ const result = [];
+ for (let i in collection) {
+ if (hasOwnProperty.call(collection, i)) {
+ result.push(iteratorFn(collection[i], i, collection));
+ }
+ }
+ return result;
+ }
+ throw new Error(`map() can't iterate on type ${typeof collection}`);
+};
diff --git a/tgui-next/packages/common/logging.js b/tgui-next/packages/common/logging.js
new file mode 100644
index 00000000000..6b5c54883b2
--- /dev/null
+++ b/tgui-next/packages/common/logging.js
@@ -0,0 +1,71 @@
+/**
+ * Copyright (c) 2019 Aleksej Komarov
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+const inception = Date.now();
+
+// Runtime detection
+const isNode = process && process.release && process.release.name === 'node';
+let isChrome = false;
+try {
+ isChrome = window.navigator.userAgent.toLowerCase().includes('chrome');
+}
+catch {}
+
+// Timestamping function
+const getTimestamp = () => {
+ const timestamp = String(Date.now() - inception)
+ .padStart(4, '0')
+ .padStart(7, ' ');
+ const seconds = timestamp.substr(0, timestamp.length - 3);
+ const millis = timestamp.substr(-3);
+ return `${seconds}.${millis}`;
+};
+
+const getPrefix = (() => {
+ if (isNode) {
+ // Escape sequences
+ const ESC = {
+ dimmed: '\x1b[38;5;240m',
+ bright: '\x1b[37;1m',
+ reset: '\x1b[0m',
+ };
+ return ns => [
+ `${ESC.dimmed}${getTimestamp()} ${ESC.bright}${ns}${ESC.reset}`,
+ ];
+ }
+ if (isChrome) {
+ // Styles
+ const styles = {
+ dimmed: 'color: #888',
+ bright: 'font-weight: bold',
+ };
+ return ns => [
+ `%c${getTimestamp()}%c ${ns}`,
+ styles.dimmed,
+ styles.bright,
+ ];
+ }
+ return ns => [
+ `${getTimestamp()} ${ns}`,
+ ];
+})();
+
+/**
+ * Creates a logger object.
+ */
+export const createLogger = ns => ({
+ log: (...args) => console.log(...getPrefix(ns), ...args),
+ trace: (...args) => console.trace(...getPrefix(ns), ...args),
+ debug: (...args) => console.debug(...getPrefix(ns), ...args),
+ info: (...args) => console.info(...getPrefix(ns), ...args),
+ warn: (...args) => console.warn(...getPrefix(ns), ...args),
+ error: (...args) => console.error(...getPrefix(ns), ...args),
+});
+
+/**
+ * Explicitly log with chosen namespace.
+ */
+export const directLog = (ns, ...args) =>
+ console.log(...getPrefix(ns), ...args);
diff --git a/tgui-next/packages/common/math.js b/tgui-next/packages/common/math.js
new file mode 100644
index 00000000000..a33b9aa214c
--- /dev/null
+++ b/tgui-next/packages/common/math.js
@@ -0,0 +1,19 @@
+/**
+ * Limits a number to the range between 'min' and 'max'.
+ */
+export const clamp = (value, min = 0, max = 1) => {
+ return Math.max(min, Math.min(value, max));
+};
+
+/**
+ * Returns a rounded number.
+ * TODO: Replace this native rounding function with a more robust one.
+ */
+export const round = value => Math.round(value);
+
+/**
+ * Returns a string representing a number in fixed point notation.
+ */
+export const toFixed = (value, fractionDigits = 0) => {
+ return Number(value).toFixed(fractionDigits);
+};
diff --git a/tgui-next/packages/common/package.json b/tgui-next/packages/common/package.json
new file mode 100644
index 00000000000..56dd3f7fd44
--- /dev/null
+++ b/tgui-next/packages/common/package.json
@@ -0,0 +1,6 @@
+{
+ "private": true,
+ "name": "common",
+ "version": "0.1.0",
+ "type": "module"
+}
diff --git a/tgui-next/packages/common/react.js b/tgui-next/packages/common/react.js
new file mode 100644
index 00000000000..c6e0af4b160
--- /dev/null
+++ b/tgui-next/packages/common/react.js
@@ -0,0 +1,77 @@
+/**
+ * Helper for conditionally adding/removing classes in React
+ *
+ * @copyright 2018 Aleksej Komarov
+ * @license GPL-2.0-or-later
+ *
+ * @return {string}
+ */
+export const classes = (...args) => {
+ const classNames = [];
+ const hasOwn = Object.prototype.hasOwnProperty;
+ for (let i = 0; i < args.length; i++) {
+ const arg = args[i];
+ if (!arg) {
+ continue;
+ }
+ if (typeof arg === 'string' || typeof arg === 'number') {
+ classNames.push(arg);
+ }
+ else if (Array.isArray(arg) && arg.length) {
+ const inner = classes.apply(null, arg);
+ if (inner) {
+ classNames.push(inner);
+ }
+ }
+ else if (typeof arg === 'object') {
+ for (let key in arg) {
+ if (hasOwn.call(arg, key) && arg[key]) {
+ classNames.push(key);
+ }
+ }
+ }
+ }
+ return classNames.join(' ');
+};
+
+/**
+ * Normalizes children prop, so that it is always an array of VDom
+ * elements.
+ */
+export const normalizeChildren = children => {
+ if (Array.isArray(children)) {
+ return children.filter(value => value);
+ }
+ if (typeof children === 'object') {
+ return [children];
+ }
+ return [];
+};
+
+/**
+ * Shallowly checks if two objects are different.
+ * Credit: https://github.com/developit/preact-compat
+ */
+export const shallowDiffers = (a, b) => {
+ let i;
+ for (i in a) {
+ if (!(i in b)) {
+ return true;
+ }
+ }
+ for (i in b) {
+ if (a[i] !== b[i]) {
+ return true;
+ }
+ }
+ return false;
+};
+
+/**
+ * Default inferno hooks for pure components.
+ */
+export const pureComponentHooks = {
+ onComponentShouldUpdate: (lastProps, nextProps) => {
+ return shallowDiffers(lastProps, nextProps);
+ },
+};
diff --git a/tgui-next/packages/common/redux.js b/tgui-next/packages/common/redux.js
new file mode 100644
index 00000000000..257a9eebf58
--- /dev/null
+++ b/tgui-next/packages/common/redux.js
@@ -0,0 +1,65 @@
+import { compose } from './fp';
+
+/**
+ * Creates a Redux store.
+ */
+export const createStore = (reducer, enhancer) => {
+ // Apply a store enhancer (applyMiddleware is one of them).
+ if (enhancer) {
+ return enhancer(createStore)(reducer);
+ }
+
+ let currentState;
+ let listeners = [];
+
+ const getState = () => currentState;
+
+ const subscribe = listener => {
+ listeners.push(listener);
+ };
+
+ const dispatch = action => {
+ currentState = reducer(currentState, action);
+ listeners.forEach(fn => fn());
+ };
+
+ // This creates the initial store by causing each reducer to be called
+ // with an undefined state
+ dispatch({
+ type: '@@INIT',
+ });
+
+ return {
+ dispatch,
+ subscribe,
+ getState,
+ };
+};
+
+/**
+ * Creates a store enhancer which applies middleware to all dispatched
+ * actions.
+ */
+export const applyMiddleware = (...middlewares) => {
+ return createStore => (reducer, ...args) => {
+ const store = createStore(reducer, ...args);
+
+ let dispatch = () => {
+ throw new Error(
+ 'Dispatching while constructing your middleware is not allowed.');
+ };
+
+ const storeApi = {
+ getState: store.getState,
+ dispatch: (action, ...args) => dispatch(action, ...args),
+ };
+
+ const chain = middlewares.map(middleware => middleware(storeApi));
+ dispatch = compose(...chain)(store.dispatch);
+
+ return {
+ ...store,
+ dispatch,
+ };
+ };
+};
diff --git a/tgui-next/packages/common/string.js b/tgui-next/packages/common/string.js
new file mode 100644
index 00000000000..09d0a31ed30
--- /dev/null
+++ b/tgui-next/packages/common/string.js
@@ -0,0 +1,150 @@
+/**
+ * @file
+ * @copyright 2018 Aleksej Komarov
+ * @license GPL-2.0-or-later
+ */
+
+/**
+ * Removes excess whitespace and indentation from the string
+ * @param {string} str
+ * @return {string}
+ */
+export const compact = str => {
+ return str
+ .trim()
+ .split('\n')
+ .map(x => x.trim())
+ .filter(x => x.length > 0)
+ .join('\n');
+};
+
+/**
+ * Template literal tag for rendering HTML
+ */
+export const html = (strings, ...expressions) => {
+ const length = strings.length;
+ let output = '';
+ for (let i = 0; i < length; i++) {
+ output += strings[i];
+ let expr = expressions[i];
+ if (typeof expr === 'boolean' || expr === undefined || expr === null) {
+ // Nothing
+ }
+ else if (Array.isArray(expr)) {
+ output += expr.join('\n');
+ }
+ else {
+ output += expr;
+ }
+ }
+ return output;
+};
+
+/**
+ * Matches strings with wildcards.
+ * Example: testGlobPattern('*@domain')('user@domain') === true
+ */
+export const testGlobPattern = pattern => {
+ const escapeString = str => str.replace(/[|\\{}()[\]^$+*?.]/g, '\\$&');
+ const regex = new RegExp('^'
+ + pattern.split(/\*+/).map(escapeString).join('.*')
+ + '$');
+ return str => regex.test(str);
+};
+
+export const capitalize = str => {
+ // Handle array
+ if (Array.isArray(str)) {
+ return str.map(capitalize);
+ }
+ // Handle string
+ return str.charAt(0).toUpperCase() + str.slice(1).toLowerCase();
+};
+
+export const toLowerCase = str => {
+ if (typeof str !== 'string') {
+ return str;
+ }
+ return str.toLowerCase();
+};
+
+export const toUpperCase = str => {
+ if (typeof str !== 'string') {
+ return str;
+ }
+ return str.toUpperCase();
+};
+
+export const toTitleCase = str => {
+ // Handle array
+ if (Array.isArray(str)) {
+ return str.map(toTitleCase);
+ }
+ // Pass non-string
+ if (typeof str !== 'string') {
+ return str;
+ }
+ // Handle string
+ const WORDS_UPPER = ['Id', 'Tv'];
+ const WORDS_LOWER = [
+ 'A', 'An', 'And', 'As', 'At', 'But', 'By', 'For', 'For', 'From', 'In', 'Into',
+ 'Near', 'Nor', 'Of', 'On', 'Onto', 'Or', 'The', 'To', 'With',
+ ];
+ let currentStr = str.replace(/([^\W_]+[^\s-]*) */g, str => {
+ return str.charAt(0).toUpperCase() + str.substr(1).toLowerCase();
+ });
+ for (let word of WORDS_LOWER) {
+ const regex = new RegExp('\\s' + word + '\\s', 'g');
+ currentStr = currentStr.replace(regex, str => str.toLowerCase());
+ }
+ for (let word of WORDS_UPPER) {
+ const regex = new RegExp('\\b' + word + '\\b', 'g');
+ currentStr = currentStr.replace(regex, str => str.toLowerCase());
+ }
+ return currentStr;
+};
+
+/**
+ * Decodes HTML entities, and removes unnecessary HTML tags.
+ *
+ * @param {String} str Encoded HTML string
+ * @return {String} Decoded HTML string
+ */
+export const decodeHtmlEntities = str => {
+ if (!str) {
+ return str;
+ }
+ const translate_re = /&(nbsp|amp|quot|lt|gt|apos);/g;
+ const translate = {
+ nbsp: ' ',
+ amp: '&',
+ quot: '"',
+ lt: '<',
+ gt: '>',
+ apos: '\'',
+ };
+ return str
+ // Newline tags
+ .replace(/ /gi, '\n')
+ .replace(/<\/?[a-z0-9-_]+[^>]*>/gi, '')
+ // Basic entities
+ .replace(translate_re, (match, entity) => translate[entity])
+ // Decimal entities
+ .replace(/?([0-9]+);/gi, (match, numStr) => {
+ const num = parseInt(numStr, 10);
+ return String.fromCharCode(num);
+ })
+ // Hex entities
+ .replace(/?([0-9a-f]+);/gi, (match, numStr) => {
+ const num = parseInt(numStr, 16);
+ return String.fromCharCode(num);
+ });
+};
+
+/**
+ * Converts an object into a query string,
+ */
+export const buildQueryString = obj => Object.keys(obj)
+ .map(key => encodeURIComponent(key)
+ + '=' + encodeURIComponent(obj[key]))
+ .join('&');
diff --git a/tgui-next/packages/tgui-dev-server/index.js b/tgui-next/packages/tgui-dev-server/index.js
new file mode 100644
index 00000000000..6af06c5ad46
--- /dev/null
+++ b/tgui-next/packages/tgui-dev-server/index.js
@@ -0,0 +1,117 @@
+import { createLogger } from 'common/logging.js';
+import fs from 'fs';
+import glob from 'glob';
+import { createRequire } from 'module';
+import os from 'os';
+import path from 'path';
+import util from 'util';
+import webpack from 'webpack';
+import { broadcastMessage, setupLink } from './link/server.js';
+
+const WEBPACK_HMR_ENABLED = process.platform === 'win32'
+ || process.argv.includes('--hot');
+
+const setupServer = async () => {
+ const link = setupLink();
+ await setupWebpack(link);
+};
+
+const getWebpackConfig = async () => {
+ const logger = createLogger('webpack');
+ const require = createRequire(import.meta.url);
+ const createConfig = await require('../tgui/webpack.config.js');
+ const config = createConfig({}, {
+ mode: 'development',
+ // Enable hot module reloading only on Windows.
+ hot: WEBPACK_HMR_ENABLED,
+ });
+ if (!WEBPACK_HMR_ENABLED) {
+ logger.log('hot module reloading is disabled');
+ }
+ return config;
+};
+
+const setupWebpack = async link => {
+ const logger = createLogger('webpack');
+ logger.log('setting up');
+ const config = await getWebpackConfig();
+ const bundleDir = config.output.path;
+ // Instantiate the compiler
+ const compiler = webpack(config);
+ // Clear garbage before compiling
+ compiler.hooks.watchRun.tapPromise('tgui-dev-server', async () => {
+ const files = await resolvePath(bundleDir, './*.hot-update.*');
+ logger.log(`clearing garbage (${files.length} files)`);
+ for (let file of files) {
+ await util.promisify(fs.unlink)(file);
+ }
+ logger.log('compiling');
+ });
+ // Start reloading when it's finished
+ compiler.hooks.done.tap('tgui-dev-server', async stats => {
+ await reloadByondCache(bundleDir);
+ // Notify all clients that update has happened
+ if (WEBPACK_HMR_ENABLED) {
+ broadcastMessage(link, {
+ type: 'hotUpdate',
+ });
+ }
+ });
+ // Start watching
+ logger.log('watching for changes');
+ compiler.watch({}, (err, stats) => {
+ if (err) {
+ logger.error('compilation error', err);
+ return;
+ }
+ logger.log(stats.toString(config.devServer.stats));
+ });
+};
+
+/**
+ * Combines path.resolve with glob patterns.
+ */
+const resolvePath = (...sections) => {
+ return util.promisify(glob)(path.resolve(...sections));
+};
+
+const CACHE_PATTERN = './BYOND/cache/tmp*';
+
+const reloadByondCache = async bundleDir => {
+ const logger = createLogger('reloader');
+ // Find BYOND cache folders
+ const cacheDirs = [
+ // Windows 10
+ ...(await resolvePath(os.homedir(), '*', CACHE_PATTERN)),
+ // Standard Wine setup
+ ...(await resolvePath(os.homedir(),
+ '.wine/drive_c/users/*/*',
+ CACHE_PATTERN)),
+ // Standard Lutris setup
+ ...(await resolvePath(os.homedir(),
+ 'Games/byond/drive_c/users/*/*',
+ CACHE_PATTERN)),
+ ];
+ if (cacheDirs.length === 0) {
+ logger.log('found no cache directories');
+ return;
+ }
+ // Clear garbage
+ for (let cacheDir of cacheDirs) {
+ const garbage = await resolvePath(cacheDir, './*.+(bundle|hot-update).*');
+ for (let file of garbage) {
+ await util.promisify(fs.unlink)(file);
+ }
+ }
+ // Copy assets
+ const assets = await resolvePath(bundleDir, './*.+(bundle|hot-update).*');
+ for (let cacheDir of cacheDirs) {
+ for (let asset of assets) {
+ const destination = path.resolve(cacheDir, path.basename(asset));
+ await util.promisify(fs.copyFile)(asset, destination);
+ }
+ logger.log(`copied ${assets.length} files to '${cacheDir}'`);
+ }
+};
+
+setupServer();
diff --git a/tgui-next/packages/tgui-dev-server/link/client.js b/tgui-next/packages/tgui-dev-server/link/client.js
new file mode 100644
index 00000000000..dfaebba4181
--- /dev/null
+++ b/tgui-next/packages/tgui-dev-server/link/client.js
@@ -0,0 +1,108 @@
+let socket;
+const queue = [];
+const subscribers = [];
+
+const ensureConnection = () => {
+ if (process.env.NODE_ENV !== 'production') {
+ if (!window.WebSocket) {
+ return;
+ }
+ if (!socket || socket.readyState === WebSocket.CLOSED) {
+ socket = new WebSocket('ws://127.0.0.1:3000');
+ socket.onopen = () => {
+ // Empty the message queue
+ while (queue.length !== 0) {
+ const msg = queue.pop();
+ socket.send(msg);
+ }
+ };
+ socket.onmessage = event => {
+ const msg = JSON.parse(event.data);
+ for (let subscriber of subscribers) {
+ subscriber(msg);
+ }
+ };
+ }
+ }
+};
+
+if (process.env.NODE_ENV !== 'production') {
+ window.onunload = () => socket && socket.close();
+}
+
+const subscribe = fn => subscribers.push(fn);
+
+const sendRawMessage = msg => {
+ if (process.env.NODE_ENV !== 'production') {
+ const json = JSON.stringify(msg);
+ // Send message using WebSocket
+ if (window.WebSocket) {
+ ensureConnection();
+ if (socket.readyState === WebSocket.OPEN) {
+ socket.send(json);
+ }
+ else {
+ // Keep only 10 latest messages in the queue
+ if (queue.length > 10) {
+ queue.shift();
+ }
+ queue.push(json);
+ }
+ }
+ // Send message using plain HTTP request.
+ else {
+ const req = new XMLHttpRequest();
+ req.open('POST', 'http://127.0.0.1:3001', true);
+ req.send(json);
+ }
+ }
+};
+
+export const sendLogEntry = (ns, ...args) => {
+ if (process.env.NODE_ENV !== 'production') {
+ try {
+ sendRawMessage({
+ type: 'log',
+ payload: {
+ ns: ns || 'client',
+ args,
+ },
+ });
+ }
+ catch (err) {}
+ }
+};
+
+export const setupHotReloading = () => {
+ if (process.env.NODE_ENV !== 'production'
+ && process.env.WEBPACK_HMR_ENABLED
+ && window.WebSocket) {
+ if (module.hot) {
+ ensureConnection();
+ sendLogEntry(null, 'setting up hot reloading');
+ subscribe(msg => {
+ const { type } = msg;
+ sendLogEntry(null, 'received', type);
+ if (type === 'hotUpdate') {
+ const status = module.hot.status();
+ if (status !== 'idle') {
+ sendLogEntry(null, 'hot reload status:', status);
+ return;
+ }
+ module.hot
+ .check({
+ ignoreUnaccepted: true,
+ ignoreDeclined: true,
+ ignoreErrored: true,
+ })
+ // .then(modules => {
+ // sendLogEntry(null, 'outdated modules', modules);
+ // })
+ .catch(err => {
+ sendLogEntry(null, 'reload error', err);
+ });
+ }
+ });
+ }
+ }
+};
diff --git a/tgui-next/packages/tgui-dev-server/link/server.js b/tgui-next/packages/tgui-dev-server/link/server.js
new file mode 100644
index 00000000000..fae417d1e07
--- /dev/null
+++ b/tgui-next/packages/tgui-dev-server/link/server.js
@@ -0,0 +1,84 @@
+import { createLogger, directLog } from 'common/logging.js';
+import http from 'http';
+import WebSocket from 'ws';
+
+const logger = createLogger('link');
+
+export const setupLink = () => {
+ logger.log('setting up');
+ const wss = setupWebSocketLink();
+ setupSimpleLink();
+ return {
+ wss,
+ };
+};
+
+export const broadcastMessage = (link, msg) => {
+ const { wss } = link;
+ const clients = [...wss.clients];
+ logger.log(`broadcasting ${msg.type} to ${clients.length} clients`);
+ for (let client of clients) {
+ const json = JSON.stringify(msg);
+ client.send(json);
+ }
+};
+
+const handleLinkMessage = msg => {
+ const { type, payload } = msg;
+
+ if (type === 'log') {
+ const { ns, args } = payload;
+ directLog(ns, ...args);
+ return;
+ }
+
+ logger.log('unhandled message', msg);
+};
+
+// WebSocket-based client link
+const setupWebSocketLink = () => {
+ const logger = createLogger('link');
+ const port = 3000;
+ const wss = new WebSocket.Server({ port });
+
+ wss.on('connection', ws => {
+ logger.log('client connected');
+
+ ws.on('message', json => {
+ const msg = JSON.parse(json);
+ handleLinkMessage(msg);
+ });
+
+ ws.on('close', () => {
+ logger.log('client disconnected');
+ });
+ });
+
+ logger.log(`listening on port ${port} (WebSocket)`);
+ return wss;
+};
+
+// One way HTTP-based client link for IE8
+const setupSimpleLink = () => {
+ const logger = createLogger('link');
+ const port = 3001;
+
+ const server = http.createServer((req, res) => {
+ if (req.method === 'POST') {
+ let body = '';
+ req.on('data', chunk => {
+ body += chunk.toString();
+ });
+ req.on('end', () => {
+ const msg = JSON.parse(body);
+ handleLinkMessage(msg);
+ res.end();
+ });
+ return;
+ }
+ res.end();
+ });
+
+ server.listen(port);
+ logger.log(`listening on port ${port} (HTTP)`);
+};
diff --git a/tgui-next/packages/tgui-dev-server/package.json b/tgui-next/packages/tgui-dev-server/package.json
new file mode 100644
index 00000000000..645adadb719
--- /dev/null
+++ b/tgui-next/packages/tgui-dev-server/package.json
@@ -0,0 +1,10 @@
+{
+ "private": true,
+ "name": "tgui-dev-server",
+ "version": "0.1.0",
+ "type": "module",
+ "dependencies": {
+ "glob": "^7.1.4",
+ "ws": "^7.1.2"
+ }
+}
diff --git a/tgui-next/packages/tgui/backend.js b/tgui-next/packages/tgui/backend.js
new file mode 100644
index 00000000000..3098774c581
--- /dev/null
+++ b/tgui-next/packages/tgui/backend.js
@@ -0,0 +1,45 @@
+import { UI_DISABLED, UI_INTERACTIVE } from './constants';
+import { tridentVersion } from './byond';
+
+/**
+ * This file provides a clear separation layer between backend updates
+ * and what state our React app sees.
+ *
+ * Sometimes backend can response without a "data" field, but our final
+ * state will still contain previous "data" because we are merging
+ * the response with already existing state.
+ */
+
+/**
+ * Creates a backend update action.
+ */
+export const backendUpdate = state => ({
+ type: 'backendUpdate',
+ payload: state,
+});
+
+/**
+ * Precisely defines state changes.
+ */
+export const backendReducer = (state, action) => {
+ const { type, payload } = action;
+
+ if (type === 'backendUpdate') {
+ // Calculate our own fields
+ const visible = payload.config.status !== UI_DISABLED;
+ const interactive = payload.config.status === UI_INTERACTIVE;
+ // Override fancy setting for IE8
+ if (tridentVersion <= 4) {
+ payload.config.fancy = 0;
+ }
+ // Merge new payload
+ return {
+ ...state,
+ ...payload,
+ visible,
+ interactive,
+ };
+ }
+
+ return state;
+};
diff --git a/tgui-next/packages/tgui/byond.js b/tgui-next/packages/tgui/byond.js
new file mode 100644
index 00000000000..2b7d3ff7720
--- /dev/null
+++ b/tgui-next/packages/tgui/byond.js
@@ -0,0 +1,84 @@
+import { buildQueryString } from 'common/string';
+
+/**
+ * Version of Trident engine used in Internet Explorer.
+ *
+ * - IE 8 - Trident 4.0
+ * - IE 11 - Trident 7.0
+ *
+ * @return An integer number or 'null' if this is not a trident engine.
+ */
+export const tridentVersion = (() => {
+ const { userAgent } = navigator;
+ const groups = userAgent.match(/Trident\/(\d+).+?;/i);
+ const majorVersion = groups[1];
+ if (!majorVersion) {
+ return null;
+ }
+ return parseInt(majorVersion, 10);
+})();
+
+/**
+ * Helper to generate a BYOND href given 'params' as an object
+ * (with an optional 'url' for eg winset).
+ */
+const href = (url, params = {}) => {
+ return 'byond://' + url + '?' + buildQueryString(params);
+};
+
+export const callByond = (url, params = {}) => {
+ window.location.href = href(url, params);
+};
+
+/**
+ * A high-level abstraction of BYJAX. Makes a call to BYOND and returns
+ * a promise, which (if endpoint has a callback parameter) resolves
+ * with the return value of that call.
+ */
+export const callByondAsync = (url, params = {}) => {
+ // Create a callback array if it doesn't exist yet
+ window.__callbacks__ = window.__callbacks__ || [];
+ // Create a Promise and push its resolve function into callback array
+ const callbackIndex = window.__callbacks__.length;
+ const promise = new Promise(resolve => {
+ // TODO: Fix a potential memory leak
+ window.__callbacks__.push(resolve);
+ });
+ // Call BYOND client
+ window.location.href = href(url, {
+ ...params,
+ callback: `__callbacks__[${callbackIndex}]`,
+ });
+ return promise;
+};
+
+/**
+ * Literally types a command on the client.
+ */
+export const runCommand = command => callByond('winset', { command });
+
+/**
+ * Helper to make a BYOND ui_act() call on the UI 'src' given an 'action'
+ * and optional 'params'.
+ */
+export const act = (src, action, params = {}) => {
+ return callByond('', { src, action, ...params });
+};
+
+/**
+ * Calls 'winget' on window, retrieving value by the 'key'.
+ */
+export const winget = async (win, key) => {
+ const obj = await callByondAsync('winget', {
+ id: win,
+ property: key,
+ });
+ return obj[key];
+};
+
+/**
+ * Calls 'winset' on window, setting 'key' to 'value'.
+ */
+export const winset = (win, key, value) => callByond('winset', {
+ [`${win}.${key}`]: value,
+});
diff --git a/tgui-next/packages/tgui/components/AnimatedNumber.js b/tgui-next/packages/tgui/components/AnimatedNumber.js
new file mode 100644
index 00000000000..884deb38c96
--- /dev/null
+++ b/tgui-next/packages/tgui/components/AnimatedNumber.js
@@ -0,0 +1,69 @@
+import { clamp, toFixed } from 'common/math';
+import { Component } from 'inferno';
+
+const FPS = 20;
+const Q = 0.5;
+
+const isSafeNumber = value => {
+ return typeof value === 'number'
+ && Number.isFinite(value)
+ && !Number.isNaN(value);
+};
+
+export class AnimatedNumber extends Component {
+ constructor(props) {
+ super(props);
+ this.timer = null;
+ this.state = {
+ value: 0,
+ };
+ // Use provided initial state
+ if (isSafeNumber(props.initial)) {
+ this.state.value = props.initial;
+ }
+ // Set initial state with value provided in props
+ else if (isSafeNumber(props.value)) {
+ this.state.value = Number(props.value);
+ }
+ }
+
+ tick() {
+ const { props, state } = this;
+ const currentValue = Number(state.value);
+ const targetValue = Number(props.value);
+ // Avoid poisoning our state with infinities and NaN
+ if (!isSafeNumber(targetValue)) {
+ return;
+ }
+ // Smooth the value using an exponential moving average
+ const value = currentValue * Q + targetValue * (1 - Q);
+ this.setState({ value });
+ }
+
+ componentDidMount() {
+ this.timer = setInterval(() => this.tick(), 1000 / FPS);
+ }
+
+ componentWillUnmount() {
+ clearTimeout(this.timer);
+ }
+
+ render() {
+ const { props, state } = this;
+ const { format } = props;
+ const currentValue = state.value;
+ const targetValue = props.value;
+ // Directly display values which can't be animated
+ if (!isSafeNumber(targetValue)) {
+ return targetValue || null;
+ }
+ // Use custom formatter
+ if (format) {
+ return format(currentValue);
+ }
+ // Fix our animated precision at target value's precision.
+ const fraction = String(targetValue).split('.')[1];
+ const precision = fraction ? fraction.length : 0;
+ return toFixed(currentValue, clamp(precision, 0, 8));
+ }
+}
diff --git a/tgui-next/packages/tgui/components/Box.js b/tgui-next/packages/tgui/components/Box.js
new file mode 100644
index 00000000000..1ee0fc73cf0
--- /dev/null
+++ b/tgui-next/packages/tgui/components/Box.js
@@ -0,0 +1,101 @@
+import { classes, pureComponentHooks } from 'common/react';
+import { createVNode } from 'inferno';
+import { ChildFlags, VNodeFlags } from 'inferno-vnode-flags';
+
+const REM_PX = 12;
+const REM_PER_INTEGER = 0.5;
+
+/**
+ * Coverts our rem-like spacing unit into a CSS unit.
+ */
+export const unit = value => {
+ if (typeof value === 'string') {
+ return value;
+ }
+ if (typeof value === 'number') {
+ return (value * REM_PX * REM_PER_INTEGER) + 'px';
+ }
+};
+
+/**
+ * Nullish coalesce function
+ */
+const firstDefined = (...args) => {
+ return args.find(arg => arg !== undefined && arg !== null);
+};
+
+export const computeBoxProps = props => {
+ const {
+ className,
+ color,
+ width,
+ minWidth,
+ maxWidth,
+ height,
+ minHeight,
+ maxHeight,
+ lineHeight,
+ inline,
+ m, mx, my, mt, mb, ml, mr,
+ opacity,
+ bold,
+ italic,
+ textAlign,
+ position,
+ top,
+ left,
+ right,
+ bottom,
+ ...rest
+ } = props;
+ return {
+ ...rest,
+ className: classes([
+ className,
+ color && 'color-' + color,
+ ]),
+ style: {
+ 'display': inline ? 'inline-block' : undefined,
+ 'margin-top': unit(firstDefined(mt, my, m)),
+ 'margin-bottom': unit(firstDefined(mb, my, m)),
+ 'margin-left': unit(firstDefined(ml, mx, m)),
+ 'margin-right': unit(firstDefined(mr, mx, m)),
+ 'opacity': opacity,
+ 'width': unit(width),
+ 'min-width': unit(minWidth),
+ 'max-width': unit(maxWidth),
+ 'height': unit(height),
+ 'min-height': unit(minHeight),
+ 'max-height': unit(maxHeight),
+ 'line-height': unit(lineHeight),
+ 'font-weight': bold ? 'bold' : undefined,
+ 'font-style': italic ? 'italic' : undefined,
+ 'text-align': textAlign,
+ 'position': position,
+ 'top': unit(top),
+ 'left': unit(left),
+ 'right': unit(right),
+ 'bottom': unit(bottom),
+ ...rest.style,
+ },
+ };
+};
+
+export const Box = props => {
+ const { as = 'div', content, children, ...rest } = props;
+ // Render props
+ if (typeof children === 'function') {
+ return children(computeBoxProps(props));
+ }
+ const { className, ...computedProps } = computeBoxProps(rest);
+ // Render a wrapper element
+ return createVNode(
+ VNodeFlags.HtmlElement,
+ as,
+ className,
+ content || children,
+ ChildFlags.UnknownChildren,
+ computedProps);
+};
+
+Box.defaultHooks = pureComponentHooks;
diff --git a/tgui-next/packages/tgui/components/Button.js b/tgui-next/packages/tgui/components/Button.js
new file mode 100644
index 00000000000..12ca4cd6a5d
--- /dev/null
+++ b/tgui-next/packages/tgui/components/Button.js
@@ -0,0 +1,72 @@
+import { classes, pureComponentHooks } from 'common/react';
+import { Box } from './Box';
+import { Icon } from './Icon';
+import { Tooltip } from './Tooltip';
+
+export const BUTTON_ACTIVATION_KEYCODES = [
+ 13, // Enter
+ 32, // Space
+];
+
+export const Button = props => {
+ const {
+ className,
+ fluid,
+ icon,
+ color,
+ disabled,
+ selected,
+ tooltip,
+ tooltipPosition,
+ content,
+ children,
+ onClick,
+ ...rest
+ } = props;
+ const hasContent = !!(content || children);
+ // NOTE: Lowercase "onclick" and unselectable is used for
+ // compatibility with IE8. Do not change it!
+ return (
+ {
+ if (disabled || !onClick) {
+ return;
+ }
+ onClick(e);
+ }}
+ onKeyPress={e => {
+ const keyCode = window.event ? e.which : e.keyCode;
+ if (BUTTON_ACTIVATION_KEYCODES.includes(keyCode)) {
+ e.preventDefault();
+ onClick(e);
+ }
+ }}
+ {...rest}>
+ {icon && (
+
+ )}
+ {content}
+ {children}
+ {tooltip && (
+
+ )}
+
+ );
+};
+
+Button.defaultHooks = pureComponentHooks;
diff --git a/tgui-next/packages/tgui/components/Button.scss b/tgui-next/packages/tgui/components/Button.scss
new file mode 100644
index 00000000000..62ce78e4d53
--- /dev/null
+++ b/tgui-next/packages/tgui/components/Button.scss
@@ -0,0 +1,95 @@
+@mixin button-color($color) {
+ transition: color, background-color 50ms;
+ background-color: $color;
+
+ // Adapt button color to background luminance to ensure high contast
+ @if luminance($color) > 0.4 {
+ color: rgba(0, 0, 0, 1);
+ }
+ @else {
+ color: rgba(255, 255, 255, 1);
+ }
+
+ &:hover {
+ transition: color, background-color 0ms;
+ }
+
+ &:focus {
+ transition: color, background-color 100ms;
+ }
+
+ &:hover,
+ &:focus {
+ background-color: lighten($color, $button-lighten-hover);
+ @if luminance($color) > 0.4 {
+ color: rgba(0, 0, 0, 1);
+ }
+ @else {
+ color: rgba(255, 255, 255, 1);
+ }
+ }
+}
+
+.Button {
+ position: relative;
+ display: inline-block;
+ line-height: 19px;
+ padding: 0 6px;
+ margin-right: 2px;
+ white-space: nowrap;
+ outline: 0;
+ margin-bottom: 2px;
+ // Disable selection in buttons
+ user-select: none;
+ -ms-user-select: none;
+
+ &:last-child {
+ margin-right: 0;
+ }
+}
+
+.Button--hasContent {
+ // Add a margin to the icon to keep it separate from the text
+ .fa, .fas, .far {
+ margin-right: 6px;
+ }
+}
+
+.Button--fluid {
+ display: block;
+ margin-left: 0;
+ margin-right: 0;
+ // padding: 3px 6px;
+}
+
+@each $color-name, $color-value in $color-map {
+ .Button--color--#{$color-name} {
+ @include button-color($color-value);
+ }
+}
+
+.Button--color--normal {
+ @include button-color($button-color-normal);
+}
+
+.Button--color--caution {
+ @include button-color($button-color-caution);
+}
+
+.Button--color--danger {
+ @include button-color($button-color-danger);
+}
+
+.Button--color--transparent {
+ @include button-color($dark-gray);
+ background-color: rgba($dark-gray, 0);
+ color: rgba(255, 255, 255, 0.5);
+}
+
+.Button--disabled {
+ background-color: $button-color-disabled !important;
+}
+
+.Button--selected {
+ @include button-color($button-color-selected);
+}
diff --git a/tgui-next/packages/tgui/components/Flex.js b/tgui-next/packages/tgui/components/Flex.js
new file mode 100644
index 00000000000..1146d993f69
--- /dev/null
+++ b/tgui-next/packages/tgui/components/Flex.js
@@ -0,0 +1,58 @@
+import { classes, pureComponentHooks } from 'common/react';
+import { Box } from './Box';
+
+export const computeFlexProps = props => {
+ const {
+ className,
+ direction,
+ wrap,
+ align,
+ justify,
+ ...rest
+ } = props;
+ return {
+ className: classes('Flex', className),
+ style: {
+ ...rest.style,
+ 'flex-direction': direction,
+ 'flex-wrap': wrap,
+ 'align-items': align,
+ 'justify-content': justify,
+ },
+ ...rest,
+ };
+};
+
+export const Flex = props => (
+
+);
+
+Flex.defaultHooks = pureComponentHooks;
+
+export const computeFlexItemProps = props => {
+ const {
+ className,
+ grow,
+ order,
+ align,
+ ...rest
+ } = props;
+ return {
+ className: classes('Flex__item', className),
+ style: {
+ ...rest.style,
+ 'flex-grow': grow,
+ 'order': order,
+ 'align-self': align,
+ },
+ ...rest,
+ };
+};
+
+export const FlexItem = props => (
+
+);
+
+FlexItem.defaultHooks = pureComponentHooks;
+
+Flex.Item = FlexItem;
diff --git a/tgui-next/packages/tgui/components/Flex.scss b/tgui-next/packages/tgui/components/Flex.scss
new file mode 100644
index 00000000000..79d4c8b4b6e
--- /dev/null
+++ b/tgui-next/packages/tgui/components/Flex.scss
@@ -0,0 +1,4 @@
+.Flex {
+ display: -ms-flexbox;
+ display: flex;
+}
diff --git a/tgui-next/packages/tgui/components/Icon.js b/tgui-next/packages/tgui/components/Icon.js
new file mode 100644
index 00000000000..6e7188bf188
--- /dev/null
+++ b/tgui-next/packages/tgui/components/Icon.js
@@ -0,0 +1,26 @@
+import { classes, pureComponentHooks } from 'common/react';
+import { Box } from './Box';
+
+const FA_OUTLINE_REGEX = /-o$/;
+
+export const Icon = props => {
+ const { name, size, className, style = {}, ...rest } = props;
+ if (size) {
+ style['font-size'] = (size * 100) + '%';
+ }
+ const faRegular = FA_OUTLINE_REGEX.test(name);
+ const faName = name.replace(FA_OUTLINE_REGEX, '');
+ return (
+
+ );
+};
+
+Icon.defaultHooks = pureComponentHooks;
diff --git a/tgui-next/packages/tgui/components/LabeledList.js b/tgui-next/packages/tgui/components/LabeledList.js
new file mode 100644
index 00000000000..d8db6bb9c16
--- /dev/null
+++ b/tgui-next/packages/tgui/components/LabeledList.js
@@ -0,0 +1,72 @@
+import { classes, pureComponentHooks } from 'common/react';
+import { unit } from './Box';
+
+export const LabeledList = props => {
+ const { children } = props;
+ return (
+