diff --git a/code/__DEFINES/traits/declarations.dm b/code/__DEFINES/traits/declarations.dm index 6600242d5a9..38500df0291 100644 --- a/code/__DEFINES/traits/declarations.dm +++ b/code/__DEFINES/traits/declarations.dm @@ -1551,4 +1551,7 @@ Remember to update _globalvars/traits.dm if you're adding/removing/renaming trai /// Trait that makes mobs with it immune to mining gear AOE attacks #define TRAIT_MINING_AOE_IMMUNE "mining_aoe_immune" +/// Trait that allows an item to perform holy rites akin to a nullrod +#define TRAIT_NULLROD_ITEM "nullrod_item" + // END TRAIT DEFINES diff --git a/code/_globalvars/traits/_traits.dm b/code/_globalvars/traits/_traits.dm index 8cf7f0d0183..820d77d60d5 100644 --- a/code/_globalvars/traits/_traits.dm +++ b/code/_globalvars/traits/_traits.dm @@ -680,6 +680,7 @@ GLOBAL_LIST_INIT(traits_by_type, list( "TRAIT_NO_SIDE_KICK" = TRAIT_NO_SIDE_KICK, "TRAIT_NODROP" = TRAIT_NODROP, "TRAIT_NO_WORN_ICON" = TRAIT_NO_WORN_ICON, + "TRAIT_NULLROD_ITEM" = TRAIT_NULLROD_ITEM, "TRAIT_OMNI_BAIT" = TRAIT_OMNI_BAIT, "TRAIT_PLANT_WILDMUTATE" = TRAIT_PLANT_WILDMUTATE, "TRAIT_POISONOUS_BAIT" = TRAIT_POISONOUS_BAIT, diff --git a/code/modules/antagonists/cult/runes.dm b/code/modules/antagonists/cult/runes.dm index 4c781158da5..bdbe7447921 100644 --- a/code/modules/antagonists/cult/runes.dm +++ b/code/modules/antagonists/cult/runes.dm @@ -428,29 +428,36 @@ structure_check() searches for nearby cultist structures required for the invoca /// Tries to convert a null rod over the rune to a cult sword /obj/effect/rune/convert/proc/try_spawn_sword() - for(var/obj/item/nullrod/rod in loc) - if(rod.anchored || (rod.resistance_flags & INDESTRUCTIBLE)) + for(var/obj/item/potential_rod in loc) + if(!HAS_TRAIT(potential_rod, TRAIT_NULLROD_ITEM)) continue - var/num_slain = LAZYLEN(rod.cultists_slain) - var/displayed_message = "[rod] glows an unholy red and begins to transform..." - if(GET_ATOM_BLOOD_DNA_LENGTH(rod)) - displayed_message += " The blood of [num_slain] fallen cultist[num_slain == 1 ? "":"s"] is absorbed into [rod]!" + if(potential_rod.anchored || (potential_rod.resistance_flags & INDESTRUCTIBLE)) + continue - rod.visible_message(span_cult_italic(displayed_message)) + var/num_slain = 0 + if (istype(potential_rod, /obj/item/nullrod)) + var/obj/item/nullrod/actual_rod = potential_rod + num_slain = LAZYLEN(actual_rod.cultists_slain) + + var/displayed_message = "[potential_rod] glows an unholy red and begins to transform..." + if(num_slain && GET_ATOM_BLOOD_DNA_LENGTH(potential_rod)) + displayed_message += " The blood of [num_slain] fallen cultist[num_slain == 1 ? "":"s"] is absorbed into [potential_rod]!" + + potential_rod.visible_message(span_cult_italic(displayed_message)) switch(num_slain) if(0) - animate_spawn_sword(rod, /obj/item/melee/cultblade/dagger) + animate_spawn_sword(potential_rod, /obj/item/melee/cultblade/dagger) if(1) - animate_spawn_sword(rod, /obj/item/melee/cultblade) + animate_spawn_sword(potential_rod, /obj/item/melee/cultblade) else - animate_spawn_sword(rod, /obj/item/melee/cultblade/halberd) + animate_spawn_sword(potential_rod, /obj/item/melee/cultblade/halberd) return TRUE return FALSE /// Does an animation of a null rod transforming into a cult sword -/obj/effect/rune/convert/proc/animate_spawn_sword(obj/item/nullrod/former_rod, new_blade_typepath) +/obj/effect/rune/convert/proc/animate_spawn_sword(obj/item/former_rod, new_blade_typepath) playsound(src, 'sound/effects/magic.ogg', 33, vary = TRUE, extrarange = SILENCED_SOUND_EXTRARANGE, frequency = 0.66) former_rod.anchored = TRUE former_rod.Shake() diff --git a/code/modules/antagonists/heretic/structures/carving_knife.dm b/code/modules/antagonists/heretic/structures/carving_knife.dm index 5b2f8743691..289b1784c4d 100644 --- a/code/modules/antagonists/heretic/structures/carving_knife.dm +++ b/code/modules/antagonists/heretic/structures/carving_knife.dm @@ -190,7 +190,7 @@ return ..() /obj/structure/trap/eldritch/item_interaction(mob/living/user, obj/item/tool, list/modifiers) - if(istype(tool, /obj/item/melee/rune_carver) || istype(tool, /obj/item/nullrod)) + if(istype(tool, /obj/item/melee/rune_carver) || HAS_TRAIT(tool, TRAIT_NULLROD_ITEM)) loc.balloon_alert(user, "carving dispelled") playsound(src, 'sound/items/sheath.ogg', 50, TRUE, SHORT_RANGE_SOUND_EXTRARANGE, ignore_walls = FALSE) qdel(src) diff --git a/code/modules/antagonists/revenant/haunted_item.dm b/code/modules/antagonists/revenant/haunted_item.dm index 642002976cb..bd1cac77fb7 100644 --- a/code/modules/antagonists/revenant/haunted_item.dm +++ b/code/modules/antagonists/revenant/haunted_item.dm @@ -7,6 +7,8 @@ var/despawn_message /// List of types that, if they hit our item, we will instantly stop the haunting var/list/types_which_dispell_us + /// List of traits which allow items outside of types_which_dispell_us to also work on us + var/list/traits_which_dispell_us /datum/component/haunted_item/Initialize( // What color should the haunted item be glowing? By default the color's white (passed into the haunted element). @@ -25,6 +27,9 @@ throw_force_max = 15, // See the types_which_dispell_us list. By default / if null, this will become the default static list. list/types_which_dispell_us, + // List of traits which allow items outside of types_which_dispell_us to also work on us + // By default / if null will default to TRAIT_NULLROD_ITEM + list/traits_which_dispell_us, ) if(!isitem(parent)) @@ -62,7 +67,9 @@ haunted_item.throwforce = min(haunted_item.throwforce + throw_force_bonus, throw_force_max) var/static/list/default_dispell_types = list(/obj/item/nullrod, /obj/item/book/bible) + var/static/list/default_dispell_traits = list(TRAIT_NULLROD_ITEM) src.types_which_dispell_us = types_which_dispell_us || default_dispell_types + src.traits_which_dispell_us = traits_which_dispell_us || default_dispell_traits src.despawn_message = despawn_message /datum/component/haunted_item/Destroy(force) @@ -94,7 +101,14 @@ SIGNAL_HANDLER if(!is_type_in_list(attacking_item, types_which_dispell_us)) - return + var/has_trait = FALSE + for(var/dispell_trait in traits_which_dispell_us) + if(HAS_TRAIT(attacking_item, dispell_trait)) + has_trait = TRUE + break + + if(!has_trait) + return attacker.visible_message(span_warning("[attacker] dispells the ghostly energy from [source]!"), span_warning("You dispel the ghostly energy from [source]!")) clear_haunting() diff --git a/code/modules/antagonists/wizard/equipment/artefact.dm b/code/modules/antagonists/wizard/equipment/artefact.dm index bee49757a18..4d90d4aa53b 100644 --- a/code/modules/antagonists/wizard/equipment/artefact.dm +++ b/code/modules/antagonists/wizard/equipment/artefact.dm @@ -63,13 +63,13 @@ qdel(src) return PROCESS_KILL -/obj/effect/rend/attackby(obj/item/I, mob/user, list/modifiers, list/attack_modifiers) - if(istype(I, /obj/item/nullrod)) - user.visible_message(span_danger("[user] seals \the [src] with \the [I].")) - qdel(src) - return - else - return ..() +/obj/effect/rend/item_interaction(mob/living/user, obj/item/tool, list/modifiers) + if(!HAS_TRAIT(tool, TRAIT_NULLROD_ITEM)) + return NONE + + user.visible_message(span_danger("[user] seals \the [src] with \the [tool].")) + qdel(src) + return ITEM_INTERACT_SUCCESS /obj/effect/rend/singularity_act() return diff --git a/code/modules/jobs/job_types/chaplain/chaplain_nullrod.dm b/code/modules/jobs/job_types/chaplain/chaplain_nullrod.dm index f48bbcc1e76..0c1ec753d15 100644 --- a/code/modules/jobs/job_types/chaplain/chaplain_nullrod.dm +++ b/code/modules/jobs/job_types/chaplain/chaplain_nullrod.dm @@ -36,30 +36,37 @@ effects_we_clear = list(/obj/effect/rune, /obj/effect/heretic_rune, /obj/effect/cosmic_rune), \ ) AddElement(/datum/element/bane, mob_biotypes = MOB_SPIRIT, damage_multiplier = 0, added_damage = 25, requires_combat_mode = FALSE) + ADD_TRAIT(src, TRAIT_NULLROD_ITEM, INNATE_TRAIT) - if((!GLOB.holy_weapon_type || !station_holy_item) && type == /obj/item/nullrod) - var/list/rods = list() - for(var/obj/item/nullrod/nullrod_type as anything in typesof(/obj/item/nullrod)) - if(!initial(nullrod_type.chaplain_spawnable)) - continue - rods[nullrod_type] = initial(nullrod_type.menu_description) - //special non-nullrod subtyped shit - rods[/obj/item/gun/ballistic/bow/divine/with_quiver] = "A divine bow and 10 quivered holy arrows." - rods[/obj/item/organ/cyberimp/arm/toolkit/shard/scythe] = "A shard that implants itself into your arm, \ - allowing you to conjure forth a vorpal scythe. \ - Allows you to behead targets for empowered strikes. \ - Harms you if you dismiss the scythe without first causing harm to a creature. \ - The shard also causes you to become Morbid, shifting your interests towards the macabre." - rods[/obj/item/melee/skateboard/holyboard] = "A skateboard that grants you flight and anti-magic abilities while ridden. Fits in your bag." - //bubberstation edit - start - rods[/obj/item/dualsaber/chaplain] = "A huge energy blade, it possesses the unique ability to block projectiles, but the unwieldy nature of it \ -means that you'll be forced to move carefully while it's on. Fits in pockets, and can be worn on the belt when off." - //bubberstation edit - end - AddComponent(/datum/component/subtype_picker, rods, CALLBACK(src, PROC_REF(on_holy_weapon_picked))) + if((GLOB.holy_weapon_type && station_holy_item) || type != /obj/item/nullrod) + return + + var/list/rods = list() + for(var/obj/item/nullrod/nullrod_type as anything in typesof(/obj/item/nullrod)) + if(!initial(nullrod_type.chaplain_spawnable)) + continue + rods[nullrod_type] = initial(nullrod_type.menu_description) + //special non-nullrod subtyped shit + rods[/obj/item/gun/ballistic/bow/divine/with_quiver] = "A divine bow and 10 quivered holy arrows." + rods[/obj/item/organ/cyberimp/arm/toolkit/shard/scythe] = "A shard that implants itself into your arm, \ + allowing you to conjure forth a vorpal scythe. \ + Allows you to behead targets for empowered strikes. \ + Harms you if you dismiss the scythe without first causing harm to a creature. \ + The shard also causes you to become Morbid, shifting your interests towards the macabre." + rods[/obj/item/melee/skateboard/holyboard] = "A skateboard that grants you flight and anti-magic abilities while ridden. Fits in your bag." + // BUBBER EDIT ADDITION BEGIN + rods[/obj/item/dualsaber/chaplain] = "A huge energy blade, it possesses the unique ability to block projectiles, but the unwieldy nature of it \ + means that you'll be forced to move carefully while it's on. Fits in pockets, and can be worn on the belt when off." + // BUBBER EDIT ADDITION END + AddComponent(/datum/component/subtype_picker, rods, CALLBACK(src, PROC_REF(on_holy_weapon_picked))) /// Callback for subtype picker, invoked when the chaplain picks a new nullrod /obj/item/nullrod/proc/on_holy_weapon_picked(obj/item/nullrod/new_holy_weapon, mob/living/picker) - new_holy_weapon.on_selected(src, picker) + // Some nullrod variants aren't nullrod subtypes + if(istype(new_holy_weapon)) + new_holy_weapon.on_selected(src, picker) + else // In which case they still need to be marked as one + ADD_TRAIT(new_holy_weapon, TRAIT_NULLROD_ITEM, INNATE_TRAIT) if(!station_holy_item) return GLOB.holy_weapon_type = new_holy_weapon.type diff --git a/code/modules/jobs/job_types/chaplain/chaplain_vorpal_scythe.dm b/code/modules/jobs/job_types/chaplain/chaplain_vorpal_scythe.dm index 57a786bd20d..f521b7603ec 100644 --- a/code/modules/jobs/job_types/chaplain/chaplain_vorpal_scythe.dm +++ b/code/modules/jobs/job_types/chaplain/chaplain_vorpal_scythe.dm @@ -11,6 +11,11 @@ If the scythe isn't empowered when you sheath it, you take a heap of damage and items_to_create = list(/obj/item/vorpalscythe) organ_traits = list(TRAIT_MORBID) +/obj/item/organ/cyberimp/arm/toolkit/shard/scythe/Initialize(mapload) + . = ..() + for (var/obj/item/scythe as anything in items_list) + ADD_TRAIT(scythe, TRAIT_NULLROD_ITEM, INNATE_TRAIT) + /obj/item/organ/cyberimp/arm/toolkit/shard/scythe/Retract() var/obj/item/vorpalscythe/scythe = active_item if(!scythe) diff --git a/code/modules/religion/burdened/psyker.dm b/code/modules/religion/burdened/psyker.dm index 6a608059c49..2ffde313f6d 100644 --- a/code/modules/religion/burdened/psyker.dm +++ b/code/modules/religion/burdened/psyker.dm @@ -100,15 +100,16 @@ 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 ..() + for(var/obj/item/possible_rod in get_turf(religious_tool)) + if(HAS_TRAIT(possible_rod, TRAIT_NULLROD_ITEM)) + transformation_target = possible_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 + var/obj/item/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!"))