mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2026-08-23 05:00:55 +01:00
Orbits are now a subsystem (#20632)
* Sleepless perfect orbits #MOGA We bind to Moved() and use datums and lists to track the orbits, no more sleeps, no more delay. * Adds some null checks to orbit checks * Forget to set orbiting. Also sets orbiters before orbiting, to avoid edge cases of deleting a list then recreating it. * Improves orbit, adds subsystem for orbits. Most orbit loc changes will happen on move, subsystem runs every 2 ticks to make up for when that isn't the case.
This commit is contained in:
committed by
oranges
parent
fa5c08442d
commit
f71dc2c9a3
@@ -1006,65 +1006,6 @@ B --><-- A
|
||||
*/
|
||||
|
||||
|
||||
//This is just so you can stop an orbit.
|
||||
//orbit() can run without it (swap orbiting for A)
|
||||
//but then you can never stop it and that's just silly.
|
||||
/atom/movable/var/atom/orbiting = null
|
||||
|
||||
//A: atom to orbit
|
||||
//radius: range to orbit at, radius of the circle formed by orbiting
|
||||
//clockwise: whether you orbit clockwise or anti clockwise
|
||||
//rotation_speed: how fast to rotate
|
||||
//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
|
||||
|
||||
if(orbiting)
|
||||
stop_orbit()
|
||||
|
||||
orbiting = A
|
||||
var/matrix/initial_transform = matrix(transform)
|
||||
var/lastloc = loc
|
||||
|
||||
//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
|
||||
while(orbiting && orbiting == A && A.loc)
|
||||
var/targetloc = get_turf(A)
|
||||
if(!lockinorbit && loc != lastloc && loc != targetloc)
|
||||
break
|
||||
loc = targetloc
|
||||
lastloc = loc
|
||||
stoplag()
|
||||
|
||||
if (orbiting == A) //make sure we haven't started orbiting something else.
|
||||
orbiting = null
|
||||
SpinAnimation(0,0)
|
||||
|
||||
|
||||
|
||||
/atom/movable/proc/stop_orbit()
|
||||
orbiting = null
|
||||
|
||||
|
||||
//Center's an image.
|
||||
//Requires:
|
||||
//The Image
|
||||
|
||||
@@ -0,0 +1,50 @@
|
||||
var/datum/subsystem/orbit/SSorbit
|
||||
|
||||
/datum/subsystem/orbit
|
||||
name = "Orbits"
|
||||
priority = 35
|
||||
wait = 2
|
||||
flags = SS_NO_INIT|SS_TICKER
|
||||
|
||||
var/list/currentrun = list()
|
||||
var/list/processing = list()
|
||||
|
||||
/datum/subsystem/orbit/New()
|
||||
NEW_SS_GLOBAL(SSorbit)
|
||||
|
||||
|
||||
/datum/subsystem/orbit/stat_entry()
|
||||
..("P:[processing.len]")
|
||||
|
||||
|
||||
/datum/subsystem/orbit/fire(resumed = 0)
|
||||
if (!resumed)
|
||||
src.currentrun = processing.Copy()
|
||||
|
||||
//cache for sanic speed (lists are references anyways)
|
||||
var/list/currentrun = src.currentrun
|
||||
|
||||
while (currentrun.len)
|
||||
var/datum/orbit/O = currentrun[currentrun.len]
|
||||
currentrun.len--
|
||||
if (!O)
|
||||
processing -= O
|
||||
if (MC_TICK_CHECK)
|
||||
return
|
||||
continue
|
||||
if (!O.orbiter)
|
||||
qdel(O)
|
||||
if (MC_TICK_CHECK)
|
||||
return
|
||||
continue
|
||||
if (O.lastprocess >= world.time) //we already checked recently
|
||||
if (MC_TICK_CHECK)
|
||||
return
|
||||
continue
|
||||
var/targetloc = get_turf(O.orbiting)
|
||||
if (targetloc != O.lastloc || O.orbiter.loc != targetloc)
|
||||
O.Check(targetloc)
|
||||
if (MC_TICK_CHECK)
|
||||
return
|
||||
|
||||
|
||||
@@ -95,7 +95,7 @@
|
||||
</span>"
|
||||
|
||||
if(wisp.orbiting)
|
||||
var/atom/A = wisp.orbiting
|
||||
var/atom/A = wisp.orbiting.orbiting
|
||||
if(istype(A, /mob/living))
|
||||
var/mob/living/M = A
|
||||
M.sight &= ~SEE_MOBS
|
||||
@@ -534,8 +534,15 @@
|
||||
var/turf/T = get_turf(src)
|
||||
var/list/contents = T.GetAllContents()
|
||||
var/mob/dead/observer/current_spirits = list()
|
||||
for(var/mob/dead/observer/G in dead_mob_list)
|
||||
if(G.orbiting in contents)
|
||||
var/list/orbiters = list()
|
||||
for(var/thing in contents)
|
||||
var/atom/A = thing
|
||||
if (A.orbiters)
|
||||
orbiters += A.orbiters
|
||||
|
||||
for(var/thing in orbiters)
|
||||
if (isobserver(thing))
|
||||
var/mob/dead/observer/G = thing
|
||||
ghost_counter++
|
||||
G.invisibility = 0
|
||||
current_spirits |= G
|
||||
|
||||
@@ -383,7 +383,7 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
|
||||
var/orbitsize = (I.Width()+I.Height())*0.5
|
||||
orbitsize -= (orbitsize/world.icon_size)*(world.icon_size*0.25)
|
||||
|
||||
if(orbiting != target)
|
||||
if(orbiting && orbiting.orbiting != target)
|
||||
src << "<span class='notice'>Now orbiting [target].</span>"
|
||||
|
||||
var/rot_seg
|
||||
@@ -403,13 +403,14 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
|
||||
orbit(target,orbitsize, FALSE, 20, rot_seg)
|
||||
|
||||
/mob/dead/observer/orbit()
|
||||
setDir(2 )//reset dir so the right directional sprites show up
|
||||
setDir(2)//reset dir so the right directional sprites show up
|
||||
..()
|
||||
|
||||
/mob/dead/observer/stop_orbit()
|
||||
..()
|
||||
//restart our floating animation after orbit is done.
|
||||
sleep 2 //orbit sets up a 2ds animation when it finishes, so we wait for that to end
|
||||
if (!orbiting) //make sure another orbit hasn't started
|
||||
pixel_y = 0
|
||||
animate(src, pixel_y = 2, time = 10, loop = -1)
|
||||
pixel_y = 0
|
||||
animate(src, pixel_y = 2, time = 10, loop = -1)
|
||||
|
||||
/mob/dead/observer/verb/jumptomob() //Moves the ghost instead of just changing the ghosts's eye -Nodrak
|
||||
set category = "Ghost"
|
||||
|
||||
@@ -0,0 +1,121 @@
|
||||
/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
|
||||
..()
|
||||
|
||||
/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
|
||||
lastloc = orbiter.loc
|
||||
|
||||
|
||||
/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/movable/Moved(atom/OldLoc, Dir)
|
||||
..()
|
||||
if (orbiters)
|
||||
for (var/thing in orbiters)
|
||||
var/datum/orbit/O = thing
|
||||
O.Check()
|
||||
if (orbiting)
|
||||
orbiting.Check()
|
||||
|
||||
/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()
|
||||
@@ -43,10 +43,9 @@ var/list/blacklisted_tesla_types = typecacheof(list(/obj/machinery/atmospherics,
|
||||
return
|
||||
|
||||
/obj/singularity/energy_ball/Destroy()
|
||||
if(orbiting && istype(orbiting, /obj/singularity/energy_ball))
|
||||
var/obj/singularity/energy_ball/EB = orbiting
|
||||
if(orbiting && istype(orbiting.orbiting, /obj/singularity/energy_ball))
|
||||
var/obj/singularity/energy_ball/EB = orbiting.orbiting
|
||||
EB.orbiting_balls -= src
|
||||
orbiting = null
|
||||
|
||||
for(var/ball in orbiting_balls)
|
||||
var/obj/singularity/energy_ball/EB = ball
|
||||
@@ -140,13 +139,16 @@ var/list/blacklisted_tesla_types = typecacheof(list(/obj/machinery/atmospherics,
|
||||
target.dissipate_strength = target.orbiting_balls.len
|
||||
|
||||
. = ..()
|
||||
|
||||
if (istype(target))
|
||||
target.orbiting_balls -= src
|
||||
target.dissipate_strength = target.orbiting_balls.len
|
||||
/obj/singularity/energy_ball/stop_orbit()
|
||||
if (orbiting && istype(orbiting.orbiting, /obj/singularity/energy_ball))
|
||||
var/obj/singularity/energy_ball/orbitingball = orbiting.orbiting
|
||||
orbitingball.orbiting_balls -= src
|
||||
orbitingball.dissipate_strength = orbitingball.orbiting_balls.len
|
||||
..()
|
||||
if (!loc)
|
||||
qdel(src)
|
||||
|
||||
|
||||
/obj/singularity/energy_ball/proc/dust_mobs(atom/A)
|
||||
if(istype(A, /mob/living/carbon))
|
||||
var/mob/living/carbon/C = A
|
||||
|
||||
@@ -150,6 +150,7 @@
|
||||
#include "code\controllers\subsystem\minimap.dm"
|
||||
#include "code\controllers\subsystem\mobs.dm"
|
||||
#include "code\controllers\subsystem\npcpool.dm"
|
||||
#include "code\controllers\subsystem\orbit.dm"
|
||||
#include "code\controllers\subsystem\pai.dm"
|
||||
#include "code\controllers\subsystem\persistence.dm"
|
||||
#include "code\controllers\subsystem\pool.dm"
|
||||
@@ -1602,6 +1603,7 @@
|
||||
#include "code\modules\ninja\suit\n_suit_verbs\ninja_stealth.dm"
|
||||
#include "code\modules\ninja\suit\n_suit_verbs\ninja_sword_recall.dm"
|
||||
#include "code\modules\ninja\suit\n_suit_verbs\ninja_teleporting.dm"
|
||||
#include "code\modules\orbit\orbit.dm"
|
||||
#include "code\modules\paperwork\clipboard.dm"
|
||||
#include "code\modules\paperwork\contract.dm"
|
||||
#include "code\modules\paperwork\filingcabinet.dm"
|
||||
|
||||
Reference in New Issue
Block a user