mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2025-12-10 09:42:29 +00:00
[MIRROR] Progress bars & cleaning particles will centre on the tile occupied by large icon objects [MDB IGNORE] (#23394)
* Progress bars & cleaning particles will centre on the tile occupied by large icon objects (#77940) ## About The Pull Request Do_after bars always draw based on the top-left corner of the targetted atom, for atoms with sprites that are larger than 32x32 this gives them a weird offset instead of being centred, which bugs me. I have tried my best to figure out a way to reverse this which does not interfere with atoms which use pixel_x/pixel_y to visually appear to be on a different tile. ## Why It's Good For The Game Before:  he hates how you missed him completely 😦 After:  now you're cleaning his feet 🙂 ## Changelog 🆑 image: progress bars and cleaning particles are now centered on the tile occupied by the target, if it is a big sprite /🆑 * Progress bars & cleaning particles will centre on the tile occupied by large icon objects --------- Co-authored-by: Jacquerel <hnevard@gmail.com>
This commit is contained in:
@@ -323,3 +323,15 @@ rough example of the "cone" made by the 3 dirs checked
|
||||
if(!storage_datum)
|
||||
return
|
||||
. += storage_datum.real_location?.resolve()
|
||||
|
||||
/// Returns an x and y value require to reverse the transformations made to center an oversized icon
|
||||
/atom/proc/get_oversized_icon_offsets()
|
||||
if (pixel_x == 0 && pixel_y == 0)
|
||||
return list("x" = 0, "y" = 0)
|
||||
var/list/icon_dimensions = get_icon_dimensions(icon)
|
||||
var/icon_width = icon_dimensions["width"]
|
||||
var/icon_height = icon_dimensions["height"]
|
||||
return list(
|
||||
"x" = icon_width > world.icon_size && pixel_x != 0 ? (icon_width - world.icon_size) * 0.5 : 0,
|
||||
"y" = icon_height > world.icon_size && pixel_y != 0 ? (icon_height - world.icon_size) * 0.5 : 0,
|
||||
)
|
||||
|
||||
@@ -1461,3 +1461,10 @@ GLOBAL_LIST_EMPTY(transformation_animation_objects)
|
||||
else
|
||||
bound_width = world.icon_size
|
||||
bound_height = size * world.icon_size
|
||||
|
||||
/// Returns a list containing the width and height of an icon file
|
||||
/proc/get_icon_dimensions(icon_path)
|
||||
if (isnull(GLOB.icon_dimensions[icon_path]))
|
||||
var/icon/my_icon = icon(icon_path)
|
||||
GLOB.icon_dimensions[icon_path] = list("width" = my_icon.Width(), "height" = my_icon.Height())
|
||||
return GLOB.icon_dimensions[icon_path]
|
||||
|
||||
@@ -216,7 +216,7 @@ Turf and target are separate in case you want to teleport some distance from a t
|
||||
|
||||
var/list/offsets = get_visual_offset(checked_atom)
|
||||
return pixel_offset_turf(atom_turf, offsets)
|
||||
|
||||
|
||||
/**
|
||||
* Returns how visually "off" the atom is from its source turf as a list of x, y (in pixel steps)
|
||||
* it takes into account:
|
||||
@@ -232,9 +232,9 @@ Turf and target are separate in case you want to teleport some distance from a t
|
||||
var/pixel_y_offset = checked_atom.pixel_y + atom_matrix.get_y_shift()
|
||||
|
||||
//Irregular objects
|
||||
var/icon/checked_atom_icon = icon(checked_atom.icon, checked_atom.icon_state)
|
||||
var/checked_atom_icon_height = checked_atom_icon.Height()
|
||||
var/checked_atom_icon_width = checked_atom_icon.Width()
|
||||
var/list/icon_dimensions = get_icon_dimensions(checked_atom.icon)
|
||||
var/checked_atom_icon_height = icon_dimensions["width"]
|
||||
var/checked_atom_icon_width = icon_dimensions["height"]
|
||||
if(checked_atom_icon_height != world.icon_size || checked_atom_icon_width != world.icon_size)
|
||||
pixel_x_offset += ((checked_atom_icon_width / world.icon_size) - 1) * (world.icon_size * 0.5)
|
||||
pixel_y_offset += ((checked_atom_icon_height / world.icon_size) - 1) * (world.icon_size * 0.5)
|
||||
|
||||
2
code/_globalvars/lists/icons.dm
Normal file
2
code/_globalvars/lists/icons.dm
Normal file
@@ -0,0 +1,2 @@
|
||||
/// Cache of the width and height of icon files, to avoid repeating the same expensive operation
|
||||
GLOBAL_LIST_EMPTY(icon_dimensions)
|
||||
@@ -98,6 +98,11 @@
|
||||
RegisterSignal(target, COMSIG_MOVABLE_Z_CHANGED, PROC_REF(cleaning_target_moved))
|
||||
var/mutable_appearance/low_bubble = mutable_appearance('icons/effects/effects.dmi', "bubbles", FLOOR_CLEAN_LAYER, target, GAME_PLANE)
|
||||
var/mutable_appearance/high_bubble = mutable_appearance('icons/effects/effects.dmi', "bubbles", FLOOR_CLEAN_LAYER, target, ABOVE_GAME_PLANE)
|
||||
var/list/icon_offsets = target.get_oversized_icon_offsets()
|
||||
low_bubble.pixel_x = icon_offsets["x"]
|
||||
low_bubble.pixel_y = icon_offsets["y"]
|
||||
high_bubble.pixel_x = icon_offsets["x"]
|
||||
high_bubble.pixel_y = icon_offsets["y"]
|
||||
if(target.plane > low_bubble.plane) //check if the higher overlay is necessary
|
||||
target.add_overlay(high_bubble)
|
||||
else if(target.plane == low_bubble.plane)
|
||||
|
||||
@@ -139,9 +139,9 @@
|
||||
* without otherwise affecting other movables with identical overlays.
|
||||
*/
|
||||
/datum/element/immerse/proc/add_immerse_overlay(atom/movable/movable)
|
||||
var/icon/movable_icon = icon(movable.icon)
|
||||
var/width = movable_icon.Width() || world.icon_size
|
||||
var/height = movable_icon.Height() || world.icon_size
|
||||
var/list/icon_dimensions = get_icon_dimensions(movable.icon)
|
||||
var/width = icon_dimensions["width"] || world.icon_size
|
||||
var/height = icon_dimensions["height"] || world.icon_size
|
||||
|
||||
var/is_below_water = movable.layer < WATER_LEVEL_LAYER ? "underwater-" : ""
|
||||
|
||||
|
||||
@@ -193,9 +193,9 @@
|
||||
|
||||
/// Reads layer configurations to take out some useful overall information
|
||||
/datum/greyscale_config/proc/ReadMetadata()
|
||||
var/icon/source = icon(icon_file)
|
||||
height = source.Height()
|
||||
width = source.Width()
|
||||
var/list/icon_dimensions = get_icon_dimensions(icon_file)
|
||||
height = icon_dimensions["width"]
|
||||
width = icon_dimensions["height"]
|
||||
|
||||
var/list/datum/greyscale_layer/all_layers = list()
|
||||
for(var/state in icon_states)
|
||||
|
||||
@@ -18,6 +18,8 @@
|
||||
var/listindex = 0
|
||||
///The type of our last value for bar_loc, for debugging
|
||||
var/location_type
|
||||
///Where to draw the progress bar above the icon
|
||||
var/offset_y
|
||||
|
||||
/datum/progressbar/New(mob/User, goal_number, atom/target)
|
||||
. = ..()
|
||||
@@ -36,7 +38,12 @@
|
||||
goal = goal_number
|
||||
bar_loc = target
|
||||
location_type = bar_loc.type
|
||||
bar = image('icons/effects/progressbar.dmi', bar_loc, "prog_bar_0")
|
||||
|
||||
var/list/icon_offsets = target.get_oversized_icon_offsets()
|
||||
var/offset_x = icon_offsets["x"]
|
||||
offset_y = icon_offsets["y"]
|
||||
|
||||
bar = image('icons/effects/progressbar.dmi', bar_loc, "prog_bar_0", pixel_x = offset_x)
|
||||
SET_PLANE_EXPLICIT(bar, ABOVE_HUD_PLANE, User)
|
||||
bar.appearance_flags = APPEARANCE_UI_IGNORE_ALPHA
|
||||
user = User
|
||||
@@ -62,8 +69,8 @@
|
||||
continue
|
||||
progress_bar.listindex--
|
||||
|
||||
progress_bar.bar.pixel_y = 32 + (PROGRESSBAR_HEIGHT * (progress_bar.listindex - 1))
|
||||
var/dist_to_travel = 32 + (PROGRESSBAR_HEIGHT * (progress_bar.listindex - 1)) - PROGRESSBAR_HEIGHT
|
||||
progress_bar.bar.pixel_y = world.icon_size + offset_y + (PROGRESSBAR_HEIGHT * (progress_bar.listindex - 1))
|
||||
var/dist_to_travel = world.icon_size + offset_y + (PROGRESSBAR_HEIGHT * (progress_bar.listindex - 1)) - PROGRESSBAR_HEIGHT
|
||||
animate(progress_bar.bar, pixel_y = dist_to_travel, time = PROGRESSBAR_ANIMATION_TIME, easing = SINE_EASING)
|
||||
|
||||
LAZYREMOVEASSOC(user.progressbars, bar_loc, src)
|
||||
@@ -118,7 +125,7 @@
|
||||
bar.pixel_y = 0
|
||||
bar.alpha = 0
|
||||
user_client.images += bar
|
||||
animate(bar, pixel_y = 32 + (PROGRESSBAR_HEIGHT * (listindex - 1)), alpha = 255, time = PROGRESSBAR_ANIMATION_TIME, easing = SINE_EASING)
|
||||
animate(bar, pixel_y = world.icon_size + offset_y + (PROGRESSBAR_HEIGHT * (listindex - 1)), alpha = 255, time = PROGRESSBAR_ANIMATION_TIME, easing = SINE_EASING)
|
||||
|
||||
|
||||
///Updates the progress bar image visually.
|
||||
|
||||
@@ -23,9 +23,10 @@
|
||||
/mob/living/simple_animal/revenant/ranged_secondary_attack(atom/target, modifiers)
|
||||
if(revealed || notransform || inhibited || !Adjacent(target) || !incorporeal_move_check(target))
|
||||
return
|
||||
var/icon/I = icon(target.icon,target.icon_state,target.dir)
|
||||
var/orbitsize = (I.Width()+I.Height())*0.5
|
||||
orbitsize -= (orbitsize/world.icon_size)*(world.icon_size*0.25)
|
||||
|
||||
var/list/icon_dimensions = get_icon_dimensions(target.icon)
|
||||
var/orbitsize = (icon_dimensions["width"] + icon_dimensions["height"]) * 0.5
|
||||
orbitsize -= (orbitsize / world.icon_size) * (world.icon_size * 0.25)
|
||||
orbit(target, orbitsize)
|
||||
|
||||
//Harvest; activated by clicking the target, will try to drain their essence.
|
||||
|
||||
@@ -478,8 +478,8 @@ Moving interrupts
|
||||
user.balloon_alert(user, "no sculpt target!")
|
||||
return FALSE
|
||||
//No big icon things
|
||||
var/icon/thing_icon = icon(target.icon, target.icon_state)
|
||||
if(thing_icon.Height() != world.icon_size || thing_icon.Width() != world.icon_size)
|
||||
var/list/icon_dimensions = get_icon_dimensions(target.icon)
|
||||
if(icon_dimensions["width"] != world.icon_size || icon_dimensions["height"] != world.icon_size)
|
||||
user.balloon_alert(user, "sculpt target is too big!")
|
||||
return FALSE
|
||||
return TRUE
|
||||
|
||||
@@ -136,10 +136,10 @@
|
||||
|
||||
// Scale the preview if it's bigger than one tile
|
||||
var/mutable_appearance/preview_overlay = new(typepath)
|
||||
var/icon/size_check = icon(initial(typepath.icon), icon_state = initial(typepath.icon_state))
|
||||
var/list/icon_dimensions = get_icon_dimensions(initial(typepath.icon))
|
||||
var/width = icon_dimensions["width"]
|
||||
var/height = icon_dimensions["height"]
|
||||
var/scale = 1
|
||||
var/width = size_check.Width()
|
||||
var/height = size_check.Height()
|
||||
if(width > world.icon_size || height > world.icon_size)
|
||||
if(width >= height)
|
||||
scale = world.icon_size / width
|
||||
|
||||
@@ -148,11 +148,10 @@
|
||||
for (var/atom/movable/ingredient as anything in ingredients)
|
||||
var/image/ingredient_overlay = image(ingredient, src)
|
||||
|
||||
var/icon/ingredient_icon = icon(ingredient.icon, ingredient.icon_state)
|
||||
|
||||
var/list/icon_dimensions = get_icon_dimensions(ingredient.icon)
|
||||
ingredient_overlay.transform = ingredient_overlay.transform.Scale(
|
||||
MICROWAVE_INGREDIENT_OVERLAY_SIZE / ingredient_icon.Width(),
|
||||
MICROWAVE_INGREDIENT_OVERLAY_SIZE / ingredient_icon.Height(),
|
||||
MICROWAVE_INGREDIENT_OVERLAY_SIZE / icon_dimensions["width"],
|
||||
MICROWAVE_INGREDIENT_OVERLAY_SIZE / icon_dimensions["height"],
|
||||
)
|
||||
|
||||
ingredient_overlay.pixel_y = -4
|
||||
|
||||
@@ -502,9 +502,8 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
|
||||
if (!istype(target) || (is_secret_level(target.z) && !client?.holder))
|
||||
return
|
||||
|
||||
var/icon/I = icon(target.icon,target.icon_state,target.dir)
|
||||
|
||||
var/orbitsize = (I.Width()+I.Height())*0.5
|
||||
var/list/icon_dimensions = get_icon_dimensions(target.icon)
|
||||
var/orbitsize = (icon_dimensions["width"] + icon_dimensions["height"]) * 0.5
|
||||
orbitsize -= (orbitsize/world.icon_size)*(world.icon_size*0.25)
|
||||
|
||||
var/rot_seg
|
||||
|
||||
@@ -354,8 +354,8 @@ Difficulty: Extremely Hard
|
||||
if(!owner.stat)
|
||||
to_chat(owner, span_userdanger("You become frozen in a cube!"))
|
||||
cube = icon('icons/effects/freeze.dmi', "ice_cube")
|
||||
var/icon/size_check = icon(owner.icon, owner.icon_state)
|
||||
cube.Scale(size_check.Width(), size_check.Height())
|
||||
var/list/icon_dimensions = get_icon_dimensions(owner.icon)
|
||||
cube.Scale(icon_dimensions["width"], icon_dimensions["height"])
|
||||
owner.add_overlay(cube)
|
||||
return ..()
|
||||
|
||||
|
||||
@@ -146,11 +146,10 @@
|
||||
)
|
||||
|
||||
miniball.transform *= pick(0.3, 0.4, 0.5, 0.6, 0.7)
|
||||
var/icon/I = icon(icon, icon_state,dir)
|
||||
var/list/icon_dimensions = get_icon_dimensions(icon)
|
||||
|
||||
var/orbitsize = (I.Width() + I.Height()) * pick(0.4, 0.5, 0.6, 0.7, 0.8)
|
||||
var/orbitsize = (icon_dimensions["width"] + icon_dimensions["height"]) * pick(0.4, 0.5, 0.6, 0.7, 0.8)
|
||||
orbitsize -= (orbitsize / world.icon_size) * (world.icon_size * 0.25)
|
||||
|
||||
miniball.orbit(src, orbitsize, pick(FALSE, TRUE), rand(10, 25), pick(3, 4, 5, 6, 36))
|
||||
|
||||
/obj/energy_ball/Bump(atom/A)
|
||||
|
||||
@@ -574,6 +574,7 @@
|
||||
#include "code\_globalvars\lists\client.dm"
|
||||
#include "code\_globalvars\lists\color.dm"
|
||||
#include "code\_globalvars\lists\flavor_misc.dm"
|
||||
#include "code\_globalvars\lists\icons.dm"
|
||||
#include "code\_globalvars\lists\keybindings.dm"
|
||||
#include "code\_globalvars\lists\maintenance_loot.dm"
|
||||
#include "code\_globalvars\lists\mapping.dm"
|
||||
|
||||
Reference in New Issue
Block a user