diff --git a/code/datums/components/afterimage.dm b/code/datums/components/afterimage.dm new file mode 100644 index 000000000000..ecec2aa3a06f --- /dev/null +++ b/code/datums/components/afterimage.dm @@ -0,0 +1,137 @@ +/datum/component/after_image + dupe_mode = COMPONENT_DUPE_UNIQUE_PASSARGS + var/rest_time + var/list/obj/after_image/after_images + + //cycles colors + var/color_cycle = FALSE + var/list/hsv + +/datum/component/after_image/Initialize(count = 4, rest_time = 1, color_cycle = FALSE) + ..() + if(!ismovable(parent)) + return COMPONENT_INCOMPATIBLE + src.rest_time = rest_time + src.after_images = list() + src.color_cycle = color_cycle + if(count > 1) + for(var/number = 1 to count) + var/obj/after_image/added_image = new /obj/after_image(null) + added_image.finalized_alpha = 200 - 100 * (number - 1) / (count - 1) + after_images += added_image + else + var/obj/after_image/added_image = new /obj/after_image(null) + added_image.finalized_alpha = 100 + after_images |= added_image + RegisterSignal(parent, COMSIG_MOVABLE_MOVED, PROC_REF(move)) + RegisterSignal(parent, COMSIG_ATOM_DIR_CHANGE, PROC_REF(change_dir)) + RegisterSignal(parent, COMSIG_MOVABLE_THROW_LANDED, PROC_REF(throw_landed)) + +/datum/component/after_image/RegisterWithParent() + for(var/obj/after_image/listed_image in src.after_images) + listed_image.active = TRUE + src.sync_after_images() + +/datum/component/after_image/UnregisterFromParent() + UnregisterSignal(parent, list(COMSIG_MOVABLE_MOVED, COMSIG_ATOM_DIR_CHANGE, COMSIG_MOVABLE_THROW_LANDED)) + for(var/obj/after_image/listed_image in src.after_images) + listed_image.active = FALSE + animate(listed_image, time = 1 SECONDS, alpha = 0) + QDEL_IN(listed_image, 1.1 SECONDS) + . = ..() + +/datum/component/after_image/Destroy() + if(length(src.after_images)) + for(var/obj/after_image/listed_image in src.after_images) + animate(listed_image, time = 1 SECONDS, alpha = 0) + QDEL_IN(listed_image, 1.1 SECONDS) + src.after_images.Cut() + src.after_images = null + . = ..() + +/datum/component/after_image/proc/change_dir(atom/movable/AM, new_dir, old_dir) + src.sync_after_images(new_dir) + +/datum/component/after_image/proc/set_loc(atom/movable/AM, atom/last_loc) + return src.move(AM, last_loc, AM.dir) + +/datum/component/after_image/proc/move(atom/movable/AM, turf/last_turf, direct) + src.sync_after_images() + +/datum/component/after_image/proc/throw_landed(atom/movable/AM, datum/thrownthing/thing) + src.sync_after_images() // necessary to fix pixel_x and pixel_y + +/datum/component/after_image/proc/sync_after_images(dir_override=null) + set waitfor = FALSE + var/obj/after_image/targeted_image = new(null) + targeted_image.active = TRUE + targeted_image.sync_with_parent(parent) + targeted_image.loc = null + + if(color_cycle) + if(!hsv) + hsv = RGBtoHSV(rgb(255, 0, 0)) + hsv = RotateHue(hsv, world.time - rest_time * 15) + targeted_image.color = HSVtoRGB(hsv) + + if(!isnull(dir_override)) + targeted_image.setDir(dir_override) + + var/atom/movable/parent_am = parent + var/atom/target_loc = parent_am.loc + for(var/obj/after_image/listed_image in src.after_images) + sleep(src.rest_time) + listed_image.sync_with_parent(targeted_image, target_loc) + qdel(targeted_image) + + + +//to-do, make this emissive +/obj/after_image + mouse_opacity = FALSE + anchored = 2 + var/finalized_alpha = 100 + var/appearance_ref = null + var/active = FALSE + +/obj/after_image/New() + . = ..() + animate(src, pixel_x=0, time=1, loop=-1) + var/count = rand(5, 10) + for(var/number = 1 to count) + var/time = 0.5 SECONDS + rand() * 3 SECONDS + var/pixel_x = number == count ? 0 : rand(-2, 2) + var/pixel_y = number == count ? 0 : rand(-2, 2) + animate(time = time, easing = pick(LINEAR_EASING, SINE_EASING, CIRCULAR_EASING, CUBIC_EASING), flags = ANIMATION_PARALLEL, pixel_x = pixel_x, pixel_y = pixel_y, loop =- 1) + +/obj/after_image/proc/sync_with_parent(atom/movable/parent, loc_override=null) + if(!src.active) + return + src.name = parent.name + src.desc = parent.desc + src.glide_size = parent.glide_size + + var/parent_appearance_ref = ref(parent.appearance) + if(istype(parent, /obj/after_image)) + var/obj/after_image/parent_after_image = parent + parent_appearance_ref = parent_after_image.appearance_ref + + if(src.appearance_ref != parent_appearance_ref) + src.appearance_ref = parent_appearance_ref + src.appearance = parent.appearance + src.alpha = src.alpha / 255.0 * src.finalized_alpha + src.plane = initial(src.plane) + src.mouse_opacity = initial(src.mouse_opacity) + src.anchored = initial(src.anchored) + + var/atom/target_loc = loc_override ? loc_override : parent.loc + + if(target_loc != src.loc) + src.loc = target_loc + + if(src.dir != parent.dir) + src.setDir(parent.dir) + +/obj/after_image/Destroy() + src.active = FALSE + . = ..() diff --git a/code/modules/surgery/organs/augments_chest.dm b/code/modules/surgery/organs/augments_chest.dm index c58ac8b27f2f..39e918e90e5a 100644 --- a/code/modules/surgery/organs/augments_chest.dm +++ b/code/modules/surgery/organs/augments_chest.dm @@ -258,7 +258,7 @@ human.physiology.crawl_speed -= 1 owner.next_move_modifier *= 0.7 owner.add_movespeed_modifier("spinalimplant", priority=100, multiplicative_slowdown=-1) - RegisterSignal(owner, COMSIG_MOVABLE_PRE_MOVE, PROC_REF(move_react)) + owner.AddComponent(/datum/component/after_image, 16, 0.5, TRUE) else if(COOLDOWN_FINISHED(src, endsoundcooldown)) playsound(owner, 'sound/effects/spinal_implant_off.ogg', 70) @@ -270,7 +270,8 @@ human.physiology.crawl_speed += 1 owner.next_move_modifier /= 0.7 owner.remove_movespeed_modifier("spinalimplant") - UnregisterSignal(owner, COMSIG_MOVABLE_PRE_MOVE) + var/datum/component/after_image = owner.GetComponent(/datum/component/after_image) + qdel(after_image) on = !on if(!silent) to_chat(owner, span_notice("You turn your spinal implant [on? "on" : "off"].")) @@ -285,15 +286,6 @@ for(var/datum/action/A as anything in actions) A.build_all_button_icons() -/obj/item/organ/cyberimp/chest/spinalspeed/proc/move_react()//afterimage - var/turf/currentloc = get_turf(owner) - var/obj/effect/temp_visual/decoy/fading/F = new(currentloc, owner) - if(!hsv) - hsv = RGBtoHSV(rgb(255, 0, 0)) - hsv = RotateHue(hsv, world.time - last_step * 15) - last_step = world.time - F.color = HSVtoRGB(hsv) //gotta add the flair - /obj/item/organ/cyberimp/chest/spinalspeed/on_life() if(!syndicate_implant)//the toy doesn't have a drawback return diff --git a/yogstation.dme b/yogstation.dme index 3638fd4ba854..6e5cfb6d8ed9 100644 --- a/yogstation.dme +++ b/yogstation.dme @@ -565,6 +565,7 @@ #include "code\datums\brain_damage\split_personality.dm" #include "code\datums\components\_component.dm" #include "code\datums\components\action_item_overlay.dm" +#include "code\datums\components\afterimage.dm" #include "code\datums\components\anti_magic.dm" #include "code\datums\components\armor_plate.dm" #include "code\datums\components\art.dm"