diff --git a/code/modules/orbit/orbit.dm b/code/modules/orbit/orbit.dm index 27fc2d86df..600042a827 100644 --- a/code/modules/orbit/orbit.dm +++ b/code/modules/orbit/orbit.dm @@ -1,3 +1,4 @@ +<<<<<<< HEAD /datum/orbit var/atom/movable/orbiter var/atom/orbiting @@ -110,3 +111,119 @@ . = ..() if (orbiting) stop_orbit() +======= +/datum/orbit + var/atom/movable/orbiter + var/atom/orbiting + var/lock = TRUE + var/turf/lastloc + var/lastprocess + +/datum/orbit/New(_orbiter, _orbiting, _lock) + orbiter = _orbiter + orbiting = _orbiting + SSorbit.processing += src + if (!orbiting.orbiters) + orbiting.orbiters = list() + orbiting.orbiters += src + + if (orbiter.orbiting) + orbiter.stop_orbit() + orbiter.orbiting = src + Check() + lock = _lock + +//do not qdel directly, use stop_orbit on the orbiter. (This way the orbiter can bind to the orbit stopping) +/datum/orbit/Destroy(force = FALSE) + SSorbit.processing -= src + if (orbiter) + orbiter.orbiting = null + orbiter = null + if (orbiting) + if (orbiting.orbiters) + orbiting.orbiters -= src + if (!orbiting.orbiters.len)//we are the last orbit, delete the list + orbiting.orbiters = null + orbiting = null + return ..() + +/datum/orbit/proc/Check(turf/targetloc) + if (!orbiter) + qdel(src) + return + if (!orbiting) + orbiter.stop_orbit() + return + if (!orbiter.orbiting) //admin wants to stop the orbit. + orbiter.orbiting = src //set it back to us first + orbiter.stop_orbit() + lastprocess = world.time + if (!targetloc) + targetloc = get_turf(orbiting) + if (!targetloc || (!lock && orbiter.loc != lastloc && orbiter.loc != targetloc)) + orbiter.stop_orbit() + return + orbiter.loc = targetloc + orbiter.update_parallax_contents() + lastloc = orbiter.loc + for(var/other_orbit in orbiter.orbiters) + var/datum/orbit/OO = other_orbit + if(OO == src) + continue + OO.Check(targetloc) + +/atom/movable/var/datum/orbit/orbiting = null +/atom/var/list/orbiters = null + +//A: atom to orbit +//radius: range to orbit at, radius of the circle formed by orbiting (in pixels) +//clockwise: whether you orbit clockwise or anti clockwise +//rotation_speed: how fast to rotate (how many ds should it take for a rotation to complete) +//rotation_segments: the resolution of the orbit circle, less = a more block circle, this can be used to produce hexagons (6 segments) triangles (3 segments), and so on, 36 is the best default. +//pre_rotation: Chooses to rotate src 90 degress towards the orbit dir (clockwise/anticlockwise), useful for things to go "head first" like ghosts +//lockinorbit: Forces src to always be on A's turf, otherwise the orbit cancels when src gets too far away (eg: ghosts) + +/atom/movable/proc/orbit(atom/A, radius = 10, clockwise = FALSE, rotation_speed = 20, rotation_segments = 36, pre_rotation = TRUE, lockinorbit = FALSE) + if (!istype(A)) + return + + new/datum/orbit(src, A, lockinorbit) + if (!orbiting) //something failed, and our orbit datum deleted itself + return + var/matrix/initial_transform = matrix(transform) + + //Head first! + if (pre_rotation) + var/matrix/M = matrix(transform) + var/pre_rot = 90 + if(!clockwise) + pre_rot = -90 + M.Turn(pre_rot) + transform = M + + var/matrix/shift = matrix(transform) + shift.Translate(0,radius) + transform = shift + + SpinAnimation(rotation_speed, -1, clockwise, rotation_segments) + + //we stack the orbits up client side, so we can assign this back to normal server side without it breaking the orbit + transform = initial_transform + +/atom/movable/proc/stop_orbit() + SpinAnimation(0,0) + qdel(orbiting) + +/atom/Destroy(force = FALSE) + . = ..() + if (orbiters) + for (var/thing in orbiters) + var/datum/orbit/O = thing + if (O.orbiter) + O.orbiter.stop_orbit() + +/atom/movable/Destroy(force = FALSE) + . = ..() + if (orbiting) + stop_orbit() +>>>>>>> e474c91... Merge pull request #31904 from AnturK/infinite