diff --git a/code/__DEFINES/hud.dm b/code/__DEFINES/hud.dm index 88cba1c449..9c161c0a5f 100644 --- a/code/__DEFINES/hud.dm +++ b/code/__DEFINES/hud.dm @@ -7,3 +7,6 @@ #define ui_borg_pda_send "CENTER+5:21,SOUTH:5" // To the right of the alert panel #define ui_borg_pda_log "CENTER+6:21,SOUTH:5" + +/// The filter name for the hover outline +#define HOVER_OUTLINE_FILTER "hover_outline" diff --git a/code/game/atoms.dm b/code/game/atoms.dm index c72b4f7b60..eac9f75a94 100644 --- a/code/game/atoms.dm +++ b/code/game/atoms.dm @@ -1356,6 +1356,11 @@ if(filter_data && filter_data[name]) return filters[filter_data.Find(name)] +/// Returns the indice in filters of the given filter name. +/// If it is not found, returns null. +/atom/proc/get_filter_index(name) + return filter_data?.Find(name) + /atom/proc/remove_filter(name_or_names) if(!filter_data) return diff --git a/code/game/objects/effects/decals/misc.dm b/code/game/objects/effects/decals/misc.dm index 752a5dff2c..fe216c0623 100644 --- a/code/game/objects/effects/decals/misc.dm +++ b/code/game/objects/effects/decals/misc.dm @@ -1,18 +1,3 @@ -/obj/effect/temp_visual/point - name = "pointer" - icon = 'icons/mob/screen_gen.dmi' - icon_state = "arrow" - layer = POINT_LAYER - duration = 25 - -/obj/effect/temp_visual/point/Initialize(mapload, set_invis = 0) - . = ..() - var/atom/old_loc = loc - loc = get_turf(src) // We don't want to actualy trigger anything when it moves - pixel_x = old_loc.pixel_x - pixel_y = old_loc.pixel_y - invisibility = set_invis - //Used by spraybottles. /obj/effect/decal/chempuff name = "chemicals" diff --git a/code/game/objects/items.dm b/code/game/objects/items.dm index 314db6b016..464017474f 100644 --- a/code/game/objects/items.dm +++ b/code/game/objects/items.dm @@ -922,13 +922,13 @@ GLOBAL_VAR_INIT(embedpocalypse, FALSE) // if true, all items will be able to emb /obj/item/MouseDrop(atom/over, src_location, over_location, src_control, over_control, params) . = ..() - remove_filter("hover_outline") //get rid of the hover effect in case the mouse exit isn't called if someone drags and drops an item and somthing goes wrong + remove_filter(HOVER_OUTLINE_FILTER) //get rid of the hover effect in case the mouse exit isn't called if someone drags and drops an item and somthing goes wrong /obj/item/MouseExited(location, control, params) SEND_SIGNAL(src, COMSIG_ITEM_MOUSE_EXIT, location, control, params) deltimer(usr.client.tip_timer) //delete any in-progress timer if the mouse is moved off the item before it finishes closeToolTip(usr) - remove_filter("hover_outline") + remove_filter(HOVER_OUTLINE_FILTER) /obj/item/proc/apply_outline(outline_color = null) if(get(src, /mob) != usr || QDELETED(src) || isobserver(usr)) //cancel if the item isn't in an inventory, is being deleted, or if the person hovering is a ghost (so that people spectating you don't randomly make your items glow) @@ -959,7 +959,7 @@ GLOBAL_VAR_INIT(embedpocalypse, FALSE) // if true, all items will be able to emb if(color) outline_color = COLOR_WHITE //if the item is recolored then the outline will be too, let's make the outline white so it becomes the same color instead of some ugly mix of the theme and the tint - add_filter("hover_outline", 1, list("type" = "outline", "size" = 1, "color" = outline_color)) + add_filter(HOVER_OUTLINE_FILTER, 1, list("type" = "outline", "size" = 1, "color" = outline_color)) // Called when a mob tries to use the item as a tool. // Handles most checks. diff --git a/code/modules/mob/mob.dm b/code/modules/mob/mob.dm index f80866d97e..0399b2bacb 100644 --- a/code/modules/mob/mob.dm +++ b/code/modules/mob/mob.dm @@ -369,27 +369,6 @@ var/msg = "[src] makes eye contact with you." addtimer(CALLBACK(GLOBAL_PROC, .proc/to_chat, examined_mob, msg), 3) -//same as above -//note: ghosts can point, this is intended -//visible_message will handle invisibility properly -//overridden here and in /mob/dead/observer for different point span classes and sanity checks -/mob/verb/pointed(atom/A as mob|obj|turf in fov_view()) - set name = "Point To" - set category = "Object" - - if(!src || !isturf(src.loc) || !(A in view(src.loc))) - return FALSE - if(istype(A, /obj/effect/temp_visual/point)) - return FALSE - - var/tile = get_turf(A) - if (!tile) - return FALSE - - new /obj/effect/temp_visual/point(A,invisibility) - SEND_SIGNAL(src, COMSIG_MOB_POINTED, A) - return TRUE - /mob/proc/can_resist() return FALSE //overridden in living.dm diff --git a/code/modules/point/point.dm b/code/modules/point/point.dm new file mode 100644 index 0000000000..cfadf391c5 --- /dev/null +++ b/code/modules/point/point.dm @@ -0,0 +1,110 @@ +#define POINT_TIME (2.5 SECONDS) + +/** + * Point at an atom + * + * Intended to enable and standardise the pointing animation for all atoms + * + * Not intended as a replacement for the mob verb + */ +/atom/movable/proc/point_at(atom/pointed_atom) + if(!isturf(loc)) + return + + if (pointed_atom in src) + create_point_bubble(pointed_atom) + return + + var/turf/tile = get_turf(pointed_atom) + if (!tile) + return + + var/turf/our_tile = get_turf(src) + var/obj/visual = new /obj/effect/temp_visual/point(our_tile, invisibility) + + animate(visual, pixel_x = (tile.x - our_tile.x) * world.icon_size + pointed_atom.pixel_x, pixel_y = (tile.y - our_tile.y) * world.icon_size + pointed_atom.pixel_y, time = 1.7, easing = EASE_OUT) + +/atom/movable/proc/create_point_bubble(atom/pointed_atom) + var/obj/effect/thought_bubble_effect = new + + var/mutable_appearance/thought_bubble = mutable_appearance( + 'icons/effects/effects.dmi', + "thought_bubble", + layer = POINT_LAYER, + appearance_flags = KEEP_APART, + ) + + var/mutable_appearance/pointed_atom_appearance = new(pointed_atom.appearance) + pointed_atom_appearance.blend_mode = BLEND_INSET_OVERLAY + pointed_atom_appearance.plane = thought_bubble.plane + pointed_atom_appearance.layer = FLOAT_LAYER + pointed_atom_appearance.pixel_x = 0 + pointed_atom_appearance.pixel_y = 0 + thought_bubble.overlays += pointed_atom_appearance + + var/hover_outline_index = pointed_atom.get_filter_index(HOVER_OUTLINE_FILTER) + if (!isnull(hover_outline_index)) + pointed_atom_appearance.filters.Cut(hover_outline_index, hover_outline_index + 1) + + thought_bubble.pixel_x = 16 + thought_bubble.pixel_y = 32 + thought_bubble.alpha = 200 + thought_bubble.mouse_opacity = MOUSE_OPACITY_TRANSPARENT + + var/mutable_appearance/point_visual = mutable_appearance( + 'icons/mob/screen_gen.dmi', + "arrow", + plane = thought_bubble.plane, + ) + + thought_bubble.overlays += point_visual + + // vis_contents is used to preserve mouse opacity + thought_bubble_effect.appearance = thought_bubble + vis_contents += thought_bubble_effect + + QDEL_IN(thought_bubble_effect, POINT_TIME) + +/obj/effect/temp_visual/point + name = "pointer" + icon = 'icons/mob/screen_gen.dmi' + icon_state = "arrow" + layer = POINT_LAYER + duration = POINT_TIME + +/obj/effect/temp_visual/point/Initialize(mapload, set_invis = 0) + . = ..() + var/atom/old_loc = loc + abstract_move(get_turf(src)) + pixel_x = old_loc.pixel_x + pixel_y = old_loc.pixel_y + invisibility = set_invis + +#undef POINT_TIME + +/** + * Point at an atom + * + * mob verbs are faster than object verbs. See + * [this byond forum post](https://secure.byond.com/forum/?post=1326139&page=2#comment8198716) + * for why this isn't atom/verb/pointed() + * + * note: ghosts can point, this is intended + * + * visible_message will handle invisibility properly + * + * overridden here and in /mob/dead/observer for different point span classes and sanity checks + */ +/mob/verb/pointed(atom/target as mob|obj|turf in fov_view()) + set name = "Point To" + set category = "Object" + + if(client && !(target in view(client.view, src))) + return FALSE + if(istype(target, /obj/effect/temp_visual/point)) + return FALSE + + point_at(target) + + SEND_SIGNAL(src, COMSIG_MOB_POINTED, target) + return TRUE diff --git a/icons/effects/effects.dmi b/icons/effects/effects.dmi index be99d57a3d..8334c83224 100644 Binary files a/icons/effects/effects.dmi and b/icons/effects/effects.dmi differ diff --git a/tgstation.dme b/tgstation.dme index 50ff9eba35..61929f6089 100644 --- a/tgstation.dme +++ b/tgstation.dme @@ -3175,6 +3175,7 @@ #include "code\modules\plumbing\plumbers\reaction_chamber.dm" #include "code\modules\plumbing\plumbers\splitters.dm" #include "code\modules\plumbing\plumbers\synthesizer.dm" +#include "code\modules\point\point.dm" #include "code\modules\pool\pool_controller.dm" #include "code\modules\pool\pool_drain.dm" #include "code\modules\pool\pool_effects.dm"