mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2026-08-30 00:29:02 +01:00
Orbit improvements:
* Orbit is now less reliant on Animate(), for most ghosts this means 36 calls to Animate, vs the previous INFINITE, for those of you with potato computers, this should ease the pain and crashing. * Orbits can now be something different to circles! * Ghosts Byond Members can now choose between orbits! (Circle, Triangle, Square, Hexagon)
This commit is contained in:
@@ -310,3 +310,10 @@ var/list/bloody_footprints_cache = list()
|
||||
#define FIRE_PROOF -1
|
||||
#define FLAMMABLE 0
|
||||
#define ON_FIRE 1
|
||||
|
||||
|
||||
//Ghost orbit types:
|
||||
#define GHOST_ORBIT_CIRCLE "circle"
|
||||
#define GHOST_ORBIT_TRIANGLE "triangle"
|
||||
#define GHOST_ORBIT_HEXAGON "hexagon"
|
||||
#define GHOST_ORBIT_SQUARE "square"
|
||||
|
||||
+21
-12
@@ -3,15 +3,24 @@
|
||||
Turn(.) //BYOND handles cases such as -270, 360, 540 etc. DOES NOT HANDLE 180 TURNS WELL, THEY TWEEN AND LOOK LIKE SHIT
|
||||
|
||||
|
||||
/atom/proc/SpinAnimation(speed = 10, loops = -1)
|
||||
var/matrix/m120 = matrix(transform)
|
||||
m120.Turn(120)
|
||||
var/matrix/m240 = matrix(transform)
|
||||
m240.Turn(240)
|
||||
var/matrix/m360 = matrix(transform)
|
||||
speed /= 3 //Gives us 3 equal time segments for our three turns.
|
||||
//Why not one turn? Because byond will see that the start and finish are the same place and do nothing
|
||||
//Why not two turns? Because byond will do a flip instead of a turn
|
||||
animate(src, transform = m120, time = speed, loops)
|
||||
animate(transform = m240, time = speed)
|
||||
animate(transform = m360, time = speed)
|
||||
/atom/proc/SpinAnimation(speed = 10, loops = -1, clockwise = 1, segments = 3)
|
||||
if(!segments)
|
||||
return
|
||||
var/segment = 360/segments
|
||||
if(!clockwise)
|
||||
segment = -segment
|
||||
var/list/matrices = list()
|
||||
for(var/i in 1 to segments-1)
|
||||
var/matrix/M = matrix(transform)
|
||||
M.Turn(segment*i)
|
||||
matrices += M
|
||||
var/matrix/last = matrix(transform)
|
||||
matrices += last
|
||||
|
||||
speed /= segments
|
||||
|
||||
animate(src, transform = matrices[1], time = speed, loops)
|
||||
for(var/i in 2 to segments) //2 because 1 is covered above
|
||||
animate(transform = matrices[i], time = speed)
|
||||
//doesn't have an object argument because this is "Stacking" with the animate call above
|
||||
//3 billion% intentional
|
||||
|
||||
+38
-33
@@ -1192,51 +1192,56 @@ B --><-- A
|
||||
//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
|
||||
//we raise this each time orbit is called to prevent mutiple calls in a short time frame from breaking things
|
||||
/atom/movable/var/orbitid = 0
|
||||
|
||||
/atom/movable/proc/orbit(atom/A, radius = 10, clockwise = 1, angle_increment = 15, lockinorbit = 0)
|
||||
//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
|
||||
orbitid++
|
||||
var/myid = orbitid
|
||||
if (orbiting)
|
||||
stop_orbit()
|
||||
//sadly this is the only way to ensure the original orbit proc stops
|
||||
//and resets the atom's transform before we continue.
|
||||
//time is based on the sleep in the loop and the time for the final animation of initial_transform.
|
||||
sleep(2.6+world.tick_lag)
|
||||
if (orbiting || !istype(A) || orbitid != myid) //post sleep re-check
|
||||
return
|
||||
orbiting = A
|
||||
var/lastloc = loc
|
||||
var/angle = 0
|
||||
var/matrix/initial_transform = matrix(transform)
|
||||
|
||||
while(orbiting && orbiting.loc && orbitid == myid)
|
||||
if(orbiting)
|
||||
stop_orbit()
|
||||
sleep(2.6+world.tick_lag) //the 2 second delay at the end of the existing orbit() call, plus some lag slack.
|
||||
|
||||
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)
|
||||
while(orbiting && orbiting.loc)
|
||||
var/targetloc = get_turf(orbiting)
|
||||
if (!lockinorbit && loc != lastloc && loc != targetloc)
|
||||
if(!lockinorbit && loc != lastloc && loc != targetloc)
|
||||
break
|
||||
loc = targetloc
|
||||
lastloc = loc
|
||||
angle += angle_increment
|
||||
sleep(0.6)
|
||||
|
||||
animate(src,transform = initial_transform, time = 2) //2 second delay
|
||||
SpinAnimation(0,0)
|
||||
|
||||
var/matrix/shift = matrix(initial_transform)
|
||||
shift.Translate(radius,0)
|
||||
if(clockwise)
|
||||
shift.Turn(angle)
|
||||
else
|
||||
shift.Turn(-angle)
|
||||
animate(src, transform = shift, 2)
|
||||
sleep(0.6) //the effect breaks above 0.6 delay
|
||||
animate(src, transform = initial_transform, 2)
|
||||
orbiting = null
|
||||
|
||||
|
||||
/atom/movable/proc/stop_orbit()
|
||||
if(orbiting)
|
||||
loc = get_turf(orbiting)
|
||||
orbiting = null
|
||||
orbiting = null
|
||||
|
||||
|
||||
//Center's an image.
|
||||
|
||||
@@ -31,6 +31,7 @@ var/list/preferences_datums = list()
|
||||
var/toggles = TOGGLES_DEFAULT
|
||||
var/chat_toggles = TOGGLES_DEFAULT_CHAT
|
||||
var/ghost_form = "ghost"
|
||||
var/ghost_orbit = GHOST_ORBIT_CIRCLE
|
||||
var/allow_midround_antag = 1
|
||||
var/preferred_map = null
|
||||
|
||||
@@ -346,6 +347,7 @@ var/list/preferences_datums = list()
|
||||
if(unlock_content)
|
||||
dat += "<b>BYOND Membership Publicity:</b> <a href='?_src_=prefs;preference=publicity'>[(toggles & MEMBER_PUBLIC) ? "Public" : "Hidden"]</a><br>"
|
||||
dat += "<b>Ghost Form:</b> <a href='?_src_=prefs;task=input;preference=ghostform'>[ghost_form]</a><br>"
|
||||
dat += "<B>Ghost Orbit: </B> <a href='?_src_=prefs;task=input;preference=ghostform'>[ghost_orbit]</a><br>"
|
||||
|
||||
if (SERVERTOOLS && config.maprotation)
|
||||
var/p_map = preferred_map
|
||||
@@ -734,6 +736,12 @@ var/list/preferences_datums = list()
|
||||
var/new_form = input(user, "Thanks for supporting BYOND - Choose your ghostly form:","Thanks for supporting BYOND",null) as null|anything in ghost_forms
|
||||
if(new_form)
|
||||
ghost_form = new_form
|
||||
if("ghostorbit")
|
||||
if(unlock_content)
|
||||
var/new_orbit = input(user, "Thanks for supporting BYOND - Choose your ghostly orbit:","Thanks for supporting BYOND", null) as null|anything in ghost_orbits
|
||||
if(new_orbit)
|
||||
ghost_orbit = new_orbit
|
||||
|
||||
if("name")
|
||||
var/new_name = reject_bad_name( input(user, "Choose your character's name:", "Character Preference") as text|null )
|
||||
if(new_name)
|
||||
|
||||
@@ -178,6 +178,7 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
|
||||
S["chat_toggles"] >> chat_toggles
|
||||
S["toggles"] >> toggles
|
||||
S["ghost_form"] >> ghost_form
|
||||
S["ghost_orbit"] >> ghost_orbit
|
||||
S["preferred_map"] >> preferred_map
|
||||
S["ignoring"] >> ignoring
|
||||
|
||||
@@ -194,6 +195,7 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
|
||||
default_slot = sanitize_integer(default_slot, 1, max_save_slots, initial(default_slot))
|
||||
toggles = sanitize_integer(toggles, 0, 65535, initial(toggles))
|
||||
ghost_form = sanitize_inlist(ghost_form, ghost_forms, initial(ghost_form))
|
||||
ghost_orbit = sanitize_inlist(ghost_orbit, ghost_orbits, initial(ghost_orbit))
|
||||
|
||||
return 1
|
||||
|
||||
@@ -215,6 +217,7 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
|
||||
S["toggles"] << toggles
|
||||
S["chat_toggles"] << chat_toggles
|
||||
S["ghost_form"] << ghost_form
|
||||
S["ghost_orbit"] << ghost_orbit
|
||||
S["preferred_map"] << preferred_map
|
||||
S["ignoring"] << ignoring
|
||||
|
||||
|
||||
@@ -205,7 +205,7 @@
|
||||
src.ambience_playing = 0
|
||||
feedback_add_details("admin_verb", "SAmbi") //If you are copy-pasting this, I bet you read this comment expecting to see the same thing :^)
|
||||
|
||||
var/list/ghost_forms = list("ghost","ghostking","ghostian2","skeleghost","ghost_red","ghost_black", \
|
||||
var/global/list/ghost_forms = list("ghost","ghostking","ghostian2","skeleghost","ghost_red","ghost_black", \
|
||||
"ghost_blue","ghost_yellow","ghost_green","ghost_pink", \
|
||||
"ghost_cyan","ghost_dblue","ghost_dred","ghost_dgreen", \
|
||||
"ghost_dcyan","ghost_grey","ghost_dyellow","ghost_dpink", "ghost_purpleswirl","ghost_funkypurp","ghost_pinksherbert","ghost_blazeit",\
|
||||
@@ -222,6 +222,22 @@ var/list/ghost_forms = list("ghost","ghostking","ghostian2","skeleghost","ghost_
|
||||
if(istype(mob,/mob/dead/observer))
|
||||
mob.icon_state = new_form
|
||||
|
||||
var/global/list/ghost_orbits = list(GHOST_ORBIT_CIRCLE,GHOST_ORBIT_TRIANGLE,GHOST_ORBIT_SQUARE,GHOST_ORBIT_HEXAGON)
|
||||
|
||||
/client/verb/pick_ghost_orbit()
|
||||
set name = "Choose Ghost Orbit"
|
||||
set category = "Preferences"
|
||||
set desc = "Choose your preferred ghostly orbit."
|
||||
if(!is_content_unlocked())
|
||||
return
|
||||
var/new_orbit = input(src, "Thanks for supporting BYOND - Choose your ghostly orbit:","Thanks for supporting BYOND",null) as null|anything in ghost_orbits
|
||||
if(new_orbit)
|
||||
prefs.ghost_orbit = new_orbit
|
||||
prefs.save_preferences()
|
||||
if(istype(mob, /mob/dead/observer))
|
||||
var/mob/dead/observer/O = mob
|
||||
O.ghost_orbit = new_orbit
|
||||
|
||||
/client/verb/toggle_intent_style()
|
||||
set name = "Toggle Intent Selection Style"
|
||||
set category = "Preferences"
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
icon_state = client.prefs.ghost_form
|
||||
if (ghostimage)
|
||||
ghostimage.icon_state = src.icon_state
|
||||
ghost_orbit = client.prefs.ghost_orbit
|
||||
|
||||
updateghostimages()
|
||||
|
||||
|
||||
@@ -24,6 +24,7 @@ var/list/image/ghost_darkness_images = list() //this is a list of images for thi
|
||||
var/seedarkness = 1
|
||||
var/ghost_hud_enabled = 1 //did this ghost disable the on-screen HUD?
|
||||
var/data_hud_seen = 0 //this should one of the defines in __DEFINES/hud.dm
|
||||
var/ghost_orbit = GHOST_ORBIT_CIRCLE
|
||||
|
||||
/mob/dead/observer/New(mob/body)
|
||||
sight |= SEE_TURFS | SEE_MOBS | SEE_OBJS | SEE_SELF
|
||||
@@ -225,7 +226,19 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
|
||||
if(orbiting != target)
|
||||
src << "<span class='notice'>Now orbiting [target].</span>"
|
||||
|
||||
orbit(target,orbitsize,0)
|
||||
var/rot_seg
|
||||
|
||||
switch(ghost_orbit)
|
||||
if(GHOST_ORBIT_TRIANGLE)
|
||||
rot_seg = 3
|
||||
if(GHOST_ORBIT_SQUARE)
|
||||
rot_seg = 4
|
||||
if(GHOST_ORBIT_HEXAGON)
|
||||
rot_seg = 6
|
||||
else //Circular
|
||||
rot_seg = 36 //360/10 bby, smooth enough aproximation of a circle
|
||||
|
||||
orbit(target,orbitsize, FALSE, 20, rot_seg)
|
||||
|
||||
/mob/dead/observer/orbit()
|
||||
..()
|
||||
|
||||
Reference in New Issue
Block a user