Fixes spirit holding component not working on null rods by adding the subtype picker component to null rods (#60767)

Null rods were not calling parent on attack_self and thus not sending signals to the component. DUMB! STINKY!!!!

I have elected to make subtype picking a component itself so this mistake will never be remade

fixes #60712 (possessed blades cannot awaken a spirit)

also, fixes spirit holder not making sounds
This commit is contained in:
tralezab
2021-10-02 00:11:55 -07:00
committed by GitHub
parent 72bb15f70f
commit d9329f3e8f
4 changed files with 105 additions and 63 deletions
+2 -2
View File
@@ -101,10 +101,10 @@
/datum/component/spirit_holding/proc/attempt_exorcism(mob/exorcist)
var/atom/movable/exorcised_movable = parent
to_chat(exorcist, span_notice("You begin to exorcise [parent]..."))
playsound(src,'sound/hallucinations/veryfar_noise.ogg',40,TRUE)
playsound(parent, 'sound/hallucinations/veryfar_noise.ogg',40,TRUE)
if(!do_after(exorcist, 4 SECONDS, target = exorcised_movable))
return
playsound(src,'sound/effects/pray_chaplain.ogg',60,TRUE)
playsound(parent, 'sound/effects/pray_chaplain.ogg',60,TRUE)
UnregisterSignal(exorcised_movable, list(COMSIG_ATOM_RELAYMOVE, COMSIG_BIBLE_SMACKED))
RegisterSignal(exorcised_movable, COMSIG_ITEM_ATTACK_SELF, .proc/on_attack_self)
to_chat(bound_spirit, span_userdanger("You were exorcised!"))
+88
View File
@@ -0,0 +1,88 @@
/**
* subtype picker component allows for an item to transform into its subtypes (this is not enforced and you can turn in whatever types, but
* i used this name as it was incredibly accurate for current usage of the behavior)
*
* Used for the null rod to pick the other holy weapons.
*/
/datum/component/subtype_picker
///A list of types and their menu descriptions
var/list/subtype2descriptions
///list given to the radial menu to display, built after init
var/list/built_radial_list
///the radial will return a name of the wanted subtype, this is a list of names back to the type, built after init
var/list/name2subtype
///optional proc to callback to when the weapon is picked
var/datum/callback/on_picked_callback
/datum/component/subtype_picker/Initialize(subtype2descriptions, on_picked_callback)
. = ..()
if(!isitem(parent))
return COMPONENT_INCOMPATIBLE
src.subtype2descriptions = subtype2descriptions
src.on_picked_callback = on_picked_callback
build_radial_list()
/datum/component/subtype_picker/RegisterWithParent()
. = ..()
RegisterSignal(parent, COMSIG_ITEM_ATTACK_SELF, .proc/on_attack_self)
/datum/component/subtype_picker/UnregisterFromParent()
. = ..()
UnregisterSignal(parent, COMSIG_ITEM_ATTACK_SELF)
///signal called by the stat of the target changing
/datum/component/subtype_picker/proc/on_attack_self(datum/target, mob/user)
SIGNAL_HANDLER
INVOKE_ASYNC(src, .proc/pick_subtype, target, user)
/**
* pick_subtype: turns the list of types to their description into all the data radial menus need
*/
/datum/component/subtype_picker/proc/build_radial_list()
built_radial_list = list()
name2subtype = list()
for(var/obj/item/subtype as anything in subtype2descriptions)
var/datum/radial_menu_choice/option = new
option.image = image(icon = initial(subtype.icon), icon_state = initial(subtype.icon_state))
option.info = span_boldnotice(subtype2descriptions[subtype])
name2subtype[initial(subtype.name)] = subtype
built_radial_list += list(initial(subtype.name) = option)
built_radial_list = sortList(built_radial_list)
/**
* pick_subtype: called from on_attack_self, shows a user a radial menu of all available null rod reskins and replaces the current null rod with the user's chosen reskinned variant
*
* Arguments:
* * target: parent this element is attached to that is being activated
* * picker: user who interacted with the item
*/
/datum/component/subtype_picker/proc/pick_subtype(datum/target, mob/picker)
var/name_of_type = show_radial_menu(picker, target, built_radial_list, custom_check = CALLBACK(src, .proc/check_menu, target, picker), radius = 42, require_near = TRUE)
if(!name_of_type || !check_menu(target, picker))
return
var/picked_subtype = name2subtype[name_of_type]
on_picked_callback?.Invoke(picked_subtype)
picked_subtype = new picked_subtype(picker.drop_location())
qdel(target)
picker.put_in_hands(picked_subtype)
/**
* Checks if we are allowed to interact with the radial menu
*
* Arguments:
* * target: parent the radial menu is from
* * user: the mob interacting with the menu
*/
/datum/component/subtype_picker/proc/check_menu(datum/target, mob/user)
if(!istype(user))
return FALSE
if(QDELETED(target))
return FALSE
if(user.incapacitated() || !user.is_holding(target))
return FALSE
return TRUE
+14 -61
View File
@@ -143,77 +143,31 @@
w_class = WEIGHT_CLASS_TINY
obj_flags = UNIQUE_RENAME
wound_bonus = -10
/// If this item has already been reskinned
var/reskinned = FALSE
/// If this item can be used in a reskin variant selection
/// boolean on whether it's allowed to be picked from the nullrod's transformation ability
var/chaplain_spawnable = TRUE
/// Short description of what this item is capable of, for radial menu uses
/// Short description of what this item is capable of, for radial menu uses.
var/menu_description = "A standard chaplain's weapon. Fits in pockets. Can be worn on the belt."
/obj/item/nullrod/Initialize(mapload)
. = ..()
AddComponent(/datum/component/anti_magic, TRUE, TRUE, FALSE, null, null, FALSE)
AddElement(/datum/element/bane, /mob/living/simple_animal/revenant, 0, 25, FALSE)
if(!GLOB.holy_weapon_type && istype(src, /obj/item/nullrod))
var/list/rods = list()
for(var/obj/item/nullrod/nullrod_type as anything in typesof(/obj/item/nullrod))
if(!chaplain_spawnable)
continue
rods[nullrod_type] = initial(nullrod_type.menu_description)
AddComponent(/datum/component/subtype_picker, rods, CALLBACK(src, .proc/on_holy_weapon_picked))
/obj/item/nullrod/proc/on_holy_weapon_picked(obj/item/nullrod/holy_weapon_type)
GLOB.holy_weapon_type = holy_weapon_type
SSblackbox.record_feedback("tally", "chaplain_weapon", 1, "[initial(holy_weapon_type.name)]")
/obj/item/nullrod/suicide_act(mob/user)
user.visible_message(span_suicide("[user] is killing [user.p_them()]self with [src]! It looks like [user.p_theyre()] trying to get closer to god!"))
return (BRUTELOSS|FIRELOSS)
/obj/item/nullrod/attack_self(mob/user)
if(user.mind && (user.mind.holy_role) && !reskinned)
reskin_holy_weapon(user)
/**
* Shows a user a radial menu of all available null rod reskins and replaces the current null rod with the user's chosen reskinned variant
*
* Arguments:
* * user The mob choosing a null rod reskin variant
*/
/obj/item/nullrod/proc/reskin_holy_weapon(mob/user)
if(GLOB.holy_weapon_type)
return
var/list/display_names = list()
var/list/nullrod_icons = list()
for(var/rod in typesof(/obj/item/nullrod))
var/obj/item/nullrod/rodtype = rod
if(initial(rodtype.chaplain_spawnable))
var/datum/radial_menu_choice/option = new
option.image = image(icon = initial(rodtype.icon), icon_state = initial(rodtype.icon_state))
option.info = span_boldnotice("[initial(rodtype.menu_description)]")
display_names[initial(rodtype.name)] = rodtype
nullrod_icons += list(initial(rodtype.name) = option)
nullrod_icons = sortList(nullrod_icons)
var/choice = show_radial_menu(user, src , nullrod_icons, custom_check = CALLBACK(src, .proc/check_menu, user), radius = 42, require_near = TRUE)
if(!choice || !check_menu(user))
return
var/picked_rod_type = display_names[choice] // This needs to be on a separate var as list member access is not allowed for new
var/obj/item/nullrod/holy_weapon = new picked_rod_type(user.drop_location())
GLOB.holy_weapon_type = holy_weapon.type
SSblackbox.record_feedback("tally", "chaplain_weapon", 1, "[choice]")
if(holy_weapon)
holy_weapon.reskinned = TRUE
qdel(src)
user.put_in_hands(holy_weapon)
/**
* Checks if we are allowed to interact with a radial menu
*
* Arguments:
* * user The mob interacting with the menu
*/
/obj/item/nullrod/proc/check_menu(mob/user)
if(!istype(user))
return FALSE
if(QDELETED(src) || reskinned)
return FALSE
if(user.incapacitated() || !user.is_holding(src))
return FALSE
return TRUE
/obj/item/nullrod/godhand
name = "god hand"
desc = "This hand of yours glows with an awesome power!"
@@ -462,8 +416,7 @@
hitsound = 'sound/weapons/chainsawhit.ogg'
tool_behaviour = TOOL_SAW
toolspeed = 0.5 //faster than normal saw
chaplain_spawnable = FALSE
menu_description = "A sharp chainsaw sword dealing a very high amount of damage which partially penetrates armor. Able to awaken a friendly spirit providing guidance. Can be used as a faster saw tool. Very effective at butchering bodies. Can be worn on the belt."
chaplain_spawnable = FALSE //prevents being pickable as a chaplain weapon (it has 30 force)
/obj/item/nullrod/hammer
name = "relic war hammer"
+1
View File
@@ -626,6 +626,7 @@
#include "code\datums\components\stationloving.dm"
#include "code\datums\components\stationstuck.dm"
#include "code\datums\components\strong_pull.dm"
#include "code\datums\components\subtype_picker.dm"
#include "code\datums\components\summoning.dm"
#include "code\datums\components\swabbing.dm"
#include "code\datums\components\swarming.dm"