diff --git a/code/modules/clothing/outfits/standard.dm b/code/modules/clothing/outfits/standard.dm index 623edd0775d..cb76ec05eb6 100644 --- a/code/modules/clothing/outfits/standard.dm +++ b/code/modules/clothing/outfits/standard.dm @@ -12,13 +12,13 @@ var/obj/item/weapon/tank/jetpack/J = H.back J.toggle() J.Topic(null, list("stat" = 1)) - + /datum/outfit/tournament /datum/outfit/tournament/ name = "tournament standard red" - + uniform = /obj/item/clothing/under/color/red shoes = /obj/item/clothing/shoes/sneakers/black suit = /obj/item/clothing/suit/armor/vest @@ -30,7 +30,7 @@ /datum/outfit/tournament/red name = "tournament standard green" - + uniform = /obj/item/clothing/under/color/green /datum/outfit/tournament/gangster @@ -156,7 +156,7 @@ /datum/outfit/assassin/post_equip(mob/living/carbon/human/H) var/obj/item/clothing/under/U = H.w_uniform U.attachTie(new /obj/item/clothing/tie/waistcoat(H)) - + //Could use a type var/obj/item/weapon/storage/secure/briefcase/sec_briefcase = H.l_hand for(var/obj/item/briefcase_item in sec_briefcase) @@ -172,7 +172,7 @@ pda.owner = H.real_name pda.ownjob = "Reaper" pda.update_label() - + var/obj/item/weapon/card/id/syndicate/W = H.wear_id W.access = get_all_accesses() W.assignment = "Reaper" @@ -340,7 +340,7 @@ var/obj/item/device/radio/R = H.ears R.set_frequency(CENTCOM_FREQ) R.freqlock = 1 - + var/obj/item/weapon/implant/loyalty/L = new/obj/item/weapon/implant/loyalty(H)//Here you go Deuryn L.imp_in = H L.implanted = 1 @@ -359,7 +359,15 @@ name = "Death Commando Officer" head = /obj/item/clothing/head/helmet/space/beret +/datum/outfit/chrono_agent + name = "Timeline Eradication Agent" + uniform = /obj/item/clothing/under/color/white + suit = /obj/item/clothing/suit/space/chronos + back = /obj/item/weapon/chrono_eraser + head = /obj/item/clothing/head/helmet/space/chronos + mask = /obj/item/clothing/mask/breath + suit_store = /obj/item/weapon/tank/internals/oxygen + - \ No newline at end of file diff --git a/code/modules/clothing/spacesuits/chronosuit.dm b/code/modules/clothing/spacesuits/chronosuit.dm index b5b219cbcf2..be2da2b3b62 100644 --- a/code/modules/clothing/spacesuits/chronosuit.dm +++ b/code/modules/clothing/spacesuits/chronosuit.dm @@ -25,19 +25,27 @@ action_button_name = "Toggle Chronosuit" armor = list(melee = 60, bullet = 60, laser = 60, energy = 60, bomb = 30, bio = 90, rad = 90) var/list/chronosafe_items = list(/obj/item/weapon/chrono_eraser, /obj/item/weapon/gun/energy/chrono_gun) + var/hands_nodrop_states var/obj/item/clothing/head/helmet/space/chronos/helmet = null var/obj/effect/chronos_cam/camera = null + var/atom/movable/overlay/phase_underlay = null + var/datum/action/innate/chrono_teleport/teleport_now = new var/activating = 0 var/activated = 0 var/cooldowntime = 50 //deciseconds var/teleporting = 0 +/obj/item/clothing/suit/space/chronos/New() + ..() + teleport_now.chronosuit = src + teleport_now.target = src /obj/item/clothing/suit/space/chronos/proc/new_camera(mob/user) if(camera) qdel(camera) - camera = new /obj/effect/chronos_cam(get_turf(user)) + camera = new /obj/effect/chronos_cam(user) camera.holder = user + camera.chronosuit = src user.remote_control = camera /obj/item/clothing/suit/space/chronos/ui_action_click() @@ -60,20 +68,48 @@ var/mob/living/carbon/human/user = src.loc switch(severity) if(1) - if(user && ishuman(user) && (user.wear_suit == src)) - user << "Elecrtromagnetic pulse detected, shutting down systems to preserve integrity..." - deactivate() + if(activated && user && ishuman(user) && (user.wear_suit == src)) + user << "E:FATAL:RAM_READ_FAIL\nE:FATAL:STACK_EMPTY\nE:FATAL:READ_NULL_POINT\nE:FATAL:PWR_BUS_OVERLOAD" + deactivate(1, 1) -/obj/item/clothing/suit/space/chronos/proc/chronowalk(mob/living/carbon/human/user) - if(!teleporting && user && (user.stat == CONSCIOUS)) +/obj/item/clothing/suit/space/chronos/proc/finish_chronowalk() + var/mob/living/carbon/human/user = src.loc + if(istype(user)) + user.SetStunned(0) + user.next_move = 1 + user.alpha = 255 + user.color = "#ffffff" + user.animate_movement = FORWARD_STEPS + user.notransform = 0 + user.anchored = 0 + teleporting = 0 + if(user.l_hand && !(hands_nodrop_states & 1)) + user.l_hand.flags &= ~NODROP + if(user.r_hand && !(hands_nodrop_states & 2)) + user.r_hand.flags &= ~NODROP + if(phase_underlay && !qdeleted(phase_underlay)) + qdel(phase_underlay) + phase_underlay = null + if(camera) + camera.remove_target_ui() + camera.loc = user + if(teleport_now.button) + teleport_now.button.UpdateIcon() + +/obj/item/clothing/suit/space/chronos/proc/chronowalk(atom/location) + var/mob/living/carbon/human/user = src.loc + if(activated && !teleporting && user && istype(user) && location && user.loc && location.loc && user.wear_suit == src && user.stat == CONSCIOUS) teleporting = 1 var/turf/from_turf = get_turf(user) - if(!from_turf) //sanity, things happen - teleporting = 0 - return - var/turf/to_turf = from_turf - var/atom/movable/overlay/phaseanim = new(from_turf) - var/obj/holder = new(camera) + var/turf/to_turf = get_turf(location) + var/distance = cheap_hypotenuse(from_turf.x, from_turf.y, to_turf.x, to_turf.y) + var/phase_in_ds = distance*2 + + if(camera) + camera.remove_target_ui() + + if(teleport_now.button) + teleport_now.button.UpdateIcon() var/list/nonsafe_slots = list(slot_belt, slot_back, slot_l_hand, slot_r_hand) for(var/slot in nonsafe_slots) @@ -81,52 +117,73 @@ if(slot_item && !(slot_item.type in chronosafe_items) && user.unEquip(slot_item)) user << "Your [slot_item.name] got left behind." - phaseanim.name = "phasing [user.name]" - phaseanim.icon = 'icons/mob/mob.dmi' - phaseanim.icon_state = "chronostuck" - phaseanim.density = 1 - phaseanim.layer = FLY_LAYER - phaseanim.master = user user.ExtinguishMob() if(user.buckled) user.buckled.unbuckle_mob() - user.loc = holder - flick("chronophase", phaseanim) - spawn(7) - if(user) - if(phaseanim) - if(camera && camera.loc) - to_turf = camera.loc - flick("chronounphase", phaseanim) - else - flick("chronostuck", phaseanim) - phaseanim.loc = to_turf - sleep(7) - if(holder) - if(user && user in holder.contents) + + phase_underlay = create_phase_underlay(user) + + hands_nodrop_states = 0 + if(user.l_hand) + hands_nodrop_states |= (user.l_hand.flags & NODROP) ? 1 : 0 + user.l_hand.flags |= NODROP + if(user.r_hand) + hands_nodrop_states |= (user.r_hand.flags & NODROP) ? 2 : 0 + user.r_hand.flags |= NODROP + + user.animate_movement = NO_STEPS + user.changeNext_move(8 + phase_in_ds) + user.notransform = 1 + user.anchored = 1 + user.Stun(INFINITY) + + animate(user, color = "#00ccee", time = 3) + spawn(3) + if(teleporting && activated && user && phase_underlay && !qdeleted(phase_underlay)) + animate(user, alpha = 0, time = 2) + animate(phase_underlay, alpha = 255, time = 2) + sleep(2) + if(teleporting && activated && user && phase_underlay && !qdeleted(phase_underlay)) + phase_underlay.loc = to_turf user.loc = to_turf - if(user.client) - if(camera) - user.client.eye = camera - else - user.client.eye = user - qdel(holder) - else if(user) - user.loc = from_turf - if(phaseanim) - qdel(phaseanim) - teleporting = 0 - if(user && !user.loc) //ubersanity - user.loc = locate(0,0,1) - user.gib() + animate(user, alpha = 255, time = phase_in_ds) + animate(phase_underlay, alpha = 0, time = phase_in_ds) + sleep(phase_in_ds) + if(teleporting && activated && phase_underlay && !qdeleted(phase_underlay)) + animate(user, color = "#ffffff", time = 3) + sleep(3) + if(teleporting && user && !qdeleted(user)) + user.loc = to_turf //this will cover if bad things happen before the teleport, yes it is redundant + finish_chronowalk() + +/obj/item/clothing/suit/space/chronos/proc/create_phase_underlay(var/mob/user) + var/icon/user_icon = getFlatIcon(user) + user_icon.Blend("#ffffff") + var/atom/movable/overlay/phase = new(user.loc) + phase.icon = user_icon + phase.density = 1 + phase.anchored = 1 + phase.master = user + phase.animate_movement = NO_STEPS + phase.alpha = 0 + phase.mouse_opacity = 0 + phase.name = user.name + phase.transform = user.transform + phase.pixel_x = user.pixel_x + phase.pixel_y = user.pixel_y + return phase /obj/item/clothing/suit/space/chronos/process() if(activated) var/mob/living/carbon/human/user = src.loc if(user && ishuman(user) && (user.wear_suit == src)) if(camera && (user.remote_control == camera)) - if(!teleporting && !((camera.x == user.x) && (camera.y == user.y) && (camera.z == user.z))) //cheaper than a couple get_turf calls??? - chronowalk(user) + if(!teleporting) + if(camera.loc != user && ((camera.x != user.x) || (camera.y != user.y) || (camera.z != user.z))) + if(camera.phase_time <= world.time) + chronowalk(camera) + else + camera.remove_target_ui() else new_camera(user) else @@ -156,33 +213,41 @@ else user << "\[ fail \] Mounting /dev/helmet" user << "FATAL: Unable to locate /dev/helmet. Aborting..." + teleport_now.Grant(user) cooldown = world.time + cooldowntime activating = 0 return 0 -/obj/item/clothing/suit/space/chronos/proc/deactivate() - if(activated) +/obj/item/clothing/suit/space/chronos/proc/deactivate(force = 0, silent = 0) + if(activated && (!teleporting || force)) activating = 1 var/mob/living/carbon/human/user = src.loc if(user && ishuman(user)) if(user.wear_suit == src) - user << "\nroot@ChronosuitMK4# chronowalk4 --stop\n" + if(!silent) + user << "\nroot@ChronosuitMK4# chronowalk4 --stop\n" if(camera) - user << "\[ ok \] Sending TERM signal to chronowalk4-view" //yes I know they aren't a different color when shutting down, but they were too similar at a glance + if(!silent) + user << "\[ ok \] Sending TERM signal to chronowalk4-view" //yes I know they aren't a different color when shutting down, but they were too similar at a glance qdel(camera) if(helmet) - user << "\[ ok \] Stopping ui display driver" - user << "\[ ok \] Stopping brainwave scanner" - user << "\[ ok \] Unmounting /dev/helmet" + if(!silent) + user << "\[ ok \] Stopping ui display driver" + user << "\[ ok \] Stopping brainwave scanner" + user << "\[ ok \] Unmounting /dev/helmet" helmet.flags &= ~NODROP helmet.suit = null helmet = null - user << "logout" + if(!silent) + user << "logout" + teleport_now.Remove(user) src.flags &= ~NODROP cooldown = world.time + cooldowntime * 1.5 activated = 0 activating = 0 - + finish_chronowalk() + if(teleporting && force) + user.electrocute_act(35, src, safety = 1) /obj/effect/chronos_cam name = "Chronosuit View" @@ -192,28 +257,90 @@ opacity = 0 mouse_opacity = 0 var/mob/holder = null + var/phase_time = 0 + var/phase_time_length = 3 + var/obj/screen/chronos_target/target_ui = null + var/obj/item/clothing/suit/space/chronos/chronosuit + +/obj/effect/chronos_cam/proc/create_target_ui() + if(holder && holder.client && chronosuit) + if(target_ui) + remove_target_ui() + target_ui = new(null, holder) + holder.client.screen += target_ui + +/obj/effect/chronos_cam/proc/remove_target_ui() + if(target_ui) + qdel(target_ui) + target_ui = null /obj/effect/chronos_cam/relaymove(var/mob/user, direction) if(holder) if(user == holder) + if(loc == user) + loc = get_turf(user) if(user.client && user.client.eye != src) src.loc = get_turf(user) - user.client.eye = src - var/step = get_step(src, direction) + user.reset_view(src) + user.set_machine(src) + var/atom/step = get_step(src, direction) if(step) - if(istype(step, /turf/space)) + if((step.x <= TRANSITIONEDGE) || (step.x >= (world.maxx - TRANSITIONEDGE - 1)) || (step.y <= TRANSITIONEDGE) || (step.y >= (world.maxy - TRANSITIONEDGE - 1))) if(!src.Move(step)) src.loc = step else src.loc = step + if((x == holder.x) && (y == holder.y) && (z == holder.z)) + remove_target_ui() + loc = user + else if(!target_ui) + create_target_ui() + phase_time = world.time + phase_time_length else qdel(src) +/obj/effect/chronos_cam/check_eye(mob/user) + if(user == holder) + return 1 + user.unset_machine() + user.reset_view(null) + /obj/effect/chronos_cam/Destroy() if(holder) if(holder.remote_control == src) holder.remote_control = null if(holder.client && (holder.client.eye == src)) - holder.client.eye = holder + holder.unset_machine() + holder.reset_view(null) return ..() +/obj/screen/chronos_target + name = "target display" + screen_loc = "CENTER,CENTER" + color = "#ff3311" + blend_mode = BLEND_SUBTRACT + +/obj/screen/chronos_target/New(loc, var/mob/living/carbon/human/user) + if(user) + var/icon/user_icon = getFlatIcon(user) + icon = user_icon + transform = user.transform + else + qdel(src) + +/datum/action/innate/chrono_teleport + name = "Teleport Now" + button_icon_state = "chrono_phase" + check_flags = AB_CHECK_ALIVE|AB_CHECK_INSIDE + var/obj/item/clothing/suit/space/chronos/chronosuit = null + +/datum/action/innate/chrono_teleport/IsAvailable() + return (!CheckRemoval(owner) && !chronosuit.teleporting) + +/datum/action/innate/chrono_teleport/Activate() + if(IsAvailable()) + if(chronosuit.camera) + chronosuit.chronowalk(chronosuit.camera) + +/datum/action/innate/chrono_teleport/CheckRemoval() + return (..() && !(chronosuit && chronosuit.activated && chronosuit.camera)) \ No newline at end of file diff --git a/html/changelogs/JJRcop-chronosuit_revisions.yml b/html/changelogs/JJRcop-chronosuit_revisions.yml new file mode 100644 index 00000000000..2968b532be2 --- /dev/null +++ b/html/changelogs/JJRcop-chronosuit_revisions.yml @@ -0,0 +1,6 @@ +author: JJRcop +delete-after: True +changes: + - tweak: "Chronosuits have had their movement revised, they now take time to teleport depending on how far you've traveled, and don't teleport automatically anymore unless you stop moving for a short moment, or press the new ' + Teleport Now' button." + - rscadd: "Added new outfit that allows admins to dress people up in the chrono equipment easier." \ No newline at end of file diff --git a/icons/mob/actions.dmi b/icons/mob/actions.dmi index 8a5c06f2524..1e72f873cc5 100644 Binary files a/icons/mob/actions.dmi and b/icons/mob/actions.dmi differ