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:
Remie Richards
2015-12-18 16:12:42 +00:00
parent 84ff5cfc36
commit 163c84344b
8 changed files with 109 additions and 47 deletions
+7
View File
@@ -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
View File
@@ -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
View File
@@ -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.
+8
View File
@@ -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
+17 -1
View File
@@ -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"
+1
View File
@@ -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()
+14 -1
View File
@@ -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()
..()