From 2b2cb3dff6d9985103cee46a6020aa1b63a3c2de Mon Sep 17 00:00:00 2001 From: LemonInTheDark <58055496+LemonInTheDark@users.noreply.github.com> Date: Tue, 18 Apr 2023 17:25:52 -0700 Subject: [PATCH] Hologram Touchup (Init savings edition) (#74793) ## About The Pull Request ### Polishes and Reworks Holograms Hologram generation currently involves a bunch of icon operations, which are slow. Not to mention a series of get flats for the human models, which is even worse. We lose 0.05 seconds of init to em off just the 2 RCD holograms. it hurts man. So instead, let's use filters and render steps to achive the same effect. While I'm here I'll dim the holo light and make it blue, make the hologram and its beam emissive (so they glow), and do some fenangling with move_hologram() (it doesn't clear the hologram off failure anymore, instead relying on callers to do that) to ensure holocalls can't be accidentially ended by moving out of the area. Ah and I added RESET_ALPHA to the emissive appearance flags, cause the alpha does override and fuck with color rendering, which ends up looking dumb. If we're gonna support this stuff it should be first class not accidential. ### Makes Static Not Shit While I'm here (since holograms see static) lets ensure the static plane is always visible if you're seeing through an ai eye. The old solution was limited to applying it to JUST ais, which isn't satisfactory for this sort of thing and missed a LOT of cases (I didn't really get how ai eyes worked before I'ma be honest) I'm adding a signal off the hud for it detecting a change in its eye here. This is semi redundant, but avoids unneeded dupe work, so I'm ok with it. The pipeline here is less sane then I'd like, but it works and that's enough ## Why It's Good For The Game ![dreamseeker_zMiLXzlZ2X](https://user-images.githubusercontent.com/58055496/232470136-add945da-5f76-469e-ba1a-6ed3159b6f5b.png) More pretty, better ux, **static works** ## Changelog :cl: add: Holograms glow now, pokes at the lighting for holocalls in general a bit to make em nicer. qol: You can no longer accidentally end a holocall (as a non ai) by leaving the area. Felt like garbage fix: Fixes static rendering improperly if viewed by a non ai /:cl: --- code/__DEFINES/dcs/signals/signals_hud.dm | 3 + code/__DEFINES/lighting.dm | 3 +- code/_onclick/hud/hud.dm | 5 + code/_onclick/hud/rendering/plane_master.dm | 25 +++- code/datums/holocall.dm | 11 +- code/game/atoms.dm | 36 ++++++ .../machinery/computer/camera_advanced.dm | 6 - code/game/machinery/hologram.dm | 112 +++++++++++------- code/game/objects/items/rcd/RCD.dm | 10 +- code/modules/mob/living/silicon/ai/ai.dm | 35 +++--- .../mob/living/silicon/ai/freelook/eye.dm | 4 +- code/modules/visuals/render_steps.dm | 20 +++- 12 files changed, 174 insertions(+), 96 deletions(-) diff --git a/code/__DEFINES/dcs/signals/signals_hud.dm b/code/__DEFINES/dcs/signals/signals_hud.dm index 50e3069a614..b4d73459db6 100644 --- a/code/__DEFINES/dcs/signals/signals_hud.dm +++ b/code/__DEFINES/dcs/signals/signals_hud.dm @@ -1,2 +1,5 @@ +/// Sent from /datum/hud/proc/on_eye_change(): (atom/old_eye, atom/new_eye) +#define COMSIG_HUD_EYE_CHANGED "hud_eye_changed" /// Sent from /datum/hud/proc/eye_z_changed() : (old_offset, new_offset) #define COMSIG_HUD_OFFSET_CHANGED "hud_offset_changed" + diff --git a/code/__DEFINES/lighting.dm b/code/__DEFINES/lighting.dm index ce86af23bfd..a54f13226be 100644 --- a/code/__DEFINES/lighting.dm +++ b/code/__DEFINES/lighting.dm @@ -76,7 +76,8 @@ GLOBAL_LIST_INIT(emissive_color, EMISSIVE_COLOR) /// A globaly cached version of [EM_BLOCK_COLOR] for quick access. GLOBAL_LIST_INIT(em_block_color, EM_BLOCK_COLOR) /// A set of appearance flags applied to all emissive and emissive blocker overlays. -#define EMISSIVE_APPEARANCE_FLAGS (KEEP_APART|KEEP_TOGETHER|RESET_COLOR) +/// KEEP_APART to prevent parent hooking, KEEP_TOGETHER for children, and we reset the color and alpha of our parent so nothing gets overriden +#define EMISSIVE_APPEARANCE_FLAGS (KEEP_APART|KEEP_TOGETHER|RESET_COLOR|RESET_ALPHA) /// The color matrix used to mask out emissive blockers on the emissive plane. Alpha should default to zero, be solely dependent on the RGB value of [EMISSIVE_COLOR], and be independant of the RGB value of [EM_BLOCK_COLOR]. #define EM_MASK_MATRIX list(0,0,0,1/3, 0,0,0,1/3, 0,0,0,1/3, 0,0,0,0, 1,1,1,0) /// A globaly cached version of [EM_MASK_MATRIX] for quick access. diff --git a/code/_onclick/hud/hud.dm b/code/_onclick/hud/hud.dm index 7547c187d97..94d19923353 100644 --- a/code/_onclick/hud/hud.dm +++ b/code/_onclick/hud/hud.dm @@ -134,10 +134,12 @@ GLOBAL_LIST_INIT(available_ui_styles, list( update_sightflags(mymob, mymob.sight, NONE) /datum/hud/proc/client_refresh(datum/source) + SIGNAL_HANDLER RegisterSignal(mymob.client, COMSIG_CLIENT_SET_EYE, PROC_REF(on_eye_change)) on_eye_change(null, null, mymob.client.eye) /datum/hud/proc/clear_client(datum/source) + SIGNAL_HANDLER if(mymob.canon_client) UnregisterSignal(mymob.canon_client, COMSIG_CLIENT_SET_EYE) @@ -148,6 +150,8 @@ GLOBAL_LIST_INIT(available_ui_styles, list( /datum/hud/proc/on_eye_change(datum/source, atom/old_eye, atom/new_eye) SIGNAL_HANDLER + SEND_SIGNAL(src, COMSIG_HUD_EYE_CHANGED, old_eye, new_eye) + if(old_eye) UnregisterSignal(old_eye, COMSIG_MOVABLE_Z_CHANGED) if(new_eye) @@ -158,6 +162,7 @@ GLOBAL_LIST_INIT(available_ui_styles, list( eye_z_changed(new_eye) /datum/hud/proc/update_sightflags(datum/source, new_sight, old_sight) + SIGNAL_HANDLER // If neither the old and new flags can see turfs but not objects, don't transform the turfs // This is to ensure parallax works when you can't see holder objects if(should_sight_scale(new_sight) == should_sight_scale(old_sight)) diff --git a/code/_onclick/hud/rendering/plane_master.dm b/code/_onclick/hud/rendering/plane_master.dm index d867fb2cea5..a873ec6d824 100644 --- a/code/_onclick/hud/rendering/plane_master.dm +++ b/code/_onclick/hud/rendering/plane_master.dm @@ -550,18 +550,31 @@ INITIALIZE_IMMEDIATE(/atom/movable/screen/plane_master) documentation = "Holds camera static images. Usually only visible to people who can well, see static.\
We use images rather then vis contents because they're lighter on maptick, and maptick sucks butt." plane = CAMERA_STATIC_PLANE - start_hidden = TRUE /atom/movable/screen/plane_master/camera_static/show_to(mob/mymob) - // If we aren't an AI, we have no need for this plane master (most of the time, ai eyes are weird and annoying) - if(force_hidden && isAI(mymob)) - unhide_plane(mymob) . = ..() if(!.) return - if(isAI(mymob)) + var/datum/hud/our_hud = home.our_hud + if(isnull(our_hud)) return - return FALSE + + // We'll hide the slate if we're not seeing through a camera eye + // This can call on a cycle cause we don't clear in hide_from + // Yes this is the best way of hooking into the hud, I hate myself too + RegisterSignal(our_hud, COMSIG_HUD_EYE_CHANGED, PROC_REF(eye_changed), override = TRUE) + eye_changed(our_hud, null, our_hud.mymob?.client?.eye) + +/atom/movable/screen/plane_master/camera_static/proc/eye_changed(datum/hud/source, atom/old_eye, atom/new_eye) + SIGNAL_HANDLER + + if(!isaicamera(new_eye)) + if(!force_hidden) + hide_plane(source.mymob) + return + + if(force_hidden) + unhide_plane(source.mymob) /atom/movable/screen/plane_master/high_game name = "High Game" diff --git a/code/datums/holocall.dm b/code/datums/holocall.dm index 3b2ded495cb..5147afc9d76 100644 --- a/code/datums/holocall.dm +++ b/code/datums/holocall.dm @@ -1,7 +1,10 @@ /mob/camera/ai_eye/remote/holo/setLoc(turf/destination, force_update = FALSE) - . = ..() + // If we're moving outside the space of our projector, then just... don't var/obj/machinery/holopad/H = origin - H?.move_hologram(eye_user, loc) + if(!H?.move_hologram(eye_user, destination)) + sprint = initial(sprint) // Reset sprint so it doesn't balloon in our calling proc + return + return ..() /obj/machinery/holopad/remove_eye_control(mob/living/user) if(user.client) @@ -63,9 +66,7 @@ //cleans up ALL references :) /datum/holocall/Destroy() QDEL_NULL(hangup) - - if(!QDELETED(eye)) - QDEL_NULL(eye) + QDEL_NULL(eye) if(connected_holopad && !QDELETED(hologram)) hologram = null diff --git a/code/game/atoms.dm b/code/game/atoms.dm index 1559e5f28b3..6d53e9f6caa 100644 --- a/code/game/atoms.dm +++ b/code/game/atoms.dm @@ -2098,3 +2098,39 @@ if(caller && (caller.pass_flags & pass_flags_self)) return TRUE . = !density + +/// Makes this atom look like a "hologram" +/// So transparent, blue, with a scanline and an emissive glow +/// This is acomplished using a combination of filters and render steps/overlays +/// The degree of the opacity is optional, based off the opacity arg (0 -> 1) +/atom/proc/makeHologram(opacity = 0.5) + // First, we'll make things blue (roughly) and sorta transparent + add_filter("HOLO: Color and Transparent", 1, color_matrix_filter(rgb(125,180,225, opacity * 255))) + // Now we're gonna do a scanline effect + // Gonna take this atom and give it a render target, then use it as a source for a filter + // (We use an atom because it seems as if setting render_target on an MA is just invalid. I hate this engine) + var/static/atom/movable/scanline + if(!scanline) + scanline = new(null) + scanline.icon = 'icons/effects/effects.dmi' + scanline.icon_state = "scanline" + // * so it doesn't render + scanline.render_target = "*HoloScanline" + // Now we add it as a filter, and overlay the appearance so the render source is always around + add_filter("HOLO: Scanline", 2, alpha_mask_filter(render_source = scanline.render_target)) + add_overlay(scanline) + // Annd let's make the sucker emissive, so it glows in the dark + if(!render_target) + var/static/uid = 0 + render_target = "HOLOGRAM [uid]" + uid++ + // I'm using static here to reduce the overhead, it does mean we need to do plane stuff manually tho + var/static/atom/movable/render_step/emissive/glow = new(null) + glow.render_source = render_target + SET_PLANE_EXPLICIT(glow, initial(glow.plane), src) + // We're creating a render step that copies ourselves, and draws it to the emissive plane + // Then we overlay it, and release "ownership" back to this proc, since we get to keep the appearance it generates + // We can't just use an MA from the start cause render_source setting starts going fuckey REALLY quick + var/mutable_appearance/glow_appearance = new(glow) + add_overlay(glow_appearance) + LAZYADD(update_overlays_on_z, glow_appearance) diff --git a/code/game/machinery/computer/camera_advanced.dm b/code/game/machinery/computer/camera_advanced.dm index 2cfcb2393a8..870f64dd575 100644 --- a/code/game/machinery/computer/camera_advanced.dm +++ b/code/game/machinery/computer/camera_advanced.dm @@ -92,9 +92,6 @@ user.remote_control = null current_user = null user.unset_machine() - - for(var/atom/movable/screen/plane_master/plane_static in user.hud_used?.get_true_plane_masters(CAMERA_STATIC_PLANE)) - plane_static.hide_plane(user) playsound(src, 'sound/machines/terminal_off.ogg', 25, FALSE) /obj/machinery/computer/camera_advanced/check_eye(mob/user) @@ -179,9 +176,6 @@ eyeobj.setLoc(eyeobj.loc) if(should_supress_view_changes) user.client.view_size.supress() - // Who passes control like this god I hate static code - for(var/atom/movable/screen/plane_master/plane_static in user.hud_used?.get_true_plane_masters(CAMERA_STATIC_PLANE)) - plane_static.unhide_plane(user) /mob/camera/ai_eye/remote name = "Inactive Camera Eye" diff --git a/code/game/machinery/hologram.dm b/code/game/machinery/hologram.dm index 878e8b9b614..a94b745ae15 100644 --- a/code/game/machinery/hologram.dm +++ b/code/game/machinery/hologram.dm @@ -45,6 +45,9 @@ Possible to do for anyone motivated enough: max_integrity = 300 armor_type = /datum/armor/machinery_holopad circuit = /obj/item/circuitboard/machine/holopad + // Blue, dim light + light_power = 0.8 + light_color = LIGHT_COLOR_BLUE /// associative lazylist of the form: list(mob calling us = hologram representing that mob). /// this is only populated for holopads answering calls from another holopad var/list/masters @@ -527,31 +530,29 @@ Possible to do for anyone motivated enough: to_chat(user, "[span_danger("ERROR:")] \black Image feed in progress.") return - var/obj/effect/overlay/holo_pad_hologram/Hologram = new(loc)//Spawn a blank effect at the location. + // What to pull our appearance out of + var/obj/effect/overlay/holo_pad_hologram/hologram = new(loc)//Spawn a blank effect at the location. + var/atom/work_off = AI?.hologram_appearance || user + + hologram.icon = work_off.icon + hologram.icon_state = work_off.icon_state + hologram.copy_overlays(work_off, TRUE) + hologram.makeHologram() + if(AI) - Hologram.icon = AI.holo_icon AI.eyeobj.setLoc(get_turf(src)) //ensure the AI camera moves to the holopad else //make it like real life - Hologram.icon = user.icon - Hologram.icon_state = user.icon_state - Hologram.copy_overlays(user, TRUE) - //codersprite some holo effects here - Hologram.alpha = 100 - Hologram.add_atom_colour("#77abff", FIXED_COLOUR_PRIORITY) - Hologram.Impersonation = user + hologram.Impersonation = user + hologram.mouse_opacity = MOUSE_OPACITY_TRANSPARENT//So you can't click on it. + hologram.layer = FLY_LAYER //Above all the other objects/mobs. Or the vast majority of them. + SET_PLANE_EXPLICIT(hologram, ABOVE_GAME_PLANE, src) + hologram.set_anchored(TRUE)//So space wind cannot drag it. + hologram.name = "[user.name] (Hologram)"//If someone decides to right click. - Hologram.mouse_opacity = MOUSE_OPACITY_TRANSPARENT//So you can't click on it. - Hologram.layer = FLY_LAYER //Above all the other objects/mobs. Or the vast majority of them. - SET_PLANE_EXPLICIT(Hologram, ABOVE_GAME_PLANE, src) - Hologram.set_anchored(TRUE)//So space wind cannot drag it. - Hologram.name = "[user.name] (Hologram)"//If someone decides to right click. - Hologram.set_light(2) //hologram lighting - move_hologram() - - set_holo(user, Hologram) + set_holo(user, hologram) visible_message(span_notice("A holographic image of [user] flickers to life before your eyes!")) - return Hologram + return hologram else to_chat(user, "[span_danger("ERROR:")] Unable to project hologram.") @@ -672,20 +673,20 @@ For the other part of the code, check silicon say.dm. Particularly robot talk.*/ return FALSE /obj/machinery/holopad/proc/move_hologram(mob/living/user, turf/new_turf) - if(LAZYLEN(masters) && masters[user]) - var/obj/effect/overlay/holo_pad_hologram/holo = masters[user] - var/transfered = FALSE - if(!validate_location(new_turf)) - if(!transfer_to_nearby_pad(new_turf,user)) - clear_holo(user) - return FALSE - else - transfered = TRUE - //All is good. - holo.abstract_move(new_turf) - SET_PLANE(holo, ABOVE_GAME_PLANE, new_turf) - if(!transfered) - update_holoray(user,new_turf) + if(!LAZYLEN(masters) || !masters[user]) + return TRUE + var/obj/effect/overlay/holo_pad_hologram/holo = masters[user] + var/transfered = FALSE + if(!validate_location(new_turf)) + if(!transfer_to_nearby_pad(new_turf,user)) + return FALSE + else + transfered = TRUE + //All is good. + holo.abstract_move(new_turf) + SET_PLANE(holo, ABOVE_GAME_PLANE, new_turf) + if(!transfered) + update_holoray(user,new_turf) return TRUE @@ -715,21 +716,19 @@ For the other part of the code, check silicon say.dm. Particularly robot talk.*/ // RECORDED MESSAGES /obj/machinery/holopad/proc/setup_replay_holo(datum/holorecord/record) - var/obj/effect/overlay/holo_pad_hologram/Hologram = new(loc)//Spawn a blank effect at the location. - Hologram.add_overlay(record.caller_image) - Hologram.alpha = 170 - Hologram.add_atom_colour("#77abff", FIXED_COLOUR_PRIORITY) - Hologram.dir = SOUTH //for now - var/datum/language_holder/holder = Hologram.get_language_holder() + var/obj/effect/overlay/holo_pad_hologram/hologram = new(loc)//Spawn a blank effect at the location. + hologram.add_overlay(record.caller_image) + hologram.makeHologram() + + var/datum/language_holder/holder = hologram.get_language_holder() holder.selected_language = record.language - Hologram.mouse_opacity = MOUSE_OPACITY_TRANSPARENT//So you can't click on it. - Hologram.layer = FLY_LAYER//Above all the other objects/mobs. Or the vast majority of them. - SET_PLANE_EXPLICIT(Hologram, ABOVE_GAME_PLANE, src) - Hologram.set_anchored(TRUE)//So space wind cannot drag it. - Hologram.name = "[record.caller_name] (Hologram)"//If someone decides to right click. - Hologram.set_light(2) //hologram lighting + hologram.mouse_opacity = MOUSE_OPACITY_TRANSPARENT//So you can't click on it. + hologram.layer = FLY_LAYER//Above all the other objects/mobs. Or the vast majority of them. + SET_PLANE_EXPLICIT(hologram, ABOVE_GAME_PLANE, src) + hologram.set_anchored(TRUE)//So space wind cannot drag it. + hologram.name = "[record.caller_name] (Hologram)"//If someone decides to right click. visible_message(span_notice("A holographic image of [record.caller_name] flickers to life before your eyes!")) - return Hologram + return hologram /obj/machinery/holopad/proc/replay_start() if(!replay_mode) @@ -827,6 +826,8 @@ For the other part of the code, check silicon say.dm. Particularly robot talk.*/ QDEL_NULL(disk.record) /obj/effect/overlay/holo_pad_hologram + // Adds KEEP_TOGETHER to ensure we render overlays right + appearance_flags = TILE_BOUND|PIXEL_SCALE|LONG_GLIDE|KEEP_TOGETHER initial_language_holder = /datum/language_holder/universal var/mob/living/Impersonation var/datum/holocall/HC @@ -858,6 +859,25 @@ For the other part of the code, check silicon say.dm. Particularly robot talk.*/ pixel_x = -32 pixel_y = -32 alpha = 100 + var/atom/movable/render_step/emissive/glow + +/obj/effect/overlay/holoray/Initialize(mapload) + . = ..() + if(!render_target) + var/static/uid = 0 + render_target = "holoray#[uid]" + uid++ + // Let's GLOW BROTHER! (Doing it like this is the most robust option compared to duped overlays) + glow = new(src, render_target) + // We need to counteract the pixel offset to ensure we don't double offset (I hate byond) + glow.pixel_x = 32 + glow.pixel_y = 32 + add_overlay(glow) + LAZYADD(update_overlays_on_z, glow) + +/obj/effect/overlay/holoray/Destroy(force) + . = ..() + QDEL_NULL(glow) #undef CAN_HEAR_ACTIVE_HOLOCALLS #undef CAN_HEAR_ALL_FLAGS diff --git a/code/game/objects/items/rcd/RCD.dm b/code/game/objects/items/rcd/RCD.dm index 8552dd4af83..a2189f396db 100644 --- a/code/game/objects/items/rcd/RCD.dm +++ b/code/game/objects/items/rcd/RCD.dm @@ -163,13 +163,8 @@ GLOBAL_VAR_INIT(icon_holographic_wall, init_holographic_wall()) GLOBAL_VAR_INIT(icon_holographic_window, init_holographic_window()) -// `initial` does not work here. Neither does instantiating a wall/whatever -// and referencing that. I don't know why. /proc/init_holographic_wall() - return getHologramIcon( - icon('icons/turf/walls/wall.dmi', "wall-0"), - opacity = 1, - ) + return icon('icons/turf/walls/wall.dmi', "wall-0") /proc/init_holographic_window() var/icon/grille_icon = icon('icons/obj/structures.dmi', "grille") @@ -177,7 +172,7 @@ GLOBAL_VAR_INIT(icon_holographic_window, init_holographic_window()) grille_icon.Blend(window_icon, ICON_OVERLAY) - return getHologramIcon(grille_icon) + return grille_icon /obj/item/construction/rcd/ui_action_click(mob/user, actiontype) if (!COOLDOWN_FINISHED(src, destructive_scan_cooldown)) @@ -223,6 +218,7 @@ GLOBAL_VAR_INIT(icon_holographic_window, init_holographic_window()) var/obj/effect/rcd_hologram/hologram = new(surrounding_turf) hologram.icon = hologram_icon + hologram.makeHologram() animate(hologram, alpha = 0, time = fade_time, easing = CIRCULAR_EASING | EASE_IN) /obj/effect/rcd_hologram diff --git a/code/modules/mob/living/silicon/ai/ai.dm b/code/modules/mob/living/silicon/ai/ai.dm index ccaa25735db..efd3171e993 100644 --- a/code/modules/mob/living/silicon/ai/ai.dm +++ b/code/modules/mob/living/silicon/ai/ai.dm @@ -36,7 +36,7 @@ var/aiRestorePowerRoutine = POWER_RESTORATION_OFF var/requires_power = POWER_REQ_ALL var/can_be_carded = TRUE - var/icon/holo_icon //Default is assigned when AI is created. + var/mutable_appearance/hologram_appearance //Default is assigned when AI is created. var/obj/controlled_equipment //A piece of equipment, to determine whether to relaymove or use the AI eye. var/radio_enabled = TRUE //Determins if a carded AI can speak with its built in radio or not. radiomod = ";" //AIs will, by default, state their laws on the internal radio. @@ -163,7 +163,7 @@ INVOKE_ASYNC(src, PROC_REF(set_core_display_icon)) - holo_icon = getHologramIcon(icon('icons/mob/silicon/ai.dmi',"default")) + hologram_appearance = mutable_appearance('icons/mob/silicon/ai.dmi',"default") spark_system = new /datum/effect_system/spark_spread() spark_system.set_up(5, 0, src) @@ -674,22 +674,17 @@ return var/mutable_appearance/character_icon = personnel_list[input] if(character_icon) - qdel(holo_icon)//Clear old icon so we're not storing it in memory. character_icon.setDir(SOUTH) - - var/icon/icon_for_holo = getFlatIcon(character_icon) - holo_icon = getHologramIcon(icon(icon_for_holo)) + hologram_appearance = character_icon if("My Character") switch(tgui_alert(usr,"WARNING: Your AI hologram will take the appearance of your currently selected character ([usr.client.prefs?.read_preference(/datum/preference/name/real_name)]). Are you sure you want to proceed?", "Customize", list("Yes","No"))) if("Yes") var/mob/living/carbon/human/dummy/ai_dummy = new - var/mutable_appearance/appearance = usr.client.prefs.render_new_preview_appearance(ai_dummy) - var/icon/character_icon = getHologramIcon(getFlatIcon(appearance)) - if(character_icon) - qdel(holo_icon) + var/mutable_appearance/dummy_appearance = usr.client.prefs.render_new_preview_appearance(ai_dummy) + if(dummy_appearance) qdel(ai_dummy) - holo_icon = character_icon + hologram_appearance = dummy_appearance if("No") return FALSE @@ -715,16 +710,17 @@ return if(isnull(icon_list[input])) return - qdel(holo_icon) + var/working_state = "" switch(input) if("poly") - holo_icon = getHologramIcon(icon(icon_list[input],"parrot_fly")) + working_state = "parrot_fly" if("chicken") - holo_icon = getHologramIcon(icon(icon_list[input],"chicken_brown")) + working_state = "chicken_brown" if("spider") - holo_icon = getHologramIcon(icon(icon_list[input],"guard")) + working_state = "guard" else - holo_icon = getHologramIcon(icon(icon_list[input], input)) + working_state = input + hologram_appearance = mutable_appearance(icon_list[input], working_state) else var/list/icon_list = list( "default" = 'icons/mob/silicon/ai.dmi', @@ -739,12 +735,13 @@ return if(isnull(icon_list[input])) return - qdel(holo_icon) + var/working_state = "" switch(input) if("xeno queen") - holo_icon = getHologramIcon(icon(icon_list[input],"alienq")) + working_state = "alienq" else - holo_icon = getHologramIcon(icon(icon_list[input], input)) + working_state = input + hologram_appearance = mutable_appearance(icon_list[input], working_state) return /datum/action/innate/core_return diff --git a/code/modules/mob/living/silicon/ai/freelook/eye.dm b/code/modules/mob/living/silicon/ai/freelook/eye.dm index dbba22c9629..e5390f9a3f0 100644 --- a/code/modules/mob/living/silicon/ai/freelook/eye.dm +++ b/code/modules/mob/living/silicon/ai/freelook/eye.dm @@ -112,7 +112,9 @@ //Holopad if(istype(ai.current, /obj/machinery/holopad)) var/obj/machinery/holopad/H = ai.current - H.move_hologram(ai, destination) + if(!H.move_hologram(ai, destination)) + H.clear_holo(ai) + if(ai.camera_light_on) ai.light_cameras() if(ai.master_multicam) diff --git a/code/modules/visuals/render_steps.dm b/code/modules/visuals/render_steps.dm index 239d8ba421f..74cc7f80d7f 100644 --- a/code/modules/visuals/render_steps.dm +++ b/code/modules/visuals/render_steps.dm @@ -56,11 +56,6 @@ * This should only be used internally. If you are directly creating more of these, you're * almost guaranteed to be doing something wrong. */ -/** - * Render step that modfies an atom's color - * Useful for creating coherent emissive blockers out of things like glass floors by lowering alpha statically using matrixes - * Other stuff too I'm sure - */ /atom/movable/render_step/emissive_blocker name = "emissive blocker" plane = EMISSIVE_PLANE @@ -69,3 +64,18 @@ /atom/movable/render_step/emissive_blocker/Initialize(mapload, source) . = ..() src.color = GLOB.em_block_color + + +/** + * Render step that makes the passed in render source GLOW + * + * Copies an appearance vis render_target and render_source on to the emissive plane + */ +/atom/movable/render_step/emissive + name = "emissive" + plane = EMISSIVE_PLANE + appearance_flags = EMISSIVE_APPEARANCE_FLAGS|RESET_TRANSFORM + +/atom/movable/render_step/emissive/Initialize(mapload, source) + . = ..() + src.color = GLOB.emissive_color