From d631b7f38b0ea101c6041fa4efb03512ac15e51a Mon Sep 17 00:00:00 2001 From: PollardTheDragon <144391971+PollardTheDragon@users.noreply.github.com> Date: Fri, 31 Jan 2025 10:57:50 -0500 Subject: [PATCH] [PTBF] Hallucination - Meet the Sniper (#27579) * Boom, headshot. * If spacing * Actually adds the hallucination to the list * Spacing, moved fire to async, images, second hallucination for blood on hit * Invisibility define * Bullet fires, image * Hit messages * Boom, headshot * Blood splatter has color now * Proc ref * Damage and target fix * More efficient bump check * Better List Appending Co-authored-by: DGamerL <108773801+DGamerL@users.noreply.github.com> Signed-off-by: PollardTheDragon <144391971+PollardTheDragon@users.noreply.github.com> * Better list appending Co-authored-by: DGamerL <108773801+DGamerL@users.noreply.github.com> Signed-off-by: PollardTheDragon <144391971+PollardTheDragon@users.noreply.github.com> * Knockdowm application Co-authored-by: DGamerL <108773801+DGamerL@users.noreply.github.com> Signed-off-by: PollardTheDragon <144391971+PollardTheDragon@users.noreply.github.com> * Loc to turf Co-authored-by: DGamerL <108773801+DGamerL@users.noreply.github.com> Signed-off-by: PollardTheDragon <144391971+PollardTheDragon@users.noreply.github.com> * Fixes knockdown * Proper knockdown Co-authored-by: DGamerL <108773801+DGamerL@users.noreply.github.com> Signed-off-by: PollardTheDragon <144391971+PollardTheDragon@users.noreply.github.com> * Range_Edge_Turfs * Capital Var * Better target turf detection Co-authored-by: Luc <89928798+lewcc@users.noreply.github.com> Signed-off-by: PollardTheDragon <144391971+PollardTheDragon@users.noreply.github.com> * Better failure handling. Reverts change in RANGE_EDGE_TURFS * Somehow a xeno got in. Purged it. * Handles lack of client in target * Removed extraneous debug log --------- Signed-off-by: PollardTheDragon <144391971+PollardTheDragon@users.noreply.github.com> Co-authored-by: DGamerL <108773801+DGamerL@users.noreply.github.com> Co-authored-by: Luc <89928798+lewcc@users.noreply.github.com> --- code/modules/hallucinations/effects/major.dm | 114 ++++++++++++++++-- code/modules/hallucinations/hallucinations.dm | 5 + 2 files changed, 112 insertions(+), 7 deletions(-) diff --git a/code/modules/hallucinations/effects/major.dm b/code/modules/hallucinations/effects/major.dm index c17b03e7667..8dda88c3ff4 100644 --- a/code/modules/hallucinations/effects/major.dm +++ b/code/modules/hallucinations/effects/major.dm @@ -362,14 +362,14 @@ if(!length(locs)) return INITIALIZE_HINT_QDEL var/turf/T = get_turf(pick(locs)) - color = pick(COLOR_BLACK, - COLOR_RIPPING_TENDRILS, - COLOR_BOILING_OIL, - COLOR_ENVENOMED_FILAMENTS, + color = pick(COLOR_BLACK, + COLOR_RIPPING_TENDRILS, + COLOR_BOILING_OIL, + COLOR_ENVENOMED_FILAMENTS, COLOR_LEXORIN_JELLY, - COLOR_KINETIC_GELATIN, - COLOR_CRYOGENIC_LIQUID, - COLOR_SORIUM, + COLOR_KINETIC_GELATIN, + COLOR_CRYOGENIC_LIQUID, + COLOR_SORIUM, COLOR_TESLIUM_PASTE) create_blob(T, core = TRUE) target.playsound_local(T, 'sound/effects/splat.ogg', 50, 1) @@ -476,3 +476,103 @@ I.color = blob.color target.client.images += I blob.target_blob_head = I + +/** + * # Hallucination - Sniper + * + * Fires a penetrator round at the target. On hit, knockdown + stam loss + hallucinated blood splatter for a bit. + */ +/obj/effect/hallucination/sniper + duration = 15 SECONDS + +/obj/effect/hallucination/sniper/Initialize(mapload, mob/living/carbon/target) + . = ..() + // Make sure the target has a client. Otherwise, stop the hallucination + if(!target.client) + qdel(src) + return + // Find a start spot for the sniper bullet + var/list/possible_turfs = list() + for(var/turf/T in RANGE_EDGE_TURFS(13, target.loc)) + possible_turfs += T + if(!length(possible_turfs)) + log_debug("Unable to find possible turf for [src].") + qdel(src) + return + var/turf/shot_loc = get_turf(pick(possible_turfs)) + fire_bullet(shot_loc, target) + +/obj/effect/hallucination/sniper/proc/fire_bullet(turf/shot_loc, mob/living/carbon/target) + // Fire the bullet + var/obj/item/projectile/bullet/sniper/penetrator/hallucination/bullet = new(shot_loc) + bullet.hallucinator = target + bullet.def_zone = BODY_ZONE_HEAD + bullet.suppressed = TRUE + + // Turn right away + var/matrix/M = new + var/angle = round(get_angle(shot_loc, target)) + M.Turn(angle) + bullet.transform = M + + // Handle who can see the bullet + bullet.bullet_image = image(bullet.icon, bullet, bullet.icon_state, OBJ_LAYER, bullet.dir) + bullet.bullet_image.transform = M + target.client.images += bullet.bullet_image + + // Start flying + bullet.trajectory = new(bullet.x, bullet.y, bullet.z, bullet.pixel_x, bullet.pixel_y, angle, SSprojectiles.global_pixel_speed) + bullet.last_projectile_move = world.time + bullet.has_been_fired = TRUE + target.playsound_local(target.loc, 'sound/weapons/gunshots/gunshot_sniper.ogg', 50) + START_PROCESSING(SSprojectiles, bullet) + +/obj/effect/hallucination/sniper_bloodsplatter + duration = 15 SECONDS + hallucination_icon = 'icons/effects/blood.dmi' + hallucination_icon_state = "mfloor1" + hallucination_color = "#A10808" + +/obj/effect/hallucination/sniper_bloodsplatter/Initialize(mapload, mob/living/carbon/target) + var/list/b_data = target.get_blood_data(target.get_blood_id()) + if(b_data && !isnull(b_data["blood_color"])) + hallucination_color = b_data["blood_color"] + . = ..() + hallucination_icon_state = pick("mfloor1", "mfloor2", "mfloor3", "mfloor4", "mfloor5", "mfloor6", "mfloor7") + + +/obj/item/projectile/bullet/sniper/penetrator/hallucination + nodamage = TRUE + invisibility = INVISIBILITY_MAXIMUM // You no see boolet + /// The hallucinator + var/mob/living/carbon/hallucinator = null + /// Handles only the victim seeing it + var/image/bullet_image = null + +/obj/item/projectile/bullet/sniper/penetrator/hallucination/on_hit(atom/target, blocked, hit_zone) + if(!isliving(target)) + return + if(target != hallucinator) + return + var/mob/living/hit_target = target + var/organ_hit_text = "" + if(hit_target.has_limbs) + organ_hit_text = " in \the [parse_zone(def_zone)]" + hit_target.playsound_local(loc, hitsound, 5, TRUE) + hit_target.apply_damage(60, STAMINA, def_zone) + hit_target.KnockDown(2 SECONDS) + new /obj/effect/hallucination/sniper_bloodsplatter(get_turf(src), hit_target) + to_chat(hit_target, "You're shot by \a [src][organ_hit_text]!") + +/obj/item/projectile/bullet/sniper/penetrator/hallucination/Bump(atom/A, yes) + if(!yes) // prevents double bumps. + return + var/turf/target_turf = get_turf(A) + prehit(A) + var/mob/living/hit_target = A + if(hit_target == hallucinator) + hit_target.bullet_act(src, def_zone) + loc = target_turf + if(A) + permutated += A + return 0 diff --git a/code/modules/hallucinations/hallucinations.dm b/code/modules/hallucinations/hallucinations.dm index 59172b6a1b9..29dcc6448a7 100644 --- a/code/modules/hallucinations/hallucinations.dm +++ b/code/modules/hallucinations/hallucinations.dm @@ -32,6 +32,7 @@ GLOBAL_LIST_INIT(hallucinations, list( /datum/hallucination_manager/blind_rush = 1, /datum/hallucination_manager/waves = 2, /obj/effect/hallucination/blob = 10, + /obj/effect/hallucination/sniper = 10 ) )) @@ -51,6 +52,8 @@ GLOBAL_LIST_INIT(hallucinations, list( var/hallucination_icon_state /// Hallucination override. var/hallucination_override = FALSE + /// Hallucination color + var/hallucination_color /// Hallucination layer. var/hallucination_layer = MOB_LAYER ///Hallucination plane. @@ -70,6 +73,8 @@ GLOBAL_LIST_INIT(hallucinations, list( target = hallucination_target if(hallucination_icon && hallucination_icon_state) var/image/I = image(hallucination_icon, hallucination_override ? src : get_turf(src), hallucination_icon_state) + if(hallucination_color) + I.color = hallucination_color I.override = hallucination_override I.layer = hallucination_layer I.plane = hallucination_plane