Gibbed / dusted / otherwise deleted heretic sacrifice targets will clear themselves from heretic target lists (#65566)

Swaps the weakref list of targets heretics use to a list of hard references, due to handling them on deletion
Uses a proc for removing sacrifice targets
Sacrifice targets which are deleted for some reason in game will automatically remove themselves from the heretic's sacrifice list, allowing them to reroll easier
Apparently, having one of your targets gibbed as a heretic is pretty unfortunate.
As I was holding weakrefs to targets, they persisted despite deletion (which I did not expect to be a problem)

So, now, when a body is completely gone (and you can no longer sacrifice them), the slot is freed for you.
This commit is contained in:
MrMelbert
2022-03-20 09:36:47 +00:00
committed by GitHub
parent 8bca0dfa02
commit af03de1da8
4 changed files with 44 additions and 25 deletions
@@ -42,7 +42,7 @@
/// A list of TOTAL how many high value sacrifices completed.
var/high_value_sacrifices = 0
/// Lazy assoc list of [weakrefs to humans] to [image previews of the human]. Humans that we have as sacrifice targets.
var/list/datum/weakref/sac_targets
var/list/mob/living/carbon/human/sac_targets
/// Whether we're drawing a rune or not
var/drawing_rune = FALSE
/// A static typecache of all tools we can scribe with.
@@ -50,6 +50,10 @@
/// A blacklist of turfs we cannot scribe on.
var/static/list/blacklisted_rune_turfs = typecacheof(list(/turf/open/space, /turf/open/openspace, /turf/open/lava, /turf/open/chasm))
/datum/antagonist/heretic/Destroy()
LAZYNULL(sac_targets)
return ..()
/datum/antagonist/heretic/ui_data(mob/user)
var/list/data = list()
@@ -356,7 +360,29 @@
var/image/target_image = image(icon = target.icon, icon_state = target.icon_state)
target_image.overlays = target.overlays
LAZYSET(sac_targets, WEAKREF(target), target_image)
LAZYSET(sac_targets, target, target_image)
RegisterSignal(target, COMSIG_PARENT_QDELETING, .proc/on_target_deleted)
/**
* Removes [target] from the heretic's sacrifice list.
* Returns FALSE if no one was removed, TRUE otherwise
*/
/datum/antagonist/heretic/proc/remove_sacrifice_target(mob/living/carbon/human/target)
if(!(target in sac_targets))
return FALSE
LAZYREMOVE(sac_targets, target)
UnregisterSignal(target, COMSIG_PARENT_QDELETING)
return TRUE
/**
* Signal proc for [COMSIG_PARENT_QDELETING] registered on sac targets
* if sacrifice targets are deleted (gibbed, dusted, whatever), free their slot and reference
*/
/datum/antagonist/heretic/proc/on_target_deleted(mob/living/carbon/human/source)
SIGNAL_HANDLER
remove_sacrifice_target(source)
/**
* Increments knowledge by one.
@@ -462,10 +488,8 @@
return
var/list/removable = list()
for(var/datum/weakref/ref as anything in sac_targets)
var/mob/living/carbon/human/old_target = ref.resolve()
if(!QDELETED(old_target))
removable[old_target.name] = old_target
for(var/mob/living/carbon/human/old_target as anything in sac_targets)
removable[old_target.name] = old_target
var/name_of_removed = tgui_input_list(admin, "Choose a human to remove", "Who to Spare", removable)
if(QDELETED(src) || !admin.client?.holder || isnull(name_of_removed))
@@ -473,10 +497,10 @@
var/mob/living/carbon/human/chosen_target = removable[name_of_removed]
if(QDELETED(chosen_target) || !ishuman(chosen_target))
return
if(!(WEAKREF(chosen_target) in sac_targets))
return
LAZYREMOVE(sac_targets, WEAKREF(chosen_target))
if(!remove_sacrifice_target(chosen_target))
to_chat(admin, span_warning("Failed to remove [name_of_removed] from [owner]'s sacrifice list. Perhaps they're no longer in the list anyways."))
return
if(tgui_alert(admin, "Let them know their targets have been updated?", "Whispers of the Mansus", list("Yes", "No")) == "Yes")
to_chat(owner.current, span_danger("The Mansus has modified your targets."))
@@ -513,11 +537,9 @@
. += "<br>"
. += "<i><b>Current Targets:</b></i><br>"
if(LAZYLEN(sac_targets))
for(var/datum/weakref/ref as anything in sac_targets)
var/mob/living/carbon/human/actual_target = ref.resolve()
if(QDELETED(actual_target))
continue
. += " - <b>[actual_target.real_name]</b>, the [actual_target.mind?.assigned_role?.title || "human"].<br>"
for(var/mob/living/carbon/human/target as anything in sac_targets)
. += " - <b>[target.real_name]</b>, the [target.mind?.assigned_role?.title || "human"].<br>"
else
. += "<i>None!</i><br>"
. += "<br>"
@@ -118,13 +118,9 @@
var/list/targets_to_choose = list()
var/list/mob/living/carbon/human/human_targets = list()
for(var/datum/weakref/target_ref as anything in heretic_datum.sac_targets)
var/mob/living/carbon/human/real_target = target_ref.resolve()
if(QDELETED(real_target))
continue
human_targets[real_target.real_name] = real_target
targets_to_choose[real_target.real_name] = heretic_datum.sac_targets[target_ref]
for(var/mob/living/carbon/human/sac_target as anything in heretic_datum.sac_targets)
human_targets[sac_target.real_name] = sac_target
targets_to_choose[sac_target.real_name] = heretic_datum.sac_targets[sac_target]
// If we don't have a last tracked name, open a radial to set one.
// If we DO have a last tracked name, we skip the radial if they right click the action.
@@ -27,7 +27,8 @@
/datum/heretic_knowledge/reroll_targets/on_finished_recipe(mob/living/user, list/selected_atoms, turf/loc)
var/datum/antagonist/heretic/heretic_datum = IS_HERETIC(user)
LAZYCLEARLIST(heretic_datum.sac_targets)
for(var/mob/living/carbon/human/target as anything in heretic_datum.sac_targets)
heretic_datum.remove_sacrifice_target(target)
var/datum/heretic_knowledge/hunt_and_sacrifice/target_finder = heretic_datum.get_knowledge(/datum/heretic_knowledge/hunt_and_sacrifice)
if(!target_finder)
@@ -65,7 +65,7 @@
// Let's remove any humans in our atoms list that aren't a sac target
for(var/mob/living/carbon/human/sacrifice in atoms)
// If the mob's not in soft crit or worse, or isn't one of the sacrifices, remove it from the list
if(sacrifice.stat < SOFT_CRIT || !(WEAKREF(sacrifice) in heretic_datum.sac_targets))
if(sacrifice.stat < SOFT_CRIT || !(sacrifice in heretic_datum.sac_targets))
atoms -= sacrifice
// Finally, return TRUE if we have a target in the list
@@ -179,12 +179,12 @@
var/mob/living/carbon/human/sacrifice = locate() in selected_atoms
if(!sacrifice)
CRASH("[type] sacrifice_process didn't have a human in the atoms list. How'd it make it so far?")
if(!(WEAKREF(sacrifice) in heretic_datum.sac_targets))
if(!(sacrifice in heretic_datum.sac_targets))
CRASH("[type] sacrifice_process managed to get a non-target human. This is incorrect.")
if(sacrifice.mind)
LAZYADD(target_blacklist, sacrifice.mind)
LAZYREMOVE(heretic_datum.sac_targets, WEAKREF(sacrifice))
heretic_datum.remove_sacrifice_target(sacrifice)
to_chat(user, span_hypnophrase("Your patrons accepts your offer."))