mirror of
https://github.com/Aurorastation/Aurora.3.git
synced 2025-12-23 00:22:12 +00:00
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
222 lines
5.8 KiB
Plaintext
222 lines
5.8 KiB
Plaintext
/////////////VISION CONE///////////////
|
|
// Vision cone code by Honkertron (for Otuska), Matt and Myazaki.
|
|
// This vision cone code allows for mobs and/or items to be blocked out from a player's field of vision.
|
|
// This code makes use of the "cone of effect" proc created by Lummox, contributed by Jtgibson.
|
|
//
|
|
// More info on that here:
|
|
// http://www.byond.com/forum/?post=195138
|
|
///////////////////////////////////////
|
|
|
|
/client
|
|
var/list/hidden_atoms = list()
|
|
var/list/hidden_mobs = list()
|
|
|
|
/proc/cone(turf/center, dir, list/list)
|
|
. = list()
|
|
for(var/turf/T in list)
|
|
if(T.InConeDirection(center, dir))
|
|
for(var/mob/M in T.contents)
|
|
if(!istype(M, /mob/abstract))
|
|
. += M.InCone(center, dir)
|
|
|
|
/turf/proc/InConeDirection(turf/center, dir)
|
|
if(get_dist(center, src) == 0 || src == center) return 0
|
|
var/d = get_dir(center, src)
|
|
|
|
if(!d || d == dir) return 1
|
|
if(dir & (dir-1))
|
|
return (d & ~dir) ? 0 : 1
|
|
if(!(d & dir)) return 0
|
|
var/dx = abs(x - center.x)
|
|
var/dy = abs(y - center.y)
|
|
if(dx == dy) return 1
|
|
if(dy > dx)
|
|
return (dir & (NORTH|SOUTH)) ? 1 : 0
|
|
return (dir & (EAST|WEST)) ? 1 : 0
|
|
|
|
/mob/living/proc/toggle_vision_cone()
|
|
set name = "Toggle Vision Cone"
|
|
set category = "OOC"
|
|
set desc = "Toggle the ability to have a vision cone"
|
|
|
|
can_have_vision_cone = !can_have_vision_cone
|
|
check_fov()
|
|
|
|
// Should return atoms that are in the cone.
|
|
/atom/proc/InCone(turf/center, dir)
|
|
SHOULD_CALL_PARENT(TRUE)
|
|
return list()
|
|
|
|
/mob/dead/InCone(turf/center, dir)
|
|
. = ..()
|
|
|
|
/mob/InCone(turf/center, dir)
|
|
. = ..() | src
|
|
|
|
/mob/living/InCone(turf/center, dir)
|
|
. = ..()
|
|
if(pulling)
|
|
. += pulling
|
|
|
|
/mob/proc/update_vision_cone()
|
|
return
|
|
|
|
/mob/living/update_vision_cone()
|
|
if(!can_have_vision_cone)
|
|
if(vision_cone_overlay)
|
|
remove_cone()
|
|
return
|
|
|
|
for(var/obj/item/item in src)
|
|
if(item.zoom)
|
|
remove_cone()
|
|
return
|
|
|
|
var/delay = 1 SECONDS
|
|
if(client)
|
|
var/image/I = null
|
|
for(I in client.hidden_atoms)
|
|
I.override = FALSE
|
|
QDEL_IN(I, delay)
|
|
delay += 1 SECONDS
|
|
|
|
check_fov()
|
|
client.hidden_atoms.Cut()
|
|
client.hidden_mobs.Cut()
|
|
|
|
|
|
if(resting || lying)
|
|
hide_cone()
|
|
return
|
|
|
|
vision_cone_overlay.dir = dir
|
|
if(vision_cone_overlay.alpha)
|
|
var/turf/T = get_turf(src)
|
|
for(var/cone_atom in cone(T, reverse_direction(dir), get_rectangle_in_dir(T, client.view + 1, reverse_direction(dir)) & oview(client.view + 1, T)))
|
|
add_to_mobs_hidden_atoms(cone_atom)
|
|
|
|
/mob/living/proc/add_to_mobs_hidden_atoms(atom/A)
|
|
var/image/I
|
|
I = image("split", A)
|
|
I.override = TRUE
|
|
client.images += I
|
|
client.hidden_atoms += I
|
|
if(ismob(A))
|
|
var/mob/hidden_mob = A
|
|
client.hidden_mobs += hidden_mob
|
|
if(pulling && (pulling == hidden_mob || pulling == hidden_mob.buckled))//If we're pulling them we don't want them to be invisible, too hard to play like that.
|
|
I.override = FALSE
|
|
return
|
|
for(var/obj/item/grab/G in src)
|
|
if(A == G.affecting)
|
|
I.override = FALSE
|
|
return
|
|
for(var/obj/item/grab/G in A)
|
|
if(src == G.affecting)
|
|
I.override = FALSE
|
|
return
|
|
|
|
/mob/living/proc/SetFov(var/n)
|
|
if(!can_have_vision_cone)
|
|
return
|
|
|
|
if(!n)
|
|
hide_cone()
|
|
else
|
|
show_cone()
|
|
|
|
/mob/living/proc/check_fov()
|
|
if(!can_have_vision_cone)
|
|
if(client)
|
|
for(var/hidden in client.hidden_atoms)
|
|
var/image/I = hidden
|
|
client.images -= I
|
|
client.hidden_atoms.Cut()
|
|
client.hidden_mobs.Cut()
|
|
remove_cone()
|
|
return
|
|
|
|
if(isnull(vision_cone_overlay))
|
|
vision_cone_overlay = new /obj/screen/fov()
|
|
client.screen |= vision_cone_overlay
|
|
|
|
if(resting || lying || client.eye != client.mob)
|
|
vision_cone_overlay.alpha = 0
|
|
return
|
|
|
|
else if(vision_cone_overlay)
|
|
show_cone()
|
|
else
|
|
hide_cone()
|
|
|
|
//Making these generic procs so you can call them anywhere.
|
|
/mob/living/proc/show_cone()
|
|
if(!can_have_vision_cone)
|
|
return
|
|
|
|
if(vision_cone_overlay)
|
|
vision_cone_overlay.alpha = client.prefs.fov_cone_alpha
|
|
|
|
/mob/living/proc/hide_cone()
|
|
if(vision_cone_overlay)
|
|
vision_cone_overlay.alpha = 0
|
|
|
|
/mob/living/proc/remove_cone()
|
|
if(vision_cone_overlay)
|
|
client.screen -= vision_cone_overlay
|
|
|
|
/mob/living/set_dir(var/new_dir, ignore_facing_dir = FALSE)
|
|
. = ..()
|
|
if(.)
|
|
update_vision_cone()
|
|
|
|
// Rotates a rectangle around a center turf
|
|
/proc/get_rectangle_in_dir(var/turf/T, var/length, var/dir)
|
|
var/matrix/M = new
|
|
var/matrix/N = new
|
|
M.Turn(dir2angle(dir))
|
|
N.Turn((dir2angle(dir)+180) % 360)
|
|
. = block(\
|
|
locate(T.x + (M.a+M.b) * length + 0.5*(M.a + M.b - 1), T.y + (M.d+M.e) * length + 0.5*(M.d + M.e - 1), T.z),\
|
|
locate(T.x + N.a * length + 0.5*(M.a + M.b - 1), T.y + N.d * length + 0.5*(M.d + M.e - 1), T.z)\
|
|
)
|
|
|
|
#define ALWAYS_FOOTSTEP_DISTANCE 2
|
|
#define MAX_FOOTSTEP_DISTANCE 5
|
|
#define RIPPLE_POSITION_BOUNDS 8
|
|
#define RIPPLE_START_RADIUS 10
|
|
#define RIPPLE_END_RADIUS 2
|
|
#define RIPPLE_START_SIZE 0
|
|
#define RIPPLE_END_SIZE 16
|
|
|
|
/turf/proc/show_footsteps(var/mob/viewer, var/turf/Tviewer, var/mob/M)
|
|
var/dist = get_dist(src, Tviewer)
|
|
if(src == Tviewer)
|
|
return
|
|
if(dist > MAX_FOOTSTEP_DISTANCE || prob(100*max(dist-ALWAYS_FOOTSTEP_DISTANCE,0) / MAX_FOOTSTEP_DISTANCE))
|
|
return
|
|
if(isdeaf(viewer))
|
|
return
|
|
if(viewer.stat || M.stat || M.lying)
|
|
return
|
|
if(ishuman(M))
|
|
var/mob/living/carbon/human/H = M
|
|
if(!H.is_noisy)
|
|
return
|
|
|
|
var/image/marker = image(icon, src, icon_state, layer = layer)
|
|
marker.overlays = overlays.Copy()
|
|
marker.override = TRUE
|
|
marker.filters += filter(type = "ripple", x=rand(-RIPPLE_POSITION_BOUNDS, RIPPLE_POSITION_BOUNDS), y=rand(-RIPPLE_POSITION_BOUNDS, RIPPLE_POSITION_BOUNDS), radius = RIPPLE_START_RADIUS, size = RIPPLE_START_SIZE, falloff = 0)
|
|
|
|
viewer.client.images += marker
|
|
QDEL_IN(marker, 1.5 SECONDS)
|
|
animate(marker.filters[marker.filters.len], time = 1.5 SECONDS, radius = RIPPLE_END_RADIUS, size = RIPPLE_END_SIZE)
|
|
|
|
#undef ALWAYS_FOOTSTEP_DISTANCE
|
|
#undef MAX_FOOTSTEP_DISTANCE
|
|
#undef RIPPLE_POSITION_BOUNDS
|
|
#undef RIPPLE_START_RADIUS
|
|
#undef RIPPLE_END_RADIUS
|
|
#undef RIPPLE_START_SIZE
|
|
#undef RIPPLE_END_SIZE |