mirror of
https://github.com/ParadiseSS13/Paradise.git
synced 2026-08-30 15:37:36 +01:00
SSOverlays & Hover Inventory Indicator
This ports the hover inventory indicator from /tg/, and by necessity, SSOverlays. The hover inventory indicator basically shows where you are trying to put an item, and then shows an item ghost in red or green, giving visual feedback as to if that item will go in the slot or not. SSOverlays is a much broader system for managing overlays, which should eventually take over *all* overlays, but I have only ported the basic system and implemented it where necessary for it to work for the hover inventory items currently.
This commit is contained in:
@@ -54,6 +54,8 @@
|
||||
// LAVA_PROTECT used on the flags_2 variable for both SUIT and HEAD items, and stops lava damage. Must be present in both to stop lava damage.
|
||||
#define LAVA_PROTECT_2 2048
|
||||
|
||||
#define OVERLAY_QUEUED_2 4096
|
||||
|
||||
//Reagent flags
|
||||
#define REAGENT_NOREACT 1
|
||||
|
||||
|
||||
@@ -124,3 +124,22 @@
|
||||
#define RUNLEVEL_POSTGAME 8
|
||||
|
||||
#define RUNLEVELS_DEFAULT (RUNLEVEL_SETUP | RUNLEVEL_GAME | RUNLEVEL_POSTGAME)
|
||||
|
||||
#define COMPILE_OVERLAYS(A)\
|
||||
if (TRUE) {\
|
||||
var/list/ad = A.add_overlays;\
|
||||
var/list/rm = A.remove_overlays;\
|
||||
var/list/po = A.priority_overlays;\
|
||||
if(LAZYLEN(rm)){\
|
||||
A.overlays -= rm;\
|
||||
rm.Cut();\
|
||||
}\
|
||||
if(LAZYLEN(ad)){\
|
||||
A.overlays |= ad;\
|
||||
ad.Cut();\
|
||||
}\
|
||||
if(LAZYLEN(po)){\
|
||||
A.overlays |= po;\
|
||||
}\
|
||||
A.flags_2 &= ~OVERLAY_QUEUED_2;\
|
||||
}
|
||||
@@ -275,8 +275,38 @@
|
||||
|
||||
/obj/screen/inventory
|
||||
var/slot_id //The indentifier for the slot. It has nothing to do with ID cards.
|
||||
var/list/object_overlays = list()
|
||||
layer = 19
|
||||
|
||||
/obj/screen/inventory/MouseEntered()
|
||||
..()
|
||||
add_overlays()
|
||||
|
||||
/obj/screen/inventory/MouseExited()
|
||||
..()
|
||||
cut_overlay(object_overlays)
|
||||
object_overlays.Cut()
|
||||
|
||||
/obj/screen/inventory/proc/add_overlays()
|
||||
var/mob/user = hud.mymob
|
||||
|
||||
if(hud && user && slot_id)
|
||||
var/obj/item/holding = user.get_active_hand()
|
||||
|
||||
if(!holding || user.get_item_by_slot(slot_id))
|
||||
return
|
||||
|
||||
var/image/item_overlay = image(holding)
|
||||
item_overlay.alpha = 92
|
||||
|
||||
if(!user.can_equip(holding, slot_id, disable_warning = TRUE))
|
||||
item_overlay.color = "#ff0000"
|
||||
else
|
||||
item_overlay.color = "#00ff00"
|
||||
|
||||
object_overlays += item_overlay
|
||||
add_overlay(object_overlays)
|
||||
|
||||
/obj/screen/inventory/Click()
|
||||
// At this point in client Click() code we have passed the 1/10 sec check and little else
|
||||
// We don't even know if it's a middle click
|
||||
|
||||
@@ -0,0 +1,213 @@
|
||||
SUBSYSTEM_DEF(overlays)
|
||||
name = "Overlay"
|
||||
flags = SS_TICKER
|
||||
wait = 1
|
||||
priority = FIRE_PRIORITY_OVERLAYS
|
||||
init_order = INIT_ORDER_OVERLAY
|
||||
|
||||
var/list/queue
|
||||
var/list/stats
|
||||
var/list/overlay_icon_state_caches
|
||||
var/list/overlay_icon_cache
|
||||
|
||||
/datum/controller/subsystem/overlays/PreInit()
|
||||
overlay_icon_state_caches = list()
|
||||
overlay_icon_cache = list()
|
||||
queue = list()
|
||||
stats = list()
|
||||
|
||||
/datum/controller/subsystem/overlays/Initialize()
|
||||
initialized = TRUE
|
||||
fire(mc_check = FALSE)
|
||||
return ..()
|
||||
|
||||
|
||||
/datum/controller/subsystem/overlays/stat_entry()
|
||||
..("Ov:[length(queue)]")
|
||||
|
||||
/datum/controller/subsystem/overlays/Recover()
|
||||
overlay_icon_state_caches = SSoverlays.overlay_icon_state_caches
|
||||
overlay_icon_cache = SSoverlays.overlay_icon_cache
|
||||
queue = SSoverlays.queue
|
||||
|
||||
|
||||
/datum/controller/subsystem/overlays/fire(resumed = FALSE, mc_check = TRUE)
|
||||
var/list/queue = src.queue
|
||||
var/static/count = 0
|
||||
if (count)
|
||||
var/c = count
|
||||
count = 0 //so if we runtime on the Cut, we don't try again.
|
||||
queue.Cut(1,c+1)
|
||||
|
||||
for (var/thing in queue)
|
||||
count++
|
||||
if(thing)
|
||||
var/atom/A = thing
|
||||
COMPILE_OVERLAYS(A)
|
||||
if(mc_check)
|
||||
if(MC_TICK_CHECK)
|
||||
break
|
||||
else
|
||||
CHECK_TICK
|
||||
|
||||
if (count)
|
||||
queue.Cut(1,count+1)
|
||||
count = 0
|
||||
|
||||
/proc/iconstate2appearance(icon, iconstate)
|
||||
var/static/image/stringbro = new()
|
||||
var/list/icon_states_cache = SSoverlays.overlay_icon_state_caches
|
||||
var/list/cached_icon = icon_states_cache[icon]
|
||||
if (cached_icon)
|
||||
var/cached_appearance = cached_icon["[iconstate]"]
|
||||
if (cached_appearance)
|
||||
return cached_appearance
|
||||
stringbro.icon = icon
|
||||
stringbro.icon_state = iconstate
|
||||
if (!cached_icon) //not using the macro to save an associated lookup
|
||||
cached_icon = list()
|
||||
icon_states_cache[icon] = cached_icon
|
||||
var/cached_appearance = stringbro.appearance
|
||||
cached_icon["[iconstate]"] = cached_appearance
|
||||
return cached_appearance
|
||||
|
||||
/proc/icon2appearance(icon)
|
||||
var/static/image/iconbro = new()
|
||||
var/list/icon_cache = SSoverlays.overlay_icon_cache
|
||||
. = icon_cache[icon]
|
||||
if (!.)
|
||||
iconbro.icon = icon
|
||||
. = iconbro.appearance
|
||||
icon_cache[icon] = .
|
||||
|
||||
/atom/proc/build_appearance_list(old_overlays)
|
||||
var/static/image/appearance_bro = new()
|
||||
var/list/new_overlays = list()
|
||||
if (!islist(old_overlays))
|
||||
old_overlays = list(old_overlays)
|
||||
for (var/overlay in old_overlays)
|
||||
if(!overlay)
|
||||
continue
|
||||
if (istext(overlay))
|
||||
new_overlays += iconstate2appearance(icon, overlay)
|
||||
else if(isicon(overlay))
|
||||
new_overlays += icon2appearance(overlay)
|
||||
else
|
||||
if(isloc(overlay))
|
||||
var/atom/A = overlay
|
||||
if (A.flags_2 & OVERLAY_QUEUED_2)
|
||||
COMPILE_OVERLAYS(A)
|
||||
appearance_bro.appearance = overlay //this works for images and atoms too!
|
||||
if(!ispath(overlay))
|
||||
var/image/I = overlay
|
||||
appearance_bro.dir = I.dir
|
||||
new_overlays += appearance_bro.appearance
|
||||
return new_overlays
|
||||
|
||||
#define NOT_QUEUED_ALREADY (!(flags_2 & OVERLAY_QUEUED_2))
|
||||
#define QUEUE_FOR_COMPILE flags_2 |= OVERLAY_QUEUED_2; SSoverlays.queue += src;
|
||||
/atom/proc/cut_overlays(priority = FALSE)
|
||||
LAZYINITLIST(priority_overlays)
|
||||
LAZYINITLIST(remove_overlays)
|
||||
LAZYINITLIST(add_overlays)
|
||||
remove_overlays = overlays.Copy()
|
||||
add_overlays.Cut()
|
||||
|
||||
if(priority)
|
||||
priority_overlays.Cut()
|
||||
|
||||
//If not already queued for work and there are overlays to remove
|
||||
if(NOT_QUEUED_ALREADY && remove_overlays.len)
|
||||
QUEUE_FOR_COMPILE
|
||||
|
||||
/atom/proc/cut_overlay(list/overlays, priority)
|
||||
if(!overlays)
|
||||
return
|
||||
overlays = build_appearance_list(overlays)
|
||||
LAZYINITLIST(add_overlays) //always initialized after this point
|
||||
LAZYINITLIST(priority_overlays)
|
||||
LAZYINITLIST(remove_overlays)
|
||||
var/a_len = add_overlays.len
|
||||
var/r_len = remove_overlays.len
|
||||
var/p_len = priority_overlays.len
|
||||
remove_overlays += overlays
|
||||
add_overlays -= overlays
|
||||
|
||||
|
||||
if(priority)
|
||||
var/list/cached_priority = priority_overlays
|
||||
LAZYREMOVE(cached_priority, overlays)
|
||||
|
||||
var/fa_len = add_overlays.len
|
||||
var/fr_len = remove_overlays.len
|
||||
var/fp_len = priority_overlays.len
|
||||
|
||||
//If not already queued and there is work to be done
|
||||
if(NOT_QUEUED_ALREADY && (fa_len != a_len || fr_len != r_len || fp_len != p_len))
|
||||
QUEUE_FOR_COMPILE
|
||||
|
||||
/atom/proc/add_overlay(list/overlays, priority = FALSE)
|
||||
if(!overlays)
|
||||
return
|
||||
|
||||
overlays = build_appearance_list(overlays)
|
||||
|
||||
LAZYINITLIST(add_overlays) //always initialized after this point
|
||||
LAZYINITLIST(priority_overlays)
|
||||
var/a_len = add_overlays.len
|
||||
var/p_len = priority_overlays.len
|
||||
|
||||
if(priority)
|
||||
priority_overlays += overlays //or in the image. Can we use [image] = image?
|
||||
var/fp_len = priority_overlays.len
|
||||
if(NOT_QUEUED_ALREADY && fp_len != p_len)
|
||||
QUEUE_FOR_COMPILE
|
||||
else
|
||||
add_overlays += overlays
|
||||
var/fa_len = add_overlays.len
|
||||
if(NOT_QUEUED_ALREADY && fa_len != a_len)
|
||||
QUEUE_FOR_COMPILE
|
||||
|
||||
/atom/proc/copy_overlays(atom/other, cut_old) //copys our_overlays from another atom
|
||||
if(!other)
|
||||
if(cut_old)
|
||||
cut_overlays()
|
||||
return
|
||||
|
||||
var/list/cached_other = other.overlays.Copy()
|
||||
if(cached_other)
|
||||
if(cut_old || !LAZYLEN(overlays))
|
||||
remove_overlays = overlays
|
||||
add_overlays = cached_other
|
||||
if(NOT_QUEUED_ALREADY)
|
||||
QUEUE_FOR_COMPILE
|
||||
else if(cut_old)
|
||||
cut_overlays()
|
||||
|
||||
#undef NOT_QUEUED_ALREADY
|
||||
#undef QUEUE_FOR_COMPILE
|
||||
|
||||
//TODO: Better solution for these?
|
||||
/image/proc/add_overlay(x)
|
||||
overlays |= x
|
||||
|
||||
/image/proc/cut_overlay(x)
|
||||
overlays -= x
|
||||
|
||||
/image/proc/cut_overlays(x)
|
||||
overlays.Cut()
|
||||
|
||||
/image/proc/copy_overlays(atom/other, cut_old)
|
||||
if(!other)
|
||||
if(cut_old)
|
||||
cut_overlays()
|
||||
return
|
||||
|
||||
var/list/cached_other = other.overlays.Copy()
|
||||
if(cached_other)
|
||||
if(cut_old || !overlays.len)
|
||||
overlays = cached_other
|
||||
else
|
||||
overlays |= cached_other
|
||||
else if(cut_old)
|
||||
cut_overlays()
|
||||
@@ -44,6 +44,10 @@
|
||||
|
||||
var/initialized = FALSE
|
||||
|
||||
var/list/priority_overlays //overlays that should remain on top and not normally removed when using cut_overlay functions, like c4.
|
||||
var/list/remove_overlays // a very temporary list of overlays to remove
|
||||
var/list/add_overlays // a very temporary list of overlays to add
|
||||
|
||||
/atom/New(loc, ...)
|
||||
if(use_preloader && (src.type == _preloader.target_path))//in case the instanciated atom is creating other atoms in New()
|
||||
_preloader.load(src)
|
||||
@@ -137,6 +141,8 @@
|
||||
|
||||
QDEL_NULL(reagents)
|
||||
invisibility = 101
|
||||
LAZYCLEARLIST(overlays)
|
||||
LAZYCLEARLIST(priority_overlays)
|
||||
return ..()
|
||||
|
||||
//Hook for running code when a dir change occurs
|
||||
|
||||
@@ -73,7 +73,7 @@
|
||||
bitesize = 4
|
||||
var/top = 1 //Do we have a top?
|
||||
var/obj/item/toptype
|
||||
var/add_overlays = 1 //Do we stack?
|
||||
var/snack_overlays = 1 //Do we stack?
|
||||
// var/offsetstuff = 1 //Do we offset the overlays?
|
||||
var/sandwich_limit = 40
|
||||
var/fullycustom = 0
|
||||
@@ -87,7 +87,7 @@
|
||||
icon_state = "personal_pizza"
|
||||
baseicon = "personal_pizza"
|
||||
basename = "personal pizza"
|
||||
add_overlays = 0
|
||||
snack_overlays = 0
|
||||
top = 0
|
||||
|
||||
/obj/item/reagent_containers/food/snacks/customizable/pasta
|
||||
@@ -96,7 +96,7 @@
|
||||
icon_state = "pasta_bot"
|
||||
baseicon = "pasta_bot"
|
||||
basename = "pasta"
|
||||
add_overlays = 0
|
||||
snack_overlays = 0
|
||||
top = 0
|
||||
|
||||
/obj/item/reagent_containers/food/snacks/customizable/cook/bread
|
||||
@@ -105,7 +105,7 @@
|
||||
icon_state = "breadcustom"
|
||||
baseicon = "breadcustom"
|
||||
basename = "bread"
|
||||
add_overlays = 0
|
||||
snack_overlays = 0
|
||||
top = 0
|
||||
|
||||
/obj/item/reagent_containers/food/snacks/customizable/cook/pie
|
||||
@@ -114,7 +114,7 @@
|
||||
icon_state = "piecustom"
|
||||
baseicon = "piecustom"
|
||||
basename = "pie"
|
||||
add_overlays = 0
|
||||
snack_overlays = 0
|
||||
top = 0
|
||||
|
||||
/obj/item/reagent_containers/food/snacks/customizable/cook/cake
|
||||
@@ -123,7 +123,7 @@
|
||||
icon_state = "cakecustom"
|
||||
baseicon = "cakecustom"
|
||||
basename = "cake"
|
||||
add_overlays = 0
|
||||
snack_overlays = 0
|
||||
top = 0
|
||||
|
||||
/obj/item/reagent_containers/food/snacks/customizable/cook/jelly
|
||||
@@ -132,7 +132,7 @@
|
||||
icon_state = "jellycustom"
|
||||
baseicon = "jellycustom"
|
||||
basename = "jelly"
|
||||
add_overlays = 0
|
||||
snack_overlays = 0
|
||||
top = 0
|
||||
|
||||
/obj/item/reagent_containers/food/snacks/customizable/cook/donkpocket
|
||||
@@ -141,7 +141,7 @@
|
||||
icon_state = "donkcustom"
|
||||
baseicon = "donkcustom"
|
||||
basename = "donk pocket"
|
||||
add_overlays = 0
|
||||
snack_overlays = 0
|
||||
top = 0
|
||||
|
||||
/obj/item/reagent_containers/food/snacks/customizable/cook/kebab
|
||||
@@ -150,7 +150,7 @@
|
||||
icon_state = "kababcustom"
|
||||
baseicon = "kababcustom"
|
||||
basename = "kebab"
|
||||
add_overlays = 0
|
||||
snack_overlays = 0
|
||||
top = 0
|
||||
|
||||
/obj/item/reagent_containers/food/snacks/customizable/cook/salad
|
||||
@@ -159,7 +159,7 @@
|
||||
icon_state = "saladcustom"
|
||||
baseicon = "saladcustom"
|
||||
basename = "salad"
|
||||
add_overlays = 0
|
||||
snack_overlays = 0
|
||||
top = 0
|
||||
|
||||
/obj/item/reagent_containers/food/snacks/customizable/cook/waffles
|
||||
@@ -168,7 +168,7 @@
|
||||
icon_state = "wafflecustom"
|
||||
baseicon = "wafflecustom"
|
||||
basename = "waffles"
|
||||
add_overlays = 0
|
||||
snack_overlays = 0
|
||||
top = 0
|
||||
|
||||
/obj/item/reagent_containers/food/snacks/customizable/candy/cookie
|
||||
@@ -177,7 +177,7 @@
|
||||
icon_state = "cookiecustom"
|
||||
baseicon = "cookiecustom"
|
||||
basename = "cookie"
|
||||
add_overlays = 0
|
||||
snack_overlays = 0
|
||||
top = 0
|
||||
|
||||
/obj/item/reagent_containers/food/snacks/customizable/candy/cotton
|
||||
@@ -186,7 +186,7 @@
|
||||
icon_state = "cottoncandycustom"
|
||||
baseicon = "cottoncandycustom"
|
||||
basename = "flavored cotton candy"
|
||||
add_overlays = 0
|
||||
snack_overlays = 0
|
||||
top = 0
|
||||
|
||||
/obj/item/reagent_containers/food/snacks/customizable/candy/gummybear
|
||||
@@ -195,7 +195,7 @@
|
||||
icon_state = "gummybearcustom"
|
||||
baseicon = "gummybearcustom"
|
||||
basename = "flavored giant gummy bear"
|
||||
add_overlays = 0
|
||||
snack_overlays = 0
|
||||
top = 0
|
||||
|
||||
/obj/item/reagent_containers/food/snacks/customizable/candy/gummyworm
|
||||
@@ -204,7 +204,7 @@
|
||||
icon_state = "gummywormcustom"
|
||||
baseicon = "gummywormcustom"
|
||||
basename = "flavored giant gummy worm"
|
||||
add_overlays = 0
|
||||
snack_overlays = 0
|
||||
top = 0
|
||||
|
||||
/obj/item/reagent_containers/food/snacks/customizable/candy/jellybean
|
||||
@@ -213,7 +213,7 @@
|
||||
icon_state = "jellybeancustom"
|
||||
baseicon = "jellybeancustom"
|
||||
basename = "flavored giant jelly bean"
|
||||
add_overlays = 0
|
||||
snack_overlays = 0
|
||||
top = 0
|
||||
|
||||
/obj/item/reagent_containers/food/snacks/customizable/candy/jawbreaker
|
||||
@@ -222,7 +222,7 @@
|
||||
icon_state = "jawbreakercustom"
|
||||
baseicon = "jawbreakercustom"
|
||||
basename = "flavored jawbreaker"
|
||||
add_overlays = 0
|
||||
snack_overlays = 0
|
||||
top = 0
|
||||
|
||||
/obj/item/reagent_containers/food/snacks/customizable/candy/candycane
|
||||
@@ -231,7 +231,7 @@
|
||||
icon_state = "candycanecustom"
|
||||
baseicon = "candycanecustom"
|
||||
basename = "flavored candy cane"
|
||||
add_overlays = 0
|
||||
snack_overlays = 0
|
||||
top = 0
|
||||
|
||||
/obj/item/reagent_containers/food/snacks/customizable/candy/gum
|
||||
@@ -240,7 +240,7 @@
|
||||
icon_state = "gumcustom"
|
||||
baseicon = "gumcustom"
|
||||
basename = "flavored gum"
|
||||
add_overlays = 0
|
||||
snack_overlays = 0
|
||||
top = 0
|
||||
|
||||
/obj/item/reagent_containers/food/snacks/customizable/candy/donut
|
||||
@@ -249,7 +249,7 @@
|
||||
icon_state = "donutcustom"
|
||||
baseicon = "donutcustom"
|
||||
basename = "filled donut"
|
||||
add_overlays = 0
|
||||
snack_overlays = 0
|
||||
top = 0
|
||||
|
||||
/obj/item/reagent_containers/food/snacks/customizable/candy/bar
|
||||
@@ -258,7 +258,7 @@
|
||||
icon_state = "barcustom"
|
||||
baseicon = "barcustom"
|
||||
basename = "flavored chocolate bar"
|
||||
add_overlays = 0
|
||||
snack_overlays = 0
|
||||
top = 0
|
||||
|
||||
/obj/item/reagent_containers/food/snacks/customizable/candy/sucker
|
||||
@@ -267,7 +267,7 @@
|
||||
icon_state = "suckercustom"
|
||||
baseicon = "suckercustom"
|
||||
basename = "flavored sucker"
|
||||
add_overlays = 0
|
||||
snack_overlays = 0
|
||||
top = 0
|
||||
|
||||
/obj/item/reagent_containers/food/snacks/customizable/candy/cash
|
||||
@@ -276,7 +276,7 @@
|
||||
icon_state = "cashcustom"
|
||||
baseicon = "cashcustom"
|
||||
basename = "flavored cash"
|
||||
add_overlays = 0
|
||||
snack_overlays = 0
|
||||
top = 0
|
||||
|
||||
/obj/item/reagent_containers/food/snacks/customizable/candy/coin
|
||||
@@ -285,7 +285,7 @@
|
||||
icon_state = "coincustom"
|
||||
baseicon = "coincustom"
|
||||
basename = "flavored coin"
|
||||
add_overlays = 0
|
||||
snack_overlays = 0
|
||||
top = 0
|
||||
|
||||
/obj/item/reagent_containers/food/snacks/customizable/fullycustom // In the event you fuckers find something I forgot to add a customizable food for.
|
||||
@@ -294,7 +294,7 @@
|
||||
icon_state = "fullycustom"
|
||||
baseicon = "fullycustom"
|
||||
basename = "on a plate"
|
||||
add_overlays = 0
|
||||
snack_overlays = 0
|
||||
top = 0
|
||||
sandwich_limit = 20
|
||||
fullycustom = 1
|
||||
@@ -305,7 +305,7 @@
|
||||
icon_state = "soup"
|
||||
baseicon = "soup"
|
||||
basename = "soup"
|
||||
add_overlays = 0
|
||||
snack_overlays = 0
|
||||
trash = /obj/item/trash/bowl
|
||||
top = 0
|
||||
|
||||
@@ -355,7 +355,7 @@
|
||||
I.color = pick("#FF0000","#0000FF","#008000","#FFFF00")
|
||||
else
|
||||
I.color = pick("#FF0000","#0000FF","#008000","#FFFF00")
|
||||
if(add_overlays)
|
||||
if(snack_overlays)
|
||||
I.pixel_x = pick(list(-1,0,1))
|
||||
I.pixel_y = (i*2)+1
|
||||
overlays += I
|
||||
|
||||
@@ -210,6 +210,7 @@
|
||||
#include "code\controllers\subsystem\nightshift.dm"
|
||||
#include "code\controllers\subsystem\npcai.dm"
|
||||
#include "code\controllers\subsystem\npcpool.dm"
|
||||
#include "code\controllers\subsystem\overlays.dm"
|
||||
#include "code\controllers\subsystem\shuttles.dm"
|
||||
#include "code\controllers\subsystem\spacedrift.dm"
|
||||
#include "code\controllers\subsystem\sun.dm"
|
||||
|
||||
Reference in New Issue
Block a user