/* All ShuttleMove procs go here */ /************************************Base procs************************************/ // Called on every turf in the shuttle region, returns a bitflag for allowed movements of that turf // returns the new move_mode (based on the old) /turf/proc/fromShuttleMove(turf/newT, move_mode) if(!(move_mode & MOVE_AREA) || !isshuttleturf(src)) return move_mode return move_mode | MOVE_TURF | MOVE_CONTENTS // Called from the new turf before anything has been moved // Only gets called if fromShuttleMove returns true first // returns the new move_mode (based on the old) /turf/proc/toShuttleMove(turf/oldT, move_mode, obj/docking_port/mobile/shuttle) . = move_mode if(!(. & MOVE_TURF)) return var/shuttle_dir = shuttle.dir for(var/i in contents) var/atom/movable/thing = i if(ismob(thing)) if(isliving(thing)) var/mob/living/M = thing if(M.buckled) M.buckled.unbuckle_mob(M, 1) if(M.pulledby) M.pulledby.stop_pulling() M.stop_pulling() M.visible_message("[shuttle] slams into [M]!") SSblackbox.record_feedback("tally", "shuttle_gib", 1, M.type) M.gib() else //non-living mobs shouldn't be affected by shuttles, which is why this is an else if(istype(thing, /obj/singularity) && !istype(thing, /obj/singularity/narsie)) //it's a singularity but not a god, ignore it. continue if(!thing.anchored) step(thing, shuttle_dir) else qdel(thing) // Called on the old turf to move the turf data /turf/proc/onShuttleMove(turf/newT, list/movement_force, move_dir) if(newT == src) // In case of in place shuttle rotation shenanigans. return //Destination turf changes //Baseturfs is definitely a list or this proc wouldnt be called var/shuttle_boundary = baseturfs.Find(/turf/baseturf_skipover/shuttle) if(!shuttle_boundary) CRASH("A turf queued to move via shuttle somehow had no skipover in baseturfs. [src]([type]):[loc]") var/depth = baseturfs.len - shuttle_boundary + 1 newT.CopyOnTop(src, 1, depth, TRUE) //Air stuff newT.blocks_air = TRUE newT.air_update_turf(TRUE) blocks_air = TRUE air_update_turf(TRUE) if(isopenturf(newT)) var/turf/open/new_open = newT new_open.copy_air_with_tile(src) return TRUE // Called on the new turf after everything has been moved /turf/proc/afterShuttleMove(turf/oldT, rotation) //Dealing with the turf we left behind oldT.TransferComponents(src) var/shuttle_boundary = baseturfs.Find(/turf/baseturf_skipover/shuttle) if(shuttle_boundary) oldT.ScrapeAway(baseturfs.len - shuttle_boundary + 1) if(rotation) shuttleRotate(rotation) //see shuttle_rotate.dm return TRUE /turf/proc/lateShuttleMove(turf/oldT) blocks_air = initial(blocks_air) air_update_turf(TRUE) oldT.blocks_air = initial(oldT.blocks_air) oldT.air_update_turf(TRUE) ///////////////////////////////////////////////////////////////////////////////////// // Called on every atom in shuttle turf contents before anything has been moved // returns the new move_mode (based on the old) // WARNING: Do not leave turf contents in beforeShuttleMove or dock() will runtime /atom/movable/proc/beforeShuttleMove(turf/newT, rotation, move_mode, obj/docking_port/mobile/moving_dock) return move_mode // Called on atoms to move the atom to the new location /atom/movable/proc/onShuttleMove(turf/newT, turf/oldT, list/movement_force, move_dir, obj/docking_port/stationary/old_dock, obj/docking_port/mobile/moving_dock) if(newT == oldT) // In case of in place shuttle rotation shenanigans. return if(loc != oldT) // This is for multi tile objects return loc = newT return TRUE // Called on atoms after everything has been moved /atom/movable/proc/afterShuttleMove(turf/oldT, list/movement_force, shuttle_dir, shuttle_preferred_direction, move_dir, rotation) var/turf/newT = get_turf(src) if (newT.z != oldT.z) onTransitZ(oldT.z, newT.z) if(light) update_light() if(rotation) shuttleRotate(rotation) update_parallax_contents() return TRUE /atom/movable/proc/lateShuttleMove(turf/oldT, list/movement_force, move_dir) if(!movement_force || anchored) return var/throw_force = movement_force["THROW"] if(!throw_force) return var/turf/target = get_edge_target_turf(src, move_dir) var/range = throw_force * 10 range = CEILING(rand(range-(range*0.1), range+(range*0.1)), 10)/10 var/speed = range/5 throw_at(target, range, speed) ///////////////////////////////////////////////////////////////////////////////////// // Called on areas before anything has been moved // returns the new move_mode (based on the old) /area/proc/beforeShuttleMove(list/shuttle_areas) if(!shuttle_areas[src]) return NONE return MOVE_AREA // Called on areas to move their turf between areas /area/proc/onShuttleMove(turf/oldT, turf/newT, area/underlying_old_area) if(newT == oldT) // In case of in place shuttle rotation shenanigans. return TRUE contents -= oldT underlying_old_area.contents += oldT oldT.change_area(src, underlying_old_area) //The old turf has now been given back to the area that turf originaly belonged to var/area/old_dest_area = newT.loc parallax_movedir = old_dest_area.parallax_movedir old_dest_area.contents -= newT contents += newT newT.change_area(old_dest_area, src) return TRUE // Called on areas after everything has been moved /area/proc/afterShuttleMove(new_parallax_dir) parallax_movedir = new_parallax_dir return TRUE /area/proc/lateShuttleMove() return /************************************Turf move procs************************************/ /************************************Area move procs************************************/ /************************************Machinery move procs************************************/ /obj/machinery/door/airlock/beforeShuttleMove(turf/newT, rotation, move_mode, obj/docking_port/mobile/moving_dock) . = ..() for(var/obj/machinery/door/airlock/A in range(1, src)) // includes src A.shuttledocked = FALSE A.air_tight = TRUE INVOKE_ASYNC(A, /obj/machinery/door/.proc/close) /obj/machinery/door/airlock/afterShuttleMove(turf/oldT, list/movement_force, shuttle_dir, shuttle_preferred_direction, move_dir, rotation) . = ..() for(var/obj/machinery/door/airlock/A in orange(1, src)) // does not include src // Cycle linking is only disabled if we are actually adjacent to another airlock shuttledocked = TRUE A.shuttledocked = TRUE /obj/machinery/camera/beforeShuttleMove(turf/newT, rotation, move_mode, obj/docking_port/mobile/moving_dock) . = ..() if(. & MOVE_AREA) . |= MOVE_CONTENTS GLOB.cameranet.removeCamera(src) /obj/machinery/camera/afterShuttleMove(turf/oldT, list/movement_force, shuttle_dir, shuttle_preferred_direction, move_dir, rotation) . = ..() GLOB.cameranet.addCamera(src) /obj/machinery/mech_bay_recharge_port/afterShuttleMove(turf/oldT, list/movement_force, shuttle_dir, shuttle_preferred_direction, move_dir) . = ..() recharging_turf = get_step(loc, dir) /obj/machinery/atmospherics/afterShuttleMove(turf/oldT, list/movement_force, shuttle_dir, shuttle_preferred_direction, move_dir, rotation) . = ..() if(pipe_vision_img) pipe_vision_img.loc = loc /obj/machinery/computer/auxillary_base/afterShuttleMove(turf/oldT, list/movement_force, shuttle_dir, shuttle_preferred_direction, move_dir, rotation) . = ..() if(is_mining_level(z)) //Avoids double logging and landing on other Z-levels due to badminnery SSblackbox.record_feedback("associative", "colonies_dropped", 1, list("x" = x, "y" = y, "z" = z)) /obj/machinery/gravity_generator/main/beforeShuttleMove(turf/newT, rotation, move_mode, obj/docking_port/mobile/moving_dock) . = ..() on = FALSE update_list() /obj/machinery/gravity_generator/main/afterShuttleMove(turf/oldT, list/movement_force, shuttle_dir, shuttle_preferred_direction, move_dir, rotation) . = ..() if(charge_count != 0 && charging_state != POWER_UP) on = TRUE update_list() /obj/machinery/atmospherics/afterShuttleMove(turf/oldT, list/movement_force, shuttle_dir, shuttle_preferred_direction, move_dir, rotation) . = ..() var/missing_nodes = FALSE for(var/i in 1 to device_type) if(nodes[i]) var/obj/machinery/atmospherics/node = nodes[i] var/connected = FALSE for(var/D in GLOB.cardinals) if(node in get_step(src, D)) connected = TRUE break if(!connected) nullifyNode(i) if(!nodes[i]) missing_nodes = TRUE if(missing_nodes) atmosinit() for(var/obj/machinery/atmospherics/A in pipeline_expansion()) A.atmosinit() if(A.returnPipenet()) A.addMember(src) build_network() else // atmosinit() calls update_icon(), so we don't need to call it update_icon() /obj/machinery/atmospherics/pipe/afterShuttleMove(turf/oldT, list/movement_force, shuttle_dir, shuttle_preferred_direction, move_dir, rotation) . = ..() var/turf/T = loc hide(T.intact) /obj/machinery/navbeacon/beforeShuttleMove(turf/newT, rotation, move_mode, obj/docking_port/mobile/moving_dock) . = ..() GLOB.navbeacons["[z]"] -= src GLOB.deliverybeacons -= src /obj/machinery/navbeacon/afterShuttleMove(turf/oldT, list/movement_force, shuttle_dir, shuttle_preferred_direction, move_dir, rotation) . = ..() var/turf/T = loc hide(T.intact) if(codes["patrol"]) if(!GLOB.navbeacons["[z]"]) GLOB.navbeacons["[z]"] = list() GLOB.navbeacons["[z]"] += src //Register with the patrol list! if(codes["delivery"]) GLOB.deliverybeacons += src GLOB.deliverybeacontags += location /obj/machinery/power/terminal/afterShuttleMove(turf/oldT, list/movement_force, shuttle_dir, shuttle_preferred_direction, move_dir, rotation) . = ..() var/turf/T = src.loc if(level==1) hide(T.intact) /************************************Item move procs************************************/ /obj/item/storage/pod/afterShuttleMove(turf/oldT, list/movement_force, shuttle_dir, shuttle_preferred_direction, move_dir, rotation) . = ..() // If the pod was launched, the storage will always open. The CentCom check // ignores the movement of the shuttle from the staging area on CentCom to // the station as it is loaded in. if (oldT && !is_centcom_level(oldT.z)) unlocked = TRUE /************************************Mob move procs************************************/ /mob/onShuttleMove(turf/newT, turf/oldT, list/movement_force, move_dir, obj/docking_port/stationary/old_dock, obj/docking_port/mobile/moving_dock) if(!move_on_shuttle) return . = ..() /mob/afterShuttleMove(turf/oldT, list/movement_force, shuttle_dir, shuttle_preferred_direction, move_dir, rotation) if(!move_on_shuttle) return . = ..() if(client && movement_force) var/shake_force = max(movement_force["THROW"], movement_force["KNOCKDOWN"]) if(buckled) shake_force *= 0.25 shake_camera(src, shake_force, 1) /mob/living/lateShuttleMove(turf/oldT, list/movement_force, move_dir) if(buckled) return . = ..() var/knockdown = movement_force["KNOCKDOWN"] if(knockdown) Knockdown(knockdown) /mob/living/simple_animal/hostile/megafauna/onShuttleMove(turf/newT, turf/oldT, list/movement_force, move_dir, obj/docking_port/stationary/old_dock, obj/docking_port/mobile/moving_dock) . = ..() message_admins("Megafauna [src] [ADMIN_FLW(src)] moved via shuttle from [ADMIN_COORDJMP(oldT)] to [ADMIN_COORDJMP(loc)]") /************************************Structure move procs************************************/ /obj/structure/grille/beforeShuttleMove(turf/newT, rotation, move_mode, obj/docking_port/mobile/moving_dock) . = ..() if(. & MOVE_AREA) . |= MOVE_CONTENTS /obj/structure/lattice/beforeShuttleMove(turf/newT, rotation, move_mode, obj/docking_port/mobile/moving_dock) . = ..() if(. & MOVE_AREA) . |= MOVE_CONTENTS /obj/structure/disposalpipe/afterShuttleMove(turf/oldT, list/movement_force, shuttle_dir, shuttle_preferred_direction, move_dir, rotation) . = ..() update() /obj/structure/cable/afterShuttleMove(turf/oldT, list/movement_force, shuttle_dir, shuttle_preferred_direction, move_dir, rotation) . = ..() var/turf/T = loc if(level==1) hide(T.intact) /obj/structure/shuttle/beforeShuttleMove(turf/newT, rotation, move_mode, obj/docking_port/mobile/moving_dock) . = ..() if(. & MOVE_AREA) . |= MOVE_CONTENTS /obj/structure/ladder/beforeShuttleMove(turf/newT, rotation, move_mode, obj/docking_port/mobile/moving_dock) . = ..() if (!(resistance_flags & INDESTRUCTIBLE)) disconnect() /obj/structure/ladder/afterShuttleMove(turf/oldT, list/movement_force, shuttle_dir, shuttle_preferred_direction, move_dir, rotation) . = ..() if (!(resistance_flags & INDESTRUCTIBLE)) LateInitialize() /obj/structure/ladder/onShuttleMove(turf/newT, turf/oldT, list/movement_force, move_dir, obj/docking_port/stationary/old_dock, obj/docking_port/mobile/moving_dock) if (resistance_flags & INDESTRUCTIBLE) // simply don't be moved return FALSE return ..() /************************************Misc move procs************************************/ /atom/movable/lighting_object/onShuttleMove() return FALSE /obj/docking_port/mobile/beforeShuttleMove(turf/newT, rotation, move_mode, obj/docking_port/mobile/moving_dock) . = ..() if(moving_dock == src) . |= MOVE_CONTENTS /obj/docking_port/stationary/onShuttleMove(turf/newT, turf/oldT, list/movement_force, move_dir, obj/docking_port/stationary/old_dock, obj/docking_port/mobile/moving_dock) if(!moving_dock.can_move_docking_ports || old_dock == src) return FALSE . = ..() /obj/docking_port/stationary/public_mining_dock/onShuttleMove(turf/newT, turf/oldT, list/movement_force, move_dir, obj/docking_port/stationary/old_dock, obj/docking_port/mobile/moving_dock) id = "mining_public" //It will not move with the base, but will become enabled as a docking point. /obj/effect/abstract/proximity_checker/onShuttleMove(turf/newT, turf/oldT, list/movement_force, move_dir, obj/docking_port/stationary/old_dock, obj/docking_port/mobile/moving_dock) //timer so it only happens once addtimer(CALLBACK(monitor, /datum/proximity_monitor/proc/SetRange, monitor.current_range, TRUE), 0, TIMER_UNIQUE)