Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[MIRROR] RPG Loot: Revisited & READY #2886

Merged
merged 1 commit into from
Apr 15, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions code/__DEFINES/subsystems.dm
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,7 @@
#define INIT_ORDER_PATH -50
#define INIT_ORDER_DECAY -61 //NOVA EDIT ADDITION
#define INIT_ORDER_EXPLOSIONS -69
#define INIT_ORDER_LOOT -70
#define INIT_ORDER_STATPANELS -97
#define INIT_ORDER_BAN_CACHE -98
#define INIT_ORDER_INIT_PROFILER -99 //Near the end, logs the costs of initialize
Expand Down
3 changes: 3 additions & 0 deletions code/__DEFINES/traits/declarations.dm
Original file line number Diff line number Diff line change
Expand Up @@ -1114,4 +1114,7 @@ Remember to update _globalvars/traits.dm if you're adding/removing/renaming trai
/// Trait applied to objects and mobs that can attack a boulder and break it down. (See /obj/item/boulder/manual_process())
#define TRAIT_BOULDER_BREAKER "boulder_breaker"

/// Prevents the affected object from opening a loot window via alt click. See atom/AltClick()
#define TRAIT_ALT_CLICK_BLOCKER "no_alt_click"

// END TRAIT DEFINES
1 change: 1 addition & 0 deletions code/_globalvars/traits/_traits.dm
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
GLOBAL_LIST_INIT(traits_by_type, list(
/atom = list(
"TRAIT_AI_PAUSED" = TRAIT_AI_PAUSED,
"TRAIT_ALT_CLICK_BLOCKER" = TRAIT_ALT_CLICK_BLOCKER,
"TRAIT_BANNED_FROM_CARGO_SHUTTLE" = TRAIT_BANNED_FROM_CARGO_SHUTTLE,
"TRAIT_BEING_SHOCKED" = TRAIT_BEING_SHOCKED,
"TRAIT_COMMISSIONED" = TRAIT_COMMISSIONED,
Expand Down
44 changes: 32 additions & 12 deletions code/_onclick/click.dm
Original file line number Diff line number Diff line change
Expand Up @@ -395,14 +395,40 @@
return
A.AltClick(src)

/**
* Alt click on an atom.
* Performs alt-click actions before attempting to open a loot window.
* Returns TRUE if successful, FALSE if not.
*/
/atom/proc/AltClick(mob/user)
if(!user.can_interact_with(src))
return FALSE

if(SEND_SIGNAL(src, COMSIG_CLICK_ALT, user) & COMPONENT_CANCEL_CLICK_ALT)
return
var/turf/T = get_turf(src)
if(T && (isturf(loc) || isturf(src)) && user.TurfAdjacent(T) && !HAS_TRAIT(user, TRAIT_MOVE_VENTCRAWLING))
user.set_listed_turf(T)
return TRUE

if(HAS_TRAIT(src, TRAIT_ALT_CLICK_BLOCKER) && !isobserver(user))
return TRUE

var/turf/tile = get_turf(src)
if(isnull(tile))
return FALSE

if(!isturf(loc) && !isturf(src))
return FALSE

if(!user.TurfAdjacent(tile))
return FALSE

if(HAS_TRAIT(user, TRAIT_MOVE_VENTCRAWLING))
return FALSE

var/datum/lootpanel/panel = user.client?.loot_panel
if(isnull(panel))
return FALSE

panel.open(tile)
return TRUE

///The base proc of when something is right clicked on when alt is held - generally use alt_click_secondary instead
/atom/proc/alt_click_on_secondary(atom/A)
Expand All @@ -421,14 +447,8 @@
user.client.toggle_tag_datum(src)
return

/// Use this instead of [/mob/proc/AltClickOn] where you only want turf content listing without additional atom alt-click interaction
/atom/proc/AltClickNoInteract(mob/user, atom/A)
var/turf/T = get_turf(A)
if(T && user.TurfAdjacent(T))
user.set_listed_turf(T)

/mob/proc/TurfAdjacent(turf/T)
return T.Adjacent(src)
/mob/proc/TurfAdjacent(turf/tile)
return tile.Adjacent(src)

/**
* Control+Shift click
Expand Down
2 changes: 1 addition & 1 deletion code/_onclick/observer.dm
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@
MiddleClickOn(A, params)
return
if(LAZYACCESS(modifiers, ALT_CLICK))
AltClickNoInteract(src, A)
A.AltClick(src)
return
if(LAZYACCESS(modifiers, CTRL_CLICK))
CtrlClickOn(A)
Expand Down
24 changes: 0 additions & 24 deletions code/controllers/subsystem/processing/obj_tab_items.dm

This file was deleted.

183 changes: 0 additions & 183 deletions code/controllers/subsystem/statpanel.dm
Original file line number Diff line number Diff line change
Expand Up @@ -107,12 +107,6 @@ SUBSYSTEM_DEF(statpanels)
if(update_actions && num_fires % default_wait == 0)
set_action_tabs(target, target_mob)

// Handle the examined turf of the stat panel, if it's been long enough, or if we've generated new images for it
var/turf/listed_turf = target_mob?.listed_turf
if(listed_turf && num_fires % default_wait == 0)
if(target.stat_tab == listed_turf.name || !(listed_turf.name in target.panel_tabs))
set_turf_examine_tab(target, target_mob)

if(MC_TICK_CHECK)
return

Expand Down Expand Up @@ -185,71 +179,6 @@ SUBSYSTEM_DEF(statpanels)

target.stat_panel.send_message("update_spells", list(spell_tabs = target.spell_tabs, actions = actions))

/datum/controller/subsystem/statpanels/proc/set_turf_examine_tab(client/target, mob/target_mob)
var/list/overrides = list()
for(var/image/target_image as anything in target.images)
if(!target_image.loc || target_image.loc.loc != target_mob.listed_turf || !target_image.override)
continue
overrides += target_image.loc

var/list/atoms_to_display = list(target_mob.listed_turf)
for(var/atom/movable/turf_content as anything in target_mob.listed_turf)
if(turf_content.mouse_opacity == MOUSE_OPACITY_TRANSPARENT)
continue
if(turf_content.invisibility > target_mob.see_invisible)
continue
if(turf_content in overrides)
continue
if(turf_content.IsObscured())
continue
atoms_to_display += turf_content

/// Set the atoms we're meant to display
var/datum/object_window_info/obj_window = target.obj_window
obj_window.atoms_to_show = atoms_to_display
START_PROCESSING(SSobj_tab_items, obj_window)
refresh_client_obj_view(target)

/datum/controller/subsystem/statpanels/proc/refresh_client_obj_view(client/refresh)
var/list/turf_items = return_object_images(refresh)
if(!length(turf_items) || !refresh.mob?.listed_turf)
return
refresh.stat_panel.send_message("update_listedturf", turf_items)

#define OBJ_IMAGE_LOADING "statpanels obj loading temporary"
/// Returns all our ready object tab images
/// Returns a list in the form list(list(object_name, object_ref, loaded_image), ...)
/datum/controller/subsystem/statpanels/proc/return_object_images(client/load_from)
// You might be inclined to think that this is a waste of cpu time, since we
// A: Double iterate over atoms in the build case, or
// B: Generate these lists over and over in the refresh case
// It's really not very hot. The hot portion of this code is genuinely mostly in the image generation
// So it's ok to pay a performance cost for cleanliness here

// No turf? go away
if(!load_from.mob?.listed_turf)
return list()
var/datum/object_window_info/obj_window = load_from.obj_window
var/list/already_seen = obj_window.atoms_to_images
var/list/to_make = obj_window.atoms_to_imagify
var/list/turf_items = list()
for(var/atom/turf_item as anything in obj_window.atoms_to_show)
// First, we fill up the list of refs to display
// If we already have one, just use that
var/existing_image = already_seen[turf_item]
if(existing_image == OBJ_IMAGE_LOADING)
continue
// We already have it. Success!
if(existing_image)
turf_items[++turf_items.len] = list("[turf_item.name]", REF(turf_item), existing_image)
continue
// Now, we're gonna queue image generation out of those refs
to_make += turf_item
already_seen[turf_item] = OBJ_IMAGE_LOADING
obj_window.RegisterSignal(turf_item, COMSIG_QDELETING, TYPE_PROC_REF(/datum/object_window_info,viewing_atom_deleted)) // we reset cache if anything in it gets deleted
return turf_items

#undef OBJ_IMAGE_LOADING

/datum/controller/subsystem/statpanels/proc/generate_mc_data()
mc_data = list(
Expand Down Expand Up @@ -291,16 +220,6 @@ SUBSYSTEM_DEF(statpanels)
set_action_tabs(target, target_mob)
return TRUE

// Handle turfs

if(target_mob?.listed_turf)
if(!target_mob.TurfAdjacent(target_mob.listed_turf))
target_mob.set_listed_turf(null)

else if(target.stat_tab == target_mob?.listed_turf.name || !(target_mob?.listed_turf.name in target.panel_tabs))
set_turf_examine_tab(target, target_mob)
return TRUE

if(!target.holder)
return FALSE

Expand All @@ -320,105 +239,3 @@ SUBSYSTEM_DEF(statpanels)

/// Stat panel window declaration
/client/var/datum/tgui_window/stat_panel

/// Datum that holds and tracks info about a client's object window
/// Really only exists because I want to be able to do logic with signals
/// And need a safe place to do the registration
/datum/object_window_info
/// list of atoms to show to our client via the object tab, at least currently
var/list/atoms_to_show = list()
/// list of atom -> image string for objects we have had in the right click tab
/// this is our caching
var/list/atoms_to_images = list()
/// list of atoms to turn into images for the object tab
var/list/atoms_to_imagify = list()
/// Our owner client
var/client/parent
/// Are we currently tracking a turf?
var/actively_tracking = FALSE

/datum/object_window_info/New(client/parent)
. = ..()
src.parent = parent

/datum/object_window_info/Destroy(force)
atoms_to_show = null
atoms_to_images = null
atoms_to_imagify = null
parent.obj_window = null
parent = null
STOP_PROCESSING(SSobj_tab_items, src)
return ..()

/// Takes a client, attempts to generate object images for it
/// We will update the client with any improvements we make when we're done
/datum/object_window_info/process(seconds_per_tick)
// Cache the datum access for sonic speed
var/list/to_make = atoms_to_imagify
var/list/newly_seen = atoms_to_images
var/index = 0
for(index in 1 to length(to_make))
var/atom/thing = to_make[index]

var/generated_string
if(ismob(thing) || length(thing.overlays) > 2)
generated_string = costly_icon2html(thing, parent, sourceonly=TRUE)
else
generated_string = icon2html(thing, parent, sourceonly=TRUE)

newly_seen[thing] = generated_string
if(TICK_CHECK)
to_make.Cut(1, index + 1)
index = 0
break
// If we've not cut yet, do it now
if(index)
to_make.Cut(1, index + 1)
SSstatpanels.refresh_client_obj_view(parent)
if(!length(to_make))
return PROCESS_KILL

/datum/object_window_info/proc/start_turf_tracking()
if(actively_tracking)
stop_turf_tracking()
var/static/list/connections = list(
COMSIG_MOVABLE_MOVED = PROC_REF(on_mob_move),
COMSIG_MOB_LOGOUT = PROC_REF(on_mob_logout),
)
AddComponent(/datum/component/connect_mob_behalf, parent, connections)
actively_tracking = TRUE

/datum/object_window_info/proc/stop_turf_tracking()
qdel(GetComponent(/datum/component/connect_mob_behalf))
actively_tracking = FALSE

/datum/object_window_info/proc/on_mob_move(mob/source)
SIGNAL_HANDLER
var/turf/listed = source.listed_turf
if(!listed || !source.TurfAdjacent(listed))
source.set_listed_turf(null)

/datum/object_window_info/proc/on_mob_logout(mob/source)
SIGNAL_HANDLER
on_mob_move(parent.mob)

/// Clears any cached object window stuff
/// We use hard refs cause we'd need a signal for this anyway. Cleaner this way
/datum/object_window_info/proc/viewing_atom_deleted(atom/deleted)
SIGNAL_HANDLER
atoms_to_show -= deleted
atoms_to_imagify -= deleted
atoms_to_images -= deleted

/mob/proc/set_listed_turf(turf/new_turf)
listed_turf = new_turf
if(!client)
return
if(!client.obj_window)
client.obj_window = new(client)
if(listed_turf)
client.stat_panel.send_message("create_listedturf", listed_turf.name)
client.obj_window.start_turf_tracking()
else
client.stat_panel.send_message("remove_listedturf")
client.obj_window.stop_turf_tracking()
1 change: 1 addition & 0 deletions code/datums/components/gps.dm
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@ GLOBAL_LIST_EMPTY(GPS_list)
SIGNAL_HANDLER

toggletracking(user)
return COMPONENT_CANCEL_CLICK_ALT

///Toggles the tracking for the gps
/datum/component/gps/item/proc/toggletracking(mob/user)
Expand Down
4 changes: 4 additions & 0 deletions code/datums/components/rotation.dm
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@
RegisterSignal(parent, COMSIG_CLICK_ALT_SECONDARY, PROC_REF(rotate_right))
RegisterSignal(parent, COMSIG_ATOM_EXAMINE, PROC_REF(ExamineMessage))
RegisterSignal(parent, COMSIG_ATOM_REQUESTING_CONTEXT_FROM_ITEM, PROC_REF(on_requesting_context_from_item))

ADD_TRAIT(parent, TRAIT_ALT_CLICK_BLOCKER, REF(src))
return ..()

/datum/component/simple_rotation/PostTransfer()
Expand All @@ -41,6 +43,8 @@
COMSIG_ATOM_EXAMINE,
COMSIG_ATOM_REQUESTING_CONTEXT_FROM_ITEM,
))

REMOVE_TRAIT(parent, TRAIT_ALT_CLICK_BLOCKER, REF(src))
return ..()

/datum/component/simple_rotation/Destroy()
Expand Down
1 change: 1 addition & 0 deletions code/game/objects/items/grenades/_grenade.dm
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@
/obj/item/grenade/Initialize(mapload)
. = ..()
ADD_TRAIT(src, TRAIT_ODD_CUSTOMIZABLE_FOOD_INGREDIENT, type)
ADD_TRAIT(src, TRAIT_ALT_CLICK_BLOCKER, REF(src))
RegisterSignal(src, COMSIG_ITEM_USED_AS_INGREDIENT, PROC_REF(on_used_as_ingredient))

/obj/item/grenade/suicide_act(mob/living/carbon/user)
Expand Down
28 changes: 28 additions & 0 deletions code/modules/asset_cache/assets/icon_ref_map.dm
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
/// Maps icon names to ref values
/datum/asset/json/icon_ref_map
name = "icon_ref_map"
early = TRUE

/datum/asset/json/icon_ref_map/generate()
var/list/data = list() //"icons/obj/drinks.dmi" => "[0xc000020]"

//var/start = "0xc000000"
var/value = 0

while(TRUE)
value += 1
var/ref = "\[0xc[num2text(value,6,16)]\]"
var/mystery_meat = locate(ref)

if(isicon(mystery_meat))
if(!isfile(mystery_meat)) // Ignore the runtime icons for now
continue
var/path = get_icon_dmi_path(mystery_meat) //Try to get the icon path
if(path)
data[path] = ref
else if(mystery_meat)
continue; //Some other non-icon resource, ogg/json/whatever
else //Out of resources end this, could also try to end this earlier as soon as runtime generated icons appear but eh
break;

return data
Loading
Loading