diff --git a/code/__DEFINES/misc.dm b/code/__DEFINES/misc.dm index 535e7a1010a3cb..b8ce480d424ce0 100644 --- a/code/__DEFINES/misc.dm +++ b/code/__DEFINES/misc.dm @@ -411,4 +411,6 @@ var/global/list/ghost_others_options = list(GHOST_OTHERS_SIMPLE, GHOST_OTHERS_DE #define TURF_DECAL_DIRT "dirt" //Error handler defines -#define ERROR_USEFUL_LEN 2 \ No newline at end of file +#define ERROR_USEFUL_LEN 2 + +#define OPPOSITE_DIR(D) turn(D, 180) \ No newline at end of file diff --git a/code/_onclick/hud/human.dm b/code/_onclick/hud/human.dm index 09df40b8dd763c..fa0868d583215f 100644 --- a/code/_onclick/hud/human.dm +++ b/code/_onclick/hud/human.dm @@ -302,6 +302,9 @@ pull_icon.screen_loc = ui_pull_resist static_inventory += pull_icon + mymob.fov = new /obj/screen/fov() + static_inventory += mymob.fov + lingchemdisplay = new /obj/screen/ling/chems() infodisplay += lingchemdisplay diff --git a/code/_onclick/hud/screen_objects.dm b/code/_onclick/hud/screen_objects.dm index 476423ddcecb36..dcc79ee5090640 100644 --- a/code/_onclick/hud/screen_objects.dm +++ b/code/_onclick/hud/screen_objects.dm @@ -691,4 +691,13 @@ /obj/screen/splash/Destroy() holder.screen -= src - return ..() \ No newline at end of file + return ..() + +/obj/screen/fov + icon = 'icons/mob/vision_cone.dmi' + icon_state = "combat" + name = " " + screen_loc = "1,1" + mouse_opacity = 0 + layer = HUD_LAYER + plane = HUD_PLANE \ No newline at end of file diff --git a/code/datums/hud.dm b/code/datums/hud.dm index 75adb165d3ae4f..4284fc2bb3cca2 100644 --- a/code/datums/hud.dm +++ b/code/datums/hud.dm @@ -48,6 +48,7 @@ var/datum/atom_hud/huds = list( \ return for(var/i in hud_icons) M.client.images -= A.hud_list[i] + M.client.hidden_images -= A.hud_list[i] /datum/atom_hud/proc/add_hud_to(mob/M) if(!M) @@ -66,9 +67,15 @@ var/datum/atom_hud/huds = list( \ /datum/atom_hud/proc/add_to_single_hud(mob/M, atom/A) //unsafe, no sanity apart from client if(!M || !M.client || !A) return + var/in_cone = FALSE + if(A in cone(M, OPPOSITE_DIR(M.dir), view(10, M))) + in_cone = TRUE for(var/i in hud_icons) if(A.hud_list[i]) - M.client.images |= A.hud_list[i] + if(in_cone) + M.client.hidden_images |= A.hud_list[i] + else + M.client.images |= A.hud_list[i] //MOB PROCS /mob/proc/reload_huds() diff --git a/code/modules/mob/living/emote.dm b/code/modules/mob/living/emote.dm index 2b0e14350c83cf..d2522a914ee061 100644 --- a/code/modules/mob/living/emote.dm +++ b/code/modules/mob/living/emote.dm @@ -459,6 +459,7 @@ message = "spins around dizzily!" /datum/emote/living/spin/run_emote(mob/user) + user.client.move_delay = (user.movement_delay() * 2) + world.time user.spin(20, 1) if(istype(user, /mob/living/silicon/robot)) var/mob/living/silicon/robot/R = user diff --git a/code/modules/mob/living/living.dm b/code/modules/mob/living/living.dm index 6142f2ccd716be..ef7ce7ec7144ce 100644 --- a/code/modules/mob/living/living.dm +++ b/code/modules/mob/living/living.dm @@ -443,6 +443,12 @@ if (s_active && !(s_active.ClickAccessible(src, depth=STORAGE_VIEW_DEPTH) || s_active.Adjacent(src))) s_active.close(src) + for(var/mob/M in oview(src)) + if(M.client && (src in cone(M, OPPOSITE_DIR(M.dir), view(10, M)))) + M.update_vision_cone() + + update_vision_cone() + /mob/living/movement_delay(ignorewalk = 0) . = ..() if(isopenturf(loc) && !is_flying()) @@ -915,3 +921,8 @@ "[C] topples over [src]!", \ "[C] leaps out of [src]'s way!")]") C.Weaken(2) + + +/mob/living/setDir(newdir) + ..() + update_vision_cone() \ No newline at end of file diff --git a/code/modules/mob/mob.dm b/code/modules/mob/mob.dm index be7b382a87fd12..834cbb84d67973 100644 --- a/code/modules/mob/mob.dm +++ b/code/modules/mob/mob.dm @@ -665,6 +665,7 @@ var/next_mob_id = 0 else if(layer == LYING_MOB_LAYER) layer = initial(layer) + update_vision_cone() update_transform() update_action_buttons_icon(status_only=TRUE) if(isliving(src)) diff --git a/code/modules/mob/vision_cone.dm b/code/modules/mob/vision_cone.dm new file mode 100644 index 00000000000000..c19cf75fbdabe7 --- /dev/null +++ b/code/modules/mob/vision_cone.dm @@ -0,0 +1,91 @@ +/mob + var/obj/screen/fov = null//The screen object because I can't figure out how the hell TG does their screen objects so I'm just using legacy code. + +client/ + var/list/hidden_atoms = list() + var/list/hidden_mobs = list() + var/list/hidden_images = list() + + + +//Procs +/atom/proc/InCone(atom/center = usr, dir = NORTH) + 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/dead/InCone(mob/center = usr, dir = NORTH)//So ghosts aren't calculated. + return + +/proc/cone(atom/center = usr, dir = NORTH, list/list = oview(center)) + for(var/atom/A in list) + if(!A.InCone(center, dir)) + list -= A + return list + +/mob/proc/update_vision_cone() + return + +/mob/living/update_vision_cone() + if(src.client) + var/image/I = null + for(I in src.client.hidden_atoms) + I.override = 0 + client.images -= I + qdel(I) + for(var/hidden_hud in client.hidden_images) + client.images += hidden_hud + client.hidden_images -= hidden_hud + rest_cone_act() + src.client.hidden_atoms = list() + src.client.hidden_mobs = list() + client.hidden_images = list() + src.fov.dir = src.dir + if(fov.alpha != 0) + var/mob/living/M + for(M in cone(src, OPPOSITE_DIR(src.dir), view(10, src))) + I = image("split", M) + I.override = 1 + src.client.images += I + src.client.hidden_atoms += I + src.client.hidden_mobs += M + if(src.pulling == M)//If we're pulling them we don't want them to be invisible, too hard to play like that. + I.override = 0 + for(var/image/HUD in client.images) + if(HUD.icon != 'icons/mob/hud.dmi') + continue + for(var/mob/living/M in client.hidden_mobs) + if(HUD.loc == M) + client.hidden_images += HUD + client.images -= HUD + break + else + return + +/mob/proc/rest_cone_act()//For showing and hiding the cone when you rest or lie down. + if(resting || lying) + hide_cone() + else + show_cone() + +//Making these generic procs so you can call them anywhere. +/mob/proc/show_cone() + if(src.fov) + src.fov.alpha = 255 + +/mob/proc/hide_cone() + if(src.fov) + src.fov.alpha = 0 + + + + diff --git a/icons/mob/vision_cone.dmi b/icons/mob/vision_cone.dmi new file mode 100644 index 00000000000000..f77e5973a2dbfb Binary files /dev/null and b/icons/mob/vision_cone.dmi differ diff --git a/tgstation.dme b/tgstation.dme index 056f2cb2bf1f25..33f43be9a03c03 100644 --- a/tgstation.dme +++ b/tgstation.dme @@ -1395,6 +1395,7 @@ #include "code\modules\mob\status_procs.dm" #include "code\modules\mob\transform_procs.dm" #include "code\modules\mob\update_icons.dm" +#include "code\modules\mob\vision_cone.dm" #include "code\modules\mob\camera\camera.dm" #include "code\modules\mob\dead\death.dm" #include "code\modules\mob\dead\observer\login.dm"