Psykers (#71566)
## About The Pull Request Finishes #66471 At burden level nine (or through a deadly genetic breakdown), you now turn into a psyker. This splits your skull in half and transforms it into a weird fleshy mass. You become blind, but your skull is perfectly suited for sending out psychic waves. You get potent psy abilities. First one is brainwave echolocation, inspired by Gehennites (but not as laggy). Secondly, you get the ability of Psychic Walls, which act similarly to wizard ones, but last shorter, and cause projectiles to ricochet off them. Thirdly, you get a projectile boost ability, this temporarily lets you fire guns twice as fast and gives them homing to the target you clicked. Lastly, you get the ability of psychic projection. This terrifies the victim, fucking their screen up and causing them to rapidfire any gun they have in their general direction (they'll probably miss you) With most of the abilities being based around guns, a burden level nine chaplain now gets a new rite, Transmogrify. This lets them turn their null rod into a 5-shot 18 damage .77 revolver. The revolver possesses a weaker version of antimagic (protects against mind and unholy spells, but not wizard/cult ones). It is reloaded by a prayer action (can also only be performed by a max burdened person). General Video: https://streamable.com/w3kkrk Psychic Projection Video: https://streamable.com/4ibu7o  ## Why It's Good For The Game Rewards the burdened chaplain with some pretty cool stuff for going through hell like losing half his limbs, cause the current psychics dont cut it as much as probably necessary, adds echolocation which can be used for neat stuff in the future (bat organs for DNA infuser for example). ## Changelog 🆑 Fikou, sprites from Halcyon, some old code from Basilman and Armhulen. refactor: Honorbound and Burdened mutations are brain traumas now. add: Psykers. Become a psyker through the path of the burdened, or a genetic breakdown. add: Echolocation Component. /🆑 Co-authored-by: tralezab <spamqetuo2@gmail.com> Co-authored-by: tralezab <40974010+tralezab@users.noreply.github.com> Co-authored-by: MrMelbert <51863163+MrMelbert@users.noreply.github.com>
@@ -325,6 +325,8 @@
|
||||
#define COMSIG_PROJECTILE_ON_HIT "projectile_on_hit"
|
||||
///from base of /obj/projectile/proc/fire(): (obj/projectile, atom/original_target)
|
||||
#define COMSIG_PROJECTILE_BEFORE_FIRE "projectile_before_fire"
|
||||
///from base of /obj/projectile/proc/fire(): (obj/projectile, atom/firer, atom/original_target)
|
||||
#define COMSIG_PROJECTILE_FIRER_BEFORE_FIRE "projectile_firer_before_fire"
|
||||
///from the base of /obj/projectile/proc/fire(): ()
|
||||
#define COMSIG_PROJECTILE_FIRE "projectile_fire"
|
||||
///sent to targets during the process_hit proc of projectiles
|
||||
|
||||
@@ -210,6 +210,7 @@
|
||||
#define BLIND_LAYER 4
|
||||
#define CRIT_LAYER 5
|
||||
#define CURSE_LAYER 6
|
||||
#define ECHO_LAYER 7
|
||||
|
||||
#define FOV_EFFECT_LAYER 100
|
||||
|
||||
|
||||
@@ -120,6 +120,7 @@
|
||||
#define BODYPART_ID_ROBOTIC "robotic"
|
||||
#define BODYPART_ID_DIGITIGRADE "digitigrade"
|
||||
#define BODYPART_ID_LARVA "larva"
|
||||
#define BODYPART_ID_PSYKER "psyker"
|
||||
|
||||
//See: datum/species/var/digitigrade_customization
|
||||
///The species does not have digitigrade legs in generation.
|
||||
|
||||
@@ -22,6 +22,8 @@
|
||||
#define CALIBER_357 ".357"
|
||||
/// The caliber used by the detective's revolver.
|
||||
#define CALIBER_38 ".38"
|
||||
/// The caliber used by the chaplain's revolver.
|
||||
#define CALIBER_77 ".77"
|
||||
/// The caliber used by the C-20r SMG, the tommygun, and the M1911 pistol.
|
||||
#define CALIBER_45 ".45"
|
||||
/// The caliber used by sniper rifles and the desert eagle.
|
||||
|
||||
@@ -609,6 +609,7 @@ Remember to update _globalvars/traits.dm if you're adding/removing/renaming trai
|
||||
#define TRAIT_GRABWEAKNESS "grab_weakness"
|
||||
#define TRAIT_SNOB "snob"
|
||||
#define TRAIT_BALD "bald"
|
||||
#define TRAIT_SHAVED "shaved"
|
||||
#define TRAIT_BADTOUCH "bad_touch"
|
||||
#define TRAIT_EXTROVERT "extrovert"
|
||||
#define TRAIT_INTROVERT "introvert"
|
||||
@@ -677,6 +678,12 @@ Remember to update _globalvars/traits.dm if you're adding/removing/renaming trai
|
||||
/// this is used to bypass tongue language restrictions but not tongue disabilities
|
||||
#define TRAIT_TOWER_OF_BABEL "tower_of_babel"
|
||||
|
||||
/// This target has recently been shot by a marksman coin and is very briefly immune to being hit by one again to prevent recursion
|
||||
#define TRAIT_RECENTLY_COINED "recently_coined"
|
||||
|
||||
/// Receives echolocation images.
|
||||
#define TRAIT_ECHOLOCATION_RECEIVER "echolocation_receiver"
|
||||
|
||||
//Medical Categories for quirks
|
||||
#define CAT_QUIRK_ALL 0
|
||||
#define CAT_QUIRK_NOTES 1
|
||||
@@ -987,5 +994,5 @@ Remember to update _globalvars/traits.dm if you're adding/removing/renaming trai
|
||||
#define RIGHT_LEG_TRAIT "right_leg"
|
||||
#define LEFT_LEG_TRAIT "left_leg"
|
||||
|
||||
/// This target has recently been shot by a marksman coin and is very briefly immune to being hit by one again to prevent recursion
|
||||
#define TRAIT_RECENTLY_COINED "trait_recently_coined"
|
||||
/// Trait given by echolocation component.
|
||||
#define ECHOLOCATION_TRAIT "echolocation"
|
||||
|
||||
@@ -45,7 +45,8 @@
|
||||
else if(ismob(parent))
|
||||
RegisterSignal(parent, COMSIG_MOB_RECEIVE_MAGIC, PROC_REF(block_receiving_magic), override = TRUE)
|
||||
RegisterSignal(parent, COMSIG_MOB_RESTRICT_MAGIC, PROC_REF(restrict_casting_magic), override = TRUE)
|
||||
to_chat(parent, span_warning("Magic seems to flee from you. You are immune to spells but are unable to cast magic."))
|
||||
if(!HAS_TRAIT(parent, TRAIT_ANTIMAGIC_NO_SELFBLOCK))
|
||||
to_chat(parent, span_warning("Magic seems to flee from you. You are immune to spells but are unable to cast magic."))
|
||||
else
|
||||
return COMPONENT_INCOMPATIBLE
|
||||
|
||||
|
||||
@@ -0,0 +1,183 @@
|
||||
/datum/component/echolocation
|
||||
/// Radius of our view.
|
||||
var/echo_range = 4
|
||||
/// Time between echolocations.
|
||||
var/cooldown_time = 2 SECONDS
|
||||
/// Time for the image to start fading out.
|
||||
var/image_expiry_time = 1.5 SECONDS
|
||||
/// Time for the image to fade in.
|
||||
var/fade_in_time = 0.5 SECONDS
|
||||
/// Time for the image to fade out and delete itself.
|
||||
var/fade_out_time = 0.5 SECONDS
|
||||
/// Are images static? If yes, spawns them on the turf and makes them not change location. Otherwise they change location and pixel shift with the original.
|
||||
var/images_are_static = TRUE
|
||||
/// With mobs that have this echo group in their echolocation receiver trait, we share echo images.
|
||||
var/echo_group = null
|
||||
/// Ref of the client color we give to the echolocator.
|
||||
var/client_color
|
||||
/// Associative list of world.time when created to a list of the images.
|
||||
var/list/images = list()
|
||||
/// Associative list of world.time when created to a list of receivers.
|
||||
var/list/receivers = list()
|
||||
/// All the saved appearances, keyed by icon-icon_state.
|
||||
var/static/list/saved_appearances = list()
|
||||
/// Typecache of all the allowed paths to render.
|
||||
var/static/list/allowed_paths
|
||||
/// Typecache of turfs that are dangerous, to give them a special icon.
|
||||
var/static/list/danger_turfs
|
||||
/// A matrix that turns everything except #ffffff into pure blackness, used for our images (the outlines are #ffffff).
|
||||
var/static/list/black_white_matrix = list(85, 85, 85, 0, 85, 85, 85, 0, 85, 85, 85, 0, 0, 0, 0, 1, -254, -254, -254, 0)
|
||||
/// Cooldown for the echolocation.
|
||||
COOLDOWN_DECLARE(cooldown_last)
|
||||
|
||||
/datum/component/echolocation/Initialize(echo_range, cooldown_time, image_expiry_time, fade_in_time, fade_out_time, images_are_static, echo_group, echo_icon, color_path)
|
||||
. = ..()
|
||||
var/mob/living/echolocator = parent
|
||||
if(!istype(echolocator))
|
||||
return COMPONENT_INCOMPATIBLE
|
||||
if(!danger_turfs)
|
||||
danger_turfs = typecacheof(list(/turf/open/space, /turf/open/openspace, /turf/open/chasm, /turf/open/lava))
|
||||
if(!allowed_paths)
|
||||
allowed_paths = typecacheof(list(/turf/closed, /obj, /mob/living)) + danger_turfs
|
||||
if(!isnull(echo_range))
|
||||
src.echo_range = echo_range
|
||||
if(!isnull(cooldown_time))
|
||||
src.cooldown_time = cooldown_time
|
||||
if(!isnull(image_expiry_time))
|
||||
src.image_expiry_time = image_expiry_time
|
||||
if(!isnull(fade_in_time))
|
||||
src.fade_in_time = fade_in_time
|
||||
if(!isnull(fade_out_time))
|
||||
src.fade_out_time = fade_out_time
|
||||
if(!isnull(images_are_static))
|
||||
src.images_are_static = images_are_static
|
||||
if(!isnull(echo_group))
|
||||
src.echo_group = echo_group
|
||||
if(!isnull(color_path))
|
||||
client_color = echolocator.add_client_colour(color_path)
|
||||
ADD_TRAIT(echolocator, TRAIT_ECHOLOCATION_RECEIVER, echo_group || REF(src))
|
||||
echolocator.become_blind(ECHOLOCATION_TRAIT)
|
||||
echolocator.overlay_fullscreen("echo", /atom/movable/screen/fullscreen/echo, echo_icon)
|
||||
START_PROCESSING(SSfastprocess, src)
|
||||
|
||||
/datum/component/echolocation/Destroy(force, silent)
|
||||
STOP_PROCESSING(SSfastprocess, src)
|
||||
var/mob/living/echolocator = parent
|
||||
QDEL_NULL(client_color)
|
||||
REMOVE_TRAIT(echolocator, TRAIT_ECHOLOCATION_RECEIVER, echo_group || REF(src))
|
||||
echolocator.cure_blind(ECHOLOCATION_TRAIT)
|
||||
echolocator.clear_fullscreen("echo")
|
||||
for(var/timeframe in images)
|
||||
delete_images(timeframe)
|
||||
return ..()
|
||||
|
||||
/datum/component/echolocation/process()
|
||||
var/mob/living/echolocator = parent
|
||||
if(echolocator.stat == DEAD)
|
||||
return
|
||||
echolocate()
|
||||
|
||||
/datum/component/echolocation/proc/echolocate()
|
||||
if(!COOLDOWN_FINISHED(src, cooldown_last))
|
||||
return
|
||||
COOLDOWN_START(src, cooldown_last, cooldown_time)
|
||||
var/mob/living/echolocator = parent
|
||||
var/list/filtered = list()
|
||||
var/list/seen = dview(echo_range, echolocator.loc)
|
||||
for(var/atom/seen_atom as anything in seen)
|
||||
if(seen_atom.invisibility > echolocator.see_invisible || !seen_atom.alpha)
|
||||
continue
|
||||
if(allowed_paths[seen_atom.type])
|
||||
filtered += seen_atom
|
||||
if(!length(filtered))
|
||||
return
|
||||
var/current_time = "[world.time]"
|
||||
images[current_time] = list()
|
||||
receivers[current_time] = list()
|
||||
for(var/mob/living/viewer in filtered)
|
||||
if(HAS_TRAIT_FROM(viewer, TRAIT_ECHOLOCATION_RECEIVER, echo_group))
|
||||
receivers[current_time] += viewer
|
||||
for(var/atom/filtered_atom as anything in filtered)
|
||||
show_image(saved_appearances["[filtered_atom.icon]-[filtered_atom.icon_state]"] || generate_appearance(filtered_atom), filtered_atom, current_time)
|
||||
addtimer(CALLBACK(src, .proc/fade_images, current_time), image_expiry_time)
|
||||
|
||||
/datum/component/echolocation/proc/show_image(image/input_appearance, atom/input, current_time)
|
||||
var/image/final_image = image(input_appearance)
|
||||
final_image.layer += EFFECTS_LAYER
|
||||
final_image.plane = FULLSCREEN_PLANE
|
||||
final_image.loc = images_are_static ? get_turf(input) : input
|
||||
final_image.dir = input.dir
|
||||
final_image.alpha = 0
|
||||
if(images_are_static)
|
||||
final_image.pixel_x = input.pixel_x
|
||||
final_image.pixel_y = input.pixel_y
|
||||
images[current_time] += final_image
|
||||
for(var/mob/living/echolocate_receiver as anything in receivers[current_time])
|
||||
if(echolocate_receiver == input)
|
||||
continue
|
||||
if(echolocate_receiver.client)
|
||||
echolocate_receiver.client.images += final_image
|
||||
animate(final_image, alpha = 255, time = fade_in_time)
|
||||
|
||||
/datum/component/echolocation/proc/generate_appearance(atom/input)
|
||||
var/use_outline = TRUE
|
||||
var/mutable_appearance/copied_appearance = new /mutable_appearance()
|
||||
copied_appearance.appearance = input
|
||||
if(istype(input, /obj/machinery/door/airlock)) //i hate you
|
||||
copied_appearance.icon = 'icons/obj/doors/airlocks/station/public.dmi'
|
||||
copied_appearance.icon_state = "closed"
|
||||
else if(danger_turfs[input.type])
|
||||
copied_appearance.icon = 'icons/turf/floors.dmi'
|
||||
copied_appearance.icon_state = "danger"
|
||||
use_outline = FALSE
|
||||
copied_appearance.color = black_white_matrix
|
||||
if(use_outline)
|
||||
copied_appearance.filters += outline_filter(size = 1, color = COLOR_WHITE)
|
||||
if(!images_are_static)
|
||||
copied_appearance.pixel_x = 0
|
||||
copied_appearance.pixel_y = 0
|
||||
copied_appearance.transform = matrix()
|
||||
if(!iscarbon(input)) //wacky overlay people get generated everytime
|
||||
saved_appearances["[input.icon]-[input.icon_state]"] = copied_appearance
|
||||
return copied_appearance
|
||||
|
||||
/datum/component/echolocation/proc/fade_images(from_when)
|
||||
for(var/image_echo in images[from_when])
|
||||
animate(image_echo, alpha = 0, time = fade_out_time)
|
||||
addtimer(CALLBACK(src, .proc/delete_images, from_when), fade_out_time)
|
||||
|
||||
/datum/component/echolocation/proc/delete_images(from_when)
|
||||
for(var/mob/living/echolocate_receiver as anything in receivers[from_when])
|
||||
if(!echolocate_receiver.client)
|
||||
continue
|
||||
for(var/image_echo in images[from_when])
|
||||
echolocate_receiver.client.images -= image_echo
|
||||
images -= from_when
|
||||
receivers -= from_when
|
||||
|
||||
/atom/movable/screen/fullscreen/echo
|
||||
icon_state = "echo"
|
||||
layer = ECHO_LAYER
|
||||
show_when_dead = TRUE
|
||||
|
||||
/atom/movable/screen/fullscreen/echo/Initialize(mapload)
|
||||
. = ..()
|
||||
particles = new /particles/echo()
|
||||
|
||||
/atom/movable/screen/fullscreen/echo/Destroy()
|
||||
QDEL_NULL(particles)
|
||||
return ..()
|
||||
|
||||
/particles/echo
|
||||
icon = 'icons/effects/particles/echo.dmi'
|
||||
icon_state = list("echo1" = 1, "echo2" = 1, "echo3" = 2)
|
||||
width = 480
|
||||
height = 480
|
||||
count = 1000
|
||||
spawning = 0.5
|
||||
lifespan = 2 SECONDS
|
||||
fade = 1 SECONDS
|
||||
gravity = list(0, -0.1)
|
||||
position = generator(GEN_BOX, list(-240, -240), list(240, 240), NORMAL_RAND)
|
||||
drift = generator(GEN_VECTOR, list(-0.1, 0), list(0.1, 0))
|
||||
rotation = generator(GEN_NUM, 0, 360, NORMAL_RAND)
|
||||
@@ -171,13 +171,7 @@
|
||||
*/
|
||||
/datum/component/religious_tool/proc/generate_available_sects(mob/user)
|
||||
var/list/sects_to_pick = list()
|
||||
var/human_highpriest = ishuman(user)
|
||||
var/mob/living/carbon/human/highpriest = user
|
||||
for(var/path in subtypesof(/datum/religion_sect))
|
||||
if(human_highpriest && initial(easy_access_sect.invalidating_qualities))
|
||||
var/datum/species/highpriest_species = highpriest.dna.species
|
||||
if(initial(easy_access_sect.invalidating_qualities) in highpriest_species.inherent_traits)
|
||||
continue
|
||||
var/list/sect = list()
|
||||
var/datum/religion_sect/not_a_real_instance_rs = path
|
||||
sect["name"] = initial(not_a_real_instance_rs.name)
|
||||
|
||||
@@ -565,7 +565,10 @@ GLOBAL_LIST_INIT(total_uf_len_by_block, populate_total_uf_len_by_block())
|
||||
skin_tone = GLOB.skin_tones[deconstruct_block(get_uni_identity_block(structure, DNA_SKIN_TONE_BLOCK), GLOB.skin_tones.len)]
|
||||
eye_color_left = sanitize_hexcolor(get_uni_identity_block(structure, DNA_EYE_COLOR_LEFT_BLOCK))
|
||||
eye_color_right = sanitize_hexcolor(get_uni_identity_block(structure, DNA_EYE_COLOR_RIGHT_BLOCK))
|
||||
facial_hairstyle = GLOB.facial_hairstyles_list[deconstruct_block(get_uni_identity_block(structure, DNA_FACIAL_HAIRSTYLE_BLOCK), GLOB.facial_hairstyles_list.len)]
|
||||
if(HAS_TRAIT(src, TRAIT_SHAVED))
|
||||
hairstyle = "Shaved"
|
||||
else
|
||||
facial_hairstyle = GLOB.facial_hairstyles_list[deconstruct_block(get_uni_identity_block(structure, DNA_FACIAL_HAIRSTYLE_BLOCK), GLOB.facial_hairstyles_list.len)]
|
||||
if(HAS_TRAIT(src, TRAIT_BALD))
|
||||
hairstyle = "Bald"
|
||||
else
|
||||
@@ -836,7 +839,7 @@ GLOBAL_LIST_INIT(total_uf_len_by_block, populate_total_uf_len_by_block())
|
||||
ForceContractDisease(new/datum/disease/gastrolosis())
|
||||
to_chat(src, span_notice("Oh, I actually feel quite alright!"))
|
||||
else
|
||||
switch(rand(0,5))
|
||||
switch(rand(0,6))
|
||||
if(0)
|
||||
investigate_log("has been gibbed by DNA instability.", INVESTIGATE_DEATHS)
|
||||
gib()
|
||||
@@ -866,6 +869,8 @@ GLOBAL_LIST_INIT(total_uf_len_by_block, populate_total_uf_len_by_block())
|
||||
if(5)
|
||||
to_chat(src, span_phobia("LOOK UP!"))
|
||||
addtimer(CALLBACK(src, PROC_REF(something_horrible_mindmelt)), 30)
|
||||
if(6)
|
||||
psykerize()
|
||||
|
||||
/mob/living/carbon/human/proc/something_horrible_mindmelt()
|
||||
if(!is_blind())
|
||||
|
||||
@@ -66,3 +66,13 @@
|
||||
name = "invisible blockade"
|
||||
desc = "You're gonna be here awhile."
|
||||
initial_duration = 1 MINUTES
|
||||
|
||||
/// Psyker forcefield
|
||||
/obj/effect/forcefield/psychic
|
||||
name = "psychic forcefield"
|
||||
desc = "A wall of psychic energy powerful enough stop the motion of objects. Projectiles ricochet."
|
||||
icon_state = "psychic"
|
||||
can_atmos_pass = ATMOS_PASS_YES
|
||||
flags_ricochet = RICOCHET_SHINY | RICOCHET_HARD
|
||||
receive_ricochet_chance_mod = INFINITY //we do ricochet a lot!
|
||||
initial_duration = 10 SECONDS
|
||||
|
||||
@@ -166,6 +166,9 @@
|
||||
if(!get_location_accessible(H, location))
|
||||
to_chat(user, span_warning("The mask is in the way!"))
|
||||
return
|
||||
if(HAS_TRAIT(H, TRAIT_SHAVED))
|
||||
to_chat(user, span_warning("[H] is just way too shaved. Like, really really shaved."))
|
||||
return
|
||||
user.visible_message(span_notice("[user] tries to change [H]'s facial hairstyle using [src]."), span_notice("You try to change [H]'s facial hairstyle using [src]."))
|
||||
if(new_style && do_after(user, 60, target = H))
|
||||
user.visible_message(span_notice("[user] successfully changes [H]'s facial hairstyle using [src]."), span_notice("You successfully change [H]'s facial hairstyle using [src]."))
|
||||
@@ -215,7 +218,7 @@
|
||||
to_chat(user, span_warning("The headgear is in the way!"))
|
||||
return
|
||||
if(HAS_TRAIT(H, TRAIT_BALD))
|
||||
to_chat(H, span_warning("[H] is just way too bald. Like, really really bald."))
|
||||
to_chat(user, span_warning("[H] is just way too bald. Like, really really bald."))
|
||||
return
|
||||
user.visible_message(span_notice("[user] tries to change [H]'s hairstyle using [src]."), span_notice("You try to change [H]'s hairstyle using [src]."))
|
||||
if(new_style && do_after(user, 60, target = H))
|
||||
|
||||
@@ -34,6 +34,8 @@ MAPPING_DIRECTIONAL_HELPERS(/obj/structure/mirror, 28)
|
||||
return TRUE
|
||||
if(!user.canUseTopic(src, be_close = TRUE, no_dexterity = FALSE, no_tk = TRUE))
|
||||
return TRUE //no tele-grooming
|
||||
if(HAS_TRAIT(hairdresser, TRAIT_SHAVED))
|
||||
to_chat(hairdresser, span_notice("If only growing back facial hair were that easy for you..."))
|
||||
hairdresser.facial_hairstyle = new_style
|
||||
else
|
||||
hairdresser.facial_hairstyle = "Shaved"
|
||||
|
||||
@@ -213,6 +213,11 @@
|
||||
/datum/client_colour/rave
|
||||
priority = PRIORITY_LOW
|
||||
|
||||
/datum/client_colour/psyker
|
||||
priority = PRIORITY_ABSOLUTE
|
||||
override = TRUE
|
||||
colour = list(0.8,0,0,0, 0,0,0,0, 0,0,1,0, 0,0,0,1, 0,0,0,0)
|
||||
|
||||
#undef PRIORITY_ABSOLUTE
|
||||
#undef PRIORITY_HIGH
|
||||
#undef PRIORITY_NORMAL
|
||||
|
||||
@@ -42,7 +42,7 @@
|
||||
/obj/item/organ/internal/brain/Insert(mob/living/carbon/C, special = FALSE, drop_if_replaced = TRUE, no_id_transfer = FALSE)
|
||||
. = ..()
|
||||
|
||||
name = "brain"
|
||||
name = initial(name)
|
||||
|
||||
if(C.mind && C.mind.has_antag_datum(/datum/antagonist/changeling) && !no_id_transfer) //congrats, you're trapped in a body you don't control
|
||||
if(brainmob && !(C.stat == DEAD || (HAS_TRAIT(C, TRAIT_DEATHCOMA))))
|
||||
@@ -88,11 +88,12 @@
|
||||
/obj/item/organ/internal/brain/Remove(mob/living/carbon/C, special = 0, no_id_transfer = FALSE)
|
||||
// Delete skillchips first as parent proc sets owner to null, and skillchips need to know the brain's owner.
|
||||
if(!QDELETED(C) && length(skillchips))
|
||||
to_chat(C, span_notice("You feel your skillchips enable emergency power saving mode, deactivating as your brain leaves your body..."))
|
||||
if(!special)
|
||||
to_chat(C, span_notice("You feel your skillchips enable emergency power saving mode, deactivating as your brain leaves your body..."))
|
||||
for(var/chip in skillchips)
|
||||
var/obj/item/skillchip/skillchip = chip
|
||||
// Run the try_ proc with force = TRUE.
|
||||
skillchip.try_deactivate_skillchip(FALSE, TRUE)
|
||||
skillchip.try_deactivate_skillchip(silent = special, force = TRUE)
|
||||
|
||||
. = ..()
|
||||
|
||||
@@ -106,7 +107,7 @@
|
||||
C.update_body_parts()
|
||||
|
||||
/obj/item/organ/internal/brain/proc/transfer_identity(mob/living/L)
|
||||
name = "[L.name]'s brain"
|
||||
name = "[L.name]'s [initial(name)]"
|
||||
if(brainmob || decoy_override)
|
||||
return
|
||||
if(!L.mind)
|
||||
@@ -297,7 +298,7 @@
|
||||
|
||||
// If we have some sort of brain type or subtype change and have skillchips, engage the failsafe procedure!
|
||||
if(owner && length(skillchips) && (replacement_brain.type != type))
|
||||
activate_skillchip_failsafe(FALSE)
|
||||
activate_skillchip_failsafe(silent = TRUE)
|
||||
|
||||
// Check through all our skillchips, remove them from this brain, add them to the replacement brain.
|
||||
for(var/chip in skillchips)
|
||||
@@ -347,7 +348,7 @@
|
||||
organ_traits = list(TRAIT_CAN_STRIP)
|
||||
|
||||
/obj/item/organ/internal/brain/primitive //No like books and stompy metal men
|
||||
name = "Primative Brain"
|
||||
name = "primitive brain"
|
||||
desc = "This juicy piece of meat has a clearly underdeveloped frontal lobe."
|
||||
organ_traits = list(TRAIT_ADVANCEDTOOLUSER, TRAIT_CAN_STRIP, TRAIT_PRIMITIVE) // No literacy
|
||||
|
||||
|
||||
@@ -94,7 +94,7 @@
|
||||
plane = FULLSCREEN_PLANE
|
||||
|
||||
/// Plays a visual effect representing a sound cue for people with vision obstructed by FOV or blindness
|
||||
/proc/play_fov_effect(atom/center, range, icon_state, dir = SOUTH, ignore_self = FALSE, angle = 0, list/override_list)
|
||||
/proc/play_fov_effect(atom/center, range, icon_state, dir = SOUTH, ignore_self = FALSE, angle = 0, time = 1.5 SECONDS, list/override_list)
|
||||
var/turf/anchor_point = get_turf(center)
|
||||
var/image/fov_image/fov_image
|
||||
var/list/clients_shown
|
||||
@@ -123,7 +123,7 @@
|
||||
//when added as an image mutable_appearances act identically. we just make it an MA becuase theyre faster to change appearance
|
||||
|
||||
if(clients_shown)
|
||||
addtimer(CALLBACK(GLOBAL_PROC, GLOBAL_PROC_REF(remove_image_from_clients), fov_image, clients_shown), 30)
|
||||
addtimer(CALLBACK(GLOBAL_PROC, GLOBAL_PROC_REF(remove_image_from_clients), fov_image, clients_shown), time)
|
||||
|
||||
/atom/movable/screen/fov_blocker
|
||||
icon = 'icons/effects/fov/field_of_view.dmi'
|
||||
|
||||
@@ -327,7 +327,7 @@
|
||||
update_appearance()
|
||||
|
||||
/obj/item/gun/ballistic/can_shoot()
|
||||
return chambered
|
||||
return chambered?.loaded_projectile
|
||||
|
||||
/obj/item/gun/ballistic/attackby(obj/item/A, mob/user, params)
|
||||
. = ..()
|
||||
|
||||
@@ -701,6 +701,8 @@
|
||||
LAZYINITLIST(impacted)
|
||||
if(fired_from)
|
||||
SEND_SIGNAL(fired_from, COMSIG_PROJECTILE_BEFORE_FIRE, src, original)
|
||||
if(firer)
|
||||
SEND_SIGNAL(firer, COMSIG_PROJECTILE_FIRER_BEFORE_FIRE, src, fired_from, original)
|
||||
//If no angle needs to resolve it from xo/yo!
|
||||
if(shrapnel_type && LAZYLEN(embedding))
|
||||
AddElement(/datum/element/embed, projectile_payload = shrapnel_type)
|
||||
|
||||
@@ -2052,7 +2052,7 @@
|
||||
|
||||
/datum/reagent/barbers_aid/expose_mob(mob/living/exposed_mob, methods=TOUCH, reac_volume, show_message=TRUE, touch_protection=FALSE)
|
||||
. = ..()
|
||||
if(!(methods & (TOUCH|VAPOR)) || !ishuman(exposed_mob) || HAS_TRAIT(exposed_mob, TRAIT_BALD))
|
||||
if(!(methods & (TOUCH|VAPOR)) || !ishuman(exposed_mob) || HAS_TRAIT(exposed_mob, TRAIT_BALD) || HAS_TRAIT(exposed_mob, TRAIT_SHAVED))
|
||||
return
|
||||
|
||||
var/mob/living/carbon/human/exposed_human = exposed_mob
|
||||
@@ -2074,7 +2074,7 @@
|
||||
|
||||
/datum/reagent/concentrated_barbers_aid/expose_mob(mob/living/exposed_mob, methods=TOUCH, reac_volume, show_message=TRUE, touch_protection=FALSE)
|
||||
. = ..()
|
||||
if(!(methods & (TOUCH|VAPOR)) || !ishuman(exposed_mob) || HAS_TRAIT(exposed_mob, TRAIT_BALD))
|
||||
if(!(methods & (TOUCH|VAPOR)) || !ishuman(exposed_mob) || HAS_TRAIT(exposed_mob, TRAIT_BALD) || HAS_TRAIT(exposed_mob, TRAIT_SHAVED))
|
||||
return
|
||||
|
||||
var/mob/living/carbon/human/exposed_human = exposed_mob
|
||||
|
||||
@@ -1,20 +1,15 @@
|
||||
|
||||
///Burdened grants some more mutations upon injuring yourself sufficiently
|
||||
/datum/mutation/human/burdened
|
||||
name = "Burdened"
|
||||
desc = "Less of a genome and more of a forceful rewrite of genes. Nothing Nanotrasen supplies allows for a genetic restructure like this... \
|
||||
The user feels compelled to injure themselves in various incapacitating and horrific ways. Oddly enough, this gene seems to be connected \
|
||||
to several other ones, possibly ready to trigger more genetic changes in the future."
|
||||
quality = POSITIVE //so it gets carried over on revives
|
||||
locked = TRUE
|
||||
text_gain_indication = "<span class='notice'>You feel burdened!</span>"
|
||||
text_lose_indication = "<span class='warning'>You no longer feel the need to burden yourself!</span>"
|
||||
/// goes from 0 to 6 (but can be beyond 6, just does nothing) and gives rewards. increased by disabling yourself with debuffs
|
||||
///Burdened grants some mutations upon injuring yourself sufficiently
|
||||
/datum/brain_trauma/special/burdened
|
||||
name = "Flagellating Compulsions"
|
||||
desc = "Patient feels compelled to injure themselves in various incapacitating and horrific ways. There seems to be an odd genetic... trigger, following these compulsions may lead to?"
|
||||
scan_desc = "damaged frontal lobe"
|
||||
gain_text = span_notice("You feel burdened!")
|
||||
lose_text = span_warning("You no longer feel the need to burden yourself!")
|
||||
random_gain = FALSE
|
||||
/// goes from 0 to 9 (but can be beyond 9, just does nothing) and gives rewards. increased by disabling yourself with debuffs
|
||||
var/burden_level = 0
|
||||
|
||||
/datum/mutation/human/burdened/on_acquiring(mob/living/carbon/human/owner)
|
||||
if(..())
|
||||
return
|
||||
/datum/brain_trauma/special/burdened/on_gain()
|
||||
RegisterSignal(owner, COMSIG_CARBON_GAIN_ORGAN, PROC_REF(organ_added_burden))
|
||||
RegisterSignal(owner, COMSIG_CARBON_LOSE_ORGAN, PROC_REF(organ_removed_burden))
|
||||
|
||||
@@ -29,9 +24,9 @@
|
||||
|
||||
RegisterSignal(owner, COMSIG_CARBON_GAIN_TRAUMA, PROC_REF(trauma_added_burden))
|
||||
RegisterSignal(owner, COMSIG_CARBON_LOSE_TRAUMA, PROC_REF(trauma_removed_burden))
|
||||
return ..()
|
||||
|
||||
/datum/mutation/human/burdened/on_losing(mob/living/carbon/human/owner)
|
||||
. = ..()
|
||||
/datum/brain_trauma/special/burdened/on_lose()
|
||||
UnregisterSignal(owner, list(
|
||||
COMSIG_CARBON_GAIN_ORGAN,
|
||||
COMSIG_CARBON_LOSE_ORGAN,
|
||||
@@ -44,6 +39,7 @@
|
||||
COMSIG_CARBON_GAIN_TRAUMA,
|
||||
COMSIG_CARBON_LOSE_TRAUMA,
|
||||
))
|
||||
return ..()
|
||||
|
||||
/**
|
||||
* Called by hooked signals whenever burden_level var needs to go up or down by 1.
|
||||
@@ -52,11 +48,15 @@
|
||||
* Arguments:
|
||||
* * increase: whether to tick burden_level up or down 1
|
||||
*/
|
||||
/datum/mutation/human/burdened/proc/update_burden(increase)
|
||||
/datum/brain_trauma/special/burdened/proc/update_burden(increase)
|
||||
var/datum/dna/dna = owner?.dna
|
||||
if(!dna)
|
||||
qdel(src)
|
||||
return
|
||||
//adjust burden
|
||||
burden_level = increase ? burden_level + 1 : burden_level - 1
|
||||
if(burden_level < 0) //basically a clamp with a stack on it, because this shouldn't be happening
|
||||
stack_trace("somehow, burden mutation is removing more burden than it's adding.")
|
||||
stack_trace("somehow, burden trauma is removing more burden than it's adding.")
|
||||
burden_level = 0
|
||||
//send a message and handle rewards
|
||||
switch(burden_level)
|
||||
@@ -73,35 +73,54 @@
|
||||
else
|
||||
to_chat(owner, span_warning("The weight on your shoulders feels lighter. You have lost some universal truths."))
|
||||
dna.remove_mutation(/datum/mutation/human/telepathy)
|
||||
dna.remove_mutation(/datum/mutation/human/mute)
|
||||
dna.remove_mutation(/datum/mutation/human/unintelligible)
|
||||
owner.remove_filter("burden_outline")
|
||||
if(3)
|
||||
if(increase)
|
||||
to_chat(owner, span_notice("Your suffering is only a fraction of [GLOB.deity]'s, and yet the universal truths are coming to you."))
|
||||
dna.add_mutation(/datum/mutation/human/telepathy)
|
||||
dna.add_mutation(/datum/mutation/human/mute)
|
||||
dna.add_mutation(/datum/mutation/human/unintelligible)
|
||||
owner.add_filter("burden_outline", 9, list("type" = "outline", "color" = "#6c6eff"))
|
||||
else
|
||||
to_chat(owner, span_warning("The weight on your shoulders feels lighter. You feel like you're about to forget."))
|
||||
if(4)
|
||||
if(increase)
|
||||
to_chat(owner, span_notice("The weight on your shoulders is immense. [GLOB.deity] is shattered across the cosmos."))
|
||||
to_chat(owner, span_notice("It hurts, each ounce of pain a lesson told. How does [GLOB.deity] bear this weight?"))
|
||||
else
|
||||
to_chat(owner, span_warning("The weight on your shoulders feels lighter. You're growing further from your goal."))
|
||||
if(5)
|
||||
if(increase)
|
||||
to_chat(owner, span_notice("You're on the cusp of another breakthrough. [GLOB.deity] lost everything."))
|
||||
to_chat(owner, span_notice("Your body is a canvas of loss. You are almost at a breakthrough."))
|
||||
else
|
||||
to_chat(owner, span_warning("The weight on your shoulders feels lighter. You have lost some universal truths."))
|
||||
dna.remove_mutation(/datum/mutation/human/telekinesis)
|
||||
dna.remove_mutation(/datum/mutation/human/mindreader)
|
||||
if(6)
|
||||
if(increase)
|
||||
to_chat(owner, span_notice("Your suffering is respectful, your scars immaculate. More universal truths are clear, but you do not fully understand yet."))
|
||||
dna.add_mutation(/datum/mutation/human/telekinesis)
|
||||
dna.add_mutation(/datum/mutation/human/mindreader)
|
||||
else
|
||||
to_chat(owner, span_warning("The weight on your shoulders feels lighter. You feel like you're about to forget."))
|
||||
if(7)
|
||||
if(increase)
|
||||
to_chat(owner, span_notice("The weight on your shoulders is immense. [GLOB.deity] is shattered across the cosmos."))
|
||||
else
|
||||
to_chat(owner, span_warning("The weight on your shoulders feels lighter. You're growing further from your goal."))
|
||||
if(8)
|
||||
if(increase)
|
||||
to_chat(owner, span_notice("You're on the cusp of another breakthrough. [GLOB.deity] lost everything."))
|
||||
else
|
||||
to_chat(owner, span_warning("The weight on your shoulders feels lighter. You have lost some universal truths."))
|
||||
if(9)
|
||||
to_chat(owner, span_notice("You have finally broken yourself enough to understand [GLOB.deity]. It's all so clear to you."))
|
||||
dna.add_mutation(/datum/mutation/human/telekinesis)
|
||||
dna.add_mutation(/datum/mutation/human/mindreader)
|
||||
var/mob/living/carbon/human/knower = owner
|
||||
if(!istype(knower))
|
||||
return
|
||||
INVOKE_ASYNC(knower, TYPE_PROC_REF(/mob/living/carbon/human, psykerize))
|
||||
|
||||
/// Signal to decrease burden_level (see update_burden proc) if an organ is added
|
||||
/datum/mutation/human/burdened/proc/organ_added_burden(mob/burdened, obj/item/organ/new_organ, special)
|
||||
/datum/brain_trauma/special/burdened/proc/organ_added_burden(mob/burdened, obj/item/organ/new_organ, special)
|
||||
SIGNAL_HANDLER
|
||||
|
||||
if(special) //aheals
|
||||
@@ -112,10 +131,13 @@
|
||||
if(new_eyes.tint < TINT_BLIND) //unless you added unworking eyes (flashlight eyes), this is removing burden
|
||||
update_burden(FALSE)
|
||||
return
|
||||
update_burden(FALSE)//working organ
|
||||
else if(istype(new_organ, /obj/item/organ/internal/appendix))
|
||||
return
|
||||
|
||||
update_burden(increase = FALSE)//working organ
|
||||
|
||||
/// Signal to increase burden_level (see update_burden proc) if an organ is removed
|
||||
/datum/mutation/human/burdened/proc/organ_removed_burden(mob/burdened, obj/item/organ/old_organ, special)
|
||||
/datum/brain_trauma/special/burdened/proc/organ_removed_burden(mob/burdened, obj/item/organ/old_organ, special)
|
||||
SIGNAL_HANDLER
|
||||
|
||||
if(special) //aheals
|
||||
@@ -125,65 +147,64 @@
|
||||
var/obj/item/organ/internal/eyes/old_eyes = old_organ
|
||||
if(old_eyes.tint < TINT_BLIND) //unless you were already blinded by them (flashlight eyes), this is adding burden!
|
||||
update_burden(TRUE)
|
||||
return
|
||||
else if(istype(old_organ, /obj/item/organ/internal/appendix))
|
||||
return
|
||||
|
||||
update_burden(TRUE)//lost organ
|
||||
update_burden(increase = TRUE)//lost organ
|
||||
|
||||
/// Signal to decrease burden_level (see update_burden proc) if a limb is added
|
||||
/datum/mutation/human/burdened/proc/limbs_added_burden(datum/source, obj/item/bodypart/new_limb, special)
|
||||
/datum/brain_trauma/special/burdened/proc/limbs_added_burden(datum/source, obj/item/bodypart/new_limb, special)
|
||||
SIGNAL_HANDLER
|
||||
|
||||
if(special) //something we don't wanna consider, like instaswapping limbs
|
||||
return
|
||||
update_burden(FALSE)
|
||||
update_burden(increase = FALSE)
|
||||
|
||||
/// Signal to increase burden_level (see update_burden proc) if a limb is removed
|
||||
/datum/mutation/human/burdened/proc/limbs_removed_burden(datum/source, obj/item/bodypart/old_limb, special)
|
||||
/datum/brain_trauma/special/burdened/proc/limbs_removed_burden(datum/source, obj/item/bodypart/old_limb, special)
|
||||
SIGNAL_HANDLER
|
||||
|
||||
if(special) //something we don't wanna consider, like instaswapping limbs
|
||||
return
|
||||
update_burden(TRUE)
|
||||
update_burden(increase = TRUE)
|
||||
|
||||
/// Signal to increase burden_level (see update_burden proc) if an addiction is added
|
||||
/datum/mutation/human/burdened/proc/addict_added_burden(datum/addiction/new_addiction, datum/mind/addict_mind)
|
||||
/datum/brain_trauma/special/burdened/proc/addict_added_burden(datum/addiction/new_addiction, datum/mind/addict_mind)
|
||||
SIGNAL_HANDLER
|
||||
|
||||
update_burden(TRUE)
|
||||
update_burden(increase = TRUE)
|
||||
|
||||
/// Signal to decrease burden_level (see update_burden proc) if an addiction is removed
|
||||
/datum/mutation/human/burdened/proc/addict_removed_burden(datum/addiction/old_addiction, datum/mind/nonaddict_mind)
|
||||
/datum/brain_trauma/special/burdened/proc/addict_removed_burden(datum/addiction/old_addiction, datum/mind/nonaddict_mind)
|
||||
SIGNAL_HANDLER
|
||||
|
||||
update_burden(FALSE)
|
||||
update_burden(increase = FALSE)
|
||||
|
||||
/// Signal to increase burden_level (see update_burden proc) if a mutation is added
|
||||
/datum/mutation/human/burdened/proc/mutation_added_burden(mob/living/carbon/burdened, datum/mutation/human/mutation_type, class)
|
||||
/datum/brain_trauma/special/burdened/proc/mutation_added_burden(mob/living/carbon/burdened, datum/mutation/human/mutation_type, class)
|
||||
SIGNAL_HANDLER
|
||||
|
||||
if(class == MUT_OTHER) //getting a mutation can give a mutation as a reward, which in turn triggers this, which then rewards a mutation, which in turn...
|
||||
return
|
||||
if(initial(mutation_type.quality) == NEGATIVE)
|
||||
update_burden(TRUE)
|
||||
update_burden(increase = TRUE)
|
||||
|
||||
/// Signal to decrease burden_level (see update_burden proc) if a mutation is removed
|
||||
/datum/mutation/human/burdened/proc/mutation_removed_burden(mob/living/carbon/burdened, datum/mutation/human/mutation_type)
|
||||
/datum/brain_trauma/special/burdened/proc/mutation_removed_burden(mob/living/carbon/burdened, datum/mutation/human/mutation_type)
|
||||
SIGNAL_HANDLER
|
||||
|
||||
if(class == MUT_OTHER) //see above
|
||||
return
|
||||
if(initial(mutation_type.quality) == NEGATIVE)
|
||||
update_burden(FALSE)
|
||||
update_burden(increase = FALSE)
|
||||
|
||||
/// Signal to increase burden_level (see update_burden proc) if a trauma is added
|
||||
/datum/mutation/human/burdened/proc/trauma_added_burden(mob/living/carbon/burdened, datum/brain_trauma/trauma_added)
|
||||
/datum/brain_trauma/special/burdened/proc/trauma_added_burden(mob/living/carbon/burdened, datum/brain_trauma/trauma_added)
|
||||
SIGNAL_HANDLER
|
||||
|
||||
if(istype(trauma_added, /datum/brain_trauma/severe))
|
||||
update_burden(TRUE)
|
||||
update_burden(increase = TRUE)
|
||||
|
||||
/// Signal to decrease burden_level (see update_burden proc) if a trauma is removed
|
||||
/datum/mutation/human/burdened/proc/trauma_removed_burden(mob/living/carbon/burdened, datum/brain_trauma/trauma_removed)
|
||||
/datum/brain_trauma/special/burdened/proc/trauma_removed_burden(mob/living/carbon/burdened, datum/brain_trauma/trauma_removed)
|
||||
SIGNAL_HANDLER
|
||||
|
||||
if(istype(trauma_removed, /datum/brain_trauma/severe))
|
||||
update_burden(FALSE)
|
||||
update_burden(increase = FALSE)
|
||||
@@ -0,0 +1,376 @@
|
||||
/obj/item/organ/internal/brain/psyker
|
||||
name = "psyker brain"
|
||||
desc = "This brain is blue, split into two hemispheres, and has immense psychic powers. What kind of monstrosity would use that?"
|
||||
icon_state = "brain-psyker"
|
||||
actions_types = list(
|
||||
/datum/action/cooldown/spell/pointed/psychic_projection,
|
||||
/datum/action/cooldown/spell/charged/psychic_booster,
|
||||
/datum/action/cooldown/spell/forcewall/psychic_wall,
|
||||
)
|
||||
organ_traits = list(TRAIT_ADVANCEDTOOLUSER, TRAIT_LITERATE, TRAIT_CAN_STRIP, TRAIT_ANTIMAGIC_NO_SELFBLOCK)
|
||||
w_class = WEIGHT_CLASS_NORMAL
|
||||
|
||||
/obj/item/organ/internal/brain/psyker/Insert(mob/living/carbon/inserted_into, special, drop_if_replaced, no_id_transfer)
|
||||
. = ..()
|
||||
inserted_into.AddComponent(/datum/component/echolocation, echo_group = "psyker", echo_icon = "psyker", color_path = /datum/client_colour/psyker)
|
||||
inserted_into.AddComponent(/datum/component/anti_magic, antimagic_flags = MAGIC_RESISTANCE_MIND)
|
||||
|
||||
/obj/item/organ/internal/brain/psyker/Remove(mob/living/carbon/removed_from, special, no_id_transfer)
|
||||
. = ..()
|
||||
qdel(removed_from.GetComponent(/datum/component/echolocation))
|
||||
qdel(removed_from.GetComponent(/datum/component/anti_magic))
|
||||
|
||||
/obj/item/organ/internal/brain/psyker/on_life(delta_time, times_fired)
|
||||
. = ..()
|
||||
var/obj/item/bodypart/head/psyker/psyker_head = owner.get_bodypart(zone)
|
||||
if(istype(psyker_head))
|
||||
return
|
||||
if(!DT_PROB(2, delta_time))
|
||||
return
|
||||
to_chat(owner, span_userdanger("Your head hurts... It can't fit your brain!"))
|
||||
owner.adjust_disgust(33 * delta_time)
|
||||
applyOrganDamage(5 * delta_time, 199)
|
||||
owner.adjustOrganLoss(ORGAN_SLOT_BRAIN, 5 * delta_time)
|
||||
|
||||
/obj/item/bodypart/head/psyker
|
||||
limb_id = BODYPART_ID_PSYKER
|
||||
is_dimorphic = FALSE
|
||||
should_draw_greyscale = FALSE
|
||||
bodypart_traits = list(TRAIT_DISFIGURED, TRAIT_BALD, TRAIT_SHAVED, TRAIT_BLIND)
|
||||
|
||||
/obj/item/bodypart/head/psyker/try_attach_limb(mob/living/carbon/new_head_owner, special, abort)
|
||||
. = ..()
|
||||
if(!. || !new_head_owner.dna?.species)
|
||||
return
|
||||
new_head_owner.dna.species.species_traits |= NOEYESPRITES //MAKE VISUALS TIED TO BODYPARTS ARGHH
|
||||
new_head_owner.update_body()
|
||||
|
||||
/// Makes us go through a transform sequency, to turn into a psyker.
|
||||
/mob/living/carbon/human/proc/psykerize()
|
||||
if(stat == DEAD || !get_bodypart(BODY_ZONE_HEAD) || istype(get_bodypart(BODY_ZONE_HEAD), /obj/item/bodypart/head/psyker))
|
||||
return
|
||||
to_chat(src, span_userdanger("You feel unwell..."))
|
||||
sleep(5 SECONDS)
|
||||
if(stat == DEAD || !get_bodypart(BODY_ZONE_HEAD))
|
||||
return
|
||||
to_chat(src, span_userdanger("You feel your skin ripping off!"))
|
||||
emote("scream")
|
||||
apply_damage(30, BRUTE, BODY_ZONE_HEAD)
|
||||
sleep(5 SECONDS)
|
||||
var/obj/item/bodypart/head/old_head = get_bodypart(BODY_ZONE_HEAD)
|
||||
var/obj/item/organ/internal/brain/old_brain = getorganslot(ORGAN_SLOT_BRAIN)
|
||||
var/obj/item/organ/internal/old_eyes = getorganslot(ORGAN_SLOT_EYES)
|
||||
if(stat == DEAD || !old_head || !old_brain)
|
||||
return
|
||||
to_chat(src, span_userdanger("Your head splits open! Your brain mutates!"))
|
||||
new /obj/effect/gibspawner/generic(drop_location(), src)
|
||||
emote("scream")
|
||||
var/obj/item/bodypart/head/psyker/psyker_head = new()
|
||||
psyker_head.receive_damage(brute = 50)
|
||||
if(!psyker_head.replace_limb(src, special = TRUE))
|
||||
return
|
||||
qdel(old_head)
|
||||
var/obj/item/organ/internal/brain/psyker/psyker_brain = new()
|
||||
old_brain.before_organ_replacement(psyker_brain)
|
||||
old_brain.Remove(src, special = TRUE, no_id_transfer = TRUE)
|
||||
qdel(old_brain)
|
||||
psyker_brain.Insert(src, special = TRUE, drop_if_replaced = FALSE)
|
||||
if(old_eyes)
|
||||
qdel(old_eyes)
|
||||
|
||||
/datum/religion_rites/nullrod_transformation
|
||||
name = "Transmogrify"
|
||||
desc = "Your full power needs a firearm to be realized. You may transform your null rod into one."
|
||||
ritual_length = 10 SECONDS
|
||||
///The rod that will be transmogrified.
|
||||
var/obj/item/nullrod/transformation_target
|
||||
|
||||
/datum/religion_rites/nullrod_transformation/perform_rite(mob/living/user, atom/religious_tool)
|
||||
if(!ishuman(user))
|
||||
return FALSE
|
||||
var/mob/living/carbon/human/human_user = user
|
||||
var/datum/brain_trauma/special/burdened/burden = human_user.has_trauma_type(/datum/brain_trauma/special/burdened)
|
||||
if(!burden || burden.burden_level < 9)
|
||||
to_chat(human_user, span_warning("You aren't burdened enough."))
|
||||
return FALSE
|
||||
for(var/obj/item/nullrod/null_rod in get_turf(religious_tool))
|
||||
transformation_target = null_rod
|
||||
return ..()
|
||||
to_chat(human_user, span_warning("You need to place a null rod on [religious_tool] to do this!"))
|
||||
return FALSE
|
||||
|
||||
/datum/religion_rites/nullrod_transformation/invoke_effect(mob/living/user, atom/movable/religious_tool)
|
||||
..()
|
||||
var/obj/item/nullrod/null_rod = transformation_target
|
||||
transformation_target = null
|
||||
if(QDELETED(null_rod) || null_rod.loc != get_turf(religious_tool))
|
||||
to_chat(user, span_warning("Your target left the altar!"))
|
||||
return FALSE
|
||||
to_chat(user, span_warning("[null_rod] turns into a gun!"))
|
||||
user.emote("smile")
|
||||
qdel(null_rod)
|
||||
new /obj/item/gun/ballistic/revolver/chaplain(get_turf(religious_tool))
|
||||
return TRUE
|
||||
|
||||
/obj/item/gun/ballistic/revolver/chaplain
|
||||
name = "chaplain's revolver"
|
||||
desc = "Holy smokes."
|
||||
icon_state = "chaplain"
|
||||
force = 10
|
||||
fire_sound = 'sound/weapons/gun/revolver/shot.ogg'
|
||||
mag_type = /obj/item/ammo_box/magazine/internal/cylinder/rev77
|
||||
obj_flags = UNIQUE_RENAME
|
||||
custom_materials = null
|
||||
actions_types = list(/datum/action/item_action/pray_refill)
|
||||
/// Needs burden level nine to refill.
|
||||
var/needs_burden = TRUE
|
||||
/// List of all possible names and descriptions.
|
||||
var/static/list/possible_names = list(
|
||||
"Requiescat" = "May they rest in peace.",
|
||||
"Requiem" = "They will never reach truth.",
|
||||
"Vade Retro" = "Having a gun might make exorcisms more effective, who knows?",
|
||||
"Extra Nos" = "Salvation is given externally.",
|
||||
"Ordo Salutis" = "First step? Fire.",
|
||||
"Absolution" = "Free of your sins.",
|
||||
"Rod of God" = "Splitting the red sea again.",
|
||||
"Holy Grail" = "You found it!",
|
||||
"Burning Bush" = "Useful for any burning ambush.",
|
||||
"Judgement" = "First of all, damn. Alpha much? Dude, so cool, and so are you! Strong, too!",
|
||||
"Paradiso" = "A divine end to the comedy of life.",
|
||||
"DVNO" = "Don't need to ask my name to figure out how cool I am.",
|
||||
"Venus Supermax" = "Did you know nearly everyone working and living on Venus is involved in sulfur extraction? Quite fitting for this weapon of gunpowder.",
|
||||
"Nirvana" = "The giver of quietude, freedom, and highest happiness.",
|
||||
"Cerebrum Dispersio" = "Latin for \"brain splitting\". How fitting.",
|
||||
"Ultimort" = "Your hope dies last.",
|
||||
"Lifelight" = "No escape, no greater fate to be made.",
|
||||
"Bendbreaker" = "FRAGILE: Please do not bend or break.",
|
||||
"Pop Pop" = "The name referring to an onomatopeia (phonetic imitation) of a gun firing.",
|
||||
"Justice" = "Justice is Splendor.",
|
||||
"Splendor" = "Splendor is Justice.",
|
||||
"Revelation" = "Awaken your faith.",
|
||||
"New Safety M62" = "This model of firearm is popular hundreds of years later due to masculine associations created by the film industry.",
|
||||
"Unmaker" = "What the !@#%* is this!",
|
||||
"INKVD" = "Savior of the soul and fighter against dirty thoughts.",
|
||||
"Life Leech" = "An artifact said to draw its power from the life energy of others.",
|
||||
"Nullray" = "Starless metal on the barrel imbibes light and routes it to the null place. The grip acrylic is patterned after ley lines.",
|
||||
"Mortis" = "Put your faith into this weapon working.",
|
||||
"Ramiel" = "Literally meaning \"God has thundered\". You could even interpret the gunshot as a thunder.",
|
||||
"Daredevil" = "Hey now, you won't be reckless with this, will you?",
|
||||
"Lacytanga" = "Rules are written by the strong.",
|
||||
"A10" = "The fist of God. Keep away from the terrible.",
|
||||
)
|
||||
|
||||
/obj/item/gun/ballistic/revolver/chaplain/Initialize(mapload)
|
||||
. = ..()
|
||||
AddComponent(/datum/component/anti_magic, MAGIC_RESISTANCE_HOLY)
|
||||
name = pick(possible_names)
|
||||
desc = possible_names[name]
|
||||
|
||||
/obj/item/gun/ballistic/revolver/chaplain/suicide_act(mob/living/user)
|
||||
. = ..()
|
||||
name = "Habemus Papam"
|
||||
desc = "I announce to you a great joy."
|
||||
|
||||
/obj/item/gun/ballistic/revolver/chaplain/attack_self(mob/living/user)
|
||||
pray_refill(user)
|
||||
|
||||
/obj/item/gun/ballistic/revolver/chaplain/proc/pray_refill(mob/living/carbon/human/user)
|
||||
if(DOING_INTERACTION_WITH_TARGET(user, src) || !istype(user))
|
||||
return
|
||||
var/datum/brain_trauma/special/burdened/burden = user.has_trauma_type(/datum/brain_trauma/special/burdened)
|
||||
if(needs_burden && (!burden || burden.burden_level < 9))
|
||||
to_chat(user, span_warning("You aren't burdened enough."))
|
||||
return
|
||||
user.manual_emote("presses [user.p_their()] palms together...")
|
||||
if(!do_after(user, 5 SECONDS, src))
|
||||
balloon_alert(user, "interrupted!")
|
||||
return
|
||||
user.say("#Oh great [GLOB.deity], give me the ammunition I need!", forced = "ammo prayer")
|
||||
magazine.top_off()
|
||||
user.playsound_local(get_turf(src), 'sound/magic/magic_block_holy.ogg', 50, TRUE)
|
||||
chamber_round()
|
||||
|
||||
/datum/action/item_action/pray_refill
|
||||
name = "Refill"
|
||||
desc = "Perform a prayer, to refill your weapon."
|
||||
|
||||
/obj/item/ammo_box/magazine/internal/cylinder/rev77
|
||||
name = "chaplain revolver cylinder"
|
||||
ammo_type = /obj/item/ammo_casing/c77
|
||||
caliber = CALIBER_77
|
||||
max_ammo = 5
|
||||
|
||||
/obj/item/ammo_casing/c77
|
||||
name = ".77 bullet casing"
|
||||
desc = "A .77 bullet casing."
|
||||
caliber = CALIBER_77
|
||||
projectile_type = /obj/projectile/bullet/c77
|
||||
custom_materials = null
|
||||
|
||||
/obj/projectile/bullet/c77
|
||||
name = ".77 bullet"
|
||||
damage = 18
|
||||
ricochets_max = 2
|
||||
ricochet_chance = 50
|
||||
ricochet_auto_aim_angle = 10
|
||||
ricochet_auto_aim_range = 3
|
||||
wound_bonus = -10
|
||||
embedding = null
|
||||
|
||||
/datum/action/cooldown/spell/pointed/psychic_projection
|
||||
name = "Psychic Projection"
|
||||
desc = "Project your psychics into a target to warp their view, and instill absolute terror that will cause them to fire their gun rapidly."
|
||||
ranged_mousepointer = 'icons/effects/mouse_pointers/cult_target.dmi'
|
||||
button_icon_state = "blind"
|
||||
school = SCHOOL_HOLY
|
||||
cooldown_time = 1 MINUTES
|
||||
antimagic_flags = MAGIC_RESISTANCE_MIND
|
||||
spell_max_level = 1
|
||||
invocation_type = INVOCATION_NONE
|
||||
spell_requirements = SPELL_REQUIRES_NO_ANTIMAGIC
|
||||
cast_range = 5
|
||||
active_msg = "You prepare to psychically project to a target..."
|
||||
/// Duration of the effects.
|
||||
var/projection_duration = 10 SECONDS
|
||||
|
||||
/datum/action/cooldown/spell/pointed/psychic_projection/is_valid_target(atom/cast_on)
|
||||
. = ..()
|
||||
if(!.)
|
||||
return FALSE
|
||||
if(!isliving(cast_on))
|
||||
return FALSE
|
||||
var/mob/living/living_target = cast_on
|
||||
return !living_target.has_status_effect(/datum/status_effect/psychic_projection)
|
||||
|
||||
/datum/action/cooldown/spell/pointed/psychic_projection/cast(mob/living/cast_on)
|
||||
. = ..()
|
||||
if(cast_on.can_block_magic(antimagic_flags))
|
||||
to_chat(cast_on, span_notice("Your mind feels weird, but it passes momentarily."))
|
||||
to_chat(owner, span_warning("The spell had no effect!"))
|
||||
return FALSE
|
||||
to_chat(cast_on, span_userdanger("Your mind gets twisted!"))
|
||||
cast_on.emote("scream")
|
||||
cast_on.apply_status_effect(/datum/status_effect/psychic_projection, projection_duration)
|
||||
return TRUE
|
||||
|
||||
/// Status effect that adds a weird view to its owner and causes them to rapidly shoot a firearm in their general direction.
|
||||
/datum/status_effect/psychic_projection
|
||||
id = "psychic_projection"
|
||||
alert_type = null
|
||||
remove_on_fullheal = TRUE
|
||||
tick_interval = 0.1 SECONDS
|
||||
/// Times the target has dry fired a weapon.
|
||||
var/times_dry_fired = 0
|
||||
/// Needs to reach times_dry_fired for the next dry fire to happen.
|
||||
var/firing_delay = 0
|
||||
|
||||
/datum/status_effect/psychic_projection/on_creation(mob/living/new_owner, duration = 10 SECONDS)
|
||||
src.duration = duration
|
||||
return ..()
|
||||
|
||||
/datum/status_effect/psychic_projection/on_apply()
|
||||
var/atom/movable/plane_master_controller/game_plane_master_controller = owner.hud_used?.plane_master_controllers[PLANE_MASTERS_GAME]
|
||||
if(!game_plane_master_controller)
|
||||
return FALSE
|
||||
game_plane_master_controller.add_filter("psychic_wave", 10, wave_filter(240, 240, 3, 0, WAVE_SIDEWAYS))
|
||||
game_plane_master_controller.add_filter("psychic_blur", 10, angular_blur_filter(0, 0, 3))
|
||||
return TRUE
|
||||
|
||||
/datum/status_effect/psychic_projection/on_remove()
|
||||
var/atom/movable/plane_master_controller/game_plane_master_controller = owner.hud_used?.plane_master_controllers[PLANE_MASTERS_GAME]
|
||||
if(!game_plane_master_controller)
|
||||
return
|
||||
game_plane_master_controller.remove_filter("psychic_blur")
|
||||
game_plane_master_controller.remove_filter("psychic_wave")
|
||||
|
||||
/datum/status_effect/psychic_projection/tick(delta_time, times_fired)
|
||||
var/obj/item/gun/held_gun = owner?.is_holding_item_of_type(/obj/item/gun)
|
||||
if(!held_gun)
|
||||
return
|
||||
if(!held_gun.can_shoot())
|
||||
if(firing_delay < times_dry_fired)
|
||||
firing_delay++
|
||||
return
|
||||
firing_delay = 0
|
||||
times_dry_fired++
|
||||
else
|
||||
times_dry_fired = 0
|
||||
var/turf/target_turf = get_offset_target_turf(get_ranged_target_turf(owner, owner.dir, 7), dx = rand(-1, 1), dy = rand(-1, 1))
|
||||
held_gun.process_fire(target_turf, owner, TRUE, null, pick(BODY_ZONE_HEAD, BODY_ZONE_CHEST, BODY_ZONE_R_ARM, BODY_ZONE_L_ARM, BODY_ZONE_R_LEG, BODY_ZONE_L_LEG))
|
||||
held_gun.semicd = FALSE
|
||||
|
||||
/datum/action/cooldown/spell/charged/psychic_booster
|
||||
name = "Psychic Booster"
|
||||
desc = "Charge up your mind to shoot firearms faster and home in on your targets. Think smarter, not harder."
|
||||
button_icon_state = "projectile"
|
||||
sound = 'sound/weapons/gun/shotgun/rack.ogg'
|
||||
school = SCHOOL_HOLY
|
||||
cooldown_time = 1 MINUTES
|
||||
antimagic_flags = MAGIC_RESISTANCE_MIND
|
||||
spell_max_level = 1
|
||||
invocation_type = INVOCATION_NONE
|
||||
spell_requirements = SPELL_REQUIRES_NO_ANTIMAGIC
|
||||
channel_message = span_notice("You focus on your trigger fingers...")
|
||||
charge_overlay_icon = 'icons/effects/effects.dmi'
|
||||
charge_overlay_state = "purplesparkles"
|
||||
channel_time = 5 SECONDS
|
||||
/// Are we currently active?
|
||||
var/boosted = FALSE
|
||||
/// How long the effect lasts for?
|
||||
var/effect_time = 10 SECONDS
|
||||
|
||||
/datum/action/cooldown/spell/charged/psychic_booster/Destroy()
|
||||
if(boosted)
|
||||
stop_effects()
|
||||
return ..()
|
||||
|
||||
/datum/action/cooldown/spell/charged/psychic_booster/Remove(mob/living/remove_from)
|
||||
if(boosted)
|
||||
stop_effects()
|
||||
return ..()
|
||||
|
||||
/datum/action/cooldown/spell/charged/psychic_booster/cast(atom/cast_on)
|
||||
. = ..()
|
||||
if(boosted)
|
||||
return
|
||||
boosted = TRUE
|
||||
to_chat(owner, span_boldnotice("Your trigger fingers feel stronger."))
|
||||
ADD_TRAIT(cast_on, TRAIT_DOUBLE_TAP, type)
|
||||
RegisterSignal(cast_on, COMSIG_PROJECTILE_FIRER_BEFORE_FIRE, PROC_REF(modify_projectile))
|
||||
addtimer(CALLBACK(src, PROC_REF(stop_effects)), effect_time)
|
||||
|
||||
/datum/action/cooldown/spell/charged/psychic_booster/proc/stop_effects()
|
||||
boosted = FALSE
|
||||
to_chat(owner, span_danger("Your trigger fingers feel weaker."))
|
||||
REMOVE_TRAIT(owner, TRAIT_DOUBLE_TAP, type)
|
||||
UnregisterSignal(owner, COMSIG_PROJECTILE_FIRER_BEFORE_FIRE)
|
||||
|
||||
/datum/action/cooldown/spell/charged/psychic_booster/proc/modify_projectile(datum/source, obj/projectile/bullet, atom/firer, atom/original_target)
|
||||
var/atom/target = original_target
|
||||
if(isturf(target) || (isobj(target) && !target.density)) //if weird target, we try to compensate in our homing
|
||||
for(var/mob/living/shooting_target in range(1, get_turf(target)))
|
||||
if(shooting_target == firer)
|
||||
continue
|
||||
target = shooting_target
|
||||
break
|
||||
if(!bullet.can_hit_target(target, direct_target = TRUE, ignore_loc = TRUE))
|
||||
return
|
||||
bullet.original = target
|
||||
bullet.homing_turn_speed = 30
|
||||
bullet.set_homing_target(target)
|
||||
|
||||
/datum/action/cooldown/spell/forcewall/psychic_wall
|
||||
name = "Psychic Wall"
|
||||
desc = "Form a psychic wall, able to deflect projectiles and prevent things from going through."
|
||||
school = SCHOOL_HOLY
|
||||
cooldown_time = 30 SECONDS
|
||||
cooldown_reduction_per_rank = 0 SECONDS
|
||||
antimagic_flags = MAGIC_RESISTANCE_MIND
|
||||
spell_requirements = SPELL_REQUIRES_NO_ANTIMAGIC
|
||||
spell_max_level = 1
|
||||
invocation_type = INVOCATION_NONE
|
||||
wall_type = /obj/effect/forcefield/psychic
|
||||
|
||||
/datum/action/cooldown/spell/forcewall/psychic_wall/spawn_wall(turf/cast_turf)
|
||||
. = ..()
|
||||
play_fov_effect(cast_turf, 5, "forcefield", time = 10 SECONDS)
|
||||
@@ -0,0 +1,174 @@
|
||||
///Makes the person holy, but they now also have to follow the honorbound code (CBT). Actually earns favor, convincing others to uphold the code (tm) is not easy
|
||||
/datum/religion_rites/deaconize
|
||||
name = "Join Crusade"
|
||||
desc = "Converts someone to your sect. They must be willing, so the first invocation will instead prompt them to join. \
|
||||
They will become honorbound like you, and you will gain a massive favor boost!"
|
||||
ritual_length = 30 SECONDS
|
||||
ritual_invocations = list(
|
||||
"A good, honorable crusade against evil is required.",
|
||||
"We need the righteous ...",
|
||||
"... the unflinching ...",
|
||||
"... and the just.",
|
||||
"Sinners must be silenced ...",
|
||||
)
|
||||
invoke_msg = "... And the code must be upheld!"
|
||||
///the invited crusader
|
||||
var/mob/living/carbon/human/new_crusader
|
||||
|
||||
/datum/religion_rites/deaconize/perform_rite(mob/living/user, atom/religious_tool)
|
||||
var/datum/religion_sect/honorbound/sect = GLOB.religious_sect
|
||||
if(!ismovable(religious_tool))
|
||||
to_chat(user, span_warning("This rite requires a religious device that individuals can be buckled to."))
|
||||
return FALSE
|
||||
var/atom/movable/movable_reltool = religious_tool
|
||||
if(!movable_reltool)
|
||||
return FALSE
|
||||
if(!LAZYLEN(movable_reltool.buckled_mobs))
|
||||
to_chat(user, span_warning("Nothing is buckled to the altar!"))
|
||||
return FALSE
|
||||
for(var/mob/living/carbon/human/possible_crusader in movable_reltool.buckled_mobs)
|
||||
if(possible_crusader.stat != CONSCIOUS)
|
||||
to_chat(user, span_warning("[possible_crusader] needs to be alive and conscious to join the crusade!"))
|
||||
return FALSE
|
||||
if(TRAIT_GENELESS in possible_crusader.dna.species.inherent_traits)
|
||||
to_chat(user, span_warning("This species disgusts [GLOB.deity]! They would never be allowed to join the crusade!"))
|
||||
return FALSE
|
||||
if(possible_crusader in sect.currently_asking)
|
||||
to_chat(user, span_warning("Wait for them to decide on whether to join or not!"))
|
||||
return FALSE
|
||||
if(!(possible_crusader in sect.possible_crusaders))
|
||||
INVOKE_ASYNC(sect, /datum/religion_sect/honorbound.proc/invite_crusader, possible_crusader)
|
||||
to_chat(user, span_notice("They have been given the option to consider joining the crusade against evil. Wait for them to decide and try again."))
|
||||
return FALSE
|
||||
new_crusader = possible_crusader
|
||||
return ..()
|
||||
|
||||
/datum/religion_rites/deaconize/invoke_effect(mob/living/carbon/human/user, atom/movable/religious_tool)
|
||||
..()
|
||||
var/mob/living/carbon/human/joining_now = new_crusader
|
||||
new_crusader = null
|
||||
if(!(joining_now in religious_tool.buckled_mobs)) //checks one last time if the right corpse is still buckled
|
||||
to_chat(user, span_warning("The new member is no longer on the altar!"))
|
||||
return FALSE
|
||||
if(joining_now.stat != CONSCIOUS)
|
||||
to_chat(user, span_warning("The new member has to stay alive for the rite to work!"))
|
||||
return FALSE
|
||||
if(!joining_now.mind)
|
||||
to_chat(user, span_warning("The new member has no mind!"))
|
||||
return FALSE
|
||||
if(joining_now.mind.has_antag_datum(/datum/antagonist/cult))//what the fuck?!
|
||||
to_chat(user, span_warning("[GLOB.deity] has seen a true, dark evil in [joining_now]'s heart, and they have been smitten!"))
|
||||
playsound(get_turf(religious_tool), 'sound/effects/pray.ogg', 50, TRUE)
|
||||
joining_now.gib(TRUE)
|
||||
return FALSE
|
||||
var/datum/brain_trauma/special/honorbound/honor = user.has_trauma_type(/datum/brain_trauma/special/honorbound)
|
||||
if(joining_now in honor.guilty)
|
||||
honor.guilty -= joining_now
|
||||
GLOB.religious_sect.adjust_favor(200, user)
|
||||
to_chat(user, span_notice("[GLOB.deity] has bound [joining_now] to the code! They are now a holy role! (albeit the lowest level of such)"))
|
||||
joining_now.mind.holy_role = HOLY_ROLE_DEACON
|
||||
GLOB.religious_sect.on_conversion(joining_now)
|
||||
playsound(get_turf(religious_tool), 'sound/effects/pray.ogg', 50, TRUE)
|
||||
return TRUE
|
||||
|
||||
///Mostly useless funny rite for forgiving someone, making them innocent once again.
|
||||
/datum/religion_rites/forgive
|
||||
name = "Forgive"
|
||||
desc = "Forgives someone, making them no longer considered guilty. A kind gesture, all things considered!"
|
||||
invoke_msg = "You are absolved of sin."
|
||||
var/mob/living/who
|
||||
|
||||
/datum/religion_rites/forgive/perform_rite(mob/living/carbon/human/user, atom/religious_tool)
|
||||
if(!ishuman(user))
|
||||
return FALSE
|
||||
var/datum/brain_trauma/special/honorbound/honor = user.has_trauma_type(/datum/brain_trauma/special/honorbound)
|
||||
if(!honor)
|
||||
return FALSE
|
||||
if(!length(honor.guilty))
|
||||
to_chat(user, span_warning("[GLOB.deity] is holding no grudges to forgive."))
|
||||
return FALSE
|
||||
var/forgiven_choice = tgui_input_list(user, "Choose one of [GLOB.deity]'s guilty to forgive", "Forgive", honor.guilty)
|
||||
if(isnull(forgiven_choice))
|
||||
return FALSE
|
||||
who = forgiven_choice
|
||||
return ..()
|
||||
|
||||
/datum/religion_rites/forgive/invoke_effect(mob/living/carbon/human/user, atom/movable/religious_tool)
|
||||
..()
|
||||
if(in_range(user, religious_tool))
|
||||
return FALSE
|
||||
var/datum/brain_trauma/special/honorbound/honor = user.has_trauma_type(/datum/brain_trauma/special/honorbound)
|
||||
if(!honor) //edge case
|
||||
return FALSE
|
||||
honor.guilty -= who
|
||||
who = null
|
||||
playsound(get_turf(religious_tool), 'sound/effects/pray.ogg', 50, TRUE)
|
||||
return TRUE
|
||||
|
||||
/datum/religion_rites/summon_rules
|
||||
name = "Summon Honorbound Rules"
|
||||
desc = "Enscribes a paper with the honorbound rules and regulations."
|
||||
invoke_msg = "Bring forth the holy writ!"
|
||||
///paper to turn into holy writ
|
||||
var/obj/item/paper/writ_target
|
||||
|
||||
/datum/religion_rites/summon_rules/perform_rite(mob/living/user, atom/religious_tool)
|
||||
for(var/obj/item/paper/could_writ in get_turf(religious_tool))
|
||||
if(istype(could_writ, /obj/item/paper/holy_writ))
|
||||
continue
|
||||
if(could_writ.get_total_length()) //blank paper pls
|
||||
continue
|
||||
writ_target = could_writ //PLEASE SIGN MY AUTOGRAPH
|
||||
return ..()
|
||||
to_chat(user, span_warning("You need to place blank paper on [religious_tool] to do this!"))
|
||||
return FALSE
|
||||
|
||||
/datum/religion_rites/summon_rules/invoke_effect(mob/living/user, atom/movable/religious_tool)
|
||||
..()
|
||||
var/obj/item/paper/autograph = writ_target
|
||||
var/turf/tool_turf = get_turf(religious_tool)
|
||||
writ_target = null
|
||||
if(QDELETED(autograph) || !(tool_turf == autograph.loc)) //check if the same food is still there
|
||||
to_chat(user, span_warning("Your target left the altar!"))
|
||||
return FALSE
|
||||
autograph.visible_message(span_notice("Words magically form on [autograph]!"))
|
||||
playsound(tool_turf, 'sound/effects/pray.ogg', 50, TRUE)
|
||||
new /obj/item/paper/holy_writ(tool_turf)
|
||||
qdel(autograph)
|
||||
return TRUE
|
||||
|
||||
/obj/item/paper/holy_writ
|
||||
icon = 'icons/obj/wizard.dmi'
|
||||
icon_state = "scroll"
|
||||
slot_flags = null
|
||||
show_written_words = FALSE
|
||||
|
||||
//info set in here because we need GLOB.deity
|
||||
/obj/item/paper/holy_writ/Initialize(mapload)
|
||||
add_filter("holy_outline", 9, list("type" = "outline", "color" = "#fdff6c"))
|
||||
name = "[GLOB.deity]'s honorbound rules"
|
||||
default_raw_text = {"[GLOB.deity]'s honorbound rules:
|
||||
<br>
|
||||
1.) Thou shalt not attack the unready!<br>
|
||||
Those who are not ready for battle should not be wrought low. The evil of this world must lose
|
||||
in a fair battle if you are to conquer them completely.
|
||||
<br>
|
||||
<br>
|
||||
2.) Thou shalt not attack the just!<br>
|
||||
Those who fight for justice and good must not be harmed. Security is uncorruptable and must
|
||||
be respected. Healers are mostly uncorruptable and if you are truly sure Medical has fallen
|
||||
to the scourge of evil, use a declaration of evil.
|
||||
<br>
|
||||
<br>
|
||||
3.) Thou shalt not attack the innocent!<br>
|
||||
There is no honor on a pre-emptive strike, unless they are truly evil vermin.
|
||||
Those who are guilty will either lay a hand on you first, or you may declare their evil.
|
||||
<br>
|
||||
<br>
|
||||
4.) Thou shalt not use profane magicks!<br>
|
||||
You are not a warlock, you are an honorable warrior. There is nothing more corruptive than
|
||||
the vile magicks used by witches, warlocks, and necromancers. There are exceptions to this rule.<br>
|
||||
You may use holy magic, and, if you recruit one, the mime may use holy mimery. Restoration has also
|
||||
been allowed as it is a school focused on the light and mending of this world.
|
||||
"}
|
||||
return ..()
|
||||
@@ -1,21 +1,14 @@
|
||||
|
||||
///Honorbound prevents you from attacking the unready, the just, or the innocent
|
||||
/datum/mutation/human/honorbound
|
||||
name = "Honorbound"
|
||||
desc = "Less of a genome and more of a forceful rewrite of genes. Nothing Nanotrasen supplies allows for a genetic restructure like this... \
|
||||
The user feels compelled to follow supposed \"rules of combat\" but in reality they physically are unable to. \
|
||||
Their brain is rewired to excuse any curious inabilities that arise from this odd effect."
|
||||
quality = POSITIVE //so it gets carried over on revives
|
||||
power_path = /datum/action/cooldown/spell/pointed/declare_evil
|
||||
locked = TRUE
|
||||
text_gain_indication = "<span class='notice'>You feel honorbound!</span>"
|
||||
text_lose_indication = "<span class='warning'>You feel unshackled from your code of honor!</span>"
|
||||
/datum/brain_trauma/special/honorbound
|
||||
name = "Dogmatic Compulsions"
|
||||
desc = "Patient feels compelled to follow supposed \"rules of combat\"."
|
||||
scan_desc = "damaged frontal lobe"
|
||||
gain_text = span_notice("You feel honorbound!")
|
||||
lose_text = span_warning("You feel unshackled from your code of honor!")
|
||||
/// list of guilty people
|
||||
var/list/guilty = list()
|
||||
|
||||
/datum/mutation/human/honorbound/on_acquiring(mob/living/carbon/human/owner)
|
||||
if(..())
|
||||
return
|
||||
/datum/brain_trauma/special/honorbound/on_gain()
|
||||
//moodlet
|
||||
owner.add_mood_event("honorbound", /datum/mood_event/honorbound)
|
||||
//checking spells cast by honorbound
|
||||
@@ -31,8 +24,11 @@
|
||||
|
||||
//signal that checks for dishonorable attacks
|
||||
RegisterSignal(owner, COMSIG_MOB_CLICKON, PROC_REF(attack_honor))
|
||||
var/datum/action/cooldown/spell/pointed/declare_evil = new(src)
|
||||
declare_evil.Grant(owner)
|
||||
return ..()
|
||||
|
||||
/datum/mutation/human/honorbound/on_losing(mob/living/carbon/human/owner)
|
||||
/datum/brain_trauma/special/honorbound/on_lose(silent)
|
||||
owner.clear_mood_event("honorbound")
|
||||
UnregisterSignal(owner, list(
|
||||
COMSIG_PARENT_ATTACKBY,
|
||||
@@ -44,11 +40,11 @@
|
||||
COMSIG_MOB_CLICKON,
|
||||
COMSIG_MOB_CAST_SPELL,
|
||||
COMSIG_MOB_FIRED_GUN,
|
||||
))
|
||||
. = ..()
|
||||
))
|
||||
return ..()
|
||||
|
||||
/// Signal to see if the mutation allows us to attack a target
|
||||
/datum/mutation/human/honorbound/proc/attack_honor(mob/living/carbon/human/honorbound, atom/clickingon, list/modifiers)
|
||||
/// Signal to see if the trauma allows us to attack a target
|
||||
/datum/brain_trauma/special/honorbound/proc/attack_honor(mob/living/carbon/human/honorbound, atom/clickingon, list/modifiers)
|
||||
SIGNAL_HANDLER
|
||||
|
||||
if(modifiers[ALT_CLICK] || modifiers[SHIFT_CLICK] || modifiers[CTRL_CLICK] || modifiers[MIDDLE_CLICK])
|
||||
@@ -69,14 +65,14 @@
|
||||
return (COMSIG_MOB_CANCEL_CLICKON)
|
||||
|
||||
/**
|
||||
* Called by hooked signals whenever someone attacks the person with this mutation
|
||||
* Called by hooked signals whenever someone attacks the person with this trauma
|
||||
* Checks if the attacker should be considered guilty and adds them to the guilty list if true
|
||||
*
|
||||
* Arguments:
|
||||
* * user: person who attacked the honorbound
|
||||
* * declaration: if this wasn't an attack, but instead the honorbound spending favor on declaring this person guilty
|
||||
*/
|
||||
/datum/mutation/human/honorbound/proc/guilty(mob/living/user, declaration = FALSE)
|
||||
/datum/brain_trauma/special/honorbound/proc/guilty(mob/living/user, declaration = FALSE)
|
||||
if(user in guilty)
|
||||
return
|
||||
var/datum/mind/guilty_conscience = user.mind
|
||||
@@ -95,10 +91,10 @@
|
||||
* Called by attack_honor signal to check whether an attack should be allowed or not
|
||||
*
|
||||
* Arguments:
|
||||
* * honorbound_human: typecasted owner of mutation
|
||||
* * honorbound_human: typecasted owner of the trauma
|
||||
* * target_creature: person honorbound_human is attacking
|
||||
*/
|
||||
/datum/mutation/human/honorbound/proc/is_honorable(mob/living/carbon/human/honorbound_human, mob/living/target_creature)
|
||||
/datum/brain_trauma/special/honorbound/proc/is_honorable(mob/living/carbon/human/honorbound_human, mob/living/target_creature)
|
||||
var/is_guilty = (target_creature in guilty)
|
||||
//THE UNREADY (Applies over ANYTHING else!)
|
||||
if(honorbound_human == target_creature)
|
||||
@@ -124,25 +120,25 @@
|
||||
return TRUE
|
||||
|
||||
// SIGNALS THAT ARE FOR BEING ATTACKED FIRST (GUILTY)
|
||||
/datum/mutation/human/honorbound/proc/attackby_guilt(datum/source, obj/item/I, mob/attacker)
|
||||
/datum/brain_trauma/special/honorbound/proc/attackby_guilt(datum/source, obj/item/I, mob/attacker)
|
||||
SIGNAL_HANDLER
|
||||
if(I.force && I.damtype != STAMINA)
|
||||
guilty(attacker)
|
||||
|
||||
/datum/mutation/human/honorbound/proc/hulk_guilt(datum/source, mob/attacker)
|
||||
/datum/brain_trauma/special/honorbound/proc/hulk_guilt(datum/source, mob/attacker)
|
||||
SIGNAL_HANDLER
|
||||
guilty(attacker)
|
||||
|
||||
/datum/mutation/human/honorbound/proc/hand_guilt(datum/source, mob/living/attacker)
|
||||
/datum/brain_trauma/special/honorbound/proc/hand_guilt(datum/source, mob/living/attacker)
|
||||
SIGNAL_HANDLER
|
||||
if(attacker.combat_mode)
|
||||
guilty(attacker)
|
||||
|
||||
/datum/mutation/human/honorbound/proc/paw_guilt(datum/source, mob/living/attacker)
|
||||
/datum/brain_trauma/special/honorbound/proc/paw_guilt(datum/source, mob/living/attacker)
|
||||
SIGNAL_HANDLER
|
||||
guilty(attacker)
|
||||
|
||||
/datum/mutation/human/honorbound/proc/bullet_guilt(datum/source, obj/projectile/proj)
|
||||
/datum/brain_trauma/special/honorbound/proc/bullet_guilt(datum/source, obj/projectile/proj)
|
||||
SIGNAL_HANDLER
|
||||
var/mob/living/shot_honorbound = source
|
||||
var/static/list/guilty_projectiles = typecacheof(list(
|
||||
@@ -157,7 +153,7 @@
|
||||
if(!proj.nodamage && proj.damage < shot_honorbound.health && isliving(proj.firer))
|
||||
guilty(proj.firer)
|
||||
|
||||
/datum/mutation/human/honorbound/proc/thrown_guilt(datum/source, atom/movable/thrown_movable, skipcatch = FALSE, hitpush = TRUE, blocked = FALSE, datum/thrownthing/throwingdatum)
|
||||
/datum/brain_trauma/special/honorbound/proc/thrown_guilt(datum/source, atom/movable/thrown_movable, skipcatch = FALSE, hitpush = TRUE, blocked = FALSE, datum/thrownthing/throwingdatum)
|
||||
SIGNAL_HANDLER
|
||||
if(isitem(thrown_movable))
|
||||
var/mob/living/honorbound = source
|
||||
@@ -167,11 +163,11 @@
|
||||
guilty(thrown_by)
|
||||
|
||||
//spell checking
|
||||
/datum/mutation/human/honorbound/proc/spell_check(mob/user, datum/action/cooldown/spell/spell_cast)
|
||||
/datum/brain_trauma/special/honorbound/proc/spell_check(mob/user, datum/action/cooldown/spell/spell_cast)
|
||||
SIGNAL_HANDLER
|
||||
punishment(user, spell_cast.school)
|
||||
|
||||
/datum/mutation/human/honorbound/proc/staff_check(mob/user, obj/item/gun/gun_fired, target, params, zone_override)
|
||||
/datum/brain_trauma/special/honorbound/proc/staff_check(mob/user, obj/item/gun/gun_fired, target, params, zone_override)
|
||||
SIGNAL_HANDLER
|
||||
if(!istype(gun_fired, /obj/item/gun/magic))
|
||||
return
|
||||
@@ -182,19 +178,19 @@
|
||||
* Called when a spell is casted or a magic gun is fired, checks the signal and punishes accordingly
|
||||
*
|
||||
* Arguments:
|
||||
* * user: typecasted owner of mutation
|
||||
* * user: typecasted owner of trauma
|
||||
* * school: school of magic casted from the staff/spell
|
||||
*/
|
||||
/datum/mutation/human/honorbound/proc/punishment(mob/living/carbon/human/user, school)
|
||||
/datum/brain_trauma/special/honorbound/proc/punishment(mob/living/carbon/human/user, school)
|
||||
switch(school)
|
||||
if(SCHOOL_HOLY, SCHOOL_MIME, SCHOOL_RESTORATION)
|
||||
return
|
||||
if(SCHOOL_NECROMANCY, SCHOOL_FORBIDDEN, SCHOOL_SANGUINE)
|
||||
to_chat(user, span_userdanger("[GLOB.deity] is enraged by your use of forbidden magic!"))
|
||||
lightningbolt(user)
|
||||
owner.add_mood_event("honorbound", /datum/mood_event/banished)
|
||||
user.dna.remove_mutation(/datum/mutation/human/honorbound)
|
||||
user.mind.holy_role = NONE
|
||||
qdel(src)
|
||||
owner.add_mood_event("honorbound", /datum/mood_event/banished) //add mood event after we already cleared our events
|
||||
to_chat(user, span_userdanger("You have been excommunicated! You are no longer holy!"))
|
||||
else
|
||||
to_chat(user, span_userdanger("[GLOB.deity] is angered by your use of [school] magic!"))
|
||||
@@ -219,8 +215,8 @@
|
||||
|
||||
/// The amount of favor required to declare on someone
|
||||
var/required_favor = 150
|
||||
/// A ref to our owner's honorbound mutation
|
||||
var/datum/mutation/human/honorbound/honor_mutation
|
||||
/// A ref to our owner's honorbound trauma
|
||||
var/datum/brain_trauma/special/honorbound/honor_trauma
|
||||
/// The declaration that's shouted in invocation. Set in New()
|
||||
var/declaration = "By the divine light of my deity, you are an evil of this world that must be wrought low!"
|
||||
|
||||
@@ -230,9 +226,9 @@
|
||||
|
||||
/datum/action/cooldown/spell/pointed/declare_evil/Destroy()
|
||||
// If we had an owner, Destroy() called Remove(), and already handled this
|
||||
if(honor_mutation)
|
||||
UnregisterSignal(honor_mutation, COMSIG_PARENT_QDELETING)
|
||||
honor_mutation = null
|
||||
if(honor_trauma)
|
||||
UnregisterSignal(honor_trauma, COMSIG_PARENT_QDELETING)
|
||||
honor_trauma = null
|
||||
return ..()
|
||||
|
||||
/datum/action/cooldown/spell/pointed/declare_evil/Grant(mob/grant_to)
|
||||
@@ -240,21 +236,21 @@
|
||||
return FALSE
|
||||
|
||||
var/mob/living/carbon/human/human_owner = grant_to
|
||||
var/datum/mutation/human/honorbound/honor_mut = human_owner.dna?.check_mutation(/datum/mutation/human/honorbound)
|
||||
if(QDELETED(honor_mut))
|
||||
var/datum/brain_trauma/special/honorbound/honorbound = human_owner.has_trauma_type(/datum/brain_trauma/special/honorbound)
|
||||
if(QDELETED(honorbound))
|
||||
return FALSE
|
||||
|
||||
RegisterSignal(honor_mut, COMSIG_PARENT_QDELETING, PROC_REF(on_honor_mutation_lost))
|
||||
honor_mutation = honor_mut
|
||||
RegisterSignal(honorbound, COMSIG_PARENT_QDELETING, PROC_REF(on_honor_trauma_lost))
|
||||
honor_trauma = honorbound
|
||||
return ..()
|
||||
|
||||
/datum/action/cooldown/spell/pointed/declare_evil/Remove(mob/living/remove_from)
|
||||
. = ..()
|
||||
UnregisterSignal(honor_mutation, COMSIG_PARENT_QDELETING)
|
||||
honor_mutation = null
|
||||
UnregisterSignal(honor_trauma, COMSIG_PARENT_QDELETING)
|
||||
honor_trauma = null
|
||||
|
||||
/// If we lose our honor mutation somehow, self-delete (and clear references)
|
||||
/datum/action/cooldown/spell/pointed/declare_evil/proc/on_honor_mutation_lost(datum/source)
|
||||
/// If we lose our honor trauma somehow, self-delete (and clear references)
|
||||
/datum/action/cooldown/spell/pointed/declare_evil/proc/on_honor_trauma_lost(datum/source)
|
||||
SIGNAL_HANDLER
|
||||
|
||||
qdel(src)
|
||||
@@ -264,9 +260,6 @@
|
||||
if(!.)
|
||||
return FALSE
|
||||
|
||||
// This shouldn't technically be a possible state, but you never know
|
||||
if(!honor_mutation)
|
||||
return FALSE
|
||||
if(GLOB.religious_sect.favor < required_favor)
|
||||
if(feedback)
|
||||
to_chat(owner, span_warning("You need at least 150 favor to declare someone evil!"))
|
||||
@@ -315,4 +308,4 @@
|
||||
/datum/action/cooldown/spell/pointed/declare_evil/cast(mob/living/cast_on)
|
||||
. = ..()
|
||||
GLOB.religious_sect.adjust_favor(-required_favor, owner)
|
||||
honor_mutation.guilty(cast_on, declaration = TRUE)
|
||||
honor_trauma.guilty(cast_on, declaration = TRUE)
|
||||
@@ -20,8 +20,6 @@
|
||||
var/alignment = ALIGNMENT_GOOD
|
||||
/// Does this require something before being available as an option?
|
||||
var/starter = TRUE
|
||||
/// species traits that block you from picking
|
||||
var/invalidating_qualities = NONE
|
||||
/// The Sect's 'Mana'
|
||||
var/favor = 0 //MANA!
|
||||
/// The max amount of favor the sect can have
|
||||
@@ -271,6 +269,33 @@
|
||||
|
||||
#undef GREEDY_HEAL_COST
|
||||
|
||||
/datum/religion_sect/burden
|
||||
name = "Punished God"
|
||||
quote = "To feel the freedom, you must first understand captivity."
|
||||
desc = "Incapacitate yourself in any way possible. Bad mutations, lost limbs, traumas, \
|
||||
even addictions. You will learn the secrets of the universe from your defeated shell."
|
||||
tgui_icon = "user-injured"
|
||||
altar_icon_state = "convertaltar-burden"
|
||||
alignment = ALIGNMENT_NEUT
|
||||
candle_overlay = FALSE
|
||||
rites_list = list(/datum/religion_rites/nullrod_transformation)
|
||||
|
||||
/datum/religion_sect/burden/on_conversion(mob/living/carbon/human/new_convert)
|
||||
..()
|
||||
if(!ishuman(new_convert))
|
||||
to_chat(new_convert, span_warning("[GLOB.deity] needs higher level creatures to fully comprehend the suffering. You are not burdened."))
|
||||
return
|
||||
new_convert.gain_trauma(/datum/brain_trauma/special/burdened, TRAUMA_RESILIENCE_MAGIC)
|
||||
|
||||
/datum/religion_sect/burden/tool_examine(mob/living/carbon/human/burdened) //display burden level
|
||||
if(!ishuman(burdened))
|
||||
return FALSE
|
||||
var/datum/brain_trauma/special/burdened/burden = burdened.has_trauma_type(/datum/brain_trauma/special/burdened)
|
||||
if(burden)
|
||||
return "You are at burden level [burden.burden_level]/9."
|
||||
return "You are not burdened."
|
||||
|
||||
|
||||
/datum/religion_sect/honorbound
|
||||
name = "Honorbound God"
|
||||
quote = "A good, honorable crusade against evil is required."
|
||||
@@ -279,7 +304,6 @@
|
||||
tgui_icon = "scroll"
|
||||
altar_icon_state = "convertaltar-white"
|
||||
alignment = ALIGNMENT_GOOD
|
||||
invalidating_qualities = TRAIT_GENELESS
|
||||
rites_list = list(/datum/religion_rites/deaconize, /datum/religion_rites/forgive, /datum/religion_rites/summon_rules)
|
||||
///people who have agreed to join the crusade, and can be deaconized
|
||||
var/list/possible_crusaders = list()
|
||||
@@ -302,41 +326,7 @@
|
||||
if(!ishuman(new_convert))
|
||||
to_chat(new_convert, span_warning("[GLOB.deity] has no respect for lower creatures, and refuses to make you honorbound."))
|
||||
return FALSE
|
||||
if(TRAIT_GENELESS in new_convert.dna.species.inherent_traits)
|
||||
to_chat(new_convert, span_warning("[GLOB.deity] has deemed your species as one that could never show honor."))
|
||||
return FALSE
|
||||
var/datum/dna/holy_dna = new_convert.dna
|
||||
holy_dna.add_mutation(/datum/mutation/human/honorbound)
|
||||
|
||||
/datum/religion_sect/burden
|
||||
name = "Punished God"
|
||||
quote = "To feel the freedom, you must first understand captivity."
|
||||
desc = "Incapacitate yourself in any way possible. Bad mutations, lost limbs, traumas, \
|
||||
even addictions. You will learn the secrets of the universe from your defeated shell."
|
||||
tgui_icon = "user-injured"
|
||||
altar_icon_state = "convertaltar-burden"
|
||||
alignment = ALIGNMENT_NEUT
|
||||
invalidating_qualities = TRAIT_GENELESS
|
||||
candle_overlay = FALSE
|
||||
|
||||
/datum/religion_sect/burden/on_conversion(mob/living/carbon/human/new_convert)
|
||||
..()
|
||||
if(!ishuman(new_convert))
|
||||
to_chat(new_convert, span_warning("[GLOB.deity] needs higher level creatures to fully comprehend the suffering. You are not burdened."))
|
||||
return
|
||||
if(TRAIT_GENELESS in new_convert.dna.species.inherent_traits)
|
||||
to_chat(new_convert, span_warning("[GLOB.deity] cannot help a species such as yourself comprehend the suffering. You are not burdened."))
|
||||
return
|
||||
var/datum/dna/holy_dna = new_convert.dna
|
||||
holy_dna.add_mutation(/datum/mutation/human/burdened)
|
||||
|
||||
/datum/religion_sect/burden/tool_examine(mob/living/carbon/human/burdened) //display burden level
|
||||
if(!ishuman(burdened))
|
||||
return FALSE
|
||||
var/datum/mutation/human/burdened/burdenmut = burdened.dna.check_mutation(/datum/mutation/human/burdened)
|
||||
if(burdenmut)
|
||||
return "You are at burden level [burdenmut.burden_level]/6."
|
||||
return "You are not burdened."
|
||||
new_convert.gain_trauma(/datum/brain_trauma/special/honorbound, TRAUMA_RESILIENCE_MAGIC)
|
||||
|
||||
#define MINIMUM_YUCK_REQUIRED 5
|
||||
|
||||
|
||||
@@ -129,14 +129,16 @@
|
||||
..()
|
||||
var/altar_turf = get_turf(religious_tool)
|
||||
var/blessing = pick(
|
||||
/obj/item/organ/internal/cyberimp/arm/surgery,
|
||||
/obj/item/organ/internal/cyberimp/eyes/hud/diagnostic,
|
||||
/obj/item/organ/internal/cyberimp/eyes/hud/medical,
|
||||
/obj/item/organ/internal/cyberimp/mouth/breathing_tube,
|
||||
/obj/item/organ/internal/cyberimp/chest/thrusters,
|
||||
/obj/item/organ/internal/eyes/robotic/glow)
|
||||
/obj/item/organ/internal/cyberimp/arm/surgery,
|
||||
/obj/item/organ/internal/cyberimp/eyes/hud/diagnostic,
|
||||
/obj/item/organ/internal/cyberimp/eyes/hud/medical,
|
||||
/obj/item/organ/internal/cyberimp/mouth/breathing_tube,
|
||||
/obj/item/organ/internal/cyberimp/chest/thrusters,
|
||||
/obj/item/organ/internal/eyes/robotic/glow,
|
||||
)
|
||||
new blessing(altar_turf)
|
||||
return TRUE
|
||||
|
||||
/**** Pyre God ****/
|
||||
|
||||
///apply a bunch of fire immunity effect to clothing
|
||||
@@ -307,182 +309,6 @@
|
||||
playsound(get_turf(religious_tool), 'sound/effects/cashregister.ogg', 60, TRUE)
|
||||
return TRUE
|
||||
|
||||
/*********Honorbound God**********/
|
||||
|
||||
///Makes the person holy, but they now also have to follow the honorbound code (CBT). Actually earns favor, convincing others to uphold the code (tm) is not easy
|
||||
/datum/religion_rites/deaconize
|
||||
name = "Join Crusade"
|
||||
desc = "Converts someone to your sect. They must be willing, so the first invocation will instead prompt them to join. \
|
||||
They will become honorbound like you, and you will gain a massive favor boost!"
|
||||
ritual_length = 30 SECONDS
|
||||
ritual_invocations = list(
|
||||
"A good, honorable crusade against evil is required.",
|
||||
"We need the righteous ...",
|
||||
"... the unflinching ...",
|
||||
"... and the just.",
|
||||
"Sinners must be silenced ...",)
|
||||
invoke_msg = "... And the code must be upheld!"
|
||||
///the invited crusader
|
||||
var/mob/living/carbon/human/new_crusader
|
||||
|
||||
/datum/religion_rites/deaconize/perform_rite(mob/living/user, atom/religious_tool)
|
||||
var/datum/religion_sect/honorbound/sect = GLOB.religious_sect
|
||||
if(!ismovable(religious_tool))
|
||||
to_chat(user, span_warning("This rite requires a religious device that individuals can be buckled to."))
|
||||
return FALSE
|
||||
var/atom/movable/movable_reltool = religious_tool
|
||||
if(!movable_reltool)
|
||||
return FALSE
|
||||
if(!LAZYLEN(movable_reltool.buckled_mobs))
|
||||
to_chat(user, span_warning("Nothing is buckled to the altar!"))
|
||||
return FALSE
|
||||
for(var/mob/living/carbon/human/possible_crusader in movable_reltool.buckled_mobs)
|
||||
if(possible_crusader.stat != CONSCIOUS)
|
||||
to_chat(user, span_warning("[possible_crusader] needs to be alive and conscious to join the crusade!"))
|
||||
return FALSE
|
||||
if(TRAIT_GENELESS in possible_crusader.dna.species.inherent_traits)
|
||||
to_chat(user, span_warning("This species disgusts [GLOB.deity]! They would never be allowed to join the crusade!"))
|
||||
return FALSE
|
||||
if(possible_crusader in sect.currently_asking)
|
||||
to_chat(user, span_warning("Wait for them to decide on whether to join or not!"))
|
||||
return FALSE
|
||||
if(!(possible_crusader in sect.possible_crusaders))
|
||||
INVOKE_ASYNC(sect, TYPE_PROC_REF(/datum/religion_sect/honorbound, invite_crusader), possible_crusader)
|
||||
to_chat(user, span_notice("They have been given the option to consider joining the crusade against evil. Wait for them to decide and try again."))
|
||||
return FALSE
|
||||
new_crusader = possible_crusader
|
||||
return ..()
|
||||
|
||||
/datum/religion_rites/deaconize/invoke_effect(mob/living/carbon/human/user, atom/movable/religious_tool)
|
||||
..()
|
||||
var/mob/living/carbon/human/joining_now = new_crusader
|
||||
new_crusader = null
|
||||
if(!(joining_now in religious_tool.buckled_mobs)) //checks one last time if the right corpse is still buckled
|
||||
to_chat(user, span_warning("The new member is no longer on the altar!"))
|
||||
return FALSE
|
||||
if(joining_now.stat != CONSCIOUS)
|
||||
to_chat(user, span_warning("The new member has to stay alive for the rite to work!"))
|
||||
return FALSE
|
||||
if(!joining_now.mind)
|
||||
to_chat(user, span_warning("The new member has no mind!"))
|
||||
return FALSE
|
||||
if(joining_now.mind.has_antag_datum(/datum/antagonist/cult))//what the fuck?!
|
||||
to_chat(user, span_warning("[GLOB.deity] has seen a true, dark evil in [joining_now]'s heart, and they have been smitten!"))
|
||||
playsound(get_turf(religious_tool), 'sound/effects/pray.ogg', 50, TRUE)
|
||||
joining_now.gib(TRUE)
|
||||
return FALSE
|
||||
var/datum/mutation/human/honorbound/honormut = user.dna.check_mutation(/datum/mutation/human/honorbound)
|
||||
if(joining_now in honormut.guilty)
|
||||
honormut.guilty -= joining_now
|
||||
GLOB.religious_sect.adjust_favor(200, user)
|
||||
to_chat(user, span_notice("[GLOB.deity] has bound [joining_now] to the code! They are now a holy role! (albeit the lowest level of such)"))
|
||||
joining_now.mind.holy_role = HOLY_ROLE_DEACON
|
||||
GLOB.religious_sect.on_conversion(joining_now)
|
||||
playsound(get_turf(religious_tool), 'sound/effects/pray.ogg', 50, TRUE)
|
||||
return TRUE
|
||||
|
||||
///Mostly useless funny rite for forgiving someone, making them innocent once again.
|
||||
/datum/religion_rites/forgive
|
||||
name = "Forgive"
|
||||
desc = "Forgives someone, making them no longer considered guilty. A kind gesture, all things considered!"
|
||||
invoke_msg = "You are absolved of sin."
|
||||
var/mob/living/who
|
||||
|
||||
/datum/religion_rites/forgive/perform_rite(mob/living/carbon/human/user, atom/religious_tool)
|
||||
if(!ishuman(user))
|
||||
return FALSE
|
||||
var/datum/mutation/human/honorbound/honormut = user.dna.check_mutation(/datum/mutation/human/honorbound)
|
||||
if(!honormut)
|
||||
return FALSE
|
||||
if(!length(honormut.guilty))
|
||||
to_chat(user, span_warning("[GLOB.deity] is holding no grudges to forgive."))
|
||||
return FALSE
|
||||
var/forgiven_choice = tgui_input_list(user, "Choose one of [GLOB.deity]'s guilty to forgive", "Forgive", honormut.guilty)
|
||||
if(isnull(forgiven_choice))
|
||||
return FALSE
|
||||
who = forgiven_choice
|
||||
return ..()
|
||||
|
||||
/datum/religion_rites/forgive/invoke_effect(mob/living/carbon/human/user, atom/movable/religious_tool)
|
||||
..()
|
||||
if(in_range(user, religious_tool))
|
||||
return FALSE
|
||||
var/datum/mutation/human/honorbound/honormut = user.dna.check_mutation(/datum/mutation/human/honorbound)
|
||||
if(!honormut) //edge case
|
||||
return FALSE
|
||||
honormut.guilty -= who
|
||||
who = null
|
||||
playsound(get_turf(religious_tool), 'sound/effects/pray.ogg', 50, TRUE)
|
||||
return TRUE
|
||||
|
||||
/datum/religion_rites/summon_rules
|
||||
name = "Summon Honorbound Rules"
|
||||
desc = "Enscribes a paper with the honorbound rules and regulations."
|
||||
invoke_msg = "Bring forth the holy writ!"
|
||||
///paper to turn into holy writ
|
||||
var/obj/item/paper/writ_target
|
||||
|
||||
/datum/religion_rites/summon_rules/perform_rite(mob/living/user, atom/religious_tool)
|
||||
for(var/obj/item/paper/could_writ in get_turf(religious_tool))
|
||||
if(istype(could_writ, /obj/item/paper/holy_writ))
|
||||
continue
|
||||
if(could_writ.get_total_length()) //blank paper pls
|
||||
continue
|
||||
writ_target = could_writ //PLEASE SIGN MY AUTOGRAPH
|
||||
return ..()
|
||||
to_chat(user, span_warning("You need to place blank paper on [religious_tool] to do this!"))
|
||||
return FALSE
|
||||
|
||||
/datum/religion_rites/summon_rules/invoke_effect(mob/living/user, atom/movable/religious_tool)
|
||||
..()
|
||||
var/obj/item/paper/autograph = writ_target
|
||||
var/turf/tool_turf = get_turf(religious_tool)
|
||||
writ_target = null
|
||||
if(QDELETED(autograph) || !(tool_turf == autograph.loc)) //check if the same food is still there
|
||||
to_chat(user, span_warning("Your target left the altar!"))
|
||||
return FALSE
|
||||
autograph.visible_message(span_notice("Words magically form on [autograph]!"))
|
||||
playsound(tool_turf, 'sound/effects/pray.ogg', 50, TRUE)
|
||||
new /obj/item/paper/holy_writ(tool_turf)
|
||||
qdel(autograph)
|
||||
return TRUE
|
||||
|
||||
/obj/item/paper/holy_writ
|
||||
icon = 'icons/obj/wizard.dmi'
|
||||
icon_state = "scroll"
|
||||
slot_flags = null
|
||||
show_written_words = FALSE
|
||||
|
||||
//info set in here because we need GLOB.deity
|
||||
/obj/item/paper/holy_writ/Initialize(mapload)
|
||||
add_filter("holy_outline", 9, list("type" = "outline", "color" = "#fdff6c"))
|
||||
name = "[GLOB.deity]'s honorbound rules"
|
||||
default_raw_text = {"[GLOB.deity]'s honorbound rules:
|
||||
<br>
|
||||
1.) Thou shalt not attack the unready!<br>
|
||||
Those who are not ready for battle should not be wrought low. The evil of this world must lose
|
||||
in a fair battle if you are to conquer them completely.
|
||||
<br>
|
||||
<br>
|
||||
2.) Thou shalt not attack the just!<br>
|
||||
Those who fight for justice and good must not be harmed. Security is uncorruptable and must
|
||||
be respected. Healers are mostly uncorruptable and if you are truly sure Medical has fallen
|
||||
to the scourge of evil, use a declaration of evil.
|
||||
<br>
|
||||
<br>
|
||||
3.) Thou shalt not attack the innocent!<br>
|
||||
There is no honor on a pre-emptive strike, unless they are truly evil vermin.
|
||||
Those who are guilty will either lay a hand on you first, or you may declare their evil.
|
||||
<br>
|
||||
<br>
|
||||
4.) Thou shalt not use profane magicks!<br>
|
||||
You are not a warlock, you are an honorable warrior. There is nothing more corruptive than
|
||||
the vile magicks used by witches, warlocks, and necromancers. There are exceptions to this rule.<br>
|
||||
You may use holy magic, and, if you recruit one, the mime may use holy mimery. Restoration has also
|
||||
been allowed as it is a school focused on the light and mending of this world.
|
||||
"}
|
||||
. = ..()
|
||||
|
||||
/*********Maintenance God**********/
|
||||
|
||||
/datum/religion_rites/maint_adaptation
|
||||
@@ -507,7 +333,7 @@
|
||||
/datum/religion_rites/maint_adaptation/invoke_effect(mob/living/user, atom/movable/religious_tool)
|
||||
..()
|
||||
to_chat(user, span_warning("You feel your genes rattled and reshaped. <b>You're becoming something new.</b>"))
|
||||
user.emote("laughs")
|
||||
user.emote("laugh")
|
||||
ADD_TRAIT(user, TRAIT_HOPELESSLY_ADDICTED, "maint_adaptation")
|
||||
//addiction sends some nasty mood effects but we want the maint adaption to be enjoyed like a fine wine
|
||||
user.add_mood_event("maint_adaptation", /datum/mood_event/maintenance_adaptation)
|
||||
@@ -574,7 +400,7 @@
|
||||
to_chat(user, span_warning("Your target left the altar!"))
|
||||
return FALSE
|
||||
to_chat(user, span_warning("[moldify] becomes rancid!"))
|
||||
user.emote("laughs")
|
||||
user.emote("laugh")
|
||||
new /obj/item/food/badrecipe/moldy(get_turf(religious_tool))
|
||||
qdel(moldify)
|
||||
return TRUE
|
||||
@@ -605,7 +431,7 @@
|
||||
to_chat(user, span_warning("[padala] reshapes into a totem!"))
|
||||
if(!padala.use(1))//use one wood
|
||||
return
|
||||
user.emote("laughs")
|
||||
user.emote("laugh")
|
||||
new /obj/item/ritual_totem(altar_turf)
|
||||
return TRUE
|
||||
|
||||
|
||||
@@ -11,6 +11,8 @@
|
||||
var/currently_channeling = FALSE
|
||||
/// How long it takes to channel the spell.
|
||||
var/channel_time = 10 SECONDS
|
||||
/// Flags of the do_after
|
||||
var/channel_flags = IGNORE_USER_LOC_CHANGE|IGNORE_HELD_ITEM
|
||||
|
||||
// Overlay optional, applied when we start channelling
|
||||
/// What icon should we use for our overlay
|
||||
@@ -75,7 +77,7 @@
|
||||
|
||||
currently_channeling = TRUE
|
||||
UpdateButtons(status_only = TRUE)
|
||||
if(!do_after(cast_on, channel_time, timed_action_flags = (IGNORE_USER_LOC_CHANGE|IGNORE_HELD_ITEM)))
|
||||
if(!do_after(cast_on, channel_time, timed_action_flags = channel_flags))
|
||||
stop_channel_effect(cast_on)
|
||||
return . | SPELL_CANCEL_CAST
|
||||
|
||||
|
||||
@@ -17,15 +17,16 @@
|
||||
|
||||
/datum/action/cooldown/spell/forcewall/cast(atom/cast_on)
|
||||
. = ..()
|
||||
new wall_type(get_turf(owner), owner)
|
||||
for(var/turf/cast_turf as anything in get_turfs())
|
||||
spawn_wall(cast_turf)
|
||||
|
||||
if(owner.dir == SOUTH || owner.dir == NORTH)
|
||||
new wall_type(get_step(owner, EAST), owner, antimagic_flags)
|
||||
new wall_type(get_step(owner, WEST), owner, antimagic_flags)
|
||||
/// This proc returns all the turfs on which we will spawn the walls.
|
||||
/datum/action/cooldown/spell/forcewall/proc/get_turfs()
|
||||
return list(get_turf(owner), get_step(owner, turn(owner.dir, 90)), get_step(owner, turn(owner.dir, 270)))
|
||||
|
||||
else
|
||||
new wall_type(get_step(owner, NORTH), owner, antimagic_flags)
|
||||
new wall_type(get_step(owner, SOUTH), owner, antimagic_flags)
|
||||
/// This proc spawns a wall on the given turf.
|
||||
/datum/action/cooldown/spell/forcewall/proc/spawn_wall(turf/cast_turf)
|
||||
new wall_type(cast_turf, owner, antimagic_flags)
|
||||
|
||||
/datum/action/cooldown/spell/forcewall/cult
|
||||
name = "Shield"
|
||||
|
||||
@@ -186,28 +186,31 @@
|
||||
else
|
||||
return SURGERY_STEP_FAIL
|
||||
|
||||
/datum/surgery_step/manipulate_organs/success(mob/living/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery, default_display_results)
|
||||
/datum/surgery_step/manipulate_organs/success(mob/living/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery, default_display_results = FALSE)
|
||||
if (target_zone == BODY_ZONE_PRECISE_EYES)
|
||||
target_zone = check_zone(target_zone)
|
||||
if(current_type == "insert")
|
||||
var/obj/item/apparatus
|
||||
if(istype(tool, /obj/item/borg/apparatus/organ_storage))
|
||||
target_organ = tool.contents[1]
|
||||
tool.icon_state = initial(tool.icon_state)
|
||||
tool.desc = initial(tool.desc)
|
||||
tool.cut_overlays()
|
||||
tool = target_organ
|
||||
else
|
||||
target_organ = tool
|
||||
apparatus = tool
|
||||
tool = tool.contents[1]
|
||||
target_organ = tool
|
||||
user.temporarilyRemoveItemFromInventory(target_organ, TRUE)
|
||||
target_organ.Insert(target)
|
||||
display_results(
|
||||
user,
|
||||
target,
|
||||
span_notice("You insert [tool] into [target]'s [parse_zone(target_zone)]."),
|
||||
span_notice("[user] inserts [tool] into [target]'s [parse_zone(target_zone)]!"),
|
||||
span_notice("[user] inserts something into [target]'s [parse_zone(target_zone)]!"),
|
||||
)
|
||||
display_pain(target, "Your [parse_zone(target_zone)] throbs with pain as your new [tool] comes to life!")
|
||||
if(target_organ.Insert(target))
|
||||
if(apparatus)
|
||||
apparatus.icon_state = initial(apparatus.icon_state)
|
||||
apparatus.desc = initial(apparatus.desc)
|
||||
apparatus.cut_overlays()
|
||||
display_results(
|
||||
user,
|
||||
target,
|
||||
span_notice("You insert [tool] into [target]'s [parse_zone(target_zone)]."),
|
||||
span_notice("[user] inserts [tool] into [target]'s [parse_zone(target_zone)]!"),
|
||||
span_notice("[user] inserts something into [target]'s [parse_zone(target_zone)]!"),
|
||||
)
|
||||
display_pain(target, "Your [parse_zone(target_zone)] throbs with pain as your new [tool] comes to life!")
|
||||
else
|
||||
target_organ.forceMove(target.loc)
|
||||
|
||||
else if(current_type == "extract")
|
||||
if(target_organ && target_organ.owner == target)
|
||||
@@ -230,7 +233,7 @@
|
||||
span_notice("[user] can't seem to extract anything from [target]'s [parse_zone(target_zone)]!"),
|
||||
span_notice("[user] can't seem to extract anything from [target]'s [parse_zone(target_zone)]!"),
|
||||
)
|
||||
return FALSE
|
||||
return ..()
|
||||
|
||||
///You can never use this MUHAHAHAHAHAHAH (because its the byond version of abstract)
|
||||
/datum/surgery_step/manipulate_organs/proc/can_use_organ(mob/user, obj/item/organ/organ)
|
||||
|
||||
@@ -201,9 +201,9 @@
|
||||
visible_message(span_danger("[user] presses one of the colorful buttons on [src], and the clown car lets out a comedic toot."))
|
||||
playsound(src, 'sound/vehicles/clowncar_fart.ogg', 100)
|
||||
for(var/mob/living/L in orange(loc, 6))
|
||||
L.emote("laughs")
|
||||
L.emote("laugh")
|
||||
for(var/mob/living/L as anything in occupants)
|
||||
L.emote("laughs")
|
||||
L.emote("laugh")
|
||||
|
||||
///resets the icon and iconstate of the clowncar after it was set to singulo states
|
||||
/obj/vehicle/sealed/car/clowncar/proc/reset_icon()
|
||||
|
||||
|
Before Width: | Height: | Size: 929 KiB After Width: | Height: | Size: 931 KiB |
|
Before Width: | Height: | Size: 3.6 KiB After Width: | Height: | Size: 4.1 KiB |
|
After Width: | Height: | Size: 261 B |
|
Before Width: | Height: | Size: 6.5 MiB After Width: | Height: | Size: 6.7 MiB |
|
Before Width: | Height: | Size: 52 KiB After Width: | Height: | Size: 52 KiB |
|
Before Width: | Height: | Size: 33 KiB After Width: | Height: | Size: 34 KiB |
|
Before Width: | Height: | Size: 33 KiB After Width: | Height: | Size: 33 KiB |
|
Before Width: | Height: | Size: 330 KiB After Width: | Height: | Size: 330 KiB |
@@ -816,6 +816,7 @@
|
||||
#include "code\datums\components\deployable.dm"
|
||||
#include "code\datums\components\drift.dm"
|
||||
#include "code\datums\components\earprotection.dm"
|
||||
#include "code\datums\components\echolocation.dm"
|
||||
#include "code\datums\components\edit_complainer.dm"
|
||||
#include "code\datums\components\effect_remover.dm"
|
||||
#include "code\datums\components\egg_layer.dm"
|
||||
@@ -1220,8 +1221,6 @@
|
||||
#include "code\datums\mutations\touch.dm"
|
||||
#include "code\datums\mutations\void_magnet.dm"
|
||||
#include "code\datums\mutations\webbing.dm"
|
||||
#include "code\datums\mutations\holy_mutation\burdened.dm"
|
||||
#include "code\datums\mutations\holy_mutation\honorbound.dm"
|
||||
#include "code\datums\proximity_monitor\field.dm"
|
||||
#include "code\datums\proximity_monitor\proximity_monitor.dm"
|
||||
#include "code\datums\proximity_monitor\fields\gravity.dm"
|
||||
@@ -4312,8 +4311,12 @@
|
||||
#include "code\modules\religion\religion_sects.dm"
|
||||
#include "code\modules\religion\religion_structures.dm"
|
||||
#include "code\modules\religion\rites.dm"
|
||||
#include "code\modules\religion\burdened\burdened_trauma.dm"
|
||||
#include "code\modules\religion\burdened\psyker.dm"
|
||||
#include "code\modules\religion\festival\instrument_rites.dm"
|
||||
#include "code\modules\religion\festival\note_particles.dm"
|
||||
#include "code\modules\religion\honorbound\honorbound_rites.dm"
|
||||
#include "code\modules\religion\honorbound\honorbound_trauma.dm"
|
||||
#include "code\modules\religion\sparring\ceremonial_gear.dm"
|
||||
#include "code\modules\religion\sparring\sparring_contract.dm"
|
||||
#include "code\modules\religion\sparring\sparring_datum.dm"
|
||||
|
||||