mirror of
https://github.com/Aurorastation/Aurora.3.git
synced 2025-12-22 16:12:19 +00:00
Overmap sensors overhaul (#15666)
This commit is contained in:
@@ -111,6 +111,7 @@
|
|||||||
#include "code\_helpers\mouse.dm"
|
#include "code\_helpers\mouse.dm"
|
||||||
#include "code\_helpers\names.dm"
|
#include "code\_helpers\names.dm"
|
||||||
#include "code\_helpers\overlay.dm"
|
#include "code\_helpers\overlay.dm"
|
||||||
|
#include "code\_helpers\overmap.dm"
|
||||||
#include "code\_helpers\sanitize_values.dm"
|
#include "code\_helpers\sanitize_values.dm"
|
||||||
#include "code\_helpers\spatial_info.dm"
|
#include "code\_helpers\spatial_info.dm"
|
||||||
#include "code\_helpers\spawn_sync.dm"
|
#include "code\_helpers\spawn_sync.dm"
|
||||||
@@ -2634,6 +2635,9 @@
|
|||||||
#include "code\modules\overmap\README.dm"
|
#include "code\modules\overmap\README.dm"
|
||||||
#include "code\modules\overmap\sectors.dm"
|
#include "code\modules\overmap\sectors.dm"
|
||||||
#include "code\modules\overmap\spacetravel.dm"
|
#include "code\modules\overmap\spacetravel.dm"
|
||||||
|
#include "code\modules\overmap\contacts\_contacts.dm"
|
||||||
|
#include "code\modules\overmap\contacts\contact_sensors.dm"
|
||||||
|
#include "code\modules\overmap\contacts\tracker.dm"
|
||||||
#include "code\modules\overmap\events\event.dm"
|
#include "code\modules\overmap\events\event.dm"
|
||||||
#include "code\modules\overmap\exoplanets\exoplanet.dm"
|
#include "code\modules\overmap\exoplanets\exoplanet.dm"
|
||||||
#include "code\modules\overmap\exoplanets\exoplanet_skybox.dm"
|
#include "code\modules\overmap\exoplanets\exoplanet_skybox.dm"
|
||||||
|
|||||||
@@ -15,6 +15,7 @@
|
|||||||
#define INVISIBILITY_LIGHTING 20
|
#define INVISIBILITY_LIGHTING 20
|
||||||
#define INVISIBILITY_LEVEL_ONE 35
|
#define INVISIBILITY_LEVEL_ONE 35
|
||||||
#define INVISIBILITY_LEVEL_TWO 45
|
#define INVISIBILITY_LEVEL_TWO 45
|
||||||
|
#define INVISIBILITY_OVERMAP 50
|
||||||
#define INVISIBILITY_OBSERVER 60
|
#define INVISIBILITY_OBSERVER 60
|
||||||
#define INVISIBILITY_EYE 61
|
#define INVISIBILITY_EYE 61
|
||||||
#define INVISIBILITY_SYSTEM 99
|
#define INVISIBILITY_SYSTEM 99
|
||||||
|
|||||||
@@ -12,4 +12,6 @@
|
|||||||
#define OVERMAP_WEAKNESS_MINING 4
|
#define OVERMAP_WEAKNESS_MINING 4
|
||||||
#define OVERMAP_WEAKNESS_EXPLOSIVE 8
|
#define OVERMAP_WEAKNESS_EXPLOSIVE 8
|
||||||
|
|
||||||
|
#define SENSOR_COEFFICENT 1000
|
||||||
|
|
||||||
#define waypoint_sector(waypoint) map_sectors["[waypoint.z]"]
|
#define waypoint_sector(waypoint) map_sectors["[waypoint.z]"]
|
||||||
|
|||||||
9
code/_helpers/overmap.dm
Normal file
9
code/_helpers/overmap.dm
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
var/datum/overmap_sectors = list()
|
||||||
|
var/datum/overmaps_by_name = list()
|
||||||
|
var/datum/overmaps_by_z = list()
|
||||||
|
|
||||||
|
/proc/get_empty_zlevel(var/base_turf_type)
|
||||||
|
if(base_turf_type && base_turf_type != world.turf)
|
||||||
|
for(var/turf/T as anything in block(locate(1, 1, .),locate(world.maxx, world.maxy, .)))
|
||||||
|
T.ChangeTurf(base_turf_type)
|
||||||
|
return world.maxz
|
||||||
@@ -9,6 +9,10 @@
|
|||||||
/proc/cmp_filter_data_priority(list/A, list/B)
|
/proc/cmp_filter_data_priority(list/A, list/B)
|
||||||
return A["priority"] - B["priority"]
|
return A["priority"] - B["priority"]
|
||||||
|
|
||||||
|
// Defining this for future proofing and ease of searching for erroneous usage.
|
||||||
|
/image/proc/add_filter(filter_name, priority, list/params)
|
||||||
|
filters += filter(arglist(params))
|
||||||
|
|
||||||
/atom/movable/proc/add_filter(filter_name, priority, list/params)
|
/atom/movable/proc/add_filter(filter_name, priority, list/params)
|
||||||
LAZYINITLIST(filter_data)
|
LAZYINITLIST(filter_data)
|
||||||
var/list/p = params.Copy()
|
var/list/p = params.Copy()
|
||||||
@@ -46,13 +50,13 @@
|
|||||||
var/list/monkeypatched_params = params.Copy()
|
var/list/monkeypatched_params = params.Copy()
|
||||||
monkeypatched_params.Insert(1, null)
|
monkeypatched_params.Insert(1, null)
|
||||||
var/index = filter_data.Find(filter_name)
|
var/index = filter_data.Find(filter_name)
|
||||||
|
|
||||||
// First, animate ourselves.
|
// First, animate ourselves.
|
||||||
monkeypatched_params[1] = filters[index]
|
monkeypatched_params[1] = filters[index]
|
||||||
animate(arglist(monkeypatched_params))
|
animate(arglist(monkeypatched_params))
|
||||||
|
|
||||||
// If we're being copied by Z-Mimic, update mimics too.
|
// If we're being copied by Z-Mimic, update mimics too.
|
||||||
if (bound_overlay)
|
if (bound_overlay)
|
||||||
for (var/atom/movable/AM as anything in get_above_oo())
|
for (var/atom/movable/AM as anything in get_above_oo())
|
||||||
monkeypatched_params[1] = AM.filters[index]
|
monkeypatched_params[1] = AM.filters[index]
|
||||||
animate(arglist(monkeypatched_params))
|
animate(arglist(monkeypatched_params))
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ var/global/list/map_sectors = list()
|
|||||||
icon_state = "start"
|
icon_state = "start"
|
||||||
requires_power = 0
|
requires_power = 0
|
||||||
base_turf = /turf/unsimulated/map
|
base_turf = /turf/unsimulated/map
|
||||||
|
dynamic_lighting = 0
|
||||||
|
|
||||||
/turf/unsimulated/map
|
/turf/unsimulated/map
|
||||||
icon = 'icons/turf/space.dmi'
|
icon = 'icons/turf/space.dmi'
|
||||||
|
|||||||
111
code/modules/overmap/contacts/_contacts.dm
Normal file
111
code/modules/overmap/contacts/_contacts.dm
Normal file
@@ -0,0 +1,111 @@
|
|||||||
|
#define SENSOR_TIME_DELAY 0.2 SECONDS
|
||||||
|
/datum/overmap_contact
|
||||||
|
|
||||||
|
var/name = "Unknown" // Contact name.
|
||||||
|
var/image/marker // Image overlay attached to the contact.
|
||||||
|
var/pinged = FALSE // Used to animate overmap effects.
|
||||||
|
var/list/images = list() // Our list of images to cast to users.
|
||||||
|
var/image/radar // Radar image for sonar esque effect
|
||||||
|
|
||||||
|
// The sensor console holding this data.
|
||||||
|
var/obj/machinery/computer/ship/sensors/owner
|
||||||
|
|
||||||
|
// The actual overmap effect associated with this.
|
||||||
|
var/obj/effect/overmap/effect
|
||||||
|
|
||||||
|
/datum/overmap_contact/New(var/obj/machinery/computer/ship/sensors/creator, var/obj/effect/overmap/source)
|
||||||
|
// Update local tracking information.
|
||||||
|
owner = creator
|
||||||
|
effect = source
|
||||||
|
name = effect.name
|
||||||
|
owner.contact_datums[effect] = src
|
||||||
|
|
||||||
|
marker = new(loc = effect)
|
||||||
|
update_marker_icon()
|
||||||
|
marker.alpha = 0 // Marker fades in on detection.
|
||||||
|
marker.appearance_flags |= RESET_TRANSFORM
|
||||||
|
|
||||||
|
images += marker
|
||||||
|
|
||||||
|
radar = image(loc = effect, icon = 'icons/obj/overmap.dmi', icon_state = "sensor_range")
|
||||||
|
radar.color = source.color
|
||||||
|
radar.tag = "radar"
|
||||||
|
radar.add_filter("blur", 1, list("blur", size = 1))
|
||||||
|
|
||||||
|
/datum/overmap_contact/proc/update_marker_icon()
|
||||||
|
|
||||||
|
marker.appearance = effect
|
||||||
|
marker.appearance_flags |= RESET_TRANSFORM
|
||||||
|
// Pixel offsets are included in appearance but since this marker's loc
|
||||||
|
// is the effect, it's already offset and we don't want to double it.
|
||||||
|
marker.pixel_x = 0
|
||||||
|
marker.pixel_y = 0
|
||||||
|
|
||||||
|
marker.transform = effect.transform
|
||||||
|
marker.dir = effect.dir
|
||||||
|
marker.overlays.Cut()
|
||||||
|
|
||||||
|
/datum/overmap_contact/proc/ping_radar(var/range = 0)
|
||||||
|
|
||||||
|
radar.transform = null
|
||||||
|
radar.alpha = 255
|
||||||
|
|
||||||
|
if(range > 1)
|
||||||
|
images |= radar
|
||||||
|
|
||||||
|
var/matrix/M = matrix()
|
||||||
|
M.Scale(range*2.6)
|
||||||
|
animate(radar, transform = M, alpha = 0, time = (SENSOR_TIME_DELAY*range), 1, SINE_EASING)
|
||||||
|
else
|
||||||
|
images -= radar
|
||||||
|
|
||||||
|
/datum/overmap_contact/proc/show()
|
||||||
|
if(!owner)
|
||||||
|
return
|
||||||
|
var/list/showing = owner.linked?.navigation_viewers || owner.viewers
|
||||||
|
if(length(showing))
|
||||||
|
for(var/datum/weakref/W in showing)
|
||||||
|
var/mob/M = W.resolve()
|
||||||
|
if(istype(M) && M.client)
|
||||||
|
M.client.images |= images
|
||||||
|
|
||||||
|
|
||||||
|
/datum/overmap_contact/proc/ping()
|
||||||
|
if(pinged)
|
||||||
|
return
|
||||||
|
pinged = TRUE
|
||||||
|
effect.opacity = 1
|
||||||
|
show()
|
||||||
|
animate(marker, alpha=255, 0.5 SECOND, 1, LINEAR_EASING)
|
||||||
|
addtimer(CALLBACK(src, PROC_REF(unping)), 1 SECOND)
|
||||||
|
|
||||||
|
/datum/overmap_contact/proc/unping()
|
||||||
|
animate(marker, alpha=75, 2 SECOND, 1, LINEAR_EASING)
|
||||||
|
pinged = FALSE
|
||||||
|
|
||||||
|
/datum/overmap_contact/Destroy()
|
||||||
|
if(owner)
|
||||||
|
// If we have a lock on what was lost, remove the lock from the targeting consoles
|
||||||
|
if(owner.connected.targeting == effect)
|
||||||
|
for(var/obj/machinery/computer/ship/targeting/console in owner.connected.consoles)
|
||||||
|
owner.connected.detarget(effect, console)
|
||||||
|
|
||||||
|
// Removes the client images from the client of the mobs that are looking at this contact
|
||||||
|
var/list/showing = owner.linked?.navigation_viewers || owner.viewers
|
||||||
|
if(length(showing))
|
||||||
|
for(var/datum/weakref/W in showing)
|
||||||
|
var/mob/M = W.resolve()
|
||||||
|
if(istype(M) && M.client)
|
||||||
|
M.client.images -= images
|
||||||
|
|
||||||
|
// Removes the effect from the contact datums of the owner, and null the owner
|
||||||
|
if(effect)
|
||||||
|
owner.contact_datums -= effect
|
||||||
|
owner = null
|
||||||
|
|
||||||
|
// Remove the effect opacity and null the effect
|
||||||
|
effect.opacity = 0
|
||||||
|
effect = null
|
||||||
|
|
||||||
|
QDEL_NULL_LIST(images)
|
||||||
|
. = ..()
|
||||||
292
code/modules/overmap/contacts/contact_sensors.dm
Normal file
292
code/modules/overmap/contacts/contact_sensors.dm
Normal file
@@ -0,0 +1,292 @@
|
|||||||
|
#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/Destroy()
|
||||||
|
objects_in_view.Cut()
|
||||||
|
trackers.Cut()
|
||||||
|
|
||||||
|
for(var/key in contact_datums)
|
||||||
|
var/datum/overmap_contact/record = contact_datums[key]
|
||||||
|
qdel(record)
|
||||||
|
contact_datums.Cut()
|
||||||
|
. = ..()
|
||||||
|
|
||||||
|
/obj/machinery/computer/ship/sensors/attempt_hook_up(obj/effect/overmap/visitable/ship/sector)
|
||||||
|
. = ..()
|
||||||
|
if(. && linked && !contact_datums[linked])
|
||||||
|
var/datum/overmap_contact/record = new(src, linked)
|
||||||
|
contact_datums[linked] = record
|
||||||
|
record.marker.alpha = 255
|
||||||
|
|
||||||
|
/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]
|
||||||
|
self_record.update_marker_icon()
|
||||||
|
self_record.ping_radar(sensor_range)
|
||||||
|
self_record.show()
|
||||||
|
|
||||||
|
// Update our 'sensor range' (ie. overmap lighting)
|
||||||
|
if(!sensors || !sensors.use_power || (stat & (NOPOWER|BROKEN)))
|
||||||
|
datalink_remove_all_ships_datalink()
|
||||||
|
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()
|
||||||
|
return
|
||||||
|
|
||||||
|
// 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()
|
||||||
|
|
||||||
|
|
||||||
|
for(var/obj/effect/overmap/contact in view(sensor_range, linked))
|
||||||
|
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 = round(90 - Atan2(contact.x - linked.x, contact.y - linked.y),5)
|
||||||
|
if(bearing < 0)
|
||||||
|
bearing += 360
|
||||||
|
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 = new /datum/overmap_contact(src, 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)
|
||||||
|
continue
|
||||||
|
// Update identification information for this record.
|
||||||
|
record.update_marker_icon()
|
||||||
|
|
||||||
|
var/time_delay = max((SENSOR_TIME_DELAY * get_dist(linked, contact)),1)
|
||||||
|
if(!record.pinged)
|
||||||
|
addtimer(CALLBACK(record, PROC_REF(ping)), time_delay)
|
||||||
|
|
||||||
|
/obj/machinery/computer/ship/sensors/attackby(var/obj/item/I, var/mob/user)
|
||||||
|
. = ..()
|
||||||
|
var/obj/item/device/multitool/P = I
|
||||||
|
if(!istype(P))
|
||||||
|
return
|
||||||
|
var/obj/item/ship_tracker/tracker = P.get_buffer()
|
||||||
|
if(!tracker || !istype(tracker))
|
||||||
|
return
|
||||||
|
|
||||||
|
if(tracker in trackers)
|
||||||
|
trackers -= tracker
|
||||||
|
destroyed_event.unregister(tracker, src, PROC_REF(remove_tracker))
|
||||||
|
to_chat(user, SPAN_NOTICE("You unlink the tracker in \the [P]'s buffer from \the [src]."))
|
||||||
|
return
|
||||||
|
trackers += tracker
|
||||||
|
destroyed_event.register(tracker, src, 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(var/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)
|
||||||
|
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
|
||||||
|
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)
|
||||||
|
visible_message(SPAN_NOTICE("<b>\The [src]</b> states, \"A datalink contact was sewered! Recalibration...\""))
|
||||||
|
|
||||||
|
|
||||||
|
/obj/machinery/computer/ship/sensors/proc/datalink_remove_all_ships_datalink()
|
||||||
|
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)
|
||||||
|
break
|
||||||
|
|
||||||
|
|
||||||
|
#undef SENSORS_DISTANCE_COEFFICIENT
|
||||||
23
code/modules/overmap/contacts/tracker.dm
Normal file
23
code/modules/overmap/contacts/tracker.dm
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
/obj/item/ship_tracker
|
||||||
|
name = "long range tracker"
|
||||||
|
desc = "A complex device that transmits conspicuous signals, easily locked onto by modern sensors hardware."
|
||||||
|
icon = 'icons/obj/ship_tracker.dmi'
|
||||||
|
icon_state = "disabled"
|
||||||
|
|
||||||
|
origin_tech = "{'magnets':3, 'programming':2}"
|
||||||
|
var/enabled = FALSE
|
||||||
|
|
||||||
|
/obj/item/ship_tracker/Initialize()
|
||||||
|
. = ..()
|
||||||
|
|
||||||
|
/obj/item/ship_tracker/attack_self(var/mob/user)
|
||||||
|
enabled = !enabled
|
||||||
|
to_chat(user, SPAN_NOTICE("You [enabled ? "enable" : "disable"] \the [src]"))
|
||||||
|
update_icon()
|
||||||
|
|
||||||
|
/obj/item/ship_tracker/proc/on_update_icon()
|
||||||
|
icon_state = enabled ? "enabled" : "disabled"
|
||||||
|
|
||||||
|
/obj/item/ship_tracker/examine(var/mob/user)
|
||||||
|
. = ..()
|
||||||
|
to_chat(user, "It appears to be [enabled ? "enabled" : "disabled"]")
|
||||||
@@ -168,14 +168,18 @@
|
|||||||
/obj/effect/overmap/event
|
/obj/effect/overmap/event
|
||||||
name = "event"
|
name = "event"
|
||||||
icon = 'icons/obj/overmap.dmi'
|
icon = 'icons/obj/overmap.dmi'
|
||||||
icon_state = "event"
|
icon_state = "blank"
|
||||||
opacity = 1
|
opacity = 0
|
||||||
var/list/events
|
var/list/events
|
||||||
var/list/event_icon_states = list("event")
|
var/list/event_icon_states = list("event")
|
||||||
var/difficulty = EVENT_LEVEL_MODERATE
|
var/difficulty = EVENT_LEVEL_MODERATE
|
||||||
var/list/victims //basically cached events on which Z level
|
var/list/victims //basically cached events on which Z level
|
||||||
var/can_be_destroyed = TRUE //Can this event be destroyed by ship guns?
|
var/can_be_destroyed = TRUE //Can this event be destroyed by ship guns?
|
||||||
|
|
||||||
|
// Events must be detected by sensors, but are otherwise instantly visible.
|
||||||
|
requires_contact = TRUE
|
||||||
|
instant_contact = TRUE
|
||||||
|
|
||||||
// Vars that determine movability, current moving direction, and moving speed //
|
// Vars that determine movability, current moving direction, and moving speed //
|
||||||
/// Whether this event can move or not
|
/// Whether this event can move or not
|
||||||
var/movable_event = FALSE
|
var/movable_event = FALSE
|
||||||
@@ -194,6 +198,8 @@
|
|||||||
/// Ticks up each process until move speed is matched, at which point the event will move
|
/// Ticks up each process until move speed is matched, at which point the event will move
|
||||||
var/ship_delay_counter = 0
|
var/ship_delay_counter = 0
|
||||||
|
|
||||||
|
var/list/colors = list() //Pick a color from this list on init
|
||||||
|
|
||||||
/obj/effect/overmap/event/Initialize()
|
/obj/effect/overmap/event/Initialize()
|
||||||
. = ..()
|
. = ..()
|
||||||
icon_state = pick(event_icon_states)
|
icon_state = pick(event_icon_states)
|
||||||
@@ -202,6 +208,8 @@
|
|||||||
start_moving()
|
start_moving()
|
||||||
else if(prob(movable_event_chance))
|
else if(prob(movable_event_chance))
|
||||||
make_movable()
|
make_movable()
|
||||||
|
if(LAZYLEN(colors))
|
||||||
|
color = pick(colors)
|
||||||
|
|
||||||
/obj/effect/overmap/event/proc/make_movable()
|
/obj/effect/overmap/event/proc/make_movable()
|
||||||
movable_event = TRUE
|
movable_event = TRUE
|
||||||
@@ -258,6 +266,7 @@
|
|||||||
events = list(/datum/event/meteor_wave/overmap)
|
events = list(/datum/event/meteor_wave/overmap)
|
||||||
event_icon_states = list("meteor1", "meteor2", "meteor3", "meteor4")
|
event_icon_states = list("meteor1", "meteor2", "meteor3", "meteor4")
|
||||||
difficulty = EVENT_LEVEL_MAJOR
|
difficulty = EVENT_LEVEL_MAJOR
|
||||||
|
colors = list("#fc1100", "#b5251b", "#be1e12")
|
||||||
|
|
||||||
/obj/effect/overmap/event/electric
|
/obj/effect/overmap/event/electric
|
||||||
name = "electrical storm"
|
name = "electrical storm"
|
||||||
@@ -266,6 +275,7 @@
|
|||||||
event_icon_states = list("electrical1", "electrical2")
|
event_icon_states = list("electrical1", "electrical2")
|
||||||
difficulty = EVENT_LEVEL_MAJOR
|
difficulty = EVENT_LEVEL_MAJOR
|
||||||
can_be_destroyed = FALSE
|
can_be_destroyed = FALSE
|
||||||
|
colors = list("#f5ed0c", "#d9d323", "#faf450")
|
||||||
|
|
||||||
/obj/effect/overmap/event/dust
|
/obj/effect/overmap/event/dust
|
||||||
name = "dust cloud"
|
name = "dust cloud"
|
||||||
@@ -280,6 +290,7 @@
|
|||||||
event_icon_states = list("ion1", "ion2", "ion3", "ion4")
|
event_icon_states = list("ion1", "ion2", "ion3", "ion4")
|
||||||
difficulty = EVENT_LEVEL_MAJOR
|
difficulty = EVENT_LEVEL_MAJOR
|
||||||
can_be_destroyed = FALSE
|
can_be_destroyed = FALSE
|
||||||
|
colors = list("#02faee", "#34d1c9", "#1b9ce7")
|
||||||
|
|
||||||
/obj/effect/overmap/event/carp
|
/obj/effect/overmap/event/carp
|
||||||
name = "carp shoal"
|
name = "carp shoal"
|
||||||
@@ -288,10 +299,12 @@
|
|||||||
difficulty = EVENT_LEVEL_MODERATE
|
difficulty = EVENT_LEVEL_MODERATE
|
||||||
event_icon_states = list("carp")
|
event_icon_states = list("carp")
|
||||||
movable_event_chance = 5
|
movable_event_chance = 5
|
||||||
|
colors = list("#c25bc7", "#ea50f2", "#f67efc")
|
||||||
|
|
||||||
/obj/effect/overmap/event/carp/major
|
/obj/effect/overmap/event/carp/major
|
||||||
name = "carp school"
|
name = "carp school"
|
||||||
difficulty = EVENT_LEVEL_MAJOR
|
difficulty = EVENT_LEVEL_MAJOR
|
||||||
|
colors = list("#a709db", "#c228c7", "#c444e4")
|
||||||
|
|
||||||
/obj/effect/overmap/event/gravity
|
/obj/effect/overmap/event/gravity
|
||||||
name = "dark matter influx"
|
name = "dark matter influx"
|
||||||
|
|||||||
@@ -8,6 +8,14 @@
|
|||||||
|
|
||||||
var/known = 0 //shows up on nav computers automatically
|
var/known = 0 //shows up on nav computers automatically
|
||||||
var/scannable //if set to TRUE will show up on ship sensors for detailed scans
|
var/scannable //if set to TRUE will show up on ship sensors for detailed scans
|
||||||
|
var/unknown_id // A unique identifier used when this entity is scanned. Assigned in Initialize().
|
||||||
|
var/requires_contact = TRUE //whether or not the effect must be identified by ship sensors before being seen.
|
||||||
|
var/instant_contact = FALSE //do we instantly identify ourselves to any ship in sensors range?
|
||||||
|
|
||||||
|
var/sensor_visibility = 10 //how likely it is to increase identification process each scan.
|
||||||
|
var/vessel_mass = 10000 // metric tonnes, very rough number, affects acceleration provided by engines
|
||||||
|
|
||||||
|
|
||||||
var/image/targeted_overlay
|
var/image/targeted_overlay
|
||||||
|
|
||||||
//Overlay of how this object should look on other skyboxes
|
//Overlay of how this object should look on other skyboxes
|
||||||
@@ -49,6 +57,9 @@
|
|||||||
H.get_known_sectors()
|
H.get_known_sectors()
|
||||||
update_icon()
|
update_icon()
|
||||||
|
|
||||||
|
if(requires_contact)
|
||||||
|
invisibility = INVISIBILITY_OVERMAP // Effects that require identification have their images cast to the client via sensors.
|
||||||
|
|
||||||
/obj/effect/overmap/Crossed(var/obj/effect/overmap/visitable/other)
|
/obj/effect/overmap/Crossed(var/obj/effect/overmap/visitable/other)
|
||||||
if(istype(other))
|
if(istype(other))
|
||||||
for(var/obj/effect/overmap/visitable/O in loc)
|
for(var/obj/effect/overmap/visitable/O in loc)
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ var/global/area/overmap/map_overmap // Global object used to locate the overmap
|
|||||||
scannable = TRUE
|
scannable = TRUE
|
||||||
var/designation //Actual name of the object.
|
var/designation //Actual name of the object.
|
||||||
var/class //Imagine a ship or station's class. "NTCC" Odin, "SCCV" Horizon, ...
|
var/class //Imagine a ship or station's class. "NTCC" Odin, "SCCV" Horizon, ...
|
||||||
|
unknown_id = "Bogey"
|
||||||
var/obfuscated_name = "unidentified object"
|
var/obfuscated_name = "unidentified object"
|
||||||
var/obfuscated_desc = "This object is not displaying its IFF signature."
|
var/obfuscated_desc = "This object is not displaying its IFF signature."
|
||||||
var/obfuscated = FALSE //Whether we hide our name and class or not.
|
var/obfuscated = FALSE //Whether we hide our name and class or not.
|
||||||
@@ -40,6 +41,11 @@ var/global/area/overmap/map_overmap // Global object used to locate the overmap
|
|||||||
var/comms_name = "shipboard"
|
var/comms_name = "shipboard"
|
||||||
/// Whether away ship comms have access to the common channel / PUB_FREQ
|
/// Whether away ship comms have access to the common channel / PUB_FREQ
|
||||||
var/use_common = FALSE
|
var/use_common = FALSE
|
||||||
|
var/list/navigation_viewers // list of weakrefs to people viewing the overmap via this ship
|
||||||
|
var/list/consoles
|
||||||
|
|
||||||
|
var/list/datalink_requests = list()// A list of datalink requests that we received
|
||||||
|
var/list/datalinked = list()// Other effects that we are datalinked with
|
||||||
|
|
||||||
/obj/effect/overmap/visitable/Initialize()
|
/obj/effect/overmap/visitable/Initialize()
|
||||||
. = ..()
|
. = ..()
|
||||||
|
|||||||
@@ -9,6 +9,16 @@
|
|||||||
circuit = /obj/item/circuitboard/ship/sensors
|
circuit = /obj/item/circuitboard/ship/sensors
|
||||||
linked_type = /obj/effect/overmap/visitable
|
linked_type = /obj/effect/overmap/visitable
|
||||||
|
|
||||||
|
var/working_sound = 'sound/machines/sensors/dradis.ogg'
|
||||||
|
var/datum/sound_token/sound_token
|
||||||
|
var/sound_id
|
||||||
|
|
||||||
|
var/datum/weakref/sensor_ref
|
||||||
|
var/list/last_scan
|
||||||
|
|
||||||
|
/obj/machinery/computer/ship/sensors/proc/get_sensors()
|
||||||
|
return sensors
|
||||||
|
|
||||||
/obj/machinery/computer/ship/sensors/attempt_hook_up(var/obj/effect/overmap/visitable/sector)
|
/obj/machinery/computer/ship/sensors/attempt_hook_up(var/obj/effect/overmap/visitable/sector)
|
||||||
. = ..()
|
. = ..()
|
||||||
if(!.)
|
if(!.)
|
||||||
@@ -27,6 +37,21 @@
|
|||||||
identification = IB
|
identification = IB
|
||||||
break
|
break
|
||||||
|
|
||||||
|
/obj/machinery/computer/ship/sensors/proc/update_sound()
|
||||||
|
if(!working_sound)
|
||||||
|
return
|
||||||
|
if(!sound_id)
|
||||||
|
sound_id = "[type]_[sequential_id(/obj/machinery/computer/ship/sensors)]"
|
||||||
|
|
||||||
|
var/obj/machinery/shipsensors/sensors = get_sensors()
|
||||||
|
if(linked && sensors?.use_power && !(sensors.stat & NOPOWER))
|
||||||
|
var/volume = 10
|
||||||
|
if(!sound_token)
|
||||||
|
sound_token = sound_player.PlayLoopingSound(src, sound_id, working_sound, volume = volume, range = 10)
|
||||||
|
sound_token.SetVolume(volume)
|
||||||
|
else if(sound_token)
|
||||||
|
QDEL_NULL(sound_token)
|
||||||
|
|
||||||
/obj/machinery/computer/ship/sensors/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1)
|
/obj/machinery/computer/ship/sensors/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1)
|
||||||
if(!linked)
|
if(!linked)
|
||||||
display_reconnect_dialog(user, "sensors")
|
display_reconnect_dialog(user, "sensors")
|
||||||
@@ -35,6 +60,7 @@
|
|||||||
var/data[0]
|
var/data[0]
|
||||||
|
|
||||||
data["viewing"] = viewing_overmap(user)
|
data["viewing"] = viewing_overmap(user)
|
||||||
|
data["muted"] = muted
|
||||||
if(sensors)
|
if(sensors)
|
||||||
data["on"] = sensors.use_power
|
data["on"] = sensors.use_power
|
||||||
data["range"] = sensors.range
|
data["range"] = sensors.range
|
||||||
@@ -62,8 +88,22 @@
|
|||||||
distress_beacons.Add(list(list("caller" = vessel.name, "sender" = "[job_string][H.name]", "bearing" = bearing)))
|
distress_beacons.Add(list(list("caller" = vessel.name, "sender" = "[job_string][H.name]", "bearing" = bearing)))
|
||||||
if(length(distress_beacons))
|
if(length(distress_beacons))
|
||||||
data["distress_beacons"] = distress_beacons
|
data["distress_beacons"] = distress_beacons
|
||||||
|
|
||||||
|
|
||||||
var/list/contacts = list()
|
var/list/contacts = list()
|
||||||
for(var/obj/effect/overmap/O in view(7,linked))
|
var/list/potential_contacts = list()
|
||||||
|
|
||||||
|
for(var/obj/effect/overmap/nearby in view(7,linked))
|
||||||
|
if(nearby.requires_contact) // Some ships require.
|
||||||
|
continue
|
||||||
|
potential_contacts |= nearby
|
||||||
|
|
||||||
|
// Effects that require contact are only added to the contacts if they have been identified.
|
||||||
|
// Allows for coord tracking out of range of the player's view.
|
||||||
|
for(var/obj/effect/overmap/visitable/identified_contact in contact_datums)
|
||||||
|
potential_contacts |= identified_contact
|
||||||
|
|
||||||
|
for(var/obj/effect/overmap/O in potential_contacts)
|
||||||
if(linked == O)
|
if(linked == O)
|
||||||
continue
|
continue
|
||||||
if(!O.scannable)
|
if(!O.scannable)
|
||||||
@@ -74,6 +114,21 @@
|
|||||||
contacts.Add(list(list("name"=O.name, "ref"="\ref[O]", "bearing"=bearing)))
|
contacts.Add(list(list("name"=O.name, "ref"="\ref[O]", "bearing"=bearing)))
|
||||||
if(length(contacts))
|
if(length(contacts))
|
||||||
data["contacts"] = contacts
|
data["contacts"] = contacts
|
||||||
|
|
||||||
|
// Add datalink requests
|
||||||
|
if(length(connected.datalink_requests))
|
||||||
|
var/list/local_datalink_requests = list()
|
||||||
|
for(var/obj/effect/overmap/visitable/requestor in connected.datalink_requests)
|
||||||
|
local_datalink_requests.Add(list(list("name"=requestor.name, "ref"="\ref[requestor]")))
|
||||||
|
data["datalink_requests"] = local_datalink_requests
|
||||||
|
|
||||||
|
if(length(connected.datalinked))
|
||||||
|
var/list/local_datalinked = list()
|
||||||
|
for(var/obj/effect/overmap/visitable/datalinked_ship in connected.datalinked)
|
||||||
|
local_datalinked.Add(list(list("name"=datalinked_ship.name, "ref"="\ref[datalinked_ship]")))
|
||||||
|
data["datalinked"] = local_datalinked
|
||||||
|
|
||||||
|
data["last_scan"] = last_scan
|
||||||
else
|
else
|
||||||
data["status"] = "MISSING"
|
data["status"] = "MISSING"
|
||||||
data["range"] = "N/A"
|
data["range"] = "N/A"
|
||||||
@@ -168,11 +223,43 @@
|
|||||||
|
|
||||||
if (href_list["scan"])
|
if (href_list["scan"])
|
||||||
var/obj/effect/overmap/O = locate(href_list["scan"])
|
var/obj/effect/overmap/O = locate(href_list["scan"])
|
||||||
if(istype(O) && !QDELETED(O) && (O in view(7,linked)))
|
if(istype(O) && !QDELETED(O))
|
||||||
playsound(loc, "sound/machines/dotprinter.ogg", 30, 1)
|
if((O in view(7,linked))|| (O in contact_datums))
|
||||||
new/obj/item/paper/(get_turf(src), O.get_scan_data(usr), "paper (Sensor Scan - [O])")
|
playsound(loc, "sound/machines/dotprinter.ogg", 30, 1)
|
||||||
|
LAZYSET(last_scan, "data", O.get_scan_data(usr))
|
||||||
|
LAZYSET(last_scan, "location", "[O.x],[O.y]")
|
||||||
|
LAZYSET(last_scan, "name", "[O]")
|
||||||
|
to_chat(usr, SPAN_NOTICE("Successfully scanned [O]."))
|
||||||
|
new/obj/item/paper/(get_turf(src), O.get_scan_data(usr), "paper (Sensor Scan - [O])")
|
||||||
|
return TOPIC_HANDLED
|
||||||
|
|
||||||
|
if (href_list["request_datalink"])
|
||||||
|
var/obj/effect/overmap/visitable/O = locate(href_list["request_datalink"])
|
||||||
|
if(istype(O) && !QDELETED(O))
|
||||||
|
if((O in view(7,linked)) || (O in contact_datums))
|
||||||
|
|
||||||
|
for(var/obj/machinery/computer/ship/sensors/sensor_console in O.consoles)
|
||||||
|
sensor_console.connected.datalink_requests |= src.connected
|
||||||
|
return TOPIC_HANDLED
|
||||||
|
|
||||||
|
if (href_list["accept_datalink_requests"])
|
||||||
|
var/obj/effect/overmap/visitable/O = locate(href_list["accept_datalink_requests"])
|
||||||
|
for(var/obj/machinery/computer/ship/sensors/sensor_console in src.connected.consoles)
|
||||||
|
sensor_console.datalink_add_ship_datalink(O)
|
||||||
|
break
|
||||||
|
src.connected.datalink_requests -= O // Remove the request
|
||||||
return TOPIC_HANDLED
|
return TOPIC_HANDLED
|
||||||
|
|
||||||
|
if (href_list["decline_datalink_requests"])
|
||||||
|
var/obj/effect/overmap/visitable/O = locate(href_list["decline_datalink_requests"])
|
||||||
|
src.connected.datalink_requests -= O // Remove the request
|
||||||
|
|
||||||
|
if (href_list["remove_datalink"])
|
||||||
|
var/obj/effect/overmap/visitable/O = locate(href_list["remove_datalink"])
|
||||||
|
for(var/obj/machinery/computer/ship/sensors/rescinder_sensor_console in src.connected.consoles) // Get sensor console from the rescinder
|
||||||
|
rescinder_sensor_console.datalink_remove_ship_datalink(O)
|
||||||
|
return TOPIC_HANDLED
|
||||||
|
|
||||||
if (href_list["play_message"])
|
if (href_list["play_message"])
|
||||||
var/caller = href_list["play_message"]
|
var/caller = href_list["play_message"]
|
||||||
var/datum/distress_beacon/beacon = SSdistress.active_distress_beacons[caller]
|
var/datum/distress_beacon/beacon = SSdistress.active_distress_beacons[caller]
|
||||||
@@ -192,18 +279,6 @@
|
|||||||
security_announcement.Announce("No fire is incoming at the current moment, resume damage control.", "Space clear!", sound('sound/misc/announcements/security_level_old.ogg'), 0)
|
security_announcement.Announce("No fire is incoming at the current moment, resume damage control.", "Space clear!", sound('sound/misc/announcements/security_level_old.ogg'), 0)
|
||||||
return TOPIC_HANDLED
|
return TOPIC_HANDLED
|
||||||
|
|
||||||
/obj/machinery/computer/ship/sensors/process()
|
|
||||||
..()
|
|
||||||
if(!linked)
|
|
||||||
return
|
|
||||||
if(sensors && sensors.use_power && sensors.powered())
|
|
||||||
var/sensor_range = round(sensors.range*1.5) + 1
|
|
||||||
linked.set_light(sensor_range, sensor_range+1, light_color)
|
|
||||||
linked.handle_sensor_state_change(TRUE)
|
|
||||||
else
|
|
||||||
linked.set_light(0)
|
|
||||||
linked.handle_sensor_state_change(FALSE)
|
|
||||||
|
|
||||||
/obj/machinery/shipsensors
|
/obj/machinery/shipsensors
|
||||||
name = "sensors suite"
|
name = "sensors suite"
|
||||||
desc = "Long range gravity scanner with various other sensors, used to detect irregularities in surrounding space. Can only run in vacuum to protect delicate quantum BS elements."
|
desc = "Long range gravity scanner with various other sensors, used to detect irregularities in surrounding space. Can only run in vacuum to protect delicate quantum BS elements."
|
||||||
@@ -216,6 +291,7 @@
|
|||||||
var/heat_reduction = 0.5 // mitigates this much heat per tick - can sustain range 2
|
var/heat_reduction = 0.5 // mitigates this much heat per tick - can sustain range 2
|
||||||
var/heat = 0
|
var/heat = 0
|
||||||
var/range = 1
|
var/range = 1
|
||||||
|
var/sensor_strength = 5//used for detecting ships via contacts
|
||||||
idle_power_usage = 5000
|
idle_power_usage = 5000
|
||||||
|
|
||||||
var/base_icon_state
|
var/base_icon_state
|
||||||
|
|||||||
@@ -56,6 +56,8 @@ somewhere on that shuttle. Subtypes of these can be then used to perform ship ov
|
|||||||
if(user.eyeobj)
|
if(user.eyeobj)
|
||||||
moved_event.register(user.eyeobj, src, PROC_REF(unlook))
|
moved_event.register(user.eyeobj, src, PROC_REF(unlook))
|
||||||
LAZYDISTINCTADD(viewers, WEAKREF(user))
|
LAZYDISTINCTADD(viewers, WEAKREF(user))
|
||||||
|
if(linked)
|
||||||
|
LAZYDISTINCTADD(linked.navigation_viewers, WEAKREF(user))
|
||||||
|
|
||||||
/obj/machinery/computer/ship/proc/unlook(var/mob/user)
|
/obj/machinery/computer/ship/proc/unlook(var/mob/user)
|
||||||
user.reset_view()
|
user.reset_view()
|
||||||
@@ -78,9 +80,15 @@ somewhere on that shuttle. Subtypes of these can be then used to perform ship ov
|
|||||||
moved_event.unregister(E.owner, src, PROC_REF(unlook))
|
moved_event.unregister(E.owner, src, PROC_REF(unlook))
|
||||||
LAZYREMOVE(viewers, WEAKREF(E.owner))
|
LAZYREMOVE(viewers, WEAKREF(E.owner))
|
||||||
LAZYREMOVE(viewers, WEAKREF(user))
|
LAZYREMOVE(viewers, WEAKREF(user))
|
||||||
|
if(linked)
|
||||||
|
LAZYREMOVE(linked.navigation_viewers, WEAKREF(user))
|
||||||
|
|
||||||
|
if(linked)
|
||||||
|
for(var/obj/machinery/computer/ship/sensors/sensor in linked.consoles)
|
||||||
|
sensor.hide_contacts(user)
|
||||||
|
|
||||||
/obj/machinery/computer/ship/proc/viewing_overmap(mob/user)
|
/obj/machinery/computer/ship/proc/viewing_overmap(mob/user)
|
||||||
return (WEAKREF(user) in viewers)
|
return (WEAKREF(user) in viewers) || (linked && (WEAKREF(user) in linked.navigation_viewers))
|
||||||
|
|
||||||
/obj/machinery/computer/ship/CouldNotUseTopic(mob/user)
|
/obj/machinery/computer/ship/CouldNotUseTopic(mob/user)
|
||||||
. = ..()
|
. = ..()
|
||||||
@@ -102,6 +110,8 @@ somewhere on that shuttle. Subtypes of these can be then used to perform ship ov
|
|||||||
return 0
|
return 0
|
||||||
|
|
||||||
/obj/machinery/computer/ship/Destroy()
|
/obj/machinery/computer/ship/Destroy()
|
||||||
|
if(linked)
|
||||||
|
linked = null
|
||||||
if(connected)
|
if(connected)
|
||||||
LAZYREMOVE(connected.consoles, src)
|
LAZYREMOVE(connected.consoles, src)
|
||||||
. = ..()
|
. = ..()
|
||||||
@@ -114,6 +124,8 @@ somewhere on that shuttle. Subtypes of these can be then used to perform ship ov
|
|||||||
var/M = W.resolve()
|
var/M = W.resolve()
|
||||||
if(M)
|
if(M)
|
||||||
unlook(M)
|
unlook(M)
|
||||||
|
if(linked)
|
||||||
|
LAZYREMOVE(linked.navigation_viewers, W)
|
||||||
. = ..()
|
. = ..()
|
||||||
|
|
||||||
/obj/machinery/computer/ship/on_user_login(mob/M)
|
/obj/machinery/computer/ship/on_user_login(mob/M)
|
||||||
|
|||||||
@@ -14,10 +14,14 @@ var/const/OVERMAP_SPEED_CONSTANT = (1 SECOND)
|
|||||||
name = "generic ship"
|
name = "generic ship"
|
||||||
desc = "Space faring vessel."
|
desc = "Space faring vessel."
|
||||||
icon_state = "ship"
|
icon_state = "ship"
|
||||||
|
requires_contact = TRUE
|
||||||
obfuscated_name = "unidentified vessel"
|
obfuscated_name = "unidentified vessel"
|
||||||
var/moving_state = "ship_moving"
|
var/moving_state = "ship_moving"
|
||||||
|
|
||||||
var/vessel_mass = 10000 //tonnes, arbitrary number, affects acceleration provided by engines
|
var/list/known_ships = list() //List of ships known at roundstart - put types here.
|
||||||
|
var/base_sensor_visibility
|
||||||
|
|
||||||
|
vessel_mass = 10000 //tonnes, arbitrary number, affects acceleration provided by engines
|
||||||
var/vessel_size = SHIP_SIZE_LARGE //arbitrary number, affects how likely are we to evade meteors
|
var/vessel_size = SHIP_SIZE_LARGE //arbitrary number, affects how likely are we to evade meteors
|
||||||
var/max_speed = 1/(1 SECOND) //"speed of light" for the ship, in turfs/tick.
|
var/max_speed = 1/(1 SECOND) //"speed of light" for the ship, in turfs/tick.
|
||||||
var/min_speed = 1/(2 MINUTES) // Below this, we round speed to 0 to avoid math errors.
|
var/min_speed = 1/(2 MINUTES) // Below this, we round speed to 0 to avoid math errors.
|
||||||
@@ -35,8 +39,6 @@ var/const/OVERMAP_SPEED_CONSTANT = (1 SECOND)
|
|||||||
var/thrust_limit = 1 //global thrust limit for all engines, 0..1
|
var/thrust_limit = 1 //global thrust limit for all engines, 0..1
|
||||||
var/halted = 0 //admin halt or other stop.
|
var/halted = 0 //admin halt or other stop.
|
||||||
|
|
||||||
var/list/consoles
|
|
||||||
|
|
||||||
comms_support = TRUE
|
comms_support = TRUE
|
||||||
|
|
||||||
/obj/effect/overmap/visitable/ship/Initialize()
|
/obj/effect/overmap/visitable/ship/Initialize()
|
||||||
@@ -44,6 +46,7 @@ var/const/OVERMAP_SPEED_CONSTANT = (1 SECOND)
|
|||||||
glide_size = world.icon_size
|
glide_size = world.icon_size
|
||||||
min_speed = round(min_speed, SHIP_MOVE_RESOLUTION)
|
min_speed = round(min_speed, SHIP_MOVE_RESOLUTION)
|
||||||
max_speed = round(max_speed, SHIP_MOVE_RESOLUTION)
|
max_speed = round(max_speed, SHIP_MOVE_RESOLUTION)
|
||||||
|
base_sensor_visibility = round((vessel_mass/SENSOR_COEFFICENT),1)
|
||||||
SSshuttle.ships += src
|
SSshuttle.ships += src
|
||||||
|
|
||||||
/obj/effect/overmap/visitable/ship/find_z_levels(var/fore_direction)
|
/obj/effect/overmap/visitable/ship/find_z_levels(var/fore_direction)
|
||||||
@@ -68,8 +71,11 @@ var/const/OVERMAP_SPEED_CONSTANT = (1 SECOND)
|
|||||||
|
|
||||||
/obj/effect/overmap/visitable/ship/get_scan_data(mob/user)
|
/obj/effect/overmap/visitable/ship/get_scan_data(mob/user)
|
||||||
. = ..()
|
. = ..()
|
||||||
|
. += "<br>Mass: [vessel_mass] tons."
|
||||||
if(!is_still())
|
if(!is_still())
|
||||||
. += "<br>Heading: [dir2angle(get_heading())], speed [get_speed() * 1000]"
|
. += "<br>Heading: [dir2angle(get_heading())], speed [get_speed() * 1000]"
|
||||||
|
if(instant_contact)
|
||||||
|
. += "<br>It is broadcasting a distress signal."
|
||||||
|
|
||||||
//Projected acceleration based on information from engines
|
//Projected acceleration based on information from engines
|
||||||
/obj/effect/overmap/visitable/ship/proc/get_acceleration()
|
/obj/effect/overmap/visitable/ship/proc/get_acceleration()
|
||||||
@@ -165,6 +171,7 @@ var/const/OVERMAP_SPEED_CONSTANT = (1 SECOND)
|
|||||||
if(newloc && loc != newloc)
|
if(newloc && loc != newloc)
|
||||||
Move(newloc)
|
Move(newloc)
|
||||||
handle_wraparound()
|
handle_wraparound()
|
||||||
|
sensor_visibility = min(round(base_sensor_visibility + get_speed_sensor_increase(), 1), 100)
|
||||||
|
|
||||||
/obj/effect/overmap/visitable/ship/update_icon()
|
/obj/effect/overmap/visitable/ship/update_icon()
|
||||||
pixel_x = position[1] * (world.icon_size/2)
|
pixel_x = position[1] * (world.icon_size/2)
|
||||||
@@ -306,6 +313,9 @@ var/const/OVERMAP_SPEED_CONSTANT = (1 SECOND)
|
|||||||
for(var/obj/machinery/computer/ship/targeting/TR in consoles)
|
for(var/obj/machinery/computer/ship/targeting/TR in consoles)
|
||||||
TR.visible_message(SPAN_NOTICE("[icon2html(src, viewers(get_turf(TR)))] Hit confirmed on [hit_data["target_name"]] in [hit_data["target_area"]] at coordinates [hit_data["coordinates"]]."), range = 2)
|
TR.visible_message(SPAN_NOTICE("[icon2html(src, viewers(get_turf(TR)))] Hit confirmed on [hit_data["target_name"]] in [hit_data["target_area"]] at coordinates [hit_data["coordinates"]]."), range = 2)
|
||||||
|
|
||||||
|
/obj/effect/overmap/visitable/ship/proc/get_speed_sensor_increase()
|
||||||
|
return min(get_speed() * 1000, 50) //Engines should never increase sensor visibility by more than 50.
|
||||||
|
|
||||||
#undef MOVING
|
#undef MOVING
|
||||||
#undef SANITIZE_SPEED
|
#undef SANITIZE_SPEED
|
||||||
#undef CHANGE_SPEED_BY
|
#undef CHANGE_SPEED_BY
|
||||||
|
|||||||
42
html/changelogs/fluffyghost-sensorsoverhaul.yml
Normal file
42
html/changelogs/fluffyghost-sensorsoverhaul.yml
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
################################
|
||||||
|
# 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: FluffyGhost
|
||||||
|
|
||||||
|
# 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:
|
||||||
|
- rscadd: "The ship sensors now work as a sonar or radar, obscuring the view when the first object is pinged, otherwise the things not in range will not be seen."
|
||||||
|
- rscadd: "The ships now need to be scanned before they appear and are identified, which takes a little of time."
|
||||||
Binary file not shown.
|
Before Width: | Height: | Size: 41 KiB After Width: | Height: | Size: 41 KiB |
BIN
icons/obj/ship_tracker.dmi
Normal file
BIN
icons/obj/ship_tracker.dmi
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 551 B |
@@ -112,6 +112,7 @@
|
|||||||
<tr>
|
<tr>
|
||||||
<div class='item'>
|
<div class='item'>
|
||||||
<td>{{:helper.link('Scan', 'search' ,{ 'scan' : value.ref }, null, null)}}</td>
|
<td>{{:helper.link('Scan', 'search' ,{ 'scan' : value.ref }, null, null)}}</td>
|
||||||
|
<td>{{:helper.link('Datalink', 'search' ,{ 'request_datalink' : value.ref }, null, null)}}</td>
|
||||||
<td><span class='white'>{{:value.name}}</span>, bearing {{:value.bearing}}</td>
|
<td><span class='white'>{{:value.name}}</span>, bearing {{:value.bearing}}</td>
|
||||||
</div>
|
</div>
|
||||||
</tr>
|
</tr>
|
||||||
@@ -120,6 +121,36 @@
|
|||||||
{{/if}}
|
{{/if}}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<h4>Datalinks</h4>
|
||||||
|
<div class='block'>
|
||||||
|
{{if data.datalink_requests}}
|
||||||
|
<table>
|
||||||
|
{{for data.datalink_requests}}
|
||||||
|
<tr>
|
||||||
|
<div class='item'>
|
||||||
|
<td>{{:helper.link('Accept', 'search' ,{ 'accept_datalink_requests' : value.ref }, null, null)}}</td>
|
||||||
|
<td>{{:helper.link('Decline', 'search' ,{ 'decline_datalink_requests' : value.ref }, null, null)}}</td>
|
||||||
|
<td><span class='white'>{{:value.name}}</span></td>
|
||||||
|
</div>
|
||||||
|
</tr>
|
||||||
|
{{/for}}
|
||||||
|
</table>
|
||||||
|
{{/if}}
|
||||||
|
{{if data.datalinked}}
|
||||||
|
<h4>Connected Datalinks</h4>
|
||||||
|
<table>
|
||||||
|
{{for data.datalinked}}
|
||||||
|
<tr>
|
||||||
|
<div class='item'>
|
||||||
|
<td>{{:helper.link('Rescind', 'search' ,{ 'remove_datalink' : value.ref }, null, null)}}</td>
|
||||||
|
<td><span class='white'>{{:value.name}}</span></td>
|
||||||
|
</div>
|
||||||
|
</tr>
|
||||||
|
{{/for}}
|
||||||
|
</table>
|
||||||
|
{{/if}}
|
||||||
|
</div>
|
||||||
|
|
||||||
{{if data.id_name == 'Horizon'}}
|
{{if data.id_name == 'Horizon'}}
|
||||||
<h4>Announce Inbound fire</h4>
|
<h4>Announce Inbound fire</h4>
|
||||||
<div class='block'>
|
<div class='block'>
|
||||||
|
|||||||
BIN
sound/machines/sensors/contact_lost.ogg
Normal file
BIN
sound/machines/sensors/contact_lost.ogg
Normal file
Binary file not shown.
BIN
sound/machines/sensors/contactgeneric.ogg
Normal file
BIN
sound/machines/sensors/contactgeneric.ogg
Normal file
Binary file not shown.
BIN
sound/machines/sensors/dradis.ogg
Normal file
BIN
sound/machines/sensors/dradis.ogg
Normal file
Binary file not shown.
BIN
sound/machines/sensors/newcontact.ogg
Normal file
BIN
sound/machines/sensors/newcontact.ogg
Normal file
Binary file not shown.
Reference in New Issue
Block a user