Skip to content

Commit

Permalink
Use DVIEW (#6712)
Browse files Browse the repository at this point in the history
# About the pull request

Switches several uses of `view` over to `dview` and related
procs/defines instead. Only swaps over where it would be inappropriate
for native BYOND darkness to effect the results, i.e. it cares about a
lack of obstructions rather than actual visibility.

Created `doview()` and `USE_DOVIEW` as the `oview` version of `dview`.

Tweaked `dview` and related procs to work slightly more like `view`
would. `view` is from the perspective of the provided atom, seeing
itself, its loc (usually a turf), and if on a turf, any surrounding
turfs. `dview` set its loc to the provided atom, meaning it was in the
*contents* of that atom, and would see itself and its loc (the atom)...
which, as an atom, means it wouldn't see surrounding turfs. Existing
uses of `dview` got around this by using `get_turf` on the provided
atom. I changed the behavior so this wasn't necessary, allowing you to
`dview` from the perspective of a atom and have it work like `view`
would.
Perhaps that should just be a built-in `get_turf` instead, but this more
closely matches how `view` works.

Used `HIDE_INVISIBLE_OBSERVER` as the see invis for `dview` as all the
uses I saw were for in-character things, and thus should only effect
things that were also in-character. Anything as invisible as an observer
or more is assumed to be out-of-character.

<!-- Remove this text and explain what the purpose of your PR is.

Mention if you have tested your changes. If you changed a map, make sure
you used the mapmerge tool.
If this is an Issue Correction, you can type "Fixes Issue #169420" to
link the PR to the corresponding Issue number #169420.

Remember: something that is self-evident to you might not be to others.
Explain your rationale fully, even if you feel it goes without saying.
-->

# Explain why it's good for the game

Should (currently) have no effect on the game as native BYOND darkness
isn't used (all areas have luminosity), but is one step towards allowing
that system to work appropriately if enabled.
# Testing Photographs and Procedure
<details>
<summary>Screenshots & Videos</summary>

Performance testing. All procs in question return a list of atoms.
The procs of interest:

![image](https://github.com/user-attachments/assets/d4b487c9-5b8d-470e-8692-c7b2d8045d19)

Current, with darkness disabled (area luminosity = 1):

![image](https://github.com/user-attachments/assets/f6ab0229-c868-4f9c-a98a-541357dd0a65)
No performance difference between `view` and `dview`.

As a test, darkness enabled (area luminosity = 0):

![image](https://github.com/user-attachments/assets/bb60b345-0df7-45f3-8f09-a97fdfd43cd9)
`dview` is notably slower than `view`, likely because `view` has smaller
lists of things it can see due to darkness and thus shorter loops.

</details>


# Changelog
No player facing changes.

---------

Co-authored-by: Drathek <[email protected]>
  • Loading branch information
Doubleumc and Drulikar authored Aug 7, 2024
1 parent 33e6c27 commit bf69d10
Show file tree
Hide file tree
Showing 25 changed files with 92 additions and 60 deletions.
33 changes: 23 additions & 10 deletions code/__HELPERS/unsorted.dm
Original file line number Diff line number Diff line change
Expand Up @@ -1340,29 +1340,35 @@ GLOBAL_LIST_INIT(WALLITEMS, list(
GLOBAL_DATUM_INIT(dview_mob, /mob/dview, new)

/// Version of view() which ignores darkness, because BYOND doesn't have it (I actually suggested it but it was tagged redundant, BUT HEARERS IS A T- /rant).
/proc/dview(range = world.view, center, invis_flags = 0)
/proc/dview(range = world.view, atom/center, invis_flags = 0)
if(!center)
return

GLOB.dview_mob.loc = center

GLOB.dview_mob.loc = isturf(center) ? center : center.loc
GLOB.dview_mob.see_invisible = invis_flags

. = view(range, GLOB.dview_mob)
. = oview(range, GLOB.dview_mob)
GLOB.dview_mob.loc = null

/// Version of oview() which ignores darkness
/proc/doview(range, atom/center, invis_flags)
if(!center)
return

return dview(range, center, invis_flags) - center

/mob/dview
name = "INTERNAL DVIEW MOB"
invisibility = 101
invisibility = INVISIBILITY_ABSTRACT
density = FALSE
see_in_dark = 1e6
see_in_dark = INFINITY
var/ready_to_die = FALSE

/mob/dview/Initialize() //Properly prevents this mob from gaining huds or joining any global lists
SHOULD_CALL_PARENT(FALSE)
if(flags_atom & INITIALIZED)
if(CHECK_BITFIELD(flags_atom, INITIALIZED))
stack_trace("Warning: [src]([type]) initialized multiple times!")
flags_atom |= INITIALIZED
ENABLE_BITFIELD(flags_atom, INITIALIZED)
return INITIALIZE_HINT_NORMAL

/mob/dview/Destroy(force = FALSE)
Expand All @@ -1378,12 +1384,19 @@ GLOBAL_DATUM_INIT(dview_mob, /mob/dview, new)


#define FOR_DVIEW(type, range, center, invis_flags) \
GLOB.dview_mob.loc = center; \
GLOB.dview_mob.loc = isturf(center) ? (center) : (center).loc; \
GLOB.dview_mob.see_invisible = invis_flags; \
for(type in view(range, GLOB.dview_mob))
for(type in oview(range, GLOB.dview_mob))

#define FOR_DVIEW_END GLOB.dview_mob.loc = null

#define FOR_DOVIEW(type, range, center, invis_flags) \
GLOB.dview_mob.loc = isturf(center) ? (center) : (center).loc; \
GLOB.dview_mob.see_invisible = invis_flags; \
for(type in oview(range, GLOB.dview_mob) - (center))

#define FOR_DOVIEW_END FOR_DVIEW_END

/proc/get_turf_pixel(atom/AM)
if(!istype(AM))
return
Expand Down
3 changes: 2 additions & 1 deletion code/datums/ammo/energy.dm
Original file line number Diff line number Diff line change
Expand Up @@ -204,7 +204,7 @@

/datum/ammo/energy/yautja/caster/sphere/stun/proc/do_area_stun(obj/projectile/P)
playsound(P, 'sound/weapons/wave.ogg', 75, 1, 25)
for (var/mob/living/carbon/M in view(src.stun_range, get_turf(P)))
FOR_DVIEW(var/mob/living/carbon/M, src.stun_range, get_turf(P), HIDE_INVISIBLE_OBSERVER)
var/stun_time = src.stun_time
log_attack("[key_name(M)] was stunned by a plasma immobilizer from [key_name(P.firer)] at [get_area(P)]")
if (isyautja(M))
Expand All @@ -214,6 +214,7 @@
to_chat(M, SPAN_DANGER("A powerful electric shock ripples through your body, freezing you in place!"))
M.apply_effect(stun_time, STUN)
M.apply_effect(stun_time, WEAKEN)
FOR_DVIEW_END

/datum/ammo/energy/yautja/rifle/bolt
name = "plasma rifle bolt"
Expand Down
9 changes: 2 additions & 7 deletions code/datums/beam.dm
Original file line number Diff line number Diff line change
Expand Up @@ -215,17 +215,12 @@
return newbeam

/proc/zap_beam(atom/source, zap_range, damage, list/blacklistmobs)
var/list/zap_data = list()
for(var/mob/living/carbon/xenomorph/beno in oview(zap_range, source))
zap_data += beno
for(var/xeno in zap_data)
var/mob/living/carbon/xenomorph/living = xeno
if(!living)
return
FOR_DOVIEW(var/mob/living/carbon/xenomorph/living, zap_range, source, HIDE_INVISIBLE_OBSERVER)
if(living.stat == DEAD)
continue
if(living in blacklistmobs)
continue
source.beam(living, icon_state="lightning[rand(1,12)]", time = 3, maxdistance = zap_range + 2)
living.set_effect(2, SLOW)
log_attack("[living] was zapped by [source]")
FOR_DOVIEW_END
3 changes: 2 additions & 1 deletion code/datums/disease.dm
Original file line number Diff line number Diff line change
Expand Up @@ -121,10 +121,11 @@ GLOBAL_LIST_INIT(diseases, typesof(/datum/disease) - /datum/disease)
check_range = 1 // everything else, like infect-on-contact things, only infect things on top of it

if(isturf(source.loc))
for(var/mob/living/carbon/victim in oview(check_range, source))
FOR_DOVIEW(var/mob/living/carbon/victim, check_range, source, HIDE_INVISIBLE_OBSERVER)
if(isturf(victim.loc))
if(AStar(source.loc, victim.loc, /turf/proc/AdjacentTurfs, /turf/proc/Distance, check_range))
victim.contract_disease(src, 0, 1, force_spread)
FOR_DOVIEW_END

return

Expand Down
3 changes: 2 additions & 1 deletion code/datums/emergency_calls/cryo_marines.dm
Original file line number Diff line number Diff line change
Expand Up @@ -37,10 +37,11 @@
human.create_hud()

if(!mind)
for(var/obj/structure/machinery/cryopod/pod in view(7,human))
FOR_DVIEW(var/obj/structure/machinery/cryopod/pod, 7, human, HIDE_INVISIBLE_OBSERVER)
if(pod && !pod.occupant)
pod.go_in_cryopod(human, silent = TRUE)
break
FOR_DVIEW_END

sleep(5)
var/datum/squad/marine/cryo/cryo_squad = GLOB.RoleAuthority.squads_by_type[/datum/squad/marine/cryo]
Expand Down
3 changes: 2 additions & 1 deletion code/datums/emergency_calls/cryo_spec.dm
Original file line number Diff line number Diff line change
Expand Up @@ -35,10 +35,11 @@
human.create_hud()

if(!mind)
for(var/obj/structure/machinery/cryopod/pod in view(7,human))
FOR_DVIEW(var/obj/structure/machinery/cryopod/pod, 7, human, HIDE_INVISIBLE_OBSERVER)
if(pod && !pod.occupant)
pod.go_in_cryopod(human, silent = TRUE)
break
FOR_DVIEW_END

sleep(5)
human.client?.prefs.copy_all_to(human, JOB_SQUAD_SPECIALIST, TRUE, TRUE)
Expand Down
4 changes: 3 additions & 1 deletion code/game/machinery/camera/camera.dm
Original file line number Diff line number Diff line change
Expand Up @@ -263,9 +263,11 @@ GLOBAL_LIST_EMPTY_TYPED(all_cameras, /obj/structure/machinery/camera)
//Return a working camera that can see a given mob
//or null if none
/proc/seen_by_camera(mob/M)
for(var/obj/structure/machinery/camera/C in oview(4, M))
FOR_DOVIEW(var/obj/structure/machinery/camera/C, 4, M, HIDE_INVISIBLE_OBSERVER)
if(C.can_use()) // check if camera disabled
FOR_DOVIEW_END
return C
FOR_DOVIEW_END
return null

/proc/near_range_camera(mob/M)
Expand Down
4 changes: 2 additions & 2 deletions code/game/machinery/computer/almayer_control.dm
Original file line number Diff line number Diff line change
Expand Up @@ -184,7 +184,7 @@
to_chat(user, SPAN_WARNING("Arrays are re-cycling. Please stand by."))
return FALSE
var/input = stripped_input(user, "Please choose a message to transmit to USCM. Please be aware that this process is very expensive, and abuse will lead to termination. Transmission does not guarantee a response. There is a small delay before you may send another message. Be clear and concise.", "To abort, send an empty message.", "")
if(!input || !(user in view(1,src)) || !COOLDOWN_FINISHED(src, cooldown_central))
if(!input || !(user in dview(1, src)) || !COOLDOWN_FINISHED(src, cooldown_central))
return FALSE

high_command_announce(input, user)
Expand All @@ -211,7 +211,7 @@
to_chat(user, SPAN_WARNING("Please allow at least [COOLDOWN_TIMELEFT(src, cooldown_message)/10] second\s to pass between announcements."))
return FALSE
var/input = stripped_multiline_input(user, "Please write a message to announce to the station crew.", "Priority Announcement", "")
if(!input || !COOLDOWN_FINISHED(src, cooldown_message) || !(user in view(1,src)))
if(!input || !COOLDOWN_FINISHED(src, cooldown_message) || !(user in dview(1, src)))
return FALSE

var/signed = null
Expand Down
4 changes: 2 additions & 2 deletions code/game/machinery/computer/communications.dm
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,7 @@
to_chat(usr, SPAN_WARNING("Please allow at least [COOLDOWN_COMM_MESSAGE_LONG*0.1] second\s to pass between announcements."))
return FALSE
var/input = stripped_multiline_input(usr, "Please write a message to announce to the station crew.", "Priority Announcement", "")
if(!input || authenticated != 2 || world.time < cooldown_message + COOLDOWN_COMM_MESSAGE_LONG || !(usr in view(1,src)))
if(!input || authenticated != 2 || world.time < cooldown_message + COOLDOWN_COMM_MESSAGE_LONG || !(usr in dview(1, src)))
return FALSE

marine_announcement(input)
Expand Down Expand Up @@ -302,7 +302,7 @@
to_chat(usr, SPAN_WARNING("Arrays recycling. Please stand by."))
return FALSE
var/input = stripped_input(usr, "Please choose a message to transmit to USCM. Please be aware that this process is very expensive, and abuse will lead to termination. Transmission does not guarantee a response. There is a small delay before you may send another message. Be clear and concise.", "To abort, send an empty message.", "")
if(!input || !(usr in view(1,src)) || authenticated != 2 || world.time < cooldown_central + COOLDOWN_COMM_CENTRAL) return FALSE
if(!input || !(usr in dview(1, src)) || authenticated != 2 || world.time < cooldown_central + COOLDOWN_COMM_CENTRAL) return FALSE

high_command_announce(input, usr)
to_chat(usr, SPAN_NOTICE("Message transmitted."))
Expand Down
2 changes: 1 addition & 1 deletion code/game/machinery/computer/groundside_operations.dm
Original file line number Diff line number Diff line change
Expand Up @@ -235,7 +235,7 @@
to_chat(usr, SPAN_WARNING("Access denied."))
return
var/input = stripped_multiline_input(usr, "Please write a message to announce to the station crew.", "Priority Announcement", "")
if(!input || !is_announcement_active || !(usr in view(1,src)))
if(!input || !is_announcement_active || !(usr in dview(1, src)))
return FALSE

is_announcement_active = FALSE
Expand Down
3 changes: 2 additions & 1 deletion code/game/objects/effects/effect_system/chemsmoke.dm
Original file line number Diff line number Diff line change
Expand Up @@ -57,10 +57,11 @@
targetTurfs = new()

//build affected area list
for(var/turf/T in view(range, location))
FOR_DVIEW(var/turf/T, range, location, HIDE_INVISIBLE_OBSERVER)
//cull turfs to circle
if(cheap_pythag(T.x - location.x, T.y - location.y) <= range)
targetTurfs += T
FOR_DVIEW_END

//make secondary list for reagents that affect walls
if(chemholder.reagents.has_reagent("thermite") || chemholder.reagents.has_reagent("plantbgone"))
Expand Down
2 changes: 1 addition & 1 deletion code/game/objects/items/devices/cictablet.dm
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@
return FALSE

var/input = stripped_multiline_input(user, "Please write a message to announce to the [MAIN_SHIP_NAME]'s crew and all groundside personnel.", "Priority Announcement", "")
if(!input || !COOLDOWN_FINISHED(src, announcement_cooldown) || !(user in view(1, src)))
if(!input || !COOLDOWN_FINISHED(src, announcement_cooldown) || !(user in dview(1, src)))
return FALSE

var/signed = null
Expand Down
4 changes: 2 additions & 2 deletions code/game/objects/items/devices/pinpointer.dm
Original file line number Diff line number Diff line change
Expand Up @@ -126,10 +126,10 @@
mode = 1

var/locationx = tgui_input_real_number(usr, "Please input the x coordinate to search for.", "Location?")
if(!locationx || !(usr in view(1,src)))
if(!locationx || !(usr in dview(1, src)))
return
var/locationy = tgui_input_real_number(usr, "Please input the y coordinate to search for.", "Location?")
if(!locationy || !(usr in view(1,src)))
if(!locationy || !(usr in dview(1, src)))
return

var/turf/Z = get_turf(src)
Expand Down
4 changes: 3 additions & 1 deletion code/game/objects/structures/tables_racks.dm
Original file line number Diff line number Diff line change
Expand Up @@ -385,9 +385,11 @@
to_chat(usr, SPAN_WARNING("You have moved a table too recently."))
return FALSE

for(var/mob/living/mob_behind_table in oview(src, 0))
FOR_DOVIEW(var/mob/living/mob_behind_table, 0, src, HIDE_INVISIBLE_OBSERVER)
to_chat(usr, SPAN_WARNING("[mob_behind_table] is in the way of [src]."))
FOR_DVIEW_END
return FALSE
FOR_DVIEW_END

var/list/directions = list()
if(direction)
Expand Down
6 changes: 4 additions & 2 deletions code/game/turfs/turf.dm
Original file line number Diff line number Diff line change
Expand Up @@ -478,18 +478,20 @@

/turf/proc/AdjacentTurfs()
var/L[] = new()
for(var/turf/t in oview(src,1))
FOR_DOVIEW(var/turf/t, 1, src, HIDE_INVISIBLE_OBSERVER)
if(!t.density)
if(!LinkBlocked(src, t) && !TurfBlockedNonWindow(t))
L.Add(t)
FOR_DOVIEW_END
return L

/turf/proc/AdjacentTurfsSpace()
var/L[] = new()
for(var/turf/t in oview(src,1))
FOR_DOVIEW(var/turf/t, 1, src, HIDE_INVISIBLE_OBSERVER)
if(!t.density)
if(!LinkBlocked(src, t) && !TurfBlockedNonWindow(t))
L.Add(t)
FOR_DOVIEW_END
return L

/turf/proc/Distance(turf/t)
Expand Down
3 changes: 2 additions & 1 deletion code/modules/cm_tech/droppod/droppod.dm
Original file line number Diff line number Diff line change
Expand Up @@ -168,8 +168,9 @@
for(var/obj/structure/machinery/defenses/def in loc)
qdel(def)

for(var/mob/mob in view(7, loc))
FOR_DVIEW(var/mob/mob, 7, loc, HIDE_INVISIBLE_OBSERVER)
shake_camera(mob, 4, 5)
FOR_DVIEW_END

addtimer(CALLBACK(src, PROC_REF(open)), open_time)

Expand Down
6 changes: 4 additions & 2 deletions code/modules/defenses/tesla_coil.dm
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@
/obj/structure/machinery/defenses/tesla_coil/proc/get_target()
targets = list()

for(var/mob/living/M in oview(tesla_range, src))
FOR_DOVIEW(var/mob/living/M, tesla_range, src, HIDE_INVISIBLE_OBSERVER)
if(M.stat == DEAD)
continue
if(HAS_TRAIT(M, TRAIT_CHARGING))
Expand All @@ -81,10 +81,12 @@
continue

targets += M
FOR_DOVIEW_END

for(var/obj/structure/machinery/defenses/D in oview(tesla_range, src))
FOR_DOVIEW(var/obj/structure/machinery/defenses/D, tesla_range, src, HIDE_INVISIBLE_OBSERVER)
if(D.turned_on)
targets += D
FOR_DOVIEW_END

/obj/structure/machinery/defenses/tesla_coil/proc/fire(atoms)
if(!(world.time - last_fired >= fire_delay) || !turned_on)
Expand Down
3 changes: 2 additions & 1 deletion code/modules/mob/living/carbon/human/say.dm
Original file line number Diff line number Diff line change
Expand Up @@ -134,9 +134,10 @@
return
if(RADIO_CHANNEL_INTERCOM)
message_mode = null
for(var/obj/item/device/radio/intercom/I in view(1))
FOR_DVIEW(var/obj/item/device/radio/intercom/I, 1, src, HIDE_INVISIBLE_OBSERVER)
used_radios += I
break // remove this if we EVER have two different intercomms with DIFFERENT frequencies IN ONE ROOM
FOR_DVIEW_END
else
if(message_mode != MESSAGE_MODE_LOCAL)
var/earpiece = get_type_in_ears(/obj/item/device/radio)
Expand Down
3 changes: 2 additions & 1 deletion code/modules/mob/living/carbon/human/whisper.dm
Original file line number Diff line number Diff line change
Expand Up @@ -79,10 +79,11 @@
listening += C

//pass on the message to objects that can hear us.
for (var/obj/O in view(message_range, src))
FOR_DVIEW(var/obj/O, message_range, src, HIDE_INVISIBLE_OBSERVER)
spawn (0)
if (O)
O.hear_talk(src, message) //O.hear_talk(src, message, verb, speaking)
FOR_DVIEW_END

var/list/eavesdropping = hearers(eavesdropping_range, src)
eavesdropping -= src
Expand Down
9 changes: 6 additions & 3 deletions code/modules/mob/living/carbon/xenomorph/Abilities.dm
Original file line number Diff line number Diff line change
Expand Up @@ -144,16 +144,18 @@
xeno.visible_message(SPAN_XENOHIGHDANGER("[xeno] emits an ear-splitting guttural roar!"))
xeno.create_shriekwave(14) //Adds the visual effect. Wom wom wom, 14 shriekwaves

for(var/mob/mob in view())
FOR_DVIEW(var/mob/mob, world.view, owner, HIDE_INVISIBLE_OBSERVER)
if(mob && mob.client)
if(isxeno(mob))
shake_camera(mob, 10, 1)
else
shake_camera(mob, 30, 1) //50 deciseconds, SORRY 5 seconds was way too long. 3 seconds now
FOR_DVIEW_END

var/list/mobs_in_view = list()
for(var/mob/living/carbon/M in oview(7, xeno))
FOR_DOVIEW(var/mob/living/carbon/M, 7, xeno, HIDE_INVISIBLE_OBSERVER)
mobs_in_view += M
FOR_DOVIEW_END
for(var/mob/living/carbon/M in orange(10, xeno))
if(SEND_SIGNAL(M, COMSIG_MOB_SCREECH_ACT, xeno) & COMPONENT_SCREECH_ACT_CANCEL)
continue
Expand Down Expand Up @@ -247,14 +249,15 @@
var/whisper = strip_html(input("Message:", "Psychic Radiance") as text|null)
if(!whisper || !xeno_player.check_state(TRUE))
return
for(var/mob/living/possible_target in view(12, xeno_player))
FOR_DVIEW(var/mob/living/possible_target, 12, xeno_player, HIDE_INVISIBLE_OBSERVER)
if(possible_target == xeno_player || !possible_target.client)
continue
target_list += possible_target
if(!istype(possible_target, /mob/living/carbon/xenomorph))
to_chat(possible_target, SPAN_XENOQUEEN("You hear a strange, alien voice in your head. \"[whisper]\""))
else
to_chat(possible_target, SPAN_XENOQUEEN("You hear the voice of [xeno_player] resonate in your head. \"[whisper]\""))
FOR_DVIEW_END
if(!length(target_list))
return
var/targetstring = english_list(target_list)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
playsound(xeno.loc, pick(predalien_roar), 75, 0, status = 0)
xeno.visible_message(SPAN_XENOHIGHDANGER("[xeno] emits a guttural roar!"))
xeno.create_shriekwave(7) //Adds the visual effect. Wom wom wom, 7 shriekwaves
for(var/mob/living/carbon/carbon in view(7, xeno))
FOR_DVIEW(var/mob/living/carbon/carbon, 7, xeno, HIDE_INVISIBLE_OBSERVER)
if(ishuman(carbon))
var/mob/living/carbon/human/human = carbon
human.disable_special_items()
Expand All @@ -29,6 +29,7 @@
if(!istype(behavior))
continue
new /datum/effects/xeno_buff(carbon, xeno, ttl = (0.25 SECONDS * behavior.kills + 3 SECONDS), bonus_damage = bonus_damage_scale * behavior.kills, bonus_speed = (bonus_speed_scale * behavior.kills))
FOR_DVIEW_END

apply_cooldown()
return ..()
Expand Down
Loading

0 comments on commit bf69d10

Please sign in to comment.