Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

CHAT CHUD ENGAGED #11

Merged
merged 2 commits into from
Jul 15, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3,436 changes: 1,718 additions & 1,718 deletions _maps/map_files/coyote_bayou/foxybarupper.dmm

Large diffs are not rendered by default.

3 changes: 2 additions & 1 deletion code/__DEFINES/layers.dm
Original file line number Diff line number Diff line change
Expand Up @@ -28,11 +28,12 @@
#define MOB_PLANE -3 // Used for mobs rendering.
#define FIELD_OF_VISION_VISUAL_PLANE -2 //Yea, FoV does require quite a few planes to work with 513 filters to a decent degree.

#define CHAT_PLANE -1 //We don't want heard messages to be hidden by FoV.
#define CHAT_LAYER 12.1 //Legacy, it doesn't matter that much because we are displayed above the game plane anyway.

#define BLACKNESS_PLANE 0 //To keep from conflicts with SEE_BLACKNESS internals

#define CHAT_PLANE 2 //We don't want heard messages to be hidden by FoV.

#define SPACE_LAYER 1.8
//#define TURF_LAYER 2 //For easy recordkeeping; this is a byond define
#define MID_TURF_LAYER 2.02
Expand Down
5 changes: 5 additions & 0 deletions code/__DEFINES/maths.dm
Original file line number Diff line number Diff line change
Expand Up @@ -270,6 +270,11 @@
var/roundie = 1 * (0.1**decimals)
return "[round(number, roundie)][unit]"

/// checks if a given turf's x/y coordinates fall within a given rectangle
/// xwest, ynorth, xeast, ysouth are the bounds of the rectangle
/// N/S is Y, Y increases as you go north
/// E/W is X, X increases as you go east
#define TURF_IN_RECTANGLE(turf, xwest, ynorth, xeast, ysouth) (turf.x >= xwest && turf.x <= xeast && turf.y >= ynorth && turf.y <= ysouth)


#define RANDOM(min, max) (rand(min*1000, max*1000)*0.001)
Expand Down
114 changes: 70 additions & 44 deletions code/__HELPERS/game.dm
Original file line number Diff line number Diff line change
Expand Up @@ -309,15 +309,15 @@ GLOBAL_LIST_EMPTY(chat_chuds)
/datum/chatchud
var/list/visible_close = list()
var/list/visible_far = list()
var/list/hidden_close_pathable = list()
var/list/hidden_pathable = list()
var/list/hidden_inaccessible = list()
var/ready = TRUE

/datum/chatchud/proc/putback()
visible_close.Cut()
visible_far.Cut()
hidden_close_pathable.Cut()
ready = TRUE
hidden_pathable.Cut()
ready = TRUE // snip snip no jutsu wuz here

/obj/effect/temp_visual/debug_heart
name = "love heart"
Expand Down Expand Up @@ -346,10 +346,14 @@ GLOBAL_LIST_EMPTY(chat_chuds)
numb = 99999999
var/list/splitnumbers = list()
/// splits numb into its digits, from most to least significant
while(numb > 0)
splitnumbers += numb % 10
numb /= 10
numb = floor(numb)
if(numb <= 0)
splitnumbers += 0
else
var/tries = 10
while(numb > 0 && tries-- > 0)
splitnumbers += numb % 10
numb /= 10
numb = floor(numb)
/// now we have to reverse the list
splitnumbers = reverseList(splitnumbers)
var/offset = 0
Expand All @@ -363,61 +367,83 @@ GLOBAL_LIST_EMPTY(chat_chuds)
if(coler)
color = coler

#define IS_IN_VIEWER_RECT(turf) TURF_IN_RECTANGLE(turf, westest, eastest, northest, southest)

/// returns a datum of players and how well they can hear the source
/proc/get_listening(atom/source, close_range, long_range, quiet)
var/area/A = get_area(source)
var/private = A.private
var/datum/chatchud/CC = get_chatchud(source)
var/list/see_close = hearers(source, close_range)
var/list/see_far = hearers(source, long_range) - see_close
var/turf/source_turf = get_turf(source)
var/debug_i = 0
dingus:
for(var/client/C in GLOB.clients)
var/mob/M = C.mob
if(M.z != source.z)
var/turf/viewer_turf = get_turf(M)
if(source_turf.z != viewer_turf.z)
continue dingus
if(get_dist(M, source) > long_range)
var/westest = max(viewer_turf.x - 9, 1)
var/eastest = min(viewer_turf.x + 9, world.maxx)
var/northest = max(viewer_turf.y - 6, 1)
var/southest = min(viewer_turf.y + 6, world.maxy)
var/list/things_in_viewer_los = view(9, viewer_turf)
if(SSchat.debug_chud)
var/turf/t_northwest = locate(westest, northest, viewer_turf.z)
var/turf/t_southeast = locate(eastest, southest, viewer_turf.z)
var/turf/t_northeast = locate(eastest, northest, viewer_turf.z)
var/turf/t_southwest = locate(westest, southest, viewer_turf.z)
/// draw a beam box!
t_northeast.Beam(t_northwest, icon_state = "1-full", time = 3 SECONDS, show_to = list(C))
t_northeast.Beam(t_southeast, icon_state = "1-full", time = 3 SECONDS, show_to = list(C))
t_southeast.Beam(t_southwest, icon_state = "1-full", time = 3 SECONDS, show_to = list(C))
t_southwest.Beam(t_northwest, icon_state = "1-full", time = 3 SECONDS, show_to = list(C))
var/in_close_view = (source_turf in things_in_viewer_los)
var/in_rect = IS_IN_VIEWER_RECT(source_turf)
if(!in_rect && get_dist(source_turf, viewer_turf) > long_range)
continue dingus
var/is_far = (M in see_far)
var/is_close = (M in see_close)
if(is_far)
if(private)
// basic visibility, fulfills these conditions:
// 1. must be in the box of visibility, so we dont have to play with pathing nonsense
// 2. must be in the line of sight of the hearer, so it shouldnt be over darkness
// basically if they're on screen, and either of the ranges are met, they're visible and we can skip the pathing
if(in_rect && in_close_view)
if(get_dist(source_turf, viewer_turf) <= close_range)
CC.visible_close[M] = TRUE
continue dingus
CC.visible_far[M] = TRUE
continue dingus
else if(is_close)
CC.visible_close[M] = TRUE
else if(get_dist(source_turf, viewer_turf) <= long_range)
CC.visible_far[M] = TRUE
continue dingus
// if the source is in a Private area,
// and the viewer is either not in the line of sight or not in the box of visibility,
// then they're hidden, so we dont bleat out a bunch of horny moaning to the whole world
if(private)
continue dingus
// if(get_dist(M, source) > long_range)
// continue dingus // they're too far away to hear
// now the fun begins. Try to find a path to them
// now the real fun begins
var/list/soundwalk = get_path_to(source, M, long_range, use_visibility = TRUE)
var/list/soundwalk = get_path_to(source_turf, viewer_turf, long_range, use_visibility = TRUE)
// they're closed off, no path to them, but they're still within long range
if(!islist(soundwalk))
CC.hidden_inaccessible[M] = TRUE
CC.hidden_inaccessible[M] = TRUE // mark them as hidden
continue dingus
// the path from source to viewer is too long, so we consider them out of range
if(!LAZYLEN(soundwalk) || LAZYLEN(soundwalk) > long_range)
CC.hidden_inaccessible[M] = TRUE
continue dingus
// now walk through the path and find the first tile that can see the source
donger:
for(var/turf/T as anything in soundwalk)
var/list/seeline = getline(T, M)
debug_i = 0
var/cole = pick("#FF0000", "#00FF00", "#0000FF", "#FFFF00", "#FF00FF", "#00FFFF")
for(var/turf/TT as anything in seeline) // beeg american TTs
if(SSchat.debug_chud)
new /obj/effect/temp_visual/numbers/backgrounded(T, debug_i, cole)
debug_i++
if(TT.opacity)
continue donger
for(var/atom/AM as anything in TT.contents)
if(AM.opacity)
continue donger
if(SSchat.debug_chud)
new /obj/effect/temp_visual/debug_heart(T)
CC.hidden_close_pathable[M] = T
continue dingus
// now walk through the path and find the first tile that can fulfill all of these conditions:
// 1. must be in the box of visibility
// 2. must be in the line of sight of the hearer
debug_i = 0
var/cole = SSchat.debug_chud && safepick("#FF0000", "#00FF00", "#0000FF", "#FFFF00", "#FF00FF", "#00FFFF")
for(var/turf/T as anything in soundwalk) // for each step we take...
if(SSchat.debug_chud)
new /obj/effect/temp_visual/numbers/backgrounded(T, debug_i, cole)
debug_i++
if(!IS_IN_VIEWER_RECT(T)) // ...check if our turf is in the viewer's box of visibility
continue // we can't see them
if(!(T in things_in_viewer_los)) // if they're in the box but not in the line of sight,
continue // we can't see them
// at this point, we have met these conditions
if(SSchat.debug_chud)
new /obj/effect/temp_visual/debug_heart(T)
CC.hidden_pathable[M] = T
continue dingus
// couldnt find anything! mark them as hidden
CC.hidden_inaccessible[M] = TRUE
return CC
Expand Down
5 changes: 3 additions & 2 deletions code/controllers/subsystem/chat.dm
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,12 @@ SUBSYSTEM_DEF(chat)
var/extended_whisper_distance = 3

var/base_sing_distance = 15
var/extended_sing_distance = INFINITY
var/extended_sing_distance = 150
var/base_yell_distance = 15
var/extended_yell_distance = INFINITY
var/extended_yell_distance = 150
var/far_distance = 6 // how far until they're considered offscreen

var/chat_display_plane = LIGHTING_PLANE + 1 // FUKCUAING FUKCING LIGHTING EATING AS //CHAT_PLANE

var/list/payload_by_client = list()
/// All the lookups for translating emotes to say prefixes
Expand Down
43 changes: 39 additions & 4 deletions code/datums/beam.dm
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,13 @@
var/finished = 0
var/turf/target_oldloc
var/turf/origin_oldloc
var/list/showing_to = list()
var/static_beam = 0
var/beam_type = /obj/effect/ebeam //must be subtype
var/timing_id = null
var/recalculating = FALSE

/datum/beam/New(beam_origin,beam_target,beam_icon='icons/effects/beam.dmi',beam_icon_state="b_beam",time=50,maxdistance=10,btype = /obj/effect/ebeam,beam_sleep_time=3)
/datum/beam/New(beam_origin,beam_target,beam_icon='icons/effects/beam.dmi',beam_icon_state="b_beam",time=50,maxdistance=10,btype = /obj/effect/ebeam,beam_sleep_time=3,list/show_to)
origin = beam_origin
origin_oldloc = get_turf(origin)
target = beam_target
Expand All @@ -29,6 +30,12 @@
icon = beam_icon
icon_state = beam_icon_state
beam_type = btype
if(!isnull(show_to))
var/list/to_show = islist(show_to) ? show_to : list(show_to)
for(var/thing in to_show)
var/client/C = extract_client(thing)
if(C)
showing_to += C
if(time < INFINITY)
addtimer(CALLBACK(src,PROC_REF(End)), time)

Expand Down Expand Up @@ -83,6 +90,11 @@

/datum/beam/proc/Reset()
for(var/obj/effect/ebeam/B in elements)
if(B.mypic && LAZYLEN(showing_to))
for(var/client/C in showing_to)
if(!C)
continue
C.images -= B.mypic
qdel(B)
elements.Cut()

Expand All @@ -109,7 +121,7 @@
for(N in 0 to length-1 step 32)//-1 as we want < not <=, but we want the speed of X in Y to Z and step X
if(finished)
break
var/obj/effect/ebeam/X = new beam_type(origin_oldloc)
var/obj/effect/ebeam/X = new beam_type(origin_oldloc, showing_to)
X.owner = src
elements += X

Expand Down Expand Up @@ -148,13 +160,27 @@

X.pixel_x = Pixel_x
X.pixel_y = Pixel_y
if(showing_to)
// snapshot no jutsu
var/image/II = image(X.icon, X.loc, X.icon_state, X.layer, X.dir, X.pixel_x, X.pixel_y)
II.transform = X.transform
X.mypic = II
for(var/client/C in showing_to)
if(C)
C.images += II
CHECK_TICK
afterDraw()

/obj/effect/ebeam
mouse_opacity = MOUSE_OPACITY_TRANSPARENT
anchored = TRUE
var/datum/beam/owner
var/image/mypic

/obj/effect/ebeam/Initialize(mapload, shows)
. = ..()
if(shows)
invisibility = INVISIBILITY_ABSTRACT

/obj/effect/ebeam/Destroy()
owner = null
Expand All @@ -165,7 +191,16 @@
/obj/effect/ebeam/singularity_act()
return

/atom/proc/Beam(atom/BeamTarget,icon_state="b_beam",icon='icons/effects/beam.dmi',time=50, maxdistance=10,beam_type=/obj/effect/ebeam,beam_sleep_time = 3)
var/datum/beam/newbeam = new(src,BeamTarget,icon,icon_state,time,maxdistance,beam_type,beam_sleep_time)
/atom/proc/Beam(
atom/BeamTarget,
icon_state="b_beam",
icon='icons/effects/beam.dmi',
time=50,
maxdistance=10,
beam_type=/obj/effect/ebeam,
beam_sleep_time = 3,
list/show_to = list()
)
var/datum/beam/newbeam = new(src,BeamTarget,icon,icon_state,time,maxdistance,beam_type,beam_sleep_time,show_to)
INVOKE_ASYNC(newbeam, TYPE_PROC_REF(/datum/beam/,Start))
return newbeam
Loading
Loading