Merge branch 'master' into joy

This commit is contained in:
Fabian
2021-03-23 20:28:09 +01:00
285 changed files with 8739 additions and 5688 deletions
@@ -125,6 +125,8 @@
/datum/antagonist/changeling/proc/remove_changeling_powers()
if(ishuman(owner.current) || ismonkey(owner.current))
reset_properties()
QDEL_NULL(cellular_emporium)
QDEL_NULL(emporium_action)
for(var/obj/effect/proc_holder/changeling/p in purchasedpowers)
if(p.always_keep)
continue
@@ -139,6 +141,7 @@
/datum/antagonist/changeling/proc/reset_powers()
if(purchasedpowers)
remove_changeling_powers()
create_actions()
//Repurchase free powers.
for(var/path in all_powers)
var/obj/effect/proc_holder/changeling/S = new path()
@@ -225,7 +228,8 @@
/datum/antagonist/changeling/proc/regenerate()
var/mob/living/carbon/the_ling = owner.current
if(istype(the_ling))
emporium_action.Grant(the_ling)
if(emporium_action)
emporium_action.Grant(the_ling)
if(the_ling.stat == DEAD)
chem_charges = min(max(0, chem_charges + chem_recharge_rate - chem_recharge_slowdown), (chem_storage*0.5))
geneticdamage = max(LING_DEAD_GENETICDAMAGE_HEAL_CAP,geneticdamage-1)
@@ -11,6 +11,14 @@
//Revive from revival stasis
/obj/effect/proc_holder/changeling/revive/sting_action(mob/living/carbon/user)
var/datum/antagonist/changeling/changeling = user.mind.has_antag_datum(/datum/antagonist/changeling)
if(!changeling)
return
if(changeling.hostile_absorbed)
to_chat(user, "<span class='notice'>We cannot muster up the strength to revive ourselves!</span>")
changeling.purchasedpowers -= src
src.action.Remove(user)
return
user.cure_fakedeath("changeling")
user.revive(full_heal = 1)
var/list/missing = user.get_missing_limbs()
@@ -27,7 +35,6 @@
user.regenerate_limbs(0, list(BODY_ZONE_HEAD))
user.regenerate_organs()
to_chat(user, "<span class='notice'>We have revived ourselves.</span>")
var/datum/antagonist/changeling/changeling = user.mind.has_antag_datum(/datum/antagonist/changeling)
changeling.purchasedpowers -= src
src.action.Remove(user)
return TRUE
@@ -144,7 +144,7 @@
to_chat(L, "<span class='heavy_brass'>\"You belong to me now.\"</span>")
if(!GLOB.application_scripture_unlocked)
GLOB.application_scripture_unlocked = TRUE
hierophant_message("<span class='large_brass bold'>With the conversion of a new servant the Ark's power grows. Application scriptures are now available.</span>")
hierophant_message("<span class='large_brass bold'>With the conversion of a new servant the Hierophant Network's power grows. Application scriptures are now available.</span>")
if(add_servant_of_ratvar(L))
L.log_message("conversion was done with a [sigil_name]", LOG_ATTACK, color="BE8700")
if(iscarbon(L))
@@ -196,4 +196,68 @@
CL.visible_message("<span class='warning'>[CL] materialises out of thin air!")
new /obj/effect/temp_visual/ratvar/sigil/transmission(T,2)
//summons a soul vessel, which is the clockwork cult version of a soul shard. It acts like a posibrain and, as long as the target has a brain, a soul shard.
/datum/clockwork_rite/soul_vessel
name = "Rite of the Vessel" //The name of the rite
desc = "This rite is used to summon a soul vessel, a special posibrain that makes whoever has their brain put into it loyal to the Justiciar.,\
When put into a cyborg shell, the created cyborg will automatically be a servant of Ratvar."
required_ingredients = list(/obj/item/stack/cable_coil, /obj/item/stock_parts/cell/, /obj/item/organ/cyberimp)
power_cost = 2500 //These things are pretty strong, I won't lie
requires_full_power = TRUE
cast_time = 50
limit = INFINITE
rite_cast_sound = 'sound/magic/summon_guns.ogg'
/datum/clockwork_rite/soul_vessel/cast(var/mob/living/invoker, var/turf/T, var/mob/living/carbon/human/target)
. = ..()
if(!.)
return FALSE
var/obj/item/mmi/posibrain/soul_vessel/SV = new /obj/item/mmi/posibrain/soul_vessel(T)
SV.visible_message("<span class='warning'>[SV] materalizes out of thin air!</span>")
new /obj/effect/temp_visual/ratvar/sigil/transmission(T,2)
/datum/clockwork_rite/cyborg_transform
name = "Rite of the Divine Form"
desc = "This rite is used to ascend into a cyborg, gaining unique scripture and a loadout that depends on which module is chosen. Consult the wiki for details on each cyborg module's loadout. Mutually exclusive to Enhanced Form."
required_ingredients = list(/obj/item/mmi/posibrain, /obj/item/stack/cable_coil, /obj/item/stock_parts/cell/super, /obj/item/bodypart/l_arm/robot, /obj/item/bodypart/r_arm/robot, /obj/item/bodypart/chest/robot, /obj/item/bodypart/head/robot, /obj/item/bodypart/r_leg/robot, /obj/item/bodypart/l_leg/robot)
power_cost = 20000
requires_human = TRUE
requires_full_power = FALSE
cast_time = 100
limit = INFINITE
rite_cast_sound = 'sound/magic/disable_tech.ogg'
/datum/clockwork_rite/cyborg_transform/cast(var/mob/living/invoker, var/turf/T, var/mob/living/carbon/human/target)
. = ..()
if(!.)
return FALSE
if(isclockworkgolem(target))
return FALSE
target.visible_message("<span class='warning'>The robotic parts magnetize to [target], the new frame's eyes glowing in a brilliant yellow!</span>")
var/mob/living/silicon/robot/R = target.Robotize()
R.cell = new /obj/item/stock_parts/cell/super(R)//takes one to use the rite to begin with
new /obj/effect/temp_visual/ratvar/sigil/transmission(T,2)
/datum/clockwork_rite/golem_transform
name = "Rite of the Enhanced Form"
desc = "This rite is used to shed one's flesh to become a clockwork automaton, becoming immune to many environmental hazards as well as being more resilient to incoming damage. Mutually exclusive to Divine Form."
required_ingredients = list(/obj/item/mmi/posibrain, /obj/item/stock_parts/cell/super, /obj/item/bodypart/l_arm/robot, /obj/item/bodypart/r_arm/robot, /obj/item/bodypart/chest/robot, /obj/item/bodypart/head/robot, /obj/item/bodypart/r_leg/robot, /obj/item/bodypart/l_leg/robot)
power_cost = 20000
requires_human = TRUE
requires_full_power = FALSE
cast_time = 100
limit = INFINITE
rite_cast_sound = 'sound/magic/disable_tech.ogg'
/datum/clockwork_rite/golem_transform/cast(var/mob/living/invoker, var/turf/T, var/mob/living/carbon/human/target)
. = ..()
if(!.)
return FALSE
target.visible_message("<span class='warning'>The robotic parts magnetize to [target], the humanoid shape's eye glowing with an inner flame!</span>")
to_chat(target, "<span class='bold alloy'>The rite's power warps your body into a clockwork form! You are now immune to many hazards, and your body is more robust against damage!</span>")
target.set_species(/datum/species/golem/clockwork/no_scrap)
new /obj/effect/temp_visual/ratvar/sigil/transmission(T,2)
#undef INFINITE
@@ -350,3 +350,22 @@
// Winter coat
/obj/item/clothing/suit/hooded/wintercoat/fabrication_vals(mob/living/user, obj/item/clockwork/replica_fabricator/fabricator, silent) //four sheets of metal
return list("operation_time" = 30, "new_obj_type" = /obj/item/clothing/suit/hooded/wintercoat/ratvar, "power_cost" = POWER_METAL * 4, "spawn_dir" = SOUTH)
//tools
/obj/item/crowbar/fabrication_vals(mob/living/user, obj/item/clockwork/replica_fabricator/fabricator, silent) //1 metal rod each
return list("operation_time" = 2, "new_obj_type" = /obj/item/crowbar/brass, "power_cost" = POWER_ROD * 1, "spawn_dir" = SOUTH)
/obj/item/screwdriver/fabrication_vals(mob/living/user, obj/item/clockwork/replica_fabricator/fabricator, silent)
return list("operation_time" = 2, "new_obj_type" = /obj/item/screwdriver/brass, "power_cost" = POWER_ROD * 1, "spawn_dir" = SOUTH)
/obj/item/weldingtool/fabrication_vals(mob/living/user, obj/item/clockwork/replica_fabricator/fabricator, silent)
return list("operation_time" = 2, "new_obj_type" = /obj/item/weldingtool/experimental/brass, "power_cost" = POWER_ROD * 1, "spawn_dir" = SOUTH)
/obj/item/wirecutters/fabrication_vals(mob/living/user, obj/item/clockwork/replica_fabricator/fabricator, silent)
return list("operation_time" = 2, "new_obj_type" = /obj/item/wirecutters/brass, "power_cost" = POWER_ROD * 1, "spawn_dir" = SOUTH)
/obj/item/wrench/fabrication_vals(mob/living/user, obj/item/clockwork/replica_fabricator/fabricator, silent)
return list("operation_time" = 2, "new_obj_type" = /obj/item/wrench/brass, "power_cost" = POWER_ROD * 1, "spawn_dir" = SOUTH)
/obj/item/multitool/fabrication_vals(mob/living/user, obj/item/clockwork/replica_fabricator/fabricator, silent)
return list("operation_time" = 2, "new_obj_type" = /obj/item/multitool/advanced/brass, "power_cost" = POWER_ROD * 1, "spawn_dir" = SOUTH)
@@ -5,7 +5,7 @@
name = "clock-themed arm-mounted implant"
var/clockwork_desc = "According to Ratvar, this really shouldn't exist. Tell Him about this immediately."
syndicate_implant = TRUE
icon_state = "clock_arm_implant"
icon_state = "toolkit_implant"
/obj/item/organ/cyberimp/arm/clockwork/ui_action_click()
if(is_servant_of_ratvar(owner) || (obj_flags & EMAGGED)) //If you somehow manage to steal a clockie's implant AND have an emag AND manage to get it implanted for yourself, good on ya!
@@ -251,7 +251,9 @@
var/mob/camera/eminence/E = owner
E.eminence_help()
/*
//Returns to the Ark - Commented out and replaced with obelisk_jump
/datum/action/innate/eminence/ark_jump
name = "Return to Ark"
@@ -265,7 +267,7 @@
owner.playsound_local(owner, 'sound/magic/magic_missile.ogg', 50, TRUE)
flash_color(owner, flash_color = "#AF0AAF", flash_time = 25)
else
to_chat(owner, "<span class='warning'>There is no Ark!</span>")
to_chat(owner, "<span class='warning '>There is no Ark!</span>")
*/
//Warps to a chosen Obelisk
@@ -0,0 +1,432 @@
//Clockwork guardian: Slow but with high damage, resides inside of a servant. Created via the Memory Allocation scripture.
/mob/living/simple_animal/hostile/clockwork/guardian
name = "clockwork guardian"
desc = "A slow, armored clockwork machine, blazing with magenta flames. It's armed with a gladius and shield, and stands ready by its master."
icon_state = "clockwork_guardian"
health = 300
maxHealth = 300
speed = 1
obj_damage = 40
melee_damage_lower = 20//ranged attacks are the way to go for fighting these
melee_damage_upper = 20
attack_verb_continuous = "slashes"
attack_verb_simple = "slash"
attack_sound = 'sound/weapons/bladeslice.ogg'
weather_immunities = list("lava")
movement_type = FLYING
AIStatus = AI_OFF //this has to be manually set so that the guardian doesn't start bashing the host, how annoying -_-
loot = list(/obj/structure/destructible/clockwork/taunting_trail)
var/true_name = "Meme Master 69" //Required to call forth the guardian
var/global/list/possible_true_names = list("Servant", "Warden", "Serf", "Page", "Usher", "Knave", "Vassal", "Escort")
var/mob/living/host //The mob that the guardian is living inside of
var/recovering = FALSE //If the guardian is recovering from recalling
var/blockchance = 17 //chance to block attacks entirely
var/counterchance = 30 //chance to counterattack after blocking
var/static/list/damage_heal_order = list(OXY, BURN, BRUTE, TOX) //we heal our host's damage in this order
light_color = "#AF0AAF"
light_range = 2
light_power = 1.1
playstyle_string = "<span class='sevtug'>You are a clockwork guardian</span><b>, a living extension of Sevtug's will. As a guardian, you are somewhat slow, but may block attacks, \
and have a chance to also counter blocked melee attacks for extra damage, in addition to being immune to extreme temperatures and pressures. \
Your primary goal is to serve the creature that you are now a part of, as well as The Clockwork Justiciar, Ratvar. You can use <span class='sevtug_small'><i>The Hierophant Network</i></span> to communicate silently with your master and their allies, \
but can only exit if your master calls your true name or if they are exceptionally damaged. \
\n\n\
Stay near your host to protect and heal them; being too far from your host will rapidly cause you massive damage. Recall to your host if you are too weak and believe you cannot continue \
fighting safely. As a final note, you should probably avoid harming any fellow servants of Ratvar.</span>"
/mob/living/simple_animal/hostile/clockwork/guardian/Initialize()
. = ..()
true_name = pick(possible_true_names)
/mob/living/simple_animal/hostile/clockwork/guardian/BiologicalLife(seconds, times_fired)
..()
if(is_in_host())
if(!is_servant_of_ratvar(host))
emerge_from_host(FALSE, TRUE)
unbind_from_host()
return
if(!GLOB.ratvar_awakens && host.stat == DEAD)
death()
return
if(GLOB.ratvar_awakens)
adjustHealth(-50)
else
adjustHealth(-10)
if(!recovering)
heal_host() //also heal our host if inside of them and we aren't recovering
else if(health == maxHealth)
to_chat(src, "<span class='userdanger'>Your strength has returned. You can once again come forward!</span>")
to_chat(host, "<span class='userdanger'>Your guardian is now strong enough to come forward again!</span>")
recovering = FALSE
else
if(GLOB.ratvar_awakens) //If Ratvar is alive, guardians don't need a host and are downright impossible to kill
adjustHealth(-5)
heal_host()
else if(host)
if(!is_servant_of_ratvar(host))
unbind_from_host()
return
if(host.stat == DEAD)
adjustHealth(50)
to_chat(src, "<span class='userdanger'>Your host is dead!</span>")
return
if(z && host.z && z == host.z)
switch(get_dist(get_turf(src), get_turf(host)))
if(2)
adjustHealth(-1)
if(3)
//EQUILIBRIUM
if(4)
adjustHealth(1)
if(5)
adjustHealth(3)
if(6)
adjustHealth(6)
if(7)
adjustHealth(9)
if(8 to INFINITY)
adjustHealth(15)
to_chat(src, "<span class='userdanger'>You're too far from your host and rapidly taking damage!</span>")
else //right next to or on top of host
adjustHealth(-2)
heal_host() //gradually heal host if nearby and host is very weak
else //well then, you're not even in the same zlevel
adjustHealth(15)
to_chat(src, "<span class='userdanger'>You're too far from your host and rapidly taking damage!</span>")
/mob/living/simple_animal/hostile/clockwork/guardian/death(gibbed)
emerge_from_host(FALSE, TRUE)
unbind_from_host()
visible_message("<span class='warning'>[src]'s equipment fades into a purple mist as the flames within sputter and dissipate.</span>", \
"<span class='userdanger'>Your equipment fades away. You feel a moment of confusion before your fragile form is annihilated.</span>")
. = ..()
/mob/living/simple_animal/hostile/clockwork/guardian/Stat()
..()
if(statpanel("Status"))
stat(null, "Current True Name: [true_name]")
stat(null, "Host: [host ? host : "NONE"]")
if(host)
var/resulthealth = round((host.health / host.maxHealth) * 100, 0.5)
if(iscarbon(host))
resulthealth = round((abs(HEALTH_THRESHOLD_DEAD - host.health) / abs(HEALTH_THRESHOLD_DEAD - host.maxHealth)) * 100)
stat(null, "Host Health: [resulthealth]%")
if(GLOB.ratvar_awakens)
stat(null, "You are [recovering ? "un" : ""]able to deploy!")
else
if(resulthealth > GUARDIAN_EMERGE_THRESHOLD)
stat(null, "You are [recovering ? "unable to deploy" : "able to deploy on hearing your True Name"]!")
else
stat(null, "You are [recovering ? "unable to deploy" : "able to deploy to protect your host"]!")
stat(null, "You do [melee_damage_upper] damage on melee attacks.")
/mob/living/simple_animal/hostile/clockwork/guardian/Process_Spacemove(movement_dir = 0)
return 1
/mob/living/simple_animal/hostile/clockwork/guardian/proc/bind_to_host(mob/living/new_host)
if(!new_host)
return FALSE
host = new_host
var/datum/action/innate/summon_guardian/SG = new()
SG.linked_guardian = src
SG.Grant(host)
var/datum/action/innate/linked_minds/LM = new()
LM.linked_guardian = src
LM.Grant(host)
return TRUE
/mob/living/simple_animal/hostile/clockwork/guardian/proc/unbind_from_host()
if(host)
for(var/datum/action/innate/summon_guardian/SG in host.actions)
qdel(SG)
for(var/datum/action/innate/linked_minds/LM in host.actions)
qdel(LM)
host = null
return TRUE
return FALSE
//DAMAGE and FATIGUE
/mob/living/simple_animal/hostile/clockwork/guardian/proc/heal_host()
if(!host)
return
var/resulthealth = round((host.health / host.maxHealth) * 100, 0.5)
if(iscarbon(host))
resulthealth = round((abs(HEALTH_THRESHOLD_DEAD - host.health) / abs(HEALTH_THRESHOLD_DEAD - host.maxHealth)) * 100)
if(GLOB.ratvar_awakens || resulthealth <= GUARDIAN_EMERGE_THRESHOLD)
new /obj/effect/temp_visual/heal(host.loc, "#AF0AAF")
host.heal_ordered_damage(4, damage_heal_order)
/mob/living/simple_animal/hostile/clockwork/guardian/adjustHealth(amount, updating_health = TRUE, forced = FALSE)
if(amount > 0)
for(var/mob/living/L in view(2, src))
if(L.is_holding_item_of_type(/obj/item/nullrod))
to_chat(src, "<span class='userdanger'>The presence of a brandished holy artifact weakens your armor!</span>")
amount *= 4 //if a wielded null rod is nearby, it takes four times the health damage
break
. = ..()
if(src && updating_health)
update_health_hud()
update_stats()
/mob/living/simple_animal/hostile/clockwork/guardian/update_health_hud()
if(hud_used && hud_used.healths)
if(istype(hud_used, /datum/hud))
var/datum/hud/marauder/G = hud_used
var/resulthealth
if(host)
if(iscarbon(host))
resulthealth = "[round((abs(HEALTH_THRESHOLD_DEAD - host.health) / abs(HEALTH_THRESHOLD_DEAD - host.maxHealth)) * 100)]%"
else
resulthealth = "[round((host.health / host.maxHealth) * 100, 0.5)]%"
else
resulthealth = "NONE"
G.hosthealth.maptext = "<div align='center' valign='middle' style='position:relative; top:0px; left:6px'><font color='#AF0AAF'>HOST<br>[resulthealth]</font></div>"
hud_used.healths.maptext = "<div align='center' valign='middle' style='position:relative; top:0px; left:6px'><font color='#AF0AAF'>[round((health / maxHealth) * 100, 0.5)]%</font>"
/mob/living/simple_animal/hostile/clockwork/guardian/proc/update_stats()
if(GLOB.ratvar_awakens)
speed = 0
melee_damage_lower = 20
melee_damage_upper = 20
attack_verb_continuous = "devastates"
else
var/healthpercent = (health/maxHealth) * 100
switch(healthpercent)
if(100 to 70) //Bonuses to speed and damage at high health
speed = 0
melee_damage_lower = 16
melee_damage_upper = 16
attack_verb_continuous = "viciously slashes"
if(70 to 40)
speed = initial(speed)
melee_damage_lower = initial(melee_damage_lower)
melee_damage_upper = initial(melee_damage_upper)
attack_verb_continuous = initial(attack_verb_continuous)
if(40 to 30) //Damage decrease, but not speed
speed = initial(speed)
melee_damage_lower = 10
melee_damage_upper = 10
attack_verb_continuous = "lightly slashes"
if(30 to 20) //Speed decrease
speed = 2
melee_damage_lower = 8
melee_damage_upper = 8
attack_verb_continuous = "lightly slashes"
if(20 to 10) //Massive speed decrease and weak melee attacks
speed = 3
melee_damage_lower = 6
melee_damage_upper = 6
attack_verb_continuous = "weakly slashes"
if(10 to 0) //We are super weak and going to die
speed = 4
melee_damage_lower = 4
melee_damage_upper = 4
attack_verb_continuous = "taps"
//ATTACKING, BLOCKING, and COUNTERING
/mob/living/simple_animal/hostile/clockwork/guardian/AttackingTarget()
if(is_in_host())
return FALSE
return ..()
/mob/living/simple_animal/hostile/clockwork/guardian/bullet_act(obj/item/projectile/Proj)
if(blockOrCounter(null, Proj))
return
return ..()
/mob/living/simple_animal/hostile/clockwork/guardian/hitby(atom/movable/AM, skipcatch, hitpush, blocked, atom/movable/AM, datum/thrownthing/throwingdatum)
if(blockOrCounter(null, AM))
return
return ..()
/mob/living/simple_animal/hostile/clockwork/guardian/attack_animal(mob/living/simple_animal/M)
if(istype(M, /mob/living/simple_animal/hostile/clockwork/guardian) || !blockOrCounter(M, M)) //we don't want infinite blockcounter loops if fighting another guardian
return ..()
/mob/living/simple_animal/hostile/clockwork/guardian/attack_paw(mob/living/carbon/monkey/M)
if(!blockOrCounter(M, M))
return ..()
/mob/living/simple_animal/hostile/clockwork/guardian/attack_alien(mob/living/carbon/alien/humanoid/M)
if(!blockOrCounter(M, M))
return ..()
/mob/living/simple_animal/hostile/clockwork/guardian/attack_slime(mob/living/simple_animal/slime/M)
if(!blockOrCounter(M, M))
return ..()
/mob/living/simple_animal/hostile/clockwork/guardian/attack_hand(mob/living/carbon/human/M)
if(!blockOrCounter(M, M))
return ..()
/mob/living/simple_animal/hostile/clockwork/guardian/attackby(obj/item/I, mob/user, params)
if(istype(I, /obj/item/nullrod) || !blockOrCounter(user, I))
return ..()
/mob/living/simple_animal/hostile/clockwork/guardian/proc/blockOrCounter(mob/target, atom/textobject)
if(GLOB.ratvar_awakens) //if ratvar has woken, we block nearly everything at a very high chance
blockchance = 90
counterchance = 90
if(prob(blockchance))
. = TRUE
if(target)
target.do_attack_animation(src)
target.DelayNextAction(CLICK_CD_MELEE)
blockchance = initial(blockchance)
playsound(src, 'sound/magic/clockwork/fellowship_armory.ogg', 30, 1, 0, 1) //clang
visible_message("<span class='boldannounce'>[src] blocks [target && isitem(textobject) ? "[target]'s [textobject.name]":"\the [textobject]"]!</span>", \
"<span class='userdanger'>You block [target && isitem(textobject) ? "[target]'s [textobject.name]":"\the [textobject]"]!</span>")
if(target && Adjacent(target))
if(prob(counterchance))
counterchance = initial(counterchance)
var/previousattack_verb_continuous = attack_verb_continuous
attack_verb_continuous = "counters"
UnarmedAttack(target)
attack_verb_continuous = previousattack_verb_continuous
else
counterchance = min(counterchance + initial(counterchance), 100)
else
blockchance = min(blockchance + initial(blockchance), 100)
if(GLOB.ratvar_awakens)
blockchance = 90
counterchance = 90
//COMMUNICATION and EMERGENCE
/*
/mob/living/simple_animal/hostile/clockwork/guardian/handle_inherent_channels(message, message_mode)
if(host && (is_in_host() || message_mode == MODE_BINARY))
guardian_comms(message)
return TRUE
return ..()
*/
/mob/living/simple_animal/hostile/clockwork/guardian/proc/guardian_comms(message)
var/name_part = "<span class='sevtug'>[src] ([true_name])</span>"
message = "<span class='sevtug_small'>\"[message]\"</span>" //Processed output
to_chat(src, "[name_part]<span class='sevtug_small'>:</span> [message]")
to_chat(host, "[name_part]<span class='sevtug_small'>:</span> [message]")
for(var/M in GLOB.mob_list)
if(isobserver(M))
var/link = FOLLOW_LINK(M, src)
to_chat(M, "[link] [name_part] <span class='sevtug_small'>(to</span> <span class='sevtug'>[findtextEx(host.name, host.real_name) ? "[host.name]" : "[host.real_name] (as [host.name])"]</span><span class='sevtug_small'>):</span> [message] ")
return TRUE
/mob/living/simple_animal/hostile/clockwork/guardian/proc/return_to_host()
if(is_in_host())
return FALSE
if(!host)
to_chat(src, "<span class='warning'>You don't have a host!</span>")
return FALSE
var/resulthealth = round((host.health / host.maxHealth) * 100, 0.5)
if(iscarbon(host))
resulthealth = round((abs(HEALTH_THRESHOLD_DEAD - host.health) / abs(HEALTH_THRESHOLD_DEAD - host.maxHealth)) * 100)
host.visible_message("<span class='warning'>[host]'s skin flashes magenta!</span>", "<span class='sevtug'>You feel [true_name]'s consciousness settle in your mind.</span>")
visible_message("<span class='warning'>[src] suddenly disappears!</span>", "<span class='sevtug'>You return to [host].</span>")
forceMove(host)
if(resulthealth > GUARDIAN_EMERGE_THRESHOLD && health != maxHealth)
recovering = TRUE
to_chat(src, "<span class='userdanger'>You have weakened and will need to recover before manifesting again!</span>")
to_chat(host, "<span class='sevtug'>[true_name] has weakened and will need to recover before manifesting again!</span>")
return TRUE
/mob/living/simple_animal/hostile/clockwork/guardian/proc/try_emerge()
if(!host)
to_chat(src, "<span class='warning'>You don't have a host!</span>")
return FALSE
if(!GLOB.ratvar_awakens)
var/resulthealth = round((host.health / host.maxHealth) * 100, 0.5)
if(iscarbon(host))
resulthealth = round((abs(HEALTH_THRESHOLD_DEAD - host.health) / abs(HEALTH_THRESHOLD_DEAD - host.maxHealth)) * 100)
if(host.stat != DEAD && resulthealth > GUARDIAN_EMERGE_THRESHOLD) //if above 20 health, fails
to_chat(src, "<span class='warning'>Your host must be at [GUARDIAN_EMERGE_THRESHOLD]% or less health to emerge like this!</span>")
return FALSE
return emerge_from_host(FALSE)
/mob/living/simple_animal/hostile/clockwork/guardian/proc/emerge_from_host(hostchosen, force) //Notice that this is a proc rather than a verb - guardians can NOT exit at will, but they CAN return
if(!is_in_host())
return FALSE
if(!force && recovering)
if(hostchosen)
to_chat(host, "<span class='sevtug'>[true_name] is too weak to come forth!</span>")
else
to_chat(host, "<span class='sevtug'>[true_name] tries to emerge to protect you, but it's too weak!</span>")
to_chat(src, "<span class='userdanger'>You try to come forth, but you're too weak!</span>")
return FALSE
if(!force)
if(hostchosen) //guardian approved
to_chat(host, "<span class='sevtug'>Your words echo with power as [true_name] emerges from your body!</span>")
else
to_chat(host, "<span class='sevtug'>[true_name] emerges from your body to protect you!</span>")
forceMove(host.loc)
visible_message("<span class='warning'>[host]'s skin glows red as [name] emerges from their body!</span>", "<span class='sevtug_small'>You exit the safety of [host]'s body!</span>")
return TRUE
/mob/living/simple_animal/hostile/clockwork/guardian/get_alt_name()
return " ([text2ratvar(true_name)])"
/mob/living/simple_animal/hostile/clockwork/guardian/proc/is_in_host() //Checks if the guardian is inside of their host
return host && loc == host
//HOST ACTIONS
//Summon guardian action: Calls forth or recalls your guardian
/datum/action/innate/summon_guardian
name = "Force Guardian to Emerge/Recall"
desc = "Allows you to force your clockwork guardian to emerge or recall as required."
button_icon_state = "clockwork_marauder"
background_icon_state = "bg_clock"
check_flags = AB_CHECK_CONSCIOUS
buttontooltipstyle = "clockcult"
var/mob/living/simple_animal/hostile/clockwork/guardian/linked_guardian
var/list/defend_phrases = list("Defend me", "Come forth", "Assist me", "Protect me", "Give aid", "Help me")
var/list/return_phrases = list("Return", "Return to me", "Your job is done", "You have served", "Come back", "Retreat")
/datum/action/innate/summon_guardian/IsAvailable()
if(!linked_guardian)
return FALSE
if(isliving(owner))
var/mob/living/L = owner
if(!L.can_speak_vocal() || L.stat)
return FALSE
return ..()
/datum/action/innate/summon_guardian/Activate()
if(linked_guardian.is_in_host())
clockwork_say(owner, text2ratvar("[pick(defend_phrases)], [linked_guardian.true_name]!"))
linked_guardian.emerge_from_host(TRUE)
else
clockwork_say(owner, text2ratvar("[pick(return_phrases)], [linked_guardian.true_name]!"))
linked_guardian.return_to_host()
return TRUE
//Linked Minds action: talks to your guardian
/datum/action/innate/linked_minds
name = "Linked Minds"
desc = "Allows you to silently communicate with your guardian."
button_icon_state = "linked_minds"
background_icon_state = "bg_clock"
check_flags = AB_CHECK_CONSCIOUS
buttontooltipstyle = "clockcult"
var/mob/living/simple_animal/hostile/clockwork/guardian/linked_guardian
/datum/action/innate/linked_minds/IsAvailable()
if(!linked_guardian)
return FALSE
return ..()
/datum/action/innate/linked_minds/Activate()
var/message = stripped_input(owner, "Enter a message to tell your guardian.", "Telepathy")
if(!owner || !message)
return FALSE
if(!linked_guardian)
to_chat(owner, "<span class='warning'>Your guardian seems to have been destroyed!</span>")
return FALSE
var/name_part = "<span class='sevtug'>Servant [findtextEx(owner.name, owner.real_name) ? "[owner.name]" : "[owner.real_name] (as [owner.name])"]</span>"
message = "<span class='sevtug_small'>\"[message]\"</span>" //Processed output
to_chat(owner, "[name_part]<span class='sevtug_small'>:</span> [message]")
to_chat(linked_guardian, "[name_part]<span class='sevtug_small'>:</span> [message]")
for(var/M in GLOB.mob_list)
if(isobserver(M))
var/link = FOLLOW_LINK(M, src)
to_chat(M, "[link] [name_part] <span class='sevtug_small'>(to</span> <span class='sevtug'>[linked_guardian] ([linked_guardian.true_name])</span><span class='sevtug_small'>):</span> [message]")
return TRUE
@@ -123,437 +123,3 @@
#undef MARAUDER_SLOWDOWN_PERCENTAGE
#undef MARAUDER_SHIELD_REGEN_TIME
//Clockwork guardian: Slow but with high damage, resides inside of a servant. Created via the Memory Allocation scripture.
/mob/living/simple_animal/hostile/clockwork/marauder/guardian
name = "clockwork guardian"
desc = "A stalwart apparition of a soldier, blazing with crimson flames. It's armed with a gladius and shield and stands ready by its master."
icon_state = "clockwork_marauder"
health = 300
maxHealth = 300
speed = 1
obj_damage = 40
melee_damage_lower = 12
melee_damage_upper = 12
attack_verb_continuous = "slashes"
attack_verb_simple = "slash"
attack_sound = 'sound/weapons/bladeslice.ogg'
weather_immunities = list("lava")
movement_type = FLYING
AIStatus = AI_OFF //this has to be manually set so that the guardian doesn't start bashing the host, how annoying -_-
loot = list(/obj/item/clockwork/component/geis_capacitor/fallen_armor)
max_shield_health = 0
shield_health = 0
var/true_name = "Meme Master 69" //Required to call forth the guardian
var/global/list/possible_true_names = list("Servant", "Warden", "Serf", "Page", "Usher", "Knave", "Vassal", "Escort")
var/mob/living/host //The mob that the guardian is living inside of
var/recovering = FALSE //If the guardian is recovering from recalling
var/blockchance = 17 //chance to block attacks entirely
var/counterchance = 30 //chance to counterattack after blocking
var/static/list/damage_heal_order = list(OXY, BURN, BRUTE, TOX) //we heal our host's damage in this order
light_range = 2
light_power = 1.1
playstyle_string = "<span class='sevtug'>You are a clockwork guardian</span><b>, a living extension of Sevtug's will. As a guardian, you are somewhat slow, but may block attacks, \
and have a chance to also counter blocked melee attacks for extra damage, in addition to being immune to extreme temperatures and pressures. \
Your primary goal is to serve the creature that you are now a part of, as well as The Clockwork Justiciar, Ratvar. You can use <span class='sevtug_small'><i>The Hierophant Network</i></span> to communicate silently with your master and their allies, \
but can only exit if your master calls your true name or if they are exceptionally damaged. \
\n\n\
Stay near your host to protect and heal them; being too far from your host will rapidly cause you massive damage. Recall to your host if you are too weak and believe you cannot continue \
fighting safely. As a final note, you should probably avoid harming any fellow servants of Ratvar.</span>"
/mob/living/simple_animal/hostile/clockwork/marauder/guardian/Initialize()
. = ..()
true_name = pick(possible_true_names)
/mob/living/simple_animal/hostile/clockwork/marauder/guardian/BiologicalLife(seconds, times_fired)
..()
if(is_in_host())
if(!is_servant_of_ratvar(host))
emerge_from_host(FALSE, TRUE)
unbind_from_host()
return
if(!GLOB.ratvar_awakens && host.stat == DEAD)
death()
return
if(GLOB.ratvar_awakens)
adjustHealth(-50)
else
adjustHealth(-10)
if(!recovering)
heal_host() //also heal our host if inside of them and we aren't recovering
else if(health == maxHealth)
to_chat(src, "<span class='userdanger'>Your strength has returned. You can once again come forward!</span>")
to_chat(host, "<span class='userdanger'>Your guardian is now strong enough to come forward again!</span>")
recovering = FALSE
else
if(GLOB.ratvar_awakens) //If Ratvar is alive, guardians don't need a host and are downright impossible to kill
adjustHealth(-5)
heal_host()
else if(host)
if(!is_servant_of_ratvar(host))
unbind_from_host()
return
if(host.stat == DEAD)
adjustHealth(50)
to_chat(src, "<span class='userdanger'>Your host is dead!</span>")
return
if(z && host.z && z == host.z)
switch(get_dist(get_turf(src), get_turf(host)))
if(2)
adjustHealth(-1)
if(3)
//EQUILIBRIUM
if(4)
adjustHealth(1)
if(5)
adjustHealth(3)
if(6)
adjustHealth(6)
if(7)
adjustHealth(9)
if(8 to INFINITY)
adjustHealth(15)
to_chat(src, "<span class='userdanger'>You're too far from your host and rapidly taking damage!</span>")
else //right next to or on top of host
adjustHealth(-2)
heal_host() //gradually heal host if nearby and host is very weak
else //well then, you're not even in the same zlevel
adjustHealth(15)
to_chat(src, "<span class='userdanger'>You're too far from your host and rapidly taking damage!</span>")
/mob/living/simple_animal/hostile/clockwork/marauder/guardian/death(gibbed)
emerge_from_host(FALSE, TRUE)
unbind_from_host()
visible_message("<span class='warning'>[src]'s equipment clatters lifelessly to the ground as the red flames within dissipate.</span>", \
"<span class='userdanger'>Your equipment falls away. You feel a moment of confusion before your fragile form is annihilated.</span>")
. = ..()
/mob/living/simple_animal/hostile/clockwork/marauder/guardian/Stat()
..()
if(statpanel("Status"))
stat(null, "Current True Name: [true_name]")
stat(null, "Host: [host ? host : "NONE"]")
if(host)
var/resulthealth = round((host.health / host.maxHealth) * 100, 0.5)
if(iscarbon(host))
resulthealth = round((abs(HEALTH_THRESHOLD_DEAD - host.health) / abs(HEALTH_THRESHOLD_DEAD - host.maxHealth)) * 100)
stat(null, "Host Health: [resulthealth]%")
if(GLOB.ratvar_awakens)
stat(null, "You are [recovering ? "un" : ""]able to deploy!")
else
if(resulthealth > GUARDIAN_EMERGE_THRESHOLD)
stat(null, "You are [recovering ? "unable to deploy" : "able to deploy on hearing your True Name"]!")
else
stat(null, "You are [recovering ? "unable to deploy" : "able to deploy to protect your host"]!")
stat(null, "You do [melee_damage_upper] damage on melee attacks.")
/mob/living/simple_animal/hostile/clockwork/marauder/guardian/Process_Spacemove(movement_dir = 0)
return 1
/mob/living/simple_animal/hostile/clockwork/marauder/guardian/proc/bind_to_host(mob/living/new_host)
if(!new_host)
return FALSE
host = new_host
var/datum/action/innate/summon_guardian/SG = new()
SG.linked_guardian = src
SG.Grant(host)
var/datum/action/innate/linked_minds/LM = new()
LM.linked_guardian = src
LM.Grant(host)
return TRUE
/mob/living/simple_animal/hostile/clockwork/marauder/guardian/proc/unbind_from_host()
if(host)
for(var/datum/action/innate/summon_guardian/SG in host.actions)
qdel(SG)
for(var/datum/action/innate/linked_minds/LM in host.actions)
qdel(LM)
host = null
return TRUE
return FALSE
//DAMAGE and FATIGUE
/mob/living/simple_animal/hostile/clockwork/marauder/guardian/proc/heal_host()
if(!host)
return
var/resulthealth = round((host.health / host.maxHealth) * 100, 0.5)
if(iscarbon(host))
resulthealth = round((abs(HEALTH_THRESHOLD_DEAD - host.health) / abs(HEALTH_THRESHOLD_DEAD - host.maxHealth)) * 100)
if(GLOB.ratvar_awakens || resulthealth <= GUARDIAN_EMERGE_THRESHOLD)
new /obj/effect/temp_visual/heal(host.loc, "#AF0AAF")
host.heal_ordered_damage(4, damage_heal_order)
/mob/living/simple_animal/hostile/clockwork/marauder/guardian/adjustHealth(amount, updating_health = TRUE, forced = FALSE)
if(amount > 0)
for(var/mob/living/L in view(2, src))
if(L.is_holding_item_of_type(/obj/item/nullrod))
to_chat(src, "<span class='userdanger'>The presence of a brandished holy artifact weakens your armor!</span>")
amount *= 4 //if a wielded null rod is nearby, it takes four times the health damage
break
. = ..()
if(src && updating_health)
update_health_hud()
update_stats()
/mob/living/simple_animal/hostile/clockwork/marauder/guardian/update_health_hud()
if(hud_used && hud_used.healths)
if(istype(hud_used, /datum/hud/marauder))
var/datum/hud/marauder/G = hud_used
var/resulthealth
if(host)
if(iscarbon(host))
resulthealth = "[round((abs(HEALTH_THRESHOLD_DEAD - host.health) / abs(HEALTH_THRESHOLD_DEAD - host.maxHealth)) * 100)]%"
else
resulthealth = "[round((host.health / host.maxHealth) * 100, 0.5)]%"
else
resulthealth = "NONE"
G.hosthealth.maptext = "<div align='center' valign='middle' style='position:relative; top:0px; left:6px'><font color='#AF0AAF'>HOST<br>[resulthealth]</font></div>"
hud_used.healths.maptext = "<div align='center' valign='middle' style='position:relative; top:0px; left:6px'><font color='#AF0AAF'>[round((health / maxHealth) * 100, 0.5)]%</font>"
/mob/living/simple_animal/hostile/clockwork/marauder/guardian/proc/update_stats()
if(GLOB.ratvar_awakens)
speed = 0
melee_damage_lower = 20
melee_damage_upper = 20
attack_verb_continuous = "devastates"
else
var/healthpercent = (health/maxHealth) * 100
switch(healthpercent)
if(100 to 70) //Bonuses to speed and damage at high health
speed = 0
melee_damage_lower = 16
melee_damage_upper = 16
attack_verb_continuous = "viciously slashes"
if(70 to 40)
speed = initial(speed)
melee_damage_lower = initial(melee_damage_lower)
melee_damage_upper = initial(melee_damage_upper)
attack_verb_continuous = initial(attack_verb_continuous)
if(40 to 30) //Damage decrease, but not speed
speed = initial(speed)
melee_damage_lower = 10
melee_damage_upper = 10
attack_verb_continuous = "lightly slashes"
if(30 to 20) //Speed decrease
speed = 2
melee_damage_lower = 8
melee_damage_upper = 8
attack_verb_continuous = "lightly slashes"
if(20 to 10) //Massive speed decrease and weak melee attacks
speed = 3
melee_damage_lower = 6
melee_damage_upper = 6
attack_verb_continuous = "weakly slashes"
if(10 to 0) //We are super weak and going to die
speed = 4
melee_damage_lower = 4
melee_damage_upper = 4
attack_verb_continuous = "taps"
//ATTACKING, BLOCKING, and COUNTERING
/mob/living/simple_animal/hostile/clockwork/marauder/guardian/AttackingTarget()
if(is_in_host())
return FALSE
return ..()
/mob/living/simple_animal/hostile/clockwork/marauder/guardian/bullet_act(obj/item/projectile/Proj)
if(blockOrCounter(null, Proj))
return
return ..()
/mob/living/simple_animal/hostile/clockwork/marauder/guardian/hitby(atom/movable/AM, skipcatch, hitpush, blocked, atom/movable/AM, datum/thrownthing/throwingdatum)
if(blockOrCounter(null, AM))
return
return ..()
/mob/living/simple_animal/hostile/clockwork/marauder/guardian/attack_animal(mob/living/simple_animal/M)
if(istype(M, /mob/living/simple_animal/hostile/clockwork/marauder/guardian) || !blockOrCounter(M, M)) //we don't want infinite blockcounter loops if fighting another guardian
return ..()
/mob/living/simple_animal/hostile/clockwork/marauder/guardian/attack_paw(mob/living/carbon/monkey/M)
if(!blockOrCounter(M, M))
return ..()
/mob/living/simple_animal/hostile/clockwork/marauder/guardian/attack_alien(mob/living/carbon/alien/humanoid/M)
if(!blockOrCounter(M, M))
return ..()
/mob/living/simple_animal/hostile/clockwork/marauder/guardian/attack_slime(mob/living/simple_animal/slime/M)
if(!blockOrCounter(M, M))
return ..()
/mob/living/simple_animal/hostile/clockwork/marauder/guardian/attack_hand(mob/living/carbon/human/M)
if(!blockOrCounter(M, M))
return ..()
/mob/living/simple_animal/hostile/clockwork/marauder/guardian/attackby(obj/item/I, mob/user, params)
if(istype(I, /obj/item/nullrod) || !blockOrCounter(user, I))
return ..()
/mob/living/simple_animal/hostile/clockwork/marauder/guardian/proc/blockOrCounter(mob/target, atom/textobject)
if(GLOB.ratvar_awakens) //if ratvar has woken, we block nearly everything at a very high chance
blockchance = 90
counterchance = 90
if(prob(blockchance))
. = TRUE
if(target)
target.do_attack_animation(src)
target.DelayNextAction(CLICK_CD_MELEE)
blockchance = initial(blockchance)
playsound(src, 'sound/magic/clockwork/fellowship_armory.ogg', 30, 1, 0, 1) //clang
visible_message("<span class='boldannounce'>[src] blocks [target && isitem(textobject) ? "[target]'s [textobject.name]":"\the [textobject]"]!</span>", \
"<span class='userdanger'>You block [target && isitem(textobject) ? "[target]'s [textobject.name]":"\the [textobject]"]!</span>")
if(target && Adjacent(target))
if(prob(counterchance))
counterchance = initial(counterchance)
var/previousattack_verb_continuous = attack_verb_continuous
attack_verb_continuous = "counters"
UnarmedAttack(target)
attack_verb_continuous = previousattack_verb_continuous
else
counterchance = min(counterchance + initial(counterchance), 100)
else
blockchance = min(blockchance + initial(blockchance), 100)
if(GLOB.ratvar_awakens)
blockchance = 90
counterchance = 90
//COMMUNICATION and EMERGENCE
/*
/mob/living/simple_animal/hostile/clockwork/marauder/guardian/handle_inherent_channels(message, message_mode)
if(host && (is_in_host() || message_mode == MODE_BINARY))
guardian_comms(message)
return TRUE
return ..()
*/
/mob/living/simple_animal/hostile/clockwork/marauder/guardian/proc/guardian_comms(message)
var/name_part = "<span class='sevtug'>[src] ([true_name])</span>"
message = "<span class='sevtug_small'>\"[message]\"</span>" //Processed output
to_chat(src, "[name_part]<span class='sevtug_small'>:</span> [message]")
to_chat(host, "[name_part]<span class='sevtug_small'>:</span> [message]")
for(var/M in GLOB.mob_list)
if(isobserver(M))
var/link = FOLLOW_LINK(M, src)
to_chat(M, "[link] [name_part] <span class='sevtug_small'>(to</span> <span class='sevtug'>[findtextEx(host.name, host.real_name) ? "[host.name]" : "[host.real_name] (as [host.name])"]</span><span class='sevtug_small'>):</span> [message] ")
return TRUE
/mob/living/simple_animal/hostile/clockwork/marauder/guardian/proc/return_to_host()
if(is_in_host())
return FALSE
if(!host)
to_chat(src, "<span class='warning'>You don't have a host!</span>")
return FALSE
var/resulthealth = round((host.health / host.maxHealth) * 100, 0.5)
if(iscarbon(host))
resulthealth = round((abs(HEALTH_THRESHOLD_DEAD - host.health) / abs(HEALTH_THRESHOLD_DEAD - host.maxHealth)) * 100)
host.visible_message("<span class='warning'>[host]'s skin flashes crimson!</span>", "<span class='sevtug'>You feel [true_name]'s consciousness settle in your mind.</span>")
visible_message("<span class='warning'>[src] suddenly disappears!</span>", "<span class='sevtug'>You return to [host].</span>")
forceMove(host)
if(resulthealth > GUARDIAN_EMERGE_THRESHOLD && health != maxHealth)
recovering = TRUE
to_chat(src, "<span class='userdanger'>You have weakened and will need to recover before manifesting again!</span>")
to_chat(host, "<span class='sevtug'>[true_name] has weakened and will need to recover before manifesting again!</span>")
return TRUE
/mob/living/simple_animal/hostile/clockwork/marauder/guardian/proc/try_emerge()
if(!host)
to_chat(src, "<span class='warning'>You don't have a host!</span>")
return FALSE
if(!GLOB.ratvar_awakens)
var/resulthealth = round((host.health / host.maxHealth) * 100, 0.5)
if(iscarbon(host))
resulthealth = round((abs(HEALTH_THRESHOLD_DEAD - host.health) / abs(HEALTH_THRESHOLD_DEAD - host.maxHealth)) * 100)
if(host.stat != DEAD && resulthealth > GUARDIAN_EMERGE_THRESHOLD) //if above 20 health, fails
to_chat(src, "<span class='warning'>Your host must be at [GUARDIAN_EMERGE_THRESHOLD]% or less health to emerge like this!</span>")
return FALSE
return emerge_from_host(FALSE)
/mob/living/simple_animal/hostile/clockwork/marauder/guardian/proc/emerge_from_host(hostchosen, force) //Notice that this is a proc rather than a verb - guardians can NOT exit at will, but they CAN return
if(!is_in_host())
return FALSE
if(!force && recovering)
if(hostchosen)
to_chat(host, "<span class='sevtug'>[true_name] is too weak to come forth!</span>")
else
to_chat(host, "<span class='sevtug'>[true_name] tries to emerge to protect you, but it's too weak!</span>")
to_chat(src, "<span class='userdanger'>You try to come forth, but you're too weak!</span>")
return FALSE
if(!force)
if(hostchosen) //guardian approved
to_chat(host, "<span class='sevtug'>Your words echo with power as [true_name] emerges from your body!</span>")
else
to_chat(host, "<span class='sevtug'>[true_name] emerges from your body to protect you!</span>")
forceMove(host.loc)
visible_message("<span class='warning'>[host]'s skin glows red as [name] emerges from their body!</span>", "<span class='sevtug_small'>You exit the safety of [host]'s body!</span>")
return TRUE
/mob/living/simple_animal/hostile/clockwork/marauder/guardian/get_alt_name()
return " ([text2ratvar(true_name)])"
/mob/living/simple_animal/hostile/clockwork/marauder/guardian/proc/is_in_host() //Checks if the guardian is inside of their host
return host && loc == host
//HOST ACTIONS
//Summon guardian action: Calls forth or recalls your guardian
/datum/action/innate/summon_guardian
name = "Force Guardian to Emerge/Recall"
desc = "Allows you to force your clockwork guardian to emerge or recall as required."
button_icon_state = "clockwork_marauder"
background_icon_state = "bg_clock"
check_flags = AB_CHECK_CONSCIOUS
buttontooltipstyle = "clockcult"
var/mob/living/simple_animal/hostile/clockwork/marauder/guardian/linked_guardian
var/list/defend_phrases = list("Defend me", "Come forth", "Assist me", "Protect me", "Give aid", "Help me")
var/list/return_phrases = list("Return", "Return to me", "Your job is done", "You have served", "Come back", "Retreat")
/datum/action/innate/summon_guardian/IsAvailable()
if(!linked_guardian)
return FALSE
if(isliving(owner))
var/mob/living/L = owner
if(!L.can_speak_vocal() || L.stat)
return FALSE
return ..()
/datum/action/innate/summon_guardian/Activate()
if(linked_guardian.is_in_host())
clockwork_say(owner, text2ratvar("[pick(defend_phrases)], [linked_guardian.true_name]!"))
linked_guardian.emerge_from_host(TRUE)
else
clockwork_say(owner, text2ratvar("[pick(return_phrases)], [linked_guardian.true_name]!"))
linked_guardian.return_to_host()
return TRUE
//Linked Minds action: talks to your guardian
/datum/action/innate/linked_minds
name = "Linked Minds"
desc = "Allows you to silently communicate with your guardian."
button_icon_state = "linked_minds"
background_icon_state = "bg_clock"
check_flags = AB_CHECK_CONSCIOUS
buttontooltipstyle = "clockcult"
var/mob/living/simple_animal/hostile/clockwork/marauder/guardian/linked_guardian
/datum/action/innate/linked_minds/IsAvailable()
if(!linked_guardian)
return FALSE
return ..()
/datum/action/innate/linked_minds/Activate()
var/message = stripped_input(owner, "Enter a message to tell your guardian.", "Telepathy")
if(!owner || !message)
return FALSE
if(!linked_guardian)
to_chat(owner, "<span class='warning'>Your guardian seems to have been destroyed!</span>")
return FALSE
var/name_part = "<span class='sevtug'>Servant [findtextEx(owner.name, owner.real_name) ? "[owner.name]" : "[owner.real_name] (as [owner.name])"]</span>"
message = "<span class='sevtug_small'>\"[message]\"</span>" //Processed output
to_chat(owner, "[name_part]<span class='sevtug_small'>:</span> [message]")
to_chat(linked_guardian, "[name_part]<span class='sevtug_small'>:</span> [message]")
for(var/M in GLOB.mob_list)
if(isobserver(M))
var/link = FOLLOW_LINK(M, src)
to_chat(M, "[link] [name_part] <span class='sevtug_small'>(to</span> <span class='sevtug'>[linked_guardian] ([linked_guardian.true_name])</span><span class='sevtug_small'>):</span> [message]")
return TRUE
@@ -5,7 +5,7 @@ Pieces of scripture require certain follower counts, contruction value, and acti
Drivers: Unlocked by default
Scripts: 35k power or one convert
Applications: 50k or three converts
Judgement 5 converts
Judgement 80k power or nine converts
*/
/datum/clockwork_scripture
@@ -18,7 +18,7 @@
tier = SCRIPTURE_APPLICATION
one_per_tile = TRUE
primary_component = HIEROPHANT_ANSIBLE
sort_priority = 1
sort_priority = 2
important = TRUE
quickbind = TRUE
quickbind_desc = "Creates a Sigil of Transmission, which can drain and will store power for clockwork structures."
@@ -72,7 +72,7 @@
tier = SCRIPTURE_APPLICATION
one_per_tile = TRUE
primary_component = HIEROPHANT_ANSIBLE
sort_priority = 2
sort_priority = 5
quickbind = TRUE
quickbind_desc = "Creates a Mania Motor, which causes minor damage and negative mental effects in non-Servants."
requires_full_power = TRUE
@@ -101,7 +101,7 @@
//Memory Allocation: Finds a willing ghost and makes them into a clockwork guardian for the invoker.
/datum/clockwork_scripture/memory_allocation
descname = "Personal Guardian, A Peice Of Your Mind."
descname = "Personal Guardian housed in the brain."
name = "Memory Allocation"
desc = "Allocates part of your consciousness to a Clockwork Guardian, a variant of Marauder that lives within you, able to be \
called forth by Speaking its True Name or if you become exceptionally low on health.<br>\
@@ -109,13 +109,13 @@
invocations = list("Fright's will...", "...call forth...")
channel_time = 100
power_cost = 8000
usage_tip = "guardians are useful as personal bodyguards and frontline warriors."
usage_tip = "Guardians are useful as personal bodyguards and frontline warriors."
tier = SCRIPTURE_APPLICATION
primary_component = GEIS_CAPACITOR
sort_priority = 5
sort_priority = 6
/datum/clockwork_scripture/memory_allocation/check_special_requirements()
for(var/mob/living/simple_animal/hostile/clockwork/marauder/guardian/M in GLOB.all_clockwork_mobs)
for(var/mob/living/simple_animal/hostile/clockwork/guardian/M in GLOB.all_clockwork_mobs)
if(M.host == invoker)
to_chat(invoker, "<span class='warning'>You can only house one guardian at a time!</span>")
return FALSE
@@ -151,7 +151,7 @@
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/guardian/M = new(invoker)
var/mob/living/simple_animal/hostile/clockwork/guardian/M = new(invoker)
M.key = theghost.key
M.bind_to_host(invoker)
invoker.visible_message("<span class='warning'>The tendril retracts from [invoker]'s head, sealing the entry wound as it does so!</span>", \
@@ -171,7 +171,7 @@
tier = SCRIPTURE_APPLICATION
one_per_tile = TRUE
primary_component = BELLIGERENT_EYE
sort_priority = 6
sort_priority = 7
quickbind = TRUE
quickbind_desc = "Creates a clockwork marauder, used for frontline combat."
object_path = /obj/item/clockwork/construct_chassis/clockwork_marauder
@@ -223,7 +223,7 @@
object_path = /obj/mecha/combat/neovgre
tier = SCRIPTURE_APPLICATION
primary_component = BELLIGERENT_EYE
sort_priority = 7
sort_priority = 8
creator_message = "<span class='brass'>Neovgre, the Anima Bulwark towers over you... your enemies reckoning has come.</span>"
/datum/clockwork_scripture/create_object/summon_arbiter/check_special_requirements()
@@ -20,7 +20,7 @@
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_APPLICATION
sort_priority = 8
sort_priority = 1
requires_full_power = TRUE
/datum/clockwork_scripture/create_object/ark_of_the_clockwork_justiciar/check_special_requirements()
@@ -81,7 +81,7 @@
priority_announce("Massive [Gibberish("bluespace", 100)] anomaly detected on all frequencies. All crew are directed to \
@!$, [text2ratvar("PURGE ALL UNTRUTHS")] <&. the anomalies and destroy their source to prevent further damage to corporate property. This is \
not a drill.", "Central Command Higher Dimensional Affairs", 'sound/magic/clockwork/ark_activation_sequence.ogg')
set_security_level("delta")
set_security_level("Delta")
for(var/V in SSticker.mode.servants_of_ratvar)
var/datum/mind/M = V
if(!M || !M.current)
@@ -29,8 +29,9 @@
sound_to_playing_players('sound/effects/ratvar_reveal.ogg')
var/mutable_appearance/alert_overlay = mutable_appearance('icons/effects/clockwork_effects.dmi', "ratvar_alert")
notify_ghosts("The Justiciar's light calls to you! Reach out to Ratvar in [get_area_name(src)] to be granted a shell to spread his glory!", null, source = src, alert_overlay = alert_overlay)
INVOKE_ASYNC(SSshuttle.emergency, /obj/docking_port/mobile/emergency.proc/request, null, 10, null, FALSE, 0)
SSpersistence.station_was_destroyed = TRUE
INVOKE_ASYNC(src, .proc/purge_the_heresy)
/obj/structure/destructible/clockwork/massive/ratvar/Destroy()
GLOB.ratvar_awakens--
@@ -151,3 +152,34 @@
sound_to_playing_players('sound/machines/clockcult/ratvar_scream.ogg', 80)
narsie.clashing = FALSE
qdel(src)
/obj/structure/destructible/clockwork/massive/ratvar/proc/purge_the_heresy()
sleep(50)
priority_announce("Massive energy surge detected. Closest matching threat: Incoming supernova. All crew are advised to evacuate NAN lightyears away from blast zone","Central Command Higher Dimensional Affairs", 'sound/misc/airraid.ogg')
sleep(300)
priority_announce("Gravitational anomalies detected on the station. [Gibberish("There is no additional dat", 100)]-BZZZZZT.","Central Command Higher Dimensional Affairs", 'sound/magic/clockwork/ratvar_announce1.ogg')
sleep(80)
sound_to_playing_players('sound/magic/clockwork/ratvar_announce2.ogg', 70)
send_to_playing_players("<span class='heavy_brass'><font size=5>\"COME, ALL THOSE FAITHFUL! WITNESS THE RAYS OF JUSTICE CAST UPON THE HERETICS!\"</font></span>")
sleep(50)
SSshuttle.registerHostileEnvironment(src)
SSshuttle.lockdown = TRUE
sleep(250)
if(QDELETED(src))
priority_announce("Energy signal no longer detected.","Central Command Higher Dimensional Affairs")
return
sound_to_playing_players('sound/magic/clockwork/ark_activation_sequence.ogg', 80) //if this isn't lessened in volume it peaks for some reason
addtimer(CALLBACK(GLOBAL_PROC, /proc/clockcult_ending_helper), 300)
/proc/clockcult_ending_helper()
for(var/mob/M in GLOB.mob_list)
if(M.client)
SEND_SOUND(M, sound('sound/magic/clockwork/ratvar_attack.ogg'))
SEND_SOUND(M, sound('sound/magic/clockwork/ratvarfire.ogg'))
if(!is_servant_of_ratvar(M) && isliving(M))
var/mob/living/L = M
L.fire_stacks = INFINITY
L.IgniteMob()
sleep(50)
SSticker.force_ending = 1
@@ -1,7 +1,7 @@
/obj/structure/destructible/clockwork/reflector
name = "reflector"
desc = "A large lantern-shaped machine made of thin brass. It looks fragile."
clockwork_desc = "A lantern-shaped generator that produces power when near starlight."
desc = "A large mirror-like structure made of thin brass on one side. It looks fragile."
clockwork_desc = "A large mirror-like structure made of thin brass on one side. It can redirect laser fire on one side"
icon_state = "reflector"
unanchored_icon = "reflector_unwrenched"
max_integrity = 40
@@ -5,7 +5,7 @@
antagpanel_category = "Clockcult"
job_rank = ROLE_SERVANT_OF_RATVAR
antag_moodlet = /datum/mood_event/cult
skill_modifiers = list(/datum/skill_modifier/job/level/wiring)
skill_modifiers = list(/datum/skill_modifier/job/level/wiring, /datum/skill_modifier/job/level/dwarfy/blacksmithing)
var/datum/action/innate/hierophant/hierophant_network = new
threat = 3
var/datum/team/clockcult/clock_team
+1 -1
View File
@@ -83,7 +83,7 @@
if(choice == "Yes" && IsAvailable())
var/datum/antagonist/cult/C = owner.mind.has_antag_datum(/datum/antagonist/cult,TRUE)
if(!C.cult_team)
to_chat(owner, "<span class='cult bold'>Do you not alreaady lead yourself?</span>")
to_chat(owner, "<span class='cult bold'>Do you not already lead yourself?</span>")
return
pollCultists(owner,C.cult_team)
@@ -25,9 +25,9 @@
to_chat(owner, "<span class='boldannounce'>You are the Heretic!</span><br>\
<B>The old ones gave you these tasks to fulfill:</B>")
owner.announce_objectives()
to_chat(owner, "<span class='cult'>The book whispers, the forbidden knowledge walks once again!<br>\
Your book allows you to research abilities, but be careful, you cannot undo what has been done.<br>\
You gain charges by either collecting influences or sacrificing people tracked by the living heart<br> \
to_chat(owner, "<span class='cult'>The book whispers softly, its forbidden knowledge walks this plane once again!<br>\
Your book allows you to research abilities. Read it very carefully, for you cannot undo what has been done!<br>\
You gain charges by either collecting influences or sacrificing people tracked by the living heart.<br> \
You can find a basic guide at : https://tgstation13.org/wiki/Heresy_101 </span>")
/datum/antagonist/heretic/on_gain()
@@ -39,7 +39,6 @@
gain_knowledge(/datum/eldritch_knowledge/spell/basic)
gain_knowledge(/datum/eldritch_knowledge/living_heart)
gain_knowledge(/datum/eldritch_knowledge/codex_cicatrix)
gain_knowledge(/datum/eldritch_knowledge/eldritch_blade)
current.log_message("has been converted to the cult of the forgotten ones!", LOG_ATTACK, color="#960000")
GLOB.reality_smash_track.AddMind(owner)
START_PROCESSING(SSprocessing,src)
@@ -59,6 +58,8 @@
GLOB.reality_smash_track.RemoveMind(owner)
STOP_PROCESSING(SSprocessing,src)
on_death()
return ..()
@@ -90,15 +91,25 @@
/datum/antagonist/heretic/process()
if(owner.current.stat == DEAD)
return
for(var/X in researched_knowledge)
var/datum/eldritch_knowledge/EK = researched_knowledge[X]
EK.on_life(owner.current)
///What happens to the heretic once he dies, used to remove any custom perks
/datum/antagonist/heretic/proc/on_death()
for(var/X in researched_knowledge)
var/datum/eldritch_knowledge/EK = researched_knowledge[X]
EK.on_death(owner.current)
/datum/antagonist/heretic/proc/forge_primary_objectives()
var/list/assasination = list()
var/list/protection = list()
for(var/i in 1 to 2)
var/pck = pick("assasinate","protect")
var/pck = pick("assasinate")
switch(pck)
if("assasinate")
var/datum/objective/assassinate/once/A = new
@@ -107,13 +118,6 @@
A.find_target(owners,protection)
assasination += A.target
objectives += A
if("protect")
var/datum/objective/protect/P = new
P.owner = owner
var/list/owners = P.get_owners()
P.find_target(owners,assasination)
protection += P.target
objectives += P
var/datum/objective/sacrifice_ecult/SE = new
SE.owner = owner
@@ -126,7 +130,7 @@
if(mob_override)
current = mob_override
add_antag_hud(antag_hud_type, antag_hud_name, current)
handle_clown_mutation(current, mob_override ? null : "Knowledge described in the book allowed you to overcome your clownish nature, allowing you to use complex items effectively.")
handle_clown_mutation(current, mob_override ? null : "Ancient knowledge described in the book allows you to overcome your clownish nature, allowing you to use complex items effectively.")
current.faction |= "heretics"
/datum/antagonist/heretic/remove_innate_effects(mob/living/mob_override)
@@ -161,7 +165,7 @@
cultiewin = FALSE
count++
if(ascended)
parts += "<span class='greentext big'>HERETIC HAS ASCENDED!</span>"
parts += "<span class='greentext big'>THE HERETIC ASCENDED!</span>"
else
if(cultiewin)
parts += "<span class='greentext'>The heretic was successful!</span>"
@@ -1,6 +1,6 @@
/obj/item/forbidden_book
name = "Codex Cicatrix"
desc = "Book describing the secrets of the veil."
desc = "This book describes the secrets of the veil between worlds."
icon = 'icons/obj/eldritch.dmi'
icon_state = "codex"
item_state = "codex"
@@ -74,8 +74,8 @@
last_user = user
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
icon_state = "book_open"
flick("book_opening", src)
icon_state = "codex_open"
flick("codex_opening", src)
ui = new(user, src, "ForbiddenLore", name)
ui.open()
@@ -133,13 +133,13 @@
if(initial(EK.name) != ekname)
continue
if(cultie.gain_knowledge(EK))
charge -= text2num(params["cost"])
charge -= initial(EK.cost)
return TRUE
update_icon() // Not applicable to all objects.
/obj/item/forbidden_book/ui_close(mob/user)
flick("book_closing",src)
flick("codex_closing",src)
icon_state = initial(icon_state)
return ..()
@@ -1,6 +1,6 @@
/obj/effect/eldritch
name = "Generic rune"
desc = "Weird combination of shapes and symbols etched into the floor itself. The indentation is filled with thick black tar-like fluid."
desc = "A flowing circle of shapes and runes is etched into the floor, filled with a thick black tar-like fluid."
anchored = TRUE
icon_state = ""
resistance_flags = FIRE_PROOF | UNACIDABLE | ACID_PROOF
@@ -14,7 +14,7 @@
I.override = TRUE
add_alt_appearance(/datum/atom_hud/alternate_appearance/basic/silicons, "heretic_rune", I)
/obj/effect/eldritch/attack_hand(mob/living/user)
/obj/effect/eldritch/attack_hand(mob/living/user, list/modifiers)
. = ..()
if(.)
return
@@ -81,7 +81,7 @@
continue
flick("[icon_state]_active",src)
playsound(user, 'sound/magic/castsummon.ogg', 75, TRUE)
playsound(user, 'sound/magic/castsummon.ogg', 75, TRUE, extrarange = SILENCED_SOUND_EXTRARANGE, falloff_exponent = 10)
//we are doing this since some on_finished_recipe subtract the atoms from selected_atoms making them invisible permanently.
var/list/atoms_to_disappear = selected_atoms.Copy()
for(var/to_disappear in atoms_to_disappear)
@@ -90,31 +90,31 @@
atom_to_disappear.invisibility = INVISIBILITY_ABSTRACT
if(current_eldritch_knowledge.on_finished_recipe(user,selected_atoms,loc))
current_eldritch_knowledge.cleanup_atoms(selected_atoms)
is_in_use = FALSE
for(var/to_appear in atoms_to_disappear)
var/atom/atom_to_appear = to_appear
//we need to reappear the item just in case the ritual didnt consume everything... or something.
atom_to_appear.invisibility = initial(atom_to_appear.invisibility)
is_in_use = FALSE
return
is_in_use = FALSE
to_chat(user,"<span class='warning'>Your ritual failed! You used either wrong components or are missing something important!</span>")
to_chat(user,"<span class='warning'>Your ritual failed! You either used the wrong components or are missing something important!</span>")
/obj/effect/eldritch/big
name = "transmutation circle"
name = "transmutation rune"
icon = 'icons/effects/96x96.dmi'
icon_state = "eldritch_rune1"
pixel_x = -32 //So the big ol' 96x96 sprite shows up right
pixel_y = -32
/**
* #Reality smash tracker
*
* Stupid fucking list holder, DONT create new ones, it will break the game, this is automnatically created whenever eldritch cultists are created.
*
* Tracks relevant data, generates relevant data, useful tool
*/
* #Reality smash tracker
*
* Stupid fucking list holder, DONT create new ones, it will break the game, this is automnatically created whenever eldritch cultists are created.
*
* Tracks relevant data, generates relevant data, useful tool
*/
/datum/reality_smash_tracker
///list of tracked reality smashes
var/list/smashes = list()
@@ -127,12 +127,11 @@
QDEL_LIST(smashes)
targets.Cut()
return ..()
/**
* Automatically fixes the target and smash network
*
* Fixes any bugs that are caused by late Generate() or exchanging clients
*/
* Automatically fixes the target and smash network
*
* Fixes any bugs that are caused by late Generate() or exchanging clients
*/
/datum/reality_smash_tracker/proc/ReworkNetwork()
listclearnulls(smashes)
for(var/mind in targets)
@@ -144,52 +143,51 @@
reality_smash.AddMind(mind)
/**
* Generates a set amount of reality smashes based on the N value
*
* Automatically creates more reality smashes
*/
/datum/reality_smash_tracker/proc/_Generate()
* Generates a set amount of reality smashes based on the N value
*
* Automatically creates more reality smashes
*/
/datum/reality_smash_tracker/proc/Generate(mob/caller)
if(istype(caller))
targets += caller
var/targ_len = length(targets)
var/smash_len = length(smashes)
var/number = targ_len * 6 - smash_len
var/number = max(targ_len * (6-(targ_len-1)) - smash_len,1)
for(var/i in 0 to number)
var/turf/chosen_location = get_safe_random_station_turf()
//we also dont want them close to each other, at least 1 tile of seperation
var/obj/effect/reality_smash/what_if_i_have_one = locate() in range(1, chosen_location)
var/obj/effect/broken_illusion/what_if_i_had_one_but_got_used = locate() in range(1, chosen_location)
if(what_if_i_have_one || what_if_i_had_one_but_got_used) //we dont want to spawn
continue
var/obj/effect/reality_smash/RS = new/obj/effect/reality_smash(chosen_location)
smashes += RS
new /obj/effect/reality_smash(chosen_location)
ReworkNetwork()
/**
* Adds a mind to the list of people that can see the reality smashes
*
* Use this whenever you want to add someone to the list
*/
/datum/reality_smash_tracker/proc/AddMind(var/datum/mind/M)
RegisterSignal(M.current,COMSIG_MOB_CLIENT_LOGIN,.proc/ReworkNetwork)
targets |= M
_Generate()
for(var/X in smashes)
var/obj/effect/reality_smash/reality_smash = X
reality_smash.AddMind(M)
* Adds a mind to the list of people that can see the reality smashes
*
* Use this whenever you want to add someone to the list
*/
/datum/reality_smash_tracker/proc/AddMind(datum/mind/e_cultists)
RegisterSignal(e_cultists.current,COMSIG_MOB_CLIENT_LOGIN,.proc/ReworkNetwork)
targets |= e_cultists
Generate()
for(var/obj/effect/reality_smash/reality_smash in smashes)
reality_smash.AddMind(e_cultists)
/**
* Removes a mind from the list of people that can see the reality smashes
*
* Use this whenever you want to remove someone from the list
*/
/datum/reality_smash_tracker/proc/RemoveMind(var/datum/mind/M)
UnregisterSignal(M.current,COMSIG_MOB_CLIENT_LOGIN)
targets -= M
for(var/obj/effect/reality_smash/RS in smashes)
RS.RemoveMind(M)
* Removes a mind from the list of people that can see the reality smashes
*
* Use this whenever you want to remove someone from the list
*/
/datum/reality_smash_tracker/proc/RemoveMind(datum/mind/e_cultists)
UnregisterSignal(e_cultists.current,COMSIG_MOB_CLIENT_LOGIN)
targets -= e_cultists
for(var/obj/effect/reality_smash/reality_smash in smashes)
reality_smash.RemoveMind(e_cultists)
/obj/effect/broken_illusion
name = "pierced reality"
@@ -198,66 +196,67 @@
anchored = TRUE
resistance_flags = FIRE_PROOF | UNACIDABLE | ACID_PROOF
alpha = 0
invisibility = INVISIBILITY_OBSERVER
/obj/effect/broken_illusion/Initialize()
. = ..()
addtimer(CALLBACK(src, .proc/show_presence), 15 SECONDS)
var/image/I = image(icon = 'icons/effects/eldritch.dmi', icon_state = null, loc = src)
addtimer(CALLBACK(src,.proc/show_presence),15 SECONDS)
var/image/I = image('icons/effects/eldritch.dmi',src,null,OBJ_LAYER)
I.override = TRUE
add_alt_appearance(/datum/atom_hud/alternate_appearance/basic/silicons, "pierced_reality", I)
///Makes this obj appear out of nothing
/obj/effect/broken_illusion/proc/show_presence()
invisibility = 0
animate(src, alpha = 255, time = 15 SECONDS)
animate(src,alpha = 255,time = 15 SECONDS)
/obj/effect/broken_illusion/attack_hand(mob/living/user)
/obj/effect/broken_illusion/attack_hand(mob/living/user, list/modifiers)
if(!ishuman(user))
return ..()
var/mob/living/carbon/human/human_user = user
if(IS_HERETIC(human_user))
to_chat(human_user,"<span class='boldwarning'>You know better than to tempt forces out of your control.</span>")
to_chat(human_user,"<span class='boldwarning'>You know better than to tempt forces out of your control!</span>")
else
var/obj/item/bodypart/arm = human_user.get_active_hand()
if(prob(25))
to_chat(human_user,"<span class='userdanger'>An otherwordly presence tears your arm apart into atoms as you try to touch the hole in the very fabric of reality!</span>")
to_chat(human_user,"<span class='userdanger'>An otherwordly presence tears and atomizes your arm as you try to touch the hole in the very fabric of reality!</span>")
arm.dismember()
qdel(arm)
else
to_chat(human_user,"<span class='danger'>You pull your hand away from the hole as eldritch energy flails out, trying to latch onto existence itself!</span>")
to_chat(human_user,"<span class='danger'>You pull your hand away from the hole as the eldritch energy flails trying to latch onto existance itself!</span>")
/obj/effect/broken_illusion/attack_tk(mob/user)
if(!ishuman(user))
return
var/mob/living/carbon/human/human_user = user
if(IS_HERETIC(human_user))
to_chat(human_user,"<span class='boldwarning'>You know better than to tempt forces out of your control.</span>")
to_chat(human_user,"<span class='boldwarning'>You know better than to tempt forces out of your control!</span>")
return
//a very elaborate way to suicide
to_chat(human_user,"<span class='userdanger'>Eldritch energy lashes out, piercing your fragile mind, tearing it to pieces!</span>")
human_user.ghostize()
var/obj/item/bodypart/head/head = locate() in human_user.bodyparts
if(head)
head.dismember()
qdel(head)
else
//a very elaborate way to suicide
to_chat(human_user,"<span class='userdanger'>Eldritch energy lashes out, piercing your fragile mind, tearing it to pieces!</span>")
human_user.ghostize()
var/obj/item/bodypart/head/head = locate() in human_user.bodyparts
if(head)
head.dismember()
qdel(head)
else
human_user.gib()
human_user.gib()
var/datum/effect_system/reagents_explosion/explosion = new()
explosion.set_up(1, get_turf(human_user), TRUE, 0)
explosion.start()
var/datum/effect_system/reagents_explosion/explosion = new()
explosion.set_up(1, get_turf(human_user), 1, 0)
explosion.start()
/obj/effect/broken_illusion/examine(mob/user)
. = ..()
if(!IS_HERETIC(user) && ishuman(user))
var/mob/living/carbon/human/human_user = user
to_chat(human_user,"<span class='userdanger'>Your brain hurts when you look at this!</span>")
human_user.adjustOrganLoss(ORGAN_SLOT_BRAIN,20,190)
to_chat(human_user,"<span class='warning'>Your mind burns as you stare at the tear!</span>")
human_user.adjustOrganLoss(ORGAN_SLOT_BRAIN,10,190)
SEND_SIGNAL(human_user, COMSIG_ADD_MOOD_EVENT, "gates_of_mansus", /datum/mood_event/gates_of_mansus)
log_game("[key_name(user)] stared at a pierced reality at [AREACOORD(user)]")
/obj/effect/reality_smash
name = "/improper reality smash"
name = "reality smash"
icon = 'icons/effects/eldritch.dmi'
anchored = TRUE
resistance_flags = FIRE_PROOF | UNACIDABLE | ACID_PROOF
@@ -271,44 +270,41 @@
/obj/effect/reality_smash/Initialize()
. = ..()
GLOB.reality_smash_track.smashes += src
img = image(icon, src, image_state, OBJ_LAYER)
generate_name()
/obj/effect/reality_smash/Destroy()
GLOB.reality_smash_track.smashes -= src
on_destroy()
return ..()
///Custom effect that happens on destruction
/obj/effect/reality_smash/proc/on_destroy()
for(var/cm in minds)
var/datum/mind/cultie = cm
if(cultie.current?.client)
cultie.current.client.images -= img
for(var/e_cultists in minds)
var/datum/mind/e_cultie = e_cultists
if(e_cultie.current?.client)
e_cultie.current.client.images -= img
//clear the list
minds -= cultie
GLOB.reality_smash_track.smashes -= src
minds -= e_cultie
img = null
new /obj/effect/broken_illusion(drop_location())
var/obj/effect/broken_illusion/illusion = new /obj/effect/broken_illusion(drop_location())
illusion.name = pick("Researched","Siphoned","Analyzed","Emptied","Drained") + " " + name
///Makes the mind able to see this effect
/obj/effect/reality_smash/proc/AddMind(var/datum/mind/cultie)
minds |= cultie
if(cultie.current.client)
cultie.current.client.images |= img
/obj/effect/reality_smash/proc/AddMind(datum/mind/e_cultie)
minds |= e_cultie
if(e_cultie.current.client)
e_cultie.current.client.images |= img
///Makes the mind not able to see this effect
/obj/effect/reality_smash/proc/RemoveMind(var/datum/mind/cultie)
minds -= cultie
if(cultie.current.client)
cultie.current.client.images -= img
/obj/effect/reality_smash/proc/RemoveMind(datum/mind/e_cultie)
minds -= e_cultie
if(e_cultie.current.client)
e_cultie.current.client.images -= img
///Generates random name
/obj/effect/reality_smash/proc/generate_name()
var/static/list/prefix = list("Omniscient","Thundering","Enlightening","Intrusive","Rejectful","Atomized","Subtle","Rising","Lowering","Fleeting","Towering","Blissful","Arrogant","Threatening","Peaceful","Aggressive")
var/static/list/postfix = list("Flaw","Presence","Crack","Heat","Cold","Memory","Reminder","Breeze","Grasp","Sight","Whisper","Flow","Touch","Veil","Thought","Imperfection","Blemish","Blush")
name = pick(prefix) + " " + pick(postfix)
name = "\improper" + pick(prefix) + " " + pick(postfix)
@@ -1,6 +1,6 @@
/obj/item/living_heart
name = "living heart"
desc = "Link to the worlds beyond."
desc = "A link to the worlds beyond."
icon = 'icons/obj/eldritch.dmi'
icon_state = "living_heart"
w_class = WEIGHT_CLASS_SMALL
@@ -35,7 +35,7 @@
if(0 to 15)
to_chat(user,"<span class='warning'>[target.real_name] is near you. They are to the [dir2text(dir)] of you!</span>")
if(16 to 31)
to_chat(user,"<span class='warning'>[target.real_name] is somewhere in your vicinty. They are to the [dir2text(dir)] of you!</span>")
to_chat(user,"<span class='warning'>[target.real_name] is somewhere in your vicinity. They are to the [dir2text(dir)] of you!</span>")
if(32 to 127)
to_chat(user,"<span class='warning'>[target.real_name] is far away from you. They are to the [dir2text(dir)] of you!</span>")
else
@@ -46,12 +46,11 @@
/datum/action/innate/heretic_shatter
name = "Shattering Offer"
desc = "By breaking your blade, you will be granted salvation from a dire situation. (Teleports you to a random safe turf on your current z level, but destroys your blade.)"
desc = "After a brief delay, you will be granted salvation from a dire situation at the cost of your blade. (Teleports you to a random safe turf on your current z level after a windup, but destroys your blade.)"
background_icon_state = "bg_ecult"
button_icon_state = "shatter"
icon_icon = 'icons/mob/actions/actions_ecult.dmi'
check_flags = NONE // required_mobility_flags handles this
required_mobility_flags = MOBILITY_HOLD|MOBILITY_MOVE|MOBILITY_USE
check_flags = MOBILITY_HOLD|MOBILITY_MOVE|MOBILITY_USE
var/mob/living/carbon/human/holder
var/obj/item/melee/sickly_blade/sword
@@ -63,19 +62,19 @@
/datum/action/innate/heretic_shatter/IsAvailable()
if(IS_HERETIC(holder) || IS_HERETIC_MONSTER(holder))
return ..()
return TRUE
else
return FALSE
/datum/action/innate/heretic_shatter/Activate()
. = ..()
var/turf/safe_turf = find_safe_turf(zlevels = sword.z, extended_safety_checks = TRUE)
do_teleport(holder,safe_turf,forceMove = TRUE)
to_chat(holder,"<span class='warning'>You feel a gust of energy flow through your body... the Rusted Hills heard your call...</span>")
qdel(sword)
if(do_after(holder,10, target = holder))
var/turf/safe_turf = find_safe_turf(zlevels = sword.z, extended_safety_checks = TRUE)
do_teleport(holder,safe_turf,forceMove = TRUE)
to_chat(holder,"<span class='warning'>You feel a gust of energy flow through your body... the Rusted Hills heard your call...</span>")
qdel(sword)
/obj/item/melee/sickly_blade
name = "eldritch blade"
name = "sickly blade"
desc = "A sickly green crescent blade, decorated with an ornamental eye. You feel like you're being watched..."
icon = 'icons/obj/eldritch.dmi'
icon_state = "eldritch_blade"
@@ -97,12 +96,17 @@
. = ..()
linked_action = new(src)
/obj/item/melee/sickly_blade/attack(mob/living/M, mob/living/user)
if(!(IS_HERETIC(user) || !IS_HERETIC_MONSTER(user)))
to_chat(user,"<span class='danger'>You feel a pulse of some alien intellect lash out at your mind!</span>")
var/mob/living/carbon/human/human_user = user
human_user.AdjustParalyzed(5 SECONDS)
return FALSE
/obj/item/melee/sickly_blade/attack(mob/living/target, mob/living/user)
if(!(IS_HERETIC(user) || IS_HERETIC_MONSTER(user)))
to_chat(user,"<span class='danger'>You feel a pulse of alien intellect lash out at your mind!</span>")
user.DefaultCombatKnockdown(100)
user.dropItemToGround(src, TRUE)
if(ishuman(user))
var/mob/living/carbon/human/H = user
H.apply_damage(rand(force/2, force), BRUTE, pick(BODY_ZONE_L_ARM, BODY_ZONE_R_ARM))
else
user.adjustBruteLoss(rand(force/2,force))
return
return ..()
/obj/item/melee/sickly_blade/pickup(mob/user)
@@ -116,20 +120,22 @@
/obj/item/melee/sickly_blade/afterattack(atom/target, mob/user, proximity_flag, click_parameters)
. = ..()
var/datum/antagonist/heretic/cultie = user.mind.has_antag_datum(/datum/antagonist/heretic)
if(!cultie || !proximity_flag)
if(!cultie)
return
var/list/knowledge = cultie.get_all_knowledge()
for(var/X in knowledge)
var/datum/eldritch_knowledge/eldritch_knowledge_datum = knowledge[X]
eldritch_knowledge_datum.on_eldritch_blade(target,user,proximity_flag,click_parameters)
if(proximity_flag)
eldritch_knowledge_datum.on_eldritch_blade(target,user,proximity_flag,click_parameters)
else
eldritch_knowledge_datum.on_ranged_attack_eldritch_blade(target,user,click_parameters)
/obj/item/melee/sickly_blade/rust
name = "rusted blade"
desc = "This crescent blade is decrepit, wasting to dust. Yet still it bites, catching flesh with jagged, rotten teeth."
desc = "This crescent blade is decrepit, wasting to rust. Yet still it bites, ripping flesh and bone with jagged, rotten teeth."
icon_state = "rust_blade"
item_state = "rust_blade"
embedding = list("pain_mult" = 4, "embed_chance" = 75, "fall_chance" = 10, "ignore_throwspeed_threshold" = TRUE)
throwforce = 17
/obj/item/melee/sickly_blade/ash
name = "ashen blade"
@@ -140,15 +146,22 @@
/obj/item/melee/sickly_blade/flesh
name = "flesh blade"
desc = "A crescent blade born from a fleshwarped creature. Keenly aware, it seeks to spread to others the excruciations it has endured from dead origins."
desc = "A crescent blade born from a fleshwarped creature. Keenly aware, it seeks to spread to others the suffering it has endured from its dreadful origins."
icon_state = "flesh_blade"
item_state = "flesh_blade"
wound_bonus = 10
bare_wound_bonus = 20
/obj/item/melee/sickly_blade/void
name = "void blade"
desc = "Devoid of any substance, this blade reflects nothingness. It is a real depiction of purity, and chaos that ensues after its implementation."
icon_state = "void_blade"
item_state = "void_blade"
throwforce = 25
/obj/item/clothing/neck/eldritch_amulet
name = "warm eldritch medallion"
desc = "A strange medallion. Peering through the crystalline surface, the world around you melts away. You see your own beating heart, and the pulse of a thousand others."
desc = "A strange medallion. Peering through the crystalline surface, the world around you melts away. You see your own beating heart, and the pulsing of a thousand others."
icon = 'icons/obj/eldritch.dmi'
icon_state = "eye_medalion"
w_class = WEIGHT_CLASS_SMALL
@@ -186,7 +199,7 @@
item_state = "eldritch_armor"
flags_inv = HIDESHOES|HIDEJUMPSUIT
body_parts_covered = CHEST|GROIN|LEGS|FEET|ARMS
allowed = list(/obj/item/melee/sickly_blade, /obj/item/forbidden_book)
allowed = list(/obj/item/melee/sickly_blade, /obj/item/forbidden_book, /obj/item/living_heart)
hoodtype = /obj/item/clothing/head/hooded/cult_hoodie/eldritch
// slightly better than normal cult robes
armor = list("melee" = 50, "bullet" = 50, "laser" = 50,"energy" = 50, "bomb" = 35, "bio" = 20, "rad" = 0, "fire" = 20, "acid" = 20)
@@ -194,7 +207,242 @@
/obj/item/reagent_containers/glass/beaker/eldritch
name = "flask of eldritch essence"
desc = "Toxic to the close minded. Healing to those with knowledge of the beyond."
desc = "Toxic to the closed minded, yet refreshing to those with knowledge of the beyond."
icon = 'icons/obj/eldritch.dmi'
icon_state = "eldrich_flask"
list_reagents = list(/datum/reagent/eldritch = 50)
/obj/item/clothing/head/hooded/cult_hoodie/void
name = "void hood"
icon_state = "void_cloak"
flags_inv = NONE
flags_cover = NONE
desc = "Black like tar, doesn't reflect any light. Runic symbols line the outside, with each flash you lose comprehension of what you are seeing."
item_flags = EXAMINE_SKIP
armor = list("melee" = 30, "bullet" = 30, "laser" = 30,"energy" = 30, "bomb" = 15, "bio" = 0, "rad" = 0, "fire" = 0, "acid" = 0)
/obj/item/clothing/suit/hooded/cultrobes/void
name = "void cloak"
desc = "Black like tar, doesn't reflect any light. Runic symbols line the outside, with each flash you loose comprehension of what you are seeing."
icon_state = "void_cloak"
item_state = "void_cloak"
allowed = list(/obj/item/melee/sickly_blade, /obj/item/forbidden_book, /obj/item/living_heart)
hoodtype = /obj/item/clothing/head/hooded/cult_hoodie/void
flags_inv = NONE
// slightly worse than normal cult robes
armor = list("melee" = 30, "bullet" = 30, "laser" = 30,"energy" = 30, "bomb" = 15, "bio" = 0, "rad" = 0, "fire" = 0, "acid" = 0)
pocket_storage_component_path = /datum/component/storage/concrete/pockets/void_cloak
/obj/item/clothing/suit/hooded/cultrobes/void/ToggleHood()
if(!iscarbon(loc))
return
var/mob/living/carbon/carbon_user = loc
if(IS_HERETIC(carbon_user) || IS_HERETIC_MONSTER(carbon_user))
. = ..()
//We need to account for the hood shenanigans, and that way we can make sure items always fit, even if one of the slots is used by the fucking hood.
if(suittoggled)
to_chat(carbon_user,"<span class='notice'>The light shifts around you making the cloak invisible!</span>")
else
to_chat(carbon_user,"<span class='notice'>The kaleidoscope of colours collapses around you, as the cloak shifts to visibility!</span>")
item_flags = suittoggled ? EXAMINE_SKIP : ~EXAMINE_SKIP
else
to_chat(carbon_user,"<span class='danger'>You can't force the hood onto your head!</span>")
/obj/item/clothing/mask/void_mask
name = "abyssal mask"
desc = "Mask created from the suffering of existance, you can look down it's eyes, and notice something gazing back at you."
icon_state = "mad_mask"
item_state = "mad_mask"
w_class = WEIGHT_CLASS_SMALL
flags_cover = MASKCOVERSEYES
resistance_flags = FLAMMABLE
flags_inv = HIDEFACE|HIDEFACIALHAIR
///Who is wearing this
var/mob/living/carbon/human/local_user
/obj/item/clothing/mask/void_mask/equipped(mob/user, slot)
. = ..()
if(ishuman(user) && user.mind && slot == SLOT_WEAR_MASK)
local_user = user
START_PROCESSING(SSobj, src)
if(IS_HERETIC(user) || IS_HERETIC_MONSTER(user))
return
ADD_TRAIT(src, TRAIT_NODROP, CLOTHING_TRAIT)
/obj/item/clothing/mask/void_mask/dropped(mob/M)
local_user = null
STOP_PROCESSING(SSobj, src)
REMOVE_TRAIT(src, TRAIT_NODROP, CLOTHING_TRAIT)
return ..()
/obj/item/clothing/mask/void_mask/process(delta_time)
if(!local_user)
return PROCESS_KILL
if((IS_HERETIC(local_user) || IS_HERETIC_MONSTER(local_user)) && HAS_TRAIT(src,TRAIT_NODROP))
REMOVE_TRAIT(src, TRAIT_NODROP, CLOTHING_TRAIT)
for(var/mob/living/carbon/human/human_in_range in spiral_range(9,local_user))
if(IS_HERETIC(human_in_range) || IS_HERETIC_MONSTER(human_in_range))
continue
SEND_SIGNAL(human_in_range,COMSIG_VOID_MASK_ACT,rand(-2,-20)*delta_time)
if(DT_PROB(60,delta_time))
human_in_range.hallucination += 5
if(DT_PROB(40,delta_time))
human_in_range.Jitter(5)
if(DT_PROB(30,delta_time))
human_in_range.emote(pick("giggle","laugh"))
human_in_range.adjustStaminaLoss(6)
if(DT_PROB(25,delta_time))
human_in_range.Dizzy(5)
/obj/item/melee/rune_knife
name = "\improper Carving Knife"
desc = "Cold steel, pure, perfect, this knife can carve the floor in many ways, but only few can evoke the dangers that lurk beneath reality."
icon = 'icons/obj/eldritch.dmi'
icon_state = "rune_carver"
flags_1 = CONDUCT_1
sharpness = SHARP_EDGED
w_class = WEIGHT_CLASS_SMALL
wound_bonus = 20
force = 10
throwforce = 20
embedding = list(embed_chance=75, jostle_chance=2, ignore_throwspeed_threshold=TRUE, pain_stam_pct=0.4, pain_mult=3, jostle_pain_mult=5, rip_time=15)
hitsound = 'sound/weapons/bladeslice.ogg'
attack_verb = list("attacked", "slashed", "stabbed", "sliced", "tore", "lacerated", "ripped", "diced", "rended")
///turfs that you cannot draw carvings on
var/static/list/blacklisted_turfs = typecacheof(list(/turf/closed,/turf/open/space,/turf/open/lava))
///A check to see if you are in process of drawing a rune
var/drawing = FALSE
///A list of current runes
var/list/current_runes = list()
///Max amount of runes
var/max_rune_amt = 3
///Linked action
var/datum/action/innate/rune_shatter/linked_action
/obj/item/melee/rune_knife/examine(mob/user)
. = ..()
. += "This item can carve 'Alert carving' - nearly invisible rune that when stepped on gives you a prompt about where someone stood on it and who it was, doesn't get destroyed by being stepped on."
. += "This item can carve 'Grasping carving' - when stepped on it causes heavy damage to the legs and stuns for 5 seconds."
. += "This item can carve 'Mad carving' - when stepped on it causes dizzyness, jiterryness, temporary blindness, confusion , stuttering and slurring."
/obj/item/melee/rune_knife/Initialize()
. = ..()
linked_action = new(src)
/obj/item/melee/rune_knife/pickup(mob/user)
. = ..()
linked_action.Grant(user, src)
/obj/item/melee/rune_knife/dropped(mob/user, silent)
. = ..()
linked_action.Remove(user, src)
/obj/item/melee/rune_knife/afterattack(atom/target, mob/user, proximity_flag, click_parameters)
. = ..()
if(!is_type_in_typecache(target,blacklisted_turfs) && !drawing && proximity_flag)
carve_rune(target,user,proximity_flag,click_parameters)
///Action of carving runes, gives you the ability to click on floor and choose a rune of your need.
/obj/item/melee/rune_knife/proc/carve_rune(atom/target, mob/user, proximity_flag, click_parameters)
var/obj/structure/trap/eldritch/elder = locate() in range(1,target)
if(elder)
to_chat(user,"<span class='notice'>You can't draw runes that close to each other!</span>")
return
for(var/X in current_runes)
var/obj/structure/trap/eldritch/eldritch = X
if(QDELETED(eldritch) || !eldritch)
current_runes -= eldritch
if(current_runes.len >= max_rune_amt)
to_chat(user,"<span class='notice'>The blade cannot support more runes!</span>")
return
var/list/pick_list = list()
for(var/E in subtypesof(/obj/structure/trap/eldritch))
var/obj/structure/trap/eldritch/eldritch = E
pick_list[initial(eldritch.name)] = eldritch
drawing = TRUE
var/type = pick_list[input(user,"Choose the rune","Rune") as null|anything in pick_list ]
if(!type)
drawing = FALSE
return
to_chat(user,"<span class='notice'>You start drawing the rune...</span>")
if(!do_after(user,5 SECONDS,target = target))
drawing = FALSE
return
drawing = FALSE
var/obj/structure/trap/eldritch/eldritch = new type(target)
eldritch.set_owner(user)
current_runes += eldritch
/datum/action/innate/rune_shatter
name = "Rune Break"
desc = "Destroys all runes that were drawn by this blade."
background_icon_state = "bg_ecult"
button_icon_state = "rune_break"
icon_icon = 'icons/mob/actions/actions_ecult.dmi'
check_flags = AB_CHECK_CONSCIOUS
///Reference to the rune knife it is inside of
var/obj/item/melee/rune_knife/sword
/datum/action/innate/rune_shatter/Grant(mob/user, obj/object)
sword = object
return ..()
/datum/action/innate/rune_shatter/Activate()
for(var/X in sword.current_runes)
var/obj/structure/trap/eldritch/eldritch = X
if(!QDELETED(eldritch) && eldritch)
qdel(eldritch)
/obj/item/eldritch_potion
name = "Brew of Day and Night"
desc = "You should never see this"
icon = 'icons/obj/eldritch.dmi'
///Typepath to the status effect this is supposed to hold
var/status_effect
/obj/item/eldritch_potion/attack_self(mob/user)
. = ..()
to_chat(user,"<span class='notice'>You drink the potion and with the viscous liquid, the glass dematerializes.</span>")
effect(user)
qdel(src)
///The effect of the potion if it has any special one, in general try not to override this and utilize the status_effect var to make custom effects.
/obj/item/eldritch_potion/proc/effect(mob/user)
if(!iscarbon(user))
return
var/mob/living/carbon/carbie = user
carbie.apply_status_effect(status_effect)
/obj/item/eldritch_potion/crucible_soul
name = "Brew of Crucible Soul"
desc = "Allows you to phase through walls for 15 seconds, after the time runs out, you get teleported to your original location."
icon_state = "crucible_soul"
status_effect = /datum/status_effect/crucible_soul
/obj/item/eldritch_potion/duskndawn
name = "Brew of Dusk and Dawn"
desc = "Allows you to see clearly through walls and objects for 60 seconds."
icon_state = "clarity"
status_effect = /datum/status_effect/duskndawn
/obj/item/eldritch_potion/wounded
name = "Brew of Wounded Soldier"
desc = "For the next 60 seconds each wound will heal you, minor wounds heal 1 of it's damage type per second, moderate heal 3 and critical heal 6. You also become immune to damage slowdon."
icon_state = "marshal"
status_effect = /datum/status_effect/marshal
@@ -65,6 +65,14 @@
/datum/eldritch_knowledge/proc/recipe_snowflake_check(list/atoms,loc)
return TRUE
/**
* A proc that handles the code when the mob dies
*
* This proc is primarily used to end any soundloops when the heretic dies
*/
/datum/eldritch_knowledge/proc/on_death(mob/user)
return
/**
* What happens once the recipe is succesfully finished
*
@@ -100,7 +108,6 @@
/datum/eldritch_knowledge/proc/on_mansus_grasp(atom/target, mob/user, proximity_flag, click_parameters)
return FALSE
/**
* Sickly blade act
*
@@ -109,6 +116,14 @@
/datum/eldritch_knowledge/proc/on_eldritch_blade(target,user,proximity_flag,click_parameters)
return
/**
* Sickly blade distant act
*
* Same as [/datum/eldritch_knowledge/proc/on_eldritch_blade] but works on targets that are not in proximity to you.
*/
/datum/eldritch_knowledge/proc/on_ranged_attack_eldritch_blade(atom/target,mob/user,click_parameters)
return
//////////////
///Subtypes///
//////////////
@@ -150,7 +165,7 @@
compiled_list[human_to_check.real_name] = human_to_check
if(compiled_list.len == 0)
to_chat(user, "<span class='warning'>The items don't posses required fingerprints.</span>")
to_chat(user, "<span class='warning'>These items don't possess the required fingerprints or DNA.</span>")
return FALSE
var/chosen_mob = input("Select the person you wish to curse","Your target") as null|anything in sortList(compiled_list, /proc/cmp_mob_realname_dsc)
@@ -222,9 +237,9 @@
/datum/eldritch_knowledge/spell/basic
name = "Break of Dawn"
desc = "Starts your journey in the mansus. Allows you to select a target using a living heart on a transmutation rune."
gain_text = "Gates of Mansus open up to your mind."
next_knowledge = list(/datum/eldritch_knowledge/base_rust,/datum/eldritch_knowledge/base_ash,/datum/eldritch_knowledge/base_flesh,/datum/eldritch_knowledge/spell/silence)
desc = "Starts your journey in the Mansus. Allows you to select a target using a living heart on a transmutation rune."
gain_text = "Another day at a meaningless job. You feel a shimmer around you, as a realization of something strange in your backpack unfolds. You look at it, unknowingly opening a new chapter in your life."
next_knowledge = list(/datum/eldritch_knowledge/base_rust,/datum/eldritch_knowledge/base_ash,/datum/eldritch_knowledge/base_flesh,/datum/eldritch_knowledge/base_void)
cost = 0
spell_to_add = /obj/effect/proc_holder/spell/targeted/touch/mansus_grasp
required_atoms = list(/obj/item/living_heart)
@@ -279,7 +294,7 @@
var/datum/mind/targeted = A.find_target(blacklist = target_blacklist)//easy way, i dont feel like copy pasting that entire block of code
if(!targeted)
break
targets[targeted.current.real_name] = targeted.current
targets["[targeted.current.real_name] the [targeted.assigned_role]"] = targeted.current
LH.target = targets[input(user,"Choose your next target","Target") in targets]
if(!LH.target && targets.len)
@@ -301,7 +316,6 @@
var/datum/antagonist/heretic/EC = carbon_user.mind.has_antag_datum(/datum/antagonist/heretic)
LH.sac_targetter = EC
EC.sac_targetted.Add(LH.target.real_name)
else
to_chat(user,"<span class='warning'>target could not be found for living heart.</span>")
@@ -311,30 +325,22 @@
/datum/eldritch_knowledge/living_heart
name = "Living Heart"
desc = "Allows you to create additional living hearts, using a heart, a pool of blood and a poppy. Living hearts when used on a transmutation rune will grant you a person to hunt and sacrifice on the rune. Every sacrifice gives you an additional charge in the book."
gain_text = "Disconnected, yet it still beats."
gain_text = "The Gates of Mansus open up to your mind."
cost = 0
required_atoms = list(/obj/item/organ/heart,/obj/effect/decal/cleanable/blood,/obj/item/reagent_containers/food/snacks/grown/poppy)
next_knowledge = list(/datum/eldritch_knowledge/spell/silence)
result_atoms = list(/obj/item/living_heart)
route = "Start"
/datum/eldritch_knowledge/codex_cicatrix
name = "Codex Cicatrix"
desc = "Allows you to create a spare Codex Cicatrix if you have lost one, using a bible, human skin, a pen and a pair of eyes."
gain_text = "Their hands are at your throat, yet you see them not."
gain_text = "Their hand is at your throat, yet you see Them not."
cost = 0
required_atoms = list(/obj/item/organ/eyes,/obj/item/stack/sheet/animalhide/human,/obj/item/storage/book/bible,/obj/item/pen)
result_atoms = list(/obj/item/forbidden_book)
route = "Start"
/datum/eldritch_knowledge/eldritch_blade
name = "Eldritch Blade"
desc = "Allows you to create a sickly, eldritch blade by transmuting a glass shard and a metal rod atop a transmutation rune."
gain_text = "The first step starts with sacrifice."
cost = 0
required_atoms = list(/obj/item/shard,/obj/item/stack/rods)
result_atoms = list(/obj/item/melee/sickly_blade)
route = "Start"
/datum/eldritch_knowledge/spell/silence
name = "Silence"
desc = "Allows you to use the power of the Mansus to force an individual's tongue to be held down for up to twenty seconds. They'll notice quickly, however."
@@ -1,6 +1,6 @@
/obj/effect/proc_holder/spell/targeted/ethereal_jaunt/shift/ash
name = "Ashen Passage"
desc = "Low range spell allowing you to pass through a few walls."
desc = "A short range spell allowing you to pass unimpeded through a few walls."
school = "transmutation"
invocation = "DULK'ES PRE'ZIMAS"
invocation_type = "whisper"
@@ -31,7 +31,7 @@
/obj/effect/proc_holder/spell/targeted/touch/mansus_grasp
name = "Mansus Grasp"
desc = "Touch spell that allows you to channel the power of the Old Gods through you."
desc = "A touch spell that lets you channel the power of the Old Gods through your grip."
hand_path = /obj/item/melee/touch_attack/mansus_fist
school = "evocation"
charge_max = 100
@@ -42,7 +42,7 @@
/obj/item/melee/touch_attack/mansus_fist
name = "Mansus Grasp"
desc = "A sinister looking aura that distorts the flow of reality around it. Causes knockdown, major stamina damage aswell as some Brute. It gains additional beneficial effects with certain knowledges you can research."
desc = "A sinister looking aura that distorts the flow of reality around it. Causes knockdown and major stamina damage in addition to some brute. It gains additional beneficial effects as you expand your knowledge of the Mansus."
icon = 'icons/obj/eldritch.dmi'
icon_state = "mansus_grasp"
item_state = "mansus"
@@ -50,13 +50,13 @@
/obj/item/melee/touch_attack/mansus_fist/afterattack(atom/target, mob/user, proximity_flag, click_parameters)
if(!proximity_flag || target == user)
if(!proximity_flag | target == user)
return
playsound(user, 'sound/items/welder.ogg', 75, TRUE)
if(ishuman(target))
var/mob/living/carbon/human/tar = target
if(tar.anti_magic_check())
tar.visible_message("<span class='danger'>Spell bounces off of [target]!</span>","<span class='danger'>The spell bounces off of you!</span>")
tar.visible_message("<span class='danger'>The spell bounces off of [target]!</span>","<span class='danger'>The spell bounces off of you!</span>")
return ..()
var/datum/mind/M = user.mind
var/datum/antagonist/heretic/cultie = M.has_antag_datum(/datum/antagonist/heretic)
@@ -79,7 +79,7 @@
/obj/effect/proc_holder/spell/aoe_turf/rust_conversion
name = "Aggressive Spread"
desc = "Spreads rust onto nearby turfs."
desc = "Spreads rust onto nearby surfaces."
school = "transmutation"
charge_max = 300 //twice as long as mansus grasp
clothes_req = FALSE
@@ -101,7 +101,7 @@
/obj/effect/proc_holder/spell/aoe_turf/rust_conversion/small
name = "Rust Conversion"
desc = "Spreads rust onto nearby turfs."
desc = "Spreads rust onto nearby surfaces."
range = 2
/obj/effect/proc_holder/spell/pointed/blood_siphon
@@ -162,7 +162,7 @@
/obj/effect/proc_holder/spell/aimed/rust_wave
name = "Patron's Reach"
desc = "Channels energy into your gauntlet - firing it results in a wave of rust being created in it's wake."
desc = "Channels energy into your gauntlet- unleashing it creates a wave of rust in its wake."
projectile_type = /obj/item/projectile/magic/spell/rust_wave
charge_max = 350
clothes_req = FALSE
@@ -213,7 +213,7 @@
/obj/effect/proc_holder/spell/pointed/cleave
name = "Cleave"
desc = "Causes severe bleeding on a target and people around them"
desc = "Causes severe bleeding on a target and several targets around them."
school = "transmutation"
charge_max = 350
clothes_req = FALSE
@@ -250,7 +250,8 @@
var/obj/item/bodypart/bodypart = pick(target.bodyparts)
var/datum/wound/slash/critical/crit_wound = new
crit_wound.apply_wound(bodypart)
target.adjustFireLoss(20)
crit_wound.apply_wound(bodypart)
target.adjustBruteLoss(20)
new /obj/effect/temp_visual/cleave(target.drop_location())
/obj/effect/proc_holder/spell/pointed/cleave/can_target(atom/target, mob/user, silent)
@@ -292,7 +293,7 @@
if(ishuman(target))
var/mob/living/carbon/human/tar = target
if(tar.anti_magic_check())
tar.visible_message("<span class='danger'>Spell bounces off of [target]!</span>","<span class='danger'>The spell bounces off of you!</span>")
tar.visible_message("<span class='danger'>The spell bounces off of [target]!</span>","<span class='danger'>The spell bounces off of you!</span>")
return ..()
if(iscarbon(target))
@@ -331,7 +332,7 @@
if(ishuman(target))
var/mob/living/carbon/human/tar = target
if(tar.anti_magic_check())
tar.visible_message("<span class='danger'>Spell bounces off of [target]!</span>","<span class='danger'>The spell bounces off of you!</span>")
tar.visible_message("<span class='danger'>The spell bounces off of [target]!</span>","<span class='danger'>The spell bounces off of you!</span>")
return ..()
if(iscarbon(target))
@@ -343,7 +344,7 @@
/obj/effect/proc_holder/spell/pointed/nightwatchers_rite
name = "Nightwatcher's Rite"
desc = "Powerful spell that releases 5 streams of fire away from you."
desc = "A powerful spell that releases 5 streams of fire away from you."
school = "transmutation"
invocation = "IGNIS'INTI"
invocation_type = "whisper"
@@ -390,13 +391,13 @@
for(var/mob/living/L in T.contents)
if(L.anti_magic_check())
L.visible_message("<span class='danger'>Spell bounces off of [L]!</span>","<span class='danger'>The spell bounces off of you!</span>")
L.visible_message("<span class='danger'>The spell bounces off of [L]!</span>","<span class='danger'>The spell bounces off of you!</span>")
continue
if(L in hit_list || L == source)
continue
hit_list += L
L.adjustFireLoss(15)
to_chat(L, "<span class='userdanger'>You're hit by a blast of fire!</span>")
to_chat(L, "<span class='userdanger'>You're hit by [source]'s eldritch flames!</span>")
new /obj/effect/hotspot(T)
T.hotspot_expose(700,50,1)
@@ -433,7 +434,7 @@
/obj/effect/proc_holder/spell/aoe_turf/fire_cascade
name = "Fire Cascade"
desc = "creates hot turfs around you."
desc = "Heats the air around you."
school = "transmutation"
charge_max = 300 //twice as long as mansus grasp
clothes_req = FALSE
@@ -470,7 +471,7 @@
/obj/effect/proc_holder/spell/targeted/fire_sworn
name = "Oath of Fire"
desc = "For a minute you will passively create a ring of fire around you."
desc = "For a minute, you will passively create a ring of fire around you."
invocation = "IGNIS'AISTRA'LISTRE"
invocation_type = "whisper"
clothes_req = FALSE
@@ -509,7 +510,7 @@
/obj/effect/proc_holder/spell/targeted/worm_contract
name = "Force Contract"
desc = "Forces all the worm parts to collapse onto a single turf"
desc = "Forces your body to contract onto a single tile."
invocation_type = "none"
clothes_req = FALSE
action_background_icon_state = "bg_ecult"
@@ -539,7 +540,7 @@
/obj/effect/proc_holder/spell/targeted/fiery_rebirth
name = "Nightwatcher's Rebirth"
desc = "Drains nearby alive people that are engulfed in flames. It heals 10 of each damage type per person. If a person is in critical condition it finishes them off."
desc = "Drains nearby alive people that are engulfed in flames. It heals 10 of each damage type per person. If a target is in critical condition it drains the last of their vitality, killing them."
invocation = "PETHRO'MINO'IGNI"
invocation_type = "whisper"
clothes_req = FALSE
@@ -571,7 +572,7 @@
/obj/effect/proc_holder/spell/pointed/manse_link
name = "Mansus Link"
desc = "Piercing through reality, connecting minds. This spell allows you to add people to a mansus net, allowing them to communicate with eachother"
desc = "Piercing through reality, connecting minds. This spell allows you to add people to a Mansus Net, allowing them to communicate with each other from afar."
school = "transmutation"
charge_max = 300
clothes_req = FALSE
@@ -605,7 +606,7 @@
/datum/action/innate/mansus_speech
name = "Mansus Link"
desc = "Send a psychic message to everyone connected to your mansus link."
desc = "Send a psychic message to everyone connected to your Mansus Net."
button_icon_state = "link_speech"
icon_icon = 'icons/mob/actions/actions_slime.dmi'
background_icon_state = "bg_ecult"
@@ -747,3 +748,219 @@
return 3
else
return 2
/obj/effect/proc_holder/spell/targeted/shed_human_form
name = "Shed form"
desc = "Shed your fragile form, become one with the arms, become one with the emperor."
invocation_type = "shout"
invocation = "REALITY UNCOIL!"
clothes_req = FALSE
action_background_icon_state = "bg_ecult"
range = -1
include_user = TRUE
charge_max = 100
action_icon = 'icons/mob/actions/actions_ecult.dmi'
action_icon_state = "worm_ascend"
var/segment_length = 10
/obj/effect/proc_holder/spell/targeted/shed_human_form/cast(list/targets, mob/user)
. = ..()
var/mob/living/target = user
var/mob/living/mob_inside = locate() in target.contents - target
if(!mob_inside)
var/mob/living/simple_animal/hostile/eldritch/armsy/prime/outside = new(user.loc,TRUE,segment_length)
target.mind.transfer_to(outside, TRUE)
target.forceMove(outside)
target.apply_status_effect(STATUS_EFFECT_STASIS,STASIS_ASCENSION_EFFECT)
for(var/mob/living/carbon/human/humie in view(9,outside)-target)
if(IS_HERETIC(humie) || IS_HERETIC_MONSTER(humie))
continue
SEND_SIGNAL(humie, COMSIG_ADD_MOOD_EVENT, "gates_of_mansus", /datum/mood_event/gates_of_mansus)
///They see the very reality uncoil before their eyes.
if(prob(25))
var/trauma = pick(subtypesof(BRAIN_TRAUMA_MILD) + subtypesof(BRAIN_TRAUMA_SEVERE))
humie.gain_trauma(new trauma(), TRAUMA_RESILIENCE_LOBOTOMY)
return
if(iscarbon(mob_inside))
var/mob/living/simple_animal/hostile/eldritch/armsy/prime/armsy = target
if(mob_inside.remove_status_effect(STATUS_EFFECT_STASIS,STASIS_ASCENSION_EFFECT))
mob_inside.forceMove(armsy.loc)
armsy.mind.transfer_to(mob_inside, TRUE)
segment_length = armsy.get_length()
qdel(armsy)
return
/obj/effect/proc_holder/spell/pointed/void_blink
name = "Void Phase"
desc = "Let's you blink to your pointed destination, causes 3x3 aoe damage bubble around your pointed destination and your current location. It has a minimum range of 3 tiles and a maximum range of 9 tiles."
invocation_type = "whisper"
invocation = "PAS'VEIK"
clothes_req = FALSE
range = 9
action_background_icon_state = "bg_ecult"
charge_max = 300
action_icon = 'icons/mob/actions/actions_ecult.dmi'
action_icon_state = "voidblink"
selection_type = "range"
/obj/effect/proc_holder/spell/pointed/void_blink/can_target(atom/target, mob/user, silent)
. = ..()
if(get_dist(get_turf(user),get_turf(target)) < 3 )
return FALSE
/obj/effect/proc_holder/spell/pointed/void_blink/cast(list/targets, mob/user)
. = ..()
var/target = targets[1]
var/turf/targeted_turf = get_turf(target)
playsound(user,'sound/magic/voidblink.ogg',100)
playsound(targeted_turf,'sound/magic/voidblink.ogg',100)
new /obj/effect/temp_visual/voidin(user.drop_location())
new /obj/effect/temp_visual/voidout(targeted_turf)
for(var/mob/living/living_mob in range(1,user)-user)
if(IS_HERETIC(living_mob) || IS_HERETIC_MONSTER(living_mob))
continue
living_mob.adjustBruteLoss(40)
for(var/mob/living/living_mob in range(1,targeted_turf)-user)
if(IS_HERETIC(living_mob) || IS_HERETIC_MONSTER(living_mob))
continue
living_mob.adjustBruteLoss(40)
do_teleport(user,targeted_turf,0,TRUE,no_effects = TRUE,channel=TELEPORT_CHANNEL_MAGIC)
/obj/effect/temp_visual/voidin
icon = 'icons/effects/96x96.dmi'
icon_state = "void_blink_in"
alpha = 150
duration = 6
pixel_x = -32
pixel_y = -32
/obj/effect/temp_visual/voidout
icon = 'icons/effects/96x96.dmi'
icon_state = "void_blink_out"
alpha = 150
duration = 6
pixel_x = -32
pixel_y = -32
/obj/effect/proc_holder/spell/targeted/void_pull
name = "Void Pull"
desc = "Call the void, this pulls all nearby people closer to you, damages people already around you. If they are 4 tiles or closer they are also knocked down and a micro-stun is applied."
invocation_type = "whisper"
invocation = "VISA'GALIS TRAUK'IMAS"
clothes_req = FALSE
action_background_icon_state = "bg_ecult"
range = -1
include_user = TRUE
charge_max = 400
action_icon = 'icons/mob/actions/actions_ecult.dmi'
action_icon_state = "voidpull"
/obj/effect/proc_holder/spell/targeted/void_pull/cast(list/targets, mob/user)
. = ..()
for(var/mob/living/living_mob in range(1,user)-user)
if(IS_HERETIC(living_mob) || IS_HERETIC_MONSTER(living_mob))
continue
living_mob.adjustBruteLoss(30)
playsound(user,'sound/magic/voidpull.ogg',75)
new /obj/effect/temp_visual/voidin(user.drop_location())
for(var/mob/living/livies in view(7,user)-user)
if(get_dist(user,livies) < 4)
livies.AdjustKnockdown(3 SECONDS)
livies.AdjustParalyzed(0.5 SECONDS)
for(var/i in 1 to 3)
livies.forceMove(get_step_towards(livies,user))
/obj/effect/proc_holder/spell/pointed/boogie_woogie
name = "Void's Applause"
desc = "Swap positions with someone at the clap of your hands."
school = "transmutation"
charge_max = 100
clothes_req = FALSE
invocation = "BOOGIE WOOGIE"
invocation_type = "none"
range = 10
message = "The world around you suddenly shifts!"
action_icon = 'icons/mob/actions/actions_ecult.dmi'
action_icon_state = "mansus_link"
action_background_icon_state = "bg_ecult"
/obj/effect/proc_holder/spell/pointed/boogie_woogie/cast(list/targets, mob/user)
. = ..()
var/target = targets[1]
user.emote("clap1")
playsound(user, 'sound/magic/voidblink.ogg', 75, TRUE)
var/turf/targeted_turf = get_turf(target)
var/turf/user_turf = get_turf(user)
new /obj/effect/temp_visual/voidswap(user.drop_location())
new /obj/effect/temp_visual/voidswap(targeted_turf)
if(isliving(target) || iscontainer(target))
do_teleport(user,targeted_turf,0,TRUE,no_effects = TRUE,channel=TELEPORT_CHANNEL_MAGIC)
do_teleport(target,user_turf,0,TRUE,no_effects = TRUE,channel=TELEPORT_CHANNEL_MAGIC)
/obj/effect/proc_holder/spell/pointed/boogie_woogie/can_target(atom/target, mob/user, silent)
. = ..()
if(!.)
return FALSE
if(!isliving(target) && !iscontainer(target))
if(!silent)
to_chat(user, "<span class='warning'>You are unable to swap with the [target]!</span>")
return FALSE
return TRUE
/obj/effect/proc_holder/spell/aoe_turf/repulse/eldritch //placeholder spell
name = "Void's Push"
desc = "With the snap of your fingers, send your enemies away."
charge_max = 400
clothes_req = FALSE
invocation = "ISN'YKTI"
invocation_type = "shout"
range = 3
selection_type = "view"
sound = 'sound/magic/voidblink.ogg'
action_background_icon_state = "bg_ecult"
sparkle_path = /obj/effect/temp_visual/voidpush
/obj/effect/proc_holder/spell/aoe_turf/repulse/eldritch/cast(list/targets,mob/user = usr)
user.emote("snap")
..(targets, user, 60)
/obj/effect/proc_holder/spell/aoe_turf/domain_expansion
name = "Infinite Void"
desc = "Create a domain that will slow down and mark all opponents with a void mark."
charge_max = 1200
clothes_req = FALSE
invocation = "RYO'IKI TEN'KAI"
invocation_type = "none"
range = 0
action_icon_state = "time"
action_background_icon_state = "bg_ecult"
var/timestop_range = 7
var/timestop_duration = 200
var/static/mutable_appearance/halo
var/sound/Snd // shamelessly ripped from lightning.
/obj/effect/proc_holder/spell/aoe_turf/domain_expansion/cast(list/targets, mob/user = usr)
Snd = new/sound('sound/magic/clockwork/ratvar_attack.ogg',channel = 7)
halo = halo || mutable_appearance('icons/effects/effects.dmi', "at_shield2", EFFECTS_LAYER)
user.add_overlay(halo)
playsound(get_turf(user), Snd, 50, 0)
if(do_mob(user,user,50,1))
user.cut_overlay(halo)
user.emote("clap1")
user.say("DOM'ENO ISPLETIMAS")
playsound(user, 'sound/magic/domain.ogg', 125, TRUE)
new /obj/effect/domain_expansion(get_turf(user), timestop_range, timestop_duration, list(user))
@@ -7,6 +7,7 @@
job_rank = ROLE_HERETIC
antag_hud_type = ANTAG_HUD_HERETIC
antag_hud_name = "heretic_beast"
show_in_antagpanel = FALSE
var/datum/antagonist/master
/datum/antagonist/heretic_monster/admin_add(datum/mind/new_owner,mob/admin)
@@ -29,6 +30,7 @@
var/datum/objective/master_obj = new
master_obj.owner = src
master_obj.explanation_text = "Assist your master in any way you can!"
master_obj.completed = TRUE
objectives += master_obj
owner.announce_objectives()
to_chat(owner, "<span class='boldannounce'>Your master is [master.owner.current.real_name]</span>")
@@ -0,0 +1,178 @@
/obj/structure/eldritch_crucible
name = "Mawed Crucible"
desc = "Immortalized cast iron, the steel-like teeth holding it in place, it's vile extract has the power of rebirthing things, remaking them from the very beginning."
icon = 'icons/obj/eldritch.dmi'
icon_state = "crucible"
anchored = FALSE
density = TRUE
///How much mass this currently holds
var/current_mass = 5
///Maximum amount of mass
var/max_mass = 5
///Check to see if it is currently being used.
var/in_use = FALSE
/obj/structure/eldritch_crucible/examine(mob/user)
. = ..()
if(!IS_HERETIC(user) && !IS_HERETIC_MONSTER(user))
return
if(current_mass < max_mass)
. += "The Crucible requires [max_mass - current_mass] more organs or bodyparts!"
else
. += "The Crucible is ready to be used!"
. += "You can anchor and reanchor it using Codex Cicatrix!"
. += "It is currently [anchored == FALSE ? "unanchored" : "anchored"]"
. += "This structure can brew 'Brew of Crucible soul' - when used it gives you the ability to phase through matter for 15 seconds, after the time elapses it teleports you back to your original location"
. += "This structure can brew 'Brew of Dusk and Dawn' - when used it gives you xray for 1 minute"
. += "This structure can brew 'Brew of Wounded Soldier' - when used it makes you immune to damage slowdown, additionally you start healing for every wound you have, quickly outpacing the damage caused by them."
/obj/structure/eldritch_crucible/attacked_by(obj/item/I, mob/living/user)
if(istype(I,/obj/item/nullrod))
qdel(src)
return
if(!IS_HERETIC(user) && !IS_HERETIC_MONSTER(user))
if(iscarbon(user))
devour(user)
return
if(istype(I,/obj/item/forbidden_book))
playsound(src, 'sound/misc/desceration-02.ogg', 75, TRUE)
anchored = !anchored
to_chat(user,"<span class='notice'>You [anchored == FALSE ? "unanchor" : "anchor"] the crucible</span>")
return
if(istype(I,/obj/item/bodypart) || istype(I,/obj/item/organ))
//Both organs and bodyparts hold information if they are organic or robotic in the exact same way.
var/obj/item/bodypart/forced = I
if(forced.status != BODYPART_ORGANIC)
return
if(current_mass >= max_mass)
to_chat(user,"<span class='notice'> Crucible is already full!</span>")
return
playsound(src, 'sound/items/eatfood.ogg', 100, TRUE)
to_chat(user,"<span class='notice'>Crucible devours [I.name] and fills itself with a little bit of liquid!</span>")
current_mass++
qdel(I)
update_icon_state()
return
return ..()
/obj/structure/eldritch_crucible/attack_hand(mob/user)
if(!IS_HERETIC(user) && !IS_HERETIC_MONSTER(user))
if(iscarbon(user))
devour(user)
return
if(in_use)
to_chat(user,"<span class='notice'>Crucible is already in use!</span>")
return
if(current_mass < max_mass)
to_chat(user,"<span class='notice'>Crucible isn't full! Bring it more organs or bodyparts!</span>")
return
in_use = TRUE
var/list/lst = list()
for(var/X in subtypesof(/obj/item/eldritch_potion))
var/obj/item/eldritch_potion/potion = X
lst[initial(potion.name)] = potion
var/type = lst[input(user,"Choose your brew","Brew") in lst]
playsound(src, 'sound/misc/desceration-02.ogg', 75, TRUE)
new type(drop_location())
current_mass = 0
in_use = FALSE
update_icon_state()
///Proc that eats the active limb of the victim
/obj/structure/eldritch_crucible/proc/devour(mob/living/carbon/user)
if(HAS_TRAIT(user,TRAIT_NODISMEMBER))
return
playsound(src, 'sound/items/eatfood.ogg', 100, TRUE)
to_chat(user,"<span class='danger'>Crucible grabs your arm and devours it whole!</span>")
var/obj/item/bodypart/arm = user.get_active_hand()
arm.dismember()
qdel(arm)
current_mass += current_mass < max_mass ? 1 : 0
update_icon_state()
/obj/structure/eldritch_crucible/update_icon_state()
. = ..()
if(current_mass == max_mass)
icon_state = "crucible"
else
icon_state = "crucible_empty"
/obj/structure/trap/eldritch
name = "elder carving"
desc = "Collection of unknown symbols, they remind you of days long gone..."
icon = 'icons/obj/eldritch.dmi'
charges = 1
///Owner of the trap
var/mob/owner
/obj/structure/trap/eldritch/Crossed(atom/movable/AM)
if(!isliving(AM))
return ..()
var/mob/living/living_mob = AM
if((owner && living_mob == owner) || IS_HERETIC(living_mob) || IS_HERETIC_MONSTER(living_mob))
return
return ..()
/obj/structure/trap/eldritch/attacked_by(obj/item/I, mob/living/user)
. = ..()
if(istype(I,/obj/item/melee/rune_knife) || istype(I,/obj/item/nullrod))
qdel(src)
///Proc that sets the owner
/obj/structure/trap/eldritch/proc/set_owner(mob/_owner)
owner = _owner
/obj/structure/trap/eldritch/alert
name = "alert carving"
icon_state = "alert_rune"
alpha = 10
/obj/structure/trap/eldritch/alert/trap_effect(mob/living/L)
if(owner)
to_chat(owner,"<span class='big boldwarning'>[L.real_name] has stepped foot on the alert rune in [get_area(src)]!</span>")
return ..()
//this trap can only get destroyed by rune carving knife or nullrod
/obj/structure/trap/eldritch/alert/flare()
return
/obj/structure/trap/eldritch/tentacle
name = "grasping carving"
icon_state = "tentacle_rune"
/obj/structure/trap/eldritch/tentacle/trap_effect(mob/living/L)
if(!iscarbon(L))
return
var/mob/living/carbon/carbon_victim = L
carbon_victim.DefaultCombatKnockdown(50)
carbon_victim.drop_all_held_items()
carbon_victim.apply_damage(20,BRUTE,BODY_ZONE_R_LEG)
carbon_victim.apply_damage(20,BRUTE,BODY_ZONE_L_LEG)
playsound(src, 'sound/magic/demon_attack1.ogg', 75, TRUE)
return ..()
/obj/structure/trap/eldritch/mad
name = "mad carving"
icon_state = "madness_rune"
/obj/structure/trap/eldritch/mad/trap_effect(mob/living/L)
if(!iscarbon(L))
return
var/mob/living/carbon/carbon_victim = L
carbon_victim.adjustStaminaLoss(60)
carbon_victim.silent += 10
carbon_victim.confused += 5
carbon_victim.Jitter(10)
carbon_victim.Dizzy(20)
carbon_victim.blind_eyes(2)
SEND_SIGNAL(carbon_victim, COMSIG_ADD_MOOD_EVENT, "gates_of_mansus", /datum/mood_event/gates_of_mansus)
return ..()
@@ -1,18 +1,18 @@
/datum/eldritch_knowledge/base_ash
name = "Nightwatcher's Secret"
desc = "Inducts you into the Path of Ash. Allows you to transmute a match with an eldritch blade into an ashen blade."
gain_text = "The City guard knows their watch. If you ask them at night they may tell you about the ashy lantern."
banned_knowledge = list(/datum/eldritch_knowledge/base_rust,/datum/eldritch_knowledge/base_flesh,/datum/eldritch_knowledge/final/rust_final,/datum/eldritch_knowledge/final/flesh_final)
desc = "Inducts you into the Path of Ash. Allows you to transmute a match with a spear into an ashen blade."
gain_text = "The City Guard know their watch. If you ask them at night, they may tell you about the ashy lantern."
banned_knowledge = list(/datum/eldritch_knowledge/base_rust,/datum/eldritch_knowledge/base_flesh,/datum/eldritch_knowledge/final/rust_final,/datum/eldritch_knowledge/final/flesh_final,/datum/eldritch_knowledge/final/void_final,/datum/eldritch_knowledge/base_void)
next_knowledge = list(/datum/eldritch_knowledge/ashen_grasp)
required_atoms = list(/obj/item/melee/sickly_blade,/obj/item/match)
required_atoms = list(/obj/item/spear,/obj/item/match)
result_atoms = list(/obj/item/melee/sickly_blade/ash)
cost = 1
cost = 0
route = PATH_ASH
/datum/eldritch_knowledge/spell/ashen_shift
name = "Ashen Shift"
gain_text = "Ash is all the same, how can one man master it all?"
desc = "A short range jaunt that will enable you to escape from danger."
gain_text = "The Nightwatcher was the first of them, his treason started it all."
desc = "A short range jaunt that can help you escape from bad situations."
cost = 1
spell_to_add = /obj/effect/proc_holder/spell/targeted/ethereal_jaunt/shift/ash
next_knowledge = list(/datum/eldritch_knowledge/ash_mark,/datum/eldritch_knowledge/essence,/datum/eldritch_knowledge/ashen_eyes)
@@ -20,7 +20,7 @@
/datum/eldritch_knowledge/ashen_grasp
name = "Grasp of Ash"
gain_text = "Gates have opened, minds have flooded, yet I remain."
gain_text = "He knew how to walk between the planes."
desc = "Empowers your mansus grasp to knock enemies down and throw them away."
cost = 1
next_knowledge = list(/datum/eldritch_knowledge/spell/ashen_shift)
@@ -32,7 +32,7 @@
return
var/mob/living/carbon/C = target
var/datum/status_effect/eldritch/E = C.has_status_effect(/datum/status_effect/eldritch/rust) || C.has_status_effect(/datum/status_effect/eldritch/ash) || C.has_status_effect(/datum/status_effect/eldritch/flesh)
var/datum/status_effect/eldritch/E = C.has_status_effect(/datum/status_effect/eldritch/rust) || C.has_status_effect(/datum/status_effect/eldritch/ash) || C.has_status_effect(/datum/status_effect/eldritch/flesh) || C.has_status_effect(/datum/status_effect/eldritch/void)
if(E)
. = TRUE
E.on_effect()
@@ -49,7 +49,7 @@
/datum/eldritch_knowledge/ashen_eyes
name = "Ashen Eyes"
gain_text = "Piercing eyes may guide me through the mundane."
gain_text = "Piercing eyes, guide me through the mundane."
desc = "Allows you to craft thermal vision amulet by transmutating eyes with a glass shard."
cost = 1
next_knowledge = list(/datum/eldritch_knowledge/spell/ashen_shift,/datum/eldritch_knowledge/flesh_ghoul)
@@ -58,11 +58,11 @@
/datum/eldritch_knowledge/ash_mark
name = "Mark of Ash"
gain_text = "Spread the famine."
desc = "Your sickly blade now applies ash mark on hit. Use your mansus grasp to proc the mark. Mark of Ash causes stamina damage, and fire loss, and spreads to a nearby carbon. Damage decreases with how many times the mark has spread."
gain_text = "The Nightwatcher was a very particular man, always watching in the dead of night. But in spite of his duty, he regularly tranced through the manse with his blazing lantern held high."
desc = "Your Mansus Grasp now applies the Mark of Ash on hit. Attack the afflicted with your Sickly Blade to detonate the mark. Upon detonation, the Mark of Ash causes stamina damage and burn damage, and spreads to an additional nearby opponent. The damage decreases with each spread."
cost = 2
next_knowledge = list(/datum/eldritch_knowledge/curse/blindness)
banned_knowledge = list(/datum/eldritch_knowledge/rust_mark,/datum/eldritch_knowledge/flesh_mark)
next_knowledge = list(/datum/eldritch_knowledge/mad_mask)
banned_knowledge = list(/datum/eldritch_knowledge/rust_mark,/datum/eldritch_knowledge/flesh_mark,/datum/eldritch_knowledge/void_mark)
route = PATH_ASH
/datum/eldritch_knowledge/ash_mark/on_eldritch_blade(target,user,proximity_flag,click_parameters)
@@ -71,28 +71,20 @@
var/mob/living/living_target = target
living_target.apply_status_effect(/datum/status_effect/eldritch/ash,5)
/datum/eldritch_knowledge/curse/blindness
name = "Curse of Blindness"
gain_text = "The blind man walks through the world, unnoticed by the masses."
desc = "Curse someone with 2 minutes of complete blindness by sacrificing a pair of eyes, a screwdriver and a pool of blood, with an object that the victim has touched with their bare hands."
/datum/eldritch_knowledge/mad_mask
name = "Mask of Madness"
gain_text = "He walks the world, unnoticed by the masses."
desc = "Allows you to transmute any mask, with a candle and a pair of eyes, to create a mask of madness, It causes passive stamina damage to everyone around the wearer and hallucinations, can be forced on a non believer to make him unable to take it off..."
cost = 1
required_atoms = list(/obj/item/organ/eyes,/obj/item/screwdriver,/obj/effect/decal/cleanable/blood)
result_atoms = list(/obj/item/clothing/mask/void_mask)
required_atoms = list(/obj/item/organ/eyes,/obj/item/clothing/mask,/obj/item/candle)
next_knowledge = list(/datum/eldritch_knowledge/curse/corrosion,/datum/eldritch_knowledge/ash_blade_upgrade,/datum/eldritch_knowledge/curse/paralysis)
timer = 2 MINUTES
route = PATH_ASH
/datum/eldritch_knowledge/curse/blindness/curse(mob/living/chosen_mob)
. = ..()
chosen_mob.become_blind(MAGIC_TRAIT)
/datum/eldritch_knowledge/curse/blindness/uncurse(mob/living/chosen_mob)
. = ..()
chosen_mob.cure_blind(MAGIC_TRAIT)
/datum/eldritch_knowledge/spell/flame_birth
name = "Fiery Rebirth"
gain_text = "Nightwatcher was a man of principles, and yet he arose from the chaos he vowed to protect from."
desc = "Drains nearby alive people that are engulfed in flames. It heals 10 of each damage type per person. If a person is in critical condition it finishes them off."
gain_text = "The Nightwatcher was a man of principles, and yet his power arose from the chaos he vowed to combat."
desc = "Drains nearby alive people that are engulfed in flames. It heals 10 of each damage type per person. If a target is in critical condition it drains the last of their vitality, killing them."
cost = 1
spell_to_add = /obj/effect/proc_holder/spell/targeted/fiery_rebirth
next_knowledge = list(/datum/eldritch_knowledge/spell/cleave,/datum/eldritch_knowledge/summon/ashy,/datum/eldritch_knowledge/flame_immunity)
@@ -122,12 +114,12 @@
route = PATH_ASH
/datum/eldritch_knowledge/ash_blade_upgrade
name = "Blazing Steel"
gain_text = "May the sun burn the heretics."
desc = "Your blade of choice will now add firestacks."
name = "Fiery Blade"
gain_text = "Blade in hand, he swung and swung as the ash fell from the skies. His city, his people... all burnt to cinders, and yet life still remained in his charred body."
desc = "Your blade of choice will now light your enemies ablaze."
cost = 2
next_knowledge = list(/datum/eldritch_knowledge/spell/flame_birth)
banned_knowledge = list(/datum/eldritch_knowledge/rust_blade_upgrade,/datum/eldritch_knowledge/flesh_blade_upgrade)
banned_knowledge = list(/datum/eldritch_knowledge/rust_blade_upgrade,/datum/eldritch_knowledge/flesh_blade_upgrade,/datum/eldritch_knowledge/void_blade_upgrade)
route = PATH_ASH
/datum/eldritch_knowledge/ash_blade_upgrade/on_eldritch_blade(target,user,proximity_flag,click_parameters)
@@ -140,10 +132,10 @@
/datum/eldritch_knowledge/curse/corrosion
name = "Curse of Corrosion"
gain_text = "Cursed land, cursed man, cursed mind."
desc = "Curse someone for 2 minutes of vomiting and major organ damage. Using a wirecutter, a spill of blood, a heart, left arm and a right arm, and an item that the victim touched with their bare hands."
desc = "Curse someone for 2 minutes of vomiting and major organ damage. Using a wirecutter, a pool of blood, a heart, left arm and a right arm, and an item that the victim touched with their bare hands."
cost = 1
required_atoms = list(/obj/item/wirecutters,/obj/effect/decal/cleanable/blood,/obj/item/organ/heart,/obj/item/bodypart/l_arm,/obj/item/bodypart/r_arm)
next_knowledge = list(/datum/eldritch_knowledge/curse/blindness,/datum/eldritch_knowledge/spell/area_conversion)
next_knowledge = list(/datum/eldritch_knowledge/mad_mask,/datum/eldritch_knowledge/spell/area_conversion)
timer = 2 MINUTES
/datum/eldritch_knowledge/curse/corrosion/curse(mob/living/chosen_mob)
@@ -157,10 +149,10 @@
/datum/eldritch_knowledge/curse/paralysis
name = "Curse of Paralysis"
gain_text = "Corrupt their flesh, make them bleed."
desc = "Curse someone for 5 minutes of inability to walk. Using a knife, pool of blood, left leg, right leg, a hatchet and an item that the victim touched with their bare hands. "
desc = "Curse someone for 5 minutes of inability to walk. Sacrifice a knife, a pool of blood, a pair of legs, a hatchet and an item that the victim touched with their bare hands. "
cost = 1
required_atoms = list(/obj/item/kitchen/knife,/obj/effect/decal/cleanable/blood,/obj/item/bodypart/l_leg,/obj/item/bodypart/r_leg,/obj/item/hatchet)
next_knowledge = list(/datum/eldritch_knowledge/curse/blindness,/datum/eldritch_knowledge/summon/raw_prophet)
next_knowledge = list(/datum/eldritch_knowledge/mad_mask,/datum/eldritch_knowledge/summon/raw_prophet)
timer = 5 MINUTES
/datum/eldritch_knowledge/curse/paralysis/curse(mob/living/chosen_mob)
@@ -177,7 +169,7 @@
/datum/eldritch_knowledge/spell/cleave
name = "Blood Cleave"
gain_text = "At first I was unfamiliar with these instruments of war, but the priest told me how to use them."
gain_text = "At first I didn't understand these instruments of war, but the priest told me to use them regardless. Soon, he said, I would know them well."
desc = "Grants a spell that will inflict wounds and bleeding upon the target, as well as in a short radius around them."
cost = 1
spell_to_add = /obj/effect/proc_holder/spell/pointed/cleave
@@ -185,8 +177,8 @@
/datum/eldritch_knowledge/final/ash_final
name = "Ashlord's Rite"
gain_text = "The forgotten lords have spoken! The Lord of Ash has come! Fear the flame!"
desc = "Bring three corpses onto a transmutation rune, after ascending you will become immune to fire, space, temperature and other environmental hazards. You will develop resistance to all other damages. You will be granted two spells, one which can bring forth a cascade of massive fire, and another which will surround your body in precious flames for a minute."
gain_text = "The Nightwatcher found the rite and shared it amongst mankind! For now I am one with the fire, WITNESS MY ASCENSION!"
desc = "Bring 3 corpses onto a transmutation rune, you will become immune to fire, the vacuum of space, cold and other enviromental hazards and become overall sturdier to all other damages. You will gain a spell that passively creates ring of fire around you as well ,as you will gain a powerful ability that lets you create a wave of flames all around you."
required_atoms = list(/mob/living/carbon/human)
cost = 5
route = PATH_ASH
@@ -1,21 +1,21 @@
/datum/eldritch_knowledge/base_flesh
name = "Principle of Hunger"
desc = "Inducts you into the Path of Flesh. Allows you to transmute a pool of blood with your eldritch blade into a Blade of Flesh."
gain_text = "Hundred's of us starved, but I.. I found the strength in my greed."
banned_knowledge = list(/datum/eldritch_knowledge/base_ash,/datum/eldritch_knowledge/base_rust,/datum/eldritch_knowledge/final/ash_final,/datum/eldritch_knowledge/final/rust_final)
desc = "Inducts you into the Path of Flesh. Allows you to transmute a pool of blood with a spear into a Blade of Flesh."
gain_text = "Hundreds of us starved, but not me... I found strength in my greed."
banned_knowledge = list(/datum/eldritch_knowledge/base_ash,/datum/eldritch_knowledge/base_rust,/datum/eldritch_knowledge/final/ash_final,/datum/eldritch_knowledge/final/rust_final,/datum/eldritch_knowledge/final/void_final,/datum/eldritch_knowledge/base_void)
next_knowledge = list(/datum/eldritch_knowledge/flesh_grasp)
required_atoms = list(/obj/item/melee/sickly_blade,/obj/effect/decal/cleanable/blood)
required_atoms = list(/obj/item/spear,/obj/effect/decal/cleanable/blood)
result_atoms = list(/obj/item/melee/sickly_blade/flesh)
cost = 1
cost = 0
route = PATH_FLESH
/datum/eldritch_knowledge/flesh_ghoul
name = "Imperfect Ritual"
desc = "Allows you to resurrect the dead as voiceless dead by sacrificing them on the transmutation rune with a poppy. Voiceless dead are mute and have 50 HP. You can only have 2 at a time."
gain_text = "I found notes... notes of a ritual, scraps, unfinished, and yet... I still did it."
gain_text = "I found notes of a dark ritual, unfinished... yet still, I pushed forward."
cost = 1
required_atoms = list(/mob/living/carbon/human,/obj/item/reagent_containers/food/snacks/grown/poppy)
next_knowledge = list(/datum/eldritch_knowledge/flesh_mark,/datum/eldritch_knowledge/armor,/datum/eldritch_knowledge/ashen_eyes)
next_knowledge = list(/datum/eldritch_knowledge/flesh_mark,/datum/eldritch_knowledge/void_cloak,/datum/eldritch_knowledge/ashen_eyes)
route = PATH_FLESH
var/max_amt = 2
var/current_amt = 0
@@ -66,8 +66,8 @@
/datum/eldritch_knowledge/flesh_grasp
name = "Grasp of Flesh"
gain_text = "'My newfound desire, it drove me to do great things,' The Priest said."
desc = "Empowers your Mansus Grasp to be able to create a single ghoul out of a dead player. You cannot raise the same person twice. Ghouls have only 50 HP and look like husks."
gain_text = "My new found desires drove me to greater and greater heights."
desc = "Empowers your mansus grasp to be able to create a single ghoul out of a dead person. Ghouls are only half as sturdy as a regular person and look like husks to the heathens' eyes."
cost = 1
next_knowledge = list(/datum/eldritch_knowledge/flesh_ghoul)
var/ghoul_amt = 4
@@ -78,8 +78,12 @@
. = ..()
if(!ishuman(target) || target == user)
return
if(iscarbon(target))
user.reagents.add_reagent(/datum/reagent/eldritch, 5)
var/mob/living/carbon/human/human_target = target
var/datum/status_effect/eldritch/eldritch_effect = human_target.has_status_effect(/datum/status_effect/eldritch/rust) || human_target.has_status_effect(/datum/status_effect/eldritch/ash) || human_target.has_status_effect(/datum/status_effect/eldritch/flesh)
var/datum/status_effect/eldritch/eldritch_effect = human_target.has_status_effect(/datum/status_effect/eldritch/rust) || human_target.has_status_effect(/datum/status_effect/eldritch/ash) || human_target.has_status_effect(/datum/status_effect/eldritch/flesh) || human_target.has_status_effect(/datum/status_effect/eldritch/void)
if(eldritch_effect)
. = TRUE
eldritch_effect.on_effect()
@@ -131,25 +135,26 @@
/datum/eldritch_knowledge/flesh_mark
name = "Mark of Flesh"
gain_text = "I saw them, the marked ones. The screams... the silence."
desc = "Your sickly blade now applies a mark of flesh to those cut by it. Once marked, using your Mansus Grasp upon them will cause additional bleeding from the target."
desc = "Your Mansus Grasp now applies the Mark of Flesh on hit. Attack the afflicted with your Sickly Blade to detonate the mark. Upon detonation, the Mark of Flesh causes additional bleeding."
cost = 2
next_knowledge = list(/datum/eldritch_knowledge/summon/raw_prophet)
banned_knowledge = list(/datum/eldritch_knowledge/rust_mark,/datum/eldritch_knowledge/ash_mark)
banned_knowledge = list(/datum/eldritch_knowledge/rust_mark,/datum/eldritch_knowledge/ash_mark,/datum/eldritch_knowledge/void_mark)
route = PATH_FLESH
/datum/eldritch_knowledge/flesh_mark/on_eldritch_blade(target,user,proximity_flag,click_parameters)
/datum/eldritch_knowledge/flesh_mark/on_mansus_grasp(atom/target, mob/user, proximity_flag, click_parameters)
. = ..()
if(isliving(target))
. = TRUE
var/mob/living/living_target = target
living_target.apply_status_effect(/datum/status_effect/eldritch/flesh)
/datum/eldritch_knowledge/flesh_blade_upgrade
name = "Bleeding Steel"
gain_text = "It rained blood, that's when I understood the gravekeeper's advice."
desc = "Your blade will now cause additional bleeding to those hit by it."
gain_text = "And then, blood rained from the heavens. That's when I finally understood the Marshal's teachings."
desc = "Your Sickly Blade will now cause additional bleeding."
cost = 2
next_knowledge = list(/datum/eldritch_knowledge/summon/stalker)
banned_knowledge = list(/datum/eldritch_knowledge/ash_blade_upgrade,/datum/eldritch_knowledge/rust_blade_upgrade)
banned_knowledge = list(/datum/eldritch_knowledge/ash_blade_upgrade,/datum/eldritch_knowledge/rust_blade_upgrade,/datum/eldritch_knowledge/void_blade_upgrade)
route = PATH_FLESH
/datum/eldritch_knowledge/flesh_blade_upgrade/on_eldritch_blade(target,user,proximity_flag,click_parameters)
@@ -162,18 +167,18 @@
/datum/eldritch_knowledge/summon/raw_prophet
name = "Raw Ritual"
gain_text = "The uncanny man walks alone in the valley, I was able to call his aid."
desc = "You can now summon a Raw Prophet using eyes, a left arm, right arm and a pool of blood using a transmutation circle. Raw prophets have increased seeing range, and can see through walls. They can jaunt long distances, though they are fragile."
gain_text = "The Uncanny Man, who walks alone in the valley between the worlds... I was able to summon his aid."
desc = "You can now summon a Raw Prophet by transmutating a pair of eyes, a left arm and a pool of blood. Raw prophets have increased seeing range, as well as X-Ray vision, but they are very fragile."
cost = 1
required_atoms = list(/obj/item/organ/eyes,/obj/item/bodypart/l_arm,/obj/item/bodypart/r_arm,/obj/effect/decal/cleanable/blood)
mob_to_summon = /mob/living/simple_animal/hostile/eldritch/raw_prophet
next_knowledge = list(/datum/eldritch_knowledge/flesh_blade_upgrade,/datum/eldritch_knowledge/spell/blood_siphon,/datum/eldritch_knowledge/curse/paralysis)
next_knowledge = list(/datum/eldritch_knowledge/flesh_blade_upgrade,/datum/eldritch_knowledge/rune_carver,/datum/eldritch_knowledge/curse/paralysis)
route = PATH_FLESH
/datum/eldritch_knowledge/summon/stalker
name = "Lonely Ritual"
gain_text = "I was able to combine my greed and desires to summon an eldritch beast I have not seen before."
desc = "You can now summon a Stalker using a knife, a candle, a pen and a piece of paper using a transmutation circle. Stalkers possess the ability to shapeshift into various forms while assuming the vigor and powers of that form."
gain_text = "I was able to combine my greed and desires to summon an eldritch beast I had never seen before. An ever shapeshifting mass of flesh, it knew well my goals."
desc = "You can now summon a Stalker by transmutating a pair of eyes, a candle, a pen and a piece of paper. Stalkers can shapeshift into harmless animals to get close to the victim."
cost = 1
required_atoms = list(/obj/item/kitchen/knife,/obj/item/candle,/obj/item/pen,/obj/item/paper)
mob_to_summon = /mob/living/simple_animal/hostile/eldritch/stalker
@@ -182,7 +187,7 @@
/datum/eldritch_knowledge/summon/ashy
name = "Ashen Ritual"
gain_text = "I combined principle of hunger with desire of destruction. The eyeful lords have noticed me."
gain_text = "I combined my principle of hunger with my desire for destruction. And the Nightwatcher knew my name."
desc = "You can now summon an Ashen One by transmuting a pile of ash, a head and a book using a transmutation circle. They possess the ability to jaunt short distances and create a cascade of flames."
cost = 1
required_atoms = list(/obj/effect/decal/cleanable/ash,/obj/item/bodypart/head,/obj/item/book)
@@ -191,66 +196,43 @@
/datum/eldritch_knowledge/summon/rusty
name = "Rusted Ritual"
gain_text = "I combined principle of hunger with desire of corruption. The rusted hills call my name."
desc = "You can now summon a Rust Walker transmuting a vomit pool, a head, and a book using a transmutation circle. Rust Walkers possess the ability to spread rust and can fire bolts of rust to further corrode the area."
gain_text = "I combined my principle of hunger with my desire for corruption. And the Rusted Hills called my name."
desc = "You can now summon a Rust Walker by transmuting a vomit pool, a severed head, and a book using a transmutation circle. Rust Walkers possess the ability to spread rust and can fire bolts of rust to further corrode the area."
cost = 1
required_atoms = list(/obj/effect/decal/cleanable/vomit,/obj/item/bodypart/head,/obj/item/book)
mob_to_summon = /mob/living/simple_animal/hostile/eldritch/rust_spirit
next_knowledge = list(/datum/eldritch_knowledge/summon/stalker,/datum/eldritch_knowledge/spell/entropic_plume)
next_knowledge = list(/datum/eldritch_knowledge/spell/voidpull,/datum/eldritch_knowledge/spell/entropic_plume)
/datum/eldritch_knowledge/spell/blood_siphon
name = "Blood Siphon"
gain_text = "Our blood is all the same after all, the owl told me."
desc = "You are granted a spell that drains some of the targets health, and returns it to you. It also has a chance to transfer any wounds you possess onto the target."
gain_text = "No matter the man, we bleed all the same. That's what the Marshal told me."
desc = "You gain a spell that drains lifeforce from your enemies to restore your own."
cost = 1
spell_to_add = /obj/effect/proc_holder/spell/pointed/blood_siphon
next_knowledge = list(/datum/eldritch_knowledge/summon/raw_prophet,/datum/eldritch_knowledge/spell/area_conversion)
next_knowledge = list(/datum/eldritch_knowledge/summon/stalker,/datum/eldritch_knowledge/spell/voidpull)
/datum/eldritch_knowledge/final/flesh_final
name = "Priest's Final Hymn"
gain_text = "Man of this world. Hear me! For the time of the lord of arms has come!"
desc = "Bring three corpses to a transmutation rune to either ascend as The Lord of the Night or summon a single Terror of the Night, however you cannot ascend more than once."
gain_text = "Men of this world. Hear me, for the time of the Lord of Arms has come! The Emperor of Flesh guides my army!"
desc = "Bring 3 bodies onto a transmutation rune to shed your human form and ascend to untold power."
required_atoms = list(/mob/living/carbon/human)
cost = 5
route = PATH_FLESH
/datum/eldritch_knowledge/final/flesh_final/on_finished_recipe(mob/living/user, list/atoms, loc)
var/alert_ = alert(user,"Do you want to ascend as the lord of the night or just summon a terror of the night?","...","Yes","No")
user.SetImmobilized(10 HOURS) // no way someone will stand 10 hours in a spot, just so he can move while the alert is still showing.
switch(alert_)
if("No")
var/mob/living/summoned = new /mob/living/simple_animal/hostile/eldritch/armsy(loc)
message_admins("[summoned.name] is being summoned by [user.real_name] in [loc]")
var/list/mob/dead/observer/candidates = pollCandidatesForMob("Do you want to play as a [summoned.real_name]", ROLE_HERETIC, null, ROLE_HERETIC, 100,summoned)
user.SetImmobilized(0)
if(LAZYLEN(candidates) == 0)
to_chat(user,"<span class='warning'>No ghost could be found...</span>")
qdel(summoned)
return FALSE
var/mob/dead/observer/ghost_candidate = pick(candidates)
priority_announce("$^@&#*$^@(#&$(@&#^$&#^@# Fear the dark, for vassal of arms has ascended! Terror of the night has come! $^@&#*$^@(#&$(@&#^$&#^@#","#$^@&#*$^@(#&$(@&#^$&#^@#", 'sound/announcer/classic/spanomalies.ogg')
log_game("[key_name_admin(ghost_candidate)] has taken control of ([key_name_admin(summoned)]).")
summoned.ghostize(FALSE)
summoned.key = ghost_candidate.key
summoned.mind.add_antag_datum(/datum/antagonist/heretic_monster) //no you will NOT get the achivement you ghost.
var/datum/antagonist/heretic_monster/monster = summoned.mind.has_antag_datum(/datum/antagonist/heretic_monster)
var/datum/antagonist/heretic/master = user.mind.has_antag_datum(/datum/antagonist/heretic)
monster.set_owner(master)
master.ascended = TRUE
if("Yes")
var/mob/living/summoned = new /mob/living/simple_animal/hostile/eldritch/armsy/prime(loc,TRUE,10)
summoned.ghostize(0)
user.SetImmobilized(0)
priority_announce("$^@&#*$^@(#&$(@&#^$&#^@# Fear the dark, for king of arms has ascended! Lord of the night has come! $^@&#*$^@(#&$(@&#^$&#^@#","#$^@&#*$^@(#&$(@&#^$&#^@#", 'sound/announcer/classic/spanomalies.ogg')
log_game("[user.real_name] ascended as [summoned.real_name]")
if(!ishuman(user))
return
var/mob/living/carbon/human/H = user
H.client?.give_award(/datum/award/achievement/misc/flesh_ascension, H)
var/datum/antagonist/heretic/ascension = user.mind.has_antag_datum(/datum/antagonist/heretic)
ascension.ascended = TRUE
user.mind.transfer_to(summoned, TRUE)
user.gib()
. = ..()
priority_announce("$^@&#*$^@(#&$(@&#^$&#^@# Ever coiling vortex. Reality unfolded. THE LORD OF ARMS, [user.real_name] has ascended! Fear the ever twisting hand! $^@&#*$^@(#&$(@&#^$&#^@#","#$^@&#*$^@(#&$(@&#^$&#^@#", 'sound/announcer/classic/spanomalies.ogg')
user.mind.AddSpell(new /obj/effect/proc_holder/spell/targeted/shed_human_form)
if(!ishuman(user))
return
var/mob/living/carbon/human/H = user
H.physiology.brute_mod *= 0.5
H.physiology.burn_mod *= 0.5
var/datum/antagonist/heretic/heretic = user.mind.has_antag_datum(/datum/antagonist/heretic)
var/datum/eldritch_knowledge/flesh_grasp/ghoul1 = heretic.get_knowledge(/datum/eldritch_knowledge/flesh_grasp)
ghoul1.ghoul_amt *= 3
var/datum/eldritch_knowledge/flesh_ghoul/ghoul2 = heretic.get_knowledge(/datum/eldritch_knowledge/flesh_ghoul)
ghoul2.max_amt *= 3
return ..()
@@ -1,18 +1,18 @@
/datum/eldritch_knowledge/base_rust
name = "Blacksmith's Tale"
desc = "Inducts you into the Path of Rust. Allows you to transmute an eldritch blade with any trash item into a Blade of Rust."
gain_text = "'Let me tell you a story,' The Blacksmith said as he gazed into his rusty blade."
banned_knowledge = list(/datum/eldritch_knowledge/base_ash,/datum/eldritch_knowledge/base_flesh,/datum/eldritch_knowledge/final/ash_final,/datum/eldritch_knowledge/final/flesh_final)
desc = "Inducts you into the Path of Rust. Allows you to transmute a spear with any trash item into a Blade of Rust."
gain_text = "'Let me tell you a story', said the Blacksmith, as he gazed deep into his rusty blade."
banned_knowledge = list(/datum/eldritch_knowledge/base_ash,/datum/eldritch_knowledge/base_flesh,/datum/eldritch_knowledge/final/ash_final,/datum/eldritch_knowledge/final/flesh_final,/datum/eldritch_knowledge/final/void_final,/datum/eldritch_knowledge/base_void)
next_knowledge = list(/datum/eldritch_knowledge/rust_fist)
required_atoms = list(/obj/item/melee/sickly_blade,/obj/item/trash)
required_atoms = list(/obj/item/spear,/obj/item/trash)
result_atoms = list(/obj/item/melee/sickly_blade/rust)
cost = 1
cost = 0
route = PATH_RUST
/datum/eldritch_knowledge/rust_fist
name = "Grasp of Rust"
desc = "Empowers your Mansus Grasp to deal 500 damage to non-living matter and rust any structure it touches. Destroys already rusted structures."
gain_text = "Rust grows on the ceiling of the mansus."
desc = "Empowers your Mansus Grasp to deal 500 damage to non-living matter and rust any surface it touches. Already rusted surfaces are destroyed."
gain_text = "On the ceiling of the Mansus, rust grows as moss does on a stone."
cost = 1
next_knowledge = list(/datum/eldritch_knowledge/rust_regen)
var/rust_force = 500
@@ -20,35 +20,40 @@
route = PATH_RUST
/datum/eldritch_knowledge/rust_fist/on_mansus_grasp(atom/target, mob/user, proximity_flag, click_parameters)
. = ..()
var/check = FALSE
if(ismob(target))
var/mob/living/mobster = target
if(!mobster.mob_biotypes & MOB_ROBOTIC)
return FALSE
else
check = TRUE
if(user.a_intent == INTENT_HARM || check)
target.rust_heretic_act()
return TRUE
/datum/eldritch_knowledge/rust_fist/on_eldritch_blade(atom/target, mob/user, proximity_flag, click_parameters)
. = ..()
if(ishuman(target))
var/mob/living/carbon/human/H = target
var/datum/status_effect/eldritch/E = H.has_status_effect(/datum/status_effect/eldritch/rust) || H.has_status_effect(/datum/status_effect/eldritch/ash) || H.has_status_effect(/datum/status_effect/eldritch/flesh)
var/datum/status_effect/eldritch/E = H.has_status_effect(/datum/status_effect/eldritch/rust) || H.has_status_effect(/datum/status_effect/eldritch/ash) || H.has_status_effect(/datum/status_effect/eldritch/flesh) || H.has_status_effect(/datum/status_effect/eldritch/void)
if(E)
E.on_effect()
H.adjustOrganLoss(pick(ORGAN_SLOT_BRAIN,ORGAN_SLOT_EARS,ORGAN_SLOT_EYES,ORGAN_SLOT_LIVER,ORGAN_SLOT_LUNGS,ORGAN_SLOT_STOMACH,ORGAN_SLOT_HEART),25)
else
for(var/X in user.mind.spell_list)
if(!istype(X,/obj/effect/proc_holder/spell/targeted/touch/mansus_grasp))
continue
var/obj/effect/proc_holder/spell/targeted/touch/mansus_grasp/MG = X
MG.charge_counter = min(round(MG.charge_counter + MG.charge_max * 0.75),MG.charge_max)
target.rust_heretic_act()
return TRUE
/datum/eldritch_knowledge/spell/area_conversion
name = "Aggressive Spread"
desc = "Spreads rust to nearby turfs. Destroys already rusted walls."
gain_text = "All wise men know not to touch the bound king."
desc = "Spreads rust to nearby surfaces. Already rusted surfaces are destroyed."
gain_text = "All wise men know well not to touch the Bound King."
cost = 1
spell_to_add = /obj/effect/proc_holder/spell/aoe_turf/rust_conversion
next_knowledge = list(/datum/eldritch_knowledge/rust_blade_upgrade,/datum/eldritch_knowledge/curse/corrosion,/datum/eldritch_knowledge/spell/blood_siphon,/datum/eldritch_knowledge/spell/rust_wave)
next_knowledge = list(/datum/eldritch_knowledge/rust_blade_upgrade,/datum/eldritch_knowledge/curse/corrosion,/datum/eldritch_knowledge/crucible,/datum/eldritch_knowledge/spell/rust_wave)
route = PATH_RUST
/datum/eldritch_knowledge/spell/rust_wave
name = "Patron's Reach"
desc = "You can now send a bolt of rust that corrupts the immediate area, and poisons the first target hit."
gain_text = "Messengers of hope fear the Rustbringer."
gain_text = "Messengers of Hope, fear the Rustbringer!"
cost = 1
spell_to_add = /obj/effect/proc_holder/spell/aimed/rust_wave
route = PATH_RUST
@@ -56,7 +61,7 @@
/datum/eldritch_knowledge/rust_regen
name = "Leeching Walk"
desc = "Passively heals you when you are on rusted tiles."
gain_text = "'The strength was unparalleled, unnatural.' The Blacksmith was smiling."
gain_text = "The strength was unparalleled, unnatural. The Blacksmith was smiling."
cost = 1
next_knowledge = list(/datum/eldritch_knowledge/rust_mark,/datum/eldritch_knowledge/armor,/datum/eldritch_knowledge/essence)
route = PATH_RUST
@@ -75,26 +80,27 @@
/datum/eldritch_knowledge/rust_mark
name = "Mark of Rust"
desc = "Your eldritch blade now applies a rust mark. Rust marks have a chance to deal between 0 to 200 damage to 75% of enemies items. To activate the mark use your Mansus Grasp on it."
gain_text = "Lords of the depths help those in dire need at a cost."
desc = "Your Mansus Grasp now applies the Mark of Rust on hit. Attack the afflicted with your Sickly Blade to detonate the mark. Upon detonation, the Mark of Rust has a chance to deal between 0 to 200 damage to 75% of your enemy's held items."
gain_text = "Rusted Hills help those in dire need at a cost."
cost = 2
next_knowledge = list(/datum/eldritch_knowledge/spell/area_conversion)
banned_knowledge = list(/datum/eldritch_knowledge/ash_mark,/datum/eldritch_knowledge/flesh_mark)
banned_knowledge = list(/datum/eldritch_knowledge/ash_mark,/datum/eldritch_knowledge/flesh_mark,/datum/eldritch_knowledge/void_mark)
route = PATH_RUST
/datum/eldritch_knowledge/rust_mark/on_eldritch_blade(target,user,proximity_flag,click_parameters)
/datum/eldritch_knowledge/rust_mark/on_mansus_grasp(atom/target, mob/user, proximity_flag, click_parameters)
. = ..()
if(isliving(target))
. = TRUE
var/mob/living/living_target = target
living_target.apply_status_effect(/datum/status_effect/eldritch/rust)
/datum/eldritch_knowledge/rust_blade_upgrade
name = "Toxic Steel"
gain_text = "Let the blade guide you through the flesh."
desc = "Your blade of choice will now add toxin to enemies bloodstream."
name = "Toxic Blade"
gain_text = "The Blade will guide you through the flesh, should you let it."
desc = "Your blade of choice will now poison your enemies on hit."
cost = 2
next_knowledge = list(/datum/eldritch_knowledge/spell/entropic_plume)
banned_knowledge = list(/datum/eldritch_knowledge/ash_blade_upgrade,/datum/eldritch_knowledge/flesh_blade_upgrade)
banned_knowledge = list(/datum/eldritch_knowledge/ash_blade_upgrade,/datum/eldritch_knowledge/flesh_blade_upgrade,/datum/eldritch_knowledge/void_blade_upgrade)
route = PATH_RUST
/datum/eldritch_knowledge/rust_blade_upgrade/on_eldritch_blade(mob/target,user,proximity_flag,click_parameters)
@@ -106,8 +112,8 @@
/datum/eldritch_knowledge/spell/entropic_plume
name = "Entropic Plume"
desc = "You can now send a befuddling plume that blinds, poisons and makes enemies strike each other, while also converting the immediate area into rust."
gain_text = "If they knew, the truth would turn them against eachother."
desc = "You can now send a disorienting plume of pure entropy that blinds, poisons and makes enemies strike each other. It also rusts any tiles it affects."
gain_text = "The slightest glimmer of truth would turn them against eachother."
cost = 1
spell_to_add = /obj/effect/proc_holder/spell/cone/staggered/entropic_plume
next_knowledge = list(/datum/eldritch_knowledge/rust_fist_upgrade,/datum/eldritch_knowledge/spell/cleave,/datum/eldritch_knowledge/summon/rusty)
@@ -115,26 +121,26 @@
/datum/eldritch_knowledge/armor
name = "Armorer's Ritual"
desc = "You can now create eldritch armor using a built table and a gas mask on top of a transmutation rune."
gain_text = "For I am the heir to the throne of doom."
desc = "You can now create Eldritch Armor using a table and a gas mask."
gain_text = "The Rusted Hills welcomed the Blacksmith in their generosity."
cost = 1
next_knowledge = list(/datum/eldritch_knowledge/rust_regen,/datum/eldritch_knowledge/flesh_ghoul)
next_knowledge = list(/datum/eldritch_knowledge/rust_regen,/datum/eldritch_knowledge/cold_snap)
required_atoms = list(/obj/structure/table,/obj/item/clothing/mask/gas)
result_atoms = list(/obj/item/clothing/suit/hooded/cultrobes/eldritch)
/datum/eldritch_knowledge/essence
name = "Priest's Ritual"
desc = "You can now transmute a tank of water into a bottle of eldritch fluid."
gain_text = "This is an old recipe, I got it from an owl."
desc = "You can now transmute a tank of water and a glass shard into a bottle of eldritch water."
gain_text = "This is an old recipe. The Owl whispered it to me."
cost = 1
next_knowledge = list(/datum/eldritch_knowledge/rust_regen,/datum/eldritch_knowledge/spell/ashen_shift)
required_atoms = list(/obj/structure/reagent_dispensers/watertank)
required_atoms = list(/obj/structure/reagent_dispensers/watertank,/obj/item/shard)
result_atoms = list(/obj/item/reagent_containers/glass/beaker/eldritch)
/datum/eldritch_knowledge/rust_fist_upgrade
name = "Vile Grip"
desc = "Empowers your Mansus Grasp further, sickening your foes and making them vomit, while also strengthening the rate at which your hand decays objects."
gain_text = "A sickly diseased touch that was, yet, so welcoming."
gain_text = "His touch vile, terrible, and yet so terribly inviting.."
cost = 2
next_knowledge = list(/datum/eldritch_knowledge/spell/grasp_of_decay)
var/rust_force = 750
@@ -145,13 +151,13 @@
. = ..()
if(ishuman(target))
var/mob/living/carbon/human/H = target
H.set_disgust(75)
H.set_disgust(25)
return TRUE
/datum/eldritch_knowledge/spell/grasp_of_decay
name = "Grasp of Decay"
desc = "Applying your knowledge of rust to the human body, a knowledge that could decay your foes from the inside out, resulting in organ failure, vomiting, or eventual death through peeling flesh."
gain_text = "Decay, similar to Rust, yet so much more terribly uninviting."
desc = "Applying your knowledge of rust to the human body, a knowledge that could decay your foes from the inside out, resulting in organ failure, vomiting, or eventual death through the peeling of rotting flesh."
gain_text = "Rust, decay, it's all the same. All that remains is application."
cost = 2
spell_to_add = /obj/effect/proc_holder/spell/targeted/touch/grasp_of_decay
next_knowledge = list(/datum/eldritch_knowledge/final/rust_final)
@@ -160,7 +166,7 @@
/datum/eldritch_knowledge/final/rust_final
name = "Rustbringer's Oath"
desc = "Bring three corpses onto a transmutation rune. After you finish the ritual, rust will now automatically spread from the rune. Your healing on rust is also tripled, while you become more resilient overall."
gain_text = "Champion of rust. Corruptor of steel. Fear the dark for Rustbringer has come!"
gain_text = "Champion of rust. Corruptor of steel. Fear the dark for the Rustbringer has come! Rusted Hills, CALL MY NAME!"
cost = 5
required_atoms = list(/mob/living/carbon/human)
route = PATH_RUST
@@ -169,7 +175,6 @@
var/mob/living/carbon/human/H = user
H.physiology.brute_mod *= 0.5
H.physiology.burn_mod *= 0.5
H.client?.give_award(/datum/award/achievement/misc/rust_ascension, H)
priority_announce("$^@&#*$^@(#&$(@&#^$&#^@# Fear the decay, for the Rustbringer, [user.real_name] has ascended! None shall escape the corrosion! $^@&#*$^@(#&$(@&#^$&#^@#","#$^@&#*$^@(#&$(@&#^$&#^@#", 'sound/announcer/classic/spanomalies.ogg')
new /datum/rust_spread(loc)
var/datum/antagonist/heretic/ascension = H.mind.has_antag_datum(/datum/antagonist/heretic)
@@ -0,0 +1,223 @@
/datum/eldritch_knowledge/base_void
name = "Glimmer of Winter"
desc = "Opens up the path of void to you. Allows you to transmute a spear in a sub-zero temperature into a void blade."
gain_text = "I feel a shimmer in the air, atmosphere around me gets colder. I feel my body realizing the emptiness of existance. Something's watching me"
banned_knowledge = list(/datum/eldritch_knowledge/base_ash,/datum/eldritch_knowledge/base_flesh,/datum/eldritch_knowledge/final/ash_final,/datum/eldritch_knowledge/final/flesh_final,/datum/eldritch_knowledge/base_rust,/datum/eldritch_knowledge/final/rust_final)
next_knowledge = list(/datum/eldritch_knowledge/void_grasp)
required_atoms = list(/obj/item/spear)
result_atoms = list(/obj/item/melee/sickly_blade/void)
cost = 0
route = PATH_VOID
/datum/eldritch_knowledge/base_void/recipe_snowflake_check(list/atoms, loc)
. = ..()
var/turf/open/turfie = loc
if(turfie.GetTemperature() > T0C)
return FALSE
/datum/eldritch_knowledge/void_grasp
name = "Grasp of Void"
desc = "Temporarily mutes your victim, also lowers their body temperature."
gain_text = "I found the cold watcher who observes me. The resonance of cold grows within me. This isn't the end of the mystery."
cost = 1
route = PATH_VOID
next_knowledge = list(/datum/eldritch_knowledge/cold_snap)
/datum/eldritch_knowledge/void_grasp/on_mansus_grasp(atom/target, mob/user, proximity_flag, click_parameters)
. = ..()
if(!iscarbon(target))
return
var/mob/living/carbon/carbon_target = target
var/turf/open/turfie = get_turf(carbon_target)
turfie.TakeTemperature(-20)
carbon_target.adjust_bodytemperature(-40)
carbon_target.silent = clamp(carbon_target.silent + 4, 0, 20)
return TRUE
/datum/eldritch_knowledge/void_grasp/on_eldritch_blade(atom/target, mob/user, proximity_flag, click_parameters)
. = ..()
if(!ishuman(target))
return
var/mob/living/carbon/human/H = target
var/datum/status_effect/eldritch/E = H.has_status_effect(/datum/status_effect/eldritch/rust) || H.has_status_effect(/datum/status_effect/eldritch/ash) || H.has_status_effect(/datum/status_effect/eldritch/flesh) || H.has_status_effect(/datum/status_effect/eldritch/void)
if(!E)
return
E.on_effect()
H.silent = clamp(H.silent + 3, 0, 20)
/datum/eldritch_knowledge/cold_snap
name = "Aristocrat's Way"
desc = "Makes you immune to cold temperatures, and you no longer need to breathe, you can still take damage from lack of pressure."
gain_text = "I found a thread of cold breath. It lead me to a strange shrine, all made of crystals. Translucent and white, a depiction of a nobleman stood before me."
cost = 1
route = PATH_VOID
next_knowledge = list(/datum/eldritch_knowledge/void_cloak,/datum/eldritch_knowledge/void_mark,/datum/eldritch_knowledge/armor)
/datum/eldritch_knowledge/cold_snap/on_gain(mob/user)
. = ..()
ADD_TRAIT(user,TRAIT_RESISTCOLD,MAGIC_TRAIT)
ADD_TRAIT(user, TRAIT_NOBREATH, MAGIC_TRAIT)
/datum/eldritch_knowledge/cold_snap/on_lose(mob/user)
. = ..()
REMOVE_TRAIT(user,TRAIT_RESISTCOLD,MAGIC_TRAIT)
ADD_TRAIT(user, TRAIT_NOBREATH, MAGIC_TRAIT)
/datum/eldritch_knowledge/void_cloak
name = "Void Cloak"
desc = "A cloak that can become invisbile at will, hiding items you store in it. To create it transmute a glass shard, any item of clothing that you can fit over your uniform and any type of bedsheet."
gain_text = "Owl is the keeper of things that quite not are in practice, but in theory are."
cost = 1
next_knowledge = list(/datum/eldritch_knowledge/flesh_ghoul,/datum/eldritch_knowledge/cold_snap)
result_atoms = list(/obj/item/clothing/suit/hooded/cultrobes/void)
required_atoms = list(/obj/item/shard,/obj/item/clothing/suit,/obj/item/bedsheet)
/datum/eldritch_knowledge/void_mark
name = "Mark of Void"
gain_text = "A gust of wind? Maybe a shimmer in the air. Presence is overwhelming, my senses betrayed me, my mind is my enemy."
desc = "Your mansus grasp now applies mark of void status effect. To proc the mark, use your sickly blade on the marked. Mark of void when procced lowers the victims body temperature significantly."
cost = 2
next_knowledge = list(/datum/eldritch_knowledge/spell/void_phase)
banned_knowledge = list(/datum/eldritch_knowledge/rust_mark,/datum/eldritch_knowledge/ash_mark,/datum/eldritch_knowledge/flesh_mark)
route = PATH_VOID
/datum/eldritch_knowledge/void_mark/on_mansus_grasp(atom/target, mob/user, proximity_flag, click_parameters)
. = ..()
if(!isliving(target))
return
. = TRUE
var/mob/living/living_target = target
living_target.apply_status_effect(/datum/status_effect/eldritch/void)
/datum/eldritch_knowledge/spell/void_phase
name = "Void Phase"
gain_text = "Reality bends under the power of memory, for all is fleeting, and what else stays?"
desc = "You gain a long range pointed blink that allows you to instantly teleport to your location, it causes aoe damage around you and your chosen location."
cost = 1
spell_to_add = /obj/effect/proc_holder/spell/pointed/void_blink
next_knowledge = list(/datum/eldritch_knowledge/rune_carver,/datum/eldritch_knowledge/crucible,/datum/eldritch_knowledge/void_blade_upgrade)
route = PATH_VOID
/datum/eldritch_knowledge/rune_carver
name = "Carving Knife"
gain_text = "Etched, carved... eternal. I can carve the monolith and evoke their powers!"
desc = "You can create a carving knife, which allows you to create up to 3 carvings on the floor that have various effects on nonbelievers who walk over them. They make quite a handy throwing weapon. To create the carving knife transmute a knife with a glass shard and a piece of paper."
cost = 1
next_knowledge = list(/datum/eldritch_knowledge/spell/void_phase,/datum/eldritch_knowledge/summon/raw_prophet)
required_atoms = list(/obj/item/kitchen/knife,/obj/item/shard,/obj/item/paper)
result_atoms = list(/obj/item/melee/rune_knife)
/datum/eldritch_knowledge/crucible
name = "Mawed Crucible"
gain_text = "This is pure agony, i wasn't able to summon the dereliction of the emperor, but i stumbled upon a diffrent recipe..."
desc = "Allows you to create a mawed crucible, eldritch structure that allows you to create potions of various effects, to do so transmute a table with a watertank"
cost = 1
next_knowledge = list(/datum/eldritch_knowledge/spell/void_phase,/datum/eldritch_knowledge/spell/area_conversion)
required_atoms = list(/obj/structure/reagent_dispensers/watertank,/obj/structure/table)
result_atoms = list(/obj/structure/eldritch_crucible)
/datum/eldritch_knowledge/void_blade_upgrade
name = "Seeking blade"
gain_text = "Fleeting memories, fleeting feet. I can mark my way with the frozen blood upon the snow. Covered and forgotten."
desc = "You can now use your blade on a distant marked target to move to them and attack them."
cost = 2
next_knowledge = list(/datum/eldritch_knowledge/spell/voidpull)
banned_knowledge = list(/datum/eldritch_knowledge/ash_blade_upgrade,/datum/eldritch_knowledge/flesh_blade_upgrade,/datum/eldritch_knowledge/rust_blade_upgrade)
route = PATH_VOID
/datum/eldritch_knowledge/void_blade_upgrade/on_ranged_attack_eldritch_blade(atom/target, mob/user, click_parameters)
. = ..()
var/mob/living/carbon/carbon_human = user
var/mob/living/carbon/human/human_target = target
var/datum/status_effect/eldritch/effect = human_target.has_status_effect(/datum/status_effect/eldritch/rust) || human_target.has_status_effect(/datum/status_effect/eldritch/ash) || human_target.has_status_effect(/datum/status_effect/eldritch/flesh) || human_target.has_status_effect(/datum/status_effect/eldritch/void)
if(!effect)
return
var/dir = angle2dir(dir2angle(get_dir(user,human_target))+180)
carbon_human.forceMove(get_step(human_target,dir))
var/obj/item/melee/sickly_blade/blade = carbon_human.get_active_held_item()
blade.melee_attack_chain(carbon_human,human_target,attackchain_flags = ATTACK_IGNORE_CLICKDELAY)
/datum/eldritch_knowledge/spell/voidpull
name = "Void Pull"
gain_text = "This entity calls itself The Aristocrat, I'm close to finishing what was started."
desc = "You gain an ability that let's you pull people around you closer to you."
cost = 1
spell_to_add = /obj/effect/proc_holder/spell/targeted/void_pull
next_knowledge = list(/datum/eldritch_knowledge/spell/boogiewoogie,/datum/eldritch_knowledge/spell/blood_siphon,/datum/eldritch_knowledge/summon/rusty)
route = PATH_VOID
/datum/eldritch_knowledge/spell/boogiewoogie
name = "Void's Applause"
gain_text = "The curtain is closing, and I'm certain that The Aristocrat is proud of me."
desc = "With the clap of your hands, you can swap your position with someone within your vision."
cost = 2
spell_to_add = /obj/effect/proc_holder/spell/pointed/boogie_woogie
next_knowledge = list(/datum/eldritch_knowledge/spell/domain_expansion)
route = PATH_VOID
/datum/eldritch_knowledge/spell/domain_expansion
name = "Infinite Void"
gain_text = "This world will be my stage, and nothing will be out of my reach."
desc = "Gain the ability to mark a 7x7 area as your domain after a short delay. Creatures in your domain are slowed and branded with a void mark, allowing you to quickly teleport to them and slash them, further inhibiting their ability to move."
cost = 2
spell_to_add = /obj/effect/proc_holder/spell/aoe_turf/domain_expansion
next_knowledge = list(/datum/eldritch_knowledge/final/void_final)
route = PATH_VOID
/datum/eldritch_knowledge/final/void_final
name = "Waltz at the End of Time"
desc = "Bring 3 corpses onto the transmutation rune. After you finish the ritual you will automatically silence people around you and will summon a snow storm around you."
gain_text = "The world falls into darkness. I stand in an empty plane, small flakes of ice fall from the sky. The Aristocrat stands before me, he motions to me. We will play a waltz to the whispers of dying reality, as the world is destroyed before our eyes."
cost = 5
required_atoms = list(/mob/living/carbon/human)
route = PATH_VOID
///soundloop for the void theme
var/datum/looping_sound/void_loop/sound_loop
///Reference to the ongoing voidstorm that surrounds the heretic
var/datum/weather/void_storm/storm
/datum/eldritch_knowledge/final/void_final/on_finished_recipe(mob/living/user, list/atoms, loc)
var/mob/living/carbon/human/H = user
user.mind.AddSpell(new /obj/effect/proc_holder/spell/aoe_turf/repulse/eldritch)
H.physiology.brute_mod *= 0.5
H.physiology.burn_mod *= 0.5
ADD_TRAIT(H, TRAIT_RESISTLOWPRESSURE, MAGIC_TRAIT)
priority_announce("$^@&#*$^@(#&$(@&#^$&#^@# The nobleman of void [H.real_name] has arrived, step along the Waltz that ends worlds! $^@&#*$^@(#&$(@&#^$&#^@#","#$^@&#*$^@(#&$(@&#^$&#^@#", 'sound/announcer/classic/spanomalies.ogg')
sound_loop = new(list(user),TRUE,TRUE)
return ..()
/datum/eldritch_knowledge/final/void_final/on_death()
if(sound_loop)
sound_loop.stop()
if(storm)
storm.end()
QDEL_NULL(storm)
/datum/eldritch_knowledge/final/void_final/on_life(mob/user)
. = ..()
if(!finished)
return
for(var/mob/living/carbon/livies in spiral_range(7,user)-user)
if(IS_HERETIC_MONSTER(livies) || IS_HERETIC(livies))
return
livies.silent = clamp(livies.silent + 1, 0, 5)
livies.adjust_bodytemperature(-20)
var/turf/turfie = get_turf(user)
if(!isopenturf(turfie))
return
var/turf/open/open_turfie = turfie
open_turfie.TakeTemperature(-20)
var/area/user_area = get_area(user)
var/turf/user_turf = get_turf(user)
if(!storm)
storm = new /datum/weather/void_storm(list(user_turf.z))
storm.telegraph()
storm.area_type = user_area.type
storm.impacted_areas = list(user_area)
storm.update_areas()
@@ -202,8 +202,9 @@
filled = 1
release_pressure = ONE_ATMOSPHERE*2
/obj/machinery/portable_atmospherics/canister/Initialize(mapload, datum/gas_mixture/existing_mixture)
. = ..()
/obj/machinery/portable_atmospherics/canister/New(loc, datum/gas_mixture/existing_mixture)
..()
if(existing_mixture)
air_contents.copy_from(existing_mixture)
else
@@ -221,10 +222,8 @@
air_contents.set_temperature(starter_temp)
/obj/machinery/portable_atmospherics/canister/air/create_gas()
var/oh_two = /datum/gas/oxygen
var/dihydrogen = /datum/gas/nitrogen //how to piss of chemists
air_contents.set_moles(oh_two, (O2STANDARD * maximum_pressure * filled) * air_contents.return_volume() / (R_IDEAL_GAS_EQUATION * air_contents.return_temperature()))
air_contents.set_moles(dihydrogen, (N2STANDARD * maximum_pressure * filled) * air_contents.return_volume() / (R_IDEAL_GAS_EQUATION * air_contents.return_temperature()))
air_contents.set_moles(/datum/gas/oxygen, (O2STANDARD * maximum_pressure * filled) * air_contents.return_volume() / (R_IDEAL_GAS_EQUATION * air_contents.return_temperature()))
air_contents.set_moles(/datum/gas/nitrogen, (N2STANDARD * maximum_pressure * filled) * air_contents.return_volume() / (R_IDEAL_GAS_EQUATION * air_contents.return_temperature()))
/obj/machinery/portable_atmospherics/canister/update_icon_state()
if(stat & BROKEN)
@@ -0,0 +1,51 @@
/datum/blackmarket_item
var/name // Name for the item entry used in the uplink.
var/desc // Description for the item entry used in the uplink.
var/category // The category this item belongs to, should be already declared in the market that this item is accessible in.
var/list/markets = list(/datum/blackmarket_market/blackmarket) // "/datum/blackmarket_market"s that this item should be in, used by SSblackmarket on init.
var/price // Price for the item, if not set creates a price according to the *_min and *_max vars.
var/stock // How many of this type of item is available, if not set creates a price according to the *_min and *_max vars.
var/item // Path to or the item itself what this entry is for, this should be set even if you override spawn_item to spawn your item.
var/price_min = 0 // Minimum price for the item if generated randomly.
var/price_max = 0 // Maximum price for the item if generated randomly.
var/stock_min = 1 // Minimum amount that there should be of this item in the market if generated randomly. This defaults to 1 as most items will have it as 1.
var/stock_max = 0 // Maximum amount that there should be of this item in the market if generated randomly.
var/availability_prob = 0 // Probability for this item to be available. Used by SSblackmarket on init.
/datum/blackmarket_item/New()
if(isnull(price))
price = rand(price_min, price_max)
if(isnull(stock))
stock = rand(stock_min, stock_max)
/datum/blackmarket_item/proc/spawn_item(loc) // Used for spawning the wanted item, override if you need to do something special with the item.
return new item(loc)
/datum/blackmarket_item/proc/buy(obj/item/blackmarket_uplink/uplink, mob/buyer, shipping_method) // Buys the item and makes SSblackmarket handle it.
// Sanity
if(!istype(uplink) || !istype(buyer))
return FALSE
if(!item || stock <= 0) // This shouldn't be able to happen unless there was some manipulation or admin fuckery.
return FALSE
var/datum/blackmarket_purchase/purchase = new(src, uplink, shipping_method) // Alright, the item has been purchased.
if(SSblackmarket.queue_item(purchase)) // SSblackmarket takes care of the shipping.
stock--
log_game("[key_name(buyer)] has succesfully purchased [name] using [shipping_method] for shipping.")
return TRUE
return FALSE
/datum/blackmarket_purchase // This exists because it is easier to keep track of all the vars this way.
var/datum/blackmarket_item/entry // The entry being purchased.
var/item // Instance of the item being sent.
var/obj/item/blackmarket_uplink/uplink // The uplink where this purchase was done from.
var/method // Shipping method used to buy this item.
/datum/blackmarket_purchase/New(_entry, _uplink, _method)
entry = _entry
if(!ispath(entry.item))
item = entry.item
uplink = _uplink
method = _method
@@ -0,0 +1,55 @@
/datum/blackmarket_item/clothing
category = "Clothing"
/datum/blackmarket_item/clothing/ninja_mask
name = "Space Ninja Mask"
desc = "Apart from being acid, lava, fireproof and being hard to take off someone it does nothing special on it's own."
item = /obj/item/clothing/mask/gas/space_ninja
price_min = 200
price_max = 500
stock_max = 3
availability_prob = 40
/datum/blackmarket_item/clothing/durathread_vest
name = "Durathread Vest"
desc = "Dont let them tell you this stuff is \"Like asbestos\" or \"Pulled from the market for safety concerns\". It could be the difference between a robusting and a retaliation."
item = /obj/item/clothing/suit/armor/vest/durathread
price_min = 200
price_max = 400
stock_max = 4
availability_prob = 50
/datum/blackmarket_item/clothing/durathread_helmet
name = "Durathread Helmet"
desc = "Customers ask why it's called a helmet when it's just made from armoured fabric and I always say the same thing: No refunds."
item = /obj/item/clothing/head/helmet/durathread
price_min = 100
price_max = 200
stock_max = 4
availability_prob = 50
/datum/blackmarket_item/clothing/full_spacesuit_set
name = "Nanotrasen Branded Spacesuit Box"
desc = "A few boxes of \"Old Style\" space suits fell off the back of a space truck."
item = /obj/item/storage/box
price_min = 1500
price_max = 4000
stock_max = 3
availability_prob = 30
/datum/blackmarket_item/clothing/full_spacesuit_set/spawn_item(loc)
var/obj/item/storage/box/B = ..()
B.name = "Spacesuit Box"
B.desc = "It has a NT logo on it."
new /obj/item/clothing/suit/space(B)
new /obj/item/clothing/head/helmet/space(B)
return B
/datum/blackmarket_item/clothing/chameleon_hat
name = "Chameleon Hat"
desc = "Pick any hat you want with this Handy device. Not Quality Tested."
item = /obj/item/clothing/head/chameleon/broken
price_min = 100
price_max = 200
stock_max = 2
availability_prob = 70
@@ -0,0 +1,58 @@
/datum/blackmarket_item/consumable
category = "Consumables"
/datum/blackmarket_item/consumable/clown_tears
name = "Bowl of Clown's Tears"
desc = "Guaranteed fresh from Weepy Boggins Tragic Kitchen"
item = /obj/item/reagent_containers/food/snacks/soup/clownstears
stock = 1
price_min = 520
price_max = 600
availability_prob = 10
/datum/blackmarket_item/consumable/donk_pocket_box
name = "Box of Donk Pockets"
desc = "A well packaged box containing the favourite snack of every spacefarer."
item = /obj/item/storage/box/donkpockets
stock_min = 2
stock_max = 5
price_min = 325
price_max = 400
availability_prob = 80
/datum/blackmarket_item/consumable/suspicious_pills
name = "Bottle of Suspicious Pills"
desc = "A random cocktail of luxury drugs that are sure to put a smile on your face!"
item = /obj/item/storage/pill_bottle
stock_min = 2
stock_max = 3
price_min = 400
price_max = 700
availability_prob = 50
/datum/blackmarket_item/consumable/suspicious_pills/spawn_item(loc)
var/pillbottle = pick(list(/obj/item/storage/pill_bottle/zoom,
/obj/item/storage/pill_bottle/happy,
/obj/item/storage/pill_bottle/lsd,
/obj/item/storage/pill_bottle/aranesp,
/obj/item/storage/pill_bottle/stimulant))
return new pillbottle(loc)
/datum/blackmarket_item/consumable/floor_pill
name = "Strange Pill"
desc = "The Russian Roulette of the Maintenance Tunnels."
item = /obj/item/reagent_containers/pill/floorpill
stock_min = 5
stock_max = 35
price_min = 10
price_max = 60
availability_prob = 50
/datum/blackmarket_item/consumable/pumpup
name = "Shoddy Stimulants"
desc = "Feel the energy inside each needle!"
item = /obj/item/reagent_containers/hypospray/medipen/stimpack
stock_max = 5
price_min = 50
price_max = 150
availability_prob = 90
@@ -0,0 +1,53 @@
/datum/blackmarket_item/misc
category = "Miscellaneous"
/datum/blackmarket_item/misc/cap_gun
name = "Cap Gun"
desc = "Prank your friends with this harmless gun! Harmlessness guranteed."
item = /obj/item/toy/gun
price_min = 50
price_max = 200
stock_max = 6
availability_prob = 80
/datum/blackmarket_item/misc/shoulder_holster
name = "Shoulder holster"
desc = "Yeehaw, hardboiled friends! This holster is the first step in your dream of becoming a detective and being allowed to shoot real guns!"
item = /obj/item/storage/belt/holster
price_min = 400
price_max = 800
stock_max = 8
availability_prob = 60
/datum/blackmarket_item/misc/holywater
name = "Flask of holy water"
desc = "Father Lootius' own brand of ready-made holy water."
item = /obj/item/reagent_containers/food/drinks/bottle/holywater
price_min = 400
price_max = 600
stock_max = 3
availability_prob = 40
/datum/blackmarket_item/misc/holywater/spawn_item(loc)
if (prob(6.66))
return new /obj/item/reagent_containers/glass/beaker/unholywater(loc)
return ..()
/datum/blackmarket_item/misc/strange_seed
name = "Strange Seeds"
desc = "An Exotic Variety of seed that can contain anything from glow to acid."
item = /obj/item/seeds/random
price_min = 320
price_max = 360
stock_min = 2
stock_max = 5
availability_prob = 50
/datum/blackmarket_item/misc/smugglers_satchel
name = "Smuggler's Satchel"
desc = "This easily hidden satchel can become a versatile tool to anybody with the desire to keep certain items out of sight and out of mind."
item = /obj/item/storage/backpack/satchel/flat
price_min = 750
price_max = 1000
stock_max = 2
availability_prob = 30
@@ -0,0 +1,74 @@
/datum/blackmarket_item/tool
category = "Tools"
/datum/blackmarket_item/tool/caravan_wrench
name = "Experimental Wrench"
desc = "The extra fast and handy wrench you always wanted!"
item = /obj/item/wrench/caravan
stock = 1
price_min = 400
price_max = 800
availability_prob = 20
/datum/blackmarket_item/tool/caravan_wirecutters
name = "Experimental Wirecutters"
desc = "The extra fast and handy wirecutters you always wanted!"
item = /obj/item/wirecutters/caravan
stock = 1
price_min = 400
price_max = 800
availability_prob = 20
/datum/blackmarket_item/tool/caravan_screwdriver
name = "Experimental Screwdriver"
desc = "The extra fast and handy screwdriver you always wanted!"
item = /obj/item/screwdriver/caravan
stock = 1
price_min = 400
price_max = 800
availability_prob = 20
/datum/blackmarket_item/tool/caravan_crowbar
name = "Experimental Crowbar"
desc = "The extra fast and handy crowbar you always wanted!"
item = /obj/item/crowbar/red/caravan
stock = 1
price_min = 400
price_max = 800
availability_prob = 20
/datum/blackmarket_item/tool/binoculars
name = "Binoculars"
desc = "Increase your sight by 150% with this handy tool!"
item = /obj/item/binoculars
stock = 1
price_min = 400
price_max = 960
availability_prob = 30
/datum/blackmarket_item/tool/riot_shield
name = "Riot Shield"
desc = "Protect yourself from an unexpected riot at your local police department!"
item = /obj/item/shield/riot
price_min = 450
price_max = 650
stock_max = 2
availability_prob = 50
/datum/blackmarket_item/tool/thermite_bottle
name = "Thermite Bottle"
desc = "30 units of Thermite to assist in creating a quick access point or get away!"
item = /obj/item/reagent_containers/glass/bottle/thermite
price_min = 500
price_max = 1500
stock_max = 3
availability_prob = 30
/datum/blackmarket_item/tool/science_goggles
name = "Science Goggles"
desc = "These glasses scan the contents of containers and projects their contents to the user in an easy-to-read format."
item = /obj/item/clothing/glasses/science
price_min = 150
price_max = 200
stock_max = 3
availability_prob = 50
@@ -0,0 +1,41 @@
/datum/blackmarket_item/weapon
category = "Weapons"
/datum/blackmarket_item/weapon/bear_trap
name = "Bear Trap"
desc = "Get the janitor back at his own game with this affordable prank kit."
item = /obj/item/restraints/legcuffs/beartrap
price_min = 300
price_max = 550
stock_max = 3
availability_prob = 40
/datum/blackmarket_item/weapon/shotgun_dart
name = "Shotgun Dart"
desc = "These handy darts can be filled up with any chemical and be shot with a shotgun! \
Prank your friends by shooting them with laughter! \
Not recommended for commercial use."
item = /obj/item/ammo_casing/shotgun/dart
price_min = 10
price_max = 50
stock_min = 5
stock_max = 30
availability_prob = 40
/datum/blackmarket_item/weapon/bone_spear
name = "Bone Spear"
desc = "Authentic tribal spear, made from real bones! A steal at any price, especially if you're a caveman."
item = /obj/item/spear/bonespear
price_min = 200
price_max = 300
stock_max = 3
availability_prob = 60
/datum/blackmarket_item/weapon/emp_grenade
name = "EMP Grenade"
desc = "Use this grenade for SHOCKING results!"
item = /obj/item/grenade/empgrenade
price_min = 100
price_max = 400
stock_max = 2
availability_prob = 50
@@ -0,0 +1,40 @@
/datum/blackmarket_market
var/name = "huh?" // Name for the market.
var/list/shipping // Available shipping methods and prices, just leave the shipping method out that you don't want to have.
// Automatic vars, do not touch these.
var/list/available_items = list() // Items available from this market, populated by SSblackmarket on initialization.
var/list/categories = list() // Item categories available from this market, only items which are in these categories can be gotten from this market.
/datum/blackmarket_market/proc/add_item(datum/blackmarket_item/item) // Adds item to the available items and add it's category if it is not in categories yet.
if(!prob(initial(item.availability_prob)))
return FALSE
if(ispath(item))
item = new item()
if(!(item.category in categories))
categories += item.category
available_items[item.category] = list()
available_items[item.category] += item
return TRUE
/datum/blackmarket_market/proc/purchase(item, category, method, obj/item/blackmarket_uplink/uplink, user) // Handles buying the item, this is mainly for future use and moving the code away from the uplink.
if(!istype(uplink) || !(method in shipping))
return FALSE
for(var/datum/blackmarket_item/I in available_items[category])
if(I.type != item)
continue
var/price = I.price + shipping[method]
if(uplink.money < price) // I can't get the price of the item and shipping in a clean way to the UI, so I have to do this.
to_chat("<span class='warning'>You don't have enough credits in [uplink] for [I] with [method] shipping.</span>")
return FALSE
if(I.buy(uplink, user, method))
uplink.money -= price
return TRUE
return FALSE
/datum/blackmarket_market/blackmarket
name = "Black Market"
shipping = list(SHIPPING_METHOD_LTSRBT =50,
SHIPPING_METHOD_LAUNCH =10,
SHIPPING_METHOD_TELEPORT=75)
@@ -0,0 +1,92 @@
/obj/item/circuitboard/machine/ltsrbt
name = "LTSRBT (Machine Board)"
icon_state = "bluespacearray"
build_path = /obj/machinery/ltsrbt
req_components = list(
/obj/item/stack/ore/bluespace_crystal = 2,
/obj/item/stock_parts/subspace/ansible = 1,
/obj/item/stock_parts/micro_laser = 1,
/obj/item/stock_parts/scanning_module = 2)
def_components = list(/obj/item/stack/ore/bluespace_crystal = /obj/item/stack/ore/bluespace_crystal/artificial)
/obj/machinery/ltsrbt
name = "Long-To-Short-Range-Bluespace-Transciever"
desc = "The LTSRBT is a compact teleportation machine for recieving and sending items outside the station and inside the station.\nUsing teleportation frequencies stolen from NT it is near undetectable.\nEssential for any illegal market operations on NT stations.\n"
icon_state = "exonet_node"
circuit = /obj/item/circuitboard/machine/ltsrbt
density = TRUE
idle_power_usage = 200
var/power_efficiency = 1 // Divider for power_usage_per_teleport.
var/power_usage_per_teleport = 10000 // Power used per teleported which gets divided by power_efficiency.
var/recharge_time = 0 // The time it takes for the machine to recharge before being able to send or recieve items.
var/recharge_cooldown = 0 // Current recharge progress.
var/base_recharge_time = 100 // Base recharge time which is used to get recharge_time.
var/recieving // Current /datum/blackmarket_purchase being recieved.
var/transmitting // Current /datum/blackmarket_purchase being sent to the target uplink.
var/list/datum/blackmarket_purchase/queue = list() // Queue for purchases that the machine should recieve and send.
/obj/machinery/ltsrbt/Initialize()
. = ..()
SSblackmarket.telepads += src
/obj/machinery/ltsrbt/Destroy()
SSblackmarket.telepads -= src
if(SSblackmarket.telepads.len) // Bye bye orders.
for(var/datum/blackmarket_purchase/P in queue)
SSblackmarket.queue_item(P)
. = ..()
/obj/machinery/ltsrbt/RefreshParts()
recharge_time = base_recharge_time
for(var/obj/item/stock_parts/scanning_module/scan in component_parts) // On tier 4 recharge_time should be 20 and by default it is 80 as scanning modules should be tier 1.
recharge_time -= scan.rating * 10
recharge_cooldown = recharge_time
power_efficiency = 0
for(var/obj/item/stock_parts/micro_laser/laser in component_parts)
power_efficiency += laser.rating
if(!power_efficiency) // Shouldn't happen but you never know.
power_efficiency = 1
/obj/machinery/ltsrbt/proc/add_to_queue(datum/blackmarket_purchase/purchase) // Adds /datum/blackmarket_purchase to queue unless the machine is free, then it sets the purchase to be instantly recieved
if(!recharge_cooldown && !recieving && !transmitting)
recieving = purchase
return
queue += purchase
/obj/machinery/ltsrbt/process()
if(stat & NOPOWER)
return
if(recharge_cooldown)
recharge_cooldown--
return
var/turf/T = get_turf(src)
if(recieving)
var/datum/blackmarket_purchase/P = recieving
if(!P.item || ispath(P.item))
P.item = P.entry.spawn_item(T)
else
var/atom/movable/M = P.item
M.forceMove(T)
use_power(power_usage_per_teleport / power_efficiency)
var/datum/effect_system/spark_spread/sparks = new
sparks.set_up(5, 1, get_turf(src))
sparks.attach(P.item)
sparks.start()
recieving = null
transmitting = P
recharge_cooldown = recharge_time
return
else if(transmitting)
var/datum/blackmarket_purchase/P = transmitting
if(!P.item)
QDEL_NULL(transmitting)
if(!(P.item in T.contents))
QDEL_NULL(transmitting)
return
do_teleport(P.item, get_turf(P.uplink))
use_power(power_usage_per_teleport / power_efficiency)
QDEL_NULL(transmitting)
recharge_cooldown = recharge_time
return
if(queue.len)
recieving = pick_n_take(queue)
@@ -0,0 +1,141 @@
/obj/item/blackmarket_uplink
name = "Black Market Uplink"
icon = 'icons/obj/blackmarket.dmi'
icon_state = "uplink"
// UI variables.
var/ui_x = 720
var/ui_y = 480
var/viewing_category
var/viewing_market
var/selected_item
var/buying
var/money = 0 // How much money is inserted into the uplink.
var/list/accessible_markets = list(/datum/blackmarket_market/blackmarket) // List of typepaths for "/datum/blackmarket_market"s that this uplink can access.
/obj/item/blackmarket_uplink/Initialize()
. = ..()
if(accessible_markets.len)
viewing_market = accessible_markets[1]
var/list/categories = SSblackmarket.markets[viewing_market].categories
if(categories && categories.len)
viewing_category = categories[1]
/obj/item/blackmarket_uplink/attackby(obj/item/I, mob/user, params)
if(istype(I, /obj/item/holochip) || istype(I, /obj/item/stack/spacecash) || istype(I, /obj/item/coin))
var/worth = I.get_item_credit_value()
if(!worth)
to_chat(user, "<span class='warning'>[I] doesn't seem to be worth anything!</span>")
money += worth
to_chat(user, "<span class='notice'>You slot [I] into [src] and it reports a total of [money] credits inserted.</span>")
qdel(I)
return
. = ..()
/obj/item/blackmarket_uplink/AltClick(mob/user)
if(!isliving(user) || !user.canUseTopic(src, BE_CLOSE, FALSE, NO_TK))
return
var/amount_to_remove = FLOOR(input(user, "How much do you want to withdraw? Current Amount: [money]", "Withdraw Funds", 5) as num|null, 1)
if(!user.canUseTopic(src, BE_CLOSE, FALSE, NO_TK))
return
if(!amount_to_remove || amount_to_remove < 0)
return
if(amount_to_remove > money)
to_chat(user, "<span class='warning'>There is only [money] credits in [src]</span>")
return
var/obj/item/holochip/holochip = new (user.drop_location(), amount_to_remove)
money -= amount_to_remove
holochip.name = "washed " + holochip.name
user.put_in_hands(holochip)
to_chat(user, "<span class='notice'>You withdraw [amount_to_remove] credits into a holochip.</span>")
/obj/item/blackmarket_uplink/ui_interact(mob/user, ui_key = "BlackMarketUplink", datum/tgui/ui = null, force_open = FALSE, datum/tgui/master_ui = null, datum/ui_state/state = GLOB.default_state)
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
ui = new(user, src, ui_key, name, ui_x, ui_y, master_ui, state)
ui.open()
/obj/item/blackmarket_uplink/ui_data(mob/user)
var/list/data = list()
var/datum/blackmarket_market/market = viewing_market ? SSblackmarket.markets[viewing_market] : null
data["categories"] = market ? market.categories : null
data["delivery_methods"] = list()
if(market)
for(var/delivery in market.shipping)
data["delivery_methods"] += list(list("name" = delivery, "price" = market.shipping[delivery]))
data["money"] = money
data["buying"] = buying
data["items"] = list()
data["viewing_category"] = viewing_category
data["viewing_market"] = viewing_market
if(viewing_category && market)
if(market.available_items[viewing_category])
for(var/datum/blackmarket_item/I in market.available_items[viewing_category])
data["items"] += list(list(
"id" = I.type,
"name" = I.name,
"cost" = I.price,
"amount" = I.stock,
"desc" = I.desc || I.name
))
return data
/obj/item/blackmarket_uplink/ui_static_data(mob/user)
var/list/data = list()
data["delivery_method_description"] = SSblackmarket.shipping_method_descriptions
data["ltsrbt_built"] = SSblackmarket.telepads.len
data["markets"] = list()
for(var/M in accessible_markets)
var/datum/blackmarket_market/BM = SSblackmarket.markets[M]
data["markets"] += list(list(
"id" = M,
"name" = BM.name
))
return data
/obj/item/blackmarket_uplink/ui_act(action, params)
if(..())
return
switch(action)
if("set_category")
if(isnull(params["category"]))
return
if(isnull(viewing_market))
return
if(!(params["category"] in SSblackmarket.markets[viewing_market].categories))
return
viewing_category = params["category"]
. = TRUE
if("set_market")
if(isnull(params["market"]))
return
var/market = text2path(params["market"])
if(!(market in accessible_markets))
return
viewing_market = market
var/list/categories = SSblackmarket.markets[viewing_market].categories
if(categories && categories.len)
viewing_category = categories[1]
else
viewing_category = null
. = TRUE
if("select")
if(isnull(params["item"]))
return
var/item = text2path(params["item"])
selected_item = item
buying = TRUE
. = TRUE
if("cancel")
selected_item = null
buying = FALSE
. = TRUE
if("buy")
if(isnull(params["method"]))
return
if(isnull(selected_item))
buying = FALSE
return
var/datum/blackmarket_market/market = SSblackmarket.markets[viewing_market]
market.purchase(selected_item, viewing_category, params["method"], src, usr)
buying = FALSE
selected_item = null
+2 -2
View File
@@ -171,11 +171,11 @@
var/worth = 10
worth += C.air_contents.get_moles(/datum/gas/bz)*3
worth += C.air_contents.get_moles(/datum/gas/stimulum)*25
worth += C.air_contents.get_moles(/datum/gas/hypernoblium)*1000
worth += C.air_contents.get_moles(/datum/gas/hypernoblium)*20
worth += C.air_contents.get_moles(/datum/gas/miasma)*2
worth += C.air_contents.get_moles(/datum/gas/tritium)*7
worth += C.air_contents.get_moles(/datum/gas/pluoxium)*6
worth += C.air_contents.get_moles(/datum/gas/nitryl)*30
worth += C.air_contents.get_moles(/datum/gas/nitryl)*10
return worth
+20 -8
View File
@@ -16,7 +16,7 @@
errors |= MANIFEST_ERROR_ITEM
/obj/item/paper/fluff/jobs/cargo/manifest/proc/is_approved()
return stamped && stamped.len && !is_denied()
return stamped?.len && !is_denied()
/obj/item/paper/fluff/jobs/cargo/manifest/proc/is_denied()
return stamped && ("stamp-deny" in stamped)
@@ -49,6 +49,7 @@
P.info += "<h2>[station_name()] Supply Requisition</h2>"
P.info += "<hr/>"
P.info += "Order #[id]<br/>"
P.info += "Time of Order: [STATION_TIME_TIMESTAMP("hh:mm:ss", world.time)]<br/>"
P.info += "Item: [pack.name]<br/>"
P.info += "Access Restrictions: [get_access_desc(pack.access)]<br/>"
P.info += "Requested by: [orderer]<br/>"
@@ -68,10 +69,10 @@
P.name = "shipping manifest - [packname?"#[id] ([pack.name])":"(Grouped Item Crate)"]"
P.info += "<h2>[command_name()] Shipping Manifest</h2>"
P.info += "<hr/>"
if(id && !(id == "Cargo"))
if(owner && !(owner == "Cargo"))
P.info += "Direct purchase from [owner]<br/>"
P.name += " - Purchased by [owner]"
P.info += "Order #[id]<br/>"
P.info += "Order[packname?"":"s"]: [id]<br/>"
P.info += "Destination: [station_name]<br/>"
if(packname)
P.info += "Item: [packname]<br/>"
@@ -82,8 +83,11 @@
var/obj/structure/closet/C = container
ignore_this += C.lockerelectronics
for(var/atom/movable/AM in container.contents - ignore_this)
if((P.errors & MANIFEST_ERROR_CONTENTS) && prob(50))
continue
if((P.errors & MANIFEST_ERROR_CONTENTS))
if(prob(50))
P.info += "<li>[AM.name]</li>"
else
continue
P.info += "<li>[AM.name]</li>"
P.info += "</ul>"
P.info += "<h4>Stamp below to confirm receipt of goods:</h4>"
@@ -94,7 +98,7 @@
/obj/structure/closet/crate/large,
/obj/structure/closet/secure_closet/goodies
))
if(blacklisted_error[container.type])
if(is_type_in_list(container, blacklisted_error))
P.errors &= ~MANIFEST_ERROR_ITEM
else
var/lost = max(round(container.contents.len / 10), 1)
@@ -108,15 +112,23 @@
var/obj/structure/closet/crate/C = container
C.manifest = P
C.update_icon()
else
// manifest goes in if it's not a crate
container.contents += P
return P
/datum/supply_order/proc/generate(atom/A)
var/account_holder
if(paying_account)
account_holder = paying_account.account_holder
else
account_holder = "Cargo"
var/obj/structure/closet/crate/C = pack.generate(A, paying_account)
generateManifest(C, paying_account, pack)
generateManifest(C, account_holder, pack)
return C
/datum/supply_order/proc/generateCombo(var/miscbox, var/misc_own, var/misc_contents)
/datum/supply_order/proc/generateCombo(miscbox, misc_own, misc_contents)
for (var/I in misc_contents)
new I(miscbox)
generateManifest(miscbox, misc_own, "")
+11
View File
@@ -434,6 +434,17 @@
/obj/item/stack/tile/noslip/thirty)
crate_name = "high-traction floor tiles crate"
/datum/supply_pack/misc/blackmarket_telepad
name = "Black Market LTSRBT"
desc = "Need a faster and better way of transporting your illegal goods from and to the station? Fear not, the Long-To-Short-Range-Bluespace-Transceiver (LTSRBT for short) is here to help. Contains a LTSRBT circuit, two bluespace crystals, and one ansible."
cost = 8000
contraband = TRUE
contains = list(/obj/item/circuitboard/machine/ltsrbt,
/obj/item/stack/ore/bluespace_crystal/artificial,
/obj/item/stack/ore/bluespace_crystal/artificial,
/obj/item/stock_parts/subspace/ansible)
crate_name = "crate"
//////////////////////////////////////////////////////////////////////////////
//////////////////////////////// Lewd Supplies ///////////////////////////////
//////////////////////////////////////////////////////////////////////////////
+9 -1
View File
@@ -67,7 +67,7 @@
/datum/supply_pack/vending/hydro
name = "Hydroponics Supply Crate"
desc = "Arnt you glad you dont have to do it the natural way? Contains a megaseed and nutrimax vending machine refill."
desc = "Aren't you glad you dont have to do it the natural way? Contains a megaseed and nutrimax vending machine refill."
cost = 5000
contains = list(/obj/item/vending_refill/hydroseeds,
/obj/item/vending_refill/hydronutrients)
@@ -82,6 +82,14 @@
contains = list(/obj/item/vending_refill/kink)
crate_name = "Kinkmate construction kit"
/datum/supply_pack/vending/barkbox
name = "Bark Box Supply Crate"
desc = "Running of out things to keep your pets happy?"
cost = 2000
contraband = TRUE
contains = list(/obj/item/vending_refill/barkbox)
crate_name = "bark box supply crate"
/datum/supply_pack/vending/medical
name = "Medical Vending Crate"
desc = "Contains refills for medical vending machines."
+37 -28
View File
@@ -130,26 +130,28 @@
/obj/structure/closet/supplypod/update_overlays()
. = ..()
if (style == STYLE_INVISIBLE)
if(style == STYLE_INVISIBLE)
return
if (rubble)
if(rubble)
. += rubble.getForeground(src)
if (style == STYLE_SEETHROUGH)
for (var/atom/A in contents)
if(style == STYLE_SEETHROUGH)
for(var/atom/A in contents)
var/mutable_appearance/itemIcon = new(A)
itemIcon.transform = matrix().Translate(-1 * SUPPLYPOD_X_OFFSET, 0)
. += itemIcon
for (var/t in turfs_in_cargo)//T is just a turf's type
for(var/t in turfs_in_cargo)//T is just a turf's type
var/turf/turf_type = t
var/mutable_appearance/itemIcon = mutable_appearance(initial(turf_type.icon), initial(turf_type.icon_state))
itemIcon.transform = matrix().Translate(-1 * SUPPLYPOD_X_OFFSET, 0)
. += itemIcon
return
if (opened) //We're opened means all we have to worry about is masking a decal if we have one
if (!decal) //We don't have a decal to mask
if(opened) //We're opened means all we have to worry about is masking a decal if we have one
if(!decal) //We don't have a decal to mask
return
if (!door) //We have a decal but no door, so let's just add the decal
if(!door) //We have a decal but no door, so let's just add the decal
. += decal
return
var/icon/masked_decal = new(icon, decal) //The decal we want to apply
@@ -159,23 +161,25 @@
door_masker.Blend("#000000", ICON_SUBTRACT)
masked_decal.Blend(door_masker, ICON_ADD)
. += masked_decal
else //If we're closed
if (!door) //We have no door, lets see if we have a decal. If not, theres nothing we need to do
if (decal)
. += decal
return
else if (GLOB.podstyles[style][POD_SHAPE] != POD_SHAPE_NORML) //If we're not a normal pod shape (aka, if we don't have fins), just add the door without masking
. += door
else
var/icon/masked_door = new(icon, door) //The door we want to apply
var/icon/fin_masker = new(icon, "mask_[fin_mask]") //The fin shape we want to 'cut out' of the door
fin_masker.MapColors(0,0,0,1, 0,0,0,1, 0,0,0,1, 1,1,1,0, 0,0,0,1)
fin_masker.SwapColor("#ffffffff", null)
fin_masker.Blend("#000000", ICON_SUBTRACT)
masked_door.Blend(fin_masker, ICON_ADD)
. += masked_door
if (decal)
return
//If we're closed
if(!door) //We have no door, lets see if we have a decal. If not, theres nothing we need to do
if(decal)
. += decal
return
else if (GLOB.podstyles[style][POD_SHAPE] != POD_SHAPE_NORML) //If we're not a normal pod shape (aka, if we don't have fins), just add the door without masking
. += door
else
var/icon/masked_door = new(icon, door) //The door we want to apply
var/icon/fin_masker = new(icon, "mask_[fin_mask]") //The fin shape we want to 'cut out' of the door
fin_masker.MapColors(0,0,0,1, 0,0,0,1, 0,0,0,1, 1,1,1,0, 0,0,0,1)
fin_masker.SwapColor("#ffffffff", null)
fin_masker.Blend("#000000", ICON_SUBTRACT)
masked_door.Blend(fin_masker, ICON_ADD)
. += masked_door
if(decal)
. += decal
/obj/structure/closet/supplypod/tool_interact(obj/item/W, mob/user)
if(bluespace) //We dont want to worry about interacting with bluespace pods, as they are due to delete themselves soon anyways.
@@ -192,7 +196,7 @@
/obj/structure/closet/supplypod/toggle(mob/living/user)
return
/obj/structure/closet/supplypod/open(mob/living/user, force = TRUE)
/obj/structure/closet/supplypod/open(mob/living/user, force = FALSE)
return
/obj/structure/closet/supplypod/proc/handleReturnAfterDeparting(atom/movable/holder = src)
@@ -550,9 +554,6 @@
var/obj/effect/pod_landingzone_effect/helper
var/list/smoke_effects = new /list(13)
/obj/effect/ex_act()
return
/obj/effect/pod_landingzone/Initialize(mapload, podParam, single_order = null, clientman)
. = ..()
if (ispath(podParam)) //We can pass either a path for a pod (as expressconsoles do), or a reference to an instantiated pod (as the centcom_podlauncher does)
@@ -647,4 +648,12 @@
desc = "This disk provides a firmware update to the Express Supply Console, granting the use of Nanotrasen's Bluespace Drop Pods to the supply department."
icon = 'icons/obj/module.dmi'
icon_state = "cargodisk"
// inhand_icon_state = "card-id"
w_class = WEIGHT_CLASS_SMALL
// let's not.
/obj/structure/closet/supplypod/handle_lock_addition()
return
/obj/structure/closet/supplypod/handle_lock_removal()
return
+49 -39
View File
@@ -105,8 +105,6 @@ GLOBAL_LIST_EMPTY(preferences_datums)
var/be_random_body = 0 //whether we'll have a random body every round
var/gender = MALE //gender of character (well duh)
var/age = 30 //age of character
var/language = "Random" //bonus language
var/choselanguage = "Random" //language appearance
var/underwear = "Nude" //underwear type
var/undie_color = "FFFFFF"
var/undershirt = "Nude" //undershirt type
@@ -130,6 +128,7 @@ GLOBAL_LIST_EMPTY(preferences_datums)
var/custom_speech_verb = "default" //if your say_mod is to be something other than your races
var/custom_tongue = "default" //if your tongue is to be something other than your races
var/additional_language = "None" //additional language your character has
var/modified_limbs = list() //prosthetic/amputated limbs
var/chosen_limb_id //body sprite selected to load for the users limbs, null means default, is sanitized when loaded
@@ -277,10 +276,11 @@ GLOBAL_LIST_EMPTY(preferences_datums)
dat += "<a href='?_src_=prefs;preference=tab;tab=0' [current_tab == 0 ? "class='linkOn'" : ""]>Character Settings</a>"
dat += "<a href='?_src_=prefs;preference=tab;tab=2' [current_tab == 2 ? "class='linkOn'" : ""]>Character Appearance</a>"
dat += "<a href='?_src_=prefs;preference=tab;tab=3' [current_tab == 3 ? "class='linkOn'" : ""]>Loadout</a>"
dat += "<a href='?_src_=prefs;preference=tab;tab=3' [current_tab == 3 ? "class='linkOn'" : ""]>Character Speech</a>"
dat += "<a href='?_src_=prefs;preference=tab;tab=4' [current_tab == 4 ? "class='linkOn'" : ""]>Loadout</a>"
dat += "<a href='?_src_=prefs;preference=tab;tab=1' [current_tab == 1 ? "class='linkOn'" : ""]>Game Preferences</a>"
dat += "<a href='?_src_=prefs;preference=tab;tab=4' [current_tab == 4 ? "class='linkOn'" : ""]>Content Preferences</a>"
dat += "<a href='?_src_=prefs;preference=tab;tab=5' [current_tab == 5 ? "class='linkOn'" : ""]>Keybindings</a>"
dat += "<a href='?_src_=prefs;preference=tab;tab=5' [current_tab == 5 ? "class='linkOn'" : ""]>Content Preferences</a>"
dat += "<a href='?_src_=prefs;preference=tab;tab=6' [current_tab == 6 ? "class='linkOn'" : ""]>Keybindings</a>"
if(!path)
dat += "<div class='notice'>Please create an account to save your preferences</div>"
@@ -328,7 +328,6 @@ GLOBAL_LIST_EMPTY(preferences_datums)
dat += "<b>Gender:</b> <a href='?_src_=prefs;preference=gender;task=input'>[gender == MALE ? "Male" : (gender == FEMALE ? "Female" : (gender == PLURAL ? "Non-binary" : "Object"))]</a><BR>"
dat += "<b>Age:</b> <a style='display:block;width:30px' href='?_src_=prefs;preference=age;task=input'>[age]</a><BR>"
dat += "<b>Language:</b> <a href='?_src_=prefs;preference=language;task=input'>[choselanguage]</a><BR>"
dat += "<b>Special Names:</b><BR>"
var/old_group
@@ -485,13 +484,6 @@ GLOBAL_LIST_EMPTY(preferences_datums)
else if(use_skintones || mutant_colors)
dat += "</td>"
dat += APPEARANCE_CATEGORY_COLUMN
dat += "<h2>Speech preferences</h2>"
dat += "<b>Custom Speech Verb:</b><BR>"
dat += "</b><a style='display:block;width:100px' href='?_src_=prefs;preference=speech_verb;task=input'>[custom_speech_verb]</a><BR>"
dat += "<b>Custom Tongue:</b><BR>"
dat += "</b><a style='display:block;width:100px' href='?_src_=prefs;preference=tongue;task=input'>[custom_tongue]</a><BR>"
if(HAIR in pref_species.species_traits)
dat += APPEARANCE_CATEGORY_COLUMN
@@ -678,6 +670,36 @@ GLOBAL_LIST_EMPTY(preferences_datums)
dat += "</td>"
dat += "</tr></table>"
if(3)
if(path)
var/savefile/S = new /savefile(path)
if(S)
dat += "<center>"
var/name
var/unspaced_slots = 0
for(var/i=1, i<=max_save_slots, i++)
unspaced_slots++
if(unspaced_slots > 4)
dat += "<br>"
unspaced_slots = 0
S.cd = "/character[i]"
S["real_name"] >> name
if(!name)
name = "Character[i]"
dat += "<a style='white-space:nowrap;' href='?_src_=prefs;preference=changeslot;num=[i];' [i == default_slot ? "class='linkOn'" : ""]>[name]</a> "
dat += "</center>"
dat += "<table><tr><td width='340px' height='300px' valign='top'>"
dat += "<h2>Speech preferences</h2>"
dat += "<b>Custom Speech Verb:</b><BR>"
dat += "</b><a style='display:block;width:100px' href='?_src_=prefs;preference=speech_verb;task=input'>[custom_speech_verb]</a><BR>"
dat += "<b>Custom Tongue:</b><BR>"
dat += "</b><a style='display:block;width:100px' href='?_src_=prefs;preference=tongue;task=input'>[custom_tongue]</a><BR>"
dat += "<b>Additional Language</b><BR>"
dat += "</b><a style='display:block;width:100px' href='?_src_=prefs;preference=language;task=input'>[additional_language]</a><BR>"
dat += "</td>"
dat += "</tr></table>"
if (1) // Game Preferences
dat += "<table><tr><td width='340px' height='300px' valign='top'>"
dat += "<h2>General Settings</h2>"
@@ -841,12 +863,12 @@ GLOBAL_LIST_EMPTY(preferences_datums)
if(days_remaining)
dat += "<b>Be [capitalize(i)]:</b> <font color=red> \[IN [days_remaining] DAYS]</font><br>"
else
dat += "<b>Be [capitalize(i)]:</b> <a href='?_src_=prefs;preference=be_special;be_special_type=[i]'>[(i in be_special) ? "Enabled" : "Disabled"]</a><br>"
dat += "<b>Be [i == ROLE_SYNDICATE ? "Antag": capitalize(i)]:</b> <a href='?_src_=prefs;preference=be_special;be_special_type=[i]'>[(i in be_special) ? "Enabled" : "Disabled"]</a><br>"
dat += "<b>Midround Antagonist:</b> <a href='?_src_=prefs;preference=allow_midround_antag'>[(toggles & MIDROUND_ANTAG) ? "Enabled" : "Disabled"]</a><br>"
dat += "<br>"
if(3)
if(4)
//calculate your gear points from the chosen item
gear_points = CONFIG_GET(number/initial_gear_points)
var/list/chosen_gear = loadout_data["SAVE_[loadout_slot]"]
@@ -965,7 +987,7 @@ GLOBAL_LIST_EMPTY(preferences_datums)
dat += "</td><td><font size=2><i>[loadout_item ? (loadout_item[LOADOUT_CUSTOM_DESCRIPTION] ? loadout_item[LOADOUT_CUSTOM_DESCRIPTION] : gear.description) : gear.description] Progress: [min(progress_made, unlockable.progress_required)]/[unlockable.progress_required]</i></font></td></tr>"
dat += "</table>"
if(4) // Content preferences
if(5) // Content preferences
dat += "<table><tr><td width='340px' height='300px' valign='top'>"
dat += "<h2>Fetish content prefs</h2>"
dat += "<b>Arousal:</b><a href='?_src_=prefs;preference=arousable'>[arousable == TRUE ? "Enabled" : "Disabled"]</a><BR>"
@@ -989,7 +1011,7 @@ GLOBAL_LIST_EMPTY(preferences_datums)
dat += "<b>Automatic Wagging:</b> <a href='?_src_=prefs;preference=auto_wag'>[(cit_toggles & NO_AUTO_WAG) ? "Disabled" : "Enabled"]</a><br>"
dat += "</tr></table>"
dat += "<br>"
if(5) // Custom keybindings
if(6) // Custom keybindings
dat += "<b>Keybindings:</b> <a href='?_src_=prefs;preference=hotkeys'>[(hotkeys) ? "Hotkeys" : "Input"]</a><br>"
dat += "Keybindings mode controls how the game behaves with tab and map/input focus.<br>If it is on <b>Hotkeys</b>, the game will always attempt to force you to map focus, meaning keypresses are sent \
directly to the map instead of the input. You will still be able to use the command bar, but you need to tab to do it every time you click on the game map.<br>\
@@ -2339,28 +2361,6 @@ GLOBAL_LIST_EMPTY(preferences_datums)
features["body_model"] = chosengender
gender = chosengender
if("language")
choselanguage = input(user, "Select a language.", "Language", language) as null|anything in list("Beachtongue","Draconic","Dwarven",
"Chimpanzee","Space Sign Language","Random")
if(!choselanguage)
return
switch(choselanguage)
if("Rachidian")
language = /datum/language/arachnid
if("Beachtongue")
language = /datum/language/beachbum
if("Draconic")
language = /datum/language/draconic
if("Dwarven")
language = /datum/language/dwarf
if("Chimpanzee")
language = /datum/language/monkey
if("Space Sign Language")
language = /datum/language/signlanguage
if("Random")
language = pick(list("Rachidian", "Beachtongue","Draconic","Dwarven",
"Chimpanzee","Space Sign Language"))
if("body_size")
var/new_body_size = input(user, "Choose your desired sprite size: (90-125%)\nWarning: This may make your character look distorted. Additionally, any size under 100% takes a 10% maximum health penalty", "Character Preference", features["body_size"]*100) as num|null
if(new_body_size)
@@ -2370,11 +2370,17 @@ GLOBAL_LIST_EMPTY(preferences_datums)
var/selected_custom_tongue = input(user, "Choose your desired tongue (none means your species tongue)", "Character Preference") as null|anything in GLOB.roundstart_tongues
if(selected_custom_tongue)
custom_tongue = selected_custom_tongue
if("speech_verb")
var/selected_custom_speech_verb = input(user, "Choose your desired speech verb (none means your species speech verb)", "Character Preference") as null|anything in GLOB.speech_verbs
if(selected_custom_speech_verb)
custom_speech_verb = selected_custom_speech_verb
if("language")
var/selected_language = input(user, "Choose your desired additional language", "Character Preference") as null|anything in GLOB.roundstart_languages
if(selected_language)
additional_language = selected_language
if("bodysprite")
var/selected_body_sprite = input(user, "Choose your desired body sprite", "Character Preference") as null|anything in pref_species.allowed_limb_ids
if(selected_body_sprite)
@@ -2909,6 +2915,10 @@ GLOBAL_LIST_EMPTY(preferences_datums)
new_custom_tongue.Insert(character)
if(custom_speech_verb != "default")
character.dna.species.say_mod = custom_speech_verb
if(additional_language && additional_language != "None")
var/language_entry = GLOB.roundstart_languages[additional_language]
if(language_entry)
character.grant_language(language_entry, TRUE, TRUE)
//limb stuff, only done when initially spawning in
if(initial_spawn)
+3 -4
View File
@@ -604,8 +604,6 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
S["body_model"] >> features["body_model"]
S["body_size"] >> features["body_size"]
S["age"] >> age
S["language"] >> language
S["choselanguage"] >> choselanguage
S["hair_color"] >> hair_color
S["facial_hair_color"] >> facial_hair_color
S["eye_type"] >> eye_type
@@ -626,6 +624,7 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
S["uplink_loc"] >> uplink_spawn_loc
S["custom_speech_verb"] >> custom_speech_verb
S["custom_tongue"] >> custom_tongue
S["additional_language"] >> additional_language
S["feature_mcolor"] >> features["mcolor"]
S["feature_lizard_tail"] >> features["tail_lizard"]
S["feature_lizard_snout"] >> features["snout"]
@@ -881,6 +880,7 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
custom_speech_verb = sanitize_inlist(custom_speech_verb, GLOB.speech_verbs, "default")
custom_tongue = sanitize_inlist(custom_tongue, GLOB.roundstart_tongues, "default")
additional_language = sanitize_inlist(additional_language, GLOB.roundstart_languages, "None")
security_records = copytext(security_records, 1, MAX_FLAVOR_LEN)
medical_records = copytext(medical_records, 1, MAX_FLAVOR_LEN)
@@ -964,8 +964,6 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
WRITE_FILE(S["body_model"] , features["body_model"])
WRITE_FILE(S["body_size"] , features["body_size"])
WRITE_FILE(S["age"] , age)
WRITE_FILE(S["language"] , language)
WRITE_FILE(S["choselanguage"] , choselanguage)
WRITE_FILE(S["hair_color"] , hair_color)
WRITE_FILE(S["facial_hair_color"] , facial_hair_color)
WRITE_FILE(S["eye_type"] , eye_type)
@@ -987,6 +985,7 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
WRITE_FILE(S["species"] , pref_species.id)
WRITE_FILE(S["custom_speech_verb"] , custom_speech_verb)
WRITE_FILE(S["custom_tongue"] , custom_tongue)
WRITE_FILE(S["additional_language"] , additional_language)
// records
WRITE_FILE(S["security_records"] , security_records)
+12
View File
@@ -190,6 +190,12 @@
tagname = stripped_input(user, "Would you like to change the name on the tag?", "Name your new pet", "Spot", MAX_NAME_LEN)
name = "[initial(name)] - [tagname]"
/obj/item/clothing/neck/petcollar/ribbon
name = "ribbon pet collar"
icon_state = "ribboncollar"
poly_states = 2
poly_colors = list("#454545", "#292929")
/obj/item/clothing/neck/petcollar/leather
name = "leather pet collar"
icon_state = "leathercollar"
@@ -225,6 +231,12 @@
return
..()
/obj/item/clothing/neck/petcollar/locked/ribbon
name = "ribbon pet collar"
icon_state = "ribboncollar"
poly_states = 2
poly_colors = list("#454545", "#292929")
/obj/item/clothing/neck/petcollar/locked/leather
name = "leather pet collar"
icon_state = "leathercollar"
+1
View File
@@ -94,6 +94,7 @@
icon_state = "sec_dep_jacket"
item_state = "sec_dep_jacket"
armor = list("melee" = 25, "bullet" = 15, "laser" = 30, "energy" = 10, "bomb" = 25, "bio" = 0, "rad" = 0, "fire" = 0, "acid" = 45)
allowed = list(/obj/item/gun/energy, /obj/item/melee/baton, /obj/item/restraints/handcuffs, /obj/item/tank/internals/emergency_oxygen, /obj/item/tank/internals/plasmaman)
/obj/item/clothing/suit/toggle/labcoat/depjacket/sup
name = "supply jacket"
@@ -567,6 +567,26 @@
attack_verb = list("warned", "cautioned", "smashed")
armor = list("melee" = 5, "bullet" = 0, "laser" = 0,"energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 0, "acid" = 0)
/obj/item/clothing/suit/petharness
name = "pet harness"
desc = "For your pet! Or not! Has a little clip on the back."
icon_state = "petharness"
item_state = "petharness"
body_parts_covered = NONE
mutantrace_variation = STYLE_DIGITIGRADE|STYLE_NO_ANTHRO_ICON
allowed = /obj/item/toy/fluff
/obj/item/clothing/suit/petharness/mesh
name = "mesh pet harness"
desc = "For your pet! Or not! Has some mesh to cover up your more sensitive bits and a little clip on the back."
icon_state = "petharness_mesh"
item_state = "petharness_mesh"
body_parts_covered = CHEST
/obj/item/clothing/suit/petharness/ComponentInitialize()
. = ..()
AddElement(/datum/element/polychromic, list("#0056D9", "#959595"), 2, _flags = POLYCHROMIC_ACTION)
// WINTER COATS
/obj/item/clothing/suit/hooded/wintercoat
+4
View File
@@ -4,6 +4,8 @@
actions_types = list(/datum/action/item_action/toggle_hood)
var/obj/item/clothing/head/hooded/hood
var/hoodtype = /obj/item/clothing/head/hooded/winterhood //so the chaplain hoodie or other hoodies can override this
///Alternative mode for hiding the hood, instead of storing the hood in the suit it qdels it, useful for when you deal with hooded suit with storage.
var/alternative_mode = FALSE
/obj/item/clothing/suit/hooded/Initialize()
. = ..()
@@ -43,6 +45,8 @@
H.transferItemToLoc(hood, src, TRUE)
H.update_inv_wear_suit()
else
if(alternative_mode)
QDEL_NULL(hood)
hood.forceMove(src)
update_icon()
+6
View File
@@ -59,6 +59,12 @@
has_sensor = TRUE
armor = list("melee" = 0, "bullet" = 0, "laser" = 0,"energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 0, "acid" = 0, "wound" = 5)
/obj/item/clothing/under/syndicate/cosmetic/skirt
name = "tactitool skirtleneck"
icon_state = "tactifool_skirt"
fitted = FEMALE_UNIFORM_TOP
mutantrace_variation = STYLE_DIGITIGRADE|STYLE_NO_ANTHRO_ICON
/obj/item/clothing/under/syndicate/sniper
name = "Tactical turtleneck suit"
desc = "A double seamed tactical turtleneck disguised as a civilian grade silk suit. Intended for the most formal operator. The collar is really sharp."
+1 -1
View File
@@ -3,7 +3,7 @@
typepath = /datum/round_event/ghost_role/abductor
weight = 10
max_occurrences = 1
min_players = 20
min_players = 30
gamemode_blacklist = list("nuclear","wizard","revolution","dynamic")
/datum/round_event/ghost_role/abductor
+19 -3
View File
@@ -13,11 +13,27 @@
var/power = 2000
/datum/round_event/supermatter_surge/setup()
power = rand(200,4000)
if(prob(70))
power = rand(200,100000)
else
power = rand(200,200000)
/datum/round_event/supermatter_surge/announce()
if(power > 800 || prob(round(power/8)))
priority_announce("Class [round(power/500) + 1] supermatter surge detected. Intervention may be required.", "Anomaly Alert")
var/severity = ""
switch(power)
if(-INFINITY to 100000)
var/low_threat_perc = 100-round(100*((power-200)/(100000-200)))
if(prob(low_threat_perc))
if(prob(low_threat_perc))
severity = "low; the supermatter should return to normal operation shortly."
else
severity = "medium; the supermatter should return to normal operation, but check NT CIMS to ensure this."
else
severity = "high; if the supermatter's cooling is not fortified, coolant may need to be added."
if(100000 to INFINITY)
severity = "extreme; emergency action is likely to be required even if coolant loop is fine."
if(power > 20000 || prob(round(power/200)))
priority_announce("Supermatter surge detected. Estimated severity is [severity]", "Anomaly Alert")
/datum/round_event/supermatter_surge/start()
GLOB.main_supermatter_engine.matter_power += power
+6 -6
View File
@@ -17,7 +17,7 @@
announceWhen = rand(4, 60)
supernova = new
SSsun.suns += supernova
if(prob(50))
if(prob(20))
power = rand(5,100) / 100
else
power = rand(5,5000) / 100
@@ -33,9 +33,9 @@
/datum/round_event/supernova/start()
supernova.power_mod = 0.00000002 * power
supernova.power_mod = 0.001 * power
var/explosion_size = rand(1000000000, 999999999)
var/turf/epicenter = get_turf_in_angle(supernova.azimuth, SSmapping.get_station_center(), world.maxx / 2)
var/turf/epicenter = get_turf_in_angle(supernova.azimuth, SSmapping.get_station_center(), round(world.maxx * 0.45))
for(var/array in GLOB.doppler_arrays)
var/obj/machinery/doppler_array/A = array
A.sense_explosion(epicenter, explosion_size/2, explosion_size, 0, 107000000 / power, explosion_size/2, explosion_size, 0)
@@ -46,13 +46,13 @@
sucker_light.give_home_power()
/datum/round_event/supernova/tick()
var/midpoint = (endWhen-startWhen)/2
var/midpoint = round((endWhen-startWhen)/2)
switch(activeFor)
if(startWhen to midpoint)
supernova.power_mod = min(supernova.power_mod*1.2, power)
if(endWhen-10 to endWhen)
supernova.power_mod /= 4
if(prob(round(supernova.power_mod / 2)) && storm_count < 3 && !SSweather.get_weather_by_type(/datum/weather/rad_storm))
if(prob(round(supernova.power_mod / 2)) && storm_count < 4 && !SSweather.get_weather_by_type(/datum/weather/rad_storm))
SSweather.run_weather(/datum/weather/rad_storm/supernova)
storm_count++
@@ -62,6 +62,6 @@
/datum/weather/rad_storm/supernova
weather_duration_lower = 50
weather_duration_lower = 100
weather_duration_upper = 100
telegraph_duration = 100
radiation_intensity = 50
+1 -1
View File
@@ -200,7 +200,7 @@
return FALSE
/mob/living/carbon/human/dummy/travelling_trader/animal_hunter/give_reward(mob/giver) //the reward is actually given in a jar, because releasing it onto the station might be a bad idea
var/obj/item/pet_carrier/bluespace/jar = new(get_turf(src))
var/obj/item/pet_carrier/bluespace/single_use/jar = new(get_turf(src))
var/chosen_animal = pickweight(possible_rewards)
var/mob/living/new_animal = new chosen_animal(jar)
if(giver && giver.tag)
+169
View File
@@ -0,0 +1,169 @@
/obj/effect/domain_expansion
anchored = TRUE
name = "infinite void"
desc = "Once inside, the user's cursed techniques are improved and cannot be avoided."
layer = FLY_LAYER
pixel_x = -64
pixel_y = -64
mouse_opacity = MOUSE_OPACITY_TRANSPARENT
var/list/immune = list() // the one who creates the domain_expansion is immune, which includes wizards and the dead slime you murdered to make this chronofield
var/turf/target
var/freezerange = 2
var/duration = 140
var/datum/proximity_monitor/advanced/domain_expansion/chronofield
alpha = 125
var/check_anti_magic = FALSE
var/check_holy = FALSE
/obj/effect/domain_expansion/Initialize(mapload, radius, time, list/immune_atoms, start = TRUE) //Immune atoms assoc list atom = TRUE
. = ..()
if(!isnull(time))
duration = time
if(!isnull(radius))
freezerange = radius
for(var/A in immune_atoms)
immune[A] = TRUE
for(var/mob/living/L in GLOB.player_list)
if(locate(/obj/effect/proc_holder/spell/aoe_turf/domain_expansion) in L.mind.spell_list) //People who can stop time are immune to its effects
immune[L] = TRUE
for(var/mob/living/simple_animal/hostile/guardian/G in GLOB.parasites)
if(G.summoner && locate(/obj/effect/proc_holder/spell/aoe_turf/domain_expansion) in G.summoner.mind.spell_list) //It would only make sense that a person's stand would also be immune.
immune[G] = TRUE
if(start)
INVOKE_ASYNC(src, .proc/domain_expansion)
/obj/effect/domain_expansion/Destroy()
qdel(chronofield)
return ..()
/obj/effect/domain_expansion/proc/domain_expansion()
target = get_turf(src)
chronofield = make_field(/datum/proximity_monitor/advanced/domain_expansion, list("current_range" = freezerange, "host" = src, "immune" = immune, "check_anti_magic" = check_anti_magic, "check_holy" = check_holy))
QDEL_IN(src, duration)
/obj/effect/domain_expansion/magic
check_anti_magic = TRUE
/datum/proximity_monitor/advanced/domain_expansion
name = "chronofield"
setup_field_turfs = TRUE
field_shape = FIELD_SHAPE_RADIUS_SQUARE
requires_processing = TRUE
var/list/immune = list()
var/list/frozen_things = list()
var/list/frozen_mobs = list() //cached separately for processing
var/list/frozen_structures = list() //Also machinery, and only frozen aestethically
var/list/frozen_turfs = list() //Only aesthetically
var/check_anti_magic = FALSE
var/check_holy = FALSE
var/static/list/global_frozen_atoms = list()
/datum/proximity_monitor/advanced/domain_expansion/Destroy()
unfreeze_all()
return ..()
/datum/proximity_monitor/advanced/domain_expansion/field_turf_crossed(atom/movable/AM)
freeze_atom(AM)
/datum/proximity_monitor/advanced/domain_expansion/proc/freeze_atom(atom/movable/A)
if(immune[A] || global_frozen_atoms[A] || !istype(A))
return FALSE
if(ismob(A))
var/mob/M = A
if(M.anti_magic_check(check_anti_magic, check_holy))
immune[A] = TRUE
return
var/frozen = TRUE
if(isliving(A))
freeze_mob(A)
else if((ismachinery(A) && !istype(A, /obj/machinery/light)) || isstructure(A)) //Special exception for light fixtures since recoloring causes them to change light
freeze_structure(A)
else
frozen = FALSE
if(A.throwing)
freeze_throwing(A)
frozen = TRUE
if(!frozen)
return
frozen_things[A] = A.move_resist
A.move_resist = INFINITY
global_frozen_atoms[A] = src
into_the_negative_zone(A)
RegisterSignal(A, COMSIG_MOVABLE_PRE_MOVE, .proc/unfreeze_atom)
RegisterSignal(A, COMSIG_ITEM_PICKUP, .proc/unfreeze_atom)
return TRUE
/datum/proximity_monitor/advanced/domain_expansion/proc/unfreeze_all()
for(var/i in frozen_things)
unfreeze_atom(i)
for(var/T in frozen_turfs)
unfreeze_turf(T)
/datum/proximity_monitor/advanced/domain_expansion/proc/unfreeze_atom(atom/movable/A)
SIGNAL_HANDLER
if(A.throwing)
unfreeze_throwing(A)
if(isliving(A))
unfreeze_mob(A)
UnregisterSignal(A, COMSIG_MOVABLE_PRE_MOVE)
UnregisterSignal(A, COMSIG_ITEM_PICKUP)
escape_the_negative_zone(A)
A.move_resist = frozen_things[A]
frozen_things -= A
global_frozen_atoms -= A
/datum/proximity_monitor/advanced/domain_expansion/proc/freeze_throwing(atom/movable/AM)
var/datum/thrownthing/T = AM.throwing
T.paused = TRUE
/datum/proximity_monitor/advanced/domain_expansion/proc/unfreeze_throwing(atom/movable/AM)
var/datum/thrownthing/T = AM.throwing
if(T)
T.paused = FALSE
/datum/proximity_monitor/advanced/domain_expansion/proc/freeze_turf(turf/T)
into_the_negative_zone(T)
frozen_turfs += T
/datum/proximity_monitor/advanced/domain_expansion/proc/unfreeze_turf(turf/T)
escape_the_negative_zone(T)
/datum/proximity_monitor/advanced/domain_expansion/proc/freeze_structure(obj/O)
into_the_negative_zone(O)
frozen_structures += O
/datum/proximity_monitor/advanced/domain_expansion/proc/unfreeze_structure(obj/O)
escape_the_negative_zone(O)
/datum/proximity_monitor/advanced/domain_expansion/process()
for(var/i in frozen_mobs)
var/mob/living/m = i
m.apply_status_effect(/datum/status_effect/eldritch/void)
/datum/proximity_monitor/advanced/domain_expansion/setup_field_turf(turf/T)
for(var/i in T.contents)
freeze_atom(i)
freeze_turf(T)
return ..()
/datum/proximity_monitor/advanced/domain_expansion/proc/freeze_mob(mob/living/L)
frozen_mobs += L
L.add_movespeed_modifier(/datum/movespeed_modifier/status_effect/domain)
/datum/proximity_monitor/advanced/domain_expansion/proc/unfreeze_mob(mob/living/L)
L.remove_movespeed_modifier(/datum/movespeed_modifier/status_effect/domain)
frozen_mobs -= L
//you don't look quite right, is something the matter?
/datum/proximity_monitor/advanced/domain_expansion/proc/into_the_negative_zone(atom/A)
A.add_atom_colour(list(-0.6,0,0,0, 0,-0.6,0,0, 0,0,-1,0, 0,0,0,1, 0.5,0.5,1,0), TEMPORARY_COLOUR_PRIORITY)
//let's put some colour back into your cheeks
/datum/proximity_monitor/advanced/domain_expansion/proc/escape_the_negative_zone(atom/A)
A.remove_atom_colour(TEMPORARY_COLOUR_PRIORITY)
@@ -466,6 +466,17 @@
foodtype = GRAIN | SUGAR
dunkable = TRUE
/obj/item/reagent_containers/food/snacks/dogtreat
name = "dog treat"
desc = "It's a scooby-snack. Right?"
icon_state = "dogtreat"
bitesize = 1
bonus_reagents = list(/datum/reagent/consumable/nutriment = 1)
list_reagents = list(/datum/reagent/consumable/nutriment = 1)
filling_color = "#635444"
tastes = list("meat" = 1, "dough" = 1)
foodtype = GRAIN | MEAT
/obj/item/reagent_containers/food/snacks/donkpocket
name = "\improper Donk-pocket"
desc = "The food of choice for the seasoned traitor."
@@ -214,6 +214,17 @@
result = /obj/item/reagent_containers/food/snacks/cracker
subcategory = CAT_PASTRY
/datum/crafting_recipe/food/dogtreat
time = 15
name = "Dog Treat"
reqs = list(
/datum/reagent/consumable/sodiumchloride = 1,
/obj/item/reagent_containers/food/snacks/meat/cutlet = 1,
/obj/item/reagent_containers/food/snacks/pastrybase = 1,
)
result = /obj/item/reagent_containers/food/snacks/dogtreat
subcategory = CAT_PASTRY
/datum/crafting_recipe/food/fortunecookie
time = 15
name = "Fortune cookie"
+1
View File
@@ -9,6 +9,7 @@
flags = NO_STUTTER | LANGUAGE_HIDE_ICON_IF_NOT_UNDERSTOOD
icon_state = "arachnid"
chooseable_roundstart = TRUE
/datum/language/arachnid/scramble(input)
. = prob(65) ? "<i>wiff</i>" : "<i>thump</i>"
+1
View File
@@ -18,3 +18,4 @@
)
icon_state = "lizard"
default_priority = 90
chooseable_roundstart = TRUE
+1
View File
@@ -11,3 +11,4 @@
default_priority = 90
icon_state = "dwarf"
chooseable_roundstart = TRUE
+2
View File
@@ -22,6 +22,8 @@
var/list/scramble_cache = list()
var/default_priority = 0 // the language that an atom knows with the highest "default_priority" is selected by default.
var/chooseable_roundstart = FALSE // can we pick it from the customization menu as an additional language?
// if you are seeing someone speak popcorn language, then something is wrong.
var/icon = 'icons/misc/language.dmi'
var/icon_state = "popcorn"
+1
View File
@@ -10,3 +10,4 @@
default_priority = 80
icon_state = "animal"
chooseable_roundstart = TRUE
+1
View File
@@ -9,3 +9,4 @@
sentence_chance = 0
default_priority = 80
syllables = list("poof", "pff", "pFfF", "piff", "puff", "pooof", "pfffff", "piffpiff", "puffpuff", "poofpoof", "pifpafpofpuf")
chooseable_roundstart = TRUE
+1
View File
@@ -10,3 +10,4 @@
default_priority = 70
icon_state = "slime"
chooseable_roundstart = TRUE
+1
View File
@@ -16,3 +16,4 @@
)
icon_state = "plant"
default_priority = 90
chooseable_roundstart = TRUE
+1
View File
@@ -12,3 +12,4 @@
)
icon_state = "volt"
default_priority = 90
chooseable_roundstart = TRUE
@@ -928,7 +928,10 @@
ghost.ManualFollow(src)
/obj/item/melee/ghost_sword/process()
ghost_check()
force = 0
var/ghost_counter = ghost_check()
force = clamp((ghost_counter * 4), 0, 75)
/obj/item/melee/ghost_sword/proc/recursive_orbit_collect(atom/A, list/L)
for(var/i in A.orbiters?.orbiters)
@@ -1282,8 +1285,8 @@
if(isliving(target) && chaser_timer <= world.time) //living and chasers off cooldown? fire one!
chaser_timer = world.time + chaser_cooldown
var/obj/effect/temp_visual/hierophant/chaser/C = new(get_turf(user), user, target, chaser_speed, friendly_fire_check)
C.damage = 30
C.monster_damage_boost = FALSE
C.damage = 15
C.monster_damage_boost = TRUE
log_combat(user, target, "fired a chaser at", src)
else
INVOKE_ASYNC(src, .proc/cardinal_blasts, T, user) //otherwise, just do cardinal blast
@@ -1399,10 +1402,10 @@
new /obj/effect/temp_visual/hierophant/telegraph/teleport(source, user)
for(var/t in RANGE_TURFS(1, T))
var/obj/effect/temp_visual/hierophant/blast/B = new /obj/effect/temp_visual/hierophant/blast(t, user, TRUE) //blasts produced will not hurt allies
B.damage = 30
B.damage = 15
for(var/t in RANGE_TURFS(1, source))
var/obj/effect/temp_visual/hierophant/blast/B = new /obj/effect/temp_visual/hierophant/blast(t, user, TRUE) //but absolutely will hurt enemies
B.damage = 30
B.damage = 15
for(var/mob/living/L in range(1, source))
INVOKE_ASYNC(src, .proc/teleport_mob, source, L, T, user) //regardless, take all mobs near us along
sleep(6) //at this point the blasts detonate
@@ -1463,8 +1466,8 @@
if(!J)
return
var/obj/effect/temp_visual/hierophant/blast/B = new(J, user, friendly_fire_check)
B.damage = 30
B.monster_damage_boost = FALSE
B.damage = 15
B.monster_damage_boost = TRUE
previousturf = J
J = get_step(previousturf, dir)
@@ -1476,7 +1479,7 @@
sleep(2)
for(var/t in RANGE_TURFS(1, T))
var/obj/effect/temp_visual/hierophant/blast/B = new(t, user, friendly_fire_check)
B.damage = 15 //keeps monster damage boost due to lower damage
B.damage = 15 //keeps monster damage boost due to lower damage (now added to all damage due to reduction to 15, 30dmg 50AP isn't cool)
//Just some minor stuff
+2 -2
View File
@@ -1237,7 +1237,7 @@
if(user.incapacitated() || !user.Adjacent(src))
return FALSE
if(W && user.a_intent == INTENT_HELP && W.can_give())
user.give()
user.give(src)
return TRUE
/mob/living/carbon/verb/give_verb()
@@ -1253,4 +1253,4 @@
var/obj/item/I = usr.get_active_held_item()
var/mob/living/carbon/C = usr
if(I.can_give())
C.give()
C.give(src)
@@ -41,10 +41,10 @@
. += "[t_He] [t_is] wearing [w_uniform.get_examine_string(user)][accessory_msg]."
//head
if(head)
if(head && !(head.item_flags & EXAMINE_SKIP))
. += "[t_He] [t_is] wearing [head.get_examine_string(user)] on [t_his] head."
//suit/armor
if(wear_suit)
if(wear_suit && !(wear_suit.item_flags & EXAMINE_SKIP))
. += "[t_He] [t_is] wearing [wear_suit.get_examine_string(user)]."
//suit/armor storage
if(s_store && !(SLOT_S_STORE in obscured))
@@ -115,13 +115,13 @@
. = ..()
if(!.)
return
if(HAS_TRAIT(src, TRAIT_NOGUNS))
to_chat(src, "<span class='warning'>You can't bring yourself to use a ranged weapon!</span>")
return FALSE
if(G.trigger_guard == TRIGGER_GUARD_NORMAL)
if(HAS_TRAIT(src, TRAIT_CHUNKYFINGERS))
to_chat(src, "<span class='warning'>Your meaty finger is much too large for the trigger guard!</span>")
return FALSE
if(HAS_TRAIT(src, TRAIT_NOGUNS))
to_chat(src, "<span class='warning'>Your fingers don't fit in the trigger guard!</span>")
return FALSE
/mob/living/carbon/human/proc/get_bank_account()
RETURN_TYPE(/datum/bank_account)
@@ -37,11 +37,11 @@
to_chat(owner, "There's something stuck to your hand, stopping you from transforming!")
return
if(IsAvailable())
transforming = TRUE
UpdateButtonIcon()
var/mutcolor = owner.get_ability_property(INNATE_ABILITY_SLIME_BLOBFORM, PROPERTY_BLOBFORM_COLOR) || ("#" + H.dna.features["mcolor"])
if(!is_puddle)
if(CHECK_MOBILITY(H, MOBILITY_USE)) //if we can use items, we can turn into a puddle
transforming = TRUE
is_puddle = TRUE //so we know which transformation to use when its used
ADD_TRAIT(H, TRAIT_HUMAN_NO_RENDER, SLIMEPUDDLE_TRAIT)
owner.cut_overlays() //we dont show our normal sprite, we show a puddle sprite
@@ -625,7 +625,7 @@
say_mod = "clicks"
limbs_id = "clockgolem"
info_text = "<span class='bold alloy'>As a </span><span class='bold brass'>Clockwork Golem</span><span class='bold alloy'>, you are faster than other types of golems, and are capable of using guns. On death, you will break down into scrap.</span>"
species_traits = list(NOBLOOD,NO_UNDERWEAR,NOEYES,NOGENITALS,NOAROUSAL)
species_traits = list(NOBLOOD,NO_UNDERWEAR,NOEYES,NOGENITALS,NOAROUSAL,ROBOTIC_LIMBS)
inherent_biotypes = MOB_ROBOTIC|MOB_HUMANOID
inherent_traits = list(TRAIT_RESISTHEAT,TRAIT_NOBREATH,TRAIT_RESISTCOLD,TRAIT_RESISTHIGHPRESSURE,TRAIT_RESISTLOWPRESSURE,TRAIT_NOFIRE,TRAIT_RADIMMUNE,TRAIT_PIERCEIMMUNE,TRAIT_NODISMEMBER)
inherent_biotypes = MOB_ROBOTIC|MOB_HUMANOID
@@ -667,6 +667,10 @@
/datum/species/golem/clockwork/no_scrap //These golems are created through the herald's beacon and leave normal corpses on death.
id = "clockwork golem servant"
species_traits = list(NOBLOOD,NO_UNDERWEAR,NOEYES,NOSTOMACH,NOLIVER,NOGENITALS,NOAROUSAL,NOTRANSSTING,ROBOTIC_LIMBS,HAS_BONE)
inherent_biotypes = MOB_ROBOTIC|MOB_HUMANOID
inherent_traits = list(TRAIT_RESISTHEAT,TRAIT_NOBREATH,TRAIT_RESISTCOLD,TRAIT_NOHUNGER,TRAIT_RESISTHIGHPRESSURE,TRAIT_RESISTLOWPRESSURE,TRAIT_NOFIRE,TRAIT_RADIMMUNE,TRAIT_PIERCEIMMUNE,TRAIT_NODISMEMBER)
inherent_biotypes = MOB_ROBOTIC|MOB_HUMANOID
armor = 15 //Balance reasons make this armor weak
no_equip = list()
nojumpsuit = FALSE
@@ -675,6 +679,8 @@
dangerous_existence = TRUE
random_eligible = FALSE
info_text = "<span class='bold alloy'>As a </span><span class='bold brass'>Clockwork Golem Servant</span><span class='bold alloy'>, you are faster than other types of golems, and are capable of using guns.</span>" //warcult golems leave a corpse
gib_types = list(/obj/effect/gibspawner/ipc, /obj/effect/gibspawner/ipc/bodypartless)
/datum/species/golem/cloth
name = "Cloth Golem"
@@ -3,7 +3,7 @@
id = SPECIES_VAMPIRE
default_color = "FFFFFF"
species_traits = list(EYECOLOR,HAIR,FACEHAIR,LIPS,DRINKSBLOOD,HAS_FLESH,HAS_BONE)
inherent_traits = list(TRAIT_NOHUNGER,TRAIT_NOBREATH)
inherent_traits = list(TRAIT_NOHUNGER,TRAIT_NOBREATH,TRAIT_NOMARROW)
inherent_biotypes = MOB_UNDEAD|MOB_HUMANOID
mutant_bodyparts = list("mcolor" = "FFFFFF", "tail_human" = "None", "ears" = "None", "deco_wings" = "None")
exotic_bloodtype = "U"
@@ -53,10 +53,11 @@
C.adjustOxyLoss(-4)
C.adjustCloneLoss(-4)
return
C.blood_volume -= 0.75 //Will take roughly 19.5 minutes to die from standard blood volume, roughly 83 minutes to die from max blood volume.
if(C.blood_volume <= (BLOOD_VOLUME_SURVIVE*C.blood_ratio))
to_chat(C, "<span class='danger'>You ran out of blood!</span>")
C.dust()
if(C.blood_volume > 0.5)
C.blood_volume -= 0.5 //Will take roughly 19.5 minutes to die from standard blood volume, roughly 83 minutes to die from max blood volume.
else
C.dust(FALSE, TRUE)
var/area/A = get_area(C)
if(istype(A, /area/chapel) && C.mind?.assigned_role != "Chaplain")
to_chat(C, "<span class='danger'>You don't belong here!</span>")
@@ -125,7 +126,7 @@
. = ..()
var/obj/item/organ/heart/vampire/darkheart = getorgan(/obj/item/organ/heart/vampire)
if(darkheart)
. += "<span class='notice'>Current blood level: [blood_volume]/[BLOOD_VOLUME_MAXIMUM].</span>"
. += "Current blood level: [blood_volume]/[BLOOD_VOLUME_MAXIMUM]."
/obj/item/organ/heart/vampire
+2 -2
View File
@@ -3,7 +3,7 @@
* Splits off into PhysicalLife() and BiologicalLife(). Override those instead of this.
*/
/mob/living/proc/Life(seconds, times_fired)
//SHOULD_NOT_SLEEP(TRUE)
SHOULD_NOT_SLEEP(TRUE)
if(mob_transforming)
return
@@ -24,7 +24,7 @@
break
var/msg = "[key_name_admin(src)] [ADMIN_JMP(src)] was found to have no .loc with an attached client, if the cause is unknown it would be wise to ask how this was accomplished."
message_admins(msg)
send2tgs_adminless_only("Mob", msg, R_ADMIN)
INVOKE_ASYNC(GLOBAL_PROC, .proc/send2tgs_adminless_only, "Mob", msg, R_ADMIN)
log_game("[key_name(src)] was found to have no .loc with an attached client.")
// This is a temporary error tracker to make sure we've caught everything
+12 -1
View File
@@ -514,10 +514,21 @@
/mob/living/ratvar_act()
if(status_flags & GODMODE)
return
if(stat != DEAD && !is_servant_of_ratvar(src))
if(stat == DEAD || is_servant_of_ratvar(src))
return
if(is_eligible_servant(src))
add_servant_of_ratvar(src)
to_chat(src, "<span class='heavy_brass'>Ratvar's influence invades your mind, praise the Justiciar!</span>")
else
to_chat(src, "<span class='userdanger'>A blinding light boils you alive! <i>Run!</i></span>")
adjust_fire_stacks(20)
adjustFireLoss(35)
IgniteMob()
if(iscultist(src))
to_chat(src, "<span class='userdanger'>You resist Ratvar's influence... but not all of it! <i>Run!</i></span>")
adjustFireLoss(35)
if(src && reagents)
reagents.add_reagent(/datum/reagent/fuel/holyoil, 5)
return FALSE
+5 -4
View File
@@ -90,11 +90,11 @@ GLOBAL_LIST_INIT(department_radio_keys, list(
var/static/list/one_character_prefix = list(MODE_HEADSET = TRUE, MODE_ROBOT = TRUE, MODE_WHISPER = TRUE)
var/ic_blocked = FALSE
/*
if(client && !forced && config.ic_filter_regex && findtext(message, config.ic_filter_regex))
if(client && !forced && CHAT_FILTER_CHECK(message))
//The filter doesn't act on the sanitized message, but the raw message.
ic_blocked = TRUE
*/
if(sanitize)
message = trim(copytext_char(sanitize(message), 1, MAX_MESSAGE_LEN))
if(!message || message == "")
@@ -103,6 +103,7 @@ GLOBAL_LIST_INIT(department_radio_keys, list(
if(ic_blocked)
//The filter warning message shows the sanitized message though.
to_chat(src, "<span class='warning'>That message contained a word prohibited in IC chat! Consider reviewing the server rules.\n<span replaceRegex='show_filtered_ic_chat'>\"[message]\"</span></span>")
SSblackbox.record_feedback("tally", "ic_blocked_words", 1, lowertext(config.ic_filter_regex.match))
return
var/datum/saymode/saymode = SSradio.saymodes[talk_key]
@@ -333,7 +334,7 @@ GLOBAL_LIST_INIT(department_radio_keys, list(
var/obj/item/bodypart/rightarm = get_bodypart(BODY_ZONE_R_ARM)
if(HAS_TRAIT(src, TRAIT_MUTE) && get_selected_language() != /datum/language/signlanguage)
return 0
if (get_selected_language() == /datum/language/signlanguage)
var/left_disabled = FALSE
var/right_disabled = FALSE
+1 -1
View File
@@ -200,7 +200,7 @@
if(option == "Random")
iconstates[option] = image(icon = src.icon, icon_state = "ai-random")
continue
iconstates[option] = image(icon = src.icon, icon_state = resolve_ai_icon(option))
iconstates[option] = image(icon = src.icon, icon_state = resolve_ai_icon(option, radial_preview = TRUE))
view_core()
var/ai_core_icon = show_radial_menu(src, src , iconstates, radius = 42)
@@ -23,13 +23,17 @@
if(module.cyborg_base_icon == "robot")
icon = 'icons/mob/robots.dmi'
pixel_x = initial(pixel_x)
if(stat != DEAD && !(IsUnconscious() ||IsStun() || IsKnockdown() || IsParalyzed() || low_power_mode)) //Not dead, not stunned.
if(stat != DEAD && !(IsUnconscious() || IsStun() || IsParalyzed() || low_power_mode)) //Not dead, not stunned.
if(!eye_lights)
eye_lights = new()
if(lamp_intensity > 2)
if(lamp_enabled || lamp_doom)
eye_lights.icon_state = "[module.special_light_key ? "[module.special_light_key]":"[module.cyborg_base_icon]"]_l"
eye_lights.color = lamp_doom? COLOR_RED : lamp_color
eye_lights.plane = 19 //glowy eyes
else
eye_lights.icon_state = "[module.special_light_key ? "[module.special_light_key]":"[module.cyborg_base_icon]"]_e[is_servant_of_ratvar(src) ? "_r" : ""]"
eye_lights.color = COLOR_WHITE
eye_lights.plane = -1
eye_lights.icon = icon
add_overlay(eye_lights)
@@ -1059,5 +1059,5 @@ Pass a positive integer as an argument to override a bot's default speed.
I.icon_state = null
path.Cut(1, 2)
/mob/living/silicon/rust_heretic_act()
/mob/living/simple_animal/bot/rust_heretic_act()
adjustBruteLoss(500)
@@ -192,6 +192,11 @@
back.contract_next_chain_into_single_tile()
return
/mob/living/simple_animal/hostile/eldritch/armsy/proc/get_length()
. += 1
if(back)
. += back.get_length()
///Updates the next mob in the chain to move to our last location, fixed the worm if somehow broken.
/mob/living/simple_animal/hostile/eldritch/armsy/proc/update_chain_links()
gib_trail()
@@ -425,7 +425,9 @@
/mob/living/simple_animal/pet/dog/corgi/Ian/BiologicalLife()
if(!(. = ..()))
return
INVOKE_ASYNC(src, .proc/corgi_ai_behavior)
/mob/living/simple_animal/pet/dog/corgi/Ian/proc/corgi_ai_behavior()
//Feeding, chasing food, FOOOOODDDD
if(!stat && CHECK_MULTIPLE_BITFIELDS(mobility_flags, MOBILITY_STAND|MOBILITY_MOVE) && !buckled)
turns_since_scan++
@@ -25,6 +25,7 @@
/obj/item/modular_computer/laptop/examine(mob/user)
. = ..()
. += "<span class='notice'>Drag it in your hand to pick it up.</span>"
if(screen_on)
. += "<span class='notice'>Alt-click to close it.</span>"
@@ -76,6 +77,9 @@
M.put_in_hand(src, H.held_index)
/obj/item/modular_computer/laptop/on_attack_hand(mob/user)
. = ..()
if(!.)
return
if(screen_on && isturf(loc))
return attack_self(user)
@@ -1,8 +1,9 @@
/datum/computer_file/program/budgetorders
filename = "orderapp"
filedesc = "Nanotrasen Internal Requisition Network (NIRN)"
filedesc = "NT IRN"
// category = PROGRAM_CATEGORY_SUPL
program_icon_state = "request"
extended_desc = "A request network that utilizes the Nanotrasen Ordering network to purchase supplies using a department budget account."
extended_desc = "Nanotrasen Internal Requisition Network interface for supply purchasing using a department budget account."
requires_ntnet = TRUE
transfer_access = ACCESS_HEADS
usage_flags = PROGRAM_LAPTOP | PROGRAM_TABLET
@@ -79,7 +80,6 @@
data["supplies"] = list()
for(var/pack in SSshuttle.supply_packs)
var/datum/supply_pack/P = SSshuttle.supply_packs[pack]
// todo: replace to P.access_view
if(!is_visible_pack(usr, P.access , null, P.contraband) || P.hidden)
continue
if(!data["supplies"][P.group])
@@ -105,7 +105,7 @@
data["docked"] = SSshuttle.supply.mode == SHUTTLE_IDLE
data["loan"] = !!SSshuttle.shuttle_loan
data["loan_dispatched"] = SSshuttle.shuttle_loan && SSshuttle.shuttle_loan.dispatched
data["can_send"] = FALSE //There is no situation where I want the app to be able to send the shuttle AWAY from the station, but conversely is fine.
data["can_send"] = FALSE //There is no situation where I want the app to be able to send the shuttle AWAY from the station, but conversely is fine.
data["can_approve_requests"] = can_approve_requests
data["app_cost"] = TRUE
var/message = "Remember to stamp and send back the supply manifests."
@@ -20,7 +20,8 @@
"Head of Security",
"Chief Engineer",
"Research Director",
"Chief Medical Officer")
"Chief Medical Officer",
"Quartermaster")
//The scaling factor of max total positions in relation to the total amount of people on board the station in %
var/max_relative_positions = 30 //30%: Seems reasonable, limit of 6 @ 20 players
@@ -43,7 +44,7 @@
/datum/computer_file/program/job_management/proc/can_close_job(datum/job/job)
if(!(job?.title in blacklisted))
if(job.total_positions > length(GLOB.player_list) * (max_relative_positions / 100))
if(job.total_positions > job.current_positions)
var/delta = (world.time / 10) - GLOB.time_last_changed_position
if((change_position_cooldown < delta) || (opened_positions[job.title] > 0))
return TRUE
@@ -67,7 +68,7 @@
if(!j || !can_open_job(j))
return
if(opened_positions[edit_job_target] >= 0)
GLOB.time_last_changed_position = world.time / 10
GLOB.time_last_changed_position = world.time / 10 // global cd
j.total_positions++
opened_positions[edit_job_target]++
playsound(computer, 'sound/machines/terminal_prompt_confirm.ogg', 50, FALSE)
@@ -161,8 +161,10 @@ GLOBAL_LIST_EMPTY(movespeed_modification_cache)
/// Handles the special case of editing the movement var
/mob/vv_edit_var(var_name, var_value)
if(var_name == NAMEOF(src, control_object))
var/obj/O = var_name
if(!istype(O) || (O.obj_flags & DANGEROUS_POSSESSION))
var/obj/O = var_value
if(!istype(O) && (var_value != null))
return FALSE
if(O.obj_flags & DANGEROUS_POSSESSION)
return FALSE
var/slowdown_edit = (var_name == NAMEOF(src, cached_multiplicative_slowdown))
var/diff
@@ -21,6 +21,9 @@
multiplicative_slowdown = 1.5
priority = 50
/datum/movespeed_modifier/status_effect/domain
multiplicative_slowdown = 3
/datum/movespeed_modifier/status_effect/tased/no_combat_mode
multiplicative_slowdown = 8
priority = 100
+3
View File
@@ -80,6 +80,9 @@
SSshuttle.lockdown = TRUE
SSpersistence.station_was_destroyed = TRUE
sleep(600)
if(QDELETED(src))
priority_announce("Accausal event alert rescinded. Eldritch presence no longer reading on sensors. Solution package disarmed. Reccomend immediate evacuation","Central Command Higher Dimensional Affairs")
return
if(resolved == FALSE)
resolved = TRUE
sound_to_playing_players('sound/machines/alarm.ogg')
+1 -1
View File
@@ -516,7 +516,7 @@
trajectory = new(starting.x, starting.y, starting.z, pixel_x, pixel_y, Angle, pixel_increment_amount)
fired = TRUE
if(hitscan)
process_hitscan()
INVOKE_ASYNC(src, .proc/process_hitscan)
return
if(!(datum_flags & DF_ISPROCESSING))
START_PROCESSING(SSprojectiles, src)
@@ -453,3 +453,8 @@
/obj/item/reagent_containers/glass/bottle/ichor/green
name = "green potion"
list_reagents = list(/datum/reagent/green_ichor = 1)
/obj/item/reagent_containers/glass/bottle/thermite
name = "thermite bottle"
list_reagents = list(/datum/reagent/thermite = 30)
@@ -105,13 +105,3 @@
materials = list(/datum/material/iron = 2000, /datum/material/bluespace = 500)
category = list("Bluespace Designs")
departmental_flags = DEPARTMENTAL_FLAG_SERVICE
/datum/design/bluespace_carrier
name = "Bluespace Jar"
desc = "A jar used to contain creatures, using the power of bluespace."
id = "bluespace_carrier"
build_type = PROTOLATHE
build_path = /obj/item/pet_carrier/bluespace
materials = list(/datum/material/glass = 1000, /datum/material/bluespace = 600)
category = list("Bluespace Designs")
departmental_flags = DEPARTMENTAL_FLAG_SCIENCE
@@ -94,7 +94,7 @@
/datum/design/medicinalsmartdart
name = "Medicinal Smartdart"
desc = "A non-harmful dart that can administer medication from a range. Once it hits a patient using it's smart nanofilter technology only medicines contained within the dart are administered to the patient. Additonally, due to capillary action, injection of chemicals past the overdose limit is prevented."
desc = "A non-harmful dart that can administer medication from a range. Once it hits a patient using its smart nanofilter technology, only medicines contained within the dart are administered to the patient. Additonally, due to capillary action, injection of chemicals past the overdose limit is prevented."
id = "medicinalsmartdart"
build_type = PROTOLATHE
materials = list(/datum/material/glass = 100, /datum/material/plastic = 100, /datum/material/iron = 100)
@@ -192,6 +192,16 @@
category = list("Medical Designs")
departmental_flags = DEPARTMENTAL_FLAG_MEDICAL | DEPARTMENTAL_FLAG_SCIENCE
/datum/design/hypospraykit
name = "Empty Hypospray Kit"
desc = "A plastic medical kit for storing hyposprays and hypospray accessories."
id = "hypokit"
build_type = PROTOLATHE
materials = list(/datum/material/plastic = 5000)
build_path = /obj/item/storage/hypospraykit // let's not summon new hyposprays thanks
category = list("Medical Designs")
departmental_flags = DEPARTMENTAL_FLAG_MEDICAL | DEPARTMENTAL_FLAG_SCIENCE
/datum/design/blood_bag
name = "Empty Blood Bag"
desc = "A small sterilized plastic bag for blood."
@@ -203,7 +213,7 @@
departmental_flags = DEPARTMENTAL_FLAG_MEDICAL
/datum/design/bsblood_bag
name = "Blue Space Empty Blood Bag"
name = "Empty Bluespace Blood Bag"
desc = "A large sterilized plastic bag for blood."
id = "bsblood_bag"
build_path = /obj/item/reagent_containers/blood/bluespace
@@ -9,7 +9,7 @@
build_type = IMPRINTER
materials = list(/datum/material/glass = 1000)
build_path = /obj/item/circuitboard/computer/cargo/express
category = list("Mining Designs")
category = list("Computer Boards")
departmental_flags = DEPARTMENTAL_FLAG_CARGO
/datum/design/bluespace_pod
@@ -19,7 +19,7 @@
build_type = PROTOLATHE
materials = list(/datum/material/glass = 1000)
build_path = /obj/item/disk/cargo/bluespace_pod
category = list("Mining Designs")
category = list("Electronics")
departmental_flags = DEPARTMENTAL_FLAG_CARGO
/datum/design/drill
@@ -104,5 +104,6 @@
// Default research tech, prevents bricking
design_ids = list("basic_matter_bin", "basic_cell", "basic_scanning", "basic_capacitor", "basic_micro_laser", "micro_mani", "desttagger", "handlabel", "packagewrap",
"destructive_analyzer", "circuit_imprinter", "experimentor", "rdconsole", "bepis", "design_disk", "tech_disk", "rdserver", "rdservercontrol", "mechfab", "paystand",
"space_heater", "beaker", "large_beaker", "bucket", "xlarge_beaker", "sec_shellclip", "sec_beanbag", "sec_rshot", "sec_bshot", "sec_slug", "sec_islug", "sec_dart", "sec_38", "sec_38lethal",
"space_heater", "beaker", "large_beaker", "xlarge_beaker", "bucket", "hypovial", "large_hypovial",
"sec_shellclip", "sec_beanbag", "sec_rshot", "sec_bshot", "sec_slug", "sec_islug", "sec_dart", "sec_38", "sec_38lethal",
"rglass","plasteel","plastitanium","plasmaglass","plasmareinforcedglass","titaniumglass","plastitaniumglass")
@@ -5,7 +5,7 @@
display_name = "Biological Technology"
description = "What makes us tick." //the MC, silly!
prereq_ids = list("base")
design_ids = list("medicalkit", "chem_heater", "chem_master", "chem_dispenser", "sleeper", "vr_sleeper", "pandemic", "defibrillator", "defibmount", "operating", "soda_dispenser", "beer_dispenser", "healthanalyzer", "blood_bag", "bloodbankgen", "telescopiciv", "medspray","genescanner","chem_pack", "portable_chem_mixer")
design_ids = list("medicalkit", "hypokit", "chem_heater", "chem_master", "chem_dispenser", "sleeper", "vr_sleeper", "pandemic", "defibrillator", "defibmount", "operating", "soda_dispenser", "beer_dispenser", "healthanalyzer", "blood_bag", "bloodbankgen", "telescopiciv", "medspray","genescanner","chem_pack", "portable_chem_mixer")
research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500)
/datum/techweb_node/adv_biotech
@@ -13,7 +13,7 @@
display_name = "Applied Bluespace Research"
description = "Using bluespace to make things faster and better."
prereq_ids = list("bluespace_basic", "engineering")
design_ids = list("bs_rped","biobag_holding","minerbag_holding", "bluespacebeaker", "bluespacesyringe", "phasic_scanning", "bluespacesmartdart", "xenobio_slimebasic", "bluespace_tray", "bluespace_carrier")
design_ids = list("bs_rped","biobag_holding","minerbag_holding", "bluespacebeaker", "bluespacesyringe", "phasic_scanning", "bluespacesmartdart", "xenobio_slimebasic", "bluespace_tray")
research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 5000)
/datum/techweb_node/adv_bluespace
@@ -24,6 +24,14 @@
design_ids = list("bluespace_matter_bin", "femto_mani", "triphasic_scanning", "bluespace_crystal", "xenobio_slimeadv")
research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 10000)
/datum/techweb_node/emp_super
id = "emp_super"
display_name = "Quantum Electromagnetic Technology"
description = "Even better electromagnetic technology."
prereq_ids = list("emp_adv", "adv_bluespace") // why should the rest of T4 be locked but not this node? grmblgrmbl
design_ids = list("quadultra_micro_laser")
research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 3000)
/datum/techweb_node/bluespace_power
id = "bluespace_power"
display_name = "Bluespace Power Technology"
@@ -37,7 +45,7 @@
display_name = "Bluespace Pockets"
description = "Studies into the mysterious alternate dimension known as bluespace and how to place items in the threads of reality."
prereq_ids = list("adv_power", "adv_bluespace", "adv_biotech", "adv_plasma")
design_ids = list( "bluespacebodybag","bag_holding", "bluespace_pod", "borg_upgrade_trashofholding", "blutrash", "satchel_holding", "bsblood_bag", "duffelbag_holding")
design_ids = list("bluespacebodybag","bag_holding", "bluespace_pod", "borg_upgrade_trashofholding", "blutrash", "satchel_holding", "bsblood_bag", "duffelbag_holding")
research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 5500)
/datum/techweb_node/bluespace_portal
@@ -49,14 +49,6 @@
design_ids = list("ultra_micro_laser")
research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 3000)
/datum/techweb_node/emp_super
id = "emp_super"
display_name = "Quantum Electromagnetic Technology" //bs
description = "Even better electromagnetic technology."
prereq_ids = list("emp_adv")
design_ids = list("quadultra_micro_laser")
research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 3000)
/////////////////////////Clown tech/////////////////////////
/datum/techweb_node/clown
id = "clown"
@@ -12,6 +12,7 @@
pixel_x = -32
pixel_y = -32
resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | UNACIDABLE | ACID_PROOF
rad_flags = RAD_NO_CONTAMINATE | RAD_PROTECT_CONTENTS
light_range = 8
light_color = LIGHT_COLOR_LAVA
var/open = FALSE
@@ -71,6 +72,7 @@
/obj/structure/opacity_blocker
icon = 'icons/effects/96x96.dmi'
icon_state = "gate_blocker"
rad_flags = RAD_NO_CONTAMINATE | RAD_PROTECT_CONTENTS
layer = EDGED_TURF_LAYER
pixel_x = -32
pixel_y = -32
@@ -252,6 +254,7 @@ GLOBAL_DATUM(necropolis_gate, /obj/structure/necropolis_gate/legion_gate)
icon = 'icons/turf/boss_floors.dmi'
icon_state = "pristine_tile1"
layer = ABOVE_OPEN_TURF_LAYER
rad_flags = RAD_NO_CONTAMINATE | RAD_PROTECT_CONTENTS
anchored = TRUE
resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | UNACIDABLE | ACID_PROOF
var/tile_key = "pristine_tile"
+63 -33
View File
@@ -25,7 +25,14 @@ GLOBAL_LIST_INIT(blacklisted_cargo_types, typecacheof(list(
/obj/item/shared_storage,
/obj/structure/extraction_point,
/obj/machinery/syndicatebomb,
/obj/item/hilbertshotel
/obj/item/hilbertshotel,
/obj/machinery/launchpad,
/obj/machinery/disposal,
/obj/structure/disposalpipe,
/obj/item/hilbertshotel,
/obj/machinery/camera,
/obj/item/gps,
/obj/structure/checkoutmachine
)))
GLOBAL_LIST_INIT(cargo_shuttle_leave_behind_typecache, typecacheof(list(
@@ -33,6 +40,11 @@ GLOBAL_LIST_INIT(cargo_shuttle_leave_behind_typecache, typecacheof(list(
/mob/living/simple_animal/slaughter
)))
/// How many goody orders we can fit in a lockbox before we upgrade to a crate
#define GOODY_FREE_SHIPPING_MAX 5
/// How much to charge oversized goody orders
#define CRATE_TAX 700
/obj/docking_port/mobile/supply
name = "supply shuttle"
id = "supply"
@@ -58,6 +70,7 @@ GLOBAL_LIST_INIT(cargo_shuttle_leave_behind_typecache, typecacheof(list(
return check_blacklist(shuttle_areas, GLOB.blacklisted_cargo_types - GLOB.cargo_shuttle_leave_behind_typecache)
return ..()
// fuc off
/obj/docking_port/mobile/supply/enterTransit()
var/list/leave_behind = list()
for(var/i in check_blacklist(shuttle_areas, GLOB.cargo_shuttle_leave_behind_typecache))
@@ -98,12 +111,11 @@ GLOBAL_LIST_INIT(cargo_shuttle_leave_behind_typecache, typecacheof(list(
sell()
/obj/docking_port/mobile/supply/proc/buy()
if(!SSshuttle.shoppinglist.len)
return
var/list/obj/miscboxes = list() //miscboxes are combo boxes that contain all goody orders grouped
var/list/misc_order_num = list() //list of strings of order numbers, so that the manifest can show all orders in a box
var/list/misc_contents = list() //list of lists of items that each box will contain
if(!SSshuttle.shoppinglist.len)
return
var/list/empty_turfs = list()
for(var/place in shuttle_areas)
@@ -113,30 +125,39 @@ GLOBAL_LIST_INIT(cargo_shuttle_leave_behind_typecache, typecacheof(list(
continue
empty_turfs += T
var/datum/bank_account/cargo_budget = SSeconomy.get_dep_account(ACCOUNT_CAR)
var/value = 0
var/purchases = 0
var/list/goodies_by_buyer = list() // if someone orders more than GOODY_FREE_SHIPPING_MAX goodies, we upcharge to a normal crate so they can't carry around 20 combat shotties
for(var/datum/supply_order/SO in SSshuttle.shoppinglist)
if(!empty_turfs.len)
break
var/price = SO.pack.cost
if(SO.applied_coupon)
price *= (1 - SO.applied_coupon.discount_pct_off)
var/datum/bank_account/D
if(SO.paying_account) //Someone paid out of pocket
D = SO.paying_account
var/list/current_buyer_orders = goodies_by_buyer[SO.paying_account] // so we can access the length a few lines down
if(!SO.pack.goody)
price *= 1.1 //TODO make this customizable by the quartermaster
// note this is before we increment, so this is the GOODY_FREE_SHIPPING_MAX + 1th goody to ship. also note we only increment off this step if they successfully pay the fee, so there's no way around it
else if(LAZYLEN(current_buyer_orders) == GOODY_FREE_SHIPPING_MAX)
price += CRATE_TAX
D.bank_card_talk("Goody order size exceeds free shipping limit: Assessing [CRATE_TAX] credit S&H fee.")
else
D = cargo_budget
D = SSeconomy.get_dep_account(ACCOUNT_CAR)
if(D)
if(!D.adjust_money(-SO.pack.cost))
if(!D.adjust_money(-price))
if(SO.paying_account)
D.bank_card_talk("Cargo order #[SO.id] rejected due to lack of funds. Credits required: [price]")
continue
if(SO.paying_account)
if(SO.pack.goody)
LAZYADD(goodies_by_buyer[SO.paying_account], SO)
D.bank_card_talk("Cargo order #[SO.id] has shipped. [price] credits have been charged to your bank account.")
var/datum/bank_account/department/cargo = SSeconomy.get_dep_account(ACCOUNT_CAR)
cargo.adjust_money(price - SO.pack.cost) //Cargo gets the handling fee
@@ -145,30 +166,7 @@ GLOBAL_LIST_INIT(cargo_shuttle_leave_behind_typecache, typecacheof(list(
SSshuttle.orderhistory += SO
QDEL_NULL(SO.applied_coupon)
if(SO.pack.goody) //goody means it gets piled in the miscbox
if(SO.paying_account)
if(!miscboxes.len || !miscboxes[D.account_holder]) //if there's no miscbox for this person
miscboxes[D.account_holder] = new /obj/item/storage/lockbox/order(pick_n_take(empty_turfs))
var/obj/item/storage/lockbox/order/our_box = miscboxes[D.account_holder]
our_box.buyer_account = SO.paying_account
miscboxes[D.account_holder].name = "small items case - purchased by [D.account_holder]"
misc_contents[D.account_holder] = list()
for (var/item in SO.pack.contains)
misc_contents[D.account_holder] += item
misc_order_num[D.account_holder] = "[misc_order_num[D.account_holder]]#[SO.id] "
else //No private payment, so we just stuff it all into a generic crate
if(!miscboxes.len || !miscboxes["Cargo"])
miscboxes["Cargo"] = new /obj/structure/closet/secure_closet/goodies(pick_n_take(empty_turfs))
miscboxes["Cargo"].name = "small items closet"
misc_contents["Cargo"] = list()
miscboxes["Cargo"].req_access = list()
for (var/item in SO.pack.contains)
misc_contents["Cargo"] += item
//new item(miscboxes["Cargo"])
if(SO.pack.access)
miscboxes["Cargo"].req_access += SO.pack.access
misc_order_num["Cargo"] = "[misc_order_num["Cargo"]]#[SO.id] "
else
if(!SO.pack.goody) //we handle goody crates below
SO.generate(pick_n_take(empty_turfs))
SSblackbox.record_feedback("nested tally", "cargo_imports", 1, list("[SO.pack.cost]", "[SO.pack.name]"))
@@ -177,16 +175,43 @@ GLOBAL_LIST_INIT(cargo_shuttle_leave_behind_typecache, typecacheof(list(
message_admins("\A [SO.pack.name] ordered by [ADMIN_LOOKUPFLW(SO.orderer_ckey)], paid by [D.account_holder] has shipped.")
purchases++
// we handle packing all the goodies last, since the type of crate we use depends on how many goodies they ordered. If it's more than GOODY_FREE_SHIPPING_MAX
// then we send it in a crate (including the CRATE_TAX cost), otherwise send it in a free shipping case
for(var/D in goodies_by_buyer)
var/list/buying_account_orders = goodies_by_buyer[D]
var/datum/bank_account/buying_account = D
var/buyer = buying_account.account_holder
if(buying_account_orders.len > GOODY_FREE_SHIPPING_MAX) // no free shipping, send a crate
var/obj/structure/closet/crate/secure/owned/our_crate = new /obj/structure/closet/crate/secure/owned(pick_n_take(empty_turfs))
our_crate.buyer_account = buying_account
our_crate.name = "goody crate - purchased by [buyer]"
miscboxes[buyer] = our_crate
else //free shipping in a case
miscboxes[buyer] = new /obj/item/storage/lockbox/order(pick_n_take(empty_turfs))
var/obj/item/storage/lockbox/order/our_case = miscboxes[buyer]
our_case.buyer_account = buying_account
miscboxes[buyer].name = "goody case - purchased by [buyer]"
misc_contents[buyer] = list()
for(var/O in buying_account_orders)
var/datum/supply_order/our_order = O
for (var/item in our_order.pack.contains)
misc_contents[buyer] += item
misc_order_num[buyer] = "[misc_order_num[buyer]]#[our_order.id] "
for(var/I in miscboxes)
var/datum/supply_order/SO = new/datum/supply_order()
SO.id = misc_order_num[I]
SO.generateCombo(miscboxes[I], I, misc_contents[I])
qdel(SO)
var/datum/bank_account/cargo_budget = SSeconomy.get_dep_account(ACCOUNT_CAR)
investigate_log("[purchases] orders in this shipment, worth [value] credits. [cargo_budget.account_balance] credits left.", INVESTIGATE_CARGO)
/obj/docking_port/mobile/supply/proc/sell()
var/datum/bank_account/D = SSeconomy.get_dep_account(ACCOUNT_CAR)
var/presale_points = D.account_balance
var/gain = 0
if(!GLOB.exports_list.len) // No exports list? Generate it!
@@ -204,6 +229,8 @@ GLOBAL_LIST_INIT(cargo_shuttle_leave_behind_typecache, typecacheof(list(
continue
if(bounty_ship_item_and_contents(AM, dry_run = FALSE))
matched_bounty = TRUE
// ignore mech checks because the mech is ONLY for bounty
continue
if(!AM.anchored || istype(AM, /obj/mecha))
export_item_and_contents(AM, export_categories , dry_run = FALSE, external_report = ex)
@@ -230,4 +257,7 @@ GLOBAL_LIST_INIT(cargo_shuttle_leave_behind_typecache, typecacheof(list(
msg = copytext_char(msg, 1, MAX_MESSAGE_LEN)
SSshuttle.centcom_message = msg
investigate_log("Shuttle contents sold for [gain] credits. Contents: [ex.exported_atoms || "none."] Message: [SSshuttle.centcom_message || "none."]", INVESTIGATE_CARGO)
investigate_log("Shuttle contents sold for [D.account_balance - presale_points] credits. Contents: [ex.exported_atoms ? ex.exported_atoms.Join(",") + "." : "none."] Message: [SSshuttle.centcom_message || "none."]", INVESTIGATE_CARGO)
#undef GOODY_FREE_SHIPPING_MAX
#undef CRATE_TAX
@@ -98,6 +98,7 @@
item = /obj/item/clothing/gloves/tackler/combat/insulated
include_modes = list(/datum/game_mode/nuclear, /datum/game_mode/nuclear/clown_ops)
cost = 2
illegal_tech = FALSE
/datum/uplink_item/device_tools/syndicate_eyepatch
name = "Mechanical Eyepatch"

Some files were not shown because too many files have changed in this diff Show More