mirror of
https://github.com/Aurorastation/Aurora.3.git
synced 2026-08-23 13:05:44 +01:00
Fix for https://aurorastation.sentry.io/issues/7405225650 Which is a significant cause for server lag during "ship combat events". I can no joke see the exact times ship combats occcured just by looking at the timing chart for when this runtime gets reported.
313 lines
13 KiB
Plaintext
313 lines
13 KiB
Plaintext
#define SENSORS_DISTANCE_COEFFICIENT 5
|
|
/obj/machinery/computer/ship/sensors
|
|
var/list/objects_in_view = list() // Associative list of objects in view -> identification process
|
|
var/list/contact_datums = list() // Associate an /obj/effect -> /datum/overmap_contact
|
|
var/list/trackers = list()
|
|
var/list/datalink_contacts = list() // A list of the datalink contacts we're receiving from the datalinks
|
|
var/tmp/muted = FALSE
|
|
|
|
/obj/machinery/computer/ship/sensors/proc/reveal_contacts(var/mob/user)
|
|
if(user && user.client)
|
|
for(var/key in contact_datums)
|
|
var/datum/overmap_contact/record = contact_datums[key]
|
|
if(record)
|
|
user.client.images |= record.marker
|
|
|
|
/obj/machinery/computer/ship/sensors/proc/hide_contacts(var/mob/user)
|
|
if(user && user.client)
|
|
for(var/key in contact_datums)
|
|
var/datum/overmap_contact/record = contact_datums[key]
|
|
if(record)
|
|
user.client.images -= record.marker
|
|
|
|
/obj/machinery/computer/ship/sensors/process()
|
|
..()
|
|
|
|
update_sound()
|
|
|
|
if(!linked)
|
|
return
|
|
|
|
// Update our own marker icon regardless of power or sensor connections.
|
|
var/sensor_range = 0
|
|
|
|
var/obj/machinery/shipsensors/sensors = get_sensors()
|
|
if(sensors?.use_power)
|
|
sensor_range = round(sensors.range,1)
|
|
var/datum/overmap_contact/self_record = contact_datums[linked]
|
|
if (self_record)
|
|
self_record.update_marker_icon()
|
|
self_record.show()
|
|
|
|
// Update our 'sensor range' (ie. overmap lighting)
|
|
if(!sensors || !sensors.use_power || (stat & (NOPOWER|BROKEN)))
|
|
if(length(datalink_contacts))
|
|
var/remove_link = !sensors || (stat & BROKEN)
|
|
datalink_remove_all_ships_datalink(remove_link)
|
|
for(var/key in contact_datums)
|
|
var/datum/overmap_contact/record = contact_datums[key]
|
|
if(record.effect == linked)
|
|
continue
|
|
qdel(record) // Immediately cut records if power is lost.
|
|
|
|
objects_in_view.Cut()
|
|
else
|
|
self_record?.ping_radar(sensor_range)
|
|
|
|
// What can we see?
|
|
var/list/objects_in_current_view = list()
|
|
|
|
// Find all sectors with a tracker on their z-level. Only works on ships when they are in space.
|
|
for(var/obj/item/ship_tracker/tracker in trackers)
|
|
if(tracker.enabled)
|
|
var/obj/effect/overmap/visitable/tracked_effect = overmap_sectors["[GET_Z(tracker)]"]
|
|
if(tracked_effect && istype(tracked_effect) && tracked_effect != linked && tracked_effect.requires_contact)
|
|
objects_in_current_view[tracked_effect] = TRUE
|
|
objects_in_view[tracked_effect] = 100
|
|
|
|
|
|
// Handle datalinked view
|
|
datalink_process()
|
|
|
|
var/turf/overmap_grid_turf = get_turf(linked)
|
|
|
|
for(var/obj/effect/overmap/contact in view(sensor_range, overmap_grid_turf))
|
|
if(contact == linked)
|
|
continue
|
|
if(!contact.requires_contact) // Only some effects require contact for visibility.
|
|
continue
|
|
|
|
objects_in_current_view[contact] = TRUE
|
|
|
|
if(contact.instant_contact) // Instantly identify the object in range.
|
|
objects_in_view[contact] = 100
|
|
else if(!(contact in objects_in_view))
|
|
objects_in_view[contact] = 0
|
|
|
|
if(sensors.deep_scan_toggled)
|
|
for(var/obj/effect/overmap/contact in range(sensors.deep_scan_range, overmap_grid_turf))
|
|
if(!contact.sensor_range_override)
|
|
continue
|
|
if(contact == linked)
|
|
continue
|
|
if(!contact.requires_contact) // Only some effects require contact for visibility.
|
|
continue
|
|
|
|
objects_in_current_view[contact] = TRUE
|
|
|
|
if(contact.instant_contact) // Instantly identify the object in range.
|
|
objects_in_view[contact] = 100
|
|
else if(!(contact in objects_in_view))
|
|
objects_in_view[contact] = 0
|
|
|
|
for(var/obj/effect/overmap/contact in objects_in_view) //Update everything.
|
|
|
|
// Are we already aware of this object?
|
|
var/datum/overmap_contact/record = contact_datums[contact]
|
|
|
|
// Fade out and remove anything that is out of range.
|
|
if(QDELETED(contact) || !objects_in_current_view[contact]) // Object has exited sensor range.
|
|
if(record)
|
|
animate(record.marker, alpha=0, 2 SECOND, 1, LINEAR_EASING)
|
|
QDEL_IN(record, 2 SECOND) // Need to restart the search if you've lost contact with the object.
|
|
if(contact.scannable) // Scannable objects are the only ones that give off notifications to prevent spam
|
|
visible_message(SPAN_NOTICE("\The [src] states, \"Contact lost with [record.name].\""))
|
|
playsound(loc, 'sound/machines/sensors/contact_lost.ogg', 30, 1)
|
|
objects_in_view -= contact
|
|
continue
|
|
|
|
// Generate contact information for this overmap object.
|
|
var/bearing = get_bearing(contact)
|
|
if(!record) // Begin attempting to identify ship.
|
|
// The chance of detection decreases with distance to the target ship.
|
|
if(contact.scannable && prob((SENSORS_DISTANCE_COEFFICIENT * contact.sensor_visibility)/max(get_dist(linked, contact), 0.5)))
|
|
var/bearing_variability = round(30/sensors.sensor_strength, 5)
|
|
var/bearing_estimate = round(rand(bearing-bearing_variability, bearing+bearing_variability), 5)
|
|
if(bearing_estimate < 0)
|
|
bearing_estimate += 360
|
|
// Give the player an idea of where the ship is in relation to the ship.
|
|
if(objects_in_view[contact] <= 0)
|
|
if(!muted)
|
|
visible_message(SPAN_NOTICE("<b>\The [src]</b> states, \"Unknown contact designation '[contact.unknown_id]' detected nearby, bearing [bearing_estimate], error +/- [bearing_variability]. Beginning trace.\""))
|
|
objects_in_view[contact] = round(sensors.sensor_strength**2)
|
|
else
|
|
objects_in_view[contact] += round(sensors.sensor_strength**2)
|
|
if(!muted)
|
|
visible_message(SPAN_NOTICE("<b>\The [src]</b> states, \"Contact '[contact.unknown_id]' tracing [objects_in_view[contact]]% complete, bearing [bearing_estimate], error +/- [bearing_variability].\""))
|
|
playsound(loc, 'sound/machines/sensors/contactgeneric.ogg', 10, 1) //Let players know there's something nearby.
|
|
if(objects_in_view[contact] >= 100) // Identification complete.
|
|
record = add_contact(contact)
|
|
continue
|
|
// Update identification information for this record.
|
|
record.update_marker_icon()
|
|
if(record.pinged_until <= world.time)
|
|
var/time_delay = max((SENSOR_TIME_DELAY * get_dist(linked, contact)), 1 SECOND)
|
|
record.ping(time_delay)
|
|
|
|
/**
|
|
* Adds an overmap object to the known contacts.
|
|
*/
|
|
/obj/machinery/computer/ship/sensors/proc/add_contact(obj/effect/overmap/contact)
|
|
var/datum/overmap_contact/record = new(src, contact)
|
|
var/bearing = get_bearing(contact)
|
|
contact_datums[contact] = record
|
|
if(contact.scannable)
|
|
playsound(loc, 'sound/machines/sensors/newcontact.ogg', 30, 1)
|
|
visible_message(SPAN_NOTICE("<b>\The [src]</b> states, \"New contact identified, designation [record.name], bearing [bearing].\""))
|
|
record.show()
|
|
animate(record.marker, alpha=255, 2 SECOND, 1, LINEAR_EASING)
|
|
return record
|
|
|
|
/**
|
|
* Gets the bearing of an obj/effect/overmap/contact from src.
|
|
*/
|
|
/obj/machinery/computer/ship/sensors/proc/get_bearing(obj/effect/overmap/contact)
|
|
. = round(90 - Atan2(contact.x - linked.x, contact.y - linked.y),5)
|
|
if(. < 0)
|
|
. += 360
|
|
|
|
/obj/machinery/computer/ship/sensors/attackby(obj/item/attacking_item, mob/user)
|
|
. = ..()
|
|
var/obj/item/multitool/P = attacking_item
|
|
if(!istype(P))
|
|
return
|
|
var/obj/item/ship_tracker/tracker = P.get_buffer()
|
|
if(!tracker || !istype(tracker))
|
|
return
|
|
|
|
if(tracker in trackers)
|
|
trackers -= tracker
|
|
UnregisterSignal(tracker, COMSIG_QDELETING)
|
|
to_chat(user, SPAN_NOTICE("You unlink the tracker in \the [P]'s buffer from \the [src]."))
|
|
return
|
|
trackers += tracker
|
|
RegisterSignal(tracker, COMSIG_QDELETING, PROC_REF(remove_tracker))
|
|
to_chat(user, SPAN_NOTICE("You link the tracker in \the [P]'s buffer to \the [src]."))
|
|
|
|
/obj/machinery/computer/ship/sensors/proc/remove_tracker(obj/item/ship_tracker/tracker)
|
|
trackers -= tracker
|
|
|
|
/obj/machinery/computer/ship/sensors/proc/datalink_process()
|
|
for(var/obj/effect/overmap/visitable/datalink_ship in src.connected.datalinked) // Get ships that are datalinked with us
|
|
for(var/obj/machinery/computer/ship/sensors/sensor_console in datalink_ship.consoles) // Pick one sensor console
|
|
|
|
|
|
var/list/diff_datalink_contacts = list()
|
|
|
|
// If it's not a known datalinked ship already, initalize its list of supplied contacts
|
|
if(!length(datalink_contacts[datalink_ship]))
|
|
datalink_contacts[datalink_ship] = list()
|
|
|
|
datalink_process_all_contacts_of_console(sensor_console, datalink_ship)
|
|
|
|
// If it's a known datalink, compute the lost contacts to remove
|
|
if(datalink_contacts[datalink_ship])
|
|
diff_datalink_contacts = datalink_contacts[datalink_ship] - (sensor_console.objects_in_view + list(datalink_ship))
|
|
|
|
for(var/obj/effect/overmap/datalink_contact in diff_datalink_contacts)
|
|
datalink_remove_contact(datalink_contact, datalink_ship)
|
|
continue
|
|
|
|
// Handle the datalinked ship's own contact
|
|
var/datum/overmap_contact/ship_contact_record = contact_datums[datalink_ship]
|
|
|
|
if(!ship_contact_record)
|
|
datalink_add_contact(datalink_ship, datalink_ship, force = TRUE)
|
|
ship_contact_record = contact_datums[datalink_ship]
|
|
|
|
ship_contact_record.ping()
|
|
ship_contact_record.update_marker_icon()
|
|
|
|
/obj/machinery/computer/ship/sensors/proc/datalink_process_all_contacts_of_console(var/obj/machinery/computer/ship/sensors/sensor_console, var/obj/effect/overmap/visitable/datalink_ship)
|
|
for(var/obj/effect/overmap/datalink_contact in sensor_console.objects_in_view) // Pick one contact that the sensor console has
|
|
if(datalink_contact != src.connected)
|
|
if(!(datalink_contact in datalink_contacts[datalink_ship])) // This is a new datalink contact
|
|
if(!(contact_datums[datalink_contact]))
|
|
datalink_add_contact(datalink_contact, datalink_ship)
|
|
else
|
|
var/datum/overmap_contact/datalink_contact_record = contact_datums[datalink_contact]
|
|
|
|
if(datalink_contact_record && !QDELING(datalink_contact_record))
|
|
datalink_contact_record.ping()
|
|
|
|
|
|
/obj/machinery/computer/ship/sensors/proc/datalink_remove_all_contacts_of_console(var/obj/machinery/computer/ship/sensors/sensor_console, var/obj/effect/overmap/visitable/datalink_ship)
|
|
for(var/obj/effect/overmap/datalink_contact in sensor_console.objects_in_view)
|
|
if(datalink_contact != src.connected)
|
|
datalink_remove_contact(datalink_contact, datalink_ship)
|
|
|
|
|
|
/obj/machinery/computer/ship/sensors/proc/datalink_add_contact(var/obj/effect/overmap/datalink_contact, var/obj/effect/overmap/visitable/datalink_ship, var/force = FALSE)
|
|
if(!(datalink_contact in datalink_contacts[datalink_ship]) && !(objects_in_view[datalink_contact]) || force) // This is a new datalink contact
|
|
|
|
var/datum/overmap_contact/datalink_contact_record = contact_datums[datalink_contact] // Is it already in the contact_datums?
|
|
if(!datalink_contact_record) // If not, create it
|
|
datalink_contact_record = new /datum/overmap_contact(src, datalink_contact)
|
|
contact_datums[datalink_contact] = datalink_contact_record // And add it with its associated effect
|
|
|
|
|
|
if(!QDELING(datalink_contact_record))
|
|
// Show the new contact
|
|
datalink_contact_record.show()
|
|
datalink_contact_record.ping()
|
|
animate(datalink_contact_record.marker, alpha=255, 2 SECOND, 1, LINEAR_EASING)
|
|
datalink_contact_record.update_marker_icon()
|
|
|
|
// Add it to the contact datum
|
|
if(!datalink_contacts[datalink_ship])
|
|
datalink_contacts[datalink_ship] = list()
|
|
datalink_contacts[datalink_ship] |= list(datalink_contact)
|
|
|
|
|
|
/obj/machinery/computer/ship/sensors/proc/datalink_remove_contact(var/obj/effect/overmap/datalink_contact, var/obj/effect/overmap/visitable/datalink_ship)
|
|
var/datum/overmap_contact/datalink_contact_record = contact_datums[datalink_contact] // Retrieve the contact record
|
|
if(!datalink_contact_record)
|
|
return
|
|
animate(datalink_contact_record.marker, alpha=0, 2 SECOND, 1, LINEAR_EASING)
|
|
QDEL_IN(datalink_contact_record, 2 SECOND)
|
|
|
|
if(datalink_contacts[datalink_ship])
|
|
datalink_contacts[datalink_ship] -= list(datalink_contact)
|
|
|
|
|
|
/obj/machinery/computer/ship/sensors/proc/datalink_add_ship_datalink(var/obj/effect/overmap/visitable/datalink_ship)
|
|
datalink_ship.datalinked |= src.connected
|
|
src.connected.datalinked |= datalink_ship
|
|
|
|
/obj/machinery/computer/ship/sensors/proc/datalink_remove_ship_datalink(var/obj/effect/overmap/visitable/datalink_ship, var/remove_link)
|
|
if(datalink_contacts[datalink_ship])
|
|
for(var/obj/machinery/computer/ship/sensors/sensor_console in datalink_ship.consoles)
|
|
// Remove the two ships from each other's datalinked list
|
|
if(remove_link)
|
|
src.connected.datalinked -= datalink_ship
|
|
datalink_ship.datalinked -= src.connected
|
|
|
|
// Removes the ship contact itself from the contacts
|
|
|
|
var/datum/overmap_contact/ship_contact_record = contact_datums[datalink_ship]
|
|
|
|
if(ship_contact_record)
|
|
animate(ship_contact_record.marker, alpha=0, 2 SECOND, 1, LINEAR_EASING)
|
|
QDEL_IN(ship_contact_record, 2 SECOND)
|
|
//contact_datums[datalink_ship] -= ship_contact_record
|
|
|
|
// Remove all contacts
|
|
datalink_remove_all_contacts_of_console(sensor_console, datalink_ship)
|
|
|
|
|
|
datalink_contacts.Remove(datalink_ship)
|
|
|
|
// Recurse the function on the other ship's instance
|
|
sensor_console.datalink_remove_ship_datalink(src.connected, remove_link)
|
|
visible_message(SPAN_NOTICE("<b>\The [src]</b> states, \"A datalink contact was severed! Recalibrating...\""))
|
|
|
|
|
|
/obj/machinery/computer/ship/sensors/proc/datalink_remove_all_ships_datalink(var/remove_link)
|
|
for(var/obj/effect/overmap/visitable/datalink_ship in linked.datalinked)
|
|
for(var/obj/machinery/computer/ship/sensors/sensor_console in datalink_ship.consoles)
|
|
sensor_console.datalink_remove_ship_datalink(linked, remove_link)
|
|
break
|
|
|
|
|
|
#undef SENSORS_DISTANCE_COEFFICIENT
|