/datum/component/supermatter_crystal ///Callback for the wrench act call var/datum/callback/tool_act_callback ///Callback used by the SM to get the damage and matter power increase/decrease var/datum/callback/consume_callback // A whitelist of items that can interact with the SM without dusting the user var/static/list/sm_item_whitelist = typecacheof(list( /obj/item/melee/roastingstick, /obj/item/toy/crayon/spraycan )) /datum/component/supermatter_crystal/Initialize(datum/callback/tool_act_callback, datum/callback/consume_callback) RegisterSignal(parent, COMSIG_ATOM_BLOB_ACT, PROC_REF(blob_hit)) RegisterSignal(parent, COMSIG_ATOM_ATTACK_PAW, PROC_REF(paw_hit)) RegisterSignal(parent, COMSIG_ATOM_ATTACK_ANIMAL, PROC_REF(animal_hit)) RegisterSignal(parent, COMSIG_ATOM_HULK_ATTACK, PROC_REF(hulk_hit)) RegisterSignal(parent, COMSIG_LIVING_UNARMED_ATTACK, PROC_REF(unarmed_hit)) RegisterSignal(parent, COMSIG_ATOM_ATTACK_HAND, PROC_REF(hand_hit)) RegisterSignal(parent, COMSIG_ATOM_ATTACKBY, PROC_REF(attackby_hit)) RegisterSignal(parent, COMSIG_ATOM_TOOL_ACT(TOOL_WRENCH), PROC_REF(tool_hit)) RegisterSignal(parent, COMSIG_ATOM_SECONDARY_TOOL_ACT(TOOL_WRENCH), PROC_REF(tool_hit)) RegisterSignal(parent, COMSIG_ATOM_BUMPED, PROC_REF(bumped_hit)) RegisterSignal(parent, COMSIG_ATOM_INTERCEPT_Z_FALL, PROC_REF(intercept_z_fall)) RegisterSignal(parent, COMSIG_ATOM_ON_Z_IMPACT, PROC_REF(on_z_impact)) src.tool_act_callback = tool_act_callback src.consume_callback = consume_callback /datum/component/supermatter_crystal/Destroy(force) tool_act_callback = null consume_callback = null return ..() /datum/component/supermatter_crystal/UnregisterFromParent(force, silent) var/list/signals_to_remove = list( COMSIG_ATOM_BLOB_ACT, COMSIG_ATOM_ATTACK_PAW, COMSIG_ATOM_ATTACK_ANIMAL, COMSIG_ATOM_HULK_ATTACK, COMSIG_LIVING_UNARMED_ATTACK, COMSIG_ATOM_ATTACK_HAND, COMSIG_ATOM_ATTACKBY, COMSIG_ATOM_TOOL_ACT(TOOL_WRENCH), COMSIG_ATOM_SECONDARY_TOOL_ACT(TOOL_WRENCH), COMSIG_ATOM_BUMPED, COMSIG_ATOM_INTERCEPT_Z_FALL, COMSIG_ATOM_ON_Z_IMPACT, ) UnregisterSignal(parent, signals_to_remove) /datum/component/supermatter_crystal/proc/blob_hit(datum/source, obj/structure/blob/blob) SIGNAL_HANDLER var/atom/atom_source = source if(!blob || isspaceturf(atom_source)) //does nothing in space return playsound(get_turf(atom_source), 'sound/effects/supermatter.ogg', 50, TRUE) consume_returns(damage_increase = blob.get_integrity() * 0.05) if(blob.get_integrity() > 100) blob.visible_message(span_danger("\The [blob] strikes at \the [atom_source] and flinches away!"), span_hear("You hear a loud crack as you are washed with a wave of heat.")) blob.take_damage(100, BURN) else blob.visible_message(span_danger("\The [blob] strikes at \the [atom_source] and rapidly flashes to ash."), span_hear("You hear a loud crack as you are washed with a wave of heat.")) consume(atom_source, blob) /datum/component/supermatter_crystal/proc/paw_hit(datum/source, mob/user, list/modifiers) SIGNAL_HANDLER if(isliving(user)) var/mob/living/living_mob = user if(living_mob.incorporeal_move || HAS_TRAIT(living_mob, TRAIT_GODMODE)) return if(isalien(user)) dust_mob(source, user, cause = "alien attack") return dust_mob(source, user, cause = "monkey attack") /datum/component/supermatter_crystal/proc/animal_hit(datum/source, mob/living/simple_animal/user, list/modifiers) SIGNAL_HANDLER if(user.incorporeal_move || HAS_TRAIT(user, TRAIT_GODMODE)) return var/atom/atom_source = source var/murder if(!user.melee_damage_upper && !user.melee_damage_lower) murder = user.friendly_verb_continuous else murder = user.attack_verb_continuous dust_mob(source, user, \ span_danger("[user] unwisely [murder] [atom_source], and [user.p_their()] body burns brilliantly before flashing into ash!"), \ span_userdanger("You unwisely touch [atom_source], and your vision glows brightly as your body crumbles to dust. Oops."), \ "simple animal attack") /datum/component/supermatter_crystal/proc/hulk_hit(datum/source, mob/user) SIGNAL_HANDLER dust_mob(source, user, cause = "hulk attack") /datum/component/supermatter_crystal/proc/unarmed_hit(datum/source, mob/user, list/modifiers) SIGNAL_HANDLER if(isliving(user)) var/mob/living/living_mob = user if(living_mob.incorporeal_move || HAS_TRAIT(living_mob, TRAIT_GODMODE)) return var/atom/atom_source = source if(iscyborg(user) && atom_source.Adjacent(user)) dust_mob(source, user, cause = "cyborg attack") return if(iscameramob(user)) return if(islarva(user)) dust_mob(source, user, cause = "larva attack") return /datum/component/supermatter_crystal/proc/hand_hit(datum/source, mob/living/user, list/modifiers) SIGNAL_HANDLER if(user.incorporeal_move || HAS_TRAIT(user, TRAIT_GODMODE)) return if(user.zone_selected != BODY_ZONE_PRECISE_MOUTH) dust_mob(source, user, cause = "hand") return var/atom/atom_source = source if(!user.is_mouth_covered()) if(user.combat_mode) dust_mob(source, user, span_danger("As [user] tries to take a bite out of [atom_source] everything goes silent before [user.p_their()] body starts to glow and burst into flames before flashing to ash."), span_userdanger("You try to take a bite out of [atom_source], but find [p_them()] far too hard to get anywhere before everything starts burning and your ears fill with ringing!"), "attempted bite" ) return var/obj/item/organ/tongue/licking_tongue = user.get_organ_slot(ORGAN_SLOT_TONGUE) if(licking_tongue) dust_mob(source, user, span_danger("As [user] hesitantly leans in and licks [atom_source] everything goes silent before [user.p_their()] body starts to glow and burst into flames before flashing to ash!"), span_userdanger("You tentatively lick [atom_source], but you can't figure out what it tastes like before everything starts burning and your ears fill with ringing!"), "attempted lick" ) return var/obj/item/bodypart/head/forehead = user.get_bodypart(BODY_ZONE_HEAD) if(forehead) dust_mob(source, user, span_danger("As [user]'s forehead bumps into [atom_source], inducing a resonance... Everything goes silent before [user.p_their()] [forehead] flashes to ash!"), span_userdanger("You feel your forehead bump into [atom_source] and everything suddenly goes silent. As your head fills with ringing you come to realize that that was not a wise decision."), "failed lick" ) return dust_mob(source, user, span_danger("[user] leans in and tries to lick [atom_source], inducing a resonance... [user.p_their()] body starts to glow and burst into flames before flashing into dust!"), span_userdanger("You lean in and try to lick [atom_source]. Everything starts burning and all you can hear is ringing. Your last thought is \"That was not a wise decision.\""), "failed lick" ) /datum/component/supermatter_crystal/proc/attackby_hit(datum/source, obj/item/item, mob/living/user, params) SIGNAL_HANDLER var/atom/atom_source = source if(!istype(item) || (item.item_flags & ABSTRACT) || !istype(user)) return if(is_type_in_typecache(item, sm_item_whitelist)) return FALSE if(istype(item, /obj/item/cigarette)) var/obj/item/cigarette/cig = item var/clumsy = HAS_TRAIT(user, TRAIT_CLUMSY) if(clumsy) var/obj/item/bodypart/dust_arm = user.get_active_hand() dust_arm.dismember() user.visible_message(span_danger("The [item] flashes out of existence on contact with \the [atom_source], resonating with a horrible sound..."),\ span_danger("Oops! The [item] flashes out of existence on contact with \the [atom_source], taking your arm with it! That was clumsy of you!")) playsound(atom_source, 'sound/effects/supermatter.ogg', 150, TRUE) consume(atom_source, dust_arm) qdel(item) return if(cig.lit || user.combat_mode) user.visible_message(span_danger("A hideous sound echoes as [item] is ashed out on contact with \the [atom_source]. That didn't seem like a good idea...")) playsound(atom_source, 'sound/effects/supermatter.ogg', 150, TRUE) consume(atom_source, item) radiation_pulse(atom_source, max_range = 3, threshold = 0.1, chance = 50) return else cig.light() user.visible_message(span_danger("As [user] lights \their [item] on \the [atom_source], silence fills the room..."),\ span_danger("Time seems to slow to a crawl as you touch \the [atom_source] with \the [item].\n\The [item] flashes alight with an eerie energy as you nonchalantly lift your hand away from \the [atom_source]. Damn.")) playsound(atom_source, 'sound/effects/supermatter.ogg', 50, TRUE) radiation_pulse(atom_source, max_range = 1, threshold = 0, chance = 100) return if(user.dropItemToGround(item)) user.visible_message(span_danger("As [user] touches \the [atom_source] with \a [item], silence fills the room..."),\ span_userdanger("You touch \the [atom_source] with \the [item], and everything suddenly goes silent.\n\The [item] flashes into dust as you flinch away from \the [atom_source]."),\ span_hear("Everything suddenly goes silent.")) user.investigate_log("has been attacked ([item]) by [key_name(user)]", INVESTIGATE_ENGINE) consume(atom_source, item) playsound(get_turf(atom_source), 'sound/effects/supermatter.ogg', 50, TRUE) radiation_pulse(atom_source, max_range = 3, threshold = 0.1, chance = 50) return if(atom_source.Adjacent(user)) //if the item is stuck to the person, kill the person too instead of eating just the item. if(user.incorporeal_move || HAS_TRAIT(user, TRAIT_GODMODE)) return var/vis_msg = span_danger("[user] reaches out and touches [atom_source] with [item], inducing a resonance... [item] starts to glow briefly before the light continues up to [user]'s body. [user.p_They()] burst[user.p_s()] into flames before flashing into dust!") var/mob_msg = span_userdanger("You reach out and touch [atom_source] with [item]. Everything starts burning and all you can hear is ringing. Your last thought is \"That was not a wise decision.\"") dust_mob(source, user, vis_msg, mob_msg) /datum/component/supermatter_crystal/proc/tool_hit(datum/source, mob/user, obj/item/tool) SIGNAL_HANDLER if(tool_act_callback) tool_act_callback.Invoke(user, tool) return ITEM_INTERACT_BLOCKING attackby_hit(source, tool, user) /datum/component/supermatter_crystal/proc/bumped_hit(datum/source, atom/movable/hit_object) SIGNAL_HANDLER if(isliving(hit_object)) var/mob/living/hit_mob = hit_object if(hit_mob.incorporeal_move || HAS_TRAIT(hit_mob, TRAIT_GODMODE)) return var/atom/atom_source = source var/obj/machinery/power/supermatter_crystal/our_supermatter = parent // Why is this a component? if(istype(our_supermatter)) our_supermatter.log_activation(who = hit_object) if(isliving(hit_object)) hit_object.visible_message(span_danger("\The [hit_object] slams into \the [atom_source] inducing a resonance... [hit_object.p_their()] body starts to glow and burst into flames before flashing into dust!"), span_userdanger("You slam into \the [atom_source] as your ears are filled with unearthly ringing. Your last thought is \"Oh, fuck.\""), span_hear("You hear an unearthly noise as a wave of heat washes over you.")) else if(isobj(hit_object) && !iseffect(hit_object)) hit_object.visible_message(span_danger("\The [hit_object] smacks into \the [atom_source] and rapidly flashes to ash."), null, span_hear("You hear a loud crack as you are washed with a wave of heat.")) else return playsound(get_turf(atom_source), 'sound/effects/supermatter.ogg', 50, TRUE) consume(atom_source, hit_object) /datum/component/supermatter_crystal/proc/intercept_z_fall(datum/source, list/falling_movables, levels) SIGNAL_HANDLER for(var/atom/movable/hit_object as anything in falling_movables) if(parent == hit_object) return bumped_hit(parent, hit_object) return FALL_INTERCEPTED | FALL_NO_MESSAGE /datum/component/supermatter_crystal/proc/on_z_impact(datum/source, turf/impacted_turf, levels) SIGNAL_HANDLER var/atom/atom_source = source for(var/mob/living/poor_target in impacted_turf) consume(atom_source, poor_target) playsound(get_turf(atom_source), 'sound/effects/supermatter.ogg', 50, TRUE) poor_target.visible_message(span_danger("\The [atom_source] slams into \the [poor_target] out of nowhere inducing a resonance... [poor_target.p_their()] body starts to glow and burst into flames before flashing into dust!"), span_userdanger("\The [atom_source] slams into you out of nowhere as your ears are filled with unearthly ringing. Your last thought is \"The fuck.\""), span_hear("You hear an unearthly noise as a wave of heat washes over you.")) for(var/atom/movable/hit_object as anything in impacted_turf) if(parent == hit_object) return if(iseffect(hit_object)) continue consume(atom_source, hit_object) playsound(get_turf(atom_source), 'sound/effects/supermatter.ogg', 50, TRUE) atom_source.visible_message(span_danger("\The [atom_source], smacks into the plating out of nowhere, reducing everything below to ash."), null, span_hear("You hear a loud crack as you are washed with a wave of heat.")) /datum/component/supermatter_crystal/proc/dust_mob(datum/source, mob/living/nom, vis_msg, mob_msg, cause) if(nom.incorporeal_move || HAS_TRAIT(nom, TRAIT_GODMODE)) //try to keep supermatter sliver's + hemostat's dust conditions in sync with this too return var/atom/atom_source = source if(!vis_msg) vis_msg = span_danger("[nom] reaches out and touches [atom_source], inducing a resonance... [nom.p_their()] body starts to glow and burst into flames before flashing into dust!") if(!mob_msg) mob_msg = span_userdanger("You reach out and touch [atom_source]. Everything starts burning and all you can hear is ringing. Your last thought is \"That was not a wise decision.\"") if(!cause) cause = "contact" nom.visible_message(vis_msg, mob_msg, span_hear("You hear an unearthly noise as a wave of heat washes over you.")) atom_source.investigate_log("has been attacked ([cause]) by [key_name(nom)]", INVESTIGATE_ENGINE) add_memory_in_range(atom_source, 7, /datum/memory/witness_supermatter_dusting, protagonist = nom, antagonist = atom_source) playsound(get_turf(atom_source), 'sound/effects/supermatter.ogg', 50, TRUE) consume(atom_source, nom) /datum/component/supermatter_crystal/proc/consume(atom/source, atom/movable/consumed_object) if(consumed_object.flags_1 & SUPERMATTER_IGNORES_1) return if(HAS_TRAIT(consumed_object, TRAIT_GODMODE)) return var/atom/atom_source = source SEND_SIGNAL(consumed_object, COMSIG_SUPERMATTER_CONSUMED, atom_source) var/object_size = 0 var/matter_increase = 0 var/damage_increase = 0 var/radiation_range = 6 var/effects_calculated = FALSE if(isliving(consumed_object)) var/mob/living/consumed_mob = consumed_object object_size = consumed_mob.mob_size + 2 message_admins("[atom_source] has consumed [key_name_admin(consumed_mob)] [ADMIN_JMP(atom_source)].") atom_source.investigate_log("has consumed [key_name(consumed_mob)].", INVESTIGATE_ENGINE) consumed_mob.investigate_log("has been dusted by [atom_source].", INVESTIGATE_DEATHS) if(istype(consumed_mob, /mob/living/basic/parrot/poly)) // Dusting Poly creates a power surge force_event(/datum/round_event_control/supermatter_surge/poly, "Poly's revenge") notify_ghosts( "[consumed_mob.real_name] has been dusted by [atom_source]!", source = atom_source, header = "Polytechnical Difficulties", ) consumed_mob.dust(force = TRUE) matter_increase += 100 * object_size * 2 if(is_clown_job(consumed_mob.mind?.assigned_role)) damage_increase += rand(-30, 30) * 2 // HONK effects_calculated = TRUE else if(isobj(consumed_object)) if(!iseffect(consumed_object) && !(consumed_object.flags_1 & SUPERMATTER_NOLOGS_1)) //BUBBER EDIT | NOLOGS flag Addition to ignore items engineers like to feed the SM :3 var/suspicion = "" if(consumed_object.fingerprintslast) suspicion = "last touched by [consumed_object.fingerprintslast]" message_admins("[atom_source] has consumed [consumed_object], [suspicion] [ADMIN_JMP(atom_source)].") atom_source.investigate_log("has consumed [consumed_object] - [suspicion].", INVESTIGATE_ENGINE) var/is_nuke = FALSE if (consumed_object.type == /obj/item/nuke_core) // No subtypes, the supermatter sliver shouldn't trigger this is_nuke = TRUE else if (istype(consumed_object, /obj/machinery/nuclearbomb)) var/obj/machinery/nuclearbomb/bomb = consumed_object is_nuke = !!bomb.core if (is_nuke) object_size = 10 radiation_range *= 2 matter_increase += 10000 damage_increase += 110 effects_calculated = TRUE qdel(consumed_object) if(!iseffect(consumed_object) && !effects_calculated) if(isitem(consumed_object)) var/obj/item/consumed_item = consumed_object object_size = consumed_item.w_class matter_increase += 70 * object_size else matter_increase += min(0.5 * consumed_object.max_integrity, 1000) //Some poor sod got eaten, go ahead and irradiate people nearby. radiation_pulse(atom_source, max_range = radiation_range, threshold = 1.2 / max(object_size, 1), chance = 10 * object_size) for(var/mob/living/near_mob in range(10)) atom_source.investigate_log("has irradiated [key_name(near_mob)] after consuming [consumed_object].", INVESTIGATE_ENGINE) if (HAS_TRAIT(near_mob, TRAIT_RADIMMUNE) || issilicon(near_mob)) continue if(ishuman(near_mob) && SSradiation.wearing_rad_protected_clothing(near_mob)) continue if(near_mob in view()) near_mob.show_message(span_danger("As \the [atom_source] slowly stops resonating, you find your skin covered in new radiation burns."), MSG_VISUAL, span_danger("The unearthly ringing subsides and you find your skin covered in new radiation burns."), MSG_AUDIBLE) else near_mob.show_message(span_hear("An unearthly ringing fills your ears, and you find your skin covered in new radiation burns."), MSG_AUDIBLE) consume_returns(matter_increase, damage_increase) var/obj/machinery/power/supermatter_crystal/our_crystal = parent if(istype(our_crystal)) our_crystal.log_activation(who = consumed_object) /datum/component/supermatter_crystal/proc/consume_returns(matter_increase = 0, damage_increase = 0) if(consume_callback) consume_callback.Invoke(matter_increase, damage_increase)