Exosuit program, tracking, and downloader improvements (#1264)

A minor project focusing on Modular computers and exosuits. Changelog is small, since most of this is changes to unreleased content
In brief:
Adds an exosuit monitor program
Fixes many visual issues with the downloader program
Tweaks Exosuit killswitch and EMP mechanics
This commit is contained in:
NanakoAC
2016-12-23 00:52:54 +02:00
committed by skull132
parent d2b49ab1cb
commit c7e56daaa6
15 changed files with 434 additions and 158 deletions
@@ -0,0 +1,142 @@
/obj/item/mecha_parts/mecha_tracking
name = "Exosuit tracking beacon"
desc = "Device used to transmit exosuit data."
icon = 'icons/obj/device.dmi'
icon_state = "motion2"
origin_tech = list(TECH_DATA = 2, TECH_MAGNET = 2)
var/control = 0//
/obj/item/mecha_parts/mecha_tracking/initialize()
if (in_mecha())
exo_beacons.Add(src)//For the sake of exosuits which spawn with a preinstalled tracking beacon
/obj/item/mecha_parts/mecha_tracking/proc/get_mecha_info()
if(!in_mecha())
return 0
var/obj/mecha/M = src.loc
var/cell_charge = M.get_charge()
var/answer = {"<b>Name:</b> [M.name]<br>
<b>Integrity:</b> [M.health/initial(M.health)*100]%<br>
<b>Cell charge:</b> [isnull(cell_charge)?"Not found":"[M.cell.percent()]%"]<br>
<b>Airtank:</b> [M.return_pressure()]kPa<br>
<b>Pilot:</b> [M.occupant||"None"]<br>
<b>Location:</b> [get_area(M)||"Unknown"]<br>
<b>Active equipment:</b> [M.selected||"None"]"}
if(istype(M, /obj/mecha/working/ripley))
var/obj/mecha/working/ripley/RM = M
answer += "<b>Used cargo space:</b> [RM.cargo.len/RM.cargo_capacity*100]%<br>"
return answer
//Alternate version of this proc for nanoui
/obj/item/mecha_parts/mecha_tracking/proc/get_mecha_info_nano()
if(!in_mecha())
return 0
var/obj/mecha/M = src.loc
var/cell_charge = M.get_charge()
var/list/answer = list()
answer["name"] = M.name
answer["health"] = round((M.health/initial(M.health))*100, 0.1)
answer["charge"] = "[isnull(cell_charge)?"Not found":M.cell.percent()]%"
answer["air"] = "[M.return_pressure()]"
if (M.occupant)
answer["pilot"] = M.occupant.name
answer["location"] = get_area(M)
answer["active"] = M.selected || "None"
answer["ref"] = "\ref[src]"
answer["control"] = control
if(istype(M, /obj/mecha/working/ripley))
var/obj/mecha/working/ripley/RM = M
answer["cargo"] = "[RM.cargo.len/RM.cargo_capacity*100]"
return answer
/obj/item/mecha_parts/mecha_tracking/proc/install(var/obj/mecha/M, var/mob/living/user = null)
if (!istype(M))
return
if (M.state < 3)
user << span("warning", "You need to open the maintenance panel in order to install \the [src]")
return
for (var/obj/item/mecha_parts/mecha_tracking/B in M.contents)
user << span("warning", "[M] already has a tracker installed. Please remove the existing one.")
return
user.drop_from_inventory(src)
src.forceMove(M)
playsound(get_turf(user), 'sound/items/Deconstruct.ogg', 50, 1)
exo_beacons.Add(src)
user.visible_message("[user] installs [src] in [M].", "You install [src] in [M]")
/obj/item/mecha_parts/mecha_tracking/proc/uninstall(var/mob/living/user)
var/obj/mecha/M = in_mecha()
if (!M)//This should never happen
return
user.put_in_hands(src)
exo_beacons.Remove(src)
user.visible_message("[user] removes [src] from [M].", "You remove [src] from [M]")
/obj/item/mecha_parts/mecha_tracking/emp_act()
qdel(src)
return
/obj/item/mecha_parts/mecha_tracking/ex_act()
qdel(src)
return
/obj/item/mecha_parts/mecha_tracking/proc/in_mecha()
if(istype(src.loc, /obj/mecha))
return src.loc
return 0
/obj/item/mecha_parts/mecha_tracking/proc/shock(var/mob/user)
return//No killswitch on the basic version
/obj/item/mecha_parts/mecha_tracking/proc/get_mecha_log()
if(!src.in_mecha())
return 0
var/obj/mecha/M = src.loc
return M.get_log_html()
//Subclass of tracking beacon which has the killswitch function
/obj/item/mecha_parts/mecha_tracking/control
control = 1
name = "Exosuit Control Beacon"
desc = "Device used to transmit exosuit data. Allows an administrator to trigger a killswitch and remotely shutdown the exosuit."
//Remote killswitch fucks everything up.
//The suit is probably not unsalvageable, but will require extensive repairs and be crippled
/obj/item/mecha_parts/mecha_tracking/control/shock(var/mob/user)
var/obj/mecha/M = in_mecha()
if(M)
M.occupant_message(span("danger", "Remote termination protocol initiated. This exosuit is now shutting down, please exit immediately. Continued operation may incur disciplinary action or death of user."))
M.emp_act(1)
M.random_internal_damage(95)//Trigger all possible forms of internal damage
M.misconfigure_systems(95)
//Screw up all systems, including maintenance mode which will cause immediate stop
M.log_message("Remote termination protocol initiated by [user].",1)
qdel(src)
/obj/item/weapon/storage/box/mechabeacons
name = "Exosuit Control Beacons"
/obj/item/weapon/storage/box/mechabeacons/New()
..()
new /obj/item/mecha_parts/mecha_tracking/control(src)
new /obj/item/mecha_parts/mecha_tracking/control(src)
new /obj/item/mecha_parts/mecha_tracking/control(src)
new /obj/item/mecha_parts/mecha_tracking/control(src)
new /obj/item/mecha_parts/mecha_tracking/control(src)
new /obj/item/mecha_parts/mecha_tracking/control(src)
new /obj/item/mecha_parts/mecha_tracking/control(src)
+1 -1
View File
@@ -97,7 +97,7 @@
M.say("*scream")
ui_interact(user)
/obj/machinery/mecha_part_fabricator/ui_interact(var/mob/user, var/ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1)
/obj/machinery/mecha_part_fabricator/ui_interact(var/mob/user, var/ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1)
var/data[0]
var/datum/design/current = queue.len ? queue[1] : null
+46 -15
View File
@@ -343,6 +343,37 @@
if(src_object in view(2, src))
return STATUS_UPDATE //if they're close enough, allow the occupant to see the screen through the viewport or whatever.
//Menu for physically removing things from the suit while fiddling around in the maintenance panel
/obj/mecha/proc/removal_menu(var/mob/living/user)
var/list/options = list()
if(src.cell)
options += "Power Cell"
var/obj/item/mecha_parts/mecha_tracking/beacon = locate(/obj/item/mecha_parts/mecha_tracking) in src
if (beacon)
options += "Tracking Beacon"
if (!options.len)
user << "There are no components in [src] that can be removed"
return
var/choice = input(user, "Choose a component to remove.", "Component removal") as null|anything in options
if (!choice || !user)
return
switch(choice)
if("Power Cell")
if (!cell)
return
user.put_in_hands(cell)
cell = null
user << "You unscrew and pry out the powercell."
log_message("Powercell removed.")
if ("Tracking Beacon")
if (beacon && beacon.loc == src)//safety
beacon.uninstall(user)
/obj/mecha/proc/melee_action(atom/target)
return
@@ -706,8 +737,10 @@
/obj/mecha/emp_act(severity)
if(get_charge())
use_power((6500)/severity)
take_damage(40 / severity,"energy")
use_power((4000)/severity)
take_damage(30 / severity,"energy")
random_internal_damage(7/severity)
misconfigure_systems(10/severity)
src.log_message("EMP detected",1)
check_for_internal_damage(list(MECHA_INT_FIRE,MECHA_INT_TEMP_CONTROL,MECHA_INT_CONTROL_LOST,MECHA_INT_SHORT_CIRCUIT),1)
return
@@ -755,17 +788,21 @@
if(state==1)
state = 2
user << "You undo the securing bolts."
playsound(get_turf(src), 'sound/items/Ratchet.ogg', 50, 1)
else if(state==2)
state = 1
user << "You tighten the securing bolts."
playsound(get_turf(src), 'sound/items/Ratchet.ogg', 50, 1)
return
else if(istype(W, /obj/item/weapon/crowbar))
if(state==2)
state = 3
user << "You open the hatch to the power unit"
playsound(get_turf(src), 'sound/items/Deconstruct.ogg', 50, 1)
else if(state==3)
state=2
user << "You close the hatch to the power unit"
playsound(get_turf(src), 'sound/items/Crowbar.ogg', 50, 1)
return
else if(istype(W, /obj/item/stack/cable_coil))
if(state == 3 && hasInternalDamage(MECHA_INT_SHORT_CIRCUIT))
@@ -780,15 +817,10 @@
if(hasInternalDamage(MECHA_INT_TEMP_CONTROL))
clearInternalDamage(MECHA_INT_TEMP_CONTROL)
user << "You repair the damaged temperature controller."
else if(state==3 && src.cell)
src.cell.forceMove(src.loc)
src.cell = null
state = 4
user << "You unscrew and pry out the powercell."
src.log_message("Powercell removed.")
else if(state==4 && src.cell)
state=3
user << "You screw the cell in place."
else if(state==3)
removal_menu(user)
return
else if(istype(W, /obj/item/device/multitool))
@@ -804,7 +836,7 @@
return
else if(istype(W, /obj/item/weapon/cell))
if(state==4)
if(state==3)
if(!src.cell)
user << "You install the powercell"
user.drop_item()
@@ -833,9 +865,8 @@
return
else if(istype(W, /obj/item/mecha_parts/mecha_tracking))
user.drop_from_inventory(W)
W.forceMove(src)
user.visible_message("[user] attaches [W] to [src].", "You attach [W] to [src]")
var/obj/item/mecha_parts/mecha_tracking/C = W
C.install(src, user)
return
else
+49 -108
View File
@@ -1,3 +1,6 @@
//Note: This console is deprecated.
//The exosuit control program in modular computers is its successor
/obj/machinery/computer/mecha
name = "Exosuit Control"
icon = 'icons/obj/computer.dmi'
@@ -10,119 +13,57 @@
var/screen = 0
var/stored_data
attack_ai(var/mob/user as mob)
/obj/machinery/computer/mecha/attack_ai(var/mob/user as mob)
return src.attack_hand(user)
attack_hand(var/mob/user as mob)
if(..())
return
user.set_machine(src)
var/dat = "<html><head><title>[src.name]</title><style>h3 {margin: 0px; padding: 0px;}</style></head><body>"
if(screen == 0)
dat += "<h3>Tracking beacons data</h3>"
for(var/obj/item/mecha_parts/mecha_tracking/TR in world)
var/answer = TR.get_mecha_info()
if(answer)
dat += {"<hr>[answer]<br/>
<a href='?src=\ref[src];send_message=\ref[TR]'>Send message</a><br/>
<a href='?src=\ref[src];get_log=\ref[TR]'>Show exosuit log</a> | <a style='color: #f00;' href='?src=\ref[src];shock=\ref[TR]'>(EMP pulse)</a><br>"}
if(screen==1)
dat += "<h3>Log contents</h3>"
dat += "<a href='?src=\ref[src];return=1'>Return</a><hr>"
dat += "[stored_data]"
dat += "<A href='?src=\ref[src];refresh=1'>(Refresh)</A><BR>"
dat += "</body></html>"
user << browse(dat, "window=computer;size=400x500")
onclose(user, "computer")
/obj/machinery/computer/mecha/attack_hand(var/mob/user as mob)
if(..())
return
user.set_machine(src)
var/dat = "<html><head><title>[src.name]</title><style>h3 {margin: 0px; padding: 0px;}</style></head><body>"
if(screen == 0)
dat += "<h3>Tracking beacons data</h3>"
for(var/obj/item/mecha_parts/mecha_tracking/TR in world)
var/answer = TR.get_mecha_info()
if(answer)
dat += {"<hr>[answer]<br/>
<a href='?src=\ref[src];send_message=\ref[TR]'>Send message</a><br/>
<a href='?src=\ref[src];get_log=\ref[TR]'>Show exosuit log</a> | <a style='color: #f00;' href='?src=\ref[src];shock=\ref[TR]'>(EMP pulse)</a><br>"}
Topic(href, href_list)
if(..())
return
var/datum/topic_input/filter = new /datum/topic_input(href,href_list)
if(href_list["send_message"])
var/obj/item/mecha_parts/mecha_tracking/MT = filter.getObj("send_message")
var/message = sanitize(input(usr,"Input message","Transmit message") as text)
var/obj/mecha/M = MT.in_mecha()
if(message && M)
M.occupant_message(message)
return
if(href_list["shock"])
var/obj/item/mecha_parts/mecha_tracking/MT = filter.getObj("shock")
MT.shock()
if(href_list["get_log"])
var/obj/item/mecha_parts/mecha_tracking/MT = filter.getObj("get_log")
stored_data = MT.get_mecha_log()
screen = 1
if(href_list["return"])
screen = 0
src.updateUsrDialog()
if(screen==1)
dat += "<h3>Log contents</h3>"
dat += "<a href='?src=\ref[src];return=1'>Return</a><hr>"
dat += "[stored_data]"
dat += "<A href='?src=\ref[src];refresh=1'>(Refresh)</A><BR>"
dat += "</body></html>"
user << browse(dat, "window=computer;size=400x500")
onclose(user, "computer")
return
/obj/machinery/computer/mecha/Topic(href, href_list)
if(..())
return
/obj/item/mecha_parts/mecha_tracking
name = "Exosuit tracking beacon"
desc = "Device used to transmit exosuit data."
icon = 'icons/obj/device.dmi'
icon_state = "motion2"
origin_tech = list(TECH_DATA = 2, TECH_MAGNET = 2)
proc/get_mecha_info()
if(!in_mecha())
return 0
var/obj/mecha/M = src.loc
var/cell_charge = M.get_charge()
var/answer = {"<b>Name:</b> [M.name]<br>
<b>Integrity:</b> [M.health/initial(M.health)*100]%<br>
<b>Cell charge:</b> [isnull(cell_charge)?"Not found":"[M.cell.percent()]%"]<br>
<b>Airtank:</b> [M.return_pressure()]kPa<br>
<b>Pilot:</b> [M.occupant||"None"]<br>
<b>Location:</b> [get_area(M)||"Unknown"]<br>
<b>Active equipment:</b> [M.selected||"None"]"}
if(istype(M, /obj/mecha/working/ripley))
var/obj/mecha/working/ripley/RM = M
answer += "<b>Used cargo space:</b> [RM.cargo.len/RM.cargo_capacity*100]%<br>"
return answer
emp_act()
qdel(src)
var/datum/topic_input/filter = new /datum/topic_input(href,href_list)
if(href_list["send_message"])
var/obj/item/mecha_parts/mecha_tracking/MT = filter.getObj("send_message")
var/message = sanitize(input(usr,"Input message","Transmit message") as text)
var/obj/mecha/M = MT.in_mecha()
if(message && M)
M.occupant_message(message)
return
ex_act()
qdel(src)
return
proc/in_mecha()
if(istype(src.loc, /obj/mecha))
return src.loc
return 0
proc/shock()
var/obj/mecha/M = in_mecha()
if(M)
M.emp_act(2)
qdel(src)
proc/get_mecha_log()
if(!src.in_mecha())
return 0
var/obj/mecha/M = src.loc
return M.get_log_html()
if(href_list["shock"])
var/obj/item/mecha_parts/mecha_tracking/MT = filter.getObj("shock")
MT.shock()
if(href_list["get_log"])
var/obj/item/mecha_parts/mecha_tracking/MT = filter.getObj("get_log")
stored_data = MT.get_mecha_log()
screen = 1
if(href_list["return"])
screen = 0
src.updateUsrDialog()
return
/obj/item/weapon/storage/box/mechabeacons
name = "Exosuit Tracking Beacons"
New()
..()
new /obj/item/mecha_parts/mecha_tracking(src)
new /obj/item/mecha_parts/mecha_tracking(src)
new /obj/item/mecha_parts/mecha_tracking(src)
new /obj/item/mecha_parts/mecha_tracking(src)
new /obj/item/mecha_parts/mecha_tracking(src)
new /obj/item/mecha_parts/mecha_tracking(src)
new /obj/item/mecha_parts/mecha_tracking(src)