mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2026-07-11 16:14:08 +01:00
21b4095dfd
Upstream 04/17/2026 fixes https://github.com/Bubberstation/Bubberstation/issues/5549 --------- Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: tgstation-ci[bot] <179393467+tgstation-ci[bot]@users.noreply.github.com> Co-authored-by: ArcaneMusic <41715314+ArcaneMusic@users.noreply.github.com> Co-authored-by: MrMelbert <51863163+MrMelbert@users.noreply.github.com> Co-authored-by: Rhials <28870487+Rhials@users.noreply.github.com> Co-authored-by: rageguy505 <54517726+rageguy505@users.noreply.github.com> Co-authored-by: LemonInTheDark <58055496+LemonInTheDark@users.noreply.github.com> Co-authored-by: John Willard <53777086+JohnFulpWillard@users.noreply.github.com> Co-authored-by: Aliceee2ch <160794176+Aliceee2ch@users.noreply.github.com> Co-authored-by: Time-Green <7501474+Time-Green@users.noreply.github.com> Co-authored-by: Tsar-Salat <62388554+Tsar-Salat@users.noreply.github.com> Co-authored-by: SmArtKar <44720187+SmArtKar@users.noreply.github.com> Co-authored-by: Maxipat <108554989+Maxipat112@users.noreply.github.com> Co-authored-by: SyncIt21 <110812394+SyncIt21@users.noreply.github.com> Co-authored-by: deltanedas <39013340+deltanedas@users.noreply.github.com> Co-authored-by: SimplyLogan <47579821+loganuk@users.noreply.github.com> Co-authored-by: loganuk <fakeemail123@aol.com> Co-authored-by: Leland Kemble <70413276+lelandkemble@users.noreply.github.com> Co-authored-by: FalloutFalcon <86381784+FalloutFalcon@users.noreply.github.com> Co-authored-by: Roxy <75404941+TealSeer@users.noreply.github.com> Co-authored-by: Lucy <lucy@absolucy.moe> Co-authored-by: siliconOpossum <138069572+siliconOpossum@users.noreply.github.com> Co-authored-by: Isratosh <Isratosh@hotmail.com> Co-authored-by: TheRyeGuyWhoWillNowDie <70169560+TheRyeGuyWhoWillNowDie@users.noreply.github.com> Co-authored-by: Neocloudy <88008002+Neocloudy@users.noreply.github.com> Co-authored-by: Alexander V. <volas@ya.ru> Co-authored-by: ElGitificador <168473461+ElGitificador@users.noreply.github.com> Co-authored-by: Twaticus <46540570+Twaticus@users.noreply.github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Bloop <13398309+vinylspiders@users.noreply.github.com> Co-authored-by: Cameron Lennox <killer65311@gmail.com> Co-authored-by: Tim <timothymtorres@gmail.com> Co-authored-by: Iamgoofball <iamgoofball@gmail.com> Co-authored-by: Layzu666 <121319428+Layzu666@users.noreply.github.com> Co-authored-by: Arturlang <24881678+Arturlang@users.noreply.github.com> Co-authored-by: _0Steven <42909981+00-Steven@users.noreply.github.com> Co-authored-by: mrmanlikesbt <99309552+mrmanlikesbt@users.noreply.github.com> Co-authored-by: Ben10Omintrix <138636438+Ben10Omintrix@users.noreply.github.com> Co-authored-by: John F. Kennedy <54908920+MacaroniCritter@users.noreply.github.com> Co-authored-by: Cursor <102828457+theselfish@users.noreply.github.com> Co-authored-by: Josh <josh.adam.powell@gmail.com> Co-authored-by: Josh Powell <josh.powell@softwire.com> Co-authored-by: Yobrocharlie <Charliemiller5617@gmail.com> Co-authored-by: Hardly3D <66234359+Hardly3D@users.noreply.github.com> Co-authored-by: shayoki <96078776+shayoki@users.noreply.github.com> Co-authored-by: LT3 <83487515+lessthnthree@users.noreply.github.com>
213 lines
8.0 KiB
Plaintext
213 lines
8.0 KiB
Plaintext
/datum/component/orbiter
|
|
can_transfer = TRUE
|
|
dupe_mode = COMPONENT_DUPE_UNIQUE_PASSARGS
|
|
/// Assoc list of all orbiters -> their initial matrix
|
|
var/list/orbiter_list
|
|
/// Assoc list of orbiters -> their orbiting parameters
|
|
var/list/orbiter_params
|
|
/// Movement tracker used to check when our owner moves
|
|
var/datum/movement_detector/tracker
|
|
|
|
//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
|
|
/datum/component/orbiter/Initialize(atom/movable/orbiter, radius, clockwise, rotation_speed, rotation_segments, pre_rotation)
|
|
if(!istype(orbiter) || !isatom(parent) || isarea(parent))
|
|
return COMPONENT_INCOMPATIBLE
|
|
|
|
orbiter_list = list()
|
|
orbiter_params = list()
|
|
|
|
begin_orbit(orbiter, radius, clockwise, rotation_speed, rotation_segments, pre_rotation)
|
|
|
|
/datum/component/orbiter/RegisterWithParent()
|
|
var/atom/target = parent
|
|
|
|
target.orbiters = src
|
|
if(ismovable(target))
|
|
tracker = new(target, CALLBACK(src, PROC_REF(move_react)))
|
|
|
|
RegisterSignal(parent, COMSIG_MOVABLE_UPDATE_GLIDE_SIZE, PROC_REF(orbiter_glide_size_update))
|
|
|
|
/datum/component/orbiter/UnregisterFromParent()
|
|
UnregisterSignal(parent, COMSIG_MOVABLE_UPDATE_GLIDE_SIZE)
|
|
var/atom/target = parent
|
|
target.orbiters = null
|
|
QDEL_NULL(tracker)
|
|
|
|
/datum/component/orbiter/Destroy()
|
|
var/atom/master = parent
|
|
if(master.orbiters == src)
|
|
master.orbiters = null
|
|
for(var/i in orbiter_list)
|
|
end_orbit(i)
|
|
orbiter_list = null
|
|
orbiter_params = null
|
|
return ..()
|
|
|
|
/datum/component/orbiter/InheritComponent(datum/component/orbiter/newcomp, original, atom/movable/orbiter, radius, clockwise, rotation_speed, rotation_segments, pre_rotation)
|
|
if(!newcomp)
|
|
begin_orbit(arglist(args.Copy(3)))
|
|
return
|
|
// The following only happens on component transfers
|
|
for(var/o in newcomp.orbiter_list)
|
|
var/atom/movable/incoming_orbiter = o
|
|
incoming_orbiter.orbiting = src
|
|
// It is important to transfer the signals so we don't get locked to the new orbiter component for all time
|
|
newcomp.UnregisterSignal(incoming_orbiter, list(COMSIG_MOVABLE_MOVED, COMSIG_ATOM_BEFORE_SHUTTLE_MOVE, COMSIG_ATOM_AFTER_SHUTTLE_MOVE))
|
|
RegisterSignal(incoming_orbiter, COMSIG_MOVABLE_MOVED, PROC_REF(orbiter_move_react))
|
|
RegisterSignal(incoming_orbiter, COMSIG_ATOM_BEFORE_SHUTTLE_MOVE, PROC_REF(orbiter_before_shuttle_move))
|
|
|
|
orbiter_list += newcomp.orbiter_list
|
|
orbiter_params += newcomp.orbiter_params
|
|
newcomp.orbiter_list = null
|
|
newcomp.orbiter_params = null
|
|
|
|
/datum/component/orbiter/PostTransfer(datum/new_parent)
|
|
if(!isatom(new_parent) || isarea(new_parent) || !get_turf(new_parent))
|
|
return COMPONENT_INCOMPATIBLE
|
|
move_react(new_parent)
|
|
|
|
/datum/component/orbiter/proc/begin_orbit(atom/movable/orbiter, radius, clockwise, rotation_speed, rotation_segments, pre_rotation)
|
|
if(orbiter.orbiting)
|
|
if(orbiter.orbiting == src)
|
|
orbiter.orbiting.end_orbit(orbiter, TRUE)
|
|
else
|
|
orbiter.orbiting.end_orbit(orbiter)
|
|
|
|
orbiter_params[orbiter] = args.Copy(2)
|
|
orbiter_list[orbiter] = TRUE
|
|
orbiter.orbiting = src
|
|
|
|
ADD_TRAIT(orbiter, TRAIT_NO_FLOATING_ANIM, ORBITING_TRAIT)
|
|
RegisterSignal(orbiter, COMSIG_MOVABLE_MOVED, PROC_REF(orbiter_move_react))
|
|
RegisterSignal(orbiter, COMSIG_ATOM_BEFORE_SHUTTLE_MOVE, PROC_REF(orbiter_before_shuttle_move))
|
|
|
|
SEND_SIGNAL(parent, COMSIG_ATOM_ORBIT_BEGIN, orbiter)
|
|
|
|
var/matrix/initial_transform = matrix(orbiter.transform)
|
|
orbiter_list[orbiter] = initial_transform
|
|
|
|
// Head first!
|
|
if(pre_rotation)
|
|
var/matrix/M = matrix(orbiter.transform)
|
|
var/pre_rot = 90
|
|
if(!clockwise)
|
|
pre_rot = -90
|
|
M.Turn(pre_rot)
|
|
orbiter.transform = M
|
|
|
|
var/matrix/shift = matrix(orbiter.transform)
|
|
shift.Translate(0, radius)
|
|
orbiter.transform = shift
|
|
|
|
orbiter.SpinAnimation(rotation_speed, -1, clockwise, rotation_segments, parallel = FALSE)
|
|
|
|
if(ismob(orbiter))
|
|
var/mob/orbiter_mob = orbiter
|
|
orbiter_mob.updating_glide_size = FALSE
|
|
if(ismovable(parent))
|
|
var/atom/movable/movable_parent = parent
|
|
orbiter.glide_size = movable_parent.glide_size
|
|
|
|
orbiter.abstract_move(get_turf(parent))
|
|
to_chat(orbiter, span_notice("Now orbiting [parent]."))
|
|
|
|
/datum/component/orbiter/proc/orbiter_before_shuttle_move(atom/source)
|
|
SIGNAL_HANDLER
|
|
// We need to detach ourselves before the shuttle moves and reattach afterwards
|
|
end_orbit(source, TRUE)
|
|
RegisterSignal(source, COMSIG_ATOM_AFTER_SHUTTLE_MOVE, PROC_REF(orbiter_after_shuttle_move))
|
|
|
|
/datum/component/orbiter/proc/orbiter_after_shuttle_move(atom/source)
|
|
SIGNAL_HANDLER
|
|
UnregisterSignal(source, COMSIG_ATOM_AFTER_SHUTTLE_MOVE)
|
|
begin_orbit(arglist(list(source) + orbiter_params[source]))
|
|
|
|
/datum/component/orbiter/proc/end_orbit(atom/movable/orbiter, refreshing = FALSE)
|
|
if(!orbiter_list[orbiter])
|
|
return
|
|
UnregisterSignal(orbiter, list(COMSIG_MOVABLE_MOVED, COMSIG_ATOM_BEFORE_SHUTTLE_MOVE, COMSIG_ATOM_AFTER_SHUTTLE_MOVE))
|
|
SEND_SIGNAL(parent, COMSIG_ATOM_ORBIT_STOP, orbiter)
|
|
orbiter.SpinAnimation(0, 0)
|
|
if(istype(orbiter_list[orbiter],/matrix)) //This is ugly.
|
|
orbiter.transform = orbiter_list[orbiter]
|
|
orbiter_list -= orbiter
|
|
if(!refreshing)
|
|
orbiter_params -= orbiter
|
|
orbiter.stop_orbit(src, refreshing)
|
|
orbiter.orbiting = null
|
|
|
|
if(ismob(orbiter))
|
|
var/mob/orbiter_mob = orbiter
|
|
orbiter_mob.updating_glide_size = TRUE
|
|
orbiter_mob.glide_size = 8
|
|
|
|
if(isobserver(orbiter))
|
|
var/mob/dead/observer/ghostie = orbiter
|
|
ghostie.orbiting_ref = null
|
|
|
|
REMOVE_TRAIT(orbiter, TRAIT_NO_FLOATING_ANIM, ORBITING_TRAIT)
|
|
|
|
if(!refreshing && !length(orbiter_list) && !QDELING(src))
|
|
qdel(src)
|
|
|
|
// This proc can receive signals by either the thing being directly orbited or anything holding it
|
|
/datum/component/orbiter/proc/move_react(atom/movable/master, atom/mover, atom/oldloc, direction)
|
|
set waitfor = FALSE // Transfer calls this directly and it doesnt care if the ghosts arent done moving
|
|
|
|
if(master.loc == oldloc)
|
|
return
|
|
|
|
var/turf/newturf = get_turf(master)
|
|
if(!newturf)
|
|
qdel(src)
|
|
|
|
var/atom/curloc = master.loc
|
|
for(var/atom/movable/movable_orbiter as anything in orbiter_list)
|
|
if(QDELETED(movable_orbiter) || movable_orbiter.loc == newturf)
|
|
continue
|
|
movable_orbiter.abstract_move(newturf)
|
|
if(CHECK_TICK && master.loc != curloc)
|
|
// We moved again during the checktick, cancel current operation
|
|
break
|
|
|
|
|
|
/datum/component/orbiter/proc/orbiter_move_react(atom/movable/orbiter, atom/oldloc, direction)
|
|
SIGNAL_HANDLER
|
|
|
|
if(orbiter.loc == get_turf(parent))
|
|
return
|
|
end_orbit(orbiter)
|
|
|
|
/datum/component/orbiter/proc/orbiter_glide_size_update(datum/source, target)
|
|
SIGNAL_HANDLER
|
|
for(var/orbiter in orbiter_list)
|
|
var/atom/movable/movable_orbiter = orbiter
|
|
movable_orbiter.glide_size = target
|
|
|
|
/////////////////////
|
|
|
|
/atom/movable/proc/orbit(atom/A, radius = 10, clockwise = FALSE, rotation_speed = 20, rotation_segments = 36, pre_rotation = TRUE)
|
|
if(!istype(A) || !get_turf(A) || A == src)
|
|
return
|
|
if (HAS_TRAIT(A, TRAIT_ORBITING_FORBIDDEN))
|
|
// Stealth-mins have an empty name, don't want "You cannot orbit at this time."
|
|
to_chat(src, span_notice("You cannot orbit ["[A]" || "them"] at this time."))
|
|
return
|
|
orbit_target = A
|
|
return A.AddComponent(/datum/component/orbiter, src, radius, clockwise, rotation_speed, rotation_segments, pre_rotation)
|
|
|
|
/atom/movable/proc/stop_orbit(datum/component/orbiter/orbits, refreshing = FALSE)
|
|
if(refreshing)
|
|
return //Only null the target if we're actually stopping the orbit for real, not if we're merely shuttle moving(or orbiting the same thing again). We will never get it back unless the orbit is fully deleted and reinstated.
|
|
orbit_target = null
|
|
|
|
|
|
/atom/proc/transfer_observers_to(atom/target)
|
|
if(!orbiters || !istype(target) || !get_turf(target) || target == src)
|
|
return
|
|
target.TakeComponent(orbiters)
|