diff --git a/code/__DEFINES/misc.dm b/code/__DEFINES/misc.dm index 418dd7f4314..8eaab195c62 100644 --- a/code/__DEFINES/misc.dm +++ b/code/__DEFINES/misc.dm @@ -327,6 +327,12 @@ #define SHELTER_DEPLOY_BAD_AREA "bad area" #define SHELTER_DEPLOY_ANCHORED_OBJECTS "anchored objects" +// transit_tube stuff +#define TRANSIT_TUBE_OPENING 0 +#define TRANSIT_TUBE_OPEN 1 +#define TRANSIT_TUBE_CLOSING 2 +#define TRANSIT_TUBE_CLOSED 3 + // Maximum donation level #define DONATOR_LEVEL_MAX 4 diff --git a/code/game/objects/structures/transit_tubes/station.dm b/code/game/objects/structures/transit_tubes/station.dm index 9d06f870fc3..6c58440e7fb 100644 --- a/code/game/objects/structures/transit_tubes/station.dm +++ b/code/game/objects/structures/transit_tubes/station.dm @@ -1,3 +1,7 @@ +#define CLOSE_DURATION 6 +#define OPEN_DURATION 6 +#define LAUNCH_COOLDOWN 50 + // A place where tube pods stop, and people can get in or out. // Mappers: use "Generate Instances from Directions" for this @@ -8,13 +12,11 @@ icon_state = "closed" exit_delay = 1 enter_delay = 2 - var/pod_moving = 0 - var/cooldown_delay = 50 + var/pod_moving = FALSE var/launch_cooldown = 0 - var/reverse_launch = 0 + var/reverse_launch = FALSE + var/hatch_state = TRANSIT_TUBE_CLOSED - var/const/OPEN_DURATION = 6 - var/const/CLOSE_DURATION = 6 var/list/disallowed_mobs = list(/mob/living/silicon/ai) /obj/structure/transit_tube/station/New() @@ -27,116 +29,134 @@ // Stations which will send the tube in the opposite direction after their stop. /obj/structure/transit_tube/station/reverse - reverse_launch = 1 + reverse_launch = TRUE /obj/structure/transit_tube/station/should_stop_pod(pod, from_dir) - return 1 + return TRUE -/obj/structure/transit_tube/station/Bumped(mob/AM as mob|obj) - if(!pod_moving && icon_state == "open" && istype(AM, /mob/living) && !is_type_in_list(AM, disallowed_mobs)) +/obj/structure/transit_tube/station/Bumped(mob/living/L) + if(!pod_moving && hatch_state == TRANSIT_TUBE_OPEN && isliving(L) && !is_type_in_list(L, disallowed_mobs)) + var/failed = FALSE for(var/obj/structure/transit_tube_pod/pod in loc) if(pod.contents.len) - to_chat(AM, "") - return + failed = TRUE else if(!pod.moving && (pod.dir in directions())) - AM.forceMove(pod) + pod.move_into(L) return + if(failed) + to_chat(L, "The pod is already occupied.") -/obj/structure/transit_tube/station/attack_hand(mob/user as mob) - if(!pod_moving) - for(var/obj/structure/transit_tube_pod/pod in loc) - if(!pod.moving && (pod.dir in directions())) - if(icon_state == "closed") - open_animation() - - else if(icon_state == "open") - if(pod.contents.len && user.loc != pod) - user.visible_message("[user] starts emptying [pod]'s contents onto the floor!") - if(do_after(user, 40, target = src)) //So it doesn't default to close_animation() on fail - if(pod.loc == loc) - for(var/atom/movable/AM in pod) - AM.loc = get_turf(user) - if(ismob(AM)) - var/mob/M = AM - M.Weaken(5) - - else - close_animation() - break +/obj/structure/transit_tube/station/attack_hand(mob/user) + if(pod_moving) + return + var/obj/structure/transit_tube_pod/pod = locate() in loc + if(!pod) + return + // Can't get in moving pods. Or pods that have openings on the other side + if(pod.moving || !(pod.dir in directions())) + return + if(hatch_state != TRANSIT_TUBE_OPEN) + return + // Can't empty it when inside or when there is nothing inside + if(!length(pod.contents) || user.loc == pod) + return + user.visible_message("[user] starts emptying [pod]'s contents onto the floor!", \ + "You start emptying [pod]'s contents onto the floor.", "You hear a loud noise! As if somebody is throwing stuff on the floor!") + if(!do_after(user, 20, target = pod)) + return + for(var/atom/movable/AM in pod) + pod.eject(AM) + if(ismob(AM)) + var/mob/M = AM + M.Weaken(5) /obj/structure/transit_tube/station/attackby(obj/item/W, mob/user, params) - if(istype(W, /obj/item/grab) && icon_state == "open") + if(istype(W, /obj/item/grab) && hatch_state == TRANSIT_TUBE_OPEN) var/obj/item/grab/G = W if(ismob(G.affecting) && G.state >= GRAB_AGGRESSIVE) var/mob/GM = G.affecting for(var/obj/structure/transit_tube_pod/pod in loc) pod.visible_message("[user] starts putting [GM] into the [pod]!") - if(do_after(user, 60, target = GM) && GM && G && G.affecting == GM) + if(do_after(user, 30, target = GM) && GM && G && G.affecting == GM) GM.Weaken(5) - src.Bumped(GM) + Bumped(GM) qdel(G) break -/obj/structure/transit_tube/station/proc/open_animation() - if(icon_state == "closed") +/obj/structure/transit_tube/station/proc/open_hatch() + if(hatch_state == TRANSIT_TUBE_CLOSED) icon_state = "opening" - spawn(OPEN_DURATION) - if(icon_state == "opening") - icon_state = "open" + hatch_state = TRANSIT_TUBE_OPENING + addtimer(CALLBACK(src, .proc/open_hatch_callback), OPEN_DURATION) + +/obj/structure/transit_tube/station/proc/open_hatch_callback() + if(hatch_state == TRANSIT_TUBE_OPENING) + icon_state = "open" + hatch_state = TRANSIT_TUBE_OPEN -/obj/structure/transit_tube/station/proc/close_animation() - if(icon_state == "open") +/obj/structure/transit_tube/station/proc/close_hatch() + if(hatch_state == TRANSIT_TUBE_OPEN) icon_state = "closing" - spawn(CLOSE_DURATION) - if(icon_state == "closing") - icon_state = "closed" - + hatch_state = TRANSIT_TUBE_CLOSING + addtimer(CALLBACK(src, .proc/close_hatch_calllback), CLOSE_DURATION) +/obj/structure/transit_tube/station/proc/close_hatch_calllback() + if(hatch_state == TRANSIT_TUBE_CLOSING) + icon_state = "closed" + hatch_state = TRANSIT_TUBE_CLOSED /obj/structure/transit_tube/station/proc/launch_pod() for(var/obj/structure/transit_tube_pod/pod in loc) if(!pod.moving && (pod.dir in directions())) - spawn(5) - pod_moving = 1 - close_animation() - sleep(CLOSE_DURATION + 2) - - //reverse directions for automated cycling - var/turf/next_loc = get_step(loc, pod.dir) - var/obj/structure/transit_tube/nexttube - for(var/obj/structure/transit_tube/tube in next_loc) - if(tube.has_entrance(pod.dir)) - nexttube = tube - break - if(!nexttube) - pod.dir = turn(pod.dir, 180) - - if(icon_state == "closed" && pod) - pod.follow_tube() - - pod_moving = 0 - + addtimer(CALLBACK(src, .proc/launch_pod_callback, pod), 5) return +/obj/structure/transit_tube/station/proc/launch_pod_callback(obj/structure/transit_tube_pod/pod) + pod_moving = TRUE + close_hatch() + sleep(CLOSE_DURATION + 2) + + //reverse directions for automated cycling + var/turf/next_loc = get_step(loc, pod.dir) + var/obj/structure/transit_tube/nexttube + for(var/obj/structure/transit_tube/tube in next_loc) + if(tube.has_entrance(pod.dir)) + nexttube = tube + break + if(!nexttube) + pod.dir = turn(pod.dir, 180) + + if(hatch_state == TRANSIT_TUBE_CLOSED && pod) + pod.follow_tube() + + pod_moving = FALSE + /obj/structure/transit_tube/station/process() - if(!pod_moving) + if(!pod_moving && launch_cooldown <= world.time) launch_pod() /obj/structure/transit_tube/station/pod_stopped(obj/structure/transit_tube_pod/pod, from_dir) - pod_moving = 1 - spawn(5) - launch_cooldown = world.time + cooldown_delay - open_animation() - sleep(OPEN_DURATION + 2) - pod_moving = 0 - pod.mix_air() + pod_moving = TRUE + addtimer(CALLBACK(src, .proc/pod_stopped_callback, pod), 5) + +/obj/structure/transit_tube/station/proc/pod_stopped_callback(obj/structure/transit_tube_pod/pod) + launch_cooldown = world.time + LAUNCH_COOLDOWN + open_hatch(pod) + sleep(OPEN_DURATION + 2) + pod.eject_mindless(dir) + pod_moving = FALSE + pod.mix_air() // Tube station directions are simply 90 to either side of // the exit. /obj/structure/transit_tube/station/init_dirs() tube_dirs = list(turn(dir, 90), turn(dir, -90)) + +#undef CLOSE_DURATION +#undef OPEN_DURATION +#undef LAUNCH_COOLDOWN diff --git a/code/game/objects/structures/transit_tubes/transit_tube_pod.dm b/code/game/objects/structures/transit_tubes/transit_tube_pod.dm index 8984dc60a52..126133cddc0 100644 --- a/code/game/objects/structures/transit_tubes/transit_tube_pod.dm +++ b/code/game/objects/structures/transit_tubes/transit_tube_pod.dm @@ -2,12 +2,11 @@ icon = 'icons/obj/pipes/transit_tube_pod.dmi' icon_state = "pod" animate_movement = FORWARD_STEPS - anchored = 1.0 - density = 1 - var/moving = 0 + anchored = TRUE + density = TRUE + var/moving = FALSE var/datum/gas_mixture/air_contents = new() - /obj/structure/transit_tube_pod/New(loc) ..(loc) @@ -26,14 +25,14 @@ /obj/structure/transit_tube_pod/Process_Spacemove() if(moving) //No drifting while moving in the tubes - return 1 + return TRUE else return ..() /obj/structure/transit_tube_pod/proc/follow_tube(var/reverse_launch) if(moving) return - moving = 1 + moving = TRUE spawn() var/obj/structure/transit_tube/current_tube = null @@ -70,23 +69,23 @@ break if(current_tube == null) - dir = next_dir + setDir(next_dir) Move(get_step(loc, dir), dir) // Allow collisions when leaving the tubes. break last_delay = current_tube.enter_delay(src, next_dir) sleep(last_delay) - dir = next_dir - loc = next_loc // When moving from one tube to another, skip collision and such. + setDir(next_dir) + forceMove(next_loc) // When moving from one tube to another, skip collision and such. density = current_tube.density if(current_tube && current_tube.should_stop_pod(src, next_dir)) current_tube.pod_stopped(src, dir) break - density = 1 + density = TRUE - moving = 0 + moving = FALSE // Should I return a copy here? If the caller edits or qdel()s the returned @@ -141,10 +140,11 @@ // the station, try to exit. If the direction matches one of the station's // tube directions, launch the pod in that direction. /obj/structure/transit_tube_pod/relaymove(mob/mob, direction) - if(istype(mob, /mob) && mob.client) + if(istype(mob) && mob.client) // If the pod is not in a tube at all, you can get out at any time. if(!(locate(/obj/structure/transit_tube) in loc)) - mob.forceMove(loc) + eject(mob, direction) + return //if(moving && istype(loc, /turf/space)) // Todo: If you get out of a moving pod in space, you should move as well. @@ -155,19 +155,41 @@ if(dir in station.directions()) if(!station.pod_moving) if(direction == station.dir) - if(station.icon_state == "open") - mob.forceMove(loc) + if(station.hatch_state == TRANSIT_TUBE_OPEN) + eject(mob, direction) else - station.open_animation() + station.open_hatch() else if(direction in station.directions()) - dir = direction + setDir(direction) station.launch_pod() return for(var/obj/structure/transit_tube/tube in loc) if(dir in tube.directions()) if(tube.has_exit(direction)) - dir = direction + setDir(direction) return + +/obj/structure/transit_tube_pod/proc/move_into(atom/movable/A) + icon_state = "pod_occupied" + A.forceMove(src) + +/obj/structure/transit_tube_pod/proc/eject_mindless(direction) + for(var/atom/movable/A in contents) + if(ismob(A)) + var/mob/M = A + if(M.mind) // Only eject mindless mobs + continue + eject(A, direction) + A.Move(get_step(loc, direction), direction) + + +/obj/structure/transit_tube_pod/proc/eject(atom/movable/A, direction) + icon_state = "pod" + A.forceMove(loc) + A.Move(get_step(loc, direction), direction) + if(ismob(A)) + var/mob/M = A + M.reset_perspective(null) diff --git a/code/modules/mob/living/silicon/robot/drone/drone.dm b/code/modules/mob/living/silicon/robot/drone/drone.dm index a8485853be1..ce5d41f1eba 100644 --- a/code/modules/mob/living/silicon/robot/drone/drone.dm +++ b/code/modules/mob/living/silicon/robot/drone/drone.dm @@ -31,6 +31,10 @@ var/obj/item/stack/sheet/plastic/stack_plastic = null var/obj/item/matter_decompiler/decompiler = null + // What objects can drones bump into + var/static/list/allowed_bumpable_objects = list(/obj/machinery/door, /obj/machinery/recharge_station, /obj/machinery/disposal/deliveryChute, + /obj/machinery/teleport/hub, /obj/effect/portal, /obj/structure/transit_tube/station) + //Used for self-mailing. var/mail_destination = 0 var/reboot_cooldown = 60 // one minute @@ -330,11 +334,7 @@ /mob/living/silicon/robot/drone/Bump(atom/movable/AM, yes) - if(istype(AM, /obj/machinery/door) \ - || istype(AM, /obj/machinery/recharge_station) \ - || istype(AM, /obj/machinery/disposal/deliveryChute) \ - || istype(AM, /obj/machinery/teleport/hub) \ - || istype(AM, /obj/effect/portal)) + if(is_type_in_list(AM, allowed_bumpable_objects)) return ..() /mob/living/silicon/robot/drone/Bumped(atom/movable/AM)