diff --git a/code/game/atoms_movable.dm b/code/game/atoms_movable.dm index 1b4455d5a3a..f0f06c0f570 100644 --- a/code/game/atoms_movable.dm +++ b/code/game/atoms_movable.dm @@ -1181,44 +1181,6 @@ animate(src, pixel_x = pixel_x + pixel_x_diff, pixel_y = pixel_y + pixel_y_diff, transform=rotated_transform, time = 1, easing=BACK_EASING|EASE_IN, flags = ANIMATION_PARALLEL) animate(pixel_x = pixel_x - pixel_x_diff, pixel_y = pixel_y - pixel_y_diff, transform=initial_transform, time = 2, easing=SINE_EASING, flags = ANIMATION_PARALLEL) -/atom/movable/proc/do_item_attack_animation(atom/attacked_atom, visual_effect_icon, obj/item/used_item) - var/image/attack_image - if(visual_effect_icon) - attack_image = image('icons/effects/effects.dmi', attacked_atom, visual_effect_icon, attacked_atom.layer + 0.1) - else if(used_item) - attack_image = image(icon = used_item, loc = attacked_atom, layer = attacked_atom.layer + 0.1) - attack_image.plane = GAME_PLANE - - // Scale the icon. - attack_image.transform *= 0.4 - // The icon should not rotate. - attack_image.appearance_flags = APPEARANCE_UI - - // Set the direction of the icon animation. - var/direction = get_dir(src, attacked_atom) - if(direction & NORTH) - attack_image.pixel_y = -12 - else if(direction & SOUTH) - attack_image.pixel_y = 12 - - if(direction & EAST) - attack_image.pixel_x = -14 - else if(direction & WEST) - attack_image.pixel_x = 14 - - if(!direction) // Attacked self?! - attack_image.pixel_z = 16 - - if(!attack_image) - return - - flick_overlay(attack_image, GLOB.clients, 10) - - // And animate the attack! - animate(attack_image, alpha = 175, transform = matrix() * 0.75, pixel_x = 0, pixel_y = 0, pixel_z = 0, time = 3) - animate(time = 1) - animate(alpha = 0, time = 3, easing = CIRCULAR_EASING|EASE_OUT) - /atom/movable/vv_get_dropdown() . = ..() . += "" @@ -1392,37 +1354,6 @@ log_admin("[key_name(usr)] has added deadchat control to [src]") message_admins(span_notice("[key_name(usr)] has added deadchat control to [src]")) -/obj/item/proc/do_pickup_animation(atom/target) - set waitfor = FALSE - if(!istype(loc, /turf)) - return - var/image/pickup_animation = image(icon = src, loc = loc, layer = layer + 0.1) - pickup_animation.plane = GAME_PLANE - pickup_animation.transform *= 0.75 - pickup_animation.appearance_flags = APPEARANCE_UI_IGNORE_ALPHA - var/turf/current_turf = get_turf(src) - var/direction - var/to_x = target.base_pixel_x - var/to_y = target.base_pixel_y - - if(!QDELETED(current_turf) && !QDELETED(target)) - direction = get_dir(current_turf, target) - if(direction & NORTH) - to_y += 32 - else if(direction & SOUTH) - to_y -= 32 - if(direction & EAST) - to_x += 32 - else if(direction & WEST) - to_x -= 32 - if(!direction) - to_y += 16 - flick_overlay(pickup_animation, GLOB.clients, 6) - var/matrix/animation_matrix = new - animation_matrix.Turn(pick(-30, 30)) - animate(pickup_animation, alpha = 175, pixel_x = to_x, pixel_y = to_y, time = 3, transform = animation_matrix, easing = CUBIC_EASING) - sleep(1) - animate(pickup_animation, alpha = 0, transform = matrix(), time = 1) /** * A wrapper for setDir that should only be able to fail by living mobs. diff --git a/code/game/objects/items.dm b/code/game/objects/items.dm index a101cd7b0b7..ad705212496 100644 --- a/code/game/objects/items.dm +++ b/code/game/objects/items.dm @@ -691,6 +691,11 @@ GLOBAL_DATUM_INIT(fire_overlay, /mutable_appearance, mutable_appearance('icons/e else return +/obj/item/on_exit_storage(datum/component/storage/concrete/master_storage) + . = ..() + var/atom/location = master_storage.real_location() + do_drop_animation(location) + /obj/item/throw_impact(atom/hit_atom, datum/thrownthing/throwingdatum) if(hit_atom && !QDELETED(hit_atom)) SEND_SIGNAL(src, COMSIG_MOVABLE_IMPACT, hit_atom, throwingdatum) @@ -1260,3 +1265,111 @@ GLOBAL_DATUM_INIT(fire_overlay, /mutable_appearance, mutable_appearance('icons/e /// Whether or not this item can be put into a storage item through attackby /obj/item/proc/attackby_storage_insert(datum/component/storage, atom/storage_holder, mob/user) return TRUE + +/obj/item/proc/do_pickup_animation(atom/target) + if(!istype(loc, /turf)) + return + var/image/pickup_animation = image(icon = src, loc = loc, layer = layer + 0.1) + pickup_animation.plane = GAME_PLANE + pickup_animation.transform.Scale(0.75) + pickup_animation.appearance_flags = APPEARANCE_UI_IGNORE_ALPHA + + var/turf/current_turf = get_turf(src) + var/direction = get_dir(current_turf, target) + var/to_x = target.base_pixel_x + var/to_y = target.base_pixel_y + + if(direction & NORTH) + to_y += 32 + else if(direction & SOUTH) + to_y -= 32 + if(direction & EAST) + to_x += 32 + else if(direction & WEST) + to_x -= 32 + if(!direction) + to_y += 10 + pickup_animation.pixel_x += 6 * (prob(50) ? 1 : -1) //6 to the right or left, helps break up the straight upward move + + flick_overlay(pickup_animation, GLOB.clients, 4) + var/matrix/animation_matrix = new + animation_matrix.Turn(pick(-30, 30)) + animation_matrix.Scale(0.65) + + animate(pickup_animation, alpha = 175, pixel_x = to_x, pixel_y = to_y, time = 3, transform = animation_matrix, easing = CUBIC_EASING) + animate(alpha = 0, transform = matrix().Scale(0.7), time = 1) + +/obj/item/proc/do_drop_animation(atom/moving_from) + if(!istype(loc, /turf)) + return + + var/turf/current_turf = get_turf(src) + var/direction = get_dir(moving_from, current_turf) + var/from_x = moving_from.base_pixel_x + var/from_y = moving_from.base_pixel_y + + if(direction & NORTH) + from_y -= 32 + else if(direction & SOUTH) + from_y += 32 + if(direction & EAST) + from_x -= 32 + else if(direction & WEST) + from_x += 32 + if(!direction) + from_y += 10 + from_x += 6 * (prob(50) ? 1 : -1) //6 to the right or left, helps break up the straight upward move + + //We're moving from these chords to our current ones + var/old_x = pixel_x + var/old_y = pixel_y + var/old_alpha = alpha + var/matrix/animation_matrix = new + animation_matrix.Turn(pick(-30, 30)) + animation_matrix.Scale(0.7) // Shrink to start, end up normal sized + + pixel_x = from_x + pixel_y = from_y + alpha = 0 + transform = animation_matrix + + // This is instant on byond's end, but to our clients this looks like a quick drop + animate(src, alpha = old_alpha, pixel_x = old_x, pixel_y = old_y, transform = matrix(), time = 3, easing = CUBIC_EASING) + +/atom/movable/proc/do_item_attack_animation(atom/attacked_atom, visual_effect_icon, obj/item/used_item) + var/image/attack_image + if(visual_effect_icon) + attack_image = image('icons/effects/effects.dmi', attacked_atom, visual_effect_icon, attacked_atom.layer + 0.1) + else if(used_item) + attack_image = image(icon = used_item, loc = attacked_atom, layer = attacked_atom.layer + 0.1) + attack_image.plane = attacked_atom.plane + + // Scale the icon. + attack_image.transform *= 0.4 + // The icon should not rotate. + attack_image.appearance_flags = APPEARANCE_UI + + // Set the direction of the icon animation. + var/direction = get_dir(src, attacked_atom) + if(direction & NORTH) + attack_image.pixel_y = -12 + else if(direction & SOUTH) + attack_image.pixel_y = 12 + + if(direction & EAST) + attack_image.pixel_x = -14 + else if(direction & WEST) + attack_image.pixel_x = 14 + + if(!direction) // Attacked self?! + attack_image.pixel_y = 12 + attack_image.pixel_x = 5 * (prob(50) ? 1 : -1) + + if(!attack_image) + return + + flick_overlay(attack_image, GLOB.clients, 10) + // And animate the attack! + animate(attack_image, alpha = 175, transform = matrix() * 0.75, pixel_x = 0, pixel_y = 0, pixel_z = 0, time = 3) + animate(time = 1) + animate(alpha = 0, time = 3, easing = CIRCULAR_EASING|EASE_OUT) diff --git a/code/modules/mob/inventory.dm b/code/modules/mob/inventory.dm index 1f07ff5d24c..6e157c1aec3 100644 --- a/code/modules/mob/inventory.dm +++ b/code/modules/mob/inventory.dm @@ -281,13 +281,17 @@ */ /mob/proc/dropItemToGround(obj/item/I, force = FALSE, silent = FALSE, invdrop = TRUE) . = doUnEquip(I, force, drop_location(), FALSE, invdrop = invdrop, silent = silent) - if(. && I && !(I.item_flags & NO_PIXEL_RANDOM_DROP)) //ensure the item exists and that it was dropped properly. + if(!. || !I) //ensure the item exists and that it was dropped properly. + return + if(!(I.item_flags & NO_PIXEL_RANDOM_DROP)) I.pixel_x = I.base_pixel_x + rand(-6, 6) I.pixel_y = I.base_pixel_y + rand(-6, 6) + I.do_drop_animation(src) //for when the item will be immediately placed in a loc other than the ground /mob/proc/transferItemToLoc(obj/item/I, newloc = null, force = FALSE, silent = TRUE) - return doUnEquip(I, force, newloc, FALSE, silent = silent) + . = doUnEquip(I, force, newloc, FALSE, silent = silent) + I.do_drop_animation(src) //visibly unequips I but it is NOT MOVED AND REMAINS IN SRC //item MUST BE FORCEMOVE'D OR QDEL'D