diff --git a/code/_onclick/hud/alert.dm b/code/_onclick/hud/alert.dm index 180e5a55e64..2eb3d0b36ed 100644 --- a/code/_onclick/hud/alert.dm +++ b/code/_onclick/hud/alert.dm @@ -308,6 +308,11 @@ or shoot a gun to move around via Newton's 3rd Law of Motion." var/mob/living/L = usr return L.resist() +//Constructs +/obj/screen/alert/holy_fire + name = "Holy Fire" + desc = "Your body is crumbling from the holy energies. Get out." + icon_state = "fire" //ALIENS diff --git a/code/datums/spell.dm b/code/datums/spell.dm index 6590876ea2f..fe2cc8e346b 100644 --- a/code/datums/spell.dm +++ b/code/datums/spell.dm @@ -121,6 +121,8 @@ GLOBAL_LIST_INIT(spells, typesof(/obj/effect/proc_holder/spell)) var/critfailchance = 0 var/centcom_cancast = TRUE //Whether or not the spell should be allowed on the admin zlevel + /// Whether or not the spell functions in a holy place + var/holy_area_cancast = TRUE var/datum/action/spell_action/action = null var/action_icon = 'icons/mob/actions/actions.dmi' @@ -561,6 +563,9 @@ GLOBAL_LIST_INIT(spells, typesof(/obj/effect/proc_holder/spell)) if(is_admin_level(user.z) && !centcom_cancast) //Certain spells are not allowed on the centcom zlevel return 0 + if(!holy_area_cancast && user.holy_check()) + return FALSE + if(charge_check) switch(charge_type) if("recharge") diff --git a/code/datums/spells/construct_spells.dm b/code/datums/spells/construct_spells.dm index 57dd43ad38c..071a8125b10 100644 --- a/code/datums/spells/construct_spells.dm +++ b/code/datums/spells/construct_spells.dm @@ -18,6 +18,7 @@ range = 0 summon_type = list(/turf/simulated/floor/engine/cult) centcom_cancast = FALSE //Stop crashing the server by spawning turfs on transit tiles + holy_area_cancast = FALSE //Stops cult magic from working on holy ground eg: chapel /obj/effect/proc_holder/spell/aoe_turf/conjure/wall name = "Summon Cult Wall" @@ -32,6 +33,7 @@ range = 0 summon_type = list(/turf/simulated/wall/cult/artificer) //we don't want artificer-based runed metal farms centcom_cancast = FALSE //Stop crashing the server by spawning turfs on transit tiles + holy_area_cancast = FALSE //Stops cult magic from working on holy ground eg: chapel /obj/effect/proc_holder/spell/aoe_turf/conjure/wall/reinforced name = "Greater Construction" @@ -43,6 +45,7 @@ invocation_type = "none" range = 0 centcom_cancast = FALSE //Stop crashing the server by spawning turfs on transit tiles + holy_area_cancast = FALSE //Stops cult magic from working on holy ground eg: chapel delay = 50 summon_type = list(/turf/simulated/wall/r_wall) @@ -58,6 +61,7 @@ invocation = "none" invocation_type = "none" range = 0 + holy_area_cancast = FALSE //Stops cult magic from working on holy ground eg: chapel summon_type = list(/obj/item/soulstone) @@ -77,6 +81,7 @@ invocation = "none" invocation_type = "none" range = 0 + holy_area_cancast = FALSE //Stops cult magic from working on holy ground eg: chapel summon_type = list(/obj/structure/cult/functional/pylon) @@ -92,6 +97,7 @@ invocation = "none" invocation_type = "none" range = 0 + holy_area_cancast = FALSE //Stops cult magic from working on holy ground eg: chapel summon_type = list(/obj/effect/forcefield/cult) summon_lifespan = 200 @@ -111,6 +117,7 @@ clothes_req = FALSE invocation = "none" invocation_type = "none" + holy_area_cancast = FALSE //Stops cult magic from working on holy ground eg: chapel jaunt_in_time = 12 jaunt_in_type = /obj/effect/temp_visual/dir_setting/wraith jaunt_out_type = /obj/effect/temp_visual/dir_setting/wraith/out @@ -137,6 +144,7 @@ clothes_req = FALSE invocation = "none" invocation_type = "none" + holy_area_cancast = FALSE //Stops cult magic from working on holy ground eg: chapel proj_lifespan = 10 max_targets = 6 @@ -150,6 +158,7 @@ clothes_req = FALSE invocation = "none" invocation_type = "none" + holy_area_cancast = FALSE //Stops cult magic from working on holy ground eg: chapel range = -1 include_user = 1 cooldown_min = 20 //25 deciseconds reduction per rank diff --git a/code/game/area/ss13_areas.dm b/code/game/area/ss13_areas.dm index ad9bd70098e..3666ba2fdfc 100644 --- a/code/game/area/ss13_areas.dm +++ b/code/game/area/ss13_areas.dm @@ -971,6 +971,7 @@ NOTE: there are two lists of areas in the end of this file: centcom and station ambientsounds = HOLY_SOUNDS is_haunted = TRUE sound_environment = SOUND_AREA_LARGE_ENCLOSED + valid_territory = FALSE /area/chapel/main name = "\improper Chapel" diff --git a/code/game/gamemodes/cult/blood_magic.dm b/code/game/gamemodes/cult/blood_magic.dm index 47a979fd108..f9d4edb105c 100644 --- a/code/game/gamemodes/cult/blood_magic.dm +++ b/code/game/gamemodes/cult/blood_magic.dm @@ -123,6 +123,8 @@ return ..() /datum/action/innate/cult/blood_spell/Activate() + if(owner.holy_check()) + return if(magic_path) // If this spell flows from the hand if(!hand_magic) // If you don't already have the spell active hand_magic = new magic_path(owner, src) @@ -178,6 +180,8 @@ ..() /datum/action/innate/cult/blood_spell/emp/Activate() + if(owner.holy_check()) + return owner.visible_message("[owner]'s body flashes a bright blue!", \ "You speak the cursed words, channeling an electromagnetic pulse from your body.") owner.emp_act(2) @@ -279,6 +283,8 @@ if(ranged_ability_user.incapacitated() || !iscultist(user)) user.ranged_ability.remove_ranged_ability(user) return + if(user.holy_check()) + return var/turf/T = get_turf(ranged_ability_user) if(!isturf(T)) return FALSE @@ -305,6 +311,8 @@ var/revealing = FALSE //if it reveals or not /datum/action/innate/cult/blood_spell/veiling/Activate() + if(owner.holy_check()) + return if(!revealing) // Hiding stuff owner.visible_message("Thin grey dust falls from [owner]'s hand!", \ "You invoke the veiling spell, hiding nearby runes and cult structures.") @@ -425,6 +433,8 @@ var/mob/living/L = target if(iscultist(target)) return + if(user.holy_check()) + return user.visible_message("[user] holds up [user.p_their()] hand, which explodes in a flash of red light!", \ "You attempt to stun [L] with the spell!") @@ -461,6 +471,8 @@ invocation = "Sas'so c'arta forbici!" /obj/item/melee/blood_magic/teleport/afterattack(atom/target, mob/living/carbon/user, proximity) + if(user.holy_check()) + return var/list/potential_runes = list() var/list/teleportnames = list() var/list/duplicaterunecount = list() @@ -526,6 +538,8 @@ color = "#000000" // black /obj/item/melee/blood_magic/shackles/afterattack(atom/target, mob/living/carbon/user, proximity) + if(user.holy_check()) + return if(iscarbon(target) && proximity) var/mob/living/carbon/C = target if(C.canBeHandcuffed() || C.get_arm_ignore()) @@ -584,6 +598,8 @@ Airlocks into brittle runed airlocks after a delay (harm intent)"} /obj/item/melee/blood_magic/construction/afterattack(atom/target, mob/user, proximity_flag, click_parameters) + if(user.holy_check()) + return if(proximity_flag) if(channeling) to_chat(user, "You are already invoking twisted construction!") @@ -638,6 +654,8 @@ color = "#33cc33" // green /obj/item/melee/blood_magic/armor/afterattack(atom/target, mob/living/carbon/user, proximity) + if(user.holy_check()) + return if(iscarbon(target) && proximity) uses-- var/mob/living/carbon/C = target @@ -661,6 +679,8 @@ has_source = FALSE //special, only availible for a blood cost. /obj/item/melee/blood_magic/empower/afterattack(atom/target, mob/user, proximity_flag, click_parameters) + if(user.holy_check()) + return if(proximity_flag) // Shielded suit @@ -708,6 +728,8 @@ // This should really be split into multiple procs /obj/item/melee/blood_magic/manipulator/afterattack(atom/target, mob/living/carbon/human/user, proximity) + if(user.holy_check()) + return if(proximity) if(ishuman(target)) var/mob/living/carbon/human/H = target @@ -848,6 +870,8 @@ uses += max(1, temp) /obj/item/melee/blood_magic/manipulator/attack_self(mob/living/user) + if(user.holy_check()) + return var/list/options = list("Blood Orb (50)" = image(icon = 'icons/obj/cult.dmi', icon_state = "summoning_orb"), "Blood Recharge (75)" = image(icon = 'icons/mob/actions/actions_cult.dmi', icon_state = "blood_charge"), "Blood Spear (150)" = image(icon = 'icons/mob/actions/actions_cult.dmi', icon_state = "bloodspear"), diff --git a/code/game/gamemodes/cult/cult_actions.dm b/code/game/gamemodes/cult/cult_actions.dm index ab81f253a32..25a9275f684 100644 --- a/code/game/gamemodes/cult/cult_actions.dm +++ b/code/game/gamemodes/cult/cult_actions.dm @@ -27,6 +27,10 @@ /datum/action/innate/cult/comm/proc/cultist_commune(mob/living/user, message) if(!user || !message) return + + if(user.holy_check()) + return + if(!user.can_speak()) to_chat(user, "You can't speak!") return diff --git a/code/game/gamemodes/cult/cult_items.dm b/code/game/gamemodes/cult/cult_items.dm index 24ffbb96ce3..720dc4db4a0 100644 --- a/code/game/gamemodes/cult/cult_items.dm +++ b/code/game/gamemodes/cult/cult_items.dm @@ -159,7 +159,7 @@ user.Weaken(5) /obj/item/clothing/suit/hooded/cultrobes/cult_shield/hit_reaction(mob/living/carbon/human/owner, atom/movable/hitby, attack_text = "the attack", final_block_chance = 0, damage = 0, attack_type = MELEE_ATTACK) - if(current_charges) + if(current_charges && !owner.holy_check()) owner.visible_message("[attack_text] is deflected in a burst of blood-red sparks!") current_charges-- playsound(loc, "sparks", 100, TRUE, SHORT_RANGE_SOUND_EXTRARANGE) @@ -321,6 +321,7 @@ . = pulled /obj/item/cult_shift/attack_self(mob/user) + if(!uses || !iscarbon(user)) to_chat(user, "[src] is dull and unmoving in your hands.") return @@ -329,7 +330,8 @@ step(src, pick(GLOB.alldirs)) to_chat(user, "[src] flickers out of your hands, too eager to move!") return - + if(user.holy_check()) + return var/outer_tele_radius = 9 var/mob/living/carbon/C = user @@ -439,7 +441,7 @@ * The illusion has a 60% chance to be hostile and attack non-cultists, and a 40% chance to just run away from the user. */ /obj/item/shield/mirror/hit_reaction(mob/living/carbon/human/owner, atom/movable/hitby, attack_text = "the attack", final_block_chance = 0, damage = 0, attack_type = MELEE_ATTACK) - if(iscultist(owner)) // Cultist holding the shield + if(iscultist(owner) && !owner.holy_check()) // Cultist holding the shield // Hit by a projectile if(istype(hitby, /obj/item/projectile)) @@ -514,6 +516,10 @@ /obj/item/shield/mirror/IsReflect() if(prob(reflect_chance)) + if(istype(loc, /mob)) + var/mob/user = loc + if(user.holy_check()) + return FALSE return TRUE return FALSE @@ -599,7 +605,7 @@ spear = blood_spear /datum/action/innate/cult/spear/Activate() - if(owner == spear.loc || cooldown > world.time) + if(owner == spear.loc || cooldown > world.time || owner.holy_check()) return var/ST = get_turf(spear) var/OT = get_turf(owner) @@ -625,6 +631,12 @@ fire_sound = 'sound/magic/wand_teleport.ogg' flags = NOBLUDGEON | DROPDEL +/obj/item/gun/projectile/shotgun/boltaction/enchanted/arcane_barrage/blood/afterattack(atom/target, mob/living/user, flag, params) + if(user.holy_check()) + return + ..() + + /obj/item/ammo_box/magazine/internal/boltaction/enchanted/arcane_barrage/blood ammo_type = /obj/item/ammo_casing/magic/arcane_barrage/blood diff --git a/code/game/gamemodes/cult/cult_structures.dm b/code/game/gamemodes/cult/cult_structures.dm index 1638fa00faf..8eae3876082 100644 --- a/code/game/gamemodes/cult/cult_structures.dm +++ b/code/game/gamemodes/cult/cult_structures.dm @@ -58,6 +58,8 @@ /obj/structure/cult/functional/attackby(obj/item/I, mob/user, params) if(istype(I, /obj/item/melee/cultblade/dagger) && iscultist(user)) + if(user.holy_check()) + return anchored = !anchored to_chat(user, "You [anchored ? "":"un"]secure [src] [anchored ? "to":"from"] the floor.") if(!anchored) diff --git a/code/game/gamemodes/cult/runes.dm b/code/game/gamemodes/cult/runes.dm index 8c725b41898..203d370af8b 100644 --- a/code/game/gamemodes/cult/runes.dm +++ b/code/game/gamemodes/cult/runes.dm @@ -142,6 +142,8 @@ fail_invoke() is called when the rune fails, via not enough people around or oth structure_check() searches for nearby cultist structures required for the invocation. Proper structures are pylons, forges, archives, and altars. */ /obj/effect/rune/proc/can_invoke(mob/living/user) + if(user.holy_check()) + return //This proc determines if the rune can be invoked at the time. If there are multiple required cultists, it will find all nearby cultists. var/list/invokers = list() //people eligible to invoke the rune var/list/chanters = list() //people who will actually chant the rune when passed to invoke() diff --git a/code/game/gamemodes/miniantags/revenant/revenant.dm b/code/game/gamemodes/miniantags/revenant/revenant.dm index fa5af6b12ff..b1e9b2644a5 100644 --- a/code/game/gamemodes/miniantags/revenant/revenant.dm +++ b/code/game/gamemodes/miniantags/revenant/revenant.dm @@ -234,6 +234,8 @@ /mob/living/simple_animal/revenant/proc/castcheck(essence_cost) if(!src) return + if(holy_check(src)) + return var/turf/T = get_turf(src) if(istype(T, /turf/simulated/wall)) to_chat(src, "You cannot use abilities from inside of a wall.") diff --git a/code/game/gamemodes/vampire/vampire_powers.dm b/code/game/gamemodes/vampire/vampire_powers.dm index 0340352412a..36a24113dc9 100644 --- a/code/game/gamemodes/vampire/vampire_powers.dm +++ b/code/game/gamemodes/vampire/vampire_powers.dm @@ -7,10 +7,12 @@ range = 1 charge_max = 1800 action_background_icon_state = "bg_vampire" + holy_area_cancast = FALSE //Stops cult magic from working on holy ground eg: chapel var/required_blood = 0 var/gain_desc = null var/deduct_blood_on_cast = TRUE //Do we want to take the blood when this is cast, or at a later point? + /obj/effect/proc_holder/spell/vampire/New() ..() if(!gain_desc) @@ -40,10 +42,6 @@ if(vampire.bloodusable < required_blood) to_chat(user, "You require at least [required_blood] units of usable blood to do that!") return 0 - //chapel check - if(istype(loc.loc, /area/chapel) && !fullpower) - to_chat(user, "Your powers are useless on this holy ground.") - return 0 return ..() /obj/effect/proc_holder/spell/vampire/can_cast(mob/user = usr, charge_check = TRUE, show_message = FALSE) diff --git a/code/game/objects/items/stacks/sheets/sheet_types.dm b/code/game/objects/items/stacks/sheets/sheet_types.dm index 99dee4e4961..c3fefa499dd 100644 --- a/code/game/objects/items/stacks/sheets/sheet_types.dm +++ b/code/game/objects/items/stacks/sheets/sheet_types.dm @@ -378,6 +378,8 @@ GLOBAL_LIST_INIT(cult_recipes, list ( \ if(!iscultist(user)) to_chat(user, "Only one with forbidden knowledge could hope to work this metal...") return + if(usr.holy_check()) + return if(!is_level_reachable(user.z)) to_chat(user, "The energies of this place interfere with the metal shaping!") return diff --git a/code/game/objects/items/stacks/stack.dm b/code/game/objects/items/stacks/stack.dm index 7e331206016..f6d55c99669 100644 --- a/code/game/objects/items/stacks/stack.dm +++ b/code/game/objects/items/stacks/stack.dm @@ -25,7 +25,7 @@ var/to_transfer = 0 var/max_amount = 50 //also see stack recipes initialisation, param "max_res_amount" must be equal to this max_amount var/merge_type = null // This path and its children should merge with this stack, defaults to src.type - var/recipe_width = 400 //Width of the recipe popup + var/recipe_width = 400 //Width of the recipe popup var/recipe_height = 400 //Height of the recipe popup /obj/item/stack/New(loc, new_amount, merge = TRUE) @@ -209,9 +209,15 @@ to_chat(usr, "\The [R.title] must be constructed on the floor!") return FALSE - if(R.no_cult_structure && (locate(/obj/structure/cult) in usr.drop_location())) - to_chat(usr, "There is a structure here!") - return FALSE + if(R.no_cult_structure) + if(usr.holy_check()) + return + if(!is_level_reachable(usr.z)) + to_chat(usr, "The energies of this place interfere with the metal shaping!") + return + if(locate(/obj/structure/cult) in usr.drop_location()) + to_chat(usr, "There is a structure here!") + return FALSE if(R.time) to_chat(usr, "Building [R.title] ...") diff --git a/code/modules/mob/living/simple_animal/constructs.dm b/code/modules/mob/living/simple_animal/constructs.dm index 2e0f90ec24e..9d18bfbd53f 100644 --- a/code/modules/mob/living/simple_animal/constructs.dm +++ b/code/modules/mob/living/simple_animal/constructs.dm @@ -94,6 +94,17 @@ /mob/living/simple_animal/hostile/construct/electrocute_act(shock_damage, source, siemens_coeff = 1, flags = NONE) return FALSE +/mob/living/simple_animal/hostile/construct/Life(seconds, times_fired) + if(holy_check(src)) + throw_alert("holy_fire", /obj/screen/alert/holy_fire, override = TRUE) + visible_message("[src] slowly crumbles to dust in this holy place!", \ + "Your shell burns as you crumble to dust in this holy place!") + playsound(loc, 'sound/items/welder.ogg', 150, TRUE) + adjustBruteLoss(maxHealth/8) + else + clear_alert("holy_fire", clear_override = TRUE) + return ..() + /////////////////Juggernaut/////////////// diff --git a/code/modules/mob/mob.dm b/code/modules/mob/mob.dm index d9df2550ae9..24d95fa1534 100644 --- a/code/modules/mob/mob.dm +++ b/code/modules/mob/mob.dm @@ -1461,3 +1461,31 @@ GLOBAL_LIST_INIT(slot_equipment_priority, list( \ */ /mob/proc/update_runechat_msg_location() return + +GLOBAL_LIST_INIT(holy_areas, typecacheof(list( + /area/chapel +))) + +/mob/proc/holy_check() + if(!is_type_in_typecache(loc.loc, GLOB.holy_areas)) + return FALSE + + if(!mind) + return FALSE + + //Allows fullpower vampires to bypass holy areas + var/datum/vampire/vampire = mind.vampire + if(vampire && vampire.get_ability(/datum/vampire_passive/full)) + return FALSE + + //Allows cult to bypass holy areas once they summon + var/datum/game_mode/gamemode = SSticker.mode + if(iscultist(src) && gamemode.cult_objs.cult_status == NARSIE_HAS_RISEN) + return FALSE + + //Execption for Holy Constructs + if(isconstruct(src) && !iscultist(src)) + return FALSE + + to_chat(src, "Your powers are useless on this holy ground.") + return TRUE