mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2025-12-10 09:42:29 +00:00
## About The Pull Request This "buffs" the hallucinatory anomaly by giving it a bit more impact and flair. This affects both the detonate effect and what happens when one initially spawns. When a hallucinatory anomaly spawns, it will spawn surrounded by "decoy" hallucination anomalies -- Illusions meant to distract you from the real one. The idea is that these are not actually there, and that they are the result of reality getting muddy in proximity to the anomaly. Scanning one of these will provide a message, either of nothing happening or a minor hallucination as your character suffers from the real anomaly's effects. Using an anomaly neutralizer on a decoy will do nothing. There's nothing to neutralize, because nothing is there. You're losing your grip on reality. Now, the detonate effect will affect people at a wider radius, through walls. This is done with a second helper different from `visible_hallucination_pulse()`, which does affect the blind and ignores walls, `hallucination_pulse()`. ## Why It's Good For The Game Hallucinatory anomalies are easily the most underwhelming and understated anomaly in the group. They have the impact of a dry fart on a round, rarely affecting anyone and vanishing without anyone noticing or caring. It makes little sense for the detonate effect to impact only those who can see it. Anyone with a pulse can make the connection between the "hallucination anomaly" vanishing and Bubblegum bodyslamming them less than a second later. By affecting those out of sight, in a wider range, there's a higher chance the detonation will not only catch people off guard, but lead to more chaos on comms. As for the illusory decoy anomalies, it was just a neat idea I had to differentiate how people typically deal with them. It makes for a more trippy experience for whoever has to deal with them, and adds confusion (which is the whole shtick with hallucinations -- confusion). So, overall, more snazziness and personality, and more of an impact when left alone. ## Changelog 🆑 Rhials balance: Hallucinatory anomalies now have a wider range, and will spawn hallucinatory decoys of itself to mislead you. /🆑 --------- Co-authored-by: Ghom <42542238+Ghommie@users.noreply.github.com>
109 lines
3.6 KiB
Plaintext
109 lines
3.6 KiB
Plaintext
/*
|
|
* Simple component for something that is able to destroy
|
|
* certain effects (such as cult runes) in one attack.
|
|
*/
|
|
/datum/component/effect_remover
|
|
dupe_mode = COMPONENT_DUPE_ALLOWED
|
|
/// Line sent to the user on successful removal.
|
|
var/success_feedback
|
|
/// Line forcesaid by the user on successful removal.
|
|
var/success_forcesay
|
|
/// The text used in the screentip when our parent is hovering over an item we can clear. Ex "Destroy rune"
|
|
var/tip_text
|
|
/// Callback invoked with removal is done.
|
|
var/datum/callback/on_clear_callback
|
|
/// A typecache of all effects we can clear with our item.
|
|
var/list/obj/effect/effects_we_clear
|
|
/// If above 0, how long it takes while standing still to remove the effect.
|
|
var/time_to_remove = 0 SECONDS
|
|
|
|
/datum/component/effect_remover/Initialize(
|
|
success_forcesay,
|
|
success_feedback,
|
|
tip_text,
|
|
on_clear_callback,
|
|
effects_we_clear,
|
|
time_to_remove,
|
|
)
|
|
|
|
. = ..()
|
|
if(!isitem(parent))
|
|
return COMPONENT_INCOMPATIBLE
|
|
|
|
if(!effects_we_clear)
|
|
stack_trace("[type] was instantiated without any valid removable effects!")
|
|
return COMPONENT_INCOMPATIBLE
|
|
|
|
src.success_feedback = success_feedback
|
|
src.success_forcesay = success_forcesay
|
|
src.tip_text = tip_text
|
|
src.on_clear_callback = on_clear_callback
|
|
src.effects_we_clear = typecacheof(effects_we_clear)
|
|
src.time_to_remove = time_to_remove
|
|
|
|
/datum/component/effect_remover/Destroy(force)
|
|
on_clear_callback = null
|
|
return ..()
|
|
|
|
/datum/component/effect_remover/RegisterWithParent()
|
|
RegisterSignal(parent, COMSIG_ITEM_INTERACTING_WITH_ATOM, PROC_REF(try_remove_effect))
|
|
|
|
if(tip_text)
|
|
var/obj/item/item_parent = parent
|
|
item_parent.item_flags |= ITEM_HAS_CONTEXTUAL_SCREENTIPS
|
|
RegisterSignal(parent, COMSIG_ITEM_REQUESTING_CONTEXT_FOR_TARGET, PROC_REF(add_item_context))
|
|
|
|
/datum/component/effect_remover/UnregisterFromParent()
|
|
UnregisterSignal(parent, list(COMSIG_ITEM_INTERACTING_WITH_ATOM, COMSIG_ITEM_REQUESTING_CONTEXT_FOR_TARGET))
|
|
|
|
/*
|
|
* Signal proc for [COMSIG_ITEM_INTERACTING_WITH_ATOM].
|
|
*/
|
|
|
|
/datum/component/effect_remover/proc/try_remove_effect(datum/source, mob/living/user, atom/target, params)
|
|
SIGNAL_HANDLER
|
|
|
|
if(!isliving(user))
|
|
return NONE
|
|
|
|
if(HAS_TRAIT(target, TRAIT_ILLUSORY_EFFECT))
|
|
to_chat(user, span_notice("You pass [parent] through the [target], but nothing seems to happen. Is it really even there?"))
|
|
return NONE
|
|
|
|
if(is_type_in_typecache(target, effects_we_clear)) // Make sure we get all subtypes and everything
|
|
INVOKE_ASYNC(src, PROC_REF(do_remove_effect), target, user)
|
|
return ITEM_INTERACT_SUCCESS
|
|
|
|
/*
|
|
* Actually removes the effect, invoking our on_clear_callback before it's deleted.
|
|
*/
|
|
/datum/component/effect_remover/proc/do_remove_effect(obj/effect/target, mob/living/user)
|
|
if(time_to_remove && !do_after(user, time_to_remove, target))
|
|
return
|
|
|
|
var/obj/item/item_parent = parent
|
|
if(success_forcesay)
|
|
user.say(success_forcesay, forced = item_parent.name)
|
|
if(success_feedback)
|
|
var/real_feedback = replacetext(success_feedback, "%THEEFFECT", "\the [target]")
|
|
real_feedback = replacetext(real_feedback, "%THEWEAPON", "\the [item_parent]")
|
|
to_chat(user, span_notice(real_feedback))
|
|
on_clear_callback?.Invoke(target, user)
|
|
|
|
if(!QDELETED(target))
|
|
qdel(target)
|
|
|
|
/*
|
|
* Signal proc for [COMSIG_ITEM_REQUESTING_CONTEXT_FOR_TARGET].
|
|
*
|
|
* Adds some context for the target, if we have one set and it's a valid target.
|
|
*/
|
|
/datum/component/effect_remover/proc/add_item_context(obj/item/source, list/context, atom/target, mob/living/user)
|
|
SIGNAL_HANDLER
|
|
|
|
if(effects_we_clear[target.type])
|
|
context[SCREENTIP_CONTEXT_LMB] = tip_text
|
|
return CONTEXTUAL_SCREENTIP_SET
|
|
|
|
return NONE
|