diff --git a/_maps/templates/lazy_templates/heretic_sacrifice.dmm b/_maps/templates/lazy_templates/heretic_sacrifice.dmm index d0277a1e712..cbabb4c6485 100644 --- a/_maps/templates/lazy_templates/heretic_sacrifice.dmm +++ b/_maps/templates/lazy_templates/heretic_sacrifice.dmm @@ -40,6 +40,14 @@ /obj/structure/cable, /turf/open/floor/plating, /area/centcom/heretic_sacrifice/rust) +"fL" = ( +/obj/effect/decal/cleanable/blood/old, +/obj/effect/decal/cleanable/dirt/dust, +/turf/open/indestructible/plating, +/area/centcom/heretic_sacrifice/knock) +"fO" = ( +/turf/open/indestructible, +/area/space) "gJ" = ( /obj/effect/decal/remains/human, /turf/open/misc/dirt/jungle/dark{ @@ -47,6 +55,11 @@ slowdown = 0 }, /area/centcom/heretic_sacrifice/ash) +"hE" = ( +/obj/effect/decal/cleanable/dirt/dust, +/obj/item/storage/toolbox/mechanical/old, +/turf/open/indestructible/plating, +/area/centcom/heretic_sacrifice/knock) "hZ" = ( /obj/effect/decal/cleanable/blood/old, /turf/open/indestructible/necropolis/air, @@ -56,6 +69,9 @@ /obj/structure/cable, /turf/open/floor/plating/rust, /area/centcom/heretic_sacrifice/rust) +"jt" = ( +/turf/closed/indestructible/reinforced, +/area/centcom/heretic_sacrifice/knock) "jB" = ( /obj/machinery/light/very_dim/directional/south, /turf/open/misc/asteroid, @@ -85,6 +101,11 @@ }, /turf/open/floor/plating, /area/centcom/heretic_sacrifice/rust) +"mW" = ( +/obj/effect/decal/cleanable/dirt/dust, +/obj/item/spear, +/turf/open/indestructible/plating, +/area/centcom/heretic_sacrifice/knock) "mZ" = ( /obj/effect/decal/fakelattice{ density = 0 @@ -150,6 +171,12 @@ /obj/effect/decal/remains/human, /turf/open/misc/asteroid, /area/centcom/heretic_sacrifice/void) +"qo" = ( +/obj/effect/decal/cleanable/blood/old, +/obj/effect/decal/cleanable/dirt/dust, +/obj/item/storage/toolbox/mechanical/old, +/turf/open/indestructible/plating, +/area/centcom/heretic_sacrifice/knock) "qu" = ( /obj/effect/turf_decal/weather/dirt, /turf/open/misc/ashplanet/wateryrock{ @@ -202,6 +229,12 @@ }, /turf/open/floor/plating/rust, /area/centcom/heretic_sacrifice/rust) +"uM" = ( +/obj/effect/decal/cleanable/blood/old, +/obj/effect/decal/cleanable/dirt/dust, +/obj/item/clothing/under/color/grey/ancient, +/turf/open/indestructible/plating, +/area/centcom/heretic_sacrifice/knock) "uT" = ( /obj/structure/cable, /turf/open/floor/plating/rust, @@ -225,6 +258,9 @@ slowdown = 0 }, /area/centcom/heretic_sacrifice/ash) +"wo" = ( +/turf/closed/indestructible/grille, +/area/centcom/heretic_sacrifice/knock) "wt" = ( /obj/structure/stone_tile/block{ dir = 1 @@ -240,6 +276,16 @@ slowdown = 0 }, /area/centcom/heretic_sacrifice/ash) +"wP" = ( +/obj/effect/decal/cleanable/dirt/dust, +/obj/item/flashlight/flare{ + fuel = 1e+031; + randomize_fuel = 0; + icon_state = "flare-on"; + on = 1 + }, +/turf/open/indestructible/plating, +/area/centcom/heretic_sacrifice/knock) "wS" = ( /turf/open/misc/dirt/jungle/dark{ planetary_atmos = 0; @@ -252,6 +298,9 @@ name = "void glass floor" }, /area/centcom/heretic_sacrifice/void) +"xc" = ( +/turf/open/indestructible/white, +/area/space) "yC" = ( /obj/effect/turf_decal/trimline/brown/line{ dir = 1 @@ -273,6 +322,11 @@ }, /turf/open/floor/plating/rust, /area/centcom/heretic_sacrifice/rust) +"Aw" = ( +/obj/effect/decal/cleanable/dirt/dust, +/obj/item/clothing/mask/gas, +/turf/open/indestructible/plating, +/area/centcom/heretic_sacrifice/knock) "AH" = ( /obj/effect/turf_decal/trimline/brown/corner, /turf/open/floor/plating/rust, @@ -287,6 +341,15 @@ "AO" = ( /turf/open/floor/fakespace, /area/centcom/heretic_sacrifice/void) +"AW" = ( +/obj/effect/decal/cleanable/dirt/dust, +/obj/item/clothing/mask/gas/tiki_mask/yalp_elor, +/turf/open/indestructible/plating, +/area/centcom/heretic_sacrifice/knock) +"AY" = ( +/obj/effect/decal/cleanable/dirt/dust, +/turf/open/indestructible/plating, +/area/centcom/heretic_sacrifice/knock) "Bv" = ( /obj/effect/decal/cleanable/dirt, /obj/effect/turf_decal/trimline/brown/line, @@ -340,6 +403,9 @@ slowdown = 0 }, /area/centcom/heretic_sacrifice/ash) +"En" = ( +/turf/closed/indestructible/fakedoor/maintenance, +/area/centcom/heretic_sacrifice/knock) "ER" = ( /turf/open/misc/ironsand, /area/centcom/heretic_sacrifice/rust) @@ -467,6 +533,17 @@ /obj/machinery/light/very_dim/directional/west, /turf/open/floor/fakespace, /area/centcom/heretic_sacrifice/void) +"MZ" = ( +/obj/effect/decal/cleanable/blood/old, +/obj/effect/decal/cleanable/dirt/dust, +/obj/item/flashlight/flare{ + fuel = 1e+031; + randomize_fuel = 0; + icon_state = "flare-on"; + on = 1 + }, +/turf/open/indestructible/plating, +/area/centcom/heretic_sacrifice/knock) "Nh" = ( /obj/effect/turf_decal/trimline/brown/line{ dir = 1 @@ -508,6 +585,11 @@ slowdown = 0 }, /area/centcom/heretic_sacrifice/ash) +"OW" = ( +/obj/effect/decal/cleanable/dirt/dust, +/obj/item/clothing/under/color/grey/ancient, +/turf/open/indestructible/plating, +/area/centcom/heretic_sacrifice/knock) "Pl" = ( /obj/effect/turf_decal/weather/dirt{ dir = 6 @@ -627,6 +709,12 @@ /obj/effect/decal/cleanable/dirt, /turf/open/indestructible/necropolis/air, /area/centcom/heretic_sacrifice/flesh) +"Zw" = ( +/obj/effect/decal/cleanable/blood/old, +/obj/effect/decal/cleanable/dirt/dust, +/obj/effect/landmark/heretic/knock, +/turf/open/indestructible/plating, +/area/centcom/heretic_sacrifice/knock) "ZA" = ( /turf/closed/indestructible/riveted/boss, /area/centcom/heretic_sacrifice/ash) @@ -661,9 +749,37 @@ ab ab ab ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab "} (2,1,1) = {" ab +ab +Fd +Fd +Fd +Fd +Fd +Fd +Fd +Fd +Fd +Fd +Fd +Fd +Fd Fd Fd Fd @@ -695,6 +811,20 @@ ab "} (3,1,1) = {" ab +ab +Fd +jt +jt +wo +wo +jt +En +En +jt +wo +wo +jt +jt Fd ZA ZA @@ -726,6 +856,20 @@ ab "} (4,1,1) = {" ab +ab +Fd +jt +AY +AY +AY +AY +AY +AY +AY +AY +fL +AY +jt Fd ZA Pl @@ -757,6 +901,20 @@ ab "} (5,1,1) = {" ab +ab +Fd +wo +AY +fL +uM +AY +AY +qo +fL +AY +mW +MZ +wo Fd ZA wS @@ -788,6 +946,20 @@ ab "} (6,1,1) = {" ab +ab +Fd +wo +AY +Aw +fL +AY +wP +fL +fL +AY +qo +AY +wo Fd ZA OG @@ -819,6 +991,20 @@ ab "} (7,1,1) = {" ab +ab +Fd +jt +AY +fL +fL +AY +AY +fL +AY +AY +fL +Aw +jt Fd ZA Bw @@ -850,6 +1036,20 @@ ab "} (8,1,1) = {" ab +ab +Fd +En +AY +MZ +fL +AY +Zw +OW +AY +AY +AY +fL +En Fd ZA Bw @@ -881,6 +1081,20 @@ ab "} (9,1,1) = {" ab +ab +Fd +En +fL +AY +AY +AY +fL +fL +AY +AY +fL +AY +En Fd ZA Bw @@ -912,6 +1126,20 @@ ab "} (10,1,1) = {" ab +ab +Fd +jt +AY +AY +fL +AY +fL +AY +fL +AY +AW +fL +jt Fd ZA Bw @@ -943,6 +1171,20 @@ ab "} (11,1,1) = {" ab +ab +Fd +wo +fL +AY +hE +MZ +AY +AY +hE +fL +wP +AY +wo Fd ZA Pl @@ -974,6 +1216,20 @@ ab "} (12,1,1) = {" ab +ab +Fd +wo +AY +fL +AY +AY +AY +fL +AY +OW +fL +fL +wo Fd ZA wS @@ -1005,6 +1261,20 @@ ab "} (13,1,1) = {" ab +ab +Fd +jt +AY +AY +fL +fL +AY +AY +AY +AY +AY +AY +jt Fd ZA OG @@ -1036,6 +1306,20 @@ ab "} (14,1,1) = {" ab +ab +Fd +jt +jt +wo +wo +jt +En +En +jt +wo +wo +jt +jt Fd ZA ZA @@ -1067,6 +1351,20 @@ ab "} (15,1,1) = {" ab +ab +Fd +Fd +Fd +Fd +Fd +Fd +Fd +Fd +Fd +Fd +Fd +Fd +Fd Fd Fd Fd @@ -1098,6 +1396,20 @@ ab "} (16,1,1) = {" ab +ab +Fd +fO +fO +fO +fO +fO +fO +fO +fO +fO +fO +fO +fO Fd WD WD @@ -1129,6 +1441,20 @@ ab "} (17,1,1) = {" ab +ab +Fd +fO +fO +fO +fO +fO +fO +xc +xc +xc +xc +xc +fO Fd WD dZ @@ -1160,6 +1486,20 @@ ab "} (18,1,1) = {" ab +ab +Fd +fO +fO +fO +fO +fO +fO +fO +fO +xc +fO +fO +fO Fd WD dZ @@ -1191,6 +1531,20 @@ ab "} (19,1,1) = {" ab +ab +Fd +fO +fO +fO +fO +fO +fO +xc +xc +xc +xc +xc +fO Fd WD ER @@ -1222,6 +1576,20 @@ ab "} (20,1,1) = {" ab +ab +Fd +fO +fO +fO +fO +fO +fO +fO +fO +fO +fO +fO +fO Fd WD Se @@ -1253,6 +1621,20 @@ ab "} (21,1,1) = {" ab +ab +Fd +fO +fO +fO +fO +fO +fO +xc +fO +xc +xc +xc +fO Fd WD Xr @@ -1284,6 +1666,20 @@ ab "} (22,1,1) = {" ab +ab +Fd +fO +fO +fO +fO +fO +fO +fO +fO +fO +fO +fO +fO Fd WD Se @@ -1315,6 +1711,20 @@ ab "} (23,1,1) = {" ab +ab +Fd +fO +fO +fO +fO +fO +fO +fO +fO +fO +fO +fO +fO Fd WD Xr @@ -1346,6 +1756,20 @@ ab "} (24,1,1) = {" ab +ab +Fd +fO +fO +fO +fO +fO +fO +fO +fO +fO +fO +fO +fO Fd WD ps @@ -1377,6 +1801,20 @@ ab "} (25,1,1) = {" ab +ab +Fd +fO +fO +fO +fO +fO +fO +fO +fO +fO +fO +fO +fO Fd WD Je @@ -1408,6 +1846,20 @@ ab "} (26,1,1) = {" ab +ab +Fd +fO +fO +fO +fO +fO +fO +fO +fO +fO +fO +fO +fO Fd WD ER @@ -1439,6 +1891,20 @@ ab "} (27,1,1) = {" ab +ab +Fd +fO +fO +fO +fO +fO +fO +fO +fO +fO +fO +fO +fO Fd WD WD @@ -1470,6 +1936,20 @@ ab "} (28,1,1) = {" ab +ab +Fd +Fd +Fd +Fd +Fd +Fd +Fd +Fd +Fd +Fd +Fd +Fd +Fd Fd Fd Fd @@ -1529,4 +2009,18 @@ ab ab ab ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab "} diff --git a/code/__DEFINES/achievements.dm b/code/__DEFINES/achievements.dm index b5efdb76f1a..4a0299d835a 100644 --- a/code/__DEFINES/achievements.dm +++ b/code/__DEFINES/achievements.dm @@ -46,6 +46,7 @@ #define MEDAL_VOID_ASCENSION "Void" #define MEDAL_BLADE_ASCENSION "Blade" #define MEDAL_COSMOS_ASCENSION "Cosmos" +#define MEDAL_KNOCK_ASCENSION "Knock" #define MEDAL_TOOLBOX_SOUL "Toolsoul" #define MEDAL_CHEM_TUT "Beginner Chemist" #define MEDAL_HOT_DAMN "Hot Damn!" diff --git a/code/__DEFINES/antagonists.dm b/code/__DEFINES/antagonists.dm index 1f8a99d9d8c..d9d0cd5cf0d 100644 --- a/code/__DEFINES/antagonists.dm +++ b/code/__DEFINES/antagonists.dm @@ -80,6 +80,7 @@ #define PATH_VOID "Void Path" #define PATH_BLADE "Blade Path" #define PATH_COSMIC "Cosmic Path" +#define PATH_KNOCK "Knock Path" /// Defines are used in /proc/has_living_heart() to report if the heretic has no heart period, no living heart, or has a living heart. #define HERETIC_NO_HEART_ORGAN -1 diff --git a/code/__DEFINES/dcs/signals/signals_atom/signals_atom_attack.dm b/code/__DEFINES/dcs/signals/signals_atom/signals_atom_attack.dm index d47833f84c0..a2198cfb63c 100644 --- a/code/__DEFINES/dcs/signals/signals_atom/signals_atom_attack.dm +++ b/code/__DEFINES/dcs/signals/signals_atom/signals_atom_attack.dm @@ -64,3 +64,6 @@ #define ATTACKER_SHOVING (1<<1) /// The attack is a damaging-type attack #define ATTACKER_DAMAGING_ATTACK (1<<2) + +/// Called on the atom being hit, from /datum/component/anti_magic/on_attack() : (obj/item/weapon, mob/user, antimagic_flags) +#define COMSIG_ATOM_HOLYATTACK "atom_holyattacked" diff --git a/code/__DEFINES/traits.dm b/code/__DEFINES/traits.dm index ade8a05798f..571f67f5b7d 100644 --- a/code/__DEFINES/traits.dm +++ b/code/__DEFINES/traits.dm @@ -1196,6 +1196,8 @@ Remember to update _globalvars/traits.dm if you're adding/removing/renaming trai #define TRAIT_MAGNETIC_ID_CARD "magnetic_id_card" /// ID cards with this trait have special appraisal text. #define TRAIT_TASTEFULLY_THICK_ID_CARD "impressive_very_nice" +/// things with this trait are treated as having no access in /obj/proc/check_access(obj/item) +#define TRAIT_ALWAYS_NO_ACCESS "alwaysnoaccess" /// Traits granted to items due to their chameleon properties. #define CHAMELEON_ITEM_TRAIT "chameleon_item_trait" diff --git a/code/_globalvars/phobias.dm b/code/_globalvars/phobias.dm index 309b31ceb37..a6cb2dedb32 100644 --- a/code/_globalvars/phobias.dm +++ b/code/_globalvars/phobias.dm @@ -366,8 +366,10 @@ GLOBAL_LIST_INIT(phobia_objs, list( "heresy" = typecacheof(list( /obj/effect/floating_blade, /obj/effect/forcefield/cosmic_field, - /obj/effect/heretic_rune, + /obj/effect/forcefield/wizard/heretic, /obj/effect/heretic_influence, + /obj/effect/heretic_rune, + /obj/effect/knock_portal, /obj/effect/visible_heretic_influence, /obj/item/ammo_box/strilka310/lionhunter, /obj/item/ammo_casing/strilka310/lionhunter, @@ -379,6 +381,7 @@ GLOBAL_LIST_INIT(phobia_objs, list( /obj/item/codex_cicatrix, /obj/item/coin/eldritch, /obj/item/gun/ballistic/rifle/lionhunter, + /obj/item/heretic_lintel, /obj/item/melee/rune_carver, /obj/item/melee/sickly_blade, /obj/item/melee/touch_attack/mansus_fist, @@ -387,6 +390,7 @@ GLOBAL_LIST_INIT(phobia_objs, list( /obj/item/toy/reality_pierce, /obj/projectile/curse_hand, /obj/structure/destructible/eldritch_crucible, + /obj/structure/knock_tear, )), "insects" = typecacheof(list( /obj/item/clothing/mask/animal/small/bee, diff --git a/code/datums/achievements/misc_achievements.dm b/code/datums/achievements/misc_achievements.dm index 8240ebbf62e..f83f2cde7b0 100644 --- a/code/datums/achievements/misc_achievements.dm +++ b/code/datums/achievements/misc_achievements.dm @@ -135,6 +135,12 @@ database_id = MEDAL_COSMOS_ASCENSION icon = "cosmicascend" +/datum/award/achievement/misc/knock_ascension + name = "Secrets behind the Spider Door" + desc = "You managed to open a gate into the mansus." + database_id = MEDAL_KNOCK_ASCENSION + icon = "knockascend" + /datum/award/achievement/misc/grand_ritual_finale name = "Archmage" desc = "Made a big impression on the station with your phenomenal cosmic power." diff --git a/code/datums/components/anti_magic.dm b/code/datums/components/anti_magic.dm index d3d53237777..059bc2f787d 100644 --- a/code/datums/components/anti_magic.dm +++ b/code/datums/components/anti_magic.dm @@ -44,6 +44,7 @@ if(isitem(parent)) RegisterSignal(parent, COMSIG_ITEM_EQUIPPED, PROC_REF(on_equip)) RegisterSignal(parent, COMSIG_ITEM_DROPPED, PROC_REF(on_drop)) + RegisterSignals(parent, list(COMSIG_ITEM_ATTACK, COMSIG_ITEM_ATTACK_ATOM), PROC_REF(on_attack)) else if(ismob(parent)) register_antimagic_signals(parent) else @@ -131,3 +132,7 @@ return COMPONENT_MAGIC_BLOCKED return NONE + +/datum/component/anti_magic/proc/on_attack(atom/movable/source, atom/target, mob/user) + SIGNAL_HANDLER + SEND_SIGNAL(target, COMSIG_ATOM_HOLYATTACK, source, user, antimagic_flags) diff --git a/code/datums/elements/embed.dm b/code/datums/elements/embed.dm index 0ba3a581d9a..1bc70dc500f 100644 --- a/code/datums/elements/embed.dm +++ b/code/datums/elements/embed.dm @@ -76,6 +76,9 @@ if(blocked || !istype(victim) || HAS_TRAIT(victim, TRAIT_PIERCEIMMUNE)) return FALSE + + if(victim.status_flags & GODMODE) + return FALSE var/flying_speed = throwingdatum?.speed || weapon.throw_speed diff --git a/code/game/objects/items/storage/belt.dm b/code/game/objects/items/storage/belt.dm index a69d5c183f4..4718471e87a 100644 --- a/code/game/objects/items/storage/belt.dm +++ b/code/game/objects/items/storage/belt.dm @@ -75,6 +75,7 @@ /obj/item/wirecutters, /obj/item/wrench, /obj/item/spess_knife, + /obj/item/melee/sickly_blade/knock, )) /obj/item/storage/belt/utility/chief diff --git a/code/game/turfs/open/_open.dm b/code/game/turfs/open/_open.dm index 67f07bf6a75..7831fa1863c 100644 --- a/code/game/turfs/open/_open.dm +++ b/code/game/turfs/open/_open.dm @@ -124,6 +124,9 @@ /turf/open/indestructible/light icon_state = "light_on-1" +/turf/open/indestructible/plating + icon_state = "plating" + /turf/open/indestructible/permalube icon_state = "darkfull" diff --git a/code/modules/antagonists/heretic/heretic_antag.dm b/code/modules/antagonists/heretic/heretic_antag.dm index ed6473548c9..e28f20dab36 100644 --- a/code/modules/antagonists/heretic/heretic_antag.dm +++ b/code/modules/antagonists/heretic/heretic_antag.dm @@ -64,6 +64,7 @@ PATH_VOID = "blue", PATH_BLADE = "label", // my favorite color is label PATH_COSMIC = "purple", + PATH_KNOCK = "yellow", ) var/static/list/path_to_rune_color = list( PATH_START = COLOR_LIME, @@ -73,6 +74,7 @@ PATH_VOID = COLOR_CYAN, PATH_BLADE = COLOR_SILVER, PATH_COSMIC = COLOR_PURPLE, + PATH_KNOCK = COLOR_YELLOW, ) /datum/antagonist/heretic/Destroy() @@ -508,6 +510,7 @@ .["Remove Heart Target"] = CALLBACK(src, PROC_REF(remove_target)) .["Adjust Knowledge Points"] = CALLBACK(src, PROC_REF(admin_change_points)) + .["Give Focus"] = CALLBACK(src, PROC_REF(admin_give_focus)) /** * Admin proc for giving a heretic a Living Heart easily. @@ -583,6 +586,18 @@ knowledge_points += change_num +/** + * Admin proc for giving a heretic a focus. + */ +/datum/antagonist/heretic/proc/admin_give_focus(mob/admin) + if(!admin.client?.holder) + to_chat(admin, span_warning("You shouldn't be using this!")) + return + + var/mob/living/pawn = owner.current + pawn.equip_to_slot_if_possible(new /obj/item/clothing/neck/heretic_focus(get_turf(pawn)), ITEM_SLOT_NECK, TRUE, TRUE) + to_chat(pawn, span_hypnophrase("The Mansus has manifested you a focus.")) + /datum/antagonist/heretic/antag_panel_data() var/list/string_of_knowledge = list() diff --git a/code/modules/antagonists/heretic/items/heretic_blades.dm b/code/modules/antagonists/heretic/items/heretic_blades.dm index c074e13c8d3..63493a5dc4b 100644 --- a/code/modules/antagonists/heretic/items/heretic_blades.dm +++ b/code/modules/antagonists/heretic/items/heretic_blades.dm @@ -115,3 +115,14 @@ icon_state = "cosmic_blade" inhand_icon_state = "cosmic_blade" after_use_message = "The Stargazer hears your call..." + +// Path of Knock's blade +/obj/item/melee/sickly_blade/knock + name = "\improper key blade" + desc = "A blade and a key, a key to what? \ + What grand gates does it open?" + icon_state = "key_blade" + inhand_icon_state = "key_blade" + after_use_message = "The Mother of Ants hears your call..." + tool_behaviour = TOOL_CROWBAR + toolspeed = 1.3 diff --git a/code/modules/antagonists/heretic/items/keyring.dm b/code/modules/antagonists/heretic/items/keyring.dm new file mode 100644 index 00000000000..0498ba9e8a2 --- /dev/null +++ b/code/modules/antagonists/heretic/items/keyring.dm @@ -0,0 +1,186 @@ +/obj/effect/knock_portal + name = "crack in reality" + desc = "A crack in space, impossibly deep and painful to the eyes. Definitely not safe." + icon = 'icons/effects/eldritch.dmi' + icon_state = "realitycrack" + light_system = STATIC_LIGHT + light_power = 1 + light_on = TRUE + light_color = COLOR_GREEN + light_range = 3 + opacity = TRUE + density = FALSE //so we dont block doors closing + layer = OBJ_LAYER //under doors + ///The knock portal we teleport to + var/obj/effect/knock_portal/destination + ///The airlock we are linked to, we delete if it is destroyed + var/obj/machinery/door/our_airlock + +/obj/effect/knock_portal/Initialize(mapload, target) + . = ..() + if(target) + our_airlock = target + RegisterSignal(target, COMSIG_QDELETING, PROC_REF(delete_on_door_delete)) + + var/static/list/loc_connections = list( + COMSIG_ATOM_ENTERED = PROC_REF(on_entered), + ) + AddElement(/datum/element/connect_loc, loc_connections) + +///Deletes us and our destination portal if our_airlock is destroyed +/obj/effect/knock_portal/proc/delete_on_door_delete(datum/source) + SIGNAL_HANDLER + qdel(src) + +///Signal handler for when our location is entered, calls teleport on the victim, if their old_loc didnt contain a portal already (to prevent loops) +/obj/effect/knock_portal/proc/on_entered(datum/source, mob/living/loser, atom/old_loc) + SIGNAL_HANDLER + if(istype(loser) && !(locate(type) in old_loc)) + teleport(loser) + +/obj/effect/knock_portal/Destroy() + QDEL_NULL(destination) + our_airlock = null + return ..() + +///Teleports the teleportee, to a random airlock if the teleportee isnt a heretic, or the other portal if they are one +/obj/effect/knock_portal/proc/teleport(mob/living/teleportee) + if(isnull(destination)) //dumbass + qdel(src) + return + + //get it? + var/obj/machinery/door/doorstination = IS_HERETIC_OR_MONSTER(teleportee) ? destination.our_airlock : find_random_airlock() + if(!do_teleport(teleportee, get_turf(doorstination), channel = TELEPORT_CHANNEL_MAGIC)) + return + + if(!IS_HERETIC_OR_MONSTER(teleportee)) + teleportee.apply_damage(20, BRUTE) //so they dont roll it like a jackpot machine to see if they can land in the armory + to_chat(teleportee, span_userdanger("You stumble through [src], battered by forces beyond your comprehension, landing anywhere but where you thought you were going.")) + + INVOKE_ASYNC(src, PROC_REF(async_opendoor), doorstination) + +///Returns a random airlock on the same Z level as our portal, that isnt our airlock +/obj/effect/knock_portal/proc/find_random_airlock() + var/list/turf/possible_destinations = list() + for(var/obj/airlock as anything in SSmachines.get_machines_by_type_and_subtypes(/obj/machinery/door/airlock)) + if(airlock.z != z) + continue + if(airlock.loc == loc) + continue + possible_destinations += airlock + return pick(possible_destinations) + +///Asynchronous proc to unbolt, then open the passed door +/obj/effect/knock_portal/proc/async_opendoor(obj/machinery/door/door) + if(istype(door, /obj/machinery/door/airlock)) //they can create portals on ANY door, but we should unlock airlocks so they can actually open + var/obj/machinery/door/airlock/as_airlock = door + as_airlock.unbolt() + door.open() + +///An ID card capable of shapeshifting to other IDs given by the Key Keepers Burden knowledge +/obj/item/card/id/advanced/heretic + ///List of IDs this card consumed + var/list/obj/item/card/id/fused_ids = list() + ///The first portal in the portal pair, so we can clear it later + var/obj/effect/knock_portal/portal_one + ///The second portal in the portal pair, so we can clear it later + var/obj/effect/knock_portal/portal_two + ///The first door we are linking in the pair, so we can create a portal pair + var/datum/weakref/link + +/obj/item/card/id/advanced/heretic/examine(mob/user) + . = ..() + if(!IS_HERETIC_OR_MONSTER(user)) + return + . += span_hypnophrase("Enchanted by the Mansus!") + . += span_hypnophrase("Using an ID on this will consume it and allow you to copy its accesses.") + . += span_hypnophrase("Using this in-hand allows you to change its appearance.") + . += span_hypnophrase("Using this on a pair of doors, allows you to link them together. Entering one door will transport you to the other, while heathens are instead teleported to a random airlock.") + +/obj/item/card/id/advanced/heretic/attack_self(mob/user) + . = ..() + if(!IS_HERETIC(user)) + return + var/cardname = tgui_input_list(user, "Shapeshift into?", "Shapeshift", fused_ids) + if(!cardname) + balloon_alert(user, "no options!") + return ..() + var/obj/item/card/id/card = fused_ids[cardname] + shapeshift(card) + +///Changes our appearance to the passed ID card +/obj/item/card/id/advanced/heretic/proc/shapeshift(obj/item/card/id/advanced/card) + trim = card.trim + assignment = card.assignment + registered_age = card.registered_age + registered_name = card.registered_name + icon_state = card.icon_state + inhand_icon_state = card.inhand_icon_state + assigned_icon_state = card.assigned_icon_state + name = card.name //not update_label because of the captains spare moment + update_icon() + +///Deletes and nulls our portal pair +/obj/item/card/id/advanced/heretic/proc/clear_portals() + QDEL_NULL(portal_one) + QDEL_NULL(portal_two) + +///Clears portal references +/obj/item/card/id/advanced/heretic/proc/clear_portal_refs() + SIGNAL_HANDLER + portal_one = null + portal_two = null + +///Creates a portal pair at door1 and door2, displays a balloon alert to user +/obj/item/card/id/advanced/heretic/proc/make_portal(mob/user, obj/machinery/door/door1, obj/machinery/door/door2) + var/message = "linked" + if(portal_one || portal_two) + clear_portals() + message += ", previous cleared" + + portal_one = new(get_turf(door2), door2) + portal_two = new(get_turf(door1), door1) + portal_one.destination = portal_two + RegisterSignal(portal_one, COMSIG_QDELETING, PROC_REF(clear_portal_refs)) //we only really need to register one because they already qdel both portals if one is destroyed + portal_two.destination = portal_one + balloon_alert(user, "[message]") + +/obj/item/card/id/advanced/heretic/attackby(obj/item/thing, mob/user, params) + if(!istype(thing, /obj/item/card/id/advanced) || !IS_HERETIC(user)) + return ..() + var/obj/item/card/id/card = thing + fused_ids[card.name] = card + card.moveToNullspace() + playsound(drop_location(),'sound/items/eatfood.ogg', rand(10,50), TRUE) + access += card.access + +/obj/item/card/id/advanced/heretic/afterattack(atom/target, mob/user, proximity_flag, click_parameters) + . = ..() + if(!proximity_flag || !IS_HERETIC(user)) + return + if(istype(target, /obj/effect/knock_portal)) + clear_portals() + return + + if(!istype(target, /obj/machinery/door)) + return + + var/reference_resolved = link?.resolve() + if(reference_resolved == target) + return + + if(reference_resolved) + make_portal(user, reference_resolved, target) + to_chat(user, span_notice("You use [src], to link [link] and [target] together.")) + link = null + balloon_alert(user, "link 2/2") + else + link = WEAKREF(target) + balloon_alert(user, "link 1/2") + +/obj/item/card/id/advanced/heretic/Destroy() + QDEL_LIST_ASSOC(fused_ids) + link = null + clear_portals() + return ..() diff --git a/code/modules/antagonists/heretic/items/lintel.dm b/code/modules/antagonists/heretic/items/lintel.dm new file mode 100644 index 00000000000..140453842c0 --- /dev/null +++ b/code/modules/antagonists/heretic/items/lintel.dm @@ -0,0 +1,64 @@ +/obj/effect/forcefield/wizard/heretic + name = "consecrated lintel" + desc = "A field of papers flying in the air, repulsing heathens with impossible force." + icon_state = "lintel" + initial_duration = 8 SECONDS + +/obj/effect/forcefield/wizard/heretic/Bumped(mob/living/bumpee) + . = ..() + if(!istype(bumpee) || IS_HERETIC_OR_MONSTER(bumpee)) + return + var/throwtarget = get_edge_target_turf(loc, get_dir(loc, get_step_away(bumpee, loc))) + bumpee.safe_throw_at(throwtarget, 10, 1, force = MOVE_FORCE_EXTREMELY_STRONG) + visible_message(span_danger("[src] repulses [bumpee] in a storm of paper!")) + +///A heretic item that spawns a barrier at the clicked turf, 3 uses +/obj/item/heretic_lintel + name = "consecrated book" + desc = "Some kind of book, its contents make your head hurt. The material is not known to you and it seems to shift and twist unnaturally." + icon = 'icons/obj/service/library.dmi' + icon_state = "hereticlintel" + force = 10 + damtype = BURN + worn_icon_state = "book" + throw_speed = 1 + throw_range = 5 + w_class = WEIGHT_CLASS_NORMAL + attack_verb_continuous = list("bashes", "curses") + attack_verb_simple = list("bash", "curse") + resistance_flags = FLAMMABLE + drop_sound = 'sound/items/handling/book_drop.ogg' + pickup_sound = 'sound/items/handling/book_pickup.ogg' + ///what type of barrier do we spawn when used + var/barrier_type = /obj/effect/forcefield/wizard/heretic + ///how many uses do we have left + var/uses = 3 + +/obj/item/heretic_lintel/examine(mob/user) + . = ..() + if(!IS_HERETIC_OR_MONSTER(user)) + return + . += span_hypnophrase("Materializes a barrier upon any tile in sight, which only you can pass through. Lasts 8 seconds.") + . += span_hypnophrase("It has [uses] uses left.") + +/obj/item/heretic_lintel/afterattack(atom/target, mob/user, proximity_flag) + . = ..() + if(IS_HERETIC(user)) + var/turf/turf_target = get_turf(target) + if(locate(barrier_type) in turf_target) + user.balloon_alert(user, "already occupied!") + return + turf_target.visible_message(span_warning("A storm of paper materializes!")) + new /obj/effect/temp_visual/paper_scatter(turf_target) + playsound(turf_target, 'sound/magic/smoke.ogg', 30) + new barrier_type(turf_target, user) + uses-- + if(uses <= 0) + to_chat(user, span_warning("[src] falls apart, turning into ash and dust!")) + qdel(src) + return + var/mob/living/carbon/human/human_user = user + to_chat(human_user, span_userdanger("Your mind burns as you stare deep into the book, a headache setting in like your brain is on fire!")) + human_user.adjustOrganLoss(ORGAN_SLOT_BRAIN, 30, 190) + human_user.add_mood_event("gates_of_mansus", /datum/mood_event/gates_of_mansus) + human_user.dropItemToGround(src) diff --git a/code/modules/antagonists/heretic/knowledge/flesh_lore.dm b/code/modules/antagonists/heretic/knowledge/flesh_lore.dm index c688e285735..33253220b22 100644 --- a/code/modules/antagonists/heretic/knowledge/flesh_lore.dm +++ b/code/modules/antagonists/heretic/knowledge/flesh_lore.dm @@ -262,6 +262,8 @@ I finally began to understand. And then, blood rained from the heavens." next_knowledge = list(/datum/heretic_knowledge/summon/stalker) route = PATH_FLESH + ///What type of wound do we apply on hit + var/wound_type = /datum/wound/slash/flesh/severe /datum/heretic_knowledge/blade_upgrade/flesh/do_melee_effects(mob/living/source, mob/living/target, obj/item/melee/sickly_blade/blade) if(!iscarbon(target) || source == target) @@ -269,7 +271,8 @@ var/mob/living/carbon/carbon_target = target var/obj/item/bodypart/bodypart = pick(carbon_target.bodyparts) - carbon_target.cause_wound_of_type_and_severity(WOUND_SLASH, bodypart, WOUND_SEVERITY_SEVERE, WOUND_SEVERITY_CRITICAL) + var/datum/wound/crit_wound = new wound_type() + crit_wound.apply_wound(bodypart, attack_direction = get_dir(source, target)) /datum/heretic_knowledge/summon/stalker name = "Lonely Ritual" diff --git a/code/modules/antagonists/heretic/knowledge/knock_lore.dm b/code/modules/antagonists/heretic/knowledge/knock_lore.dm new file mode 100644 index 00000000000..fcb2c6ceb4c --- /dev/null +++ b/code/modules/antagonists/heretic/knowledge/knock_lore.dm @@ -0,0 +1,227 @@ +/** + * # The path of Knock. + * + * Goes as follows: + * + * A Locksmith’s Secret + * Grasp of Knock + * > Sidepaths: + * Ashen Eyes + * Codex Cicatrix + * Key Keeper’s Burden + * + * Rite Of Passage + * Mark Of Knock + * Ritual of Knowledge + * Burglar's Finesse + * > Sidepaths: + * Apetra Vulnera + * Opening Blast + * + * Opening Blade + * Caretaker’s Last Refuge + * + * Many secrets behind the Spider Door + */ +/datum/heretic_knowledge/limited_amount/starting/base_knock + name = "A Locksmith’s Secret" + desc = "Opens up the Path of Knock to you. \ + Allows you to transmute a knife and a crowbar into a Key Blade. \ + You can only create two at a time and they function as fast crowbars. \ + In addition, they can fit into utility belts." + gain_text = "The Knock permits no seal and no isolation. It thrusts us gleefully out of the safety of ignorance." + next_knowledge = list(/datum/heretic_knowledge/knock_grasp) + required_atoms = list( + /obj/item/knife = 1, + /obj/item/crowbar = 1, + ) + result_atoms = list(/obj/item/melee/sickly_blade/knock) + limit = 2 + route = PATH_KNOCK + +/datum/heretic_knowledge/knock_grasp + name = "Grasp of Knock" + desc = "Your mansus grasp allows you to access anything! Right click on an airlock or a locker to force it open. \ + DNA locks on mechs will be removed, and any pilot will be ejected. Works on consoles. \ + Makes a distinctive knocking sound on use." + gain_text = "Nothing may remain closed from my touch." + next_knowledge = list( + /datum/heretic_knowledge/key_ring, + /datum/heretic_knowledge/medallion, + /datum/heretic_knowledge/codex_cicatrix, + ) + cost = 1 + route = PATH_KNOCK + +/datum/heretic_knowledge/knock_grasp/on_gain(mob/user, datum/antagonist/heretic/our_heretic) + RegisterSignal(user, COMSIG_HERETIC_MANSUS_GRASP_ATTACK_SECONDARY, PROC_REF(on_secondary_mansus_grasp)) + RegisterSignal(user, COMSIG_HERETIC_MANSUS_GRASP_ATTACK, PROC_REF(on_mansus_grasp)) + +/datum/heretic_knowledge/knock_grasp/on_lose(mob/user, datum/antagonist/heretic/our_heretic) + UnregisterSignal(user, COMSIG_HERETIC_MANSUS_GRASP_ATTACK_SECONDARY) + UnregisterSignal(user, COMSIG_HERETIC_MANSUS_GRASP_ATTACK) + +/datum/heretic_knowledge/knock_grasp/proc/on_mansus_grasp(mob/living/source, mob/living/target) + SIGNAL_HANDLER + var/obj/item/clothing/under/suit = target.get_item_by_slot(ITEM_SLOT_ICLOTHING) + if(istype(suit) && suit.adjusted == NORMAL_STYLE) + suit.toggle_jumpsuit_adjust() + suit.update_appearance() + +/datum/heretic_knowledge/knock_grasp/proc/on_secondary_mansus_grasp(mob/living/source, atom/target) + SIGNAL_HANDLER + + if(ismecha(target)) + var/obj/vehicle/sealed/mecha/mecha = target + mecha.dna_lock = null + for(var/mob/living/occupant as anything in mecha.occupants) + if(isAI(occupant)) + continue + mecha.mob_exit(occupant, randomstep = TRUE) + else if(istype(target,/obj/machinery/door/airlock)) + var/obj/machinery/door/airlock/door = target + door.unbolt() + else if(istype(target, /obj/machinery/computer)) + var/obj/machinery/computer/computer = target + computer.authenticated = TRUE + computer.balloon_alert(source, "unlocked") + + var/turf/target_turf = get_turf(target) + SEND_SIGNAL(target_turf, COMSIG_ATOM_MAGICALLY_UNLOCKED, src, source) + playsound(target, 'sound/magic/hereticknock.ogg', 100, TRUE, -1) + + return COMPONENT_USE_HAND + +/datum/heretic_knowledge/key_ring + name = "Key Keeper’s Burden" + desc = "Allows you to transmute a wallet, an iron rod, and an ID card to create an Eldritch Card. \ + It functions the same as an ID Card, but attacking it with an ID card fuses it and gains its access. \ + You can use it in-hand to change its form to a card you fused. \ + Does not preserve the card used in the ritual." + gain_text = "Gateways shall open before me, my very will ensnaring reality." + required_atoms = list( + /obj/item/storage/wallet = 1, + /obj/item/stack/rods = 1, + /obj/item/card/id = 1, + ) + result_atoms = list(/obj/item/card/id/advanced/heretic) + next_knowledge = list(/datum/heretic_knowledge/limited_amount/rite_of_passage) + cost = 1 + route = PATH_KNOCK + +/datum/heretic_knowledge/limited_amount/rite_of_passage // item that creates 3 max at a time heretic only barriers, probably should limit to 1 only, holy people can also pass + name = "Rite Of Passage" + desc = "Allows you to transmute a white crayon, a wooden plank, and a multitool to create a Consecrated Book. \ + It can materialize a barricade at range that only you and people resistant to magic can pass. 3 uses." + gain_text = "With this I can repel those that intend me harm." + required_atoms = list( + /obj/item/toy/crayon/white = 1, + /obj/item/stack/sheet/mineral/wood = 1, + /obj/item/multitool = 1, + ) + result_atoms = list(/obj/item/heretic_lintel) + next_knowledge = list(/datum/heretic_knowledge/mark/knock_mark) + cost = 1 + route = PATH_KNOCK + +/datum/heretic_knowledge/mark/knock_mark + name = "Mark of Knock" + desc = "Your Mansus Grasp now applies the Mark of Knock. \ + Attack a marked person to bar them from all passages for the duration of the mark. \ + This will make it so that they have no access whatsoever, even public access doors will reject them." + gain_text = "Their requests for passage will remain unheeded." + next_knowledge = list(/datum/heretic_knowledge/knowledge_ritual/knock) + route = PATH_KNOCK + mark_type = /datum/status_effect/eldritch/knock + +/datum/heretic_knowledge/knowledge_ritual/knock + next_knowledge = list(/datum/heretic_knowledge/spell/burglar_finesse) + route = PATH_KNOCK + +/datum/heretic_knowledge/spell/burglar_finesse + name = "Burglar's Finesse" + desc = "Grants you Burglar's Finesse, a single-target spell \ + that puts a random item from the victims backpack into your hand." + gain_text = "Their trinkets will be mine, as will their lives in due time." + next_knowledge = list( + /datum/heretic_knowledge/spell/apetra_vulnera, + /datum/heretic_knowledge/spell/opening_blast, + /datum/heretic_knowledge/blade_upgrade/flesh/knock, + ) + spell_to_add = /datum/action/cooldown/spell/pointed/burglar_finesse + cost = 2 + route = PATH_KNOCK + +/datum/heretic_knowledge/blade_upgrade/flesh/knock //basically a chance-based weeping avulsion version of the former + name = "Opening Blade" + desc = "Your blade has a chance to cause a weeping avulsion on attack." + gain_text = "The power of my patron courses through my blade, willing their very flesh to part." + next_knowledge = list(/datum/heretic_knowledge/spell/caretaker_refuge) + route = PATH_KNOCK + wound_type = /datum/wound/slash/flesh/critical + var/chance = 35 + +/datum/heretic_knowledge/blade_upgrade/flesh/knock/do_melee_effects(mob/living/source, mob/living/target, obj/item/melee/sickly_blade/blade) + if(prob(chance)) + return ..() + +/datum/heretic_knowledge/spell/caretaker_refuge + name = "Caretaker’s Last Refuge" + desc = "Gives you a spell that makes you transparent and not dense. Cannot be used near living sentient beings. \ + While in refuge, you cannot use your hands or spells, and you are immune to slowdown. \ + You are invincible but unable to harm anything. Cancelled by being hit with an anti-magic item." + gain_text = "Then I saw my my own reflection cascaded mind-numbingly enough times that I was but a haze." + next_knowledge = list(/datum/heretic_knowledge/ultimate/knock_final) + route = PATH_KNOCK + spell_to_add = /datum/action/cooldown/spell/caretaker + cost = 1 + +/datum/heretic_knowledge/ultimate/knock_final + name = "Many secrets behind the Spider Door" + desc = "The ascension ritual of the Path of Knock. \ + Bring 3 corpses without organs in their torso to a transmutation rune to complete the ritual. \ + When completed, you gain the ability to transform into empowered eldritch creatures \ + and in addition, create a tear to the Spider Door; \ + a tear in reality located at the site of this ritual. \ + Eldritch creatures will endlessly pour from this rift \ + who are bound to obey your instructions." + gain_text = "With her knowledge, and what I had seen, I knew what to do. \ + I had to open the gates, with the holes in my foes as Ways! \ + Reality will soon be torn, the Spider Gate opened! WITNESS ME!" + required_atoms = list(/mob/living/carbon/human = 3) + route = PATH_KNOCK + +/datum/heretic_knowledge/ultimate/knock_final/recipe_snowflake_check(mob/living/user, list/atoms, list/selected_atoms, turf/loc) + . = ..() + if(!.) + return FALSE + + for(var/mob/living/carbon/human/body in atoms) + if(body.stat != DEAD) + continue + var/obj/item/bodypart/chest = body.get_bodypart(BODY_ZONE_CHEST) + if(LAZYLEN(chest.get_organs())) + to_chat(user, span_hierophant_warning("[body] has organs in their chest.")) + continue + + selected_atoms += body + + if(!LAZYLEN(selected_atoms)) + loc.balloon_alert(user, "ritual failed, not enough valid bodies!") + return FALSE + return TRUE + +/datum/heretic_knowledge/ultimate/knock_final/on_finished_recipe(mob/living/user, list/selected_atoms, turf/loc) + . = ..() + priority_announce("Delta-class dimensional anomaly detec[generate_heretic_text()] Reality rended, torn. Gates open, doors open, [user.real_name] has ascended! Fear the tide! [generate_heretic_text()]", "Centra[generate_heretic_text()]", ANNOUNCER_SPANOMALIES) + user.client?.give_award(/datum/award/achievement/misc/knock_ascension, user) + + // buffs + var/datum/action/cooldown/spell/shapeshift/eldritch/ascension/transform_spell = new(user.mind) + transform_spell.Grant(user) + + user.client?.give_award(/datum/award/achievement/misc/knock_ascension, user) + var/datum/antagonist/heretic/heretic_datum = IS_HERETIC(user) + var/datum/heretic_knowledge/blade_upgrade/flesh/knock/blade_upgrade = heretic_datum.get_knowledge(/datum/heretic_knowledge/blade_upgrade/flesh/knock) + blade_upgrade.chance += 30 + new /obj/structure/knock_tear(loc, user.mind) diff --git a/code/modules/antagonists/heretic/knowledge/sacrifice_knowledge/sacrifice_map.dm b/code/modules/antagonists/heretic/knowledge/sacrifice_knowledge/sacrifice_map.dm index 942b053ae67..983bbee32c6 100644 --- a/code/modules/antagonists/heretic/knowledge/sacrifice_knowledge/sacrifice_map.dm +++ b/code/modules/antagonists/heretic/knowledge/sacrifice_knowledge/sacrifice_map.dm @@ -34,6 +34,10 @@ GLOBAL_LIST_EMPTY(heretic_sacrifice_landmarks) name = "rust heretic sacrifice landmark" for_heretic_path = PATH_RUST +/obj/effect/landmark/heretic/knock + name = "knock heretic sacrifice landmark" + for_heretic_path = PATH_KNOCK + // A fluff signpost object that doesn't teleport you somewhere when you touch it. /obj/structure/no_effect_signpost name = "signpost" @@ -106,3 +110,8 @@ GLOBAL_LIST_EMPTY(heretic_sacrifice_landmarks) name = "Mansus Rust Gate" ambience_index = AMBIENCE_REEBE sound_environment = SOUND_ENVIRONMENT_SEWER_PIPE + +/area/centcom/heretic_sacrifice/knock + name = "Mansus Knock Gate" + ambience_index = AMBIENCE_DANGER + sound_environment = SOUND_ENVIRONMENT_PSYCHOTIC diff --git a/code/modules/antagonists/heretic/knowledge/side_flesh_void.dm b/code/modules/antagonists/heretic/knowledge/side_flesh_void.dm index 4a315575d61..6439840fed5 100644 --- a/code/modules/antagonists/heretic/knowledge/side_flesh_void.dm +++ b/code/modules/antagonists/heretic/knowledge/side_flesh_void.dm @@ -26,6 +26,7 @@ Also has a chance to transfer wounds from you to the victim." gain_text = "\"No matter the man, we bleed all the same.\" That's what the Marshal told me." next_knowledge = list( + /datum/heretic_knowledge/spell/apetra_vulnera, /datum/heretic_knowledge/spell/void_phase, /datum/heretic_knowledge/summon/raw_prophet, ) diff --git a/code/modules/antagonists/heretic/knowledge/side_knock_flesh.dm b/code/modules/antagonists/heretic/knowledge/side_knock_flesh.dm new file mode 100644 index 00000000000..97218ce5e94 --- /dev/null +++ b/code/modules/antagonists/heretic/knowledge/side_knock_flesh.dm @@ -0,0 +1,28 @@ +// Sidepaths for knowledge between Knock and Flesh. + +/datum/heretic_knowledge/spell/apetra_vulnera + name = "Apetra Vulnera" + desc = "Grants you Apetra Vulnera, a spell \ + which causes heavy bleeding on all bodyparts of the victim that have more than 15 brute damage. \ + Wounds a random limb if no limb is sufficiently damaged." + gain_text = "Flesh opens, and blood spills. My master seeks sacrifice, and I shall appease." + next_knowledge = list( + /datum/heretic_knowledge/spell/blood_siphon, + /datum/heretic_knowledge/void_cloak, + ) + spell_to_add = /datum/action/cooldown/spell/pointed/apetra_vulnera + cost = 1 + route = PATH_SIDE + +/datum/heretic_knowledge/spell/opening_blast + name = "Wave Of Desperation" + desc = "Grants you Wave Of Desparation, a spell which can only be cast while restrained. \ + It removes your restraints, repels and knocks down adjacent people, and applies the Mansus Grasp to everything nearby." + gain_text = "My shackles undone in dark fury, their feeble bindings crumble before my power." + next_knowledge = list( + /datum/heretic_knowledge/summon/ashy, + /datum/heretic_knowledge/void_cloak, + ) + spell_to_add = /datum/action/cooldown/spell/aoe/wave_of_desperation + cost = 1 + route = PATH_SIDE diff --git a/code/modules/antagonists/heretic/magic/apetravulnera.dm b/code/modules/antagonists/heretic/magic/apetravulnera.dm new file mode 100644 index 00000000000..801104dddf9 --- /dev/null +++ b/code/modules/antagonists/heretic/magic/apetravulnera.dm @@ -0,0 +1,59 @@ +/datum/action/cooldown/spell/pointed/apetra_vulnera + name = "Apetra Vulnera" + desc = "Causes severe bleeding on every limb of a target which has more than 15 brute damage. \ + Wounds a random limb if no limb is sufficiently damaged." + background_icon_state = "bg_heretic" + overlay_icon_state = "bg_heretic_border" + button_icon = 'icons/mob/actions/actions_ecult.dmi' + button_icon_state = "cleave" + + school = SCHOOL_FORBIDDEN + cooldown_time = 45 SECONDS + + invocation = "AP'TRA VULN'RA!" + invocation_type = INVOCATION_WHISPER + spell_requirements = NONE + + cast_range = 4 + /// What type of wound we apply + var/wound_type = /datum/wound/slash/flesh/critical/cleave + +/datum/action/cooldown/spell/pointed/apetra_vulnera/is_valid_target(atom/cast_on) + return ..() && ishuman(cast_on) + +/datum/action/cooldown/spell/pointed/apetra_vulnera/cast(mob/living/carbon/human/cast_on) + . = ..() + + if(IS_HERETIC_OR_MONSTER(cast_on)) + return FALSE + + if(!cast_on.blood_volume) + return FALSE + + if(cast_on.can_block_magic(antimagic_flags)) + cast_on.visible_message( + span_danger("[cast_on]'s bruises briefly glow, but repels the effect!"), + span_danger("Your bruises sting a little, but you are protected!") + ) + return FALSE + + var/a_limb_got_damaged = FALSE + for(var/obj/item/bodypart/bodypart in cast_on.bodyparts) + if(bodypart.brute_dam < 15) + continue + a_limb_got_damaged = TRUE + var/datum/wound/slash/crit_wound = new wound_type() + crit_wound.apply_wound(bodypart) + + if(!a_limb_got_damaged) + var/datum/wound/slash/crit_wound = new wound_type() + crit_wound.apply_wound(pick(cast_on.bodyparts)) + + cast_on.visible_message( + span_danger("[cast_on]'s scratches and bruises are torn open by an unholy force!"), + span_danger("Your scratches and bruises are torn open by some horrible unholy force!") + ) + + new /obj/effect/temp_visual/cleave(get_turf(cast_on)) + + return TRUE diff --git a/code/modules/antagonists/heretic/magic/ascended_shapeshift.dm b/code/modules/antagonists/heretic/magic/ascended_shapeshift.dm new file mode 100644 index 00000000000..4395b4a54b3 --- /dev/null +++ b/code/modules/antagonists/heretic/magic/ascended_shapeshift.dm @@ -0,0 +1,32 @@ +// Given to ascended knock heretics, is a form of shapeshift that can turn into all 4 common heretic summons, and is not limited to 1 selection. +/datum/action/cooldown/spell/shapeshift/eldritch/ascension + name = "Ascended Shapechange" + desc = "A spell that allows you to take on the form of another eldritch creature, gaining their abilities. \ + You can change your choice at any time, and if your form dies, you dont die." + cooldown_time = 20 SECONDS + die_with_shapeshifted_form = FALSE + possible_shapes = list( + /mob/living/simple_animal/hostile/heretic_summon/raw_prophet, + /mob/living/simple_animal/hostile/heretic_summon/rust_spirit, + /mob/living/simple_animal/hostile/heretic_summon/ash_spirit, + /mob/living/simple_animal/hostile/heretic_summon/stalker, + ) + +/datum/action/cooldown/spell/shapeshift/eldritch/ascension/do_shapeshift(mob/living/caster) + . = ..() + if(!.) + return + //buff our forms so this ascension ability isnt shit + playsound(caster, 'sound/magic/demon_consume.ogg', 50, TRUE) + var/mob/living/monster = . + monster.AddComponent(/datum/component/seethrough_mob) + monster.maxHealth *= 1.5 + monster.health = monster.maxHealth + monster.melee_damage_lower = max((monster.melee_damage_lower * 2), 40) + monster.melee_damage_upper = monster.melee_damage_upper / 2 + monster.transform *= 1.5 + monster.AddElement(/datum/element/wall_smasher, strength_flag = ENVIRONMENT_SMASH_RWALLS) + +/datum/action/cooldown/spell/shapeshift/eldritch/ascension/do_unshapeshift(mob/living/caster) + . = ..() + shapeshift_type = null //pick another loser diff --git a/code/modules/antagonists/heretic/magic/burglar_finesse.dm b/code/modules/antagonists/heretic/magic/burglar_finesse.dm new file mode 100644 index 00000000000..7bb6960354e --- /dev/null +++ b/code/modules/antagonists/heretic/magic/burglar_finesse.dm @@ -0,0 +1,39 @@ +/datum/action/cooldown/spell/pointed/burglar_finesse + name = "Burglar's Finesse" + desc = "Steal a random item from the victim's backpack." + background_icon_state = "bg_heretic" + overlay_icon_state = "bg_heretic_border" + button_icon = 'icons/mob/actions/actions_ecult.dmi' + button_icon_state = "burglarsfinesse" + + school = SCHOOL_FORBIDDEN + cooldown_time = 40 SECONDS + + invocation = "Y'O'K!" + invocation_type = INVOCATION_WHISPER + spell_requirements = NONE + + cast_range = 4 + +/datum/action/cooldown/spell/pointed/burglar_finesse/is_valid_target(atom/cast_on) + return ..() && ishuman(cast_on) && (locate(/obj/item/storage/backpack) in cast_on.contents) + +/datum/action/cooldown/spell/pointed/burglar_finesse/cast(mob/living/carbon/human/cast_on) + . = ..() + if(cast_on.can_block_magic(antimagic_flags)) + to_chat(cast_on, span_danger("You feel a light tug, but are otherwise fine, you were protected by holiness!")) + to_chat(owner, span_danger("[cast_on] is protected by holy forces!")) + return FALSE + + var/obj/storage_item = locate(/obj/item/storage/backpack) in cast_on.contents + + if(isnull(storage_item)) + return FALSE + + var/item = pick(storage_item.contents) + if(isnull(item)) + return FALSE + + to_chat(cast_on, span_warning("Your [storage_item] feels lighter...")) + to_chat(owner, span_notice("With a blink, you pull [item] out of [cast_on][p_s()] [storage_item].")) + owner.put_in_active_hand(item) diff --git a/code/modules/antagonists/heretic/magic/caretaker.dm b/code/modules/antagonists/heretic/magic/caretaker.dm new file mode 100644 index 00000000000..87f3a69dad1 --- /dev/null +++ b/code/modules/antagonists/heretic/magic/caretaker.dm @@ -0,0 +1,39 @@ +/datum/action/cooldown/spell/caretaker + name = "Caretaker’s Last Refuge" + desc = "Shifts you into the Caretaker's Refuge, rendering you translucent and intangible. \ + While in the Refuge your movement is unrestricted, but you cannot use your hands or cast any spells. \ + You cannot enter the Refuge while near other sentient beings, \ + and you can be removed from it upon contact with antimagical artifacts." + background_icon_state = "bg_heretic" + overlay_icon_state = "bg_heretic_border" + button_icon = 'icons/mob/actions/actions_minor_antag.dmi' + button_icon_state = "ninja_cloak" + sound = 'sound/effects/curse2.ogg' + + school = SCHOOL_FORBIDDEN + cooldown_time = 1 MINUTES + + invocation_type = INVOCATION_NONE + spell_requirements = NONE + +/datum/action/cooldown/spell/caretaker/Remove(mob/living/remove_from) + if(remove_from.has_status_effect(/datum/status_effect/caretaker_refuge)) + remove_from.remove_status_effect(/datum/status_effect/caretaker_refuge) + return ..() + +/datum/action/cooldown/spell/caretaker/is_valid_target(atom/cast_on) + return isliving(cast_on) + +/datum/action/cooldown/spell/caretaker/cast(atom/cast_on) + . = ..() + for(var/mob/living/alive in orange(5, owner)) + if(alive.stat != DEAD && alive.client) + owner.balloon_alert(owner, "other minds nearby!") + return FALSE + + var/mob/living/carbon/carbon_user = owner + if(carbon_user.has_status_effect(/datum/status_effect/caretaker_refuge)) + carbon_user.remove_status_effect(/datum/status_effect/caretaker_refuge) + else + carbon_user.apply_status_effect(/datum/status_effect/caretaker_refuge) + return TRUE diff --git a/code/modules/antagonists/heretic/magic/wave_of_desperation.dm b/code/modules/antagonists/heretic/magic/wave_of_desperation.dm new file mode 100644 index 00000000000..3b78b56ddc0 --- /dev/null +++ b/code/modules/antagonists/heretic/magic/wave_of_desperation.dm @@ -0,0 +1,79 @@ +/datum/action/cooldown/spell/aoe/wave_of_desperation + name = "Wave Of Desperation" + desc = "Removes your restraints, repels and knocks down adjacent people, and applies certain effects of the Mansus Grasp upon everything nearby. \ + Cannot be cast unless you are restrained, and the stress renders you unconscious 12 seconds later!" + background_icon_state = "bg_heretic" + overlay_icon_state = "bg_heretic_border" + button_icon = 'icons/mob/actions/actions_ecult.dmi' + button_icon_state = "uncuff" + sound = 'sound/magic/swap.ogg' + + school = SCHOOL_FORBIDDEN + cooldown_time = 5 MINUTES + + invocation = "F'K 'FF." + invocation_type = INVOCATION_WHISPER + spell_requirements = NONE + + aoe_radius = 3 + +/datum/action/cooldown/spell/aoe/wave_of_desperation/is_valid_target(mob/living/carbon/cast_on) + return ..() && istype(cast_on) && (cast_on.handcuffed || cast_on.legcuffed) + +// Before the cast, we do some small AOE damage around the caster +/datum/action/cooldown/spell/aoe/wave_of_desperation/before_cast(mob/living/carbon/cast_on) + . = ..() + if(. & SPELL_CANCEL_CAST) + return + + if(cast_on.handcuffed) + cast_on.visible_message(span_danger("[cast_on.handcuffed] on [cast_on] shatter!")) + QDEL_NULL(cast_on.handcuffed) + if(cast_on.legcuffed) + cast_on.visible_message(span_danger("[cast_on.legcuffed] on [cast_on] shatters!")) + QDEL_NULL(cast_on.legcuffed) + + cast_on.apply_status_effect(/datum/status_effect/heretic_lastresort) + new /obj/effect/temp_visual/knockblast(get_turf(cast_on)) + + for(var/mob/living/victim in get_things_to_cast_on(cast_on, radius_override = 1)) + victim.AdjustKnockdown(3 SECONDS) + victim.AdjustParalyzed(0.5 SECONDS) + +/datum/action/cooldown/spell/aoe/wave_of_desperation/get_things_to_cast_on(atom/center, radius_override) + . = list() + for(var/atom/nearby in orange(center, radius_override ? radius_override : aoe_radius)) + if(nearby == owner || nearby == center || isarea(nearby)) + continue + if(!ismob(nearby)) + . += nearby + continue + var/mob/living/nearby_mob = nearby + if(!isturf(nearby_mob.loc)) + continue + if(IS_HERETIC_OR_MONSTER(nearby_mob)) + continue + if(nearby_mob.can_block_magic(antimagic_flags)) + continue + + . += nearby_mob + +/datum/action/cooldown/spell/aoe/wave_of_desperation/cast_on_thing_in_aoe(atom/victim, atom/caster) + if(!ismob(victim)) + SEND_SIGNAL(owner, COMSIG_HERETIC_MANSUS_GRASP_ATTACK_SECONDARY, victim) + + var/atom/movable/mover = victim + if(!istype(mover)) + return + + if(mover.anchored) + return + var/our_turf = get_turf(caster) + var/throwtarget = get_edge_target_turf(our_turf, get_dir(our_turf, get_step_away(mover, our_turf))) + mover.safe_throw_at(throwtarget, 3, 1, force = MOVE_FORCE_STRONG) + +/obj/effect/temp_visual/knockblast + icon = 'icons/effects/effects.dmi' + icon_state = "shield-flash" + alpha = 180 + duration = 1 SECONDS diff --git a/code/modules/antagonists/heretic/status_effects/buffs.dm b/code/modules/antagonists/heretic/status_effects/buffs.dm index 0f6809a898a..f1c96c51ad4 100644 --- a/code/modules/antagonists/heretic/status_effects/buffs.dm +++ b/code/modules/antagonists/heretic/status_effects/buffs.dm @@ -236,3 +236,53 @@ return addtimer(CALLBACK(src, PROC_REF(create_blade)), blade_recharge_time) + +/datum/status_effect/caretaker_refuge + id = "Caretaker’s Last Refuge" + status_type = STATUS_EFFECT_REFRESH + duration = -1 + alert_type = null + var/static/list/caretaking_traits = list(TRAIT_HANDS_BLOCKED, TRAIT_IGNORESLOWDOWN) + +/datum/status_effect/caretaker_refuge/on_apply() + owner.add_traits(caretaking_traits, TRAIT_STATUS_EFFECT(id)) + owner.status_flags |= GODMODE + animate(owner, alpha = 45,time = 0.5 SECONDS) + owner.density = FALSE + RegisterSignal(owner, SIGNAL_REMOVETRAIT(TRAIT_ALLOW_HERETIC_CASTING), PROC_REF(on_focus_lost)) + RegisterSignal(owner, COMSIG_MOB_BEFORE_SPELL_CAST, PROC_REF(prevent_spell_usage)) + RegisterSignal(owner, COMSIG_ATOM_HOLYATTACK, PROC_REF(nullrod_handler)) + return TRUE + +/datum/status_effect/caretaker_refuge/on_remove() + owner.remove_traits(caretaking_traits, TRAIT_STATUS_EFFECT(id)) + owner.status_flags &= ~GODMODE + owner.alpha = initial(owner.alpha) + owner.density = initial(owner.density) + UnregisterSignal(owner, SIGNAL_REMOVETRAIT(TRAIT_ALLOW_HERETIC_CASTING)) + UnregisterSignal(owner, COMSIG_MOB_BEFORE_SPELL_CAST) + UnregisterSignal(owner, COMSIG_ATOM_HOLYATTACK) + owner.visible_message( + span_warning("The haze around [owner] disappears, leaving them materialized!"), + span_notice("You exit the refuge."), + ) + +/datum/status_effect/caretaker_refuge/get_examine_text() + return span_warning("[owner.p_Theyre()] enveloped in an unholy haze!") + +/datum/status_effect/caretaker_refuge/proc/nullrod_handler(datum/source, obj/item/weapon) + SIGNAL_HANDLER + playsound(get_turf(owner), 'sound/effects/curse1.ogg', 80, TRUE) + owner.visible_message(span_warning("[weapon] repels the haze around [owner]!")) + owner.remove_status_effect(type) + +/datum/status_effect/caretaker_refuge/proc/on_focus_lost() + SIGNAL_HANDLER + to_chat(owner, span_danger("Without a focus, your refuge weakens and dissipates!")) + owner.remove_status_effect(type) + +/datum/status_effect/caretaker_refuge/proc/prevent_spell_usage(datum/source, datum/spell) + SIGNAL_HANDLER + if(!istype(spell, /datum/action/cooldown/spell/caretaker)) + owner.balloon_alert(owner, "may not cast spells in refuge!") + return SPELL_CANCEL_CAST diff --git a/code/modules/antagonists/heretic/status_effects/debuffs.dm b/code/modules/antagonists/heretic/status_effects/debuffs.dm index 55c5af3aa08..c286c7b5092 100644 --- a/code/modules/antagonists/heretic/status_effects/debuffs.dm +++ b/code/modules/antagonists/heretic/status_effects/debuffs.dm @@ -192,3 +192,25 @@ /datum/status_effect/star_mark/extended duration = 3 MINUTES + +// Last Resort +/datum/status_effect/heretic_lastresort + id = "heretic_lastresort" + alert_type = /atom/movable/screen/alert/status_effect/heretic_lastresort + duration = 12 SECONDS + status_type = STATUS_EFFECT_REPLACE + tick_interval = -1 + +/atom/movable/screen/alert/status_effect/heretic_lastresort + name = "Last Resort" + desc = "Your head spins, heart pumping as fast as it can, losing the fight with the ground. Run to safety!" + icon_state = "lastresort" + +/datum/status_effect/heretic_lastresort/on_apply() + ADD_TRAIT(owner, TRAIT_IGNORESLOWDOWN, TRAIT_STATUS_EFFECT(id)) + to_chat(owner, span_userdanger("You are on the brink of losing consciousness, run!")) + return TRUE + +/datum/status_effect/heretic_lastresort/on_remove() + REMOVE_TRAIT(owner, TRAIT_IGNORESLOWDOWN, TRAIT_STATUS_EFFECT(id)) + owner.AdjustUnconscious(20 SECONDS, ignore_canstun = TRUE) diff --git a/code/modules/antagonists/heretic/status_effects/mark_effects.dm b/code/modules/antagonists/heretic/status_effects/mark_effects.dm index d5f759ec962..068570f76c7 100644 --- a/code/modules/antagonists/heretic/status_effects/mark_effects.dm +++ b/code/modules/antagonists/heretic/status_effects/mark_effects.dm @@ -246,3 +246,17 @@ new teleport_effect(get_turf(owner)) owner.Paralyze(2 SECONDS) return ..() + +// MARK OF KNOCK + +/datum/status_effect/eldritch/knock + effect_icon_state = "emark7" + duration = 10 SECONDS + +/datum/status_effect/eldritch/knock/on_apply() + . = ..() + ADD_TRAIT(owner, TRAIT_ALWAYS_NO_ACCESS, STATUS_EFFECT_TRAIT) + +/datum/status_effect/eldritch/knock/on_remove() + REMOVE_TRAIT(owner, TRAIT_ALWAYS_NO_ACCESS, STATUS_EFFECT_TRAIT) + return ..() diff --git a/code/modules/antagonists/heretic/structures/knock_final.dm b/code/modules/antagonists/heretic/structures/knock_final.dm new file mode 100644 index 00000000000..85face85609 --- /dev/null +++ b/code/modules/antagonists/heretic/structures/knock_final.dm @@ -0,0 +1,67 @@ +/obj/structure/knock_tear + name = "???" + desc = "It stares back. Theres no reason to remain. Run." + max_integrity = INFINITE + resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | UNACIDABLE | ACID_PROOF + icon = 'icons/obj/anomaly.dmi' + icon_state = "bhole3" + color = "#53277E" + light_color = "#53277E" //cooler purple + light_range = 20 + anchored = TRUE + density = FALSE + layer = HIGH_PIPE_LAYER //0.01 above sigil layer used by heretic runes + move_resist = INFINITY + var/datum/mind/ascendee + ///a static list of heretic summons, this shouldnt even matter enough to be static but whatever + var/static/list/monster_types + +/obj/structure/knock_tear/Initialize(mapload, ascendant) + . = ..() + transform *= 3 + if(!monster_types) + monster_types = subtypesof(/mob/living/simple_animal/hostile/heretic_summon) - /mob/living/simple_animal/hostile/heretic_summon/armsy/prime + if(ascendant) + ascendee = ascendant + SSpoints_of_interest.make_point_of_interest(src) + INVOKE_ASYNC(src, PROC_REF(poll_ghosts)) + +/obj/structure/knock_tear/proc/poll_ghosts() + var/list/candidates = poll_ghost_candidates("Would you like to be a random eldritch monster attacking the crew?", ROLE_SENTIENCE, ROLE_SENTIENCE, 10 SECONDS, POLL_IGNORE_HERETIC_MONSTER) + while(LAZYLEN(candidates)) + var/mob/dead/observer/candidate = pick_n_take(candidates) + ghost_to_monster(candidate, should_ask = FALSE) + +/obj/structure/knock_tear/attack_ghost(mob/user) + . = ..() + if(.) + return + ghost_to_monster(user) + +/obj/structure/knock_tear/proc/ghost_to_monster(mob/dead/observer/user, should_ask = TRUE) + if(should_ask) + var/ask = tgui_alert(user, "Become a monster?", "Ascended Rift", list("Yes", "No")) + if(ask != "Yes" || QDELETED(src) || QDELETED(user)) + return FALSE + var/monster_type = pick(monster_types) + var/mob/living/monster = new monster_type(loc) + monster.key = user.key + monster.set_name() + var/datum/antagonist/heretic_monster/woohoo_free_antag = new(src) + monster.mind.add_antag_datum(woohoo_free_antag) + if(ascendee) + monster.faction = ascendee.current.faction + woohoo_free_antag.set_owner(ascendee) + var/datum/objective/kill_all_your_friends = new() + kill_all_your_friends.owner = monster.mind + kill_all_your_friends.explanation_text = "The station's crew must be culled." + kill_all_your_friends.completed = TRUE + woohoo_free_antag.objectives += kill_all_your_friends + +/obj/structure/knock_tear/move_crushed(atom/movable/pusher, force = MOVE_FORCE_DEFAULT, direction) + return FALSE + +/obj/structure/knock_tear/Destroy(force) //this shouldnt happen but hey + if(ascendee) + ascendee = null + return ..() diff --git a/code/modules/jobs/access.dm b/code/modules/jobs/access.dm index 2a52705a132..7502165f811 100644 --- a/code/modules/jobs/access.dm +++ b/code/modules/jobs/access.dm @@ -6,6 +6,8 @@ return TRUE if(result_bitflags & COMPONENT_OBJ_DISALLOW) // override all other checks return FALSE + if(HAS_TRAIT(accessor, TRAIT_ALWAYS_NO_ACCESS)) + return FALSE //check if it doesn't require any access at all if(check_access(null)) return TRUE diff --git a/code/modules/mob/living/blood.dm b/code/modules/mob/living/blood.dm index 9608db4d4c6..9354f02e2b2 100644 --- a/code/modules/mob/living/blood.dm +++ b/code/modules/mob/living/blood.dm @@ -88,7 +88,7 @@ //Makes a blood drop, leaking amt units of blood from the mob /mob/living/carbon/proc/bleed(amt) - if(!blood_volume) + if(!blood_volume || (status_flags & GODMODE)) return blood_volume = max(blood_volume - amt, 0) diff --git a/icons/effects/effects.dmi b/icons/effects/effects.dmi index bad30238246..29e59dc6c71 100644 Binary files a/icons/effects/effects.dmi and b/icons/effects/effects.dmi differ diff --git a/icons/effects/eldritch.dmi b/icons/effects/eldritch.dmi index 40d4ea80df2..8b7738f3b46 100644 Binary files a/icons/effects/eldritch.dmi and b/icons/effects/eldritch.dmi differ diff --git a/icons/hud/screen_alert.dmi b/icons/hud/screen_alert.dmi index 944337b18e5..a1fc01434e4 100644 Binary files a/icons/hud/screen_alert.dmi and b/icons/hud/screen_alert.dmi differ diff --git a/icons/mob/actions/actions_ecult.dmi b/icons/mob/actions/actions_ecult.dmi index a684dd1fbe6..747b57949be 100644 Binary files a/icons/mob/actions/actions_ecult.dmi and b/icons/mob/actions/actions_ecult.dmi differ diff --git a/icons/mob/inhands/64x64_lefthand.dmi b/icons/mob/inhands/64x64_lefthand.dmi index 26c177f7293..8a6bab69776 100644 Binary files a/icons/mob/inhands/64x64_lefthand.dmi and b/icons/mob/inhands/64x64_lefthand.dmi differ diff --git a/icons/mob/inhands/64x64_righthand.dmi b/icons/mob/inhands/64x64_righthand.dmi index 79c30f5cb19..251458590bd 100644 Binary files a/icons/mob/inhands/64x64_righthand.dmi and b/icons/mob/inhands/64x64_righthand.dmi differ diff --git a/icons/obj/service/library.dmi b/icons/obj/service/library.dmi index dfd8aca6b89..8229c1fc394 100644 Binary files a/icons/obj/service/library.dmi and b/icons/obj/service/library.dmi differ diff --git a/icons/obj/weapons/khopesh.dmi b/icons/obj/weapons/khopesh.dmi index 4bbd4d5f0f9..ab7a0c252cb 100644 Binary files a/icons/obj/weapons/khopesh.dmi and b/icons/obj/weapons/khopesh.dmi differ diff --git a/icons/ui_icons/achievements/achievements.dmi b/icons/ui_icons/achievements/achievements.dmi index ad34dfd16f0..b3e64c9d09f 100644 Binary files a/icons/ui_icons/achievements/achievements.dmi and b/icons/ui_icons/achievements/achievements.dmi differ diff --git a/sound/magic/hereticknock.ogg b/sound/magic/hereticknock.ogg new file mode 100644 index 00000000000..87ca57302a2 Binary files /dev/null and b/sound/magic/hereticknock.ogg differ diff --git a/tgstation.dme b/tgstation.dme index 6c75e06e53c..1c463faa4c4 100644 --- a/tgstation.dme +++ b/tgstation.dme @@ -2854,17 +2854,21 @@ #include "code\modules\antagonists\heretic\items\heretic_blades.dm" #include "code\modules\antagonists\heretic\items\heretic_necks.dm" #include "code\modules\antagonists\heretic\items\hunter_rifle.dm" +#include "code\modules\antagonists\heretic\items\keyring.dm" +#include "code\modules\antagonists\heretic\items\lintel.dm" #include "code\modules\antagonists\heretic\items\madness_mask.dm" #include "code\modules\antagonists\heretic\knowledge\ash_lore.dm" #include "code\modules\antagonists\heretic\knowledge\blade_lore.dm" #include "code\modules\antagonists\heretic\knowledge\cosmic_lore.dm" #include "code\modules\antagonists\heretic\knowledge\flesh_lore.dm" #include "code\modules\antagonists\heretic\knowledge\general_side.dm" +#include "code\modules\antagonists\heretic\knowledge\knock_lore.dm" #include "code\modules\antagonists\heretic\knowledge\rust_lore.dm" #include "code\modules\antagonists\heretic\knowledge\side_ash_flesh.dm" #include "code\modules\antagonists\heretic\knowledge\side_blade_rust.dm" #include "code\modules\antagonists\heretic\knowledge\side_cosmos_ash.dm" #include "code\modules\antagonists\heretic\knowledge\side_flesh_void.dm" +#include "code\modules\antagonists\heretic\knowledge\side_knock_flesh.dm" #include "code\modules\antagonists\heretic\knowledge\side_rust_cosmos.dm" #include "code\modules\antagonists\heretic\knowledge\side_void_blade.dm" #include "code\modules\antagonists\heretic\knowledge\starting_lore.dm" @@ -2874,10 +2878,14 @@ #include "code\modules\antagonists\heretic\knowledge\sacrifice_knowledge\sacrifice_map.dm" #include "code\modules\antagonists\heretic\knowledge\sacrifice_knowledge\sacrifice_moodlets.dm" #include "code\modules\antagonists\heretic\magic\aggressive_spread.dm" +#include "code\modules\antagonists\heretic\magic\apetravulnera.dm" +#include "code\modules\antagonists\heretic\magic\ascended_shapeshift.dm" #include "code\modules\antagonists\heretic\magic\ash_ascension.dm" #include "code\modules\antagonists\heretic\magic\ash_jaunt.dm" #include "code\modules\antagonists\heretic\magic\blood_cleave.dm" #include "code\modules\antagonists\heretic\magic\blood_siphon.dm" +#include "code\modules\antagonists\heretic\magic\burglar_finesse.dm" +#include "code\modules\antagonists\heretic\magic\caretaker.dm" #include "code\modules\antagonists\heretic\magic\cosmic_expansion.dm" #include "code\modules\antagonists\heretic\magic\cosmic_runes.dm" #include "code\modules\antagonists\heretic\magic\eldritch_blind.dm" @@ -2905,12 +2913,14 @@ #include "code\modules\antagonists\heretic\magic\void_cold_cone.dm" #include "code\modules\antagonists\heretic\magic\void_phase.dm" #include "code\modules\antagonists\heretic\magic\void_pull.dm" +#include "code\modules\antagonists\heretic\magic\wave_of_desperation.dm" #include "code\modules\antagonists\heretic\mobs\maid_in_mirror.dm" #include "code\modules\antagonists\heretic\status_effects\buffs.dm" #include "code\modules\antagonists\heretic\status_effects\debuffs.dm" #include "code\modules\antagonists\heretic\status_effects\ghoul.dm" #include "code\modules\antagonists\heretic\status_effects\mark_effects.dm" #include "code\modules\antagonists\heretic\structures\carving_knife.dm" +#include "code\modules\antagonists\heretic\structures\knock_final.dm" #include "code\modules\antagonists\heretic\structures\mawed_crucible.dm" #include "code\modules\antagonists\highlander\highlander.dm" #include "code\modules\antagonists\hypnotized\hypnotized.dm"