Splits various massive clockwork cult code files up into various folders (#21177)

* Splits various massive clockwork cult code files up into various folders

* JUST1C4R

* 4BSURD

* this is faintly horrifying to look at

* that's right i don't need to double it, just to swap the order
This commit is contained in:
Joan Lung
2016-10-26 09:50:04 +13:00
committed by oranges
parent d587040256
commit 09b426df79
38 changed files with 3534 additions and 3489 deletions
+18 -15
View File
@@ -17,14 +17,17 @@ Game-wise, clockwork slabs will generate components over time, with more powerfu
This file's folder contains:
clock_cult.dm: Core gamemode files.
clock_items.dm: Items (excluding the proselytizer).
clock_machines.dm: Machinery like the mending motor.
clock_mobs.dm: Hostile and benign clockwork creatures.
clock_proselytizer: The clockwork proselytizer and all of its special interactions.
clock_ratvar.dm: The Ark of the Clockwork Justiciar and Ratvar himself. Important enough to have his own file.
clock_scripture.dm: Scripture and rites.
clock_structures.dm: Structures and effects
clock_unsorted.dm: Anything else with no place to be
clock_effect.dm: The base clockwork effect code.
- Effect files are in game/gamemodes/clock_cult/clock_effects/
clock_item.dm: The base clockwork item code.
- Item files are in game/gamemodes/clock_cult/clock_items/
clock_mobs.dm: Hostile clockwork creatures.
clock_scripture.dm: The base Scripture code.
- Scripture files are in game/gamemodes/clock_cult/clock_scripture/
clock_structure.dm: The base clockwork structure code, including clockwork machines.
- Structure files, and Ratvar, are in game/gamemodes/clock_cult/clock_structures/
game/gamemodes/clock_cult/clock_helpers/ contains several helper procs, including the Ratvarian language.
clockcult defines are in __DEFINES/clockcult.dm
@@ -47,19 +50,19 @@ Credit where due:
/proc/is_eligible_servant(mob/living/M)
if(!istype(M))
return 0
return FALSE
if(M.mind)
if(ishuman(M) && (M.mind.assigned_role in list("Captain", "Chaplain")))
return 0
return FALSE
if(M.mind.enslaved_to && !is_servant_of_ratvar(M.mind.enslaved_to))
return 0
return FALSE
else
return 0
return FALSE
if(iscultist(M) || isconstruct(M) || M.isloyal())
return 0
return FALSE
if(ishuman(M) || isbrain(M) || isguardian(M) || issilicon(M) || isclockmob(M) || istype(M, /mob/living/simple_animal/drone/cogscarab))
return 1
return 0
return TRUE
return FALSE
/proc/add_servant_of_ratvar(mob/living/L, silent = FALSE)
var/update_type = /datum/antagonist/clockcultist
@@ -0,0 +1,25 @@
//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 = 1
density = 0
opacity = 0
resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | UNACIDABLE | ACID_PROOF
/obj/effect/clockwork/New()
..()
all_clockwork_objects += src
/obj/effect/clockwork/Destroy()
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)
@@ -0,0 +1,46 @@
//an "overlay" used by clockwork walls and floors to appear normal to mesons.
/obj/effect/clockwork/overlay
mouse_opacity = 0
var/atom/linked
/obj/effect/clockwork/overlay/examine(mob/user)
if(linked)
linked.examine(user)
/obj/effect/clockwork/overlay/ex_act()
return FALSE
/obj/effect/clockwork/overlay/singularity_pull(S, current_size)
return
/obj/effect/clockwork/overlay/Destroy()
if(linked)
linked = null
..()
return QDEL_HINT_PUTINPOOL
/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/New()
..()
queue_smooth_neighbors(src)
addtimer(GLOBAL_PROC, "queue_smooth", 1, FALSE, src)
/obj/effect/clockwork/overlay/wall/Destroy()
queue_smooth_neighbors(src)
..()
return QDEL_HINT_QUEUE
/obj/effect/clockwork/overlay/floor
icon = 'icons/turf/floors.dmi'
icon_state = "clockwork_floor"
layer = TURF_LAYER
/obj/effect/clockwork/overlay/floor/bloodcult //this is used by BLOOD CULT, it shouldn't use such a path...
icon_state = "cult"
@@ -0,0 +1,329 @@
//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/resist_string = "glows blinding white" //string for when a null rod blocks its effects, "glows [resist_string]"
/obj/effect/clockwork/sigil/attackby(obj/item/I, mob/living/user, params)
if(I.force && !is_servant_of_ratvar(user))
user.visible_message("<span class='warning'>[user] scatters [src] with [I]!</span>", "<span class='danger'>You scatter [src] with [I]!</span>")
qdel(src)
return 1
..()
/obj/effect/clockwork/sigil/attack_hand(mob/user)
if(iscarbon(user) && !user.stat && (!is_servant_of_ratvar(user) || (is_servant_of_ratvar(user) && user.a_intent == "harm")))
user.visible_message("<span class='warning'>[user] stamps out [src]!</span>", "<span class='danger'>You stomp on [src], scattering it into thousands of particles.</span>")
qdel(src)
return 1
..()
/obj/effect/clockwork/sigil/ex_act(severity)
visible_message("<span class='warning'>[src] scatters into thousands of particles.</span>")
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) || (is_servant_of_ratvar(L) && affects_servants)) && L.mind)
if(L.null_rod_check())
var/obj/item/I = L.null_rod_check()
L.visible_message("<span class='warning'>[L]'s [I.name] [resist_string], protecting them from [src]'s effects!</span>", \
"<span class='userdanger'>Your [I.name] [resist_string], protecting you!</span>")
return
sigil_effects(L)
return 1
/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 stun
/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 first non-servant to cross it. Nar-Sie's dogs will be knocked down."
icon_state = "sigildull"
color = "#FAE48C"
/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))
L << "<span class='heavy_brass'>\"Watch your step, wretch.\"</span>"
L.adjustBruteLoss(10)
L.Weaken(7)
L.visible_message("<span class='warning'>[src] appears around [L] in a burst of light!</span>", \
"<span class='userdanger'>[target_flashed ? "An unseen force":"The glowing sigil around you"] holds you in place!</span>")
L.Stun(5)
PoolOrNew(/obj/effect/overlay/temp/ratvar/sigil/transgression, get_turf(src))
qdel(src)
return 1
//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 the first person to cross it, provided they remain on it for seven seconds."
icon_state = "sigilsubmission"
color = "#FAE48C"
alpha = 125
stat_affected = UNCONSCIOUS
resist_string = "glows faintly yellow"
var/convert_time = 70
var/glow_light = 2 //soft light
var/glow_falloff = 1
var/delete_on_finish = TRUE
var/sigil_name = "Sigil of Submission"
var/glow_type
/obj/effect/clockwork/sigil/submission/New()
..()
SetLuminosity(glow_light,glow_falloff)
/obj/effect/clockwork/sigil/submission/proc/post_channel(mob/living/L)
/obj/effect/clockwork/sigil/submission/sigil_effects(mob/living/L)
L.visible_message("<span class='warning'>[src] begins to glow a piercing magenta!</span>", "<span class='sevtug'>You feel something start to invade your mind...</span>")
animate(src, color = "#AF0AAF", time = convert_time)
var/obj/effect/overlay/temp/ratvar/sigil/glow
if(glow_type)
glow = PoolOrNew(glow_type, get_turf(src))
animate(glow, alpha = 255, time = convert_time)
var/I = 0
while(I < convert_time && get_turf(L) == get_turf(src))
I++
sleep(1)
if(get_turf(L) != get_turf(src))
if(glow)
qdel(glow)
animate(src, color = initial(color), time = 20)
visible_message("<span class='warning'>[src] slowly stops glowing!</span>")
return 0
post_channel(L)
if(is_eligible_servant(L))
L << "<span class='heavy_brass'>\"You belong to me now.\"</span>"
add_servant_of_ratvar(L)
L.Weaken(3) //Completely defenseless for about five seconds - mainly to give them time to read over the information they've just been presented with
L.Stun(3)
if(iscarbon(L))
var/mob/living/carbon/C = L
C.silent += 5
var/message = "[sigil_name] in [get_area(src)] <span class='sevtug'>[is_servant_of_ratvar(L) ? "successfully converted" : "failed to convert"]</span>"
for(var/M in mob_list)
if(isobserver(M))
var/link = FOLLOW_LINK(M, L)
M << "[link] <span class='heavy_brass'>[message] [L.real_name]!</span>"
else if(is_servant_of_ratvar(M))
if(M == L)
M << "<span class='heavy_brass'>[message] you!</span>"
else
M << "<span class='heavy_brass'>[message] [L.real_name]!</span>"
if(delete_on_finish)
qdel(src)
else
animate(src, color = initial(color), time = 20)
visible_message("<span class='warning'>[src] slowly stops glowing!</span>")
return 1
//Sigil of Accession: After a short time, converts any non-servant standing on it though implants. Knocks down and silences them for five seconds afterwards.
/obj/effect/clockwork/sigil/submission/accession
name = "terrifying sigil"
desc = "A luminous brassy sigil. Something about it makes you want to flee."
clockwork_desc = "A sigil that will enslave any person who crosses it, provided they remain on it for seven seconds. \n\
It can convert a mindshielded target once before disppearing, but can convert any number of non-implanted targets."
icon_state = "sigiltransgression"
color = "#A97F1B"
alpha = 200
glow_light = 4 //bright light
glow_falloff = 3
delete_on_finish = FALSE
sigil_name = "Sigil of Accession"
glow_type = /obj/effect/overlay/temp/ratvar/sigil/accession
resist_string = "glows bright orange"
/obj/effect/clockwork/sigil/submission/accession/post_channel(mob/living/L)
if(L.isloyal())
var/mob/living/carbon/C = L
delete_on_finish = TRUE
C.visible_message("<span class='warning'>[C] visibly trembles!</span>", \
"<span class='sevtug'>[text2ratvar("You will be mine and his. This puny trinket will not stop me.")]</span>")
for(var/obj/item/weapon/implant/mindshield/M in C.implants)
qdel(M)
//Sigil of Transmission: Stores power for clockwork machinery, serving as a battery.
/obj/effect/clockwork/sigil/transmission
name = "suspicious sigil"
desc = "A glowing orange sigil. The air around it feels staticky."
clockwork_desc = "A sigil that will serve as a battery for clockwork structures. Use Volt Void while standing on it to charge it."
icon_state = "sigiltransmission"
color = "#EC8A2D"
alpha = 50
resist_string = "glows faintly"
var/power_charge = REPLICANT_ALLOY_POWER //starts with REPLICANT_ALLOY_POWER by default
/obj/effect/clockwork/sigil/transmission/ex_act(severity)
if(severity == 3)
modify_charge(-500)
visible_message("<span class='warning'>[src] flares a brilliant orange!</span>")
else
..()
/obj/effect/clockwork/sigil/transmission/examine(mob/user)
..()
if(is_servant_of_ratvar(user) || isobserver(user))
user << "<span class='[power_charge ? "brass":"alloy"]'>It is storing <b>[power_charge]W</b> of power.</span>"
/obj/effect/clockwork/sigil/transmission/sigil_effects(mob/living/L)
if(power_charge)
L << "<span class='brass'>You feel a slight, static shock.</span>"
return 1
/obj/effect/clockwork/sigil/transmission/New()
..()
alpha = min(initial(alpha) + power_charge*0.02, 255)
/obj/effect/clockwork/sigil/transmission/proc/modify_charge(amount)
if(power_charge - amount < 0)
return 0
power_charge -= amount
alpha = min(initial(alpha) + power_charge*0.02, 255)
return 1
//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"
color = "#123456"
alpha = 75
affects_servants = TRUE
stat_affected = DEAD
resist_string = "glows shimmering yellow"
var/vitality = 0
var/base_revive_cost = 20
var/sigil_active = FALSE
var/animation_number = 3 //each cycle increments this by 1, at 4 it produces an animation and resets
/obj/effect/clockwork/sigil/vitality/examine(mob/user)
..()
if(is_servant_of_ratvar(user) || isobserver(user))
user << "<span class='[vitality ? "inathneq_small":"alloy"]'>It is storing <b>[ratvar_awakens ? "INFINITE":"[vitality]"]</b> units of vitality.</span>"
user << "<span class='inathneq_small'>It requires at least <b>[base_revive_cost]</b> units of vitality to revive dead servants, in addition to any damage the servant has.</span>"
/obj/effect/clockwork/sigil/vitality/sigil_effects(mob/living/L)
if((is_servant_of_ratvar(L) && L.suiciding) || sigil_active)
return 0
visible_message("<span class='warning'>[src] begins to glow bright blue!</span>")
animate(src, alpha = 255, time = 10)
sleep(10)
sigil_active = TRUE
//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
while(L && (!is_servant_of_ratvar(L) || (is_servant_of_ratvar(L) && vitality)) && get_turf(L) == get_turf(src))
if(animation_number >= 4)
PoolOrNew(/obj/effect/overlay/temp/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)
vitality_drained = L.maxHealth
var/obj/effect/overlay/temp/ratvar/sigil/vitality/V = PoolOrNew(/obj/effect/overlay/temp/ratvar/sigil/vitality, get_turf(src))
animate(V, alpha = 0, transform = matrix()*2, time = 8)
playsound(L, 'sound/magic/WandODeath.ogg', 50, 1)
L.visible_message("<span class='warning'>[L] collapses in on [L.p_them()]self as [src] flares bright blue!</span>")
L << "<span class='inathneq_large'>\"[text2ratvar("Your life will not be wasted.")]\"</span>"
for(var/obj/item/W in L)
if(!L.unEquip(W))
qdel(W)
L.dust()
else
vitality_drained = L.adjustToxLoss(1.5)
if(vitality_drained)
vitality += vitality_drained
else
break
else
var/clone_to_heal = L.getCloneLoss()
var/tox_to_heal = L.getToxLoss()
var/burn_to_heal = L.getFireLoss()
var/brute_to_heal = L.getBruteLoss()
var/oxy_to_heal = L.getOxyLoss()
var/total_damage = clone_to_heal + tox_to_heal + burn_to_heal + brute_to_heal + oxy_to_heal
if(L.stat == DEAD)
var/revival_cost = base_revive_cost + total_damage - oxy_to_heal //ignores oxygen damage
if(ratvar_awakens)
revival_cost = 0
var/mob/dead/observer/ghost = L.get_ghost(TRUE)
if(ghost)
if(vitality >= revival_cost)
ghost.reenter_corpse()
L.revive(1, 1)
playsound(L, 'sound/magic/Staff_Healing.ogg', 50, 1)
L.visible_message("<span class='warning'>[L] suddenly gets back up, [L.p_their()] mouth dripping blue ichor!</span>", \
"<span class='inathneq'>\"[text2ratvar("You will be okay, child.")]\"</span>")
vitality -= revival_cost
break
else
break
if(!total_damage)
break
var/vitality_for_cycle = min(vitality, 3)
var/vitality_used = 0
if(ratvar_awakens)
vitality_for_cycle = 3
if(clone_to_heal && vitality_for_cycle)
var/healing = min(vitality_for_cycle, clone_to_heal)
vitality_for_cycle -= healing
L.adjustCloneLoss(-healing)
vitality_used += healing
if(tox_to_heal && vitality_for_cycle)
var/healing = min(vitality_for_cycle, tox_to_heal)
vitality_for_cycle -= healing
L.adjustToxLoss(-healing)
vitality_used += healing
if(burn_to_heal && vitality_for_cycle)
var/healing = min(vitality_for_cycle, burn_to_heal)
vitality_for_cycle -= healing
L.adjustFireLoss(-healing)
vitality_used += healing
if(brute_to_heal && vitality_for_cycle)
var/healing = min(vitality_for_cycle, brute_to_heal)
vitality_for_cycle -= healing
L.adjustBruteLoss(-healing)
vitality_used += healing
if(oxy_to_heal && vitality_for_cycle)
var/healing = min(vitality_for_cycle, oxy_to_heal)
vitality_for_cycle -= healing
L.adjustOxyLoss(-healing)
vitality_used += healing
if(!ratvar_awakens)
vitality -= vitality_used
sleep(2)
animation_number = initial(animation_number)
sigil_active = FALSE
animate(src, alpha = initial(alpha), time = 20)
visible_message("<span class='warning'>[src] slowly stops glowing!</span>")
@@ -0,0 +1,57 @@
//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/New()
..()
animate(src, alpha = 0, time = 10)
QDEL_IN(src, 10)
/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/187x381.dmi'
icon_state = "inath-neq"
pixel_x = -77
pixel_y = -174
/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/340x428.dmi'
icon_state = "nezbere"
pixel_x = -154
pixel_y = -198
/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/211x247.dmi'
icon_state = "sevtug"
pixel_x = -89
pixel_y = -107
/obj/effect/clockwork/general_marker/nzcrentr
name = "Nzcrentr, the Eternal Thunderbolt"
desc = "A terrifying spiked construct crackling with limitless energy."
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/254x361.dmi'
icon_state = "nzcrentr"
pixel_x = -111
pixel_y = -164
@@ -0,0 +1,186 @@
//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 = 1
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
/obj/effect/clockwork/spatial_gateway/New()
..()
addtimer(src, "check_setup", 1)
/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."
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))
user << "<span class='brass'>It has [uses] uses remaining.</span>"
/obj/effect/clockwork/spatial_gateway/attack_ghost(mob/user)
if(linked_gateway)
user.forceMove(get_turf(linked_gateway))
..()
/obj/effect/clockwork/spatial_gateway/attack_hand(mob/living/user)
if(!uses)
return FALSE
if(user.pulling && user.a_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("<span class='warning'>[user] shoves [L] into [src]!</span>", "<span class='danger'>You shove [L] into [src]!</span>")
user.stop_pulling()
pass_through_gateway(L)
return TRUE
if(!user.canUseTopic(src))
return FALSE
user.visible_message("<span class='warning'>[user] climbs through [src]!</span>", "<span class='danger'>You brace yourself and step through [src]...</span>")
pass_through_gateway(user)
return TRUE
/obj/effect/clockwork/spatial_gateway/attackby(obj/item/I, mob/living/user, params)
if(istype(I, /obj/item/weapon/nullrod))
user.visible_message("<span class='warning'>[user] dispels [src] with [I]!</span>", "<span class='danger'>You close [src] with [I]!</span>")
qdel(linked_gateway)
qdel(src)
return TRUE
if(istype(I, /obj/item/clockwork/slab))
user << "<span class='heavy_brass'>\"I don't think you want to drop your slab into that\".\n\"If you really want to, try throwing it.\"</span>"
return TRUE
if(user.drop_item() && uses)
user.visible_message("<span class='warning'>[user] drops [I] into [src]!</span>", "<span class='danger'>You drop [I] into [src]!</span>")
pass_through_gateway(I)
return TRUE
return ..()
/obj/effect/clockwork/spatial_gateway/ex_act(severity)
if(severity == 1 && uses)
uses = 0
visible_message("<span class='warning'>[src] is disrupted!</span>")
animate(src, alpha = 0, transform = matrix()*2, time = 10)
QDEL_IN(src, 10)
linked_gateway.uses = 0
linked_gateway.visible_message("<span class='warning'>[linked_gateway] is disrupted!</span>")
animate(linked_gateway, alpha = 0, transform = matrix()*2, time = 10)
QDEL_IN(linked_gateway, 10)
return TRUE
return FALSE
/obj/effect/clockwork/spatial_gateway/Bumped(atom/A)
..()
if(isliving(A) || istype(A, /obj/item))
pass_through_gateway(A)
/obj/effect/clockwork/spatial_gateway/proc/pass_through_gateway(atom/movable/A)
if(!linked_gateway)
qdel(src)
return FALSE
if(!sender)
visible_message("<span class='warning'>[A] bounces off of [src]!</span>")
return FALSE
if(!uses)
return FALSE
if(isliving(A))
var/mob/living/user = A
user << "<span class='warning'><b>You pass through [src] and appear elsewhere!</b></span>"
linked_gateway.visible_message("<span class='warning'>A shape appears in [linked_gateway] before emerging!</span>")
playsound(src, 'sound/effects/EMPulse.ogg', 50, 1)
playsound(linked_gateway, 'sound/effects/EMPulse.ogg', 50, 1)
transform = matrix() * 1.5
animate(src, transform = matrix() / 1.5, time = 10)
linked_gateway.transform = matrix() * 1.5
animate(linked_gateway, transform = matrix() / 1.5, time = 10)
A.forceMove(get_turf(linked_gateway))
uses = max(0, uses - 1)
linked_gateway.uses = max(0, linked_gateway.uses - 1)
addtimer(src, "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()
var/list/duplicatenamecount = list()
for(var/obj/structure/destructible/clockwork/powered/clockwork_obelisk/O in all_clockwork_objects)
if(!O.Adjacent(invoker) && O != src && (O.z <= ZLEVEL_SPACEMAX)) //don't list obelisks that we're next to
var/area/A = get_area(O)
var/locname = initial(A.name)
var/resultkey = "[locname] [O.name]"
if(resultkey in teleportnames) //why the fuck did you put two obelisks in the same area
duplicatenamecount[resultkey]++
resultkey = "[resultkey] ([duplicatenamecount[resultkey]])"
else
teleportnames.Add(resultkey)
duplicatenamecount[resultkey] = 1
possible_targets[resultkey] = O
for(var/mob/living/L in living_mob_list)
if(!L.stat && is_servant_of_ratvar(L) && !L.Adjacent(invoker) && L != invoker && (L.z <= ZLEVEL_SPACEMAX)) //People right next to the invoker can't be portaled to, for obvious reasons
var/resultkey = "[L.name] ([L.real_name])"
if(resultkey in teleportnames)
duplicatenamecount[resultkey]++
resultkey = "[resultkey] ([duplicatenamecount[resultkey]])"
else
teleportnames.Add(resultkey)
duplicatenamecount[resultkey] = 1
possible_targets[resultkey] = L
if(!possible_targets.len)
invoker << "<span class='warning'>There are no other eligible targets for a Spatial Gateway!</span>"
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 || !target || !invoker || !invoker.canUseTopic(src, BE_CLOSE) || !is_servant_of_ratvar(invoker) || (istype(src, /obj/item) && invoker.get_active_held_item() != src))
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
var/istargetobelisk = istype(target, /obj/structure/destructible/clockwork/powered/clockwork_obelisk)
if(istargetobelisk)
gateway_uses *= 2
time_duration *= 2
invoker.visible_message("<span class='warning'>The air in front of [invoker] ripples before suddenly tearing open!</span>", \
"<span class='brass'>With a word, you rip open a [two_way ? "two-way":"one-way"] rift to [input_target_key]. It will last for [time_duration / 10] seconds and has [gateway_uses] use[gateway_uses > 1 ? "s" : ""].</span>")
var/obj/effect/clockwork/spatial_gateway/S1 = new(istype(src, /obj/structure/destructible/clockwork/powered/clockwork_obelisk) ? 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("<span class='warning'>The air in front of [target] ripples before suddenly tearing open!</span>")
return TRUE
@@ -0,0 +1,118 @@
//generates a component in the global component cache, either random based on lowest or a specific component
/proc/generate_cache_component(specific_component_id)
if(specific_component_id)
clockwork_component_cache[specific_component_id]++
else
var/component_to_generate = get_weighted_component_id()
clockwork_component_cache[component_to_generate]++
//returns a chosen component id based on the lowest amount of that component in the global cache, the global cache plus the slab if there are caches, or the slab if there are no caches.
/proc/get_weighted_component_id(obj/item/clockwork/slab/storage_slab)
. = list()
if(storage_slab)
if(clockwork_caches)
for(var/i in clockwork_component_cache)
.[i] = max(MAX_COMPONENTS_BEFORE_RAND - LOWER_PROB_PER_COMPONENT*(clockwork_component_cache[i] + storage_slab.stored_components[i]), 1)
else
for(var/i in clockwork_component_cache)
.[i] = max(MAX_COMPONENTS_BEFORE_RAND - LOWER_PROB_PER_COMPONENT*storage_slab.stored_components[i], 1)
else
for(var/i in clockwork_component_cache)
.[i] = max(MAX_COMPONENTS_BEFORE_RAND - LOWER_PROB_PER_COMPONENT*clockwork_component_cache[i], 1)
. = pickweight(.)
//returns a component name from a component id
/proc/get_component_name(id)
switch(id)
if("belligerent_eye")
return "Belligerent Eye"
if("vanguard_cogwheel")
return "Vanguard Cogwheel"
if("guvax_capacitor")
return "Guvax Capacitor"
if("replicant_alloy")
return "Replicant Alloy"
if("hierophant_ansible")
return "Hierophant Ansible"
else
return null
//returns a component id from a component name
/proc/get_component_id(name)
switch(name)
if("Belligerent Eye")
return "belligerent_eye"
if("Vanguard Cogwheel")
return "vanguard_cogwheel"
if("Guvax Capacitor")
return "guvax_capacitor"
if("Replicant Alloy")
return "replicant_alloy"
if("Hierophant Ansible")
return "hierophant_ansible"
else
return null
//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("guvax_capacitor")
return "sevtug"
if("replicant_alloy")
return "nezbere"
if("hierophant_ansible")
return "nzcrentr"
else
return null
//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("guvax_capacitor")
return "#AF0AAF"
if("replicant_alloy")
return "#42474D"
if("hierophant_ansible")
return "#DAAA18"
else
return "#BE8700"
//returns a type for a floating component animation from a component id
/proc/get_component_animation_type(id)
switch(id)
if("belligerent_eye")
return /obj/effect/overlay/temp/ratvar/component
if("vanguard_cogwheel")
return /obj/effect/overlay/temp/ratvar/component/cogwheel
if("guvax_capacitor")
return /obj/effect/overlay/temp/ratvar/component/capacitor
if("replicant_alloy")
return /obj/effect/overlay/temp/ratvar/component/alloy
if("hierophant_ansible")
return /obj/effect/overlay/temp/ratvar/component/ansible
else
return null
//returns a type for a component from a component id
/proc/get_component_type(id)
switch(id)
if("belligerent_eye")
return /obj/item/clockwork/component/belligerent_eye
if("vanguard_cogwheel")
return /obj/item/clockwork/component/vanguard_cogwheel
if("guvax_capacitor")
return /obj/item/clockwork/component/guvax_capacitor
if("replicant_alloy")
return /obj/item/clockwork/component/replicant_alloy
if("hierophant_ansible")
return /obj/item/clockwork/component/hierophant_ansible
else
return null
@@ -0,0 +1,47 @@
//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 mob_list)
if(!servantsonly && isobserver(M))
if(target)
var/link = FOLLOW_LINK(M, target)
M << "[link] [message]"
else
M << message
else if(is_servant_of_ratvar(M))
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 = "<span class='[name_span]'>[user_title ? "[user_title] ":""][findtextEx(user.name, user.real_name) ? user.name : "[user.real_name] (as [user.name])"]: \
</span><span class='[message_span]'>\"[message]\"</span>"
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."
button_icon_state = "hierophant"
background_icon_state = "bg_clock"
check_flags = AB_CHECK_RESTRAINED|AB_CHECK_STUNNED|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
titled_hierophant_message(owner, input, span_for_name, span_for_message, title)
@@ -1,153 +1,4 @@
/obj/item/clockwork/clockwork_proselytizer //Clockwork proselytizer (yes, that's a real word): Converts applicable objects to Ratvarian variants.
name = "clockwork proselytizer"
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 liquified Replicant Alloy to function."
icon_state = "clockwork_proselytizer"
w_class = 3
force = 5
flags = NOBLUDGEON
var/stored_alloy = 0 //Requires this to function; each chunk of replicant alloy provides REPLICANT_ALLOY_UNIT
var/max_alloy = REPLICANT_ALLOY_UNIT * 10
var/uses_alloy = TRUE
var/metal_to_alloy = FALSE
var/repairing = null //what we're currently repairing, if anything
/obj/item/clockwork/clockwork_proselytizer/preloaded
stored_alloy = REPLICANT_WALL_MINUS_FLOOR+REPLICANT_WALL_TOTAL
/obj/item/clockwork/clockwork_proselytizer/scarab
name = "scarab proselytizer"
clockwork_desc = "A cogscarab's internal proselytizer. It can only be successfully used by a cogscarab and requires liquified Replicant Alloy to function."
metal_to_alloy = TRUE
item_state = "nothing"
w_class = 1
var/debug = FALSE
/obj/item/clockwork/clockwork_proselytizer/scarab/proselytize(atom/target, mob/living/user)
if(!debug && !isdrone(user))
return 0
return ..()
/obj/item/clockwork/clockwork_proselytizer/scarab/debug
clockwork_desc = "A cogscarab's internal proselytizer. It can convert nearly any object into a Ratvarian variant."
uses_alloy = FALSE
debug = TRUE
/obj/item/clockwork/clockwork_proselytizer/examine(mob/living/user)
..()
if(is_servant_of_ratvar(user) || isobserver(user))
user << "<span class='brass'>Can be used to convert walls, floors, windows, airlocks, windoors, and grilles to clockwork variants.</span>"
user << "<span class='brass'>Can also form some objects into Replicant Alloy, as well as reform Clockwork Walls into Clockwork Floors, and vice versa.</span>"
if(metal_to_alloy)
user << "<span class='alloy'>It can convert rods, metal, and plasteel to liquified replicant alloy at a low rate.</span>"
if(uses_alloy)
user << "<span class='alloy'>It has <b>[stored_alloy]/[max_alloy]</b> units of liquified alloy stored.</span>"
user << "<span class='alloy'>Use it on a Tinkerer's Cache, strike it with Replicant Alloy, or attack Replicant Alloy with it to add additional liquified alloy.</span>"
user << "<span class='alloy'>Use it in-hand to remove stored liquified alloy.</span>"
/obj/item/clockwork/clockwork_proselytizer/attack_self(mob/living/user)
if(is_servant_of_ratvar(user) && uses_alloy)
if(!can_use_alloy(REPLICANT_ALLOY_UNIT))
user << "<span class='warning'>[src] [stored_alloy ? "Lacks enough":"Contains no"] alloy to reform[stored_alloy ? "":" any"] into solidified alloy!</span>"
return
modify_stored_alloy(-REPLICANT_ALLOY_UNIT)
playsound(src, 'sound/items/Deconstruct.ogg', 50, 1)
new/obj/item/clockwork/component/replicant_alloy(user.loc)
user << "<span class='brass'>You force [stored_alloy ? "some":"all"] of the alloy in [src]'s compartments to reform and solidify. \
It now contains <b>[stored_alloy]/[max_alloy]</b> units of liquified alloy.</span>"
/obj/item/clockwork/clockwork_proselytizer/attackby(obj/item/I, mob/living/user, params)
if(istype(I, /obj/item/clockwork/component/replicant_alloy) && is_servant_of_ratvar(user) && uses_alloy)
if(!can_use_alloy(-REPLICANT_ALLOY_UNIT))
user << "<span class='warning'>[src]'s replicant alloy compartments are full!</span>"
return 0
modify_stored_alloy(REPLICANT_ALLOY_UNIT)
playsound(user, 'sound/machines/click.ogg', 50, 1)
clockwork_say(user, text2ratvar("Transmute into fuel."), TRUE)
user << "<span class='brass'>You force [I] to liquify and pour it into [src]'s compartments. It now contains <b>[stored_alloy]/[max_alloy]</b> units of liquified alloy.</span>"
user.drop_item()
qdel(I)
return 1
else
return ..()
/obj/item/clockwork/clockwork_proselytizer/afterattack(atom/target, mob/living/user, proximity_flag, params)
if(!target || !user || !proximity_flag)
return 0
if(!is_servant_of_ratvar(user))
return ..()
proselytize(target, user)
/obj/item/clockwork/clockwork_proselytizer/proc/modify_stored_alloy(amount)
if(can_use_alloy(RATVAR_ALLOY_CHECK)) //Ratvar makes it free
amount = 0
stored_alloy = Clamp(stored_alloy + amount, 0, max_alloy)
return 1
/obj/item/clockwork/clockwork_proselytizer/proc/can_use_alloy(amount)
if(amount == RATVAR_ALLOY_CHECK)
if(ratvar_awakens || !uses_alloy)
return TRUE
else
return FALSE
if(stored_alloy - amount < 0)
return FALSE
if(stored_alloy - amount > max_alloy)
return FALSE
return TRUE
/obj/item/clockwork/clockwork_proselytizer/proc/proselytize(atom/target, mob/living/user)
if(!target || !user)
return 0
var/target_type = target.type
var/list/proselytize_values = target.proselytize_vals(user, src) //relevant values for proselytizing stuff, given as an associated list
if(!islist(proselytize_values))
if(proselytize_values != TRUE) //if we get true, fail, but don't send a message for whatever reason
user << "<span class='warning'>[target] cannot be proselytized!</span>"
return 0
if(repairing)
user << "<span class='warning'>You are currently repairing [repairing] with [src]!</span>"
return 0
if(!uses_alloy)
proselytize_values["alloy_cost"] = 0
if(!can_use_alloy(proselytize_values["alloy_cost"]))
if(stored_alloy - proselytize_values["alloy_cost"] < 0)
user << "<span class='warning'>You need <b>[proselytize_values["alloy_cost"]]</b> liquified alloy to proselytize [target]!</span>"
else if(stored_alloy - proselytize_values["alloy_cost"] > max_alloy)
user << "<span class='warning'>You have too much liquified alloy stored to proselytize [target]!</span>"
return 0
if(can_use_alloy(RATVAR_ALLOY_CHECK)) //Ratvar makes it faster
proselytize_values["operation_time"] *= 0.5
user.visible_message("<span class='warning'>[user]'s [name] begins tearing apart [target]!</span>", "<span class='brass'>You begin proselytizing [target]...</span>")
playsound(target, 'sound/machines/click.ogg', 50, 1)
if(proselytize_values["operation_time"] && !do_after(user, proselytize_values["operation_time"], target = target))
return 0
if(!can_use_alloy(proselytize_values["alloy_cost"])) //Check again to prevent bypassing via spamclick
return 0
if(!target || target.type != target_type)
return 0
if(repairing)
return 0
user.visible_message("<span class='warning'>[user]'s [name] disgorges a chunk of metal and shapes it over what's left of [target]!</span>", \
"<span class='brass'>You proselytize [target].</span>")
playsound(target, 'sound/items/Deconstruct.ogg', 50, 1)
var/new_thing_type = proselytize_values["new_obj_type"]
if(isturf(target))
var/turf/T = target
T.ChangeTurf(new_thing_type)
else
if(proselytize_values["dir_in_new"])
new new_thing_type(get_turf(target), proselytize_values["spawn_dir"])
else
var/atom/A = new new_thing_type(get_turf(target))
A.setDir(proselytize_values["spawn_dir"])
qdel(target)
modify_stored_alloy(-proselytize_values["alloy_cost"])
return 1
//For the clockwork proselytizer, this proc exists to make it easy to customize what the proselytizer 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, "alloy_cost" = 5, "spawn_dir" = dir, "dir_in_new" = TRUE)
@@ -157,6 +8,7 @@
/atom/proc/proselytize_vals(mob/living/user, obj/item/clockwork/clockwork_proselytizer/proselytizer)
return FALSE
//Turf conversion
/turf/closed/wall/proselytize_vals(mob/living/user, obj/item/clockwork/clockwork_proselytizer/proselytizer)
return list("operation_time" = 50, "new_obj_type" = /turf/closed/wall/clockwork, "alloy_cost" = REPLICANT_WALL_TOTAL, "spawn_dir" = SOUTH)
@@ -185,6 +37,7 @@
return FALSE
return list("operation_time" = 100, "new_obj_type" = /turf/closed/wall/clockwork, "alloy_cost" = REPLICANT_WALL_MINUS_FLOOR, "spawn_dir" = SOUTH)
//Metal conversion
/obj/item/stack/rods/proselytize_vals(mob/living/user, obj/item/clockwork/clockwork_proselytizer/proselytizer)
if(get_amount() >= 10)
var/sheets_to_make = round(get_amount() * 0.1)
@@ -218,6 +71,7 @@
user << "<span class='warning'>You need at least 10 sheets of plasteel to convert into brass.</span>"
return TRUE
//Brass directly to alloy; scarab only
/obj/item/stack/sheet/brass/proselytize_vals(mob/living/user, obj/item/clockwork/clockwork_proselytizer/proselytizer)
if(!proselytizer.metal_to_alloy)
return FALSE
@@ -225,6 +79,7 @@
var/prosel_time = -amount*1
return list("operation_time" = -prosel_time, "new_obj_type" = /obj/effect/overlay/temp/ratvar/beam/itemconsume, "alloy_cost" = prosel_cost, "spawn_dir" = SOUTH)
//Airlock conversion
/obj/machinery/door/airlock/proselytize_vals(mob/living/user, obj/item/clockwork/clockwork_proselytizer/proselytizer)
var/doortype = /obj/machinery/door/airlock/clockwork
if(glass)
@@ -234,6 +89,7 @@
/obj/machinery/door/airlock/clockwork/proselytize_vals(mob/living/user, obj/item/clockwork/clockwork_proselytizer/proselytizer)
return FALSE
//Window conversion
/obj/structure/window/proselytize_vals(mob/living/user, obj/item/clockwork/clockwork_proselytizer/proselytizer)
var/windowtype = /obj/structure/window/reinforced/clockwork
var/new_dir = TRUE
@@ -249,12 +105,14 @@
/obj/structure/window/reinforced/clockwork/proselytize_vals(mob/living/user, obj/item/clockwork/clockwork_proselytizer/proselytizer)
return FALSE
//Windoor conversion
/obj/machinery/door/window/proselytize_vals(mob/living/user, obj/item/clockwork/clockwork_proselytizer/proselytizer)
return list("operation_time" = 30, "new_obj_type" = /obj/machinery/door/window/clockwork, "alloy_cost" = REPLICANT_STANDARD, "spawn_dir" = dir, "dir_in_new" = TRUE)
/obj/machinery/door/window/clockwork/proselytize_vals(mob/living/user, obj/item/clockwork/clockwork_proselytizer/proselytizer)
return FALSE
//Grille conversion
/obj/structure/grille/proselytize_vals(mob/living/user, obj/item/clockwork/clockwork_proselytizer/proselytizer)
var/grilletype = /obj/structure/grille/ratvar
var/prosel_time = 15
@@ -266,6 +124,7 @@
/obj/structure/grille/ratvar/proselytize_vals(mob/living/user, obj/item/clockwork/clockwork_proselytizer/proselytizer)
return FALSE
//Hitting a clockwork structure will try to repair it.
/obj/structure/destructible/clockwork/proselytize_vals(mob/living/user, obj/item/clockwork/clockwork_proselytizer/proselytizer)
. = TRUE
if(proselytizer.repairing) //no spamclicking for fast repairs, bucko
@@ -319,6 +178,7 @@
"<span class='alloy'>You finish repairing [src]. It is now at <b>[obj_integrity]/[max_integrity]</b> integrity.</span>")
return
//Hitting a tinkerer's cache will try to fill the proselytizer with alloy after trying to repair.
/obj/structure/destructible/clockwork/cache/proselytize_vals(mob/living/user, obj/item/clockwork/clockwork_proselytizer/proselytizer)
. = ..()
if(proselytizer.can_use_alloy(RATVAR_ALLOY_CHECK) || proselytizer.stored_alloy + REPLICANT_ALLOY_UNIT > proselytizer.max_alloy)
@@ -341,6 +201,7 @@
"<span class='brass'>You finish filling [proselytizer] with liquified alloy. It now contains <b>[proselytizer.stored_alloy]/[proselytizer.max_alloy]</b> units of liquified alloy.</span>")
return
//Convert shards, wall gears, and replicant alloy directly to liquid alloy
/obj/structure/destructible/clockwork/wall_gear/proselytize_vals(mob/living/user, obj/item/clockwork/clockwork_proselytizer/proselytizer)
return list("operation_time" = 10, "new_obj_type" = /obj/effect/overlay/temp/ratvar/beam/itemconsume, "alloy_cost" = -REPLICANT_GEAR, "spawn_dir" = SOUTH)
@@ -0,0 +1,107 @@
/*
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])","g")
#define RATVAR_PRE_AND_REPLACEMENT "$1-$2"
#define RATVAR_POST_AND_MATCH regex("(\[aA]\[nN]\[dD])\\s(\\w)","g")
#define RATVAR_POST_AND_REPLACEMENT "$1-$2"
#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 = 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)
ratvarian = replacetext(ratvarian, RATVAR_MY_MATCH, RATVAR_MY_REPLACEMENT)
return rot13(ratvarian)
/proc/ratvar2text(ratvarian) //Reverts ravarian styling and rot13 in text.
var/text = replacetext(rot13(ratvarian), "`", "")
text = replacetext(text, 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)
text = replacetext(text, REVERSE_RATVAR_HYPHEN_OF_MATCH, REVERSE_RATVAR_HYPHEN_OF_REPLACEMENT)
return text
//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)
var/old_languages_spoken = AM.languages_spoken
AM.languages_spoken = HUMAN //anyone who can understand HUMAN will hear weird shitty ratvar speak, otherwise it'll get starred out
if(isliving(AM))
var/mob/living/L = AM
if(!whisper)
L.say(message, "clock", spans)
else
L.whisper(message)
else
AM.say(message)
AM.languages_spoken = old_languages_spoken
@@ -0,0 +1,37 @@
//returns a list of scriptures and if they're unlocked or not
/proc/scripture_unlock_check()
var/servants = 0
var/unconverted_ai_exists = FALSE
for(var/mob/living/M in living_mob_list)
if(is_servant_of_ratvar(M) && (ishuman(M) || issilicon(M)))
servants++
else if(isAI(M))
unconverted_ai_exists = TRUE
. = list(SCRIPTURE_DRIVER = TRUE, SCRIPTURE_SCRIPT = FALSE, SCRIPTURE_APPLICATION = FALSE, SCRIPTURE_REVENANT = FALSE, SCRIPTURE_JUDGEMENT = FALSE)
//Drivers: always unlocked
.[SCRIPTURE_SCRIPT] = (servants >= 5 && clockwork_caches >= 1)
//Script: 5 or more non-brain servants and 1+ clockwork caches
.[SCRIPTURE_APPLICATION] = (servants >= 8 && clockwork_caches >= 3 && clockwork_construction_value >= 100)
//Application: 8 or more non-brain servants, 3+ clockwork caches, and at least 100 CV
.[SCRIPTURE_REVENANT] = (servants >= 10 && clockwork_caches >= 4 && clockwork_construction_value >= 200)
//Revenant: 10 or more non-brain servants, 4+ clockwork caches, and at least 200 CV
.[SCRIPTURE_JUDGEMENT] = (servants >= 12 && clockwork_caches >= 5 && clockwork_construction_value >= 300 && !unconverted_ai_exists)
//Judgement: 12 or more non-brain servants, 5+ clockwork caches, at least 300 CV, and there are no living, non-servant ais
//reports to servants when scripture is locked or unlocked
/proc/scripture_unlock_alert(list/previous_states)
. = scripture_unlock_check()
for(var/i in .)
if(.[i] != previous_states[i])
hierophant_message("<span class='large_brass'><i>Hierophant Network:</i> <b>[i] Scripture has been [.[i] ? "un":""]locked.</b></span>")
//changes construction value
/proc/change_construction_value(amount)
clockwork_construction_value += amount
//throws the no cache alert if there are no caches and clears it otherwise
/proc/cache_check(mob/M)
if(!clockwork_caches)
M.throw_alert("nocache", /obj/screen/alert/clockwork/nocache)
else
M.clear_alert("nocache")
@@ -0,0 +1,150 @@
/obj/item/clockwork/clockwork_proselytizer //Clockwork proselytizer (yes, that's a real word): Converts applicable objects to Ratvarian variants.
name = "clockwork proselytizer"
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 liquified Replicant Alloy to function."
icon_state = "clockwork_proselytizer"
w_class = 3
force = 5
flags = NOBLUDGEON
var/stored_alloy = 0 //Requires this to function; each chunk of replicant alloy provides REPLICANT_ALLOY_UNIT
var/max_alloy = REPLICANT_ALLOY_UNIT * 10
var/uses_alloy = TRUE
var/metal_to_alloy = FALSE
var/repairing = null //what we're currently repairing, if anything
/obj/item/clockwork/clockwork_proselytizer/preloaded
stored_alloy = REPLICANT_WALL_MINUS_FLOOR+REPLICANT_WALL_TOTAL
/obj/item/clockwork/clockwork_proselytizer/scarab
name = "scarab proselytizer"
clockwork_desc = "A cogscarab's internal proselytizer. It can only be successfully used by a cogscarab and requires liquified Replicant Alloy to function."
metal_to_alloy = TRUE
item_state = "nothing"
w_class = 1
var/debug = FALSE
/obj/item/clockwork/clockwork_proselytizer/scarab/proselytize(atom/target, mob/living/user)
if(!debug && !isdrone(user))
return 0
return ..()
/obj/item/clockwork/clockwork_proselytizer/scarab/debug
clockwork_desc = "A cogscarab's internal proselytizer. It can convert nearly any object into a Ratvarian variant."
uses_alloy = FALSE
debug = TRUE
/obj/item/clockwork/clockwork_proselytizer/examine(mob/living/user)
..()
if(is_servant_of_ratvar(user) || isobserver(user))
user << "<span class='brass'>Can be used to convert walls, floors, windows, airlocks, windoors, and grilles to clockwork variants.</span>"
user << "<span class='brass'>Can also form some objects into Replicant Alloy, as well as reform Clockwork Walls into Clockwork Floors, and vice versa.</span>"
if(metal_to_alloy)
user << "<span class='alloy'>It can convert rods, metal, and plasteel to liquified replicant alloy at a low rate.</span>"
if(uses_alloy)
user << "<span class='alloy'>It has <b>[stored_alloy]/[max_alloy]</b> units of liquified alloy stored.</span>"
user << "<span class='alloy'>Use it on a Tinkerer's Cache, strike it with Replicant Alloy, or attack Replicant Alloy with it to add additional liquified alloy.</span>"
user << "<span class='alloy'>Use it in-hand to remove stored liquified alloy.</span>"
/obj/item/clockwork/clockwork_proselytizer/attack_self(mob/living/user)
if(is_servant_of_ratvar(user) && uses_alloy)
if(!can_use_alloy(REPLICANT_ALLOY_UNIT))
user << "<span class='warning'>[src] [stored_alloy ? "Lacks enough":"Contains no"] alloy to reform[stored_alloy ? "":" any"] into solidified alloy!</span>"
return
modify_stored_alloy(-REPLICANT_ALLOY_UNIT)
playsound(src, 'sound/items/Deconstruct.ogg', 50, 1)
new/obj/item/clockwork/component/replicant_alloy(user.loc)
user << "<span class='brass'>You force [stored_alloy ? "some":"all"] of the alloy in [src]'s compartments to reform and solidify. \
It now contains <b>[stored_alloy]/[max_alloy]</b> units of liquified alloy.</span>"
/obj/item/clockwork/clockwork_proselytizer/attackby(obj/item/I, mob/living/user, params)
if(istype(I, /obj/item/clockwork/component/replicant_alloy) && is_servant_of_ratvar(user) && uses_alloy)
if(!can_use_alloy(-REPLICANT_ALLOY_UNIT))
user << "<span class='warning'>[src]'s replicant alloy compartments are full!</span>"
return 0
modify_stored_alloy(REPLICANT_ALLOY_UNIT)
playsound(user, 'sound/machines/click.ogg', 50, 1)
clockwork_say(user, text2ratvar("Transmute into fuel."), TRUE)
user << "<span class='brass'>You force [I] to liquify and pour it into [src]'s compartments. It now contains <b>[stored_alloy]/[max_alloy]</b> units of liquified alloy.</span>"
user.drop_item()
qdel(I)
return 1
else
return ..()
/obj/item/clockwork/clockwork_proselytizer/afterattack(atom/target, mob/living/user, proximity_flag, params)
if(!target || !user || !proximity_flag)
return 0
if(!is_servant_of_ratvar(user))
return ..()
proselytize(target, user)
/obj/item/clockwork/clockwork_proselytizer/proc/modify_stored_alloy(amount)
if(can_use_alloy(RATVAR_ALLOY_CHECK)) //Ratvar makes it free
amount = 0
stored_alloy = Clamp(stored_alloy + amount, 0, max_alloy)
return 1
/obj/item/clockwork/clockwork_proselytizer/proc/can_use_alloy(amount)
if(amount == RATVAR_ALLOY_CHECK)
if(ratvar_awakens || !uses_alloy)
return TRUE
else
return FALSE
if(stored_alloy - amount < 0)
return FALSE
if(stored_alloy - amount > max_alloy)
return FALSE
return TRUE
/obj/item/clockwork/clockwork_proselytizer/proc/proselytize(atom/target, mob/living/user)
if(!target || !user)
return 0
var/target_type = target.type
var/list/proselytize_values = target.proselytize_vals(user, src) //relevant values for proselytizing stuff, given as an associated list
if(!islist(proselytize_values))
if(proselytize_values != TRUE) //if we get true, fail, but don't send a message for whatever reason
user << "<span class='warning'>[target] cannot be proselytized!</span>"
return 0
if(repairing)
user << "<span class='warning'>You are currently repairing [repairing] with [src]!</span>"
return 0
if(!uses_alloy)
proselytize_values["alloy_cost"] = 0
if(!can_use_alloy(proselytize_values["alloy_cost"]))
if(stored_alloy - proselytize_values["alloy_cost"] < 0)
user << "<span class='warning'>You need <b>[proselytize_values["alloy_cost"]]</b> liquified alloy to proselytize [target]!</span>"
else if(stored_alloy - proselytize_values["alloy_cost"] > max_alloy)
user << "<span class='warning'>You have too much liquified alloy stored to proselytize [target]!</span>"
return 0
if(can_use_alloy(RATVAR_ALLOY_CHECK)) //Ratvar makes it faster
proselytize_values["operation_time"] *= 0.5
user.visible_message("<span class='warning'>[user]'s [name] begins tearing apart [target]!</span>", "<span class='brass'>You begin proselytizing [target]...</span>")
playsound(target, 'sound/machines/click.ogg', 50, 1)
if(proselytize_values["operation_time"] && !do_after(user, proselytize_values["operation_time"], target = target))
return 0
if(!can_use_alloy(proselytize_values["alloy_cost"])) //Check again to prevent bypassing via spamclick
return 0
if(!target || target.type != target_type)
return 0
if(repairing)
return 0
user.visible_message("<span class='warning'>[user]'s [name] disgorges a chunk of metal and shapes it over what's left of [target]!</span>", \
"<span class='brass'>You proselytize [target].</span>")
playsound(target, 'sound/items/Deconstruct.ogg', 50, 1)
var/new_thing_type = proselytize_values["new_obj_type"]
if(isturf(target))
var/turf/T = target
T.ChangeTurf(new_thing_type)
else
if(proselytize_values["dir_in_new"])
new new_thing_type(get_turf(target), proselytize_values["spawn_dir"])
else
var/atom/A = new new_thing_type(get_turf(target))
A.setDir(proselytize_values["spawn_dir"])
qdel(target)
modify_stored_alloy(-proselytize_values["alloy_cost"])
return 1
@@ -1,676 +0,0 @@
////////////////////////
// CLOCKWORK MACHINES //
////////////////////////
//not-actually-machines
/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))
var/powered = total_accessable_power()
user << "<span class='[powered ? "brass":"alloy"]'>It has access to <b>[powered == INFINITY ? "INFINITY":"[powered]"]W</b> of power.</span>"
/obj/structure/destructible/clockwork/powered/Destroy()
SSfastprocess.processing -= src
SSobj.processing -= src
return ..()
/obj/structure/destructible/clockwork/powered/process()
var/powered = total_accessable_power()
return powered == PROCESS_KILL ? 25 : powered //make sure we don't accidentally return the arbitrary PROCESS_KILL define
/obj/structure/destructible/clockwork/powered/proc/toggle(fast_process, mob/living/user)
if(user)
if(!is_servant_of_ratvar(user))
return 0
user.visible_message("<span class='notice'>[user] [active ? "dis" : "en"]ables [src].</span>", "<span class='brass'>You [active ? "dis" : "en"]able [src].</span>")
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)
/obj/structure/destructible/clockwork/powered/proc/total_accessable_power() //how much power we have and can use
if(!needs_power || ratvar_awakens)
return INFINITY //oh yeah we've got power why'd you ask
var/power = 0
power += accessable_apc_power()
power += accessable_sigil_power()
return power
/obj/structure/destructible/clockwork/powered/proc/accessable_apc_power()
var/power = 0
var/area/A = get_area(src)
var/area/targetAPCA
for(var/obj/machinery/power/apc/APC in apcs_list)
var/area/APCA = get_area(APC)
if(APCA == A)
target_apc = APC
if(target_apc)
targetAPCA = get_area(target_apc)
if(targetAPCA != A)
target_apc = null
else if(target_apc.cell)
var/apccharge = target_apc.cell.charge
if(apccharge >= MIN_CLOCKCULT_POWER)
power += apccharge
return power
/obj/structure/destructible/clockwork/powered/proc/accessable_sigil_power()
var/power = 0
for(var/obj/effect/clockwork/sigil/transmission/T in range(1, src))
power += T.power_charge
return power
/obj/structure/destructible/clockwork/powered/proc/try_use_power(amount) //try to use an amount of power
if(!needs_power || ratvar_awakens)
return 1
if(amount <= 0)
return 0
var/power = total_accessable_power()
if(!power || power < amount)
return 0
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
var/sigilpower = accessable_sigil_power()
var/list/sigils_in_range = list()
for(var/obj/effect/clockwork/sigil/transmission/T in range(1, src))
sigils_in_range |= T
while(sigilpower && amount >= MIN_CLOCKCULT_POWER)
for(var/S in sigils_in_range)
var/obj/effect/clockwork/sigil/transmission/T = S
if(amount >= MIN_CLOCKCULT_POWER && T.modify_charge(MIN_CLOCKCULT_POWER))
sigilpower -= MIN_CLOCKCULT_POWER
amount -= MIN_CLOCKCULT_POWER
var/apcpower = accessable_apc_power()
while(apcpower >= MIN_CLOCKCULT_POWER && amount >= MIN_CLOCKCULT_POWER)
if(target_apc.cell.use(MIN_CLOCKCULT_POWER))
apcpower -= MIN_CLOCKCULT_POWER
amount -= MIN_CLOCKCULT_POWER
target_apc.update()
target_apc.update_icon()
else
apcpower = 0
if(amount)
return 0
else
return 1
/obj/structure/destructible/clockwork/powered/proc/return_power(amount) //returns a given amount of power to all nearby sigils
if(amount <= 0)
return 0
var/list/sigils_in_range = list()
for(var/obj/effect/clockwork/sigil/transmission/T in range(1, src))
sigils_in_range |= T
if(!sigils_in_range.len)
return 0
while(amount >= MIN_CLOCKCULT_POWER)
for(var/S in sigils_in_range)
var/obj/effect/clockwork/sigil/transmission/T = S
if(amount >= MIN_CLOCKCULT_POWER && T.modify_charge(-MIN_CLOCKCULT_POWER))
amount -= MIN_CLOCKCULT_POWER
return 1
/obj/structure/destructible/clockwork/powered/interdiction_lens //Interdiction lens: A powerful artifact that constantly disrupts electronics but, if it fails to find something to disrupt, turns off.
name = "interdiction lens"
desc = "An ominous, double-pronged brass totem. There's a strange gemstone clasped between the pincers."
clockwork_desc = "A powerful totem that constantly drains nearby electronics and funnels the power drained into nearby Sigils of Transmission."
icon_state = "interdiction_lens"
construction_value = 25
active_icon = "interdiction_lens_active"
inactive_icon = "interdiction_lens"
break_message = "<span class='warning'>The lens flares a blinding violet before shattering!</span>"
break_sound = 'sound/effects/Glassbr3.ogg'
var/recharging = 0 //world.time when the lens was last used
var/recharge_time = 1200 //if it drains no power and affects no objects, it turns off for two minutes
var/disabled = FALSE //if it's actually usable
var/interdiction_range = 14 //how large an area it drains and disables in
/obj/structure/destructible/clockwork/powered/interdiction_lens/examine(mob/user)
..()
user << "<span class='[recharging > world.time ? "nezbere_small":"brass"]'>Its gemstone [recharging > world.time ? "has been breached by writhing tendrils of blackness that cover the totem" \
: "vibrates in place and thrums with power"].</span>"
if(is_servant_of_ratvar(user) || isobserver(user))
user << "<span class='nezbere_small'>If it fails to drain any electronics, it will disable itself for <b>[round(recharge_time/600, 1)]</b> minutes.</span>"
/obj/structure/destructible/clockwork/powered/interdiction_lens/toggle(fast_process, mob/living/user)
..()
if(active)
SetLuminosity(4,2)
else
SetLuminosity(0)
/obj/structure/destructible/clockwork/powered/interdiction_lens/attack_hand(mob/living/user)
if(user.canUseTopic(src, BE_CLOSE))
if(disabled)
user << "<span class='warning'>As you place your hand on the gemstone, cold tendrils of black matter crawl up your arm. You quickly pull back.</span>"
return 0
toggle(0, user)
/obj/structure/destructible/clockwork/powered/interdiction_lens/process()
if(recharging > world.time)
return
if(disabled)
visible_message("<span class='warning'>The writhing tendrils return to the gemstone, which begins to glow with power!</span>")
flick("interdiction_lens_recharged", src)
disabled = FALSE
toggle(0)
else
var/successfulprocess = FALSE
var/power_drained = 0
var/list/atoms_to_test = list()
for(var/A in spiral_range_turfs(interdiction_range, src))
var/turf/T = A
for(var/M in T)
atoms_to_test |= M
CHECK_TICK
for(var/M in atoms_to_test)
var/atom/movable/A = M
if(!A || qdeleted(A))
continue
power_drained += A.power_drain(TRUE)
if(istype(A, /obj/machinery/camera))
var/obj/machinery/camera/C = A
if(C.isEmpProof() || !C.status)
continue
successfulprocess = TRUE
if(C.emped)
continue
C.emp_act(1)
else if(istype(A, /obj/item/device/radio))
var/obj/item/device/radio/O = A
successfulprocess = TRUE
if(O.emped || !O.on)
continue
O.emp_act(1)
else if((isliving(A) && !is_servant_of_ratvar(A)) || istype(A, /obj/structure/closet) || istype(A, /obj/item/weapon/storage)) //other things may have radios in them but we don't care
for(var/obj/item/device/radio/O in A.GetAllContents())
successfulprocess = TRUE
if(O.emped || !O.on)
continue
O.emp_act(1)
CHECK_TICK
if(power_drained && power_drained >= MIN_CLOCKCULT_POWER && return_power(power_drained))
successfulprocess = TRUE
playsound(src, 'sound/items/PSHOOM.ogg', 50, 1, interdiction_range-7, 1)
if(!successfulprocess)
visible_message("<span class='warning'>The gemstone suddenly turns horribly dark, writhing tendrils covering it!</span>")
recharging = world.time + recharge_time
flick("interdiction_lens_discharged", src)
icon_state = "interdiction_lens_inactive"
SetLuminosity(2,1)
disabled = TRUE
/obj/structure/destructible/clockwork/powered/mending_motor //Mending motor: A prism that consumes replicant alloy to repair nearby mechanical servants at a quick rate.
name = "mending motor"
desc = "A dark onyx prism, held in midair by spiraling tendrils of stone."
clockwork_desc = "A powerful prism that rapidly repairs nearby mechanical servants and clockwork structures."
icon_state = "mending_motor_inactive"
active_icon = "mending_motor"
inactive_icon = "mending_motor_inactive"
construction_value = 20
max_integrity = 125
obj_integrity = 125
break_message = "<span class='warning'>The prism collapses with a heavy thud!</span>"
debris = list(/obj/item/clockwork/alloy_shards/small = 5, \
/obj/item/clockwork/alloy_shards/medium = 1, \
/obj/item/clockwork/alloy_shards/large = 1, \
/obj/item/clockwork/component/vanguard_cogwheel = 1)
var/stored_alloy = 0
var/max_alloy = REPLICANT_ALLOY_POWER * 10
var/mob_cost = 200
var/structure_cost = 250
var/cyborg_cost = 300
/obj/structure/destructible/clockwork/powered/mending_motor/prefilled
stored_alloy = REPLICANT_ALLOY_POWER //starts with 1 replicant alloy's worth of power
/obj/structure/destructible/clockwork/powered/mending_motor/total_accessable_power()
. = ..()
if(. != INFINITY)
. += accessable_alloy_power()
/obj/structure/destructible/clockwork/powered/mending_motor/proc/accessable_alloy_power()
return stored_alloy
/obj/structure/destructible/clockwork/powered/mending_motor/use_power(amount)
var/alloypower = accessable_alloy_power()
while(alloypower >= MIN_CLOCKCULT_POWER && amount >= MIN_CLOCKCULT_POWER)
stored_alloy -= MIN_CLOCKCULT_POWER
alloypower -= MIN_CLOCKCULT_POWER
amount -= MIN_CLOCKCULT_POWER
return ..()
/obj/structure/destructible/clockwork/powered/mending_motor/examine(mob/user)
..()
if(is_servant_of_ratvar(user) || isobserver(user))
user << "<span class='alloy'>It contains <b>[stored_alloy*CLOCKCULT_POWER_TO_ALLOY_MULTIPLIER]/[max_alloy*CLOCKCULT_POWER_TO_ALLOY_MULTIPLIER]</b> units of liquified alloy, \
which is equivalent to <b>[stored_alloy]W/[max_alloy]W</b> of power.</span>"
user << "<span class='inathneq_small'>It requires <b>[mob_cost]W</b> to heal clockwork mobs, <b>[structure_cost]W</b> for clockwork structures, and <b>[cyborg_cost]W</b> for cyborgs.</span>"
/obj/structure/destructible/clockwork/powered/mending_motor/process()
if(..() < mob_cost)
visible_message("<span class='warning'>[src] emits an airy chuckling sound and falls dark!</span>")
toggle()
return
for(var/atom/movable/M in range(5, src))
if(isclockmob(M) || istype(M, /mob/living/simple_animal/drone/cogscarab))
var/mob/living/simple_animal/hostile/clockwork/W = M
var/fatigued = FALSE
if(istype(M, /mob/living/simple_animal/hostile/clockwork/marauder))
var/mob/living/simple_animal/hostile/clockwork/marauder/E = M
if(E.fatigue)
fatigued = TRUE
if((!fatigued && W.health == W.maxHealth) || W.stat)
continue
if(!try_use_power(mob_cost))
break
W.adjustHealth(-20)
else if(istype(M, /obj/structure/destructible/clockwork))
var/obj/structure/destructible/clockwork/C = M
if(C.obj_integrity == C.max_integrity)
continue
if(!try_use_power(structure_cost))
break
C.obj_integrity = min(C.obj_integrity + 20, C.max_integrity)
else if(issilicon(M))
var/mob/living/silicon/S = M
if(S.health == S.maxHealth || S.stat == DEAD || !is_servant_of_ratvar(S))
continue
if(!try_use_power(cyborg_cost))
break
S.adjustBruteLoss(-20)
S.adjustFireLoss(-10)
return 1
/obj/structure/destructible/clockwork/powered/mending_motor/attack_hand(mob/living/user)
if(user.canUseTopic(src, BE_CLOSE))
if(total_accessable_power() < mob_cost)
user << "<span class='warning'>[src] needs more power or replicant alloy to function!</span>"
return 0
toggle(0, user)
/obj/structure/destructible/clockwork/powered/mending_motor/attackby(obj/item/I, mob/user, params)
if(istype(I, /obj/item/clockwork/component/replicant_alloy) && is_servant_of_ratvar(user))
if(stored_alloy + REPLICANT_ALLOY_POWER > max_alloy)
user << "<span class='warning'>[src] is too full to accept any more alloy!</span>"
return 0
playsound(user, 'sound/machines/click.ogg', 50, 1)
clockwork_say(user, text2ratvar("Transmute into fuel."), TRUE)
user << "<span class='brass'>You force [I] to liquify and pour it into [src]'s compartments. \
It now contains <b>[stored_alloy*CLOCKCULT_POWER_TO_ALLOY_MULTIPLIER]/[max_alloy*CLOCKCULT_POWER_TO_ALLOY_MULTIPLIER]</b> units of liquified alloy.</span>"
stored_alloy = stored_alloy + REPLICANT_ALLOY_POWER
user.drop_item()
qdel(I)
return 1
else
return ..()
/obj/structure/destructible/clockwork/powered/mania_motor //Mania motor: A pair of antenna that, while active, cause braindamage and hallucinations in nearby human mobs.
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 hallucinations and brain damage as long as it remains powered."
icon_state = "mania_motor_inactive"
active_icon = "mania_motor"
inactive_icon = "mania_motor_inactive"
construction_value = 20
max_integrity = 80
obj_integrity = 80
break_message = "<span class='warning'>The antenna break off, leaving a pile of shards!</span>"
debris = list(/obj/item/clockwork/alloy_shards/large = 1, \
/obj/item/clockwork/alloy_shards/small = 3, \
/obj/item/clockwork/component/guvax_capacitor/antennae = 1)
var/mania_cost = 200
var/convert_attempt_cost = 200
var/convert_cost = 200
var/mania_messages = list("\"Go nuts.\"", "\"Take a crack at crazy.\"", "\"Make a bid for insanity.\"", "\"Get kooky.\"", "\"Move towards mania.\"", "\"Become bewildered.\"", "\"Wax wild.\"", \
"\"Go round the bend.\"", "\"Land in lunacy.\"", "\"Try dementia.\"", "\"Strive to get a screw loose.\"")
var/compel_messages = list("\"Come closer.\"", "\"Approach the transmitter.\"", "\"Touch the antennae.\"", "\"I always have to deal with idiots. Move towards the mania motor.\"", \
"\"Advance forward and place your head between the antennae - that's all it's good for.\"", "\"If you were smarter, you'd be over here already.\"", "\"Move FORWARD, you fool.\"")
var/convert_messages = list("\"You won't do. Go to sleep while I tell these nitwits how to convert you.\"", "\"You are insufficient. I must instruct these idiots in the art of conversion.\"", \
"\"Oh of course, someone we can't convert. These servants are fools.\"", "\"How hard is it to use a Sigil, anyway? All it takes is dragging someone onto it.\"", \
"\"How do they fail to use a Sigil of Accession, anyway?\"", "\"Why is it that all servants are this inept?\"", "\"It's quite likely you'll be stuck here for a while.\"")
var/close_messages = list("\"Well, you can't reach the motor from THERE, you moron.\"", "\"Interesting location. I'd prefer if you went somewhere you could ACTUALLY TOUCH THE ANTENNAE!\"", \
"\"Amazing. You somehow managed to wedge yourself somewhere you can't actually reach the motor from.\"", "\"Such a show of idiocy is unparalleled. Perhaps I should put you on display?\"", \
"\"Did you do this on purpose? I can't imagine you doing so accidentally. Oh, wait, I can.\"", "\"How is it that such smart creatures can still do something AS STUPID AS THIS!\"")
/obj/structure/destructible/clockwork/powered/mania_motor/examine(mob/user)
..()
if(is_servant_of_ratvar(user) || isobserver(user))
user << "<span class='sevtug_small'>It requires <b>[mania_cost]W</b> to run, and <b>[convert_attempt_cost + convert_cost]W</b> to convert humans adjecent to it.</span>"
/obj/structure/destructible/clockwork/powered/mania_motor/process()
if(try_use_power(mania_cost))
var/turf/T = get_turf(src)
var/hum = get_sfx('sound/effects/screech.ogg') //like playsound, same sound for everyone affected
for(var/mob/living/carbon/human/H in view(1, src))
if(is_servant_of_ratvar(H))
continue
if(H.Adjacent(src) && try_use_power(convert_attempt_cost))
if(is_eligible_servant(H) && try_use_power(convert_cost))
H << "<span class='sevtug'>\"[text2ratvar("You are mine and his, now.")]\"</span>"
H.playsound_local(T, hum, 80, 1)
add_servant_of_ratvar(H)
else if(!H.stat)
if(H.getBrainLoss() >= 100)
H.Paralyse(5)
H << "<span class='sevtug'>[text2ratvar(pick(convert_messages))]</span>"
else
H.adjustBrainLoss(100)
H.visible_message("<span class='warning'>[H] reaches out and touches [src].</span>", "<span class='sevtug'>You touch [src] involuntarily.</span>")
else
visible_message("<span class='warning'>[src]'s antennae fizzle quietly.</span>")
playsound(src, 'sound/effects/light_flicker.ogg', 50, 1)
for(var/mob/living/carbon/human/H in range(10, src))
if(is_servant_of_ratvar(H))
if(H.getBrainLoss() || H.hallucination || H.druggy || H.dizziness || H.confused)
H.adjustBrainLoss(-H.getBrainLoss()) //heals servants of braindamage, hallucination, druggy, dizziness, and confusion
H.hallucination = 0
H.adjust_drugginess(-H.druggy)
H.dizziness = 0
H.confused = 0
else if(!H.null_rod_check() && H.stat == CONSCIOUS)
var/distance = get_dist(T, get_turf(H))
var/falloff_distance = min((110) - distance * 10, 80)
var/sound_distance = falloff_distance * 0.5
var/targetbrainloss = H.getBrainLoss()
if(distance >= 4 && prob(falloff_distance * 0.5))
H << "<span class='sevtug_small'>[text2ratvar(pick(mania_messages))]</span>"
H.playsound_local(T, hum, sound_distance, 1)
switch(distance)
if(2 to 3)
if(prob(falloff_distance * 0.5))
if(prob(falloff_distance))
H << "<span class='sevtug_small'>[text2ratvar(pick(mania_messages))]</span>"
else
H << "<span class='sevtug'>[text2ratvar(pick(compel_messages))]</span>"
if(targetbrainloss <= 50)
H.adjustBrainLoss(50 - targetbrainloss) //got too close had brain eaten
H.adjust_drugginess(Clamp(7, 0, 100 - H.druggy))
H.hallucination = min(H.hallucination + 7, 100)
H.dizziness = min(H.dizziness + 3, 45)
H.confused = min(H.confused + 3, 45)
if(4 to 5)
if(targetbrainloss <= 50)
H.adjustBrainLoss(1)
H.adjust_drugginess(Clamp(5, 0, 80 - H.druggy))
H.hallucination = min(H.hallucination + 5, 80)
H.dizziness = min(H.dizziness + 2, 30)
H.confused = min(H.confused + 2, 30)
if(6 to 7)
if(targetbrainloss <= 30)
H.adjustBrainLoss(1)
H.adjust_drugginess(Clamp(2, 0, 60 - H.druggy))
H.hallucination = min(H.hallucination + 2, 60)
H.dizziness = min(H.dizziness + 2, 15)
H.confused = min(H.confused + 2, 15)
if(8 to 9)
if(targetbrainloss <= 10)
H.adjustBrainLoss(1)
H.adjust_drugginess(Clamp(2, 0, 40 - H.druggy))
H.hallucination = min(H.hallucination + 2, 40)
if(10 to INFINITY)
H.adjust_drugginess(Clamp(2, 0, 20 - H.druggy))
H.hallucination = min(H.hallucination + 2, 20)
else //if it's a distance of 1 and they can't see it/aren't adjacent or they're on top of it(how'd they get on top of it and still trigger this???)
if(prob(falloff_distance * 0.5))
if(prob(falloff_distance))
H << "<span class='sevtug'>[text2ratvar(pick(compel_messages))]</span>"
else if(prob(falloff_distance * 0.5))
H << "<span class='sevtug'>[text2ratvar(pick(close_messages))]</span>"
else
H << "<span class='sevtug_small'>[text2ratvar(pick(mania_messages))]</span>"
if(targetbrainloss <= 99)
H.adjustBrainLoss(99 - targetbrainloss)
H.adjust_drugginess(Clamp(10, 0, 150 - H.druggy))
H.hallucination = min(H.hallucination + 10, 150)
H.dizziness = min(H.dizziness + 5, 60)
H.confused = min(H.confused + 5, 60)
else
visible_message("<span class='warning'>[src] hums loudly, then the sockets at its base fall dark!</span>")
playsound(src, 'sound/effects/screech.ogg', 40, 1)
toggle(0)
/obj/structure/destructible/clockwork/powered/mania_motor/attack_hand(mob/living/user)
if(user.canUseTopic(src, BE_CLOSE))
if(!total_accessable_power() >= mania_cost)
user << "<span class='warning'>[src] needs more power to function!</span>"
return 0
toggle(0, user)
/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"
construction_value = 20
max_integrity = 150
obj_integrity = 150
break_message = "<span class='warning'>The obelisk falls to the ground, undamaged!</span>"
debris = list(/obj/item/clockwork/alloy_shards/small = 3, \
/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
var/gateway_active = FALSE
/obj/structure/destructible/clockwork/powered/clockwork_obelisk/New()
..()
toggle(1)
/obj/structure/destructible/clockwork/powered/clockwork_obelisk/examine(mob/user)
..()
if(is_servant_of_ratvar(user) || isobserver(user))
user << "<span class='nzcrentr_small'>It requires <b>[hierophant_cost]W</b> to broadcast over the Hierophant Network, and <b>[gateway_cost]W</b> to open a Spatial Gateway.</span>"
/obj/structure/destructible/clockwork/powered/clockwork_obelisk/process()
if(locate(/obj/effect/clockwork/spatial_gateway) in loc)
icon_state = active_icon
density = 0
gateway_active = TRUE
else
icon_state = inactive_icon
density = 1
gateway_active = FALSE
/obj/structure/destructible/clockwork/powered/clockwork_obelisk/attack_hand(mob/living/user)
if(!is_servant_of_ratvar(user) || !total_accessable_power() >= hierophant_cost)
user << "<span class='warning'>You place your hand on the obelisk, but it doesn't react.</span>"
return
var/choice = alert(user,"You place your hand on the obelisk...",,"Hierophant Broadcast","Spatial Gateway","Cancel")
switch(choice)
if("Hierophant Broadcast")
if(gateway_active)
user << "<span class='warning'>The obelisk is sustaining a gateway and cannot broadcast!</span>"
return
var/input = stripped_input(usr, "Please choose a message to send over the Hierophant Network.", "Hierophant Broadcast", "")
if(!input || !user.canUseTopic(src, BE_CLOSE))
return
if(gateway_active)
user << "<span class='warning'>The obelisk is sustaining a gateway and cannot broadcast!</span>"
return
if(!try_use_power(hierophant_cost))
user << "<span class='warning'>The obelisk lacks the power to broadcast!</span>"
return
clockwork_say(user, text2ratvar("Hierophant Broadcast, activate!"))
titled_hierophant_message(user, input, "big_brass", "large_brass")
if("Spatial Gateway")
if(gateway_active)
user << "<span class='warning'>The obelisk is already sustaining a gateway!</span>"
return
if(!try_use_power(gateway_cost))
user << "<span class='warning'>The obelisk lacks the power to open a gateway!</span>"
return
if(procure_gateway(user, 100, 5, 1) && !gateway_active)
clockwork_say(user, text2ratvar("Spatial Gateway, activate!"))
else
return_power(gateway_cost)
if("Cancel")
return
/obj/structure/destructible/clockwork/powered/tinkerers_daemon
name = "tinkerer's daemon"
desc = "A strange machine with three small brass obelisks attached to it."
clockwork_desc = "An efficient machine that can rapidly produce components at a small power cost. It will only function if outnumbered by servants at a rate to 5:1."
icon_state = "tinkerers_daemon"
active_icon = "tinkerers_daemon"
inactive_icon = "tinkerers_daemon"
max_integrity = 100
obj_integrity = 100
break_message = "<span class='warning'>The daemon shatters into millions of pieces!</span>"
debris = list(/obj/item/clockwork/alloy_shards/large = 2, \
/obj/item/clockwork/alloy_shards/medium = 4, \
/obj/item/clockwork/alloy_shards/small = 6)
var/image/daemon_glow
var/image/component_glow
var/component_id_to_produce
var/production_time = 0 //last time we produced a component
var/production_cooldown = 120
/obj/structure/destructible/clockwork/powered/tinkerers_daemon/New()
..()
clockwork_daemons++
/obj/structure/destructible/clockwork/powered/tinkerers_daemon/Destroy()
clockwork_daemons--
return ..()
/obj/structure/destructible/clockwork/powered/tinkerers_daemon/examine(mob/user)
..()
if(is_servant_of_ratvar(user) || isobserver(user))
if(active)
if(component_id_to_produce)
user << "<span class='[get_component_span(component_id_to_produce)]_small'>It is currently producing [get_component_name(component_id_to_produce)][component_id_to_produce != "replicant_alloy" ? "s":""].</span>"
else
user << "<span class='brass'>It is currently producing random components.</span>"
user << "<span class='nezbere_small'>It will produce a component every <b>[production_cooldown*0.1]</b> seconds and requires at least the following power for each component type:</span>"
for(var/i in clockwork_component_cache)
user << "<span class='[get_component_span(i)]_small'><i>[get_component_name(i)]:</i> <b>[get_component_cost(i)]W</b> <i>([clockwork_component_cache[i]] exist[clockwork_component_cache[i] == 1 ? "s" : ""])</i></span>"
/obj/structure/destructible/clockwork/powered/tinkerers_daemon/attack_hand(mob/living/user)
if(!is_servant_of_ratvar(user))
user << "<span class='warning'>You place your hand on the daemon, but nothing happens.</span>"
return
if(active)
toggle(0, user)
else
if(!clockwork_caches)
user << "<span class='warning'>There are no clockwork caches! Activating this daemon would be a waste of power.</span>"
return
var/choice = alert(user,"Activate Daemon...",,"Specific Component","Random Component","Cancel")
switch(choice)
if("Specific Component")
var/list/components = list()
for(var/i in clockwork_component_cache)
components["[get_component_name(i)] ([get_component_cost(i)]W)"] = i
var/input_component = input(user, "Choose a component type.", name) as null|anything in components
component_id_to_produce = components[input_component]
if(!user.canUseTopic(src, BE_CLOSE) || active)
return
if(!component_id_to_produce)
user << "<span class='warning'>You decide not to select a component and activate the daemon.</span>"
return
if(total_accessable_power() < get_component_cost(component_id_to_produce))
user << "<span class='warning'>There is too little power to produce this type of component!</span>"
return
toggle(0, user)
if("Random Component")
component_id_to_produce = null
toggle(0, user)
/obj/structure/destructible/clockwork/powered/tinkerers_daemon/toggle(fast_process, mob/living/user)
. = ..()
if(active)
var/component_color = get_component_color(component_id_to_produce)
if(!daemon_glow)
daemon_glow = new('icons/obj/clockwork_objects.dmi', "tinkerglow")
daemon_glow.color = component_color
add_overlay(daemon_glow)
if(!component_glow)
component_glow = new('icons/obj/clockwork_objects.dmi', "t_[component_id_to_produce ? component_id_to_produce :"random_component"]")
else
component_glow.icon_state = "t_[component_id_to_produce ? component_id_to_produce :"random_component"]"
component_glow.color = component_color
add_overlay(component_glow)
production_time = world.time + production_cooldown //don't immediately produce when turned on afteer being off
else
cut_overlays()
/obj/structure/destructible/clockwork/powered/tinkerers_daemon/proc/get_component_cost(id)
return max(MIN_CLOCKCULT_POWER, MIN_CLOCKCULT_POWER * (1 + round(clockwork_component_cache[id] * 0.2)))
/obj/structure/destructible/clockwork/powered/tinkerers_daemon/process()
var/servants = 0
for(var/mob/living/L in living_mob_list)
if(is_servant_of_ratvar(L))
servants++
. = ..()
var/min_power_usable = 0
if(!component_id_to_produce)
for(var/i in clockwork_component_cache)
if(!min_power_usable)
min_power_usable = get_component_cost(i)
else
min_power_usable = min(min_power_usable, get_component_cost(i))
else
min_power_usable = get_component_cost(component_id_to_produce)
if(!clockwork_caches || servants * 0.2 < clockwork_daemons || . < min_power_usable) //if we don't have enough to produce the lowest or what we chose to produce, cancel out
visible_message("<span class='warning'>[src] shuts down!</span>")
toggle()
return
if(production_time <= world.time)
var/component_to_generate = component_id_to_produce
if(!component_to_generate)
component_to_generate = get_weighted_component_id() //more likely to generate components that we have less of
if(!try_use_power(get_component_cost(component_to_generate)))
component_to_generate = null
if(!component_id_to_produce)
for(var/i in clockwork_component_cache)
if(try_use_power(get_component_cost(i))) //if we fail but are producing random, try and get a different component to produce
component_to_generate = i
break
if(component_to_generate)
PoolOrNew(get_component_animation_type(component_to_generate), get_turf(src))
clockwork_component_cache[component_to_generate]++
production_time = world.time + production_cooldown //go on cooldown
visible_message("<span class='warning'>[src] hums as it produces a [get_component_name(component_to_generate)].</span>")
else
visible_message("<span class='warning'>[src] shuts down!</span>") //we shouldn't actually ever get here, as we should cancel out way before this
toggle()
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,257 @@
//////////////////
// APPLICATIONS //
//////////////////
//Sigil of Accession: Creates a sigil of accession, which is like a sigil of submission, but can convert any number of non-implanted targets and up to one implanted target.
/datum/clockwork_scripture/create_object/sigil_of_accession
descname = "Permenant Conversion Trap"
name = "Sigil of Accession"
desc = "Places a luminous sigil much like a Sigil of Submission, but it will remain even after successfully converting a non-implanted target. \
It will penetrate mindshield implants once before disappearing."
invocations = list("Divinity, enslave...", "...all who trespass here!")
channel_time = 70
required_components = list("belligerent_eye" = 3, "guvax_capacitor" = 1, "hierophant_ansible" = 1)
consumed_components = list("belligerent_eye" = 2, "guvax_capacitor" = 1, "hierophant_ansible" = 1)
whispered = TRUE
object_path = /obj/effect/clockwork/sigil/submission/accession
prevent_path = /obj/effect/clockwork/sigil/submission
creator_message = "<span class='brass'>A luminous sigil appears below you. All non-servants to cross it will be enslaved after a brief time if they do not move.</span>"
usage_tip = "It will remain after converting a target, unless that target has a mindshield implant, which it will break to convert them, but consume itself in the process."
tier = SCRIPTURE_APPLICATION
one_per_tile = TRUE
sort_priority = 1
//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 = "Damage Trap"
name = "Vitality Matrix"
desc = "Scribes a sigil beneath the invoker which drains life from any living non-servants that cross it. Servants that cross it, however, will be healed based on how much it drained from non-servants. \
Dead servants can be revived by this sigil if it has enough stored vitality."
invocations = list("Divinity...", "...steal their life...", "...for these shells!")
channel_time = 70
required_components = list("belligerent_eye" = 1, "vanguard_cogwheel" = 3, "hierophant_ansible" = 1)
consumed_components = list("belligerent_eye" = 1, "vanguard_cogwheel" = 2, "hierophant_ansible" = 1)
whispered = TRUE
object_path = /obj/effect/clockwork/sigil/vitality
creator_message = "<span class='brass'>A vitality matrix appears below you. It will drain life from non-servants and heal servants that cross it.</span>"
usage_tip = "To revive a servant, the sigil must have 20 vitality plus the target servant's non-oxygen damage. It will still heal dead servants if it lacks the vitality to outright revive them."
tier = SCRIPTURE_APPLICATION
one_per_tile = TRUE
sort_priority = 2
//Memory Allocation: Finds a willing ghost and makes them into a clockwork marauders for the invoker.
/datum/clockwork_scripture/memory_allocation
descname = "Guardian"
name = "Memory Allocation"
desc = "Allocates part of your consciousness to a Clockwork Marauder, a vigilent fighter that lives within you, able to be \
called forth by Speaking its True Name or if you become exceptionally low on health.<br> \
It gains Fatigue as it is attacked, weakening it. Marauders cannot move too far from their hosts, \
and will gain Fatigue at an increasing rate as they grow farther away. At maximum Fatigue, the marauder is forced to return to you and will be unable to manifest until its Fatigue is at zero."
invocations = list("Fright's will...", "...call forth...")
channel_time = 100
required_components = list("belligerent_eye" = 1, "vanguard_cogwheel" = 1, "guvax_capacitor" = 3)
consumed_components = list("belligerent_eye" = 1, "vanguard_cogwheel" = 1, "guvax_capacitor" = 2)
usage_tip = "Marauders are useful as personal bodyguards and frontline warriors, although they do little damage."
tier = SCRIPTURE_APPLICATION
sort_priority = 3
/datum/clockwork_scripture/memory_allocation/check_special_requirements()
for(var/mob/living/simple_animal/hostile/clockwork/marauder/M in living_mob_list)
if(M.host == invoker)
invoker << "<span class='warning'>You can only house one marauder at a time!</span>"
return FALSE
return TRUE
/datum/clockwork_scripture/memory_allocation/scripture_effects()
return create_marauder()
/datum/clockwork_scripture/memory_allocation/proc/create_marauder()
invoker.visible_message("<span class='warning'>A yellow tendril appears from [invoker]'s [slab.name] and impales itself in [invoker.p_their()] forehead!</span>", \
"<span class='heavy_brass'>A tendril flies from [slab] into your forehead. You begin waiting while it painfully rearranges your thought pattern...</span>")
invoker.notransform = TRUE //Vulnerable during the process
slab.busy = "Thought modification in process"
if(!do_after(invoker, 50, target = invoker))
invoker.visible_message("<span class='warning'>The tendril, covered in blood, retracts from [invoker]'s head and back into the [slab.name]!</span>", \
"<span class='heavy_brass'>Total agony overcomes you as the tendril is forced out early!</span>")
invoker.notransform = FALSE
invoker.Stun(5)
invoker.Weaken(5)
invoker.apply_damage(10, BRUTE, "head")
slab.busy = null
return FALSE
clockwork_say(invoker, text2ratvar("...the mind made..."))
invoker.notransform = FALSE
slab.busy = null
if(!check_special_requirements())
return FALSE
invoker << "<span class='warning'>The tendril shivers slightly as it selects a marauder...</span>"
var/list/marauder_candidates = pollCandidates("Do you want to play as the clockwork marauder of [invoker.real_name]?", ROLE_SERVANT_OF_RATVAR, null, FALSE, 100)
if(!check_special_requirements())
return FALSE
if(!marauder_candidates.len)
invoker.visible_message("<span class='warning'>The tendril retracts from [invoker]'s head, sealing the entry wound as it does so!</span>", \
"<span class='warning'>The tendril was unsuccessful! Perhaps you should try again another time.</span>")
return FALSE
clockwork_say(invoker, text2ratvar("...sword and shield!"))
var/mob/dead/observer/theghost = pick(marauder_candidates)
var/mob/living/simple_animal/hostile/clockwork/marauder/M = new(invoker)
M.key = theghost.key
M.host = invoker
M << M.playstyle_string
M << "<b>Your true name is \"[M.true_name]\". You can change this <i>once</i> by using the Change True Name verb in your Marauder tab.</b>"
add_servant_of_ratvar(M, TRUE)
invoker.visible_message("<span class='warning'>The tendril retracts from [invoker]'s head, sealing the entry wound as it does so!</span>", \
"<span class='heavy_brass'>The procedure was successful! [M.true_name], a clockwork marauder, has taken up residence in your mind. Communicate with it via the \"Linked Minds\" ability in the \
Clockwork tab.</span>")
invoker.verbs += /mob/living/proc/talk_with_marauder
return TRUE
//Anima Fragment: Creates an empty anima fragment, which produces an anima fragment that moves at extreme speed and does high damage.
/datum/clockwork_scripture/create_object/anima_fragment
descname = "Fast Soul Vessel Shell"
name = "Anima Fragment"
desc = "Creates a large shell fitted for soul vessels. Adding an active soul vessel to it results in a powerful construct with decent health, notable melee power, \
and exceptional speed, though taking damage will temporarily slow it down."
invocations = list("Call forth...", "...the soldiers of Armorer.")
channel_time = 80
required_components = list("belligerent_eye" = 1, "vanguard_cogwheel" = 1, "replicant_alloy" = 3)
consumed_components = list("belligerent_eye" = 1, "vanguard_cogwheel" = 1, "replicant_alloy" = 2)
object_path = /obj/structure/destructible/clockwork/shell/fragment
creator_message = "<span class='brass'>You form an anima fragment, a powerful soul vessel receptable.</span>"
observer_message = "<span class='warning'>The slab disgorges a puddle of black metal that expands and forms into a strange shell!</span>"
usage_tip = "Useless without a soul vessel and should not be created without one."
tier = SCRIPTURE_APPLICATION
sort_priority = 4
//Sigil of Transmission: Creates a sigil of transmission that can store power for clockwork structures.
/datum/clockwork_scripture/create_object/sigil_of_transmission
descname = "Structure Battery"
name = "Sigil of Transmission"
desc = "Scribes a sigil beneath the invoker which stores power to power clockwork structures."
invocations = list("Divinity...", "...power our creations!")
channel_time = 70
required_components = list("vanguard_cogwheel" = 1, "guvax_capacitor" = 1, "hierophant_ansible" = 3)
consumed_components = list("vanguard_cogwheel" = 1, "guvax_capacitor" = 1, "hierophant_ansible" = 2)
whispered = TRUE
object_path = /obj/effect/clockwork/sigil/transmission
creator_message = "<span class='brass'>A sigil silently appears below you. It will automatically power clockwork structures adjecent to it.</span>"
usage_tip = "Can be recharged by using Volt Void while standing on it."
tier = SCRIPTURE_APPLICATION
one_per_tile = TRUE
sort_priority = 5
//Interdiction Lens: Creates a powerful totem that disables radios and cameras and drains power into nearby sigils of transmission.
/datum/clockwork_scripture/create_object/interdiction_lens
descname = "Structure, Disables Machinery"
name = "Interdiction Lens"
desc = "Creates a clockwork totem that sabotages nearby machinery and funnels drained power into nearby Sigils of Transmission."
invocations = list("May this totem...", "...shroud the false suns!")
channel_time = 80
required_components = list("belligerent_eye" = 4, "replicant_alloy" = 1, "hierophant_ansible" = 1)
consumed_components = list("belligerent_eye" = 3, "replicant_alloy" = 1, "hierophant_ansible" = 1)
object_path = /obj/structure/destructible/clockwork/powered/interdiction_lens
creator_message = "<span class='brass'>You form an interdiction lens, which disrupts cameras and radios and drains power.</span>"
observer_message = "<span class='warning'>A brass totem rises from the ground, a purple gem appearing in its center!</span>"
invokers_required = 2
multiple_invokers_used = TRUE
usage_tip = "If it fails to funnel power into a nearby Sigil of Transmission and fails to disable even one thing, it will disable itself for two minutes."
tier = SCRIPTURE_APPLICATION
one_per_tile = TRUE
sort_priority = 6
//Mending Motor: Creates a prism that will quickly heal mechanical servants/clockwork structures and consume power or replicant alloy.
/datum/clockwork_scripture/create_object/mending_motor
descname = "Structure, Repairs Other Structures"
name = "Mending Motor"
desc = "Creates a mechanized prism that will rapidly repair damage to clockwork creatures, converted cyborgs, and clockwork structures. Requires replicant alloy or power to function."
invocations = list("May this prism...", "...mend our dents and scratches!")
channel_time = 80
required_components = list("vanguard_cogwheel" = 4, "guvax_capacitor" = 1, "replicant_alloy" = 1)
consumed_components = list("vanguard_cogwheel" = 3, "guvax_capacitor" = 1, "replicant_alloy" = 1)
object_path = /obj/structure/destructible/clockwork/powered/mending_motor/prefilled
creator_message = "<span class='brass'>You form a mending motor, which will consume power or replicant alloy to mend the wounds of mechanized servants.</span>"
observer_message = "<span class='warning'>An onyx prism forms in midair and sprouts tendrils to support itself!</span>"
invokers_required = 2
multiple_invokers_used = TRUE
usage_tip = "Powerful healing but power use is very inefficient, and its alloy use is little better."
tier = SCRIPTURE_APPLICATION
one_per_tile = TRUE
sort_priority = 7
//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 = "Structure, Area Denial"
name = "Mania Motor"
desc = "Creates a mania motor which will cause brain damage and hallucinations in nearby non-servant humans. It will also try to convert humans directly adjecent to the motor."
invocations = list("May this transmitter...", "...break the will of all who oppose us!")
channel_time = 80
required_components = list("guvax_capacitor" = 4, "replicant_alloy" = 1, "hierophant_ansible" = 1)
consumed_components = list("guvax_capacitor" = 3, "replicant_alloy" = 1, "hierophant_ansible" = 1)
object_path = /obj/structure/destructible/clockwork/powered/mania_motor
creator_message = "<span class='brass'>You form a mania motor which will cause brain damage and hallucinations in nearby humans while active.</span>"
observer_message = "<span class='warning'>A two-pronged machine rises from the ground!</span>"
invokers_required = 2
multiple_invokers_used = TRUE
usage_tip = "Eligible human servants next to the motor will be converted at an additional power cost. It will also cure hallucinations and brain damage in nearby servants."
tier = SCRIPTURE_APPLICATION
one_per_tile = TRUE
sort_priority = 8
//Tinkerer's Daemon: Creates an efficient machine that rapidly produces components at a power cost.
/datum/clockwork_scripture/create_object/tinkerers_daemon
descname = "Structure, Component Generator"
name = "Tinkerer's Daemon"
desc = "Creates a tinkerer's daemon which can rapidly collect components. It will only function if it has sufficient power, is outnumbered by servants by a ratio of 5:1, and there is at least one existing cache."
invocations = list("May this generator...", "...collect Engine parts that yet hold greatness!")
channel_time = 80
required_components = list("belligerent_eye" = 1, "guvax_capacitor" = 1, "replicant_alloy" = 4)
consumed_components = list("belligerent_eye" = 1, "guvax_capacitor" = 1, "replicant_alloy" = 3)
object_path = /obj/structure/destructible/clockwork/powered/tinkerers_daemon
creator_message = "<span class='brass'>You form a tinkerer's daemon which can rapidly collect components at a power cost.</span>"
invokers_required = 2
multiple_invokers_used = TRUE
usage_tip = "Vital to your success!"
tier = SCRIPTURE_APPLICATION
one_per_tile = TRUE
sort_priority = 9
/datum/clockwork_scripture/create_object/tinkerers_daemon/check_special_requirements()
var/servants = 0
for(var/mob/living/L in living_mob_list)
if(is_servant_of_ratvar(L))
servants++
if(servants * 0.2 < clockwork_daemons)
invoker << "<span class='nezbere'>\"Daemons are already disabled, making more of them would be a waste.\"</span>"
return FALSE
if(servants * 0.2 < clockwork_daemons+1)
invoker << "<span class='nezbere'>\"This daemon would be useless, friend.\"</span>"
return FALSE
return ..()
//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 = "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
required_components = list("vanguard_cogwheel" = 1, "replicant_alloy" = 1, "hierophant_ansible" = 4)
consumed_components = list("vanguard_cogwheel" = 1, "replicant_alloy" = 1, "hierophant_ansible" = 3)
object_path = /obj/structure/destructible/clockwork/powered/clockwork_obelisk
creator_message = "<span class='brass'>You form a clockwork obelisk which can broadcast messages or produce Spatial Gateways.</span>"
observer_message = "<span class='warning'>A brass obelisk appears handing in midair!</span>"
invokers_required = 2
multiple_invokers_used = TRUE
usage_tip = "Producing a gateway has a high power cost. Gateways to or between clockwork obelisks recieve double duration and uses."
tier = SCRIPTURE_APPLICATION
one_per_tile = TRUE
sort_priority = 10
@@ -0,0 +1,279 @@
/////////////
// DRIVERS //
/////////////
//Belligerent: Channeled for up to fifteen times over thirty seconds. Forces non-servants that can hear the chant to walk, doing minor damage. Nar-Sian cultists are burned.
/datum/clockwork_scripture/channeled/belligerent
descname = "Channeled, Area Slowdown"
name = "Belligerent"
desc = "Forces all nearby non-servants to walk rather than run, doing minor damage. Chanted every two seconds for up to thirty seconds."
chant_invocations = list("Punish their blindness!", "Take time, make slow!")
chant_amount = 15
chant_interval = 20
required_components = list("belligerent_eye" = 1)
usage_tip = "Useful for crowd control in a populated area and disrupting mass movement."
tier = SCRIPTURE_DRIVER
sort_priority = 1
var/noncultist_damage = 2 //damage per chant to noncultists
var/cultist_damage = 8 //damage per chant to non-walking cultists
/datum/clockwork_scripture/channeled/belligerent/chant_effects(chant_number)
for(var/mob/living/carbon/C in hearers(7, invoker))
var/number_legs = C.get_num_legs()
if(!is_servant_of_ratvar(C) && !C.null_rod_check() && number_legs) //you have legs right
C.apply_damage(noncultist_damage * 0.5, BURN, "l_leg")
C.apply_damage(noncultist_damage * 0.5, BURN, "r_leg")
if(C.m_intent != "walk")
if(!iscultist(C))
C << "<span class='warning'>Your leg[number_legs > 1 ? "s shiver":" shivers"] with pain!</span>"
else //Cultists take extra burn damage
C << "<span class='warning'>Your leg[number_legs > 1 ? "s burn":" burns"] with pain!</span>"
C.apply_damage(cultist_damage * 0.5, BURN, "l_leg")
C.apply_damage(cultist_damage * 0.5, BURN, "r_leg")
C.m_intent = "walk"
//Judicial Visor: Creates a judicial visor, which can smite an area.
/datum/clockwork_scripture/create_object/judicial_visor
descname = "Delayed Area Stun Glasses"
name = "Judicial Visor"
desc = "Forms a visor that, when worn, will grant the ability to smite an area, stunning, muting, and damaging the nonfaithful. \
Cultists of Nar-Sie will be set on fire, though they will be stunned for half the time."
invocations = list("Grant me the flames of Engine!")
channel_time = 10
required_components = list("belligerent_eye" = 2)
consumed_components = list("belligerent_eye" = 1)
whispered = TRUE
object_path = /obj/item/clothing/glasses/judicial_visor
creator_message = "<span class='brass'>You form a judicial visor, which is capable of smiting the unworthy.</span>"
usage_tip = "The visor has a thirty-second cooldown once used, and the marker it creates has a delay of 3 seconds before exploding."
tier = SCRIPTURE_DRIVER
space_allowed = TRUE
sort_priority = 2
//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 stunned for the equivalent of 25% of all stuns they absorbed. \
Excessive absorption will cause unconsciousness."
invocations = list("Shield me...", "...from darkness!")
channel_time = 30
required_components = list("vanguard_cogwheel" = 1)
usage_tip = "You cannot reactivate Vanguard while still shielded by it."
tier = SCRIPTURE_DRIVER
sort_priority = 3
/datum/clockwork_scripture/vanguard/check_special_requirements()
if(islist(invoker.stun_absorption) && invoker.stun_absorption["vanguard"] && invoker.stun_absorption["vanguard"]["end_time"] > world.time)
invoker << "<span class='warning'>You are already shielded by a Vanguard!</span>"
return FALSE
return TRUE
/datum/clockwork_scripture/vanguard/scripture_effects()
invoker.apply_status_effect(STATUS_EFFECT_VANGUARD)
return TRUE
//Sentinel's Compromise: Allows the invoker to select a nearby servant convert their brute and burn damage into half as much toxin damage.
/datum/clockwork_scripture/sentinels_compromise
descname = "Convert Brute/Burn to Half Toxin"
name = "Sentinel's Compromise"
desc = "Heals all brute and burn damage on a nearby living, friendly servant, but deals 50% of the damage they had as toxin damage."
invocations = list("Mend the wounds of...", "...my inferior flesh.")
channel_time = 30
required_components = list("vanguard_cogwheel" = 2)
consumed_components = list("vanguard_cogwheel" = 1)
usage_tip = "The Compromise is very fast to invoke."
tier = SCRIPTURE_DRIVER
sort_priority = 4
/datum/clockwork_scripture/sentinels_compromise/scripture_effects()
var/list/nearby_cultists = list()
for(var/mob/living/C in range(7, invoker))
if(C.stat != DEAD && is_servant_of_ratvar(C) && (C.getBruteLoss() || C.getFireLoss()))
nearby_cultists += C
if(!nearby_cultists.len)
invoker << "<span class='warning'>There are no eligible servants nearby!</span>"
return FALSE
var/mob/living/L = input(invoker, "Choose a fellow servant to heal.", name) as null|anything in nearby_cultists
if(!L || !invoker || !slab || qdeleted(slab) || !invoker.canUseTopic(slab) || !invoker.get_active_held_item() != slab || L.stat == DEAD)
return FALSE
var/brutedamage = L.getBruteLoss()
var/burndamage = L.getFireLoss()
var/totaldamage = brutedamage + burndamage
if(!totaldamage)
invoker << "<span class='warning'>[L] is not burned or bruised!</span>"
return FALSE
L.adjustToxLoss(totaldamage * 0.5)
L.adjustBruteLoss(-brutedamage)
L.adjustFireLoss(-burndamage)
var/healseverity = max(round(totaldamage*0.05, 1), 1) //shows the general severity of the damage you just healed, 1 glow per 20
var/targetturf = get_turf(L)
for(var/i in 1 to healseverity)
PoolOrNew(/obj/effect/overlay/temp/heal, list(targetturf, "#1E8CE1"))
invoker << "<span class='brass'>You bathe [L] in Inath-neq's power!</span>"
L.visible_message("<span class='warning'>A blue light washes over [L], mending [L.p_their()] bruises and burns!</span>", \
"<span class='heavy_brass'>You feel Inath-neq's power healing your wounds, but a deep nausea overcomes you!</span>")
playsound(targetturf, 'sound/magic/Staff_Healing.ogg', 50, 1)
return TRUE
//Guvax: Converts anyone adjacent to the invoker after completion, but gets gradually slower as the cult gets more dominant.
/datum/clockwork_scripture/guvax
descname = "Melee Area Convert"
name = "Guvax"
desc = "Enlists all nearby living unshielded creatures into servitude to Ratvar. Also purges holy water from nearby Servants."
invocations = list("Enlighten this heathen!", "All are insects before Engine!", "Purge all untruths and honor Engine.")
channel_time = 50
required_components = list("guvax_capacitor" = 1)
usage_tip = "Only works on those in melee range and does not penetrate mindshield implants. Much more efficient than a Sigil of Submission at low Servant amounts."
tier = SCRIPTURE_DRIVER
sort_priority = 5
/datum/clockwork_scripture/guvax/run_scripture()
var/servants = 0
for(var/mob/living/M in living_mob_list)
if(is_servant_of_ratvar(M) && (ishuman(M) || issilicon(M)))
servants++
if(servants > 5)
servants -= 5
channel_time = min(channel_time + servants*10, 200) //if above 5 servants, is much slower
return ..()
/datum/clockwork_scripture/guvax/scripture_effects()
for(var/mob/living/L in hearers(1, get_turf(invoker))) //Affects silicons
if(!is_servant_of_ratvar(L))
if(L.stat != DEAD)
add_servant_of_ratvar(L)
else
if(L.reagents && L.reagents.has_reagent("holywater"))
L.reagents.remove_reagent("holywater", 1000)
L << "<span class='heavy_brass'>Ratvar's light flares, banishing the darkness. Your devotion remains intact!</span>"
return TRUE
//Taunting Tirade: Channeled for up to five times over thirty seconds. Confuses non-servants that can hear it and allows movement for a brief time after each chant.
/datum/clockwork_scripture/channeled/taunting_tirade
descname = "Channeled, Mobile Area Confusion"
name = "Taunting Tirade"
desc = "Weakens, confuses and dizzies all nearby non-servants with a short invocation, then allows movement for five seconds. Chanted every second for up to thirty seconds."
chant_invocations = list("Hostiles on my back!", "Enemies on my trail!", "Gonna try and shake my tail.", "Bogeys on my six!")
chant_amount = 5
chant_interval = 10
required_components = list("guvax_capacitor" = 2)
consumed_components = list("guvax_capacitor" = 1)
usage_tip = "Useful for fleeing attackers, as few will be able to follow someone using this scripture."
tier = SCRIPTURE_DRIVER
sort_priority = 6
var/flee_time = 47 //allow fleeing for 5 seconds
var/grace_period = 3 //very short grace period so you don't have to stop immediately
var/datum/progressbar/progbar
/datum/clockwork_scripture/channeled/taunting_tirade/chant_effects(chant_number)
for(var/mob/living/L in hearers(7, invoker))
if(!is_servant_of_ratvar(L) && !L.null_rod_check())
L.confused = min(L.confused + 20, 100)
L.dizziness = min(L.dizziness + 20, 100)
L.Weaken(1)
invoker.visible_message("<span class='warning'>[invoker] is suddenly covered with a thin layer of dark purple smoke!</span>")
invoker.color = "#AF0AAF"
animate(invoker, color = initial(invoker.color), time = flee_time+grace_period)
if(chant_number != chant_amount) //if this is the last chant, we don't have a movement period because the chant is over
var/endtime = world.time + flee_time
var/starttime = world.time
progbar = new(invoker, flee_time, invoker)
progbar.bar.color = "#AF0AAF"
animate(progbar.bar, color = initial(progbar.bar.color), time = flee_time+grace_period)
while(world.time < endtime)
sleep(1)
progbar.update(world.time - starttime)
qdel(progbar)
sleep(grace_period)
/datum/clockwork_scripture/channeled/taunting_tirade/chant_end_effects()
qdel(progbar)
//Replicant: Creates a new clockwork slab. Doesn't use create_object because of its unique behavior.
/datum/clockwork_scripture/replicant
descname = "New Clockwork Slab"
name = "Replicant"
desc = "Creates a new clockwork slab."
invocations = list("Metal, become greater!")
channel_time = 10
required_components = list("replicant_alloy" = 1)
whispered = TRUE
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
sort_priority = 7
/datum/clockwork_scripture/replicant/scripture_effects()
invoker << "<span class='brass'>You copy a piece of replicant alloy and command it into a new slab.</span>" //No visible message, for stealth purposes
var/obj/item/clockwork/slab/S = new(get_turf(invoker))
invoker.put_in_hands(S) //Put it in your hands if possible
return TRUE
//Tinkerer's Cache: Creates a tinkerer's cache, allowing global component storage.
/datum/clockwork_scripture/create_object/tinkerers_cache
descname = "Necessary, Shares Components"
name = "Tinkerer's Cache"
desc = "Forms a cache that can store an infinite amount of components. All caches are linked and will provide components to slabs."
invocations = list("Constructing...", "...a cache!")
channel_time = 50
required_components = list("belligerent_eye" = 0, "vanguard_cogwheel" = 0, "guvax_capacitor" = 0, "replicant_alloy" = 2, "hierophant_ansible" = 0)
consumed_components = list("belligerent_eye" = 0, "vanguard_cogwheel" = 0, "guvax_capacitor" = 0, "replicant_alloy" = 1, "hierophant_ansible" = 0)
object_path = /obj/structure/destructible/clockwork/cache
creator_message = "<span class='brass'>You form a tinkerer's cache, which is capable of storing components, which will automatically be used by slabs.</span>"
observer_message = "<span class='warning'>A hollow brass spire rises and begins to blaze!</span>"
usage_tip = "Slabs will draw components from the global cache after the slab's own repositories, making caches very efficient."
tier = SCRIPTURE_DRIVER
one_per_tile = TRUE
sort_priority = 8
/datum/clockwork_scripture/create_object/tinkerers_cache/New()
var/cache_cost_increase = min(round(clockwork_caches*0.2), 5)
for(var/i in required_components)
if(i != "replicant_alloy")
required_components[i] += cache_cost_increase
for(var/i in consumed_components)
if(i != "replicant_alloy")
consumed_components[i] += cache_cost_increase
return ..()
//Wraith Spectacles: Creates a pair of wraith spectacles, which grant xray vision but damage vision slowly.
/datum/clockwork_scripture/create_object/wraith_spectacles
descname = "Xray Vision Glasses"
name = "Wraith Spectacles"
desc = "Fabricates a pair of glasses that provides true sight but quickly damage vision, eventually causing blindness if worn for too long."
invocations = list("Show the truth of this world to me!")
channel_time = 10
required_components = list("hierophant_ansible" = 1)
whispered = TRUE
object_path = /obj/item/clothing/glasses/wraith_spectacles
creator_message = "<span class='brass'>You form a pair of wraith spectacles, which will grant true sight when worn.</span>"
usage_tip = "\"True sight\" means that you are able to see through walls and in darkness."
tier = SCRIPTURE_DRIVER
space_allowed = TRUE
sort_priority = 9
//Sigil of Transgression: Creates a sigil of transgression, which stuns the first nonservant to cross it.
/datum/clockwork_scripture/create_object/sigil_of_transgression
descname = "Stun Trap"
name = "Sigil of Transgression"
desc = "Wards a tile with a sigil. The next person to cross the sigil will be smitten and unable to move. Nar-Sian cultists are stunned altogether."
invocations = list("Divinity, dazzle...", "...those who tresspass here!")
channel_time = 50
required_components = list("hierophant_ansible" = 2)
consumed_components = list("hierophant_ansible" = 1)
whispered = TRUE
object_path = /obj/effect/clockwork/sigil/transgression
creator_message = "<span class='brass'>A sigil silently appears below you. The next non-servant to cross it will be immobilized.</span>"
usage_tip = "The sigil, while fairly powerful in its stun, does not induce muteness in its victim."
tier = SCRIPTURE_DRIVER
one_per_tile = TRUE
sort_priority = 10
@@ -0,0 +1,108 @@
///////////////
// JUDGEMENT //
///////////////
//Ark of the Clockwork Justiciar: Creates a Gateway to the Celestial Derelict, either summoning ratvar or proselytizing everything.
/datum/clockwork_scripture/ark_of_the_clockwork_justiciar
descname = "Win Condition"
name = "Ark of the Clockwork Justiciar"
desc = "Pulls from the power of all of Ratvar's servants and generals to construct a massive machine used to tear apart a rift in spacetime to the Celestial Derelict. This gateway will \
call forth Ratvar from his exile after some time."
invocations = list("ARMORER! FRIGHT! AMPERAGE! VANGUARD! I CALL UPON YOU!!", \
"THE TIME HAS COME FOR OUR MASTER TO BREAK THE CHAINS OF EXILE!!", \
"LEND US YOUR AID! ENGINE COMES!!")
channel_time = 150
required_components = list("belligerent_eye" = 10, "vanguard_cogwheel" = 10, "guvax_capacitor" = 10, "replicant_alloy" = 10, "hierophant_ansible" = 10)
consumed_components = list("belligerent_eye" = 10, "vanguard_cogwheel" = 10, "guvax_capacitor" = 10, "replicant_alloy" = 10, "hierophant_ansible" = 10)
invokers_required = 5
multiple_invokers_used = TRUE
usage_tip = "The gateway is completely vulnerable to attack during its five-minute duration. It will periodically give indication of its general position to everyone on the station \
as well as being loud enough to be heard throughout the entire sector. Defend it with your life!"
tier = SCRIPTURE_JUDGEMENT
sort_priority = 1
/datum/clockwork_scripture/ark_of_the_clockwork_justiciar/New()
if(ticker && ticker.mode && ticker.mode.clockwork_objective != CLOCKCULT_GATEWAY)
invocations = list("ARMORER! FRIGHT! AMPERAGE! VANGUARD! I CALL UPON YOU!!", \
"THIS STATION WILL BE A BEACON OF HOPE IN THE DARKNESS OF SPACE!!", \
"HELP US MAKE THIS SHOW ENGINE'S GLORY!!")
..()
/datum/clockwork_scripture/ark_of_the_clockwork_justiciar/check_special_requirements()
if(!slab.no_cost)
if(ratvar_awakens)
invoker << "<span class='big_brass'>\"I am already here, idiot.\"</span>"
return FALSE
for(var/obj/structure/destructible/clockwork/massive/celestial_gateway/G in all_clockwork_objects)
var/area/gate_area = get_area(G)
invoker << "<span class='userdanger'>There is already a gateway at [gate_area.map_name]!</span>"
return FALSE
var/area/A = get_area(invoker)
var/turf/T = get_turf(invoker)
if(!T || T.z != ZLEVEL_STATION || istype(A, /area/shuttle))
invoker << "<span class='warning'>You must be on the station to activate the Ark!</span>"
return FALSE
if(clockwork_gateway_activated)
if(ticker && ticker.mode && ticker.mode.clockwork_objective != CLOCKCULT_GATEWAY)
invoker << "<span class='nezbere'>\"Look upon his works. Is it not glorious?\"</span>"
else
invoker << "<span class='warning'>Ratvar's recent banishment renders him too weak to be wrung forth from Reebe!</span>"
return FALSE
return TRUE
/datum/clockwork_scripture/ark_of_the_clockwork_justiciar/scripture_effects()
var/turf/T = get_turf(invoker)
new/obj/effect/clockwork/general_marker/inathneq(T)
if(ticker && ticker.mode && ticker.mode.clockwork_objective == CLOCKCULT_GATEWAY)
T.visible_message("<span class='inathneq'>\"[text2ratvar("Engine, come forth and show your servants your mercy!")]\"</span>")
else
T.visible_message("<span class='inathneq'>\"[text2ratvar("We will show all the mercy of Engine!")]\"</span>")
playsound(T, 'sound/magic/clockwork/invoke_general.ogg', 30, 0)
sleep(10)
if(!check_special_requirements())
return FALSE
new/obj/effect/clockwork/general_marker/sevtug(T)
if(ticker && ticker.mode && ticker.mode.clockwork_objective == CLOCKCULT_GATEWAY)
T.visible_message("<span class='sevtug'>\"[text2ratvar("Engine, come forth and show this station your decorating skills!")]\"</span>")
else
T.visible_message("<span class='sevtug'>\"[text2ratvar("We will show all Engine's decorating skills.")]\"</span>")
playsound(T, 'sound/magic/clockwork/invoke_general.ogg', 45, 0)
sleep(10)
if(!check_special_requirements())
return FALSE
new/obj/effect/clockwork/general_marker/nezbere(T)
if(ticker && ticker.mode && ticker.mode.clockwork_objective == CLOCKCULT_GATEWAY)
T.visible_message("<span class='nezbere'>\"[text2ratvar("Engine, come forth and shine your light across this realm!!")]\"</span>")
else
T.visible_message("<span class='nezbere'>\"[text2ratvar("We will show all Engine's light!!")]\"</span>")
playsound(T, 'sound/magic/clockwork/invoke_general.ogg', 60, 0)
sleep(10)
if(!check_special_requirements())
return FALSE
new/obj/effect/clockwork/general_marker/nzcrentr(T)
if(ticker && ticker.mode && ticker.mode.clockwork_objective == CLOCKCULT_GATEWAY)
T.visible_message("<span class='nzcrentr'>\"[text2ratvar("Engine, come forth.")]\"</span>")
else
T.visible_message("<span class='nezbere'>\"[text2ratvar("We will show all Engine's power!")]\"</span>")
playsound(T, 'sound/magic/clockwork/invoke_general.ogg', 75, 0)
sleep(10)
if(check_special_requirements())
var/obj/structure/destructible/clockwork/massive/celestial_gateway/CG = new/obj/structure/destructible/clockwork/massive/celestial_gateway(T)
if(ticker && ticker.mode && ticker.mode.clockwork_objective != CLOCKCULT_GATEWAY)
CG.ratvar_portal = FALSE
hierophant_message("<span class='big_brass'>This newly constructed gateway will not free Ratvar, \
and will instead simply proselytize and convert everything and everyone on the station.</span>", TRUE)
playsound(T, 'sound/magic/clockwork/invoke_general.ogg', 100, 0)
var/list/open_turfs = list()
for(var/turf/open/OT in orange(1, T))
var/list/dense_objects = list()
for(var/obj/O in OT)
if(O.density && !O.CanPass(invoker, OT, 5))
dense_objects |= O
if(!dense_objects.len)
open_turfs |= OT
if(open_turfs.len)
for(var/mob/living/L in T)
L.forceMove(pick(open_turfs)) //shove living mobs off of the gate's new location
return TRUE
return FALSE
@@ -0,0 +1,228 @@
//////////////
// REVENANT //
//////////////
//Invoke Inath-neq, the Resonant Cogwheel: Grants invulnerability and stun immunity to everyone nearby for 15 seconds.
/datum/clockwork_scripture/invoke_inathneq
descname = "Area Invuln"
name = "Invoke Inath-neq, the Resonant Cogwheel"
desc = "Taps the limitless power of Inath-neq, one of Ratvar's four generals. The benevolence of Inath-Neq will grant complete invulnerability to all servants in range for fifteen seconds."
invocations = list("I call upon you, Vanguard!!", "Let the Resonant Cogs turn once more!!", "Grant me and my allies the strength to vanquish our foes!!")
channel_time = 150
required_components = list("vanguard_cogwheel" = 6, "guvax_capacitor" = 3, "replicant_alloy" = 3, "hierophant_ansible" = 3)
consumed_components = list("vanguard_cogwheel" = 6, "guvax_capacitor" = 3, "replicant_alloy" = 3, "hierophant_ansible" = 3)
usage_tip = "Those affected by this scripture are only weak to things that outright destroy bodies, such as bombs or the singularity."
tier = SCRIPTURE_REVENANT
sort_priority = 2
var/total_duration = 150
/datum/clockwork_scripture/invoke_inathneq/check_special_requirements()
if(!slab.no_cost && clockwork_generals_invoked["inath-neq"] > world.time)
invoker << "<span class='inathneq'>\"[text2ratvar("I cannot lend you my aid yet, champion. Please be careful.")]\"</span>\n\
<span class='warning'>Inath-neq has already been invoked recently! You must wait several minutes before calling upon the Resonant Cogwheel.</span>"
return FALSE
return TRUE
/datum/clockwork_scripture/invoke_inathneq/scripture_effects()
new/obj/effect/clockwork/general_marker/inathneq(get_turf(invoker))
hierophant_message("<span class='inathneq'>[text2ratvar("Vanguard: \"I lend you my aid, champions! Let glory guide your blows!")]\"</span>", FALSE, invoker)
clockwork_generals_invoked["inath-neq"] = world.time + CLOCKWORK_GENERAL_COOLDOWN
playsound(invoker, 'sound/magic/clockwork/invoke_general.ogg', 50, 0)
if(invoker.real_name == "Lucio")
clockwork_say(invoker, text2ratvar("Aww, let's break it DOWN!!"))
for(var/mob/living/L in range(7, invoker))
if(!is_servant_of_ratvar(L) || L.stat == DEAD)
continue
L.apply_status_effect(STATUS_EFFECT_INATHNEQS_ENDOWMENT)
return TRUE
//Invoke Nezbere, the Brass Eidolon: Invokes Nezbere, bolstering the strength of many clockwork items for one minute.
/datum/clockwork_scripture/invoke_nezbere
descname = "Structure Buff"
name = "Invoke Nezbere, the Brass Eidolon"
desc = "Taps the limitless power of Nezbere, one of Ratvar's four generals. The restless toil of the Eidolon will empower a wide variety of clockwork apparatus for a full minute - notably, \
clockwork proselytizers will cost no replicant alloy to use."
invocations = list("I call upon you, Armorer!!", "Let your machinations reign on this miserable station!!", "Let your power flow through the tools of your master!!")
channel_time = 150
required_components = list("belligerent_eye" = 3, "vanguard_cogwheel" = 3, "guvax_capacitor" = 3, "replicant_alloy" = 6)
consumed_components = list("belligerent_eye" = 3, "vanguard_cogwheel" = 3, "guvax_capacitor" = 3, "replicant_alloy" = 6)
usage_tip = "Ocular wardens will become empowered, clockwork proselytizers will require no alloy, tinkerer's daemons will produce twice as quickly, \
and interdiction lenses, mending motors, mania motors, tinkerer's daemons, and clockwork obelisks will all require no power."
tier = SCRIPTURE_REVENANT
sort_priority = 3
invokers_required = 3
multiple_invokers_used = TRUE
/datum/clockwork_scripture/invoke_nezbere/check_special_requirements()
if(!slab.no_cost && clockwork_generals_invoked["nezbere"] > world.time)
invoker << "<span class='nezbere'>\"[text2ratvar("Not just yet, friend. Patience is a virtue.")]\"</span>\n\
<span class='warning'>Nezbere has already been invoked recently! You must wait several minutes before calling upon the Brass Eidolon.</span>"
return FALSE
if(!slab.no_cost && ratvar_awakens)
invoker << "<span class='nezbere'>\"[text2ratvar("Our master is here already. You do not require my help, friend.")]\"</span>\n\
<span class='warning'>Nezbere will not grant his power while Ratvar's dwarfs his own!</span>"
return FALSE
return TRUE
/datum/clockwork_scripture/invoke_nezbere/scripture_effects()
new/obj/effect/clockwork/general_marker/nezbere(get_turf(invoker))
hierophant_message("<span class='nezbere'>[text2ratvar("Armorer: \"I heed your call, champions. May your artifacts bring ruin upon the heathens that oppose our master!")]\"</span>", FALSE, invoker)
clockwork_generals_invoked["nezbere"] = world.time + CLOCKWORK_GENERAL_COOLDOWN
playsound(invoker, 'sound/magic/clockwork/invoke_general.ogg', 50, 0)
for(var/obj/structure/destructible/clockwork/ocular_warden/W in all_clockwork_objects) //Ocular wardens have increased damage and radius
W.damage_per_tick *= 1.5
W.sight_range *= 2
for(var/obj/item/clockwork/clockwork_proselytizer/P in all_clockwork_objects) //Proselytizers no longer require alloy
P.uses_alloy = FALSE
for(var/obj/structure/destructible/clockwork/powered/M in all_clockwork_objects) //Powered clockwork structures no longer need power
M.needs_power = FALSE
if(istype(M, /obj/structure/destructible/clockwork/powered/tinkerers_daemon)) //Daemons produce components twice as quickly
var/obj/structure/destructible/clockwork/powered/tinkerers_daemon/D = M
D.production_time *= 0.5
spawn(600)
for(var/obj/structure/destructible/clockwork/ocular_warden/W in all_clockwork_objects)
W.damage_per_tick = initial(W.damage_per_tick)
W.sight_range = initial(W.sight_range)
for(var/obj/item/clockwork/clockwork_proselytizer/P in all_clockwork_objects)
P.uses_alloy = initial(P.uses_alloy)
for(var/obj/structure/destructible/clockwork/powered/M in all_clockwork_objects)
M.needs_power = initial(M.needs_power)
if(istype(M, /obj/structure/destructible/clockwork/powered/tinkerers_daemon))
var/obj/structure/destructible/clockwork/powered/tinkerers_daemon/D = M
D.production_time = initial(D.production_time)
return TRUE
//Invoke Sevtug, the Formless Pariah: Causes massive global hallucinations, braindamage, confusion, and dizziness to all humans on the same zlevel.
/datum/clockwork_scripture/invoke_sevtug
descname = "Global Hallucination"
name = "Invoke Sevtug, the Formless Pariah"
desc = "Taps the limitless power of Sevtug, one of Ratvar's four generals. The mental manipulation ability of the Pariah allows its wielder to cause mass hallucinations and confusion \
for all non-servant humans on the same z-level as them. The power of this scripture falls off somewhat with distance, and certain things may reduce its effects."
invocations = list("I call upon you, Fright!!", "Let your power shatter the sanity of the weak-minded!!", "Let your tendrils hold sway over all!!")
channel_time = 150
required_components = list("belligerent_eye" = 3, "vanguard_cogwheel" = 3, "guvax_capacitor" = 6, "hierophant_ansible" = 3)
consumed_components = list("belligerent_eye" = 3, "vanguard_cogwheel" = 3, "guvax_capacitor" = 6, "hierophant_ansible" = 3)
usage_tip = "Causes brain damage, hallucinations, confusion, and dizziness in massive amounts."
tier = SCRIPTURE_REVENANT
sort_priority = 4
invokers_required = 3
multiple_invokers_used = TRUE
var/list/mindbreaksayings = list("\"Oh, great. I get to shatter some minds.\"", "\"More minds to crush.\"", \
"\"Really, this is almost boring.\"", "\"None of these minds have anything interesting in them.\"", "\"Maybe I can instill a little bit of terror in this one.\"", \
"\"What a waste of my power.\"", "\"I'm sure I could just control these minds instead, but they never ask.\"")
/datum/clockwork_scripture/invoke_sevtug/check_special_requirements()
if(!slab.no_cost && clockwork_generals_invoked["sevtug"] > world.time)
invoker << "<span class='sevtug'>\"[text2ratvar("Is it really so hard - even for a simpleton like you - to grasp the concept of waiting?")]\"</span>\n\
<span class='warning'>Sevtug has already been invoked recently! You must wait several minutes before calling upon the Formless Pariah.</span>"
return FALSE
if(!slab.no_cost && ratvar_awakens)
invoker << "<span class='sevtug'>\"[text2ratvar("Do you really think anything I can do right now will compare to Engine's power?")]\"</span>\n\
<span class='warning'>Sevtug will not grant his power while Ratvar's dwarfs his own!</span>"
return FALSE
return TRUE
/datum/clockwork_scripture/invoke_sevtug/scripture_effects()
new/obj/effect/clockwork/general_marker/sevtug(get_turf(invoker))
hierophant_message("<span class='sevtug'>[text2ratvar("Fright: \"I heed your call, idiots. Get going and use this chance while it lasts!")]\"</span>", FALSE, invoker)
clockwork_generals_invoked["sevtug"] = world.time + CLOCKWORK_GENERAL_COOLDOWN
playsound(invoker, 'sound/magic/clockwork/invoke_general.ogg', 50, 0)
var/hum = get_sfx('sound/effects/screech.ogg') //like playsound, same sound for everyone affected
var/turf/T = get_turf(invoker)
for(var/mob/living/carbon/human/H in living_mob_list)
if(H.z == invoker.z && !is_servant_of_ratvar(H))
var/distance = 0
distance += get_dist(T, get_turf(H))
var/messaged = FALSE
var/visualsdistance = max(150 - distance, 5)
var/minordistance = max(200 - distance*2, 5)
var/majordistance = max(150 - distance*3, 5)
if(H.null_rod_check())
visualsdistance = round(visualsdistance * 0.25)
minordistance = round(minordistance * 0.25)
majordistance = round(majordistance * 0.25)
H << "<span class='sevtug'>[text2ratvar("Oh, a void weapon. How annoying, I may as well not bother.")]</span>\n\
<span class='warning'>Your holy weapon glows a faint orange in an attempt to defend your mind!</span>"
messaged = TRUE
if(H.isloyal())
visualsdistance = round(visualsdistance * 0.5) //half effect for shielded targets
minordistance = round(minordistance * 0.5)
majordistance = round(majordistance * 0.5)
if(!messaged)
H << "<span class='sevtug'>[text2ratvar("Oh, look, a mindshield. Cute, I suppose I'll humor it.")]</span>"
messaged = TRUE
if(!messaged && prob(visualsdistance))
H << "<span class='sevtug'>[text2ratvar(pick(mindbreaksayings))]</span>"
H.playsound_local(T, hum, visualsdistance, 1)
flash_color(H, flash_color="#AF0AAF", flash_time=visualsdistance*10)
H.set_drugginess(visualsdistance + H.druggy)
H.dizziness = minordistance + H.dizziness
H.hallucination = minordistance + H.hallucination
H.confused = majordistance + H.confused
H.setBrainLoss(majordistance + H.getBrainLoss())
return TRUE
//Invoke Nzcrentr, the Eternal Thunderbolt: Imbues an immense amount of energy into the invoker. After several seconds, everyone near the invoker will be hit with a devastating lightning blast.
/datum/clockwork_scripture/invoke_nzcrentr
descname = "Lightning Blast"
name = "Invoke Nzcrentr, the Eternal Thunderbolt"
desc = "Taps the limitless power of Nzcrentr, one of Ratvar's four generals. The immense energy Nzcrentr wields will allow you to imbue a tiny fraction of it into your body. After several \
seconds, anyone near you will be struck by a devastating lightning bolt."
invocations = list("I call upon you, Amperage!!", "Let your energy flow through me!!", "Let your boundless power shatter stars!!")
channel_time = 150
required_components = list("belligerent_eye" = 3, "guvax_capacitor" = 3, "replicant_alloy" = 3, "hierophant_ansible" = 6)
consumed_components = list("belligerent_eye" = 3, "guvax_capacitor" = 3, "replicant_alloy" = 3, "hierophant_ansible" = 6)
usage_tip = "Struck targets will also be knocked down for about sixteen seconds."
tier = SCRIPTURE_REVENANT
sort_priority = 5
/datum/clockwork_scripture/invoke_nzcrentr/check_special_requirements()
if(!slab.no_cost && clockwork_generals_invoked["nzcrentr"] > world.time)
invoker << "<span class='nzcrentr'>\"[text2ratvar("The boss says you have to wait. Hey, do you think he would mind if I killed you? ...He would? Ok.")]\"</span>\n\
<span class='warning'>Nzcrentr has already been invoked recently! You must wait several minutes before calling upon the Forgotten Arbiter.</span>"
return FALSE
return TRUE
/datum/clockwork_scripture/invoke_nzcrentr/scripture_effects()
new/obj/effect/clockwork/general_marker/nzcrentr(get_turf(invoker))
clockwork_generals_invoked["nzcrentr"] = world.time + CLOCKWORK_GENERAL_COOLDOWN
hierophant_message("<span class='nzcrentr'>[text2ratvar("Amperage: \"[invoker.real_name] has called forth my power. Hope they do not shatter under it!")]\"</span>", FALSE, invoker)
invoker.visible_message("<span class='warning'>[invoker] begins to radiate a blinding light!</span>", \
"<span class='nzcrentr'>\"[text2ratvar("The boss says it's okay to do this. Don't blame me if you die from it.")]\"</span>\n \
<span class='userdanger'>You feel limitless power surging through you!</span>")
playsound(invoker, 'sound/magic/clockwork/invoke_general.ogg', 50, 0)
playsound(invoker, 'sound/magic/lightning_chargeup.ogg', 100, 0)
animate(invoker, color = list(rgb(255, 255, 255), rgb(255, 255, 255), rgb(255, 255, 255), rgb(0,0,0)), time = 88) //Gradual advancement to extreme brightness
sleep(88)
if(invoker)
invoker.visible_message("<span class='warning'>Massive bolts of energy emerge from across [invoker]'s body!</span>", \
"<span class='nzcrentr'>\"[text2ratvar("I told you you wouldn't be able to handle it.")]\"</span>\n \
<span class='userdanger'>TOO... MUCH! CAN'T... TAKE IT!</span>")
playsound(invoker, 'sound/magic/lightningbolt.ogg', 100, 0)
if(invoker.stat == CONSCIOUS)
animate(invoker, color = initial(invoker.color), time = 10)
for(var/mob/living/L in view(7, invoker))
if(is_servant_of_ratvar(L))
continue
invoker.Beam(L, icon_state = "nzcrentrs_power", time = 10)
var/randdamage = rand(40, 60)
if(iscarbon(L))
L.electrocute_act(randdamage, "Nzcrentr's power", 1, randdamage)
else
L.adjustFireLoss(randdamage)
L.visible_message(
"<span class='danger'>[L] was shocked by Nzcrentr's power!</span>", \
"<span class='userdanger'>You feel a powerful shock coursing through your body!</span>", \
"<span class='italics'>You hear a heavy electrical crack.</span>" \
)
L.Weaken(8)
playsound(L, 'sound/magic/LightningShock.ogg', 50, 1)
else
playsound(invoker, 'sound/magic/Disintegrate.ogg', 50, 1)
invoker.gib()
return TRUE
else
return FALSE
@@ -0,0 +1,292 @@
/////////////
// SCRIPTS //
/////////////
//Ocular Warden: Creates an ocular warden, which defends a small area near it.
/datum/clockwork_scripture/create_object/ocular_warden
descname = "Turret"
name = "Ocular Warden"
desc = "Forms an automatic short-range turret that deals low sustained damage to the unenlightened in its range."
invocations = list("Guardians...", "...of the Engine...", "...defend us!")
channel_time = 120
required_components = list("belligerent_eye" = 2, "replicant_alloy" = 1)
consumed_components = list("belligerent_eye" = 1, "replicant_alloy" = 1)
object_path = /obj/structure/destructible/clockwork/ocular_warden
creator_message = "<span class='brass'>You form an ocular warden, which will focus its searing gaze upon nearby unenlightened.</span>"
observer_message = "<span class='warning'>A brass eye takes shape and slowly rises into the air, its red iris glaring!</span>"
usage_tip = "Although powerful, the warden is very weak and should optimally be placed behind barricades."
tier = SCRIPTURE_SCRIPT
one_per_tile = TRUE
space_allowed = TRUE
sort_priority = 1
/datum/clockwork_scripture/create_object/ocular_warden/check_special_requirements()
for(var/obj/structure/destructible/clockwork/ocular_warden/W in range(3, invoker))
invoker << "<span class='alloy'>You sense another ocular warden too near this location. Placing another this close would cause them to fight.</span>" //fluff message
return FALSE
return ..()
//Cogscarab: Creates an empty cogscarab shell, which produces a cogscarab dedicated to maintaining and defending the cult.
/datum/clockwork_scripture/create_object/cogscarab
descname = "Constructor Soul Vessel Shell"
name = "Cogscarab"
desc = "Creates a small shell fitted for soul vessels. Adding an active soul vessel to it results in a small construct with tools and an inbuilt proselytizer."
invocations = list("Call forth...", "...the workers of Armorer.")
channel_time = 60
required_components = list("belligerent_eye" = 2, "hierophant_ansible" = 1)
consumed_components = list("belligerent_eye" = 1, "hierophant_ansible" = 1)
object_path = /obj/structure/destructible/clockwork/shell/cogscarab
creator_message = "<span class='brass'>You form a cogscarab, a constructor soul vessel receptable.</span>"
observer_message = "<span class='warning'>The slab disgorges a puddle of black metal that contracts and forms into a strange shell!</span>"
usage_tip = "Useless without a soul vessel and should not be created without one."
tier = SCRIPTURE_SCRIPT
sort_priority = 2
//Fellowship Armory: Arms the invoker and nearby servants with Ratvarian armor.
/datum/clockwork_scripture/fellowship_armory
descname = "Area Servant Armor"
name = "Fellowship Armory"
desc = "Equips the invoker and any nearby servants with Ratvarian armor. This armor provides high melee resistance but a weakness to lasers. \
It grows faster to invoke with more nearby servants."
invocations = list("Shield me...", "...with the...", "... fragments of Engine!")
channel_time = 110 //effectively 100 because it counts the invoker
required_components = list("vanguard_cogwheel" = 2, "replicant_alloy" = 1)
consumed_components = list("vanguard_cogwheel" = 1, "replicant_alloy" = 1)
usage_tip = "Before using, advise adjacent allies to remove their helmets, external suits, gloves, and shoes."
tier = SCRIPTURE_SCRIPT
multiple_invokers_used = TRUE
multiple_invokers_optional = TRUE
sort_priority = 4
/datum/clockwork_scripture/fellowship_armory/run_scripture()
for(var/mob/living/L in range(1, invoker))
if(is_servant_of_ratvar(L) && L.can_speak_vocal())
channel_time = max(channel_time - 10, 0)
return ..()
/datum/clockwork_scripture/fellowship_armory/scripture_effects()
for(var/mob/living/L in range(1, invoker))
if(!is_servant_of_ratvar(L))
continue
L.visible_message("<span class='warning'>Strange armor appears on [L]!</span>", "<span class='heavy_brass'>A bright shimmer runs down your body, equipping you with Ratvarian armor.</span>")
playsound(L, 'sound/magic/clockwork/fellowship_armory.ogg', 50, 1)
L.equip_to_slot_or_del(new/obj/item/clothing/head/helmet/clockwork(null), slot_head)
L.equip_to_slot_or_del(new/obj/item/clothing/suit/armor/clockwork(null), slot_wear_suit)
L.equip_to_slot_or_del(new/obj/item/clothing/gloves/clockwork(null), slot_gloves)
L.equip_to_slot_or_del(new/obj/item/clothing/shoes/clockwork(null), slot_shoes)
return TRUE
//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 = "Conversion Trap"
name = "Sigil of Submission"
desc = "Places a luminous sigil that will enslave any valid beings standing on it after a time."
invocations = list("Divinity, enlighten...", "...those who trespass here!")
channel_time = 60
required_components = list("belligerent_eye" = 1, "guvax_capacitor" = 2)
consumed_components = list("belligerent_eye" = 1, "guvax_capacitor" = 1)
whispered = TRUE
object_path = /obj/effect/clockwork/sigil/submission
creator_message = "<span class='brass'>A luminous sigil appears below you. The next non-servant to cross it will be enslaved after a brief time if they do not move.</span>"
usage_tip = "This is not a primary conversion method - use Guvax for that. It is advantageous as a trap, however, as it will transmit the name of the newly-converted."
tier = SCRIPTURE_SCRIPT
one_per_tile = TRUE
sort_priority = 5
//Soul Vessel: Creates a soul vessel, which can seek a ghost or be used on the uncovered head of a dead or dying human to take their brain.
/datum/clockwork_scripture/create_object/soul_vessel
descname = "Clockwork Posibrain"
name = "Soul Vessel"
desc = "Forms an ancient positronic brain with an overriding directive to serve Ratvar."
invocations = list("Herd the souls of...", "...the blasphemous damned!")
channel_time = 30
required_components = list("vanguard_cogwheel" = 1, "guvax_capacitor" = 2)
consumed_components = list("vanguard_cogwheel" = 1, "guvax_capacitor" = 1)
whispered = TRUE
object_path = /obj/item/device/mmi/posibrain/soul_vessel
creator_message = "<span class='brass'>You form a soul vessel, which can be used in-hand to attract spirits, or used on an unconscious or dead human to extract their consciousness.</span>"
usage_tip = "The vessel can be used as a teleport target for Spatial Gateway, though it is generally better-used by placing it in a shell."
tier = SCRIPTURE_SCRIPT
space_allowed = TRUE
sort_priority = 6
//Clockwork Proselytizer: Creates a clockwork proselytizer, used to convert objects and repair clockwork structures.
/datum/clockwork_scripture/create_object/clockwork_proselytizer
descname = "Necessary, Converts Objects"
name = "Clockwork Proselytizer"
desc = "Forms a device that, when used on certain objects, converts them into their Ratvarian equivalents. It requires replicant alloys to function."
invocations = list("With this device...", "...his presence shall be made known.")
channel_time = 20
required_components = list("guvax_capacitor" = 1, "replicant_alloy" = 2)
consumed_components = list("guvax_capacitor" = 1, "replicant_alloy" = 1)
whispered = TRUE
object_path = /obj/item/clockwork/clockwork_proselytizer/preloaded
creator_message = "<span class='brass'>You form a clockwork proselytizer, which is already pre-loaded with a small amount of replicant alloy.</span>"
usage_tip = "Clockwork walls cause adjacent tinkerer's caches to generate components passively, making them a vital tool. Clockwork floors heal servants standing on them."
tier = SCRIPTURE_SCRIPT
space_allowed = TRUE
sort_priority = 7
//Function Call: Grants the invoker the ability to call forth a Ratvarian spear that deals significant damage to silicons.
/datum/clockwork_scripture/function_call
descname = "Summonable Spear"
name = "Function Call"
desc = "Grants the invoker the ability to call forth a powerful Ratvarian spear every three minutes. The spear will deal significant damage to Nar-Sie's dogs and silicon lifeforms, but will \
vanish three minutes after being summoned."
invocations = list("Grant me...", "...the might of brass!")
channel_time = 20
required_components = list("replicant_alloy" = 2, "hierophant_ansible" = 1)
consumed_components = list("replicant_alloy" = 1, "hierophant_ansible" = 1)
whispered = TRUE
usage_tip = "You can impale human targets with the spear by pulling them, then attacking. Throwing the spear at a mob will do massive damage and stun them, but break the spear."
tier = SCRIPTURE_SCRIPT
sort_priority = 8
/datum/clockwork_scripture/function_call/check_special_requirements()
for(var/datum/action/innate/function_call/F in invoker.actions)
invoker << "<span class='warning'>You have already bound a Ratvarian spear to yourself!</span>"
return FALSE
return invoker.can_hold_items()
/datum/clockwork_scripture/function_call/scripture_effects()
invoker.visible_message("<span class='warning'>A shimmer of yellow light infuses [invoker]!</span>", \
"<span class='brass'>You bind a Ratvarian spear to yourself. Use the \"Function Call\" action button to call it forth.</span>")
var/datum/action/innate/function_call/F = new()
F.Grant(invoker)
return TRUE
//Function Call action: Calls forth a Ratvarian spear once every 3 minutes.
/datum/action/innate/function_call
name = "Function Call"
desc = "Allows you to summon a Ratvarian spear to fight enemies."
button_icon_state = "ratvarian_spear"
background_icon_state = "bg_clock"
check_flags = AB_CHECK_RESTRAINED|AB_CHECK_STUNNED|AB_CHECK_CONSCIOUS
buttontooltipstyle = "clockcult"
var/cooldown = 0
var/base_cooldown = 1800
/datum/action/innate/function_call/IsAvailable()
if(!is_servant_of_ratvar(owner) || cooldown > world.time)
return FALSE
return ..()
/datum/action/innate/function_call/Activate()
if(!owner.get_empty_held_indexes())
usr << "<span class='warning'>You need an empty to hand to call forth your spear!</span>"
return FALSE
owner.visible_message("<span class='warning'>A strange spear materializes in [owner]'s hands!</span>", "<span class='brass'>You call forth your spear!</span>")
var/obj/item/clockwork/ratvarian_spear/R = new(get_turf(usr))
owner.put_in_hands(R)
if(!ratvar_awakens)
owner << "<span class='warning'>Your spear begins to break down in this plane of existence. You can't use it for long!</span>"
addtimer(R, "break_spear", base_cooldown, FALSE)
cooldown = base_cooldown + world.time
owner.update_action_buttons_icon()
addtimer(src, "update_actions", base_cooldown, FALSE)
return TRUE
/datum/action/innate/function_call/proc/update_actions()
if(owner)
owner.update_action_buttons_icon()
//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
required_components = list("vanguard_cogwheel" = 1, "hierophant_ansible" = 2)
consumed_components = list("vanguard_cogwheel" = 1, "hierophant_ansible" = 1)
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
sort_priority = 9
/datum/clockwork_scripture/spatial_gateway/check_special_requirements()
if(!isturf(invoker.loc))
invoker << "<span class='warning'>You must not be inside an object to use this scripture!</span>"
return FALSE
var/other_servants = 0
for(var/mob/living/L in living_mob_list)
if(is_servant_of_ratvar(L) && !L.stat != DEAD)
other_servants++
for(var/obj/structure/destructible/clockwork/powered/clockwork_obelisk/O in all_clockwork_objects)
other_servants++
if(!other_servants)
invoker << "<span class='warning'>There are no other servants or clockwork obelisks!</span>"
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(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)
//Volt Void: Channeled for up to thirty times over thirty seconds. Consumes power from most power storages and deals slight burn damage to the invoker.
/datum/clockwork_scripture/channeled/volt_void
descname = "Channeled, Area Power Drain"
name = "Volt Void" //Alternative name: "On all levels but physical, I am a power sink"
desc = "Drains energy from nearby power sources, dealing burn damage if the total power consumed is above a threshhold. Channeled every second for a maximum of thirty seconds."
chant_invocations = list("Draw charge to this shell!")
chant_amount = 30
chant_interval = 10
required_components = list("guvax_capacitor" = 1, "hierophant_ansible" = 2)
consumed_components = list("guvax_capacitor" = 1, "hierophant_ansible" = 1)
usage_tip = "If standing on a Sigil of Transmission, will transfer power to it. Augumented limbs will also be healed unless above a very high threshhold."
tier = SCRIPTURE_SCRIPT
sort_priority = 10
var/total_power_drained = 0
var/power_damage_threshhold = 3000
var/augument_damage_threshhold = 6000
/datum/clockwork_scripture/channeled/volt_void/chant_effects(chant_number)
playsound(invoker, 'sound/effects/EMPulse.ogg', 50, 1)
var/power_drained = 0
for(var/atom/movable/A in view(7, invoker))
power_drained += A.power_drain(TRUE)
var/obj/effect/clockwork/sigil/transmission/ST = locate(/obj/effect/clockwork/sigil/transmission) in get_turf(invoker)
if(ST && power_drained >= 50)
var/sigil_drain = 0
while(power_drained >= 50)
ST.modify_charge(-50)
power_drained -= 50
sigil_drain += 10
power_drained += sigil_drain //readd part of the power given to the sigil to the power drained this cycle
ST.visible_message("<span class='warning'>[ST] flares a brilliant orange!</span>")
total_power_drained += power_drained
if(power_drained >= 100 && total_power_drained >= power_damage_threshhold)
var/power_damage = power_drained * 0.01
invoker.visible_message("<span class='warning'>[invoker] flares a brilliant orange!</span>", "<span class='warning'>You feel the warmth of electricity running into your body.</span>")
if(ishuman(invoker))
var/mob/living/carbon/human/H = invoker
for(var/X in H.bodyparts)
var/obj/item/bodypart/BP = X
if(ratvar_awakens || (BP.status == BODYPART_ROBOTIC && total_power_drained < augument_damage_threshhold)) //if ratvar is alive, it won't damage and will always heal augumented limbs
if(BP.heal_damage(power_damage, power_damage, 1, 0)) //heals one point of burn and brute for every ~100W drained on augumented limbs
H.update_damage_overlays()
else
if(BP.receive_damage(0, power_damage))
H.update_damage_overlays()
else if(isanimal(invoker))
var/mob/living/simple_animal/A = invoker
A.adjustHealth(-power_damage) //if a simple animal is using volt void, just heal it
return TRUE
@@ -0,0 +1,200 @@
//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"
anchored = 1
density = 1
resistance_flags = FIRE_PROOF | ACID_PROOF
var/repair_amount = 5 //how much a proselytizer can repair each cycle
var/can_be_repaired = TRUE //if a proselytizer can repair it at all
break_message = "<span class='warning'>The frog isn't a meme after all!</span>" //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
/obj/structure/destructible/clockwork/New()
..()
change_construction_value(construction_value)
all_clockwork_objects += src
/obj/structure/destructible/clockwork/Destroy()
change_construction_value(-construction_value)
all_clockwork_objects -= src
return ..()
/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)
/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(!(resistance_flags & INDESTRUCTIBLE))
var/t_It = p_they(TRUE)
var/t_is = p_are()
var/servant_message = "[t_It] [t_is] at <b>[obj_integrity]/[max_integrity]</b> integrity"
var/heavily_damaged = FALSE
var/healthpercent = (obj_integrity/max_integrity) * 100
if(healthpercent < 50)
heavily_damaged = TRUE
if(can_see_clockwork)
user << "<span class='[heavily_damaged ? "alloy":"brass"]'>[servant_message][heavily_damaged ? "!":"."]</span>"
//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
/obj/structure/destructible/clockwork/massive/New()
..()
poi_list += src
/obj/structure/destructible/clockwork/massive/Destroy()
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))
var/powered = total_accessable_power()
user << "<span class='[powered ? "brass":"alloy"]'>It has access to <b>[powered == INFINITY ? "INFINITY":"[powered]"]W</b> of power.</span>"
/obj/structure/destructible/clockwork/powered/Destroy()
SSfastprocess.processing -= src
SSobj.processing -= src
return ..()
/obj/structure/destructible/clockwork/powered/process()
var/powered = total_accessable_power()
return powered == PROCESS_KILL ? 25 : powered //make sure we don't accidentally return the arbitrary PROCESS_KILL define
/obj/structure/destructible/clockwork/powered/proc/toggle(fast_process, mob/living/user)
if(user)
if(!is_servant_of_ratvar(user))
return FALSE
user.visible_message("<span class='notice'>[user] [active ? "dis" : "en"]ables [src].</span>", "<span class='brass'>You [active ? "dis" : "en"]able [src].</span>")
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/total_accessable_power() //how much power we have and can use
if(!needs_power || ratvar_awakens)
return INFINITY //oh yeah we've got power why'd you ask
var/power = 0
power += accessable_apc_power()
power += accessable_sigil_power()
return power
/obj/structure/destructible/clockwork/powered/proc/accessable_apc_power()
var/power = 0
var/area/A = get_area(src)
var/area/targetAPCA
for(var/obj/machinery/power/apc/APC in apcs_list)
var/area/APCA = get_area(APC)
if(APCA == A)
target_apc = APC
if(target_apc)
targetAPCA = get_area(target_apc)
if(targetAPCA != A)
target_apc = null
else if(target_apc.cell)
var/apccharge = target_apc.cell.charge
if(apccharge >= MIN_CLOCKCULT_POWER)
power += apccharge
return power
/obj/structure/destructible/clockwork/powered/proc/accessable_sigil_power()
var/power = 0
for(var/obj/effect/clockwork/sigil/transmission/T in range(1, src))
power += T.power_charge
return power
/obj/structure/destructible/clockwork/powered/proc/try_use_power(amount) //try to use an amount of power
if(!needs_power || ratvar_awakens)
return 1
if(amount <= 0)
return FALSE
var/power = total_accessable_power()
if(!power || power < amount)
return FALSE
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
var/sigilpower = accessable_sigil_power()
var/list/sigils_in_range = list()
for(var/obj/effect/clockwork/sigil/transmission/T in range(1, src))
sigils_in_range |= T
while(sigilpower && amount >= MIN_CLOCKCULT_POWER)
for(var/S in sigils_in_range)
var/obj/effect/clockwork/sigil/transmission/T = S
if(amount >= MIN_CLOCKCULT_POWER && T.modify_charge(MIN_CLOCKCULT_POWER))
sigilpower -= MIN_CLOCKCULT_POWER
amount -= MIN_CLOCKCULT_POWER
var/apcpower = accessable_apc_power()
while(apcpower >= MIN_CLOCKCULT_POWER && amount >= MIN_CLOCKCULT_POWER)
if(target_apc.cell.use(MIN_CLOCKCULT_POWER))
apcpower -= MIN_CLOCKCULT_POWER
amount -= MIN_CLOCKCULT_POWER
target_apc.update()
target_apc.update_icon()
else
apcpower = 0
if(amount)
return FALSE
else
return TRUE
/obj/structure/destructible/clockwork/powered/proc/return_power(amount) //returns a given amount of power to all nearby sigils
if(amount <= 0)
return FALSE
var/list/sigils_in_range = list()
for(var/obj/effect/clockwork/sigil/transmission/T in range(1, src))
sigils_in_range |= T
if(!sigils_in_range.len)
return FALSE
while(amount >= MIN_CLOCKCULT_POWER)
for(var/S in sigils_in_range)
var/obj/effect/clockwork/sigil/transmission/T = S
if(amount >= MIN_CLOCKCULT_POWER && T.modify_charge(-MIN_CLOCKCULT_POWER))
amount -= MIN_CLOCKCULT_POWER
return TRUE
@@ -1,928 +0,0 @@
//////////////////////////
// CLOCKWORK STRUCTURES //
//////////////////////////
/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"
anchored = 1
density = 1
resistance_flags = FIRE_PROOF | ACID_PROOF
var/repair_amount = 5 //how much a proselytizer can repair each cycle
var/can_be_repaired = TRUE //if a proselytizer can repair it at all
break_message = "<span class='warning'>The frog isn't a meme after all!</span>" //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
/obj/structure/destructible/clockwork/New()
..()
change_construction_value(construction_value)
all_clockwork_objects += src
/obj/structure/destructible/clockwork/Destroy()
change_construction_value(-construction_value)
all_clockwork_objects -= src
return ..()
/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)
/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(!(resistance_flags & INDESTRUCTIBLE))
var/t_It = p_they(TRUE)
var/t_is = p_are()
var/servant_message = "[t_It] [t_is] at <b>[obj_integrity]/[max_integrity]</b> integrity"
var/heavily_damaged = FALSE
var/healthpercent = (obj_integrity/max_integrity) * 100
if(healthpercent < 50)
heavily_damaged = TRUE
if(can_see_clockwork)
user << "<span class='[heavily_damaged ? "alloy":"brass"]'>[servant_message][heavily_damaged ? "!":"."]</span>"
/obj/structure/destructible/clockwork/cache //Tinkerer's cache: Stores components for later use.
name = "tinkerer's cache"
desc = "A large brass spire with a flaming hole in its center."
clockwork_desc = "A brass container capable of storing a large amount of components.\n\
Shares components with all other caches and will gradually generate components if near a Clockwork Wall."
icon_state = "tinkerers_cache"
construction_value = 10
break_message = "<span class='warning'>The cache's fire winks out before it falls in on itself!</span>"
max_integrity = 80
obj_integrity = 80
var/wall_generation_cooldown
var/turf/closed/wall/clockwork/linkedwall //if we've got a linked wall and are producing
/obj/structure/destructible/clockwork/cache/New()
..()
START_PROCESSING(SSobj, src)
clockwork_caches++
SetLuminosity(2,1)
for(var/i in all_clockwork_mobs)
cache_check(i)
/obj/structure/destructible/clockwork/cache/Destroy()
clockwork_caches--
STOP_PROCESSING(SSobj, src)
if(linkedwall)
linkedwall.linkedcache = null
linkedwall = null
for(var/i in all_clockwork_mobs)
cache_check(i)
return ..()
/obj/structure/destructible/clockwork/cache/deconstruct(disassembled = TRUE)
if(!(flags & NODECONSTRUCT))
for(var/I in src)
var/atom/movable/A = I
A.forceMove(get_turf(src)) //drop any daemons we have
return ..()
/obj/structure/destructible/clockwork/cache/process()
for(var/turf/closed/wall/clockwork/C in view(4, src))
if(!C.linkedcache && !linkedwall)
C.linkedcache = src
linkedwall = C
wall_generation_cooldown = world.time + CACHE_PRODUCTION_TIME
visible_message("<span class='warning'>[src] starts to whirr in the presence of [C]...</span>")
break
if(linkedwall && wall_generation_cooldown <= world.time)
wall_generation_cooldown = world.time + CACHE_PRODUCTION_TIME
var/component_to_generate = get_weighted_component_id()
PoolOrNew(get_component_animation_type(component_to_generate), get_turf(src))
clockwork_component_cache[component_to_generate]++
playsound(C, 'sound/magic/clockwork/fellowship_armory.ogg', rand(15, 20), 1, -3, 1, 1)
visible_message("<span class='warning'>Something clunks around inside of [src]...</span>")
break
/obj/structure/destructible/clockwork/cache/attackby(obj/item/I, mob/living/user, params)
if(!is_servant_of_ratvar(user))
return ..()
if(istype(I, /obj/item/clockwork/component))
var/obj/item/clockwork/component/C = I
clockwork_component_cache[C.component_id]++
user << "<span class='notice'>You add [C] to [src].</span>"
user.drop_item()
qdel(C)
return 1
else if(istype(I, /obj/item/clockwork/slab))
var/obj/item/clockwork/slab/S = I
for(var/i in S.stored_components)
clockwork_component_cache[i] += S.stored_components[i]
S.stored_components[i] = 0
user.visible_message("<span class='notice'>[user] empties [S] into [src].</span>", "<span class='notice'>You offload your slab's components into [src].</span>")
return 1
else
return ..()
/obj/structure/destructible/clockwork/cache/attack_hand(mob/user)
if(!is_servant_of_ratvar(user))
return 0
if(!clockwork_component_cache["replicant_alloy"])
user << "<span class='warning'>There is no Replicant Alloy in the global component cache!</span>"
return 0
clockwork_component_cache["replicant_alloy"]--
var/obj/item/clockwork/component/replicant_alloy/A = new(get_turf(src))
user.visible_message("<span class='notice'>[user] withdraws [A] from [src].</span>", "<span class='notice'>You withdraw [A] from [src].</span>")
user.put_in_hands(A)
return 1
/obj/structure/destructible/clockwork/cache/examine(mob/user)
..()
if(is_servant_of_ratvar(user) || isobserver(user))
if(linkedwall)
user << "<span class='brass'>It is linked and will generate components!</span>"
user << "<b>Stored components:</b>"
for(var/i in clockwork_component_cache)
user << "<span class='[get_component_span(i)]_small'><i>[get_component_name(i)][i != "replicant_alloy" ? "s":""]:</i> <b>[clockwork_component_cache[i]]</b></span>"
/obj/structure/destructible/clockwork/ocular_warden //Ocular warden: Low-damage, low-range turret. Deals constant damage to whoever it makes eye contact with.
name = "ocular warden"
desc = "A large brass eye with tendrils trailing below it and a wide red iris."
clockwork_desc = "A fragile turret that will deal sustained damage to any non-faithful it sees."
icon_state = "ocular_warden"
obj_integrity = 25
max_integrity = 25
construction_value = 15
layer = HIGH_OBJ_LAYER
break_message = "<span class='warning'>The warden's eye gives a glare of utter hate before falling dark!</span>"
debris = list(/obj/item/clockwork/component/belligerent_eye/blind_eye = 1)
resistance_flags = LAVA_PROOF | FIRE_PROOF | ACID_PROOF
var/damage_per_tick = 2.5
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/New()
..()
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)
..()
user << "<span class='brass'>[target ? "<b>It's fixated on [target]!</b>" : "Its gaze is wandering aimlessly."]</span>"
/obj/structure/destructible/clockwork/ocular_warden/process()
var/list/validtargets = acquire_nearby_targets()
if(ratvar_awakens && (damage_per_tick == initial(damage_per_tick) || sight_range == initial(sight_range))) //Massive buff if Ratvar has returned
damage_per_tick = 10
sight_range = 5
if(target)
if(!(target in validtargets))
lose_target()
else
if(isliving(target))
var/mob/living/L = target
if(!L.null_rod_check())
L.adjustFireLoss(!iscultist(L) ? damage_per_tick : damage_per_tick * 2) //Nar-Sian cultists take additional damage
if(ratvar_awakens && L)
L.adjust_fire_stacks(damage_per_tick)
L.IgniteMob()
else if(istype(target,/obj/mecha))
var/obj/mecha/M = target
M.take_damage(damage_per_tick, BURN, "melee", 1, get_dir(src, M)) //does about half of standard damage to mechs * whatever their fire armor is
setDir(get_dir(get_turf(src), get_turf(target)))
if(!target)
if(validtargets.len)
target = pick(validtargets)
visible_message("<span class='warning'>[src] swivels to face [target]!</span>")
if(isliving(target))
var/mob/living/L = target
L << "<span class='heavy_brass'>\"I SEE YOU!\"</span>\n<span class='userdanger'>[src]'s gaze [ratvar_awakens ? "melts you alive" : "burns you"]!</span>"
else if(istype(target,/obj/mecha))
var/obj/mecha/M = target
M.occupant << "<span class='heavy_brass'>\"I SEE YOU!\"</span>" //heeeellooooooo, person in mech.
else if(prob(0.5)) //Extremely low chance because of how fast the subsystem it uses processes
if(prob(50))
visible_message("<span class='notice'>[src][pick(idle_messages)]</span>")
else
setDir(pick(cardinal))//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/weapon/storage/book/bible/B = L.bible_check()
if(!is_servant_of_ratvar(L) && !L.stat && L.mind && !(L.disabilities & BLIND) && !L.null_rod_check() && !B)
. += L
else if(B)
if(!(B.resistance_flags & ON_FIRE))
L << "<span class='warning'>Your [B.name] bursts into flames!</span>"
for(var/obj/item/weapon/storage/book/bible/BI in L.GetAllContents())
if(!(BI.resistance_flags & ON_FIRE))
BI.fire_act()
for(var/N in mechas_list)
var/obj/mecha/M = N
if(get_dist(M, src) <= sight_range && M.occupant && !is_servant_of_ratvar(M.occupant) && (M in view(sight_range, src)))
. += M
/obj/structure/destructible/clockwork/ocular_warden/proc/lose_target()
if(!target)
return 0
target = null
visible_message("<span class='warning'>[src] settles and seems almost disappointed.</span>")
return 1
/obj/structure/destructible/clockwork/shell
construction_value = 0
anchored = 0
density = 0
resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | ACID_PROOF
var/mobtype = /mob/living/simple_animal/hostile/clockwork
var/spawn_message = " is an error and you should yell at whoever spawned this shell."
/obj/structure/destructible/clockwork/shell/attackby(obj/item/I, mob/living/user, params)
if(istype(I, /obj/item/device/mmi/posibrain/soul_vessel))
if(!is_servant_of_ratvar(user))
..()
return 0
var/obj/item/device/mmi/posibrain/soul_vessel/S = I
if(!S.brainmob)
user << "<span class='warning'>[S] hasn't trapped a spirit! Turn it on first.</span>"
return 0
if(S.brainmob && (!S.brainmob.client || !S.brainmob.mind))
user << "<span class='warning'>[S]'s trapped spirit appears inactive!</span>"
return 0
user.visible_message("<span class='notice'>[user] places [S] in [src], where it fuses to the shell.</span>", "<span class='brass'>You place [S] in [src], fusing it to the shell.</span>")
var/mob/living/simple_animal/A = new mobtype(get_turf(src))
A.visible_message("<span class='brass'>[src][spawn_message]</span>")
S.brainmob.mind.transfer_to(A)
user.drop_item()
qdel(S)
qdel(src)
return 1
else
return ..()
/obj/structure/destructible/clockwork/shell/cogscarab
name = "cogscarab shell"
desc = "A small brass shell with a cube-shaped receptable in its center. It gives off an aura of obsessive perfectionism."
clockwork_desc = "A dormant receptable that, when powered with a soul vessel, will become a weak construct with an inbuilt proselytizer."
icon_state = "clockdrone_shell"
mobtype = /mob/living/simple_animal/drone/cogscarab
spawn_message = "'s eyes blink open, glowing bright red."
/obj/structure/destructible/clockwork/shell/fragment //Anima fragment: Useless on its own, but can accept an active soul vessel to create a powerful construct.
name = "fragment shell"
desc = "A massive brass shell with a small cube-shaped receptable in its center. It gives off an aura of contained power."
clockwork_desc = "A dormant receptable that, when powered with a soul vessel, will become a powerful construct."
icon_state = "anime_fragment"
mobtype = /mob/living/simple_animal/hostile/clockwork/fragment
spawn_message = " whirs and rises from the ground on a flickering jet of reddish fire."
/obj/structure/destructible/clockwork/wall_gear
name = "massive gear"
icon_state = "wall_gear"
climbable = TRUE
max_integrity = 50
obj_integrity = 50
desc = "A massive brass gear. You could probably secure or unsecure it with a wrench, or just climb over it."
clockwork_desc = "A massive brass gear. You could probably secure or unsecure it with a wrench, just climb over it, or proselytize it into replicant alloy."
break_message = "<span class='warning'>The gear breaks apart into shards of alloy!</span>"
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/attackby(obj/item/I, mob/user, params)
if(istype(I, /obj/item/weapon/wrench))
default_unfasten_wrench(user, I, 10)
return 1
else if(istype(I, /obj/item/stack/sheet/brass))
var/obj/item/stack/sheet/brass/W = I
if(W.get_amount() < 1)
user << "<span class='warning'>You need one brass sheet to do this!</span>"
return
var/turf/T = get_turf(src)
if(iswallturf(T))
user << "<span class='warning'>There is already a wall present!</span>"
return
if(!isfloorturf(T))
user << "<span class='warning'>A floor must be present to build a [anchored ? "false ":""]wall!</span>"
return
if(locate(/obj/structure/falsewall) in T.contents)
user << "<span class='warning'>There is already a false wall present!</span>"
return
user << "<span class='notice'>You start adding [W] to [src]...</span>"
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.ChangeTurf(/turf/closed/wall/clockwork)
else
T.ChangeTurf(/turf/open/floor/clockwork)
new /obj/structure/falsewall/brass(T)
qdel(src)
else
user << "<span class='warning'>You need more brass to make a [anchored ? "false ":""]wall!</span>"
return 1
return ..()
/obj/structure/destructible/clockwork/wall_gear/examine(mob/user)
..()
user << "<span class='notice'>[src] is [anchored ? "":"not "]secured to the floor.</span>"
///////////////////////
// CLOCKWORK EFFECTS //
///////////////////////
/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 = 1
density = 0
opacity = 0
resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | UNACIDABLE | ACID_PROOF
/obj/effect/clockwork/New()
..()
all_clockwork_objects += src
/obj/effect/clockwork/Destroy()
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)
/obj/effect/clockwork/spatial_gateway //Spatial gateway: A usually one-way rift to another location.
name = "spatial gateway"
desc = "A gently thrumming tear in reality."
clockwork_desc = "A gateway in reality."
icon_state = "spatial_gateway"
density = 1
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
/obj/effect/clockwork/spatial_gateway/New()
..()
spawn(1)
if(!linked_gateway)
qdel(src)
return 0
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."
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 0
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 1
/obj/effect/clockwork/spatial_gateway/examine(mob/user)
..()
if(is_servant_of_ratvar(user) || isobserver(user))
user << "<span class='brass'>It has [uses] uses remaining.</span>"
/obj/effect/clockwork/spatial_gateway/attack_ghost(mob/user)
if(linked_gateway)
user.forceMove(get_turf(linked_gateway))
..()
/obj/effect/clockwork/spatial_gateway/attack_hand(mob/living/user)
if(!uses)
return 0
if(user.pulling && user.a_intent == "grab" && isliving(user.pulling))
var/mob/living/L = user.pulling
if(L.buckled || L.anchored || L.has_buckled_mobs())
return 0
user.visible_message("<span class='warning'>[user] shoves [L] into [src]!</span>", "<span class='danger'>You shove [L] into [src]!</span>")
user.stop_pulling()
pass_through_gateway(L)
return 1
if(!user.canUseTopic(src))
return 0
user.visible_message("<span class='warning'>[user] climbs through [src]!</span>", "<span class='danger'>You brace yourself and step through [src]...</span>")
pass_through_gateway(user)
return 1
/obj/effect/clockwork/spatial_gateway/attackby(obj/item/I, mob/living/user, params)
if(istype(I, /obj/item/weapon/nullrod))
user.visible_message("<span class='warning'>[user] dispels [src] with [I]!</span>", "<span class='danger'>You close [src] with [I]!</span>")
qdel(linked_gateway)
qdel(src)
return 1
if(istype(I, /obj/item/clockwork/slab))
user << "<span class='heavy_brass'>\"I don't think you want to drop your slab into that\".\n\"If you really want to, try throwing it.\"</span>"
return 1
if(user.drop_item() && uses)
user.visible_message("<span class='warning'>[user] drops [I] into [src]!</span>", "<span class='danger'>You drop [I] into [src]!</span>")
pass_through_gateway(I)
..()
/obj/effect/clockwork/spatial_gateway/ex_act(severity)
if(severity == 1 && uses)
uses = 0
visible_message("<span class='warning'>[src] is disrupted!</span>")
animate(src, alpha = 0, transform = matrix()*2, time = 10)
QDEL_IN(src, 10)
linked_gateway.uses = 0
linked_gateway.visible_message("<span class='warning'>[linked_gateway] is disrupted!</span>")
animate(linked_gateway, alpha = 0, transform = matrix()*2, time = 10)
QDEL_IN(linked_gateway, 10)
return TRUE
return FALSE
/obj/effect/clockwork/spatial_gateway/Bumped(atom/A)
..()
if(isliving(A) || istype(A, /obj/item))
pass_through_gateway(A)
/obj/effect/clockwork/spatial_gateway/proc/pass_through_gateway(atom/movable/A)
if(!linked_gateway)
qdel(src)
return 0
if(!sender)
visible_message("<span class='warning'>[A] bounces off of [src]!</span>")
return 0
if(!uses)
return 0
if(isliving(A))
var/mob/living/user = A
user << "<span class='warning'><b>You pass through [src] and appear elsewhere!</b></span>"
linked_gateway.visible_message("<span class='warning'>A shape appears in [linked_gateway] before emerging!</span>")
playsound(src, 'sound/effects/EMPulse.ogg', 50, 1)
playsound(linked_gateway, 'sound/effects/EMPulse.ogg', 50, 1)
transform = matrix() * 1.5
animate(src, transform = matrix() / 1.5, time = 10)
linked_gateway.transform = matrix() * 1.5
animate(linked_gateway, transform = matrix() / 1.5, time = 10)
A.forceMove(get_turf(linked_gateway))
uses = max(0, uses - 1)
linked_gateway.uses = max(0, linked_gateway.uses - 1)
spawn(10)
if(!uses)
qdel(src)
qdel(linked_gateway)
return 1
/obj/effect/clockwork/overlay
mouse_opacity = 0
var/atom/linked
/obj/effect/clockwork/overlay/examine(mob/user)
if(linked)
linked.examine(user)
/obj/effect/clockwork/overlay/ex_act()
return FALSE
/obj/effect/clockwork/overlay/singularity_pull(S, current_size)
return
/obj/effect/clockwork/overlay/Destroy()
if(linked)
linked = null
..()
return QDEL_HINT_PUTINPOOL
/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/New()
..()
queue_smooth_neighbors(src)
addtimer(GLOBAL_PROC, "queue_smooth", 1, FALSE, src)
/obj/effect/clockwork/overlay/wall/Destroy()
queue_smooth_neighbors(src)
..()
return QDEL_HINT_QUEUE
/obj/effect/clockwork/overlay/floor
icon = 'icons/turf/floors.dmi'
icon_state = "clockwork_floor"
layer = TURF_LAYER
/obj/effect/clockwork/overlay/floor/bloodcult //this is used by BLOOD CULT, it shouldn't use such a path...
icon_state = "cult"
/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/New()
..()
animate(src, alpha = 0, time = 10)
QDEL_IN(src, 10)
/obj/effect/clockwork/general_marker/ex_act()
return FALSE
/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."
icon = 'icons/effects/340x428.dmi'
icon_state = "nezbere"
pixel_x = -154
pixel_y = -198
/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."
icon = 'icons/effects/211x247.dmi'
icon_state = "sevtug"
pixel_x = -89
pixel_y = -107
/obj/effect/clockwork/general_marker/nzcrentr
name = "Nzcrentr, the Eternal Thunderbolt"
desc = "A terrifying spiked construct crackling with limitless energy."
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/254x361.dmi'
icon_state = "nzcrentr"
pixel_x = -111
pixel_y = -164
/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/187x381.dmi'
icon_state = "inath-neq"
pixel_x = -77
pixel_y = -174
/obj/effect/clockwork/sigil //Sigils: Rune-like markings on the ground with various effects.
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/resist_string = "glows blinding white" //string for when a null rod blocks its effects, "glows [resist_string]"
/obj/effect/clockwork/sigil/attackby(obj/item/I, mob/living/user, params)
if(I.force && !is_servant_of_ratvar(user))
user.visible_message("<span class='warning'>[user] scatters [src] with [I]!</span>", "<span class='danger'>You scatter [src] with [I]!</span>")
qdel(src)
return 1
..()
/obj/effect/clockwork/sigil/attack_hand(mob/user)
if(iscarbon(user) && !user.stat && (!is_servant_of_ratvar(user) || (is_servant_of_ratvar(user) && user.a_intent == "harm")))
user.visible_message("<span class='warning'>[user] stamps out [src]!</span>", "<span class='danger'>You stomp on [src], scattering it into thousands of particles.</span>")
qdel(src)
return 1
..()
/obj/effect/clockwork/sigil/ex_act(severity)
visible_message("<span class='warning'>[src] scatters into thousands of particles.</span>")
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) || (is_servant_of_ratvar(L) && affects_servants)) && L.mind)
if(L.null_rod_check())
var/obj/item/I = L.null_rod_check()
L.visible_message("<span class='warning'>[L]'s [I.name] [resist_string], protecting them from [src]'s effects!</span>", \
"<span class='userdanger'>Your [I.name] [resist_string], protecting you!</span>")
return
sigil_effects(L)
return 1
/obj/effect/clockwork/sigil/proc/sigil_effects(mob/living/L)
/obj/effect/clockwork/sigil/transgression //Sigil of Transgression: Stuns and flashes the first non-servant to walk on it. Nar-Sian cultists are damaged and knocked down for a longer stun
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 first non-servant to cross it. Nar-Sie's dogs will be knocked down."
icon_state = "sigildull"
color = "#FAE48C"
/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))
L << "<span class='heavy_brass'>\"Watch your step, wretch.\"</span>"
L.adjustBruteLoss(10)
L.Weaken(7)
L.visible_message("<span class='warning'>[src] appears around [L] in a burst of light!</span>", \
"<span class='userdanger'>[target_flashed ? "An unseen force":"The glowing sigil around you"] holds you in place!</span>")
L.Stun(5)
PoolOrNew(/obj/effect/overlay/temp/ratvar/sigil/transgression, get_turf(src))
qdel(src)
return 1
/obj/effect/clockwork/sigil/submission //Sigil of Submission: After a short time, converts any non-servant standing on it. Knocks down and silences them for five seconds afterwards.
name = "ominous sigil"
desc = "A luminous golden sigil. Something about it really bothers you."
clockwork_desc = "A sigil that will enslave the first person to cross it, provided they remain on it for seven seconds."
icon_state = "sigilsubmission"
color = "#FAE48C"
alpha = 125
stat_affected = UNCONSCIOUS
resist_string = "glows faintly yellow"
var/convert_time = 70
var/glow_light = 2 //soft light
var/glow_falloff = 1
var/delete_on_finish = TRUE
var/sigil_name = "Sigil of Submission"
var/glow_type
/obj/effect/clockwork/sigil/submission/New()
..()
SetLuminosity(glow_light,glow_falloff)
/obj/effect/clockwork/sigil/submission/proc/post_channel(mob/living/L)
/obj/effect/clockwork/sigil/submission/sigil_effects(mob/living/L)
L.visible_message("<span class='warning'>[src] begins to glow a piercing magenta!</span>", "<span class='sevtug'>You feel something start to invade your mind...</span>")
animate(src, color = "#AF0AAF", time = convert_time)
var/obj/effect/overlay/temp/ratvar/sigil/glow
if(glow_type)
glow = PoolOrNew(glow_type, get_turf(src))
animate(glow, alpha = 255, time = convert_time)
var/I = 0
while(I < convert_time && get_turf(L) == get_turf(src))
I++
sleep(1)
if(get_turf(L) != get_turf(src))
if(glow)
qdel(glow)
animate(src, color = initial(color), time = 20)
visible_message("<span class='warning'>[src] slowly stops glowing!</span>")
return 0
post_channel(L)
if(is_eligible_servant(L))
L << "<span class='heavy_brass'>\"You belong to me now.\"</span>"
add_servant_of_ratvar(L)
L.Weaken(3) //Completely defenseless for about five seconds - mainly to give them time to read over the information they've just been presented with
L.Stun(3)
if(iscarbon(L))
var/mob/living/carbon/C = L
C.silent += 5
var/message = "[sigil_name] in [get_area(src)] <span class='sevtug'>[is_servant_of_ratvar(L) ? "successfully converted" : "failed to convert"]</span>"
for(var/M in mob_list)
if(isobserver(M))
var/link = FOLLOW_LINK(M, L)
M << "[link] <span class='heavy_brass'>[message] [L.real_name]!</span>"
else if(is_servant_of_ratvar(M))
if(M == L)
M << "<span class='heavy_brass'>[message] you!</span>"
else
M << "<span class='heavy_brass'>[message] [L.real_name]!</span>"
if(delete_on_finish)
qdel(src)
else
animate(src, color = initial(color), time = 20)
visible_message("<span class='warning'>[src] slowly stops glowing!</span>")
return 1
/obj/effect/clockwork/sigil/submission/accession //Sigil of Accession: After a short time, converts any non-servant standing on it though implants. Knocks down and silences them for five seconds afterwards.
name = "terrifying sigil"
desc = "A luminous brassy sigil. Something about it makes you want to flee."
clockwork_desc = "A sigil that will enslave any person who crosses it, provided they remain on it for seven seconds. \n\
It can convert a mindshielded target once before disppearing, but can convert any number of non-implanted targets."
icon_state = "sigiltransgression"
color = "#A97F1B"
alpha = 200
glow_light = 4 //bright light
glow_falloff = 3
delete_on_finish = FALSE
sigil_name = "Sigil of Accession"
glow_type = /obj/effect/overlay/temp/ratvar/sigil/accession
resist_string = "glows bright orange"
/obj/effect/clockwork/sigil/submission/accession/post_channel(mob/living/L)
if(L.isloyal())
var/mob/living/carbon/C = L
delete_on_finish = TRUE
C.visible_message("<span class='warning'>[C] visibly trembles!</span>", \
"<span class='sevtug'>[text2ratvar("You will be mine and his. This puny trinket will not stop me.")]</span>")
for(var/obj/item/weapon/implant/mindshield/M in C.implants)
qdel(M)
/obj/effect/clockwork/sigil/transmission
name = "suspicious sigil"
desc = "A glowing orange sigil. The air around it feels staticky."
clockwork_desc = "A sigil that will serve as a battery for clockwork structures. Use Volt Void while standing on it to charge it."
icon_state = "sigiltransmission"
color = "#EC8A2D"
alpha = 50
resist_string = "glows faintly"
var/power_charge = REPLICANT_ALLOY_POWER //starts with REPLICANT_ALLOY_POWER by default
/obj/effect/clockwork/sigil/transmission/ex_act(severity)
if(severity == 3)
modify_charge(-500)
visible_message("<span class='warning'>[src] flares a brilliant orange!</span>")
else
..()
/obj/effect/clockwork/sigil/transmission/examine(mob/user)
..()
if(is_servant_of_ratvar(user) || isobserver(user))
user << "<span class='[power_charge ? "brass":"alloy"]'>It is storing <b>[power_charge]W</b> of power.</span>"
/obj/effect/clockwork/sigil/transmission/sigil_effects(mob/living/L)
if(power_charge)
L << "<span class='brass'>You feel a slight, static shock.</span>"
return 1
/obj/effect/clockwork/sigil/transmission/New()
..()
alpha = min(initial(alpha) + power_charge*0.02, 255)
/obj/effect/clockwork/sigil/transmission/proc/modify_charge(amount)
if(power_charge - amount < 0)
return 0
power_charge -= amount
alpha = min(initial(alpha) + power_charge*0.02, 255)
return 1
/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"
color = "#123456"
alpha = 75
affects_servants = TRUE
stat_affected = DEAD
resist_string = "glows shimmering yellow"
var/vitality = 0
var/base_revive_cost = 20
var/sigil_active = FALSE
var/animation_number = 3 //each cycle increments this by 1, at 4 it produces an animation and resets
/obj/effect/clockwork/sigil/vitality/examine(mob/user)
..()
if(is_servant_of_ratvar(user) || isobserver(user))
user << "<span class='[vitality ? "inathneq_small":"alloy"]'>It is storing <b>[ratvar_awakens ? "INFINITE":"[vitality]"]</b> units of vitality.</span>"
user << "<span class='inathneq_small'>It requires at least <b>[base_revive_cost]</b> units of vitality to revive dead servants, in addition to any damage the servant has.</span>"
/obj/effect/clockwork/sigil/vitality/sigil_effects(mob/living/L)
if((is_servant_of_ratvar(L) && L.suiciding) || sigil_active)
return 0
visible_message("<span class='warning'>[src] begins to glow bright blue!</span>")
animate(src, alpha = 255, time = 10)
sleep(10)
sigil_active = TRUE
//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
while(L && (!is_servant_of_ratvar(L) || (is_servant_of_ratvar(L) && vitality)) && get_turf(L) == get_turf(src))
if(animation_number >= 4)
PoolOrNew(/obj/effect/overlay/temp/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)
vitality_drained = L.maxHealth
var/obj/effect/overlay/temp/ratvar/sigil/vitality/V = PoolOrNew(/obj/effect/overlay/temp/ratvar/sigil/vitality, get_turf(src))
animate(V, alpha = 0, transform = matrix()*2, time = 8)
playsound(L, 'sound/magic/WandODeath.ogg', 50, 1)
L.visible_message("<span class='warning'>[L] collapses in on [L.p_them()]self as [src] flares bright blue!</span>")
L << "<span class='inathneq_large'>\"[text2ratvar("Your life will not be wasted.")]\"</span>"
for(var/obj/item/W in L)
if(!L.unEquip(W))
qdel(W)
L.dust()
else
vitality_drained = L.adjustToxLoss(1.5)
if(vitality_drained)
vitality += vitality_drained
else
break
else
var/clone_to_heal = L.getCloneLoss()
var/tox_to_heal = L.getToxLoss()
var/burn_to_heal = L.getFireLoss()
var/brute_to_heal = L.getBruteLoss()
var/oxy_to_heal = L.getOxyLoss()
var/total_damage = clone_to_heal + tox_to_heal + burn_to_heal + brute_to_heal + oxy_to_heal
if(L.stat == DEAD)
var/revival_cost = base_revive_cost + total_damage - oxy_to_heal //ignores oxygen damage
if(ratvar_awakens)
revival_cost = 0
var/mob/dead/observer/ghost = L.get_ghost(TRUE)
if(ghost)
if(vitality >= revival_cost)
ghost.reenter_corpse()
L.revive(1, 1)
playsound(L, 'sound/magic/Staff_Healing.ogg', 50, 1)
L.visible_message("<span class='warning'>[L] suddenly gets back up, [L.p_their()] mouth dripping blue ichor!</span>", \
"<span class='inathneq'>\"[text2ratvar("You will be okay, child.")]\"</span>")
vitality -= revival_cost
break
else
break
if(!total_damage)
break
var/vitality_for_cycle = min(vitality, 3)
var/vitality_used = 0
if(ratvar_awakens)
vitality_for_cycle = 3
if(clone_to_heal && vitality_for_cycle)
var/healing = min(vitality_for_cycle, clone_to_heal)
vitality_for_cycle -= healing
L.adjustCloneLoss(-healing)
vitality_used += healing
if(tox_to_heal && vitality_for_cycle)
var/healing = min(vitality_for_cycle, tox_to_heal)
vitality_for_cycle -= healing
L.adjustToxLoss(-healing)
vitality_used += healing
if(burn_to_heal && vitality_for_cycle)
var/healing = min(vitality_for_cycle, burn_to_heal)
vitality_for_cycle -= healing
L.adjustFireLoss(-healing)
vitality_used += healing
if(brute_to_heal && vitality_for_cycle)
var/healing = min(vitality_for_cycle, brute_to_heal)
vitality_for_cycle -= healing
L.adjustBruteLoss(-healing)
vitality_used += healing
if(oxy_to_heal && vitality_for_cycle)
var/healing = min(vitality_for_cycle, oxy_to_heal)
vitality_for_cycle -= healing
L.adjustOxyLoss(-healing)
vitality_used += healing
if(!ratvar_awakens)
vitality -= vitality_used
sleep(2)
animation_number = initial(animation_number)
sigil_active = FALSE
animate(src, alpha = initial(alpha), time = 20)
visible_message("<span class='warning'>[src] slowly stops glowing!</span>")
@@ -1,21 +1,3 @@
/obj/structure/destructible/clockwork/massive //For objects that are typically very large
name = "massive construct"
desc = "A very large construction."
layer = MASSIVE_OBJ_LAYER
density = FALSE
resistance_flags = LAVA_PROOF | FIRE_PROOF | ACID_PROOF
/obj/structure/destructible/clockwork/massive/New()
..()
poi_list += src
/obj/structure/destructible/clockwork/massive/Destroy()
poi_list -= src
return ..()
/obj/structure/destructible/clockwork/massive/singularity_pull(S, current_size)
return
/obj/structure/destructible/clockwork/massive/celestial_gateway //The gateway to Reebe, from which Ratvar emerges
name = "Gateway to the Celestial Derelict"
desc = "A massive, thrumming rip in spacetime."
@@ -88,6 +70,28 @@
else if(GATEWAY_RATVAR_ARRIVAL - progress_in_seconds > 0)
. = "[round(max((GATEWAY_RATVAR_ARRIVAL - progress_in_seconds) / (GATEWAY_SUMMON_RATE * 0.5), 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))
user << "<span class='big'><b>Seconds until [ratvar_portal ? "Ratvar's arrival":"Proselytization"]:</b> [get_arrival_text(TRUE)]</span>"
switch(progress_in_seconds)
if(-INFINITY to GATEWAY_REEBE_FOUND)
user << "<span class='heavy_brass'>It's still opening.</span>"
if(GATEWAY_REEBE_FOUND to GATEWAY_RATVAR_COMING)
user << "<span class='heavy_brass'>It's reached the Celestial Derelict and is drawing power from it.</span>"
if(GATEWAY_RATVAR_COMING to INFINITY)
user << "<span class='heavy_brass'>[ratvar_portal ? "Ratvar is coming through the gateway":"The gateway is glowing with massed power"]!</span>"
else
switch(progress_in_seconds)
if(-INFINITY to GATEWAY_REEBE_FOUND)
user << "<span class='warning'>It's a swirling mass of blackness.</span>"
if(GATEWAY_REEBE_FOUND to GATEWAY_RATVAR_COMING)
user << "<span class='warning'>It seems to be leading somewhere.</span>"
if(GATEWAY_RATVAR_COMING to INFINITY)
user << "<span class='boldwarning'>[ratvar_portal ? "Something is coming through":"It's glowing brightly"]!</span>"
/obj/structure/destructible/clockwork/massive/celestial_gateway/process()
if(!progress_in_seconds || prob(7))
for(var/M in mob_list)
@@ -154,181 +158,10 @@
if(M.stat == CONSCIOUS)
clockwork_say(M, text2ratvar(pick("Purge all untruths and honor Engine!", "All glory to Engine's light!", "Engine's power is unmatched!")))
/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))
user << "<span class='big'><b>Seconds until [ratvar_portal ? "Ratvar's arrival":"Proselytization"]:</b> [get_arrival_text(TRUE)]</span>"
switch(progress_in_seconds)
if(-INFINITY to GATEWAY_REEBE_FOUND)
user << "<span class='heavy_brass'>It's still opening.</span>"
if(GATEWAY_REEBE_FOUND to GATEWAY_RATVAR_COMING)
user << "<span class='heavy_brass'>It's reached the Celestial Derelict and is drawing power from it.</span>"
if(GATEWAY_RATVAR_COMING to INFINITY)
user << "<span class='heavy_brass'>[ratvar_portal ? "Ratvar is coming through the gateway":"The gateway is glowing with massed power"]!</span>"
else
switch(progress_in_seconds)
if(-INFINITY to GATEWAY_REEBE_FOUND)
user << "<span class='warning'>It's a swirling mass of blackness.</span>"
if(GATEWAY_REEBE_FOUND to GATEWAY_RATVAR_COMING)
user << "<span class='warning'>It seems to be leading somewhere.</span>"
if(GATEWAY_RATVAR_COMING to INFINITY)
user << "<span class='boldwarning'>[ratvar_portal ? "Something is coming through":"It's glowing brightly"]!</span>"
/obj/effect/clockwork/overlay/gateway_glow //the actual appearance of the Gateway to the Celestial Derelict; an object so the edges of the gate can be clicked through.
//the actual appearance of the Gateway to the Celestial Derelict; 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_charging"
pixel_x = -32
pixel_y = -32
layer = MASSIVE_OBJ_LAYER
/obj/structure/destructible/clockwork/massive/ratvar
name = "Ratvar, the Clockwork Justiciar"
desc = "<span class='userdanger'>What is what is what are what real what is all a lie all a lie it's all a lie why how can what is</span>"
clockwork_desc = "<span class='large_brass'><b><i>Ratvar, the Clockwork Justiciar, your master eternal.</i></b></span>"
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
var/atom/prey //Whatever Ratvar is chasing
var/clashing = FALSE //If Ratvar is FUCKING FIGHTING WITH NAR-SIE
var/proselytize_range = 10
/obj/structure/destructible/clockwork/massive/ratvar/New()
..()
ratvar_awakens++
for(var/obj/item/clockwork/ratvarian_spear/R in all_clockwork_objects)
R.update_force()
START_PROCESSING(SSobj, src)
world << "<span class='ratvar'>\"[text2ratvar("ONCE AGAIN MY LIGHT SHALL SHINE ACROSS THIS PATHETIC REALM")]!!\"</span>"
world << 'sound/effects/ratvar_reveal.ogg'
var/image/alert_overlay = image('icons/effects/clockwork_effects.dmi', "ratvar_alert")
var/area/A = get_area(src)
notify_ghosts("The Justiciar's light calls to you! Reach out to Ratvar in [A.name] to be granted a shell to spread his glory!", null, source = src, alert_overlay = alert_overlay)
addtimer(SSshuttle.emergency, "request", 50, FALSE, null, 0.1)
/obj/structure/destructible/clockwork/massive/ratvar/Destroy()
ratvar_awakens--
for(var/obj/item/clockwork/ratvarian_spear/R in all_clockwork_objects)
R.update_force()
STOP_PROCESSING(SSobj, src)
world << "<span class='heavy_brass'><font size=6>\"NO! I will not... be...</font> <font size=5>banished...</font> <font size=4>again...\"</font></span>"
return ..()
/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" || !O)
return 0
var/mob/living/simple_animal/drone/cogscarab/ratvar/R = new/mob/living/simple_animal/drone/cogscarab/ratvar(get_turf(src))
R.visible_message("<span class='heavy_brass'>[R] forms, and its eyes blink open, glowing bright red!</span>")
R.key = O.key
/obj/structure/destructible/clockwork/massive/ratvar/Bump(atom/A)
var/turf/T = get_turf(A)
forceMove(T)
T.ratvar_act()
/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, proselytize_range))
var/turf/T = I
T.ratvar_act()
for(var/I in circleviewturfs(src, round(proselytize_range * 0.5)))
var/turf/T = I
T.ratvar_act(1)
var/dir_to_step_in = pick(cardinal)
if(!prey)
for(var/obj/singularity/narsie/N in poi_list)
if(N.z == z)
prey = N
break
if(!prey) //In case there's a Nar-Sie
var/list/meals = list()
for(var/mob/living/L in living_mob_list)
if(L.z == z && !is_servant_of_ratvar(L) && L.mind)
meals += L
if(meals.len)
prey = pick(meals)
prey << "<span class='heavy_brass'><font size=5>\"You will do.\"</font></span>\n\
<span class='userdanger'>Something very large and very malevolent begins lumbering its way towards you...</span>"
prey << 'sound/effects/ratvar_reveal.ogg'
else
if(prob(10) || is_servant_of_ratvar(prey) || prey.z != z)
prey << "<span class='heavy_brass'><font size=5>\"How dull. Leave me.\"</font></span>\n\
<span class='userdanger'>You feel tremendous relief as a set of horrible eyes loses sight of you...</span>"
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/narsie_act()
if(clashing)
return 0
clashing = TRUE
world << "<span class='heavy_brass'><font size=5>\"[pick("BLOOD GOD!!!", "NAR-SIE!!!", "AT LAST, YOUR TIME HAS COME!")]\"</font></span>"
world << "<span class='cult'><font size=5>\"<b>Ratvar?! How?!</b>\"</font></span>"
for(var/obj/singularity/narsie/N in range(15, src))
if(N.clashing)
continue
N.clashing = TRUE
clash_of_the_titans(N) //IT'S TIME FOR THE BATTLE OF THE AGES
break
return 1
/obj/structure/destructible/clockwork/massive/ratvar/proc/clash_of_the_titans(obj/singularity/narsie/narsie)
var/winner = "Undeclared"
var/base_victory_chance = 1
while(TRUE)
world << 'sound/magic/clockwork/ratvar_attack.ogg'
sleep(5.2)
for(var/mob/M in mob_list)
flash_color(M, flash_color="#966400", flash_time=1)
shake_camera(M, 4, 3)
var/ratvar_chance = min(ticker.mode.servants_of_ratvar.len, 50)
var/narsie_chance = ticker.mode.cult.len
for(var/mob/living/simple_animal/hostile/construct/harvester/C in player_list)
narsie_chance++
ratvar_chance = rand(base_victory_chance, ratvar_chance)
narsie_chance = rand(base_victory_chance, min(narsie_chance, 50))
if(ratvar_chance > narsie_chance)
winner = "Ratvar"
break
sleep(rand(2,5))
world << 'sound/magic/clockwork/narsie_attack.ogg'
sleep(7.4)
for(var/mob/M in mob_list)
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")
world << "<span class='heavy_brass'><font size=5>\"[pick("DIE! DIE! DIE!", "FILTH!!!", "SUFFER!!!", text2ratvar("ROT FOR CENTURIES AS I HAVE!!"))]\"</font></span>" //nar-sie get out
world << "<span class='cult'><font size=5>\"<b>[pick("Nooooo...", "Not die. To y-", "Die. Ratv-", "Sas tyen re-")]\"</b></font></span>"
world << 'sound/magic/clockwork/anima_fragment_attack.ogg'
world << 'sound/magic/demon_dies.ogg'
clashing = FALSE
qdel(narsie)
return 1
if("Nar-Sie")
world << "<span class='cult'><font size=5>\"<b>[pick("Ha.", "Ra'sha fonn dest.", "You fool. To come here.")]</b>\"</font></span>" //Broken English
world << 'sound/magic/demon_attack1.ogg'
world << 'sound/magic/clockwork/anima_fragment_death.ogg'
narsie.clashing = FALSE
qdel(src)
return 1
@@ -0,0 +1,47 @@
//Useless on their own, these shells can create powerful constructs.
/obj/structure/destructible/clockwork/shell
construction_value = 0
anchored = 0
density = 0
resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | ACID_PROOF
var/mobtype = /mob/living/simple_animal/hostile/clockwork
var/spawn_message = " is an error and you should yell at whoever spawned this shell."
/obj/structure/destructible/clockwork/shell/attackby(obj/item/I, mob/living/user, params)
if(istype(I, /obj/item/device/mmi/posibrain/soul_vessel))
if(!is_servant_of_ratvar(user))
..()
return 0
var/obj/item/device/mmi/posibrain/soul_vessel/S = I
if(!S.brainmob)
user << "<span class='warning'>[S] hasn't trapped a spirit! Turn it on first.</span>"
return 0
if(S.brainmob && (!S.brainmob.client || !S.brainmob.mind))
user << "<span class='warning'>[S]'s trapped spirit appears inactive!</span>"
return 0
user.visible_message("<span class='notice'>[user] places [S] in [src], where it fuses to the shell.</span>", "<span class='brass'>You place [S] in [src], fusing it to the shell.</span>")
var/mob/living/simple_animal/A = new mobtype(get_turf(src))
A.visible_message("<span class='brass'>[src][spawn_message]</span>")
S.brainmob.mind.transfer_to(A)
user.drop_item()
qdel(S)
qdel(src)
return 1
else
return ..()
/obj/structure/destructible/clockwork/shell/cogscarab
name = "cogscarab shell"
desc = "A small brass shell with a cube-shaped receptable in its center. It gives off an aura of obsessive perfectionism."
clockwork_desc = "A dormant receptable that, when powered with a soul vessel, will become a weak construct with an inbuilt proselytizer."
icon_state = "clockdrone_shell"
mobtype = /mob/living/simple_animal/drone/cogscarab
spawn_message = "'s eyes blink open, glowing bright red."
/obj/structure/destructible/clockwork/shell/fragment
name = "fragment shell"
desc = "A massive brass shell with a small cube-shaped receptable in its center. It gives off an aura of contained power."
clockwork_desc = "A dormant receptable that, when powered with a soul vessel, will become a powerful construct."
icon_state = "anime_fragment"
mobtype = /mob/living/simple_animal/hostile/clockwork/fragment
spawn_message = " whirs and rises from the ground on a flickering jet of reddish fire."
@@ -0,0 +1,69 @@
//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"
construction_value = 20
max_integrity = 150
obj_integrity = 150
break_message = "<span class='warning'>The obelisk falls to the ground, undamaged!</span>"
debris = list(/obj/item/clockwork/alloy_shards/small = 3, \
/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
var/gateway_active = FALSE
/obj/structure/destructible/clockwork/powered/clockwork_obelisk/New()
..()
toggle(1)
/obj/structure/destructible/clockwork/powered/clockwork_obelisk/examine(mob/user)
..()
if(is_servant_of_ratvar(user) || isobserver(user))
user << "<span class='nzcrentr_small'>It requires <b>[hierophant_cost]W</b> to broadcast over the Hierophant Network, and <b>[gateway_cost]W</b> to open a Spatial Gateway.</span>"
/obj/structure/destructible/clockwork/powered/clockwork_obelisk/process()
if(locate(/obj/effect/clockwork/spatial_gateway) in loc)
icon_state = active_icon
density = 0
gateway_active = TRUE
else
icon_state = inactive_icon
density = 1
gateway_active = FALSE
/obj/structure/destructible/clockwork/powered/clockwork_obelisk/attack_hand(mob/living/user)
if(!is_servant_of_ratvar(user) || !total_accessable_power() >= hierophant_cost)
user << "<span class='warning'>You place your hand on the obelisk, but it doesn't react.</span>"
return
var/choice = alert(user,"You place your hand on the obelisk...",,"Hierophant Broadcast","Spatial Gateway","Cancel")
switch(choice)
if("Hierophant Broadcast")
if(gateway_active)
user << "<span class='warning'>The obelisk is sustaining a gateway and cannot broadcast!</span>"
return
var/input = stripped_input(usr, "Please choose a message to send over the Hierophant Network.", "Hierophant Broadcast", "")
if(!input || !user.canUseTopic(src, BE_CLOSE))
return
if(gateway_active)
user << "<span class='warning'>The obelisk is sustaining a gateway and cannot broadcast!</span>"
return
if(!try_use_power(hierophant_cost))
user << "<span class='warning'>The obelisk lacks the power to broadcast!</span>"
return
clockwork_say(user, text2ratvar("Hierophant Broadcast, activate!"))
titled_hierophant_message(user, input, "big_brass", "large_brass")
if("Spatial Gateway")
if(gateway_active)
user << "<span class='warning'>The obelisk is already sustaining a gateway!</span>"
return
if(!try_use_power(gateway_cost))
user << "<span class='warning'>The obelisk lacks the power to open a gateway!</span>"
return
if(procure_gateway(user, 100, 5, 1) && !gateway_active)
clockwork_say(user, text2ratvar("Spatial Gateway, activate!"))
else
return_power(gateway_cost)
@@ -0,0 +1,96 @@
//Interdiction Lens: A powerful artifact that constantly disrupts electronics and drains power but, if it fails to find something to disrupt, turns off.
/obj/structure/destructible/clockwork/powered/interdiction_lens
name = "interdiction lens"
desc = "An ominous, double-pronged brass totem. There's a strange gemstone clasped between the pincers."
clockwork_desc = "A powerful totem that constantly drains nearby electronics and funnels the power drained into nearby Sigils of Transmission."
icon_state = "interdiction_lens"
construction_value = 25
active_icon = "interdiction_lens_active"
inactive_icon = "interdiction_lens"
break_message = "<span class='warning'>The lens flares a blinding violet before shattering!</span>"
break_sound = 'sound/effects/Glassbr3.ogg'
var/recharging = 0 //world.time when the lens was last used
var/recharge_time = 1200 //if it drains no power and affects no objects, it turns off for two minutes
var/disabled = FALSE //if it's actually usable
var/interdiction_range = 14 //how large an area it drains and disables in
/obj/structure/destructible/clockwork/powered/interdiction_lens/examine(mob/user)
..()
user << "<span class='[recharging > world.time ? "nezbere_small":"brass"]'>Its gemstone [recharging > world.time ? "has been breached by writhing tendrils of blackness that cover the totem" \
: "vibrates in place and thrums with power"].</span>"
if(is_servant_of_ratvar(user) || isobserver(user))
user << "<span class='nezbere_small'>If it fails to drain any electronics, it will disable itself for <b>[round(recharge_time/600, 1)]</b> minutes.</span>"
/obj/structure/destructible/clockwork/powered/interdiction_lens/toggle(fast_process, mob/living/user)
..()
if(active)
SetLuminosity(4,2)
else
SetLuminosity(0)
/obj/structure/destructible/clockwork/powered/interdiction_lens/attack_hand(mob/living/user)
if(user.canUseTopic(src, BE_CLOSE))
if(disabled)
user << "<span class='warning'>As you place your hand on the gemstone, cold tendrils of black matter crawl up your arm. You quickly pull back.</span>"
return 0
toggle(0, user)
/obj/structure/destructible/clockwork/powered/interdiction_lens/process()
if(recharging > world.time)
return
if(disabled)
visible_message("<span class='warning'>The writhing tendrils return to the gemstone, which begins to glow with power!</span>")
flick("interdiction_lens_recharged", src)
disabled = FALSE
toggle(0)
else
var/successfulprocess = FALSE
var/power_drained = 0
var/list/atoms_to_test = list()
for(var/A in spiral_range_turfs(interdiction_range, src))
var/turf/T = A
for(var/M in T)
atoms_to_test |= M
CHECK_TICK
for(var/M in atoms_to_test)
var/atom/movable/A = M
if(!A || qdeleted(A))
continue
power_drained += A.power_drain(TRUE)
if(istype(A, /obj/machinery/camera))
var/obj/machinery/camera/C = A
if(C.isEmpProof() || !C.status)
continue
successfulprocess = TRUE
if(C.emped)
continue
C.emp_act(1)
else if(istype(A, /obj/item/device/radio))
var/obj/item/device/radio/O = A
successfulprocess = TRUE
if(O.emped || !O.on)
continue
O.emp_act(1)
else if((isliving(A) && !is_servant_of_ratvar(A)) || istype(A, /obj/structure/closet) || istype(A, /obj/item/weapon/storage)) //other things may have radios in them but we don't care
for(var/obj/item/device/radio/O in A.GetAllContents())
successfulprocess = TRUE
if(O.emped || !O.on)
continue
O.emp_act(1)
CHECK_TICK
if(power_drained && power_drained >= MIN_CLOCKCULT_POWER && return_power(power_drained))
successfulprocess = TRUE
playsound(src, 'sound/items/PSHOOM.ogg', 50, 1, interdiction_range-7, 1)
if(!successfulprocess)
visible_message("<span class='warning'>The gemstone suddenly turns horribly dark, writhing tendrils covering it!</span>")
recharging = world.time + recharge_time
flick("interdiction_lens_discharged", src)
icon_state = "interdiction_lens_inactive"
SetLuminosity(2,1)
disabled = TRUE
@@ -0,0 +1,135 @@
//Mania Motor: A pair of antenna that, while active, cause braindamage and hallucinations 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 hallucinations and brain damage as long as it remains powered."
icon_state = "mania_motor_inactive"
active_icon = "mania_motor"
inactive_icon = "mania_motor_inactive"
construction_value = 20
max_integrity = 80
obj_integrity = 80
break_message = "<span class='warning'>The antenna break off, leaving a pile of shards!</span>"
debris = list(/obj/item/clockwork/alloy_shards/large = 1, \
/obj/item/clockwork/alloy_shards/small = 3, \
/obj/item/clockwork/component/guvax_capacitor/antennae = 1)
var/mania_cost = 200
var/convert_attempt_cost = 200
var/convert_cost = 200
var/mania_messages = list("\"Go nuts.\"", "\"Take a crack at crazy.\"", "\"Make a bid for insanity.\"", "\"Get kooky.\"", "\"Move towards mania.\"", "\"Become bewildered.\"", "\"Wax wild.\"", \
"\"Go round the bend.\"", "\"Land in lunacy.\"", "\"Try dementia.\"", "\"Strive to get a screw loose.\"")
var/compel_messages = list("\"Come closer.\"", "\"Approach the transmitter.\"", "\"Touch the antennae.\"", "\"I always have to deal with idiots. Move towards the mania motor.\"", \
"\"Advance forward and place your head between the antennae - that's all it's good for.\"", "\"If you were smarter, you'd be over here already.\"", "\"Move FORWARD, you fool.\"")
var/convert_messages = list("\"You won't do. Go to sleep while I tell these nitwits how to convert you.\"", "\"You are insufficient. I must instruct these idiots in the art of conversion.\"", \
"\"Oh of course, someone we can't convert. These servants are fools.\"", "\"How hard is it to use a Sigil, anyway? All it takes is dragging someone onto it.\"", \
"\"How do they fail to use a Sigil of Accession, anyway?\"", "\"Why is it that all servants are this inept?\"", "\"It's quite likely you'll be stuck here for a while.\"")
var/close_messages = list("\"Well, you can't reach the motor from THERE, you moron.\"", "\"Interesting location. I'd prefer if you went somewhere you could ACTUALLY TOUCH THE ANTENNAE!\"", \
"\"Amazing. You somehow managed to wedge yourself somewhere you can't actually reach the motor from.\"", "\"Such a show of idiocy is unparalleled. Perhaps I should put you on display?\"", \
"\"Did you do this on purpose? I can't imagine you doing so accidentally. Oh, wait, I can.\"", "\"How is it that such smart creatures can still do something AS STUPID AS THIS!\"")
/obj/structure/destructible/clockwork/powered/mania_motor/examine(mob/user)
..()
if(is_servant_of_ratvar(user) || isobserver(user))
user << "<span class='sevtug_small'>It requires <b>[mania_cost]W</b> to run, and <b>[convert_attempt_cost + convert_cost]W</b> to convert humans adjecent to it.</span>"
/obj/structure/destructible/clockwork/powered/mania_motor/process()
if(try_use_power(mania_cost))
var/turf/T = get_turf(src)
var/hum = get_sfx('sound/effects/screech.ogg') //like playsound, same sound for everyone affected
for(var/mob/living/carbon/human/H in view(1, src))
if(is_servant_of_ratvar(H))
continue
if(H.Adjacent(src) && try_use_power(convert_attempt_cost))
if(is_eligible_servant(H) && try_use_power(convert_cost))
H << "<span class='sevtug'>\"[text2ratvar("You are mine and his, now.")]\"</span>"
H.playsound_local(T, hum, 80, 1)
add_servant_of_ratvar(H)
else if(!H.stat)
if(H.getBrainLoss() >= 100)
H.Paralyse(5)
H << "<span class='sevtug'>[text2ratvar(pick(convert_messages))]</span>"
else
H.adjustBrainLoss(100)
H.visible_message("<span class='warning'>[H] reaches out and touches [src].</span>", "<span class='sevtug'>You touch [src] involuntarily.</span>")
else
visible_message("<span class='warning'>[src]'s antennae fizzle quietly.</span>")
playsound(src, 'sound/effects/light_flicker.ogg', 50, 1)
for(var/mob/living/carbon/human/H in range(10, src))
if(is_servant_of_ratvar(H))
if(H.getBrainLoss() || H.hallucination || H.druggy || H.dizziness || H.confused)
H.adjustBrainLoss(-H.getBrainLoss()) //heals servants of braindamage, hallucination, druggy, dizziness, and confusion
H.hallucination = 0
H.adjust_drugginess(-H.druggy)
H.dizziness = 0
H.confused = 0
else if(!H.null_rod_check() && H.stat == CONSCIOUS)
var/distance = get_dist(T, get_turf(H))
var/falloff_distance = min((110) - distance * 10, 80)
var/sound_distance = falloff_distance * 0.5
var/targetbrainloss = H.getBrainLoss()
if(distance >= 4 && prob(falloff_distance * 0.5))
H << "<span class='sevtug_small'>[text2ratvar(pick(mania_messages))]</span>"
H.playsound_local(T, hum, sound_distance, 1)
switch(distance)
if(2 to 3)
if(prob(falloff_distance * 0.5))
if(prob(falloff_distance))
H << "<span class='sevtug_small'>[text2ratvar(pick(mania_messages))]</span>"
else
H << "<span class='sevtug'>[text2ratvar(pick(compel_messages))]</span>"
if(targetbrainloss <= 50)
H.adjustBrainLoss(50 - targetbrainloss) //got too close had brain eaten
H.adjust_drugginess(Clamp(7, 0, 100 - H.druggy))
H.hallucination = min(H.hallucination + 7, 100)
H.dizziness = min(H.dizziness + 3, 45)
H.confused = min(H.confused + 3, 45)
if(4 to 5)
if(targetbrainloss <= 50)
H.adjustBrainLoss(1)
H.adjust_drugginess(Clamp(5, 0, 80 - H.druggy))
H.hallucination = min(H.hallucination + 5, 80)
H.dizziness = min(H.dizziness + 2, 30)
H.confused = min(H.confused + 2, 30)
if(6 to 7)
if(targetbrainloss <= 30)
H.adjustBrainLoss(1)
H.adjust_drugginess(Clamp(2, 0, 60 - H.druggy))
H.hallucination = min(H.hallucination + 2, 60)
H.dizziness = min(H.dizziness + 2, 15)
H.confused = min(H.confused + 2, 15)
if(8 to 9)
if(targetbrainloss <= 10)
H.adjustBrainLoss(1)
H.adjust_drugginess(Clamp(2, 0, 40 - H.druggy))
H.hallucination = min(H.hallucination + 2, 40)
if(10 to INFINITY)
H.adjust_drugginess(Clamp(2, 0, 20 - H.druggy))
H.hallucination = min(H.hallucination + 2, 20)
else //if it's a distance of 1 and they can't see it/aren't adjacent or they're on top of it(how'd they get on top of it and still trigger this???)
if(prob(falloff_distance * 0.5))
if(prob(falloff_distance))
H << "<span class='sevtug'>[text2ratvar(pick(compel_messages))]</span>"
else if(prob(falloff_distance * 0.5))
H << "<span class='sevtug'>[text2ratvar(pick(close_messages))]</span>"
else
H << "<span class='sevtug_small'>[text2ratvar(pick(mania_messages))]</span>"
if(targetbrainloss <= 99)
H.adjustBrainLoss(99 - targetbrainloss)
H.adjust_drugginess(Clamp(10, 0, 150 - H.druggy))
H.hallucination = min(H.hallucination + 10, 150)
H.dizziness = min(H.dizziness + 5, 60)
H.confused = min(H.confused + 5, 60)
else
visible_message("<span class='warning'>[src] hums loudly, then the sockets at its base fall dark!</span>")
playsound(src, 'sound/effects/screech.ogg', 40, 1)
toggle(0)
/obj/structure/destructible/clockwork/powered/mania_motor/attack_hand(mob/living/user)
if(user.canUseTopic(src, BE_CLOSE) && is_servant_of_ratvar(user))
if(!total_accessable_power() >= mania_cost)
user << "<span class='warning'>[src] needs more power to function!</span>"
return 0
toggle(0, user)
@@ -0,0 +1,105 @@
//Mending Motor: A prism that consumes replicant alloy or power to repair nearby mechanical servants at a quick rate.
/obj/structure/destructible/clockwork/powered/mending_motor
name = "mending motor"
desc = "A dark onyx prism, held in midair by spiraling tendrils of stone."
clockwork_desc = "A powerful prism that rapidly repairs nearby mechanical servants and clockwork structures."
icon_state = "mending_motor_inactive"
active_icon = "mending_motor"
inactive_icon = "mending_motor_inactive"
construction_value = 20
max_integrity = 125
obj_integrity = 125
break_message = "<span class='warning'>The prism collapses with a heavy thud!</span>"
debris = list(/obj/item/clockwork/alloy_shards/small = 5, \
/obj/item/clockwork/alloy_shards/medium = 1, \
/obj/item/clockwork/alloy_shards/large = 1, \
/obj/item/clockwork/component/vanguard_cogwheel = 1)
var/stored_alloy = 0
var/max_alloy = REPLICANT_ALLOY_POWER * 10
var/mob_cost = 200
var/structure_cost = 250
var/cyborg_cost = 300
/obj/structure/destructible/clockwork/powered/mending_motor/prefilled
stored_alloy = REPLICANT_ALLOY_POWER //starts with 1 replicant alloy's worth of power
/obj/structure/destructible/clockwork/powered/mending_motor/total_accessable_power()
. = ..()
if(. != INFINITY)
. += accessable_alloy_power()
/obj/structure/destructible/clockwork/powered/mending_motor/proc/accessable_alloy_power()
return stored_alloy
/obj/structure/destructible/clockwork/powered/mending_motor/use_power(amount)
var/alloypower = accessable_alloy_power()
while(alloypower >= MIN_CLOCKCULT_POWER && amount >= MIN_CLOCKCULT_POWER)
stored_alloy -= MIN_CLOCKCULT_POWER
alloypower -= MIN_CLOCKCULT_POWER
amount -= MIN_CLOCKCULT_POWER
return ..()
/obj/structure/destructible/clockwork/powered/mending_motor/examine(mob/user)
..()
if(is_servant_of_ratvar(user) || isobserver(user))
user << "<span class='alloy'>It contains <b>[stored_alloy*CLOCKCULT_POWER_TO_ALLOY_MULTIPLIER]/[max_alloy*CLOCKCULT_POWER_TO_ALLOY_MULTIPLIER]</b> units of liquified alloy, \
which is equivalent to <b>[stored_alloy]W/[max_alloy]W</b> of power.</span>"
user << "<span class='inathneq_small'>It requires <b>[mob_cost]W</b> to heal clockwork mobs, <b>[structure_cost]W</b> for clockwork structures, and <b>[cyborg_cost]W</b> for cyborgs.</span>"
/obj/structure/destructible/clockwork/powered/mending_motor/process()
if(..() < mob_cost)
visible_message("<span class='warning'>[src] emits an airy chuckling sound and falls dark!</span>")
toggle()
return
for(var/atom/movable/M in range(5, src))
if(isclockmob(M) || istype(M, /mob/living/simple_animal/drone/cogscarab))
var/mob/living/simple_animal/hostile/clockwork/W = M
var/fatigued = FALSE
if(istype(M, /mob/living/simple_animal/hostile/clockwork/marauder))
var/mob/living/simple_animal/hostile/clockwork/marauder/E = M
if(E.fatigue)
fatigued = TRUE
if((!fatigued && W.health == W.maxHealth) || W.stat)
continue
if(!try_use_power(mob_cost))
break
W.adjustHealth(-20)
else if(istype(M, /obj/structure/destructible/clockwork))
var/obj/structure/destructible/clockwork/C = M
if(C.obj_integrity == C.max_integrity)
continue
if(!try_use_power(structure_cost))
break
C.obj_integrity = min(C.obj_integrity + 20, C.max_integrity)
else if(issilicon(M))
var/mob/living/silicon/S = M
if(S.health == S.maxHealth || S.stat == DEAD || !is_servant_of_ratvar(S))
continue
if(!try_use_power(cyborg_cost))
break
S.adjustBruteLoss(-20)
S.adjustFireLoss(-10)
return 1
/obj/structure/destructible/clockwork/powered/mending_motor/attack_hand(mob/living/user)
if(user.canUseTopic(src, BE_CLOSE))
if(total_accessable_power() < mob_cost)
user << "<span class='warning'>[src] needs more power or replicant alloy to function!</span>"
return 0
toggle(0, user)
/obj/structure/destructible/clockwork/powered/mending_motor/attackby(obj/item/I, mob/user, params)
if(istype(I, /obj/item/clockwork/component/replicant_alloy) && is_servant_of_ratvar(user))
if(stored_alloy + REPLICANT_ALLOY_POWER > max_alloy)
user << "<span class='warning'>[src] is too full to accept any more alloy!</span>"
return 0
playsound(user, 'sound/machines/click.ogg', 50, 1)
clockwork_say(user, text2ratvar("Transmute into fuel."), TRUE)
user << "<span class='brass'>You force [I] to liquify and pour it into [src]'s compartments. \
It now contains <b>[stored_alloy*CLOCKCULT_POWER_TO_ALLOY_MULTIPLIER]/[max_alloy*CLOCKCULT_POWER_TO_ALLOY_MULTIPLIER]</b> units of liquified alloy.</span>"
stored_alloy = stored_alloy + REPLICANT_ALLOY_POWER
user.drop_item()
qdel(I)
return 1
else
return ..()
@@ -0,0 +1,90 @@
//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 that will deal sustained damage to any non-faithful it sees."
icon_state = "ocular_warden"
obj_integrity = 25
max_integrity = 25
construction_value = 15
layer = HIGH_OBJ_LAYER
break_message = "<span class='warning'>The warden's eye gives a glare of utter hate before falling dark!</span>"
debris = list(/obj/item/clockwork/component/belligerent_eye/blind_eye = 1)
resistance_flags = LAVA_PROOF | FIRE_PROOF | ACID_PROOF
var/damage_per_tick = 2.5
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/New()
..()
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)
..()
user << "<span class='brass'>[target ? "<b>It's fixated on [target]!</b>" : "Its gaze is wandering aimlessly."]</span>"
/obj/structure/destructible/clockwork/ocular_warden/process()
var/list/validtargets = acquire_nearby_targets()
if(ratvar_awakens && (damage_per_tick == initial(damage_per_tick) || sight_range == initial(sight_range))) //Massive buff if Ratvar has returned
damage_per_tick = 10
sight_range = 5
if(target)
if(!(target in validtargets))
lose_target()
else
if(isliving(target))
var/mob/living/L = target
if(!L.null_rod_check())
L.adjustFireLoss(!iscultist(L) ? damage_per_tick : damage_per_tick * 2) //Nar-Sian cultists take additional damage
if(ratvar_awakens && L)
L.adjust_fire_stacks(damage_per_tick)
L.IgniteMob()
else if(istype(target,/obj/mecha))
var/obj/mecha/M = target
M.take_damage(damage_per_tick, BURN, "melee", 1, get_dir(src, M)) //does about half of standard damage to mechs * whatever their fire armor is
setDir(get_dir(get_turf(src), get_turf(target)))
if(!target)
if(validtargets.len)
target = pick(validtargets)
visible_message("<span class='warning'>[src] swivels to face [target]!</span>")
if(isliving(target))
var/mob/living/L = target
L << "<span class='heavy_brass'>\"I SEE YOU!\"</span>\n<span class='userdanger'>[src]'s gaze [ratvar_awakens ? "melts you alive" : "burns you"]!</span>"
else if(istype(target,/obj/mecha))
var/obj/mecha/M = target
M.occupant << "<span class='heavy_brass'>\"I SEE YOU!\"</span>" //heeeellooooooo, person in mech.
else if(prob(0.5)) //Extremely low chance because of how fast the subsystem it uses processes
if(prob(50))
visible_message("<span class='notice'>[src][pick(idle_messages)]</span>")
else
setDir(pick(cardinal))//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/weapon/storage/book/bible/B = L.bible_check()
if(!is_servant_of_ratvar(L) && !L.stat && L.mind && !(L.disabilities & BLIND) && !L.null_rod_check() && !B)
. += L
else if(B)
if(!(B.resistance_flags & ON_FIRE))
L << "<span class='warning'>Your [B.name] bursts into flames!</span>"
for(var/obj/item/weapon/storage/book/bible/BI in L.GetAllContents())
if(!(BI.resistance_flags & ON_FIRE))
BI.fire_act()
for(var/N in mechas_list)
var/obj/mecha/M = N
if(get_dist(M, src) <= sight_range && M.occupant && !is_servant_of_ratvar(M.occupant) && (M in view(sight_range, src)))
. += M
/obj/structure/destructible/clockwork/ocular_warden/proc/lose_target()
if(!target)
return 0
target = null
visible_message("<span class='warning'>[src] settles and seems almost disappointed.</span>")
return 1
@@ -0,0 +1,143 @@
//Ratvar himself. Impossible to damage by most standard means, He will dominate the station and all upon it.
/obj/structure/destructible/clockwork/massive/ratvar
name = "Ratvar, the Clockwork Justiciar"
desc = "<span class='userdanger'>What is what is what are what real what is all a lie all a lie it's all a lie why how can what is</span>"
clockwork_desc = "<span class='large_brass'><b><i>Ratvar, the Clockwork Justiciar, your master eternal.</i></b></span>"
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
var/atom/prey //Whatever Ratvar is chasing
var/clashing = FALSE //If Ratvar is FUCKING FIGHTING WITH NAR-SIE
var/proselytize_range = 10
/obj/structure/destructible/clockwork/massive/ratvar/New()
..()
ratvar_awakens++
for(var/obj/item/clockwork/ratvarian_spear/R in all_clockwork_objects)
R.update_force()
START_PROCESSING(SSobj, src)
world << "<span class='ratvar'>\"[text2ratvar("ONCE AGAIN MY LIGHT SHALL SHINE ACROSS THIS PATHETIC REALM")]!!\"</span>"
world << 'sound/effects/ratvar_reveal.ogg'
var/image/alert_overlay = image('icons/effects/clockwork_effects.dmi', "ratvar_alert")
var/area/A = get_area(src)
notify_ghosts("The Justiciar's light calls to you! Reach out to Ratvar in [A.name] to be granted a shell to spread his glory!", null, source = src, alert_overlay = alert_overlay)
addtimer(SSshuttle.emergency, "request", 50, FALSE, null, 0.1)
/obj/structure/destructible/clockwork/massive/ratvar/Destroy()
ratvar_awakens--
for(var/obj/item/clockwork/ratvarian_spear/R in all_clockwork_objects)
R.update_force()
STOP_PROCESSING(SSobj, src)
world << "<span class='heavy_brass'><font size=6>\"NO! I will not... be...</font> <font size=5>banished...</font> <font size=4>again...\"</font></span>"
return ..()
/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" || !O)
return 0
var/mob/living/simple_animal/drone/cogscarab/ratvar/R = new/mob/living/simple_animal/drone/cogscarab/ratvar(get_turf(src))
R.visible_message("<span class='heavy_brass'>[R] forms, and its eyes blink open, glowing bright red!</span>")
R.key = O.key
/obj/structure/destructible/clockwork/massive/ratvar/Bump(atom/A)
var/turf/T = get_turf(A)
forceMove(T)
T.ratvar_act()
/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, proselytize_range))
var/turf/T = I
T.ratvar_act()
for(var/I in circleviewturfs(src, round(proselytize_range * 0.5)))
var/turf/T = I
T.ratvar_act(1)
var/dir_to_step_in = pick(cardinal)
if(!prey)
for(var/obj/singularity/narsie/N in poi_list)
if(N.z == z)
prey = N
break
if(!prey) //In case there's a Nar-Sie
var/list/meals = list()
for(var/mob/living/L in living_mob_list)
if(L.z == z && !is_servant_of_ratvar(L) && L.mind)
meals += L
if(meals.len)
prey = pick(meals)
prey << "<span class='heavy_brass'><font size=5>\"You will do.\"</font></span>\n\
<span class='userdanger'>Something very large and very malevolent begins lumbering its way towards you...</span>"
prey << 'sound/effects/ratvar_reveal.ogg'
else
if(prob(10) || is_servant_of_ratvar(prey) || prey.z != z)
prey << "<span class='heavy_brass'><font size=5>\"How dull. Leave me.\"</font></span>\n\
<span class='userdanger'>You feel tremendous relief as a set of horrible eyes loses sight of you...</span>"
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/narsie_act()
if(clashing)
return FALSE
clashing = TRUE
world << "<span class='heavy_brass'><font size=5>\"[pick("BLOOD GOD!!!", "NAR-SIE!!!", "AT LAST, YOUR TIME HAS COME!")]\"</font></span>"
world << "<span class='cult'><font size=5>\"<b>Ratvar?! How?!</b>\"</font></span>"
for(var/obj/singularity/narsie/N in range(15, src))
if(N.clashing)
continue
N.clashing = TRUE
clash_of_the_titans(N) //IT'S TIME FOR THE BATTLE OF THE AGES
break
return TRUE
//Put me in Reebe, will you? Ratvar has found and is going to fucking murder 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)
world << 'sound/magic/clockwork/ratvar_attack.ogg'
sleep(5.2)
for(var/mob/M in mob_list)
flash_color(M, flash_color="#966400", flash_time=1)
shake_camera(M, 4, 3)
var/ratvar_chance = min(ticker.mode.servants_of_ratvar.len, 50)
var/narsie_chance = ticker.mode.cult.len
for(var/mob/living/simple_animal/hostile/construct/harvester/C in player_list)
narsie_chance++
ratvar_chance = rand(base_victory_chance, ratvar_chance)
narsie_chance = rand(base_victory_chance, min(narsie_chance, 50))
if(ratvar_chance > narsie_chance)
winner = "Ratvar"
break
sleep(rand(2,5))
world << 'sound/magic/clockwork/narsie_attack.ogg'
sleep(7.4)
for(var/mob/M in mob_list)
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")
world << "<span class='heavy_brass'><font size=5>\"[pick("DIE! DIE! DIE!", "FILTH!!!", "SUFFER!!!", text2ratvar("ROT FOR CENTURIES AS I HAVE!!"))]\"</font></span>" //nar-sie get out
world << "<span class='cult'><font size=5>\"<b>[pick("Nooooo...", "Not die. To y-", "Die. Ratv-", "Sas tyen re-")]\"</b></font></span>"
world << 'sound/magic/clockwork/anima_fragment_attack.ogg'
world << 'sound/magic/demon_dies.ogg'
clashing = FALSE
qdel(narsie)
if("Nar-Sie")
world << "<span class='cult'><font size=5>\"<b>[pick("Ha.", "Ra'sha fonn dest.", "You fool. To come here.")]</b>\"</font></span>" //Broken English
world << 'sound/magic/demon_attack1.ogg'
world << 'sound/magic/clockwork/anima_fragment_death.ogg'
narsie.clashing = FALSE
qdel(src)
@@ -0,0 +1,89 @@
//Tinkerer's cache: Stores components for later use.
/obj/structure/destructible/clockwork/cache
name = "tinkerer's cache"
desc = "A large brass spire with a flaming hole in its center."
clockwork_desc = "A brass container capable of storing a large amount of components.\n\
Shares components with all other caches and will gradually generate components if near a Clockwork Wall."
icon_state = "tinkerers_cache"
construction_value = 10
break_message = "<span class='warning'>The cache's fire winks out before it falls in on itself!</span>"
max_integrity = 80
obj_integrity = 80
var/wall_generation_cooldown
var/turf/closed/wall/clockwork/linkedwall //if we've got a linked wall and are producing
/obj/structure/destructible/clockwork/cache/New()
..()
START_PROCESSING(SSobj, src)
clockwork_caches++
SetLuminosity(2,1)
for(var/i in all_clockwork_mobs)
cache_check(i)
/obj/structure/destructible/clockwork/cache/Destroy()
clockwork_caches--
STOP_PROCESSING(SSobj, src)
if(linkedwall)
linkedwall.linkedcache = null
linkedwall = null
for(var/i in all_clockwork_mobs)
cache_check(i)
return ..()
/obj/structure/destructible/clockwork/cache/process()
for(var/turf/closed/wall/clockwork/C in view(4, src))
if(!C.linkedcache && !linkedwall)
C.linkedcache = src
linkedwall = C
wall_generation_cooldown = world.time + CACHE_PRODUCTION_TIME
visible_message("<span class='warning'>[src] starts to whirr in the presence of [C]...</span>")
break
if(linkedwall && wall_generation_cooldown <= world.time)
wall_generation_cooldown = world.time + CACHE_PRODUCTION_TIME
var/component_to_generate = get_weighted_component_id()
PoolOrNew(get_component_animation_type(component_to_generate), get_turf(src))
clockwork_component_cache[component_to_generate]++
playsound(C, 'sound/magic/clockwork/fellowship_armory.ogg', rand(15, 20), 1, -3, 1, 1)
visible_message("<span class='warning'>Something clunks around inside of [src]...</span>")
break
/obj/structure/destructible/clockwork/cache/attackby(obj/item/I, mob/living/user, params)
if(!is_servant_of_ratvar(user))
return ..()
if(istype(I, /obj/item/clockwork/component))
var/obj/item/clockwork/component/C = I
clockwork_component_cache[C.component_id]++
user << "<span class='notice'>You add [C] to [src].</span>"
user.drop_item()
qdel(C)
return 1
else if(istype(I, /obj/item/clockwork/slab))
var/obj/item/clockwork/slab/S = I
for(var/i in S.stored_components)
clockwork_component_cache[i] += S.stored_components[i]
S.stored_components[i] = 0
user.visible_message("<span class='notice'>[user] empties [S] into [src].</span>", "<span class='notice'>You offload your slab's components into [src].</span>")
return 1
else
return ..()
/obj/structure/destructible/clockwork/cache/attack_hand(mob/user)
if(!is_servant_of_ratvar(user))
return 0
if(!clockwork_component_cache["replicant_alloy"])
user << "<span class='warning'>There is no Replicant Alloy in the global component cache!</span>"
return 0
clockwork_component_cache["replicant_alloy"]--
var/obj/item/clockwork/component/replicant_alloy/A = new(get_turf(src))
user.visible_message("<span class='notice'>[user] withdraws [A] from [src].</span>", "<span class='notice'>You withdraw [A] from [src].</span>")
user.put_in_hands(A)
return 1
/obj/structure/destructible/clockwork/cache/examine(mob/user)
..()
if(is_servant_of_ratvar(user) || isobserver(user))
if(linkedwall)
user << "<span class='brass'>It is linked and will generate components!</span>"
user << "<b>Stored components:</b>"
for(var/i in clockwork_component_cache)
user << "<span class='[get_component_span(i)]_small'><i>[get_component_name(i)][i != "replicant_alloy" ? "s":""]:</i> <b>[clockwork_component_cache[i]]</b></span>"
@@ -0,0 +1,130 @@
//Tinkerer's Daemon: A machine that rapidly produces components at a power cost.
/obj/structure/destructible/clockwork/powered/tinkerers_daemon
name = "tinkerer's daemon"
desc = "A strange machine with three small brass obelisks attached to it."
clockwork_desc = "An efficient machine that can rapidly produce components at a small power cost. It will only function if outnumbered by servants at a rate to 5:1."
icon_state = "tinkerers_daemon"
active_icon = "tinkerers_daemon"
inactive_icon = "tinkerers_daemon"
max_integrity = 100
obj_integrity = 100
break_message = "<span class='warning'>The daemon shatters into millions of pieces!</span>"
debris = list(/obj/item/clockwork/alloy_shards/large = 2, \
/obj/item/clockwork/alloy_shards/medium = 4, \
/obj/item/clockwork/alloy_shards/small = 6)
var/image/daemon_glow
var/image/component_glow
var/component_id_to_produce
var/production_time = 0 //last time we produced a component
var/production_cooldown = 120
/obj/structure/destructible/clockwork/powered/tinkerers_daemon/New()
..()
clockwork_daemons++
/obj/structure/destructible/clockwork/powered/tinkerers_daemon/Destroy()
clockwork_daemons--
return ..()
/obj/structure/destructible/clockwork/powered/tinkerers_daemon/examine(mob/user)
..()
if(is_servant_of_ratvar(user) || isobserver(user))
if(active)
if(component_id_to_produce)
user << "<span class='[get_component_span(component_id_to_produce)]_small'>It is currently producing [get_component_name(component_id_to_produce)][component_id_to_produce != "replicant_alloy" ? "s":""].</span>"
else
user << "<span class='brass'>It is currently producing random components.</span>"
user << "<span class='nezbere_small'>It will produce a component every <b>[production_cooldown*0.1]</b> seconds and requires at least the following power for each component type:</span>"
for(var/i in clockwork_component_cache)
user << "<span class='[get_component_span(i)]_small'><i>[get_component_name(i)]:</i> <b>[get_component_cost(i)]W</b> <i>([clockwork_component_cache[i]] exist[clockwork_component_cache[i] == 1 ? "s" : ""])</i></span>"
/obj/structure/destructible/clockwork/powered/tinkerers_daemon/attack_hand(mob/living/user)
if(!is_servant_of_ratvar(user))
user << "<span class='warning'>You place your hand on the daemon, but nothing happens.</span>"
return
if(active)
toggle(0, user)
else
if(!clockwork_caches)
user << "<span class='warning'>There are no clockwork caches! Activating this daemon would be a waste of power.</span>"
return
var/choice = alert(user,"Activate Daemon...",,"Specific Component","Random Component","Cancel")
switch(choice)
if("Specific Component")
var/list/components = list()
for(var/i in clockwork_component_cache)
components["[get_component_name(i)] ([get_component_cost(i)]W)"] = i
var/input_component = input(user, "Choose a component type.", name) as null|anything in components
component_id_to_produce = components[input_component]
if(!user.canUseTopic(src, BE_CLOSE) || active)
return
if(!component_id_to_produce)
user << "<span class='warning'>You decide not to select a component and activate the daemon.</span>"
return
if(total_accessable_power() < get_component_cost(component_id_to_produce))
user << "<span class='warning'>There is too little power to produce this type of component!</span>"
return
toggle(0, user)
if("Random Component")
component_id_to_produce = null
toggle(0, user)
/obj/structure/destructible/clockwork/powered/tinkerers_daemon/toggle(fast_process, mob/living/user)
. = ..()
if(active)
var/component_color = get_component_color(component_id_to_produce)
if(!daemon_glow)
daemon_glow = new('icons/obj/clockwork_objects.dmi', "tinkerglow")
daemon_glow.color = component_color
add_overlay(daemon_glow)
if(!component_glow)
component_glow = new('icons/obj/clockwork_objects.dmi', "t_[component_id_to_produce ? component_id_to_produce :"random_component"]")
else
component_glow.icon_state = "t_[component_id_to_produce ? component_id_to_produce :"random_component"]"
component_glow.color = component_color
add_overlay(component_glow)
production_time = world.time + production_cooldown //don't immediately produce when turned on afteer being off
else
cut_overlays()
/obj/structure/destructible/clockwork/powered/tinkerers_daemon/proc/get_component_cost(id)
return max(MIN_CLOCKCULT_POWER, MIN_CLOCKCULT_POWER * (1 + round(clockwork_component_cache[id] * 0.2)))
/obj/structure/destructible/clockwork/powered/tinkerers_daemon/process()
var/servants = 0
for(var/mob/living/L in living_mob_list)
if(is_servant_of_ratvar(L))
servants++
. = ..()
var/min_power_usable = 0
if(!component_id_to_produce)
for(var/i in clockwork_component_cache)
if(!min_power_usable)
min_power_usable = get_component_cost(i)
else
min_power_usable = min(min_power_usable, get_component_cost(i))
else
min_power_usable = get_component_cost(component_id_to_produce)
if(!clockwork_caches || servants * 0.2 < clockwork_daemons || . < min_power_usable) //if we don't have enough to produce the lowest or what we chose to produce, cancel out
visible_message("<span class='warning'>[src] shuts down!</span>")
toggle()
return
if(production_time <= world.time)
var/component_to_generate = component_id_to_produce
if(!component_to_generate)
component_to_generate = get_weighted_component_id() //more likely to generate components that we have less of
if(!try_use_power(get_component_cost(component_to_generate)))
component_to_generate = null
if(!component_id_to_produce)
for(var/i in clockwork_component_cache)
if(try_use_power(get_component_cost(i))) //if we fail but are producing random, try and get a different component to produce
component_to_generate = i
break
if(component_to_generate)
PoolOrNew(get_component_animation_type(component_to_generate), get_turf(src))
clockwork_component_cache[component_to_generate]++
production_time = world.time + production_cooldown //go on cooldown
visible_message("<span class='warning'>[src] hums as it produces a [get_component_name(component_to_generate)].</span>")
else
visible_message("<span class='warning'>[src] shuts down!</span>") //we shouldn't actually ever get here, as we should cancel out way before this
toggle()
@@ -0,0 +1,56 @@
//A massive gear, effectively a girder for clocks.
/obj/structure/destructible/clockwork/wall_gear
name = "massive gear"
icon_state = "wall_gear"
climbable = TRUE
max_integrity = 50
obj_integrity = 50
desc = "A massive brass gear. You could probably secure or unsecure it with a wrench, or just climb over it."
clockwork_desc = "A massive brass gear. You could probably secure or unsecure it with a wrench, just climb over it, or proselytize it into replicant alloy."
break_message = "<span class='warning'>The gear breaks apart into shards of alloy!</span>"
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/examine(mob/user)
..()
user << "<span class='notice'>[src] is [anchored ? "":"not "]secured to the floor.</span>"
/obj/structure/destructible/clockwork/wall_gear/attackby(obj/item/I, mob/user, params)
if(istype(I, /obj/item/weapon/wrench))
default_unfasten_wrench(user, I, 10)
return 1
else if(istype(I, /obj/item/stack/sheet/brass))
var/obj/item/stack/sheet/brass/W = I
if(W.get_amount() < 1)
user << "<span class='warning'>You need one brass sheet to do this!</span>"
return
var/turf/T = get_turf(src)
if(iswallturf(T))
user << "<span class='warning'>There is already a wall present!</span>"
return
if(!isfloorturf(T))
user << "<span class='warning'>A floor must be present to build a [anchored ? "false ":""]wall!</span>"
return
if(locate(/obj/structure/falsewall) in T.contents)
user << "<span class='warning'>There is already a false wall present!</span>"
return
user << "<span class='notice'>You start adding [W] to [src]...</span>"
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.ChangeTurf(/turf/closed/wall/clockwork)
else
T.ChangeTurf(/turf/open/floor/clockwork)
new /obj/structure/falsewall/brass(T)
qdel(src)
else
user << "<span class='warning'>You need more brass to make a [anchored ? "false ":""]wall!</span>"
return 1
return ..()
@@ -1,372 +0,0 @@
//sends messages via hierophant
/proc/titled_hierophant_message(mob/user, message, name_span = "heavy_brass", message_span = "brass", user_title = "Servant")
if(!user || !message || !ticker || !ticker.mode)
return 0
var/parsed_message = "<span class='[name_span]'>[user_title ? "[user_title] ":""][findtextEx(user.name, user.real_name) ? user.name : "[user.real_name] (as [user.name])"]: \
</span><span class='[message_span]'>\"[message]\"</span>"
hierophant_message(parsed_message, FALSE, user)
return 1
/proc/hierophant_message(message, servantsonly, atom/target) //sends a generic message to all servants and optionally observers
if(!message || !ticker || !ticker.mode)
return 0
for(var/M in mob_list)
if(!servantsonly && isobserver(M))
if(target)
var/link = FOLLOW_LINK(M, target)
M << "[link] [message]"
else
M << message
else if(is_servant_of_ratvar(M))
M << message
//Hierophant Network action, allows a servant with it to communicate
/datum/action/innate/hierophant
name = "Hierophant Network"
desc = "Allows you to communicate with other Servants."
button_icon_state = "hierophant"
background_icon_state = "bg_clock"
check_flags = AB_CHECK_RESTRAINED|AB_CHECK_STUNNED|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 0
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
titled_hierophant_message(owner, input, span_for_name, span_for_message, title)
//Function Call action: Calls forth a Ratvarian spear once every 3 minutes
/datum/action/innate/function_call
name = "Function Call"
desc = "Allows you to summon a Ratvarian spear to fight enemies."
button_icon_state = "ratvarian_spear"
background_icon_state = "bg_clock"
check_flags = AB_CHECK_RESTRAINED|AB_CHECK_STUNNED|AB_CHECK_CONSCIOUS
buttontooltipstyle = "clockcult"
var/cooldown = 0
var/base_cooldown = 1800
/datum/action/innate/function_call/IsAvailable()
if(!is_servant_of_ratvar(owner) || cooldown > world.time)
return 0
return ..()
/datum/action/innate/function_call/Activate()
if(!owner.get_empty_held_indexes())
usr << "<span class='warning'>You need an empty to hand to call forth your spear!</span>"
return 0
owner.visible_message("<span class='warning'>A strange spear materializes in [owner]'s hands!</span>", "<span class='brass'>You call forth your spear!</span>")
var/obj/item/clockwork/ratvarian_spear/R = new(get_turf(usr))
owner.put_in_hands(R)
if(!ratvar_awakens)
owner << "<span class='warning'>Your spear begins to break down in this plane of existence. You can't use it for long!</span>"
addtimer(R, "break_spear", base_cooldown, FALSE)
cooldown = base_cooldown + world.time
owner.update_action_buttons_icon()
addtimer(src, "update_actions", base_cooldown, FALSE)
return 1
/datum/action/innate/function_call/proc/update_actions()
if(owner)
owner.update_action_buttons_icon()
//allows a mob to select a target to gate to
/atom/movable/proc/procure_gateway(mob/living/invoker, time_duration, gateway_uses, two_way)
var/list/possible_targets = list()
var/list/teleportnames = list()
var/list/duplicatenamecount = list()
for(var/obj/structure/destructible/clockwork/powered/clockwork_obelisk/O in all_clockwork_objects)
if(!O.Adjacent(invoker) && O != src && (O.z <= ZLEVEL_SPACEMAX)) //don't list obelisks that we're next to
var/area/A = get_area(O)
var/locname = initial(A.name)
var/resultkey = "[locname] [O.name]"
if(resultkey in teleportnames) //why the fuck did you put two obelisks in the same area
duplicatenamecount[resultkey]++
resultkey = "[resultkey] ([duplicatenamecount[resultkey]])"
else
teleportnames.Add(resultkey)
duplicatenamecount[resultkey] = 1
possible_targets[resultkey] = O
for(var/mob/living/L in living_mob_list)
if(!L.stat && is_servant_of_ratvar(L) && !L.Adjacent(invoker) && L != invoker && (L.z <= ZLEVEL_SPACEMAX)) //People right next to the invoker can't be portaled to, for obvious reasons
var/resultkey = "[L.name] ([L.real_name])"
if(resultkey in teleportnames)
duplicatenamecount[resultkey]++
resultkey = "[resultkey] ([duplicatenamecount[resultkey]])"
else
teleportnames.Add(resultkey)
duplicatenamecount[resultkey] = 1
possible_targets[resultkey] = L
if(!possible_targets.len)
invoker << "<span class='warning'>There are no other eligible targets for a Spatial Gateway!</span>"
return 0
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 || !target || !invoker || !invoker.canUseTopic(src, BE_CLOSE) || !is_servant_of_ratvar(invoker) || (istype(src, /obj/item) && invoker.get_active_held_item() != src))
return 0 //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
var/istargetobelisk = istype(target, /obj/structure/destructible/clockwork/powered/clockwork_obelisk)
if(istargetobelisk)
gateway_uses *= 2
time_duration *= 2
invoker.visible_message("<span class='warning'>The air in front of [invoker] ripples before suddenly tearing open!</span>", \
"<span class='brass'>With a word, you rip open a [two_way ? "two-way":"one-way"] rift to [input_target_key]. It will last for [time_duration / 10] seconds and has [gateway_uses] use[gateway_uses > 1 ? "s" : ""].</span>")
var/obj/effect/clockwork/spatial_gateway/S1 = new(istype(src, /obj/structure/destructible/clockwork/powered/clockwork_obelisk) ? 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("<span class='warning'>The air in front of [target] ripples before suddenly tearing open!</span>")
return 1
/proc/scripture_unlock_check() //returns a list of scriptures and if they're unlocked or not
var/servants = 0
var/unconverted_ai_exists = FALSE
for(var/mob/living/M in living_mob_list)
if(is_servant_of_ratvar(M) && (ishuman(M) || issilicon(M)))
servants++
else if(isAI(M))
unconverted_ai_exists = TRUE
. = list(SCRIPTURE_DRIVER = TRUE, SCRIPTURE_SCRIPT = FALSE, SCRIPTURE_APPLICATION = FALSE, SCRIPTURE_REVENANT = FALSE, SCRIPTURE_JUDGEMENT = FALSE)
//Drivers: always unlocked
.[SCRIPTURE_SCRIPT] = (servants >= 5 && clockwork_caches >= 1)
//Script: 5 or more non-brain servants and 1+ clockwork caches
.[SCRIPTURE_APPLICATION] = (servants >= 8 && clockwork_caches >= 3 && clockwork_construction_value >= 100)
//Application: 8 or more non-brain servants, 3+ clockwork caches, and at least 100 CV
.[SCRIPTURE_REVENANT] = (servants >= 10 && clockwork_caches >= 4 && clockwork_construction_value >= 200)
//Revenant: 10 or more non-brain servants, 4+ clockwork caches, and at least 200 CV
.[SCRIPTURE_JUDGEMENT] = (servants >= 12 && clockwork_caches >= 5 && clockwork_construction_value >= 300 && !unconverted_ai_exists)
//Judgement: 12 or more non-brain servants, 5+ clockwork caches, at least 300 CV, and there are no living, non-servant ais
/proc/scripture_unlock_alert(list/previous_states) //reports to servants when scripture is locked or unlocked
. = scripture_unlock_check()
for(var/i in .)
if(.[i] != previous_states[i])
hierophant_message("<span class='large_brass'><i>Hierophant Network:</i> <b>[i] Scripture has been [.[i] ? "un":""]locked.</b></span>")
/proc/change_construction_value(amount)
clockwork_construction_value += amount
/proc/get_component_name(id) //returns a component name from a component id
switch(id)
if("belligerent_eye")
return "Belligerent Eye"
if("vanguard_cogwheel")
return "Vanguard Cogwheel"
if("guvax_capacitor")
return "Guvax Capacitor"
if("replicant_alloy")
return "Replicant Alloy"
if("hierophant_ansible")
return "Hierophant Ansible"
else
return null
/proc/get_component_span(id) //returns a component spanclass from a component id
switch(id)
if("belligerent_eye")
return "neovgre"
if("vanguard_cogwheel")
return "inathneq"
if("guvax_capacitor")
return "sevtug"
if("replicant_alloy")
return "nezbere"
if("hierophant_ansible")
return "nzcrentr"
else
return null
/proc/get_component_color(id) //returns a component color from a component id
switch(id)
if("belligerent_eye")
return "#6E001A"
if("vanguard_cogwheel")
return "#1E8CE1"
if("guvax_capacitor")
return "#AF0AAF"
if("replicant_alloy")
return "#42474D"
if("hierophant_ansible")
return "#DAAA18"
else
return "#BE8700"
/proc/get_component_id(name) //returns a component id from a component name
switch(name)
if("Belligerent Eye")
return "belligerent_eye"
if("Vanguard Cogwheel")
return "vanguard_cogwheel"
if("Guvax Capacitor")
return "guvax_capacitor"
if("Replicant Alloy")
return "replicant_alloy"
if("Hierophant Ansible")
return "hierophant_ansible"
else
return null
/proc/get_component_animation_type(id)
switch(id)
if("belligerent_eye")
return /obj/effect/overlay/temp/ratvar/component
if("vanguard_cogwheel")
return /obj/effect/overlay/temp/ratvar/component/cogwheel
if("guvax_capacitor")
return /obj/effect/overlay/temp/ratvar/component/capacitor
if("replicant_alloy")
return /obj/effect/overlay/temp/ratvar/component/alloy
if("hierophant_ansible")
return /obj/effect/overlay/temp/ratvar/component/ansible
else
return null
/proc/generate_cache_component(specific_component_id) //generates a component in the global component cache, either random based on lowest or a specific component
if(specific_component_id)
clockwork_component_cache[specific_component_id]++
else
var/component_to_generate = get_weighted_component_id()
clockwork_component_cache[component_to_generate]++
/proc/get_weighted_component_id(obj/item/clockwork/slab/storage_slab) //returns a chosen component id based on the lowest amount of that component
. = list()
if(storage_slab)
if(clockwork_caches)
for(var/i in clockwork_component_cache)
.[i] = max(MAX_COMPONENTS_BEFORE_RAND - LOWER_PROB_PER_COMPONENT*(clockwork_component_cache[i] + storage_slab.stored_components[i]), 1)
else
for(var/i in clockwork_component_cache)
.[i] = max(MAX_COMPONENTS_BEFORE_RAND - LOWER_PROB_PER_COMPONENT*storage_slab.stored_components[i], 1)
else
for(var/i in clockwork_component_cache)
.[i] = max(MAX_COMPONENTS_BEFORE_RAND - LOWER_PROB_PER_COMPONENT*clockwork_component_cache[i], 1)
. = pickweight(.)
/proc/clockwork_say(atom/movable/AM, message, whisper=FALSE)
// When servants invoke ratvar's power, they speak in ways that non
// servants do not comprehend.
// Our ratvarian chants are stored in their ratvar forms
var/list/spans = list(SPAN_ROBOT)
var/old_languages_spoken = AM.languages_spoken
AM.languages_spoken = HUMAN //anyone who can understand HUMAN will hear weird shitty ratvar speak, otherwise it'll get starred out
if(isliving(AM))
var/mob/living/L = AM
if(!whisper)
L.say(message, "clock", spans)
else
L.whisper(message)
else
AM.say(message)
AM.languages_spoken = old_languages_spoken
/proc/cache_check(mob/M)
if(!clockwork_caches)
M.throw_alert("nocache", /obj/screen/alert/clockwork/nocache)
else
M.clear_alert("nocache")
/*
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])","g")
#define RATVAR_PRE_AND_REPLACEMENT "$1-$2"
#define RATVAR_POST_AND_MATCH regex("(\[aA]\[nN]\[dD])\\s(\\w)","g")
#define RATVAR_POST_AND_REPLACEMENT "$1-$2"
#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 = 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)
ratvarian = replacetext(ratvarian, RATVAR_MY_MATCH, RATVAR_MY_REPLACEMENT)
return rot13(ratvarian)
/proc/ratvar2text(ratvarian) //Reverts ravarian styling and rot13 in text.
var/text = replacetext(rot13(ratvarian), "`", "")
text = replacetext(text, 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)
text = replacetext(text, REVERSE_RATVAR_HYPHEN_OF_MATCH, REVERSE_RATVAR_HYPHEN_OF_REPLACEMENT)
return text
+1 -1
View File
@@ -324,7 +324,7 @@
/mob/living/ratvar_act()
if(!add_servant_of_ratvar(src) && !is_servant_of_ratvar(src))
if(!is_servant_of_ratvar(src) && !add_servant_of_ratvar(src))
src << "<span class='userdanger'>A blinding light boils you alive! <i>Run!</i></span>"
adjustFireLoss(35)
if(src)
+31 -8
View File
@@ -348,22 +348,45 @@
#include "code\game\gamemodes\changeling\powers\tiny_prick.dm"
#include "code\game\gamemodes\changeling\powers\transform.dm"
#include "code\game\gamemodes\clock_cult\clock_cult.dm"
#include "code\game\gamemodes\clock_cult\clock_effect.dm"
#include "code\game\gamemodes\clock_cult\clock_item.dm"
#include "code\game\gamemodes\clock_cult\clock_machines.dm"
#include "code\game\gamemodes\clock_cult\clock_mobs.dm"
#include "code\game\gamemodes\clock_cult\clock_powerdrain.dm"
#include "code\game\gamemodes\clock_cult\clock_ratvar.dm"
#include "code\game\gamemodes\clock_cult\clock_scripture.dm"
#include "code\game\gamemodes\clock_cult\clock_structures.dm"
#include "code\game\gamemodes\clock_cult\clock_unsorted.dm"
#include "code\game\gamemodes\clock_cult\clock_items\clock_armor.dm"
#include "code\game\gamemodes\clock_cult\clock_structure.dm"
#include "code\game\gamemodes\clock_cult\clock_effects\clock_overlay.dm"
#include "code\game\gamemodes\clock_cult\clock_effects\clock_sigils.dm"
#include "code\game\gamemodes\clock_cult\clock_effects\general_markers.dm"
#include "code\game\gamemodes\clock_cult\clock_effects\spatial_gateway.dm"
#include "code\game\gamemodes\clock_cult\clock_helpers\clock_powerdrain.dm"
#include "code\game\gamemodes\clock_cult\clock_helpers\component_helpers.dm"
#include "code\game\gamemodes\clock_cult\clock_helpers\hierophant_network.dm"
#include "code\game\gamemodes\clock_cult\clock_helpers\proselytizer_helpers.dm"
#include "code\game\gamemodes\clock_cult\clock_helpers\ratvarian_language.dm"
#include "code\game\gamemodes\clock_cult\clock_helpers\scripture_checks.dm"
#include "code\game\gamemodes\clock_cult\clock_items\clock_components.dm"
#include "code\game\gamemodes\clock_cult\clock_items\clock_proselytizer.dm"
#include "code\game\gamemodes\clock_cult\clock_items\clock_slab.dm"
#include "code\game\gamemodes\clock_cult\clock_items\clockwork_armor.dm"
#include "code\game\gamemodes\clock_cult\clock_items\clockwork_proselytizer.dm"
#include "code\game\gamemodes\clock_cult\clock_items\clockwork_slab.dm"
#include "code\game\gamemodes\clock_cult\clock_items\judicial_visor.dm"
#include "code\game\gamemodes\clock_cult\clock_items\ratvarian_spear.dm"
#include "code\game\gamemodes\clock_cult\clock_items\soul_vessel.dm"
#include "code\game\gamemodes\clock_cult\clock_items\wraith_spectacles.dm"
#include "code\game\gamemodes\clock_cult\clock_scriptures\scripture_applications.dm"
#include "code\game\gamemodes\clock_cult\clock_scriptures\scripture_drivers.dm"
#include "code\game\gamemodes\clock_cult\clock_scriptures\scripture_judgement.dm"
#include "code\game\gamemodes\clock_cult\clock_scriptures\scripture_revenant.dm"
#include "code\game\gamemodes\clock_cult\clock_scriptures\scripture_scripts.dm"
#include "code\game\gamemodes\clock_cult\clock_structures\ark_of_the_clockwork_justicar.dm"
#include "code\game\gamemodes\clock_cult\clock_structures\clock_shells.dm"
#include "code\game\gamemodes\clock_cult\clock_structures\clockwork_obelisk.dm"
#include "code\game\gamemodes\clock_cult\clock_structures\interdiction_lens.dm"
#include "code\game\gamemodes\clock_cult\clock_structures\mania_motor.dm"
#include "code\game\gamemodes\clock_cult\clock_structures\mending_motor.dm"
#include "code\game\gamemodes\clock_cult\clock_structures\ocular_warden.dm"
#include "code\game\gamemodes\clock_cult\clock_structures\ratvar_the_clockwork_justicar.dm"
#include "code\game\gamemodes\clock_cult\clock_structures\tinkerers_cache.dm"
#include "code\game\gamemodes\clock_cult\clock_structures\tinkerers_daemon.dm"
#include "code\game\gamemodes\clock_cult\clock_structures\wall_gear.dm"
#include "code\game\gamemodes\cult\cult.dm"
#include "code\game\gamemodes\cult\cult_comms.dm"
#include "code\game\gamemodes\cult\cult_items.dm"