mirror of
https://github.com/Aurorastation/Aurora.3.git
synced 2026-07-18 19:39:42 +01:00
Fixes mobs being unable to hear from inside machines or objects. (#14823)
This commit is contained in:
@@ -52,6 +52,8 @@
|
||||
|
||||
#define isbrain(A) istype(A, /mob/living/carbon/brain)
|
||||
|
||||
#define isvirtualmob(A) istype(A, /mob/abstract/observer/virtual)
|
||||
|
||||
#define iscarbon(A) istype(A, /mob/living/carbon)
|
||||
|
||||
#define iscorgi(A) istype(A, /mob/living/simple_animal/corgi)
|
||||
|
||||
@@ -11,4 +11,4 @@
|
||||
dview_mob.loc = center; \
|
||||
dview_mob.see_invisible = invis_flags; \
|
||||
output = view(range, dview_mob); \
|
||||
dview_mob.loc = null;
|
||||
dview_mob.loc = null;
|
||||
@@ -150,15 +150,11 @@
|
||||
SearchVar(round_progressing)
|
||||
SearchVar(master_mode)
|
||||
SearchVar(secret_force_mode)
|
||||
SearchVar(host)
|
||||
SearchVar(jobMax)
|
||||
SearchVar(bombers)
|
||||
SearchVar(admin_log)
|
||||
SearchVar(lastsignalers)
|
||||
SearchVar(lawchanges)
|
||||
SearchVar(reg_dna)
|
||||
SearchVar(monkeystart)
|
||||
SearchVar(wizardstart)
|
||||
SearchVar(newplayer_start)
|
||||
SearchVar(latejoin)
|
||||
SearchVar(latejoin_gateway)
|
||||
@@ -167,15 +163,10 @@
|
||||
SearchVar(latejoin_merchant)
|
||||
SearchVar(latejoin_living_quarters_lift)
|
||||
SearchVar(kickoffsloc)
|
||||
SearchVar(prisonwarp)
|
||||
SearchVar(holdingfacility)
|
||||
SearchVar(xeno_spawn)
|
||||
SearchVar(tdome1)
|
||||
SearchVar(tdome2)
|
||||
SearchVar(tdomeobserve)
|
||||
SearchVar(tdomeadmin)
|
||||
SearchVar(prisonsecuritywarp)
|
||||
SearchVar(prisonwarped)
|
||||
SearchVar(ninjastart)
|
||||
SearchVar(cardinal)
|
||||
SearchVar(cornerdirs)
|
||||
|
||||
@@ -48,6 +48,10 @@
|
||||
if (bound_overlay)
|
||||
QDEL_NULL(bound_overlay)
|
||||
|
||||
if(virtual_mob && !ispath(virtual_mob))
|
||||
qdel(virtual_mob)
|
||||
virtual_mob = null
|
||||
|
||||
// This is called when this atom is prevented from moving by atom/A.
|
||||
/atom/movable/proc/Collide(atom/A)
|
||||
if(airflow_speed > 0 && airflow_dest)
|
||||
|
||||
@@ -16,10 +16,6 @@
|
||||
|
||||
/obj/effect/landmark/proc/do_landmark_effect()
|
||||
switch(name) //some of these are probably obsolete
|
||||
if("monkey")
|
||||
monkeystart += loc
|
||||
delete_me = 1
|
||||
return
|
||||
if("start")
|
||||
newplayer_start = get_turf(loc)
|
||||
delete_me = 1
|
||||
@@ -55,12 +51,6 @@
|
||||
latejoin_merchant += loc
|
||||
delete_me = 1
|
||||
return
|
||||
if("prisonwarp")
|
||||
prisonwarp += loc
|
||||
delete_me = 1
|
||||
return
|
||||
if("Holding Facility")
|
||||
holdingfacility += loc
|
||||
if("tdome1")
|
||||
tdome1 += loc
|
||||
if("tdome2")
|
||||
@@ -69,14 +59,6 @@
|
||||
tdomeadmin += loc
|
||||
if("tdomeobserve")
|
||||
tdomeobserve += loc
|
||||
if("prisonsecuritywarp")
|
||||
prisonsecuritywarp += loc
|
||||
delete_me = 1
|
||||
return
|
||||
if("xeno_spawn")
|
||||
xeno_spawn += loc
|
||||
delete_me = 1
|
||||
return
|
||||
if("endgame_exit")
|
||||
endgame_safespawns += loc
|
||||
delete_me = 1
|
||||
|
||||
@@ -34,9 +34,6 @@ var/round_progressing = 1
|
||||
var/master_mode = "extended" // "extended"
|
||||
var/secret_force_mode = "secret" // if this is anything but "secret", the secret rotation will forceably choose this mode.
|
||||
|
||||
var/host = null //only here until check @ code\modules\ghosttrap\trap.dm:112 is fixed
|
||||
|
||||
var/list/jobMax = list()
|
||||
var/list/bombers = list()
|
||||
var/list/admin_log = list()
|
||||
var/list/signal_log = list()
|
||||
@@ -44,8 +41,6 @@ var/list/lastsignalers = list() // Keeps last 100 signals here in format: "[src]
|
||||
var/list/lawchanges = list() // Stores who uploaded laws to which silicon-based lifeform, and what the law was.
|
||||
var/list/reg_dna = list()
|
||||
|
||||
var/list/monkeystart = list()
|
||||
var/list/wizardstart = list()
|
||||
var/turf/newplayer_start = null
|
||||
|
||||
//Spawnpoints.
|
||||
@@ -59,16 +54,11 @@ var/list/latejoin_living_quarters_lift = list()
|
||||
var/list/kickoffsloc = list()
|
||||
var/list/virtual_reality_spawn = list()
|
||||
|
||||
var/list/prisonwarp = list() // Prisoners go to these
|
||||
var/list/holdingfacility = list() // Captured people go here
|
||||
var/list/xeno_spawn = list() // Aliens spawn at at these.
|
||||
var/list/asteroid_spawn = list() // Asteroid "Dungeons" spawn at these.
|
||||
var/list/tdome1 = list()
|
||||
var/list/tdome2 = list()
|
||||
var/list/tdomeobserve = list()
|
||||
var/list/tdomeadmin = list()
|
||||
var/list/prisonsecuritywarp = list() // Prison security goes to these.
|
||||
var/list/prisonwarped = list() // List of players already warped.
|
||||
var/list/ninjastart = list()
|
||||
|
||||
var/list/cardinal = list(NORTH, SOUTH, EAST, WEST)
|
||||
|
||||
@@ -77,8 +77,7 @@ proc/admin_notice(var/message, var/rights)
|
||||
"}
|
||||
|
||||
if(M.client)
|
||||
body += "| <A HREF='?src=\ref[src];sendtoprison=\ref[M]'>Prison</A> | "
|
||||
body += "<a href='?src=\ref[src];admin_wind_player=\ref[M]'>Wind</a> | "
|
||||
body += "| <a href='?src=\ref[src];admin_wind_player=\ref[M]'>Wind</a> | "
|
||||
body += "\ <A HREF='?src=\ref[src];sendbacktolobby=\ref[M]]'>Send back to Lobby</A>"
|
||||
var/muted = M.client.prefs.muted
|
||||
body += {"<br><b>Mute: </b>
|
||||
|
||||
@@ -493,47 +493,6 @@
|
||||
log_admin("[key_name(usr)] forced [key_name(M)] to say: [speech]",admin_key=key_name(usr))
|
||||
message_admins("<span class='notice'>[key_name_admin(usr)] forced [key_name_admin(M)] to say: [speech]</span>")
|
||||
|
||||
else if(href_list["sendtoprison"])
|
||||
if(!check_rights(R_ADMIN)) return
|
||||
|
||||
if(alert(usr, "Send to admin prison for the round?", "Message", "Yes", "No") != "Yes")
|
||||
return
|
||||
|
||||
var/mob/M = locate(href_list["sendtoprison"])
|
||||
if(!ismob(M))
|
||||
to_chat(usr, "This can only be used on instances of type /mob")
|
||||
return
|
||||
if(istype(M, /mob/living/silicon/ai))
|
||||
to_chat(usr, "This cannot be used on instances of type /mob/living/silicon/ai")
|
||||
return
|
||||
|
||||
var/turf/prison_cell = pick(prisonwarp)
|
||||
if(!prison_cell) return
|
||||
|
||||
var/obj/structure/closet/secure_closet/brig/locker = new /obj/structure/closet/secure_closet/brig(prison_cell)
|
||||
locker.opened = 0
|
||||
locker.locked = 1
|
||||
|
||||
//strip their stuff and stick it in the crate
|
||||
for(var/obj/item/I in M)
|
||||
M.drop_from_inventory(I, locker)
|
||||
M.update_icon()
|
||||
|
||||
//so they black out before warping
|
||||
M.Paralyse(5)
|
||||
sleep(5)
|
||||
if(!M) return
|
||||
|
||||
M.forceMove(prison_cell)
|
||||
if(istype(M, /mob/living/carbon/human))
|
||||
var/mob/living/carbon/human/prisoner = M
|
||||
prisoner.equip_to_slot_or_del(new /obj/item/clothing/under/color/orange(prisoner), slot_w_uniform)
|
||||
prisoner.equip_to_slot_or_del(new /obj/item/clothing/shoes/orange(prisoner), slot_shoes)
|
||||
|
||||
to_chat(M, "<span class='warning'>You have been sent to the prison station!</span>")
|
||||
log_admin("[key_name(usr)] sent [key_name(M)] to the prison station.",,admin_key=key_name(usr),ckey=key_name(M))
|
||||
message_admins("<span class='notice'>[key_name_admin(usr)] sent [key_name_admin(M)] to the prison station.</span>", 1)
|
||||
|
||||
else if(href_list["sendbacktolobby"])
|
||||
if(!check_rights(R_ADMIN))
|
||||
return
|
||||
|
||||
@@ -16,32 +16,6 @@
|
||||
message_admins("[key_name_admin(usr)] made [key_name_admin(M)] drop everything!", 1)
|
||||
feedback_add_details("admin_verb","DEVR") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
|
||||
|
||||
/client/proc/cmd_admin_prison(mob/M as mob in mob_list)
|
||||
set category = "Admin"
|
||||
set name = "Prison"
|
||||
if(!holder)
|
||||
to_chat(src, "Only administrators may use this command.")
|
||||
return
|
||||
if (ismob(M))
|
||||
if(istype(M, /mob/living/silicon/ai))
|
||||
alert("The AI can't be sent to prison you jerk!", null, null, null, null, null)
|
||||
return
|
||||
//strip their stuff before they teleport into a cell :downs:
|
||||
for(var/obj/item/W in M)
|
||||
M.drop_from_inventory(W)
|
||||
//teleport person to cell
|
||||
M.Paralyse(5)
|
||||
sleep(5) //so they black out before warping
|
||||
M.forceMove(pick(prisonwarp))
|
||||
if(istype(M, /mob/living/carbon/human))
|
||||
var/mob/living/carbon/human/prisoner = M
|
||||
prisoner.equip_to_slot_or_del(new /obj/item/clothing/under/color/orange(prisoner), slot_w_uniform)
|
||||
prisoner.equip_to_slot_or_del(new /obj/item/clothing/shoes/orange(prisoner), slot_shoes)
|
||||
spawn(50)
|
||||
to_chat(M, "<span class='danger'>You have been sent to the prison station!</span>")
|
||||
log_admin("[key_name(usr)] sent [key_name(M)] to the prison station.",admin_key=key_name(usr),ckey=key_name(M))
|
||||
message_admins("<span class='notice'>[key_name_admin(usr)] sent [key_name_admin(M)] to the prison station.</span>", 1)
|
||||
feedback_add_details("admin_verb","PRISON") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
|
||||
|
||||
/client/proc/cmd_admin_subtle_message(mob/M as mob in mob_list)
|
||||
set category = "Special Verbs"
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
|
||||
anchored = 1 // don't get pushed around
|
||||
simulated = FALSE
|
||||
virtual_mob = null // Hear no evil, speak no evil
|
||||
|
||||
var/last_ready_name // This has to be saved because the client is nulled prior to Logout()
|
||||
|
||||
|
||||
@@ -1,13 +1,103 @@
|
||||
/proc/mobs_in_range(var/atom/movable/AM)
|
||||
. = list()
|
||||
for(var/mob/abstract/observer/virtual/v_mob in range(world.view, get_turf(AM)))
|
||||
if(ismob(v_mob.host))
|
||||
. += v_mob.host
|
||||
/*
|
||||
* These calls could easily be setup to be a bunch of call()() with relevant procs and predicates but performance is a concern.
|
||||
* BYOND is also a bit inflexible, as some predicates are of the sort /proc/name(host), others host.proc_name(), and some even do host.proc_name(parameter).
|
||||
* Nothing that cannot be worked around, but it'd be a little messy. I miss C# lambdas...
|
||||
*/
|
||||
|
||||
/proc/clients_in_range(var/atom/movable/AM)
|
||||
// Procs are arranged by "in range/hearers/viewers()" usage, as opposed to virtual mob hear/see abilities.
|
||||
// Most of these procs can technically take any movable atom but unless they have a virtual mob the returned objects may not be the expected ones
|
||||
|
||||
#define ACQUIRE_VIRTUAL_OR_TURF(A) A = (isvirtualmob(A) ? A : (((istype(A) && A.virtual_mob) ? A.virtual_mob : get_turf(A)))) ; if(!A) return
|
||||
#define ACQUIRE_VIRTUAL_OR_RETURN(A) A = (isvirtualmob(A) ? A : (((istype(A) && A.virtual_mob) ? A.virtual_mob : null))) ; if(!A) return
|
||||
|
||||
/****************
|
||||
* Range Helpers *
|
||||
****************/
|
||||
/proc/clients_in_range(var/atom/movable/center_vmob)
|
||||
. = list()
|
||||
for(var/mob/abstract/observer/virtual/v_mob in range(world.view, get_turf(AM)))
|
||||
if(ismob(v_mob.host))
|
||||
var/mob/M = v_mob.host
|
||||
if(M.client)
|
||||
. |= M.client
|
||||
|
||||
ACQUIRE_VIRTUAL_OR_TURF(center_vmob)
|
||||
for(var/mob/abstract/observer/virtual/v_mob in range(world.view, center_vmob))
|
||||
var/client/C = v_mob.get_client()
|
||||
if(C)
|
||||
. |= C
|
||||
|
||||
/proc/hearers_in_range(var/atom/movable/center_vmob, var/hearing_range = world.view)
|
||||
. = list()
|
||||
|
||||
ACQUIRE_VIRTUAL_OR_TURF(center_vmob)
|
||||
for(var/mob/abstract/observer/virtual/v_mob in range(hearing_range, center_vmob))
|
||||
if(v_mob.abilities & VIRTUAL_ABILITY_HEAR)
|
||||
. |= v_mob.host
|
||||
|
||||
/proc/viewers_in_range(var/atom/movable/center_vmob)
|
||||
. = list()
|
||||
|
||||
ACQUIRE_VIRTUAL_OR_TURF(center_vmob)
|
||||
for(var/mob/abstract/observer/virtual/v_mob in range(world.view, center_vmob))
|
||||
if(v_mob.abilities & VIRTUAL_ABILITY_SEE)
|
||||
. |= v_mob.host
|
||||
|
||||
/***************
|
||||
* Hear Helpers *
|
||||
***************/
|
||||
// A mob hears another mob if they have direct line of sight, ignoring turf luminosity.
|
||||
// If there is an opaque object beteween the mobs then they cannot hear each other, even if their respective turfs can be seen.
|
||||
// Thus, unlike viewing hearing is communicative. I.e. if Mob A can hear Mob B then Mob B can also hear Mob A.
|
||||
|
||||
// Gets the hosts of all the virtual mobs that can hear the given movable atom (or rather, it's virtual mob or turf in that existence order)
|
||||
/proc/all_hearers(var/atom/movable/heard_vmob, var/range = world.view)
|
||||
. = list()
|
||||
|
||||
ACQUIRE_VIRTUAL_OR_TURF(heard_vmob)
|
||||
for(var/mob/abstract/observer/virtual/v_mob in hearers(range, heard_vmob))
|
||||
if(v_mob.abilities & VIRTUAL_ABILITY_HEAR)
|
||||
. |= v_mob.host
|
||||
|
||||
/***************
|
||||
* View Helpers *
|
||||
***************/
|
||||
// A mob can see another mob if:
|
||||
// * Within visual range, with the following differences for (N)PCs.
|
||||
// * PCs: Target is within client.view range, with center originating from either the mob or client.eye depending on client.eye_perspective.
|
||||
// * NPCs: Target is within world.view range, with center always originating from the mob.
|
||||
// * Either of the following is true:
|
||||
// * The target mob is in direct line of sight and not standing on a turf with luminosity = 0 unless the viewing mob is close enough for see_in_dark to also be in range
|
||||
// * The viewing mob has the SEE_MOBS sight flag.
|
||||
|
||||
// Gets the hosts of all virtual mobs that can see the given atom movable as well as its turf
|
||||
/proc/all_viewers(var/mob/abstract/observer/virtual/viewed_atom)
|
||||
. = list()
|
||||
|
||||
viewed_atom = istype(viewed_atom) ? viewed_atom.host : viewed_atom
|
||||
var/turf/T = get_turf(viewed_atom)
|
||||
if(!T)
|
||||
return
|
||||
|
||||
for(var/mob/abstract/observer/virtual/seeing_v_mob in viewers(world.view, viewed_atom))
|
||||
if(!(seeing_v_mob.abilities & VIRTUAL_ABILITY_SEE))
|
||||
continue
|
||||
var/atom/movable/host = seeing_v_mob.host
|
||||
if(host.virtual_can_see_turf(T))
|
||||
. |= host
|
||||
|
||||
// This proc returns all hosts of virtual mobs in the given atom's view range (using its turf), ignoring invisibility, VIRUAL_ABILITY_SEE, and most other restrictions.
|
||||
// In most cases you actually want the all_* procs above. This helper was designed with LOOC in mind.
|
||||
/proc/hosts_in_view_range(var/atom/movable/viewing_atom, var/range = world.view)
|
||||
. = list()
|
||||
|
||||
ACQUIRE_VIRTUAL_OR_TURF(viewing_atom)
|
||||
// As per http://www.byond.com/docs/ref/info.html#/proc/view by using a non-mob/client this automatically skips the vast majority of sight checks
|
||||
for(var/mob/abstract/observer/virtual/v_mob in viewers(range, get_turf(viewing_atom.loc)))
|
||||
. |= v_mob.host
|
||||
|
||||
/*
|
||||
Misc. helper
|
||||
*/
|
||||
|
||||
// Eye mobs technically see everything always, the owner just has an overlay applied, thus this helper
|
||||
/atom/movable/proc/virtual_can_see_turf(var/turf/T)
|
||||
return TRUE // We assume objects have already been filtered using viewers() or similar proc
|
||||
|
||||
#undef ACQUIRE_VIRTUAL_OR_TURF
|
||||
#undef ACQUIRE_VIRTUAL_OR_RETURN
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
/mob/living/carbon/human/dummy
|
||||
real_name = "Test Dummy"
|
||||
status_flags = GODMODE|CANPUSH
|
||||
virtual_mob = null
|
||||
|
||||
/mob/living/carbon/human/dummy/mannequin
|
||||
mob_thinks = FALSE
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
animate_movement = 2
|
||||
flags = PROXMOVE
|
||||
sight = DEFAULT_SIGHT
|
||||
virtual_mob = /mob/abstract/observer/virtual/mob
|
||||
var/datum/mind/mind
|
||||
|
||||
var/stat = 0 //Whether a mob is alive or dead. TODO: Move this to living - Nodrak
|
||||
|
||||
@@ -1290,3 +1290,15 @@ proc/is_blind(A)
|
||||
|
||||
/mob/proc/get_talk_bubble()
|
||||
return 'icons/mob/talk.dmi'
|
||||
|
||||
/datum/proc/get_client()
|
||||
return null
|
||||
|
||||
/client/get_client()
|
||||
return src
|
||||
|
||||
/mob/get_client()
|
||||
return client
|
||||
|
||||
/mob/abstract/observer/virtual/get_client()
|
||||
return host.get_client()
|
||||
|
||||
@@ -77,7 +77,7 @@
|
||||
|
||||
if(href_list["send"])
|
||||
radio.send_signal("ACTIVATE")
|
||||
computer.output_message("[icon2html(host, viewers(get_turf(src)))] *beep* *beep*", 1)
|
||||
computer.output_message("[icon2html(computer, viewers(get_turf(src)))] *beep* *beep*", 1)
|
||||
return TRUE
|
||||
|
||||
else if(href_list["freq"])
|
||||
|
||||
@@ -12,7 +12,6 @@
|
||||
s["enter"] = config.enter_allowed
|
||||
s["vote"] = config.allow_vote_mode
|
||||
s["ai"] = config.allow_ai
|
||||
s["host"] = host ? host : null
|
||||
s["stationtime"] = worldtime2text()
|
||||
s["roundduration"] = get_round_duration_formatted()
|
||||
s["gameid"] = game_id
|
||||
|
||||
@@ -49,6 +49,8 @@ datum/unit_test/observation/moved_shall_not_register_on_enter_without_listeners/
|
||||
var/turf/T = locate(20,20,1)
|
||||
var/mob/living/carbon/human/H = new(T)
|
||||
var/obj/structure/closet/C = new(T)
|
||||
qdel(H.virtual_mob)
|
||||
H.virtual_mob = null
|
||||
|
||||
H.forceMove(C)
|
||||
if(!is_listening_to_movement(C, H))
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
################################
|
||||
# Example Changelog File
|
||||
#
|
||||
# Note: This file, and files beginning with ".", and files that don't end in ".yml" will not be read. If you change this file, you will look really dumb.
|
||||
#
|
||||
# Your changelog will be merged with a master changelog. (New stuff added only, and only on the date entry for the day it was merged.)
|
||||
# When it is, any changes listed below will disappear.
|
||||
#
|
||||
# Valid Prefixes:
|
||||
# bugfix
|
||||
# wip (For works in progress)
|
||||
# tweak
|
||||
# soundadd
|
||||
# sounddel
|
||||
# rscadd (general adding of nice things)
|
||||
# rscdel (general deleting of nice things)
|
||||
# imageadd
|
||||
# imagedel
|
||||
# maptweak
|
||||
# spellcheck (typo fixes)
|
||||
# experiment
|
||||
# balance
|
||||
# admin
|
||||
# backend
|
||||
# security
|
||||
# refactor
|
||||
#################################
|
||||
|
||||
# Your name.
|
||||
author: MattAtlas
|
||||
|
||||
# Optional: Remove this file after generating master changelog. Useful for PR changelogs that won't get used again.
|
||||
delete-after: True
|
||||
|
||||
# Any changes you've made. See valid prefix list above.
|
||||
# INDENT WITH TWO SPACES. NOT TABS. SPACES.
|
||||
# SCREW THIS UP AND IT WON'T WORK.
|
||||
# Also, all entries are changed into a single [] after a master changelog generation. Just remove the brackets when you add new entries.
|
||||
# Please surround your changes in double quotes ("), as certain characters otherwise screws up compiling. The quotes will not show up in the changelog.
|
||||
changes:
|
||||
- bugfix: "Fixed mobs being unable to hear from inside machines or objects."
|
||||
Reference in New Issue
Block a user