Merge branch 'master' into kk-adminships

This commit is contained in:
Novacat
2020-09-27 17:02:08 -04:00
committed by GitHub
746 changed files with 49441 additions and 38323 deletions
+8 -6
View File
@@ -91,16 +91,16 @@
var/icon/default_worn_icon //Default on-mob icon
var/worn_layer //Default on-mob layer
// Pickup/Drop/Equip/Throw Sounds
///Used when thrown into a mob
var/mob_throw_hit_sound
// Sound used when equipping the items into a valid slot.
var/equip_sound
var/equip_sound
// pickup sound - this is the default
var/pickup_sound = 'sound/items/pickup/device.ogg'
var/pickup_sound = "generic_pickup"
// drop sound - this is the default
var/drop_sound = 'sound/items/drop/device.ogg'
var/drop_sound = "generic_drop"
var/tip_timer // reference to timer id for a tooltip we might open soon
@@ -468,12 +468,12 @@ var/list/global/slot_flags_enumeration = list(
if(!canremove)
return 0
if(!slot)
if(issilicon(M))
return 1 // for stuff in grippers
return 0
if(!M.slot_is_accessible(slot, src, disable_warning? null : M))
return 0
return 1
@@ -785,6 +785,8 @@ modules/mob/living/carbon/human/life.dm if you die, you will be zoomed out.
// My best guess as to why this is here would be that it does so little. Still, keep it under all the procs, for sanity's sake.
/obj/item/device
icon = 'icons/obj/device.dmi'
pickup_sound = 'sound/items/pickup/device.ogg'
drop_sound = 'sound/items/drop/device.ogg'
//Worn icon generation for on-mob sprites
/obj/item/proc/make_worn_icon(var/body_type,var/slot_name,var/inhands,var/default_icon,var/default_layer,var/icon/clip_mask = null) //VOREStation edit - add 'clip mask' argument.
File diff suppressed because it is too large Load Diff
@@ -1,26 +0,0 @@
/obj/item/device/pda
var/delete_id = FALSE //Guaranteed deletion of ID upon deletion of PDA
/obj/item/device/pda/multicaster/exploration/New()
..()
owner = "Exploration Department"
name = "Exploration Department (Relay)"
cartridges_to_send_to = exploration_cartridges
/obj/item/device/pda/centcom
default_cartridge = /obj/item/weapon/cartridge/captain
icon_state = "pda-h"
detonate = 0
// hidden = 1
/obj/item/device/pda/pathfinder
default_cartridge = /obj/item/weapon/cartridge/explorer
icon_state = "pda-lawyer-old"
/obj/item/device/pda/explorer
default_cartridge = /obj/item/weapon/cartridge/explorer
icon_state = "pda-det"
/obj/item/device/pda/sar
default_cartridge = /obj/item/weapon/cartridge/sar
icon_state = "pda-h"
-630
View File
@@ -1,630 +0,0 @@
var/list/command_cartridges = list(
/obj/item/weapon/cartridge/captain,
/obj/item/weapon/cartridge/hop,
/obj/item/weapon/cartridge/hos,
/obj/item/weapon/cartridge/ce,
/obj/item/weapon/cartridge/rd,
/obj/item/weapon/cartridge/cmo,
/obj/item/weapon/cartridge/head,
/obj/item/weapon/cartridge/lawyer // Internal Affaris,
)
var/list/security_cartridges = list(
/obj/item/weapon/cartridge/security,
/obj/item/weapon/cartridge/detective,
/obj/item/weapon/cartridge/hos
)
var/list/engineering_cartridges = list(
/obj/item/weapon/cartridge/engineering,
/obj/item/weapon/cartridge/atmos,
/obj/item/weapon/cartridge/ce
)
var/list/medical_cartridges = list(
/obj/item/weapon/cartridge/medical,
/obj/item/weapon/cartridge/chemistry,
/obj/item/weapon/cartridge/cmo
)
var/list/research_cartridges = list(
/obj/item/weapon/cartridge/signal/science,
/obj/item/weapon/cartridge/rd
)
var/list/cargo_cartridges = list(
/obj/item/weapon/cartridge/quartermaster, // This also covers cargo-techs, apparently,
/obj/item/weapon/cartridge/miner,
/obj/item/weapon/cartridge/hop
)
var/list/civilian_cartridges = list(
/obj/item/weapon/cartridge/janitor,
/obj/item/weapon/cartridge/service,
/obj/item/weapon/cartridge/hop
)
/obj/item/weapon/cartridge
name = "generic cartridge"
desc = "A data cartridge for portable microcomputers."
icon = 'icons/obj/pda.dmi'
icon_state = "cart"
item_state = "electronic"
w_class = ITEMSIZE_TINY
drop_sound = 'sound/items/drop/component.ogg'
pickup_sound = 'sound/items/pickup/component.ogg'
var/obj/item/radio/integrated/radio = null
var/access_security = 0
var/access_engine = 0
var/access_atmos = 0
var/access_medical = 0
var/access_clown = 0
var/access_mime = 0
var/access_janitor = 0
// var/access_flora = 0
var/access_reagent_scanner = 0
var/access_remote_door = 0 // Control some blast doors remotely!!
var/remote_door_id = ""
var/access_status_display = 0
var/access_quartermaster = 0
var/access_detonate_pda = 0
var/access_hydroponics = 0
var/charges = 0
var/mode = null
var/menu
var/datum/data/record/active1 = null //General
var/datum/data/record/active2 = null //Medical
var/datum/data/record/active3 = null //Security
var/selected_sensor = null // Power Sensor
var/message1 // used for status_displays
var/message2
var/list/stored_data = list()
/obj/item/weapon/cartridge/Destroy()
QDEL_NULL(radio)
return ..()
/obj/item/weapon/cartridge/engineering
name = "\improper Power-ON cartridge"
icon_state = "cart-e"
access_engine = 1
/obj/item/weapon/cartridge/atmos
name = "\improper BreatheDeep cartridge"
icon_state = "cart-a"
access_atmos = 1
/obj/item/weapon/cartridge/medical
name = "\improper Med-U cartridge"
icon_state = "cart-m"
access_medical = 1
/obj/item/weapon/cartridge/chemistry
name = "\improper ChemWhiz cartridge"
icon_state = "cart-chem"
access_reagent_scanner = 1
access_medical = 1
/obj/item/weapon/cartridge/security
name = "\improper R.O.B.U.S.T. cartridge"
icon_state = "cart-s"
access_security = 1
/obj/item/weapon/cartridge/security/Initialize()
radio = new /obj/item/radio/integrated/beepsky(src)
. = ..()
/obj/item/weapon/cartridge/detective
name = "\improper D.E.T.E.C.T. cartridge"
icon_state = "cart-s"
access_security = 1
access_medical = 1
/obj/item/weapon/cartridge/janitor
name = "\improper CustodiPRO cartridge"
desc = "The ultimate in clean-room design."
icon_state = "cart-j"
access_janitor = 1
/obj/item/weapon/cartridge/lawyer
name = "\improper P.R.O.V.E. cartridge"
icon_state = "cart-s"
access_security = 1
/obj/item/weapon/cartridge/clown
name = "\improper Honkworks 5.0 cartridge"
icon_state = "cart-clown"
access_clown = 1
charges = 5
/obj/item/weapon/cartridge/mime
name = "\improper Gestur-O 1000 cartridge"
icon_state = "cart-mi"
access_mime = 1
charges = 5
/*
/obj/item/weapon/cartridge/botanist
name = "Green Thumb v4.20"
icon_state = "cart-b"
access_flora = 1
*/
/obj/item/weapon/cartridge/service
name = "\improper Serv-U Pro cartridge"
desc = "A data cartridge designed to serve YOU!"
/obj/item/weapon/cartridge/signal
name = "generic signaler cartridge"
desc = "A data cartridge with an integrated radio signaler module."
var/qdeled = 0
/obj/item/weapon/cartridge/signal/science
name = "\improper Signal Ace 2 cartridge"
desc = "Complete with integrated radio signaler!"
icon_state = "cart-tox"
access_reagent_scanner = 1
access_atmos = 1
/obj/item/weapon/cartridge/signal/Initialize()
radio = new /obj/item/radio/integrated/signal(src)
. = ..()
/obj/item/weapon/cartridge/quartermaster
name = "\improper Space Parts & Space Vendors cartridge"
desc = "Perfect for the Quartermaster on the go!"
icon_state = "cart-q"
access_quartermaster = 1
/obj/item/weapon/cartridge/miner
name = "\improper Drill-Jockey 4.5 cartridge"
desc = "It's covered in some sort of sand."
icon_state = "cart-q"
/obj/item/weapon/cartridge/head
name = "\improper Easy-Record DELUXE cartridge"
icon_state = "cart-h"
access_status_display = 1
/obj/item/weapon/cartridge/hop
name = "\improper HumanResources9001 cartridge"
icon_state = "cart-h"
access_status_display = 1
access_quartermaster = 1
access_janitor = 1
access_security = 1
/obj/item/weapon/cartridge/hos
name = "\improper R.O.B.U.S.T. DELUXE cartridge"
icon_state = "cart-hos"
access_status_display = 1
access_security = 1
/obj/item/weapon/cartridge/hos/Initialize()
radio = new /obj/item/radio/integrated/beepsky(src)
. = ..()
/obj/item/weapon/cartridge/ce
name = "\improper Power-On DELUXE cartridge"
icon_state = "cart-ce"
access_status_display = 1
access_engine = 1
access_atmos = 1
/obj/item/weapon/cartridge/cmo
name = "\improper Med-U DELUXE cartridge"
icon_state = "cart-cmo"
access_status_display = 1
access_reagent_scanner = 1
access_medical = 1
/obj/item/weapon/cartridge/rd
name = "\improper Signal Ace DELUXE cartridge"
icon_state = "cart-rd"
access_status_display = 1
access_reagent_scanner = 1
access_atmos = 1
/obj/item/weapon/cartridge/rd/Initialize()
radio = new /obj/item/radio/integrated/signal(src)
. = ..()
/obj/item/weapon/cartridge/captain
name = "\improper Value-PAK cartridge"
desc = "Now with 200% more value!"
icon_state = "cart-c"
access_quartermaster = 1
access_janitor = 1
access_engine = 1
access_security = 1
access_medical = 1
access_reagent_scanner = 1
access_status_display = 1
access_atmos = 1
/obj/item/weapon/cartridge/syndicate
name = "\improper Detomatix cartridge"
icon_state = "cart"
access_remote_door = 1
access_detonate_pda = 1
remote_door_id = "smindicate" //Make sure this matches the syndicate shuttle's shield/door id!! //don't ask about the name, testing.
charges = 4
/obj/item/weapon/cartridge/proc/post_status(var/command, var/data1, var/data2)
var/datum/radio_frequency/frequency = radio_controller.return_frequency(1435)
if(!frequency) return
var/datum/signal/status_signal = new
status_signal.source = src
status_signal.transmission_method = TRANSMISSION_RADIO
status_signal.data["command"] = command
switch(command)
if("message")
status_signal.data["msg1"] = data1
status_signal.data["msg2"] = data2
if(loc)
var/obj/item/PDA = loc
var/mob/user = PDA.fingerprintslast
log_admin("STATUS: [user] set status screen with [PDA]. Message: [data1] [data2]")
message_admins("STATUS: [user] set status screen with [PDA]. Message: [data1] [data2]")
if("alert")
status_signal.data["picture_state"] = data1
frequency.post_signal(src, status_signal)
/*
This generates the nano values of the cart menus.
Because we close the UI when we insert a new cart
we don't have to worry about null values on items
the user can't access. Well, unless they are href hacking.
But in that case their UI will just lock up.
*/
/obj/item/weapon/cartridge/proc/create_NanoUI_values(mob/user as mob)
var/values[0]
/* Signaler (Mode: 40) */
if(istype(radio,/obj/item/radio/integrated/signal) && (mode==40))
var/obj/item/radio/integrated/signal/R = radio
values["signal_freq"] = format_frequency(R.frequency)
values["signal_code"] = R.code
/* Station Display (Mode: 42) */
if(mode==42)
values["message1"] = message1 ? message1 : "(none)"
values["message2"] = message2 ? message2 : "(none)"
/* Power Monitor (Mode: 43 / 433) */
if(mode==43 || mode==433)
var/list/sensors = list()
var/obj/machinery/power/sensor/MS = null
var/my_z = get_z(user)
var/list/levels = using_map.get_map_levels(my_z)
for(var/obj/machinery/power/sensor/S in machines)
if(!(get_z(S) in levels))
continue
sensors.Add(list(list("name_tag" = S.name_tag)))
if(S.name_tag == selected_sensor)
MS = S
values["power_sensors"] = sensors
if(selected_sensor && MS)
values["sensor_reading"] = MS.return_reading_data()
/* General Records (Mode: 44 / 441 / 45 / 451) */
if(mode == 44 || mode == 441 || mode == 45 || mode ==451)
if(istype(active1, /datum/data/record) && (active1 in data_core.general))
values["general"] = active1.fields
values["general_exists"] = 1
else
values["general_exists"] = 0
/* Medical Records (Mode: 44 / 441) */
if(mode == 44 || mode == 441)
var/medData[0]
for(var/datum/data/record/R in sortRecord(data_core.general))
medData[++medData.len] = list(Name = R.fields["name"],"ref" = "\ref[R]")
values["medical_records"] = medData
if(istype(active2, /datum/data/record) && (active2 in data_core.medical))
values["medical"] = active2.fields
values["medical_exists"] = 1
else
values["medical_exists"] = 0
/* Security Records (Mode:45 / 451) */
if(mode == 45 || mode == 451)
var/secData[0]
for (var/datum/data/record/R in sortRecord(data_core.general))
secData[++secData.len] = list(Name = R.fields["name"], "ref" = "\ref[R]")
values["security_records"] = secData
if(istype(active3, /datum/data/record) && (active3 in data_core.security))
values["security"] = active3.fields
values["security_exists"] = 1
else
values["security_exists"] = 0
/* Security Bot Control (Mode: 46) */
if(mode==46)
var/botsData[0]
var/beepskyData[0]
if(istype(radio,/obj/item/radio/integrated/beepsky))
var/obj/item/radio/integrated/beepsky/SC = radio
beepskyData["active"] = SC.active
if(SC.active && !isnull(SC.botstatus))
var/area/loca = SC.botstatus["loca"]
var/loca_name = sanitize(loca.name)
beepskyData["botstatus"] = list("loca" = loca_name, "mode" = SC.botstatus["mode"])
else
beepskyData["botstatus"] = list("loca" = null, "mode" = -1)
var/botsCount=0
if(SC.botlist && SC.botlist.len)
for(var/mob/living/bot/B in SC.botlist)
botsCount++
if(B.loc)
botsData[++botsData.len] = list("Name" = sanitize(B.name), "Location" = sanitize(B.loc.loc.name), "ref" = "\ref[B]")
if(!botsData.len)
botsData[++botsData.len] = list("Name" = "No bots found", "Location" = "Invalid", "ref"= null)
beepskyData["bots"] = botsData
beepskyData["count"] = botsCount
else
beepskyData["active"] = 0
botsData[++botsData.len] = list("Name" = "No bots found", "Location" = "Invalid", "ref"= null)
beepskyData["botstatus"] = list("loca" = null, "mode" = null)
beepskyData["bots"] = botsData
beepskyData["count"] = 0
values["beepsky"] = beepskyData
/* MULEBOT Control (Mode: 48) */
if(mode==48)
var/mulebotsData[0]
var/count = 0
for(var/mob/living/bot/mulebot/M in living_mob_list)
if(!M.on)
continue
++count
var/muleData[0]
muleData["name"] = M.suffix
muleData["location"] = get_area(M)
muleData["paused"] = M.paused
muleData["home"] = M.homeName
muleData["target"] = M.targetName
muleData["ref"] = "\ref[M]"
muleData["load"] = M.load ? M.load.name : "Nothing"
mulebotsData[++mulebotsData.len] = muleData.Copy()
values["mulebotcount"] = count
values["mulebots"] = mulebotsData
/* Supply Shuttle Requests Menu (Mode: 47) */
if(mode==47)
var/supplyData[0]
var/datum/shuttle/autodock/ferry/supply/shuttle = SSsupply.shuttle
if (shuttle)
supplyData["shuttle_moving"] = shuttle.has_arrive_time()
supplyData["shuttle_eta"] = shuttle.eta_minutes()
supplyData["shuttle_loc"] = shuttle.at_station() ? "Station" : "Dock"
var/supplyOrderCount = 0
var/supplyOrderData[0]
for(var/S in SSsupply.shoppinglist)
var/datum/supply_order/SO = S
supplyOrderData[++supplyOrderData.len] = list("Number" = SO.ordernum, "Name" = html_encode(SO.object.name), "ApprovedBy" = SO.ordered_by, "Comment" = html_encode(SO.comment))
if(!supplyOrderData.len)
supplyOrderData[++supplyOrderData.len] = list("Number" = null, "Name" = null, "OrderedBy"=null)
supplyData["approved"] = supplyOrderData
supplyData["approved_count"] = supplyOrderCount
var/requestCount = 0
var/requestData[0]
for(var/S in SSsupply.order_history)
var/datum/supply_order/SO = S
if(SO.status != SUP_ORDER_REQUESTED)
continue
requestCount++
requestData[++requestData.len] = list("Number" = SO.ordernum, "Name" = html_encode(SO.object.name), "OrderedBy" = SO.ordered_by, "Comment" = html_encode(SO.comment))
if(!requestData.len)
requestData[++requestData.len] = list("Number" = null, "Name" = null, "orderedBy" = null, "Comment" = null)
supplyData["requests"] = requestData
supplyData["requests_count"] = requestCount
values["supply"] = supplyData
/* Janitor Supplies Locator (Mode: 49) */
if(mode==49)
var/JaniData[0]
var/turf/cl = get_turf(src)
if(cl)
JaniData["user_loc"] = list("x" = cl.x, "y" = cl.y)
else
JaniData["user_loc"] = list("x" = 0, "y" = 0)
var/MopData[0]
for(var/obj/item/weapon/mop/M in all_mops)
var/turf/ml = get_turf(M)
if(ml)
if(ml.z != cl.z)
continue
var/direction = get_dir(src, M)
MopData[++MopData.len] = list ("x" = ml.x, "y" = ml.y, "dir" = uppertext(dir2text(direction)), "status" = M.reagents.total_volume ? "Wet" : "Dry")
if(!MopData.len)
MopData[++MopData.len] = list("x" = 0, "y" = 0, dir=null, status = null)
var/BucketData[0]
for(var/obj/structure/mopbucket/B in all_mopbuckets)
var/turf/bl = get_turf(B)
if(bl)
if(bl.z != cl.z)
continue
var/direction = get_dir(src,B)
BucketData[++BucketData.len] = list ("x" = bl.x, "y" = bl.y, "dir" = uppertext(dir2text(direction)), "status" = B.reagents.total_volume/100)
if(!BucketData.len)
BucketData[++BucketData.len] = list("x" = 0, "y" = 0, dir=null, status = null)
var/CbotData[0]
for(var/mob/living/bot/cleanbot/B in mob_list)
var/turf/bl = get_turf(B)
if(bl)
if(bl.z != cl.z)
continue
var/direction = get_dir(src,B)
CbotData[++CbotData.len] = list("x" = bl.x, "y" = bl.y, "dir" = uppertext(dir2text(direction)), "status" = B.on ? "Online" : "Offline")
if(!CbotData.len)
CbotData[++CbotData.len] = list("x" = 0, "y" = 0, dir=null, status = null)
var/CartData[0]
for(var/obj/structure/janitorialcart/B in all_janitorial_carts)
var/turf/bl = get_turf(B)
if(bl)
if(bl.z != cl.z)
continue
var/direction = get_dir(src,B)
var/status = "No Bucket"
if(B.mybucket)
status = B.mybucket.reagents.total_volume / 100
CartData[++CartData.len] = list("x" = bl.x, "y" = bl.y, "dir" = uppertext(dir2text(direction)), "status" = status)
if(!CartData.len)
CartData[++CartData.len] = list("x" = 0, "y" = 0, dir=null, status = null)
JaniData["mops"] = MopData
JaniData["buckets"] = BucketData
JaniData["cleanbots"] = CbotData
JaniData["carts"] = CartData
values["janitor"] = JaniData
return values
/obj/item/weapon/cartridge/Topic(href, href_list)
..()
if (!usr.canmove || usr.stat || usr.restrained() || !in_range(loc, usr))
usr.unset_machine()
usr << browse(null, "window=pda")
return
switch(href_list["choice"])
if("Medical Records")
var/datum/data/record/R = locate(href_list["target"])
var/datum/data/record/M = locate(href_list["target"])
loc:mode = 441
mode = 441
if (R in data_core.general)
for (var/datum/data/record/E in data_core.medical)
if ((E.fields["name"] == R.fields["name"] || E.fields["id"] == R.fields["id"]))
M = E
break
active1 = R
active2 = M
if("Security Records")
var/datum/data/record/R = locate(href_list["target"])
var/datum/data/record/S = locate(href_list["target"])
loc:mode = 451
mode = 451
if (R in data_core.general)
for (var/datum/data/record/E in data_core.security)
if ((E.fields["name"] == R.fields["name"] || E.fields["id"] == R.fields["id"]))
S = E
break
active1 = R
active3 = S
if("Send Signal")
if(is_jammed(src))
return
spawn( 0 )
radio:send_signal("ACTIVATE")
return
if("Signal Frequency")
var/new_frequency = sanitize_frequency(radio:frequency + text2num(href_list["sfreq"]))
radio:set_frequency(new_frequency)
if("Signal Code")
radio:code += text2num(href_list["scode"])
radio:code = round(radio:code)
radio:code = min(100, radio:code)
radio:code = max(1, radio:code)
if("Status")
switch(href_list["statdisp"])
if("message")
post_status("message", message1, message2)
if("alert")
post_status("alert", href_list["alert"])
if("setmsg1")
message1 = reject_bad_text(sanitize(input("Line 1", "Enter Message Text", message1) as text|null, 40), 40)
updateSelfDialog()
if("setmsg2")
message2 = reject_bad_text(sanitize(input("Line 2", "Enter Message Text", message2) as text|null, 40), 40)
updateSelfDialog()
else
post_status(href_list["statdisp"])
if("Power Select")
selected_sensor = href_list["target"]
loc:mode = 433
mode = 433
if("Power Clear")
selected_sensor = null
loc:mode = 43
mode = 43
if("MULEbot")
var/mob/living/bot/mulebot/M = locate(href_list["ref"])
if(istype(M))
M.obeyCommand(href_list["command"])
return 1
@@ -1,17 +0,0 @@
var/list/exploration_cartridges = list(
/obj/item/weapon/cartridge/explorer,
/obj/item/weapon/cartridge/sar
)
/obj/item/weapon/cartridge/explorer
name = "\improper Explorator cartridge"
icon_state = "cart-e"
access_reagent_scanner = 1
access_atmos = 1
/obj/item/weapon/cartridge/sar
name = "\improper Med-Exp cartridge"
icon_state = "cart-m"
access_medical = 1
access_reagent_scanner = 1
access_atmos = 1
@@ -1,16 +0,0 @@
var/list/chatrooms = list()
/datum/chatroom
var/name = "Generic Chatroom"
var/list/logged_in = list()
var/list/logs = list() // chat logs
var/list/banned = list() // banned users
var/list/whitelist = list() // whitelisted users
var/list/muted = list()
var/topic = "" // topic message for the chatroom
var/password = "" // blank for no password.
var/operator = "" // name of the operator
/datum/chatroom/proc/attempt_connect(var/obj/item/device/pda/device, var/obj/password)
if(!device)
return
@@ -1,153 +0,0 @@
/obj/item/radio/integrated
name = "\improper PDA radio module"
desc = "An electronic radio system."
icon = 'icons/obj/module.dmi'
icon_state = "power_mod"
var/obj/item/device/pda/hostpda = null
var/on = 0 //Are we currently active??
var/menu_message = ""
New()
..()
if (istype(loc.loc, /obj/item/device/pda))
hostpda = loc.loc
proc/post_signal(var/freq, var/key, var/value, var/key2, var/value2, var/key3, var/value3, s_filter)
//to_world("Post: [freq]: [key]=[value], [key2]=[value2]")
var/datum/radio_frequency/frequency = radio_controller.return_frequency(freq)
if(!frequency) return
var/datum/signal/signal = new()
signal.source = src
signal.transmission_method = TRANSMISSION_RADIO
signal.data[key] = value
if(key2)
signal.data[key2] = value2
if(key3)
signal.data[key3] = value3
frequency.post_signal(src, signal, radio_filter = s_filter)
return
proc/generate_menu()
/obj/item/radio/integrated/beepsky
var/list/botlist = null // list of bots
var/mob/living/bot/secbot/active // the active bot; if null, show bot list
var/list/botstatus // the status signal sent by the bot
var/control_freq = BOT_FREQ
// create a new QM cartridge, and register to receive bot control & beacon message
New()
..()
spawn(5)
if(radio_controller)
radio_controller.add_object(src, control_freq, radio_filter = RADIO_SECBOT)
// receive radio signals
// can detect bot status signals
// create/populate list as they are recvd
receive_signal(datum/signal/signal)
// var/obj/item/device/pda/P = src.loc
/*
to_world("recvd:[P] : [signal.source]")
for(var/d in signal.data)
to_world("- [d] = [signal.data[d]]")
*/
if (signal.data["type"] == "secbot")
if(!botlist)
botlist = new()
if(!(signal.source in botlist))
botlist += signal.source
if(active == signal.source)
var/list/b = signal.data
botstatus = b.Copy()
// if (istype(P)) P.updateSelfDialog()
Topic(href, href_list)
..()
var/obj/item/device/pda/PDA = src.hostpda
switch(href_list["op"])
if("control")
active = locate(href_list["bot"])
post_signal(control_freq, "command", "bot_status", "active", active, s_filter = RADIO_SECBOT)
if("scanbots") // find all bots
botlist = null
post_signal(control_freq, "command", "bot_status", s_filter = RADIO_SECBOT)
if("botlist")
active = null
if("stop", "go")
post_signal(control_freq, "command", href_list["op"], "active", active, s_filter = RADIO_SECBOT)
post_signal(control_freq, "command", "bot_status", "active", active, s_filter = RADIO_SECBOT)
if("summon")
post_signal(control_freq, "command", "summon", "active", active, "target", get_turf(PDA) , s_filter = RADIO_SECBOT)
post_signal(control_freq, "command", "bot_status", "active", active, s_filter = RADIO_SECBOT)
/obj/item/radio/integrated/beepsky/Destroy()
if(radio_controller)
radio_controller.remove_object(src, control_freq)
return ..()
/*
* Radio Cartridge, essentially a signaler.
*/
/obj/item/radio/integrated/signal
var/frequency = 1457
var/code = 30.0
var/last_transmission
var/datum/radio_frequency/radio_connection
/obj/item/radio/integrated/signal/Initialize()
if(!radio_controller)
return
if (src.frequency < PUBLIC_LOW_FREQ || src.frequency > PUBLIC_HIGH_FREQ)
src.frequency = sanitize_frequency(src.frequency)
set_frequency(frequency)
/obj/item/radio/integrated/signal/proc/set_frequency(new_frequency)
radio_controller.remove_object(src, frequency)
frequency = new_frequency
radio_connection = radio_controller.add_object(src, frequency)
/obj/item/radio/integrated/signal/proc/send_signal(message="ACTIVATE")
if(last_transmission && world.time < (last_transmission + 5))
return
last_transmission = world.time
var/time = time2text(world.realtime,"hh:mm:ss")
var/turf/T = get_turf(src)
lastsignalers.Add("[time] <B>:</B> [usr.key] used [src] @ location ([T.x],[T.y],[T.z]) <B>:</B> [format_frequency(frequency)]/[code]")
var/datum/signal/signal = new
signal.source = src
signal.encryption = code
signal.data["message"] = message
radio_connection.post_signal(src, signal)
/obj/item/radio/integrated/signal/Destroy()
if(radio_controller)
radio_controller.remove_object(src, frequency)
return ..()
@@ -1,292 +0,0 @@
// Proc: ui_interact()
// Parameters: 4 (standard NanoUI arguments)
// Description: Uses a bunch of for loops to turn lists into lists of lists, so they can be displayed in nanoUI, then displays various buttons to the user.
/obj/item/device/communicator/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1, var/key_state = null)
// this is the data which will be sent to the ui
var/data[0] //General nanoUI information
var/communicators[0] //List of communicators
var/invites[0] //Communicators and ghosts we've invited to our communicator.
var/requests[0] //Communicators and ghosts wanting to go in our communicator.
var/voices[0] //Current /mob/living/voice s inside the device.
var/connected_communicators[0] //Current communicators connected to the device.
var/im_contacts_ui[0] //List of communicators that have been messaged.
var/im_list_ui[0] //List of messages.
var/weather[0]
var/modules_ui[0] //Home screen info.
//First we add other 'local' communicators.
for(var/obj/item/device/communicator/comm in known_devices)
if(comm.network_visibility && comm.exonet)
communicators[++communicators.len] = list("name" = sanitize(comm.name), "address" = comm.exonet.address)
//Now for ghosts who we pretend have communicators.
for(var/mob/observer/dead/O in known_devices)
if(O.client && O.client.prefs.communicator_visibility == 1 && O.exonet)
communicators[++communicators.len] = list("name" = sanitize("[O.client.prefs.real_name]'s communicator"), "address" = O.exonet.address, "ref" = "\ref[O]")
//Lists all the other communicators that we invited.
for(var/obj/item/device/communicator/comm in voice_invites)
if(comm.exonet)
invites[++invites.len] = list("name" = sanitize(comm.name), "address" = comm.exonet.address, "ref" = "\ref[comm]")
//Ghosts we invited.
for(var/mob/observer/dead/O in voice_invites)
if(O.exonet && O.client)
invites[++invites.len] = list("name" = sanitize("[O.client.prefs.real_name]'s communicator"), "address" = O.exonet.address, "ref" = "\ref[O]")
//Communicators that want to talk to us.
for(var/obj/item/device/communicator/comm in voice_requests)
if(comm.exonet)
requests[++requests.len] = list("name" = sanitize(comm.name), "address" = comm.exonet.address, "ref" = "\ref[comm]")
//Ghosts that want to talk to us.
for(var/mob/observer/dead/O in voice_requests)
if(O.exonet && O.client)
requests[++requests.len] = list("name" = sanitize("[O.client.prefs.real_name]'s communicator"), "address" = O.exonet.address, "ref" = "\ref[O]")
//Now for all the voice mobs inside the communicator.
for(var/mob/living/voice/voice in contents)
voices[++voices.len] = list("name" = sanitize("[voice.name]'s communicator"), "true_name" = sanitize(voice.name))
//Finally, all the communicators linked to this one.
for(var/obj/item/device/communicator/comm in communicating)
connected_communicators[++connected_communicators.len] = list("name" = sanitize(comm.name), "true_name" = sanitize(comm.name), "ref" = "\ref[comm]")
//Devices that have been messaged or recieved messages from.
for(var/obj/item/device/communicator/comm in im_contacts)
if(comm.exonet)
im_contacts_ui[++im_contacts_ui.len] = list("name" = sanitize(comm.name), "address" = comm.exonet.address, "ref" = "\ref[comm]")
for(var/mob/observer/dead/ghost in im_contacts)
if(ghost.exonet)
im_contacts_ui[++im_contacts_ui.len] = list("name" = sanitize(ghost.name), "address" = ghost.exonet.address, "ref" = "\ref[ghost]")
for(var/obj/item/integrated_circuit/input/EPv2/CIRC in im_contacts)
if(CIRC.exonet && CIRC.assembly)
im_contacts_ui[++im_contacts_ui.len] = list("name" = sanitize(CIRC.assembly.name), "address" = CIRC.exonet.address, "ref" = "\ref[CIRC]")
//Actual messages.
for(var/I in im_list)
im_list_ui[++im_list_ui.len] = list("address" = I["address"], "to_address" = I["to_address"], "im" = I["im"])
//Weather reports.
for(var/datum/planet/planet in SSplanets.planets)
if(planet.weather_holder && planet.weather_holder.current_weather)
var/list/W = list(
"Planet" = planet.name,
"Time" = planet.current_time.show_time("hh:mm"),
"Weather" = planet.weather_holder.current_weather.name,
"Temperature" = planet.weather_holder.temperature - T0C,
"High" = planet.weather_holder.current_weather.temp_high - T0C,
"Low" = planet.weather_holder.current_weather.temp_low - T0C,
"WindDir" = planet.weather_holder.wind_dir ? dir2text(planet.weather_holder.wind_dir) : "None",
"WindSpeed" = planet.weather_holder.wind_speed ? "[planet.weather_holder.wind_speed > 2 ? "Severe" : "Normal"]" : "None",
"Forecast" = english_list(planet.weather_holder.forecast, and_text = "&#8594;", comma_text = "&#8594;", final_comma_text = "&#8594;") // Unicode RIGHTWARDS ARROW.
)
weather[++weather.len] = W
// Update manifest
data_core.get_manifest_list()
//Modules for homescreen.
for(var/list/R in modules)
modules_ui[++modules_ui.len] = R
data["user"] = "\ref[user]" // For receiving input() via topic, because input(usr,...) wasn't working on cartridges
data["owner"] = owner ? owner : "Unset"
data["occupation"] = occupation ? occupation : "Swipe ID to set."
data["connectionStatus"] = get_connection_to_tcomms()
data["visible"] = network_visibility
data["address"] = exonet.address ? exonet.address : "Unallocated"
data["targetAddress"] = target_address
data["targetAddressName"] = target_address_name
data["currentTab"] = selected_tab
data["knownDevices"] = communicators
data["invitesSent"] = invites
data["requestsReceived"] = requests
data["voice_mobs"] = voices
data["communicating"] = connected_communicators
data["video_comm"] = video_source ? "\ref[video_source.loc]" : null
data["imContacts"] = im_contacts_ui
data["imList"] = im_list_ui
data["time"] = stationtime2text()
data["ring"] = ringer
data["homeScreen"] = modules_ui
data["note"] = note // current notes
data["weather"] = weather
data["aircontents"] = src.analyze_air()
data["flashlight"] = fon
data["manifest"] = PDA_Manifest
data["feeds"] = compile_news()
data["latest_news"] = get_recent_news()
if(newsfeed_channel)
data["target_feed"] = data["feeds"][newsfeed_channel]
if(cartridge) // If there's a cartridge, we need to grab the information from it
data["cart_devices"] = cartridge.get_device_status()
data["cart_templates"] = cartridge.ui_templates
for(var/list/L in cartridge.get_data())
data[L["field"]] = L["value"]
// cartridge.get_data() returns a list of tuples:
// The field element is the tag used to access the information by the template
// The value element is the actual data, and can take any form necessary for the template
// update the ui if it exists, returns null if no ui is passed/found
ui = SSnanoui.try_update_ui(user, src, ui_key, ui, data, force_open)
if(!ui)
// the ui does not exist, so we'll create a new() one
// for a list of parameters and their descriptions see the code docs in \code\modules\nano\nanoui.dm
data["currentTab"] = 1 // Reset the current tab, because we're going to home page
ui = new(user, src, ui_key, "communicator_header.tmpl", "Communicator", 475, 700, state = key_state)
// add templates for screens in common with communicator.
ui.add_template("atmosphericScan", "atmospheric_scan.tmpl")
ui.add_template("crewManifest", "crew_manifest.tmpl")
ui.add_template("Body", "communicator.tmpl") // Main body
// when the ui is first opened this is the data it will use
ui.set_initial_data(data)
// open the new ui window
ui.open()
// auto update every five Master Controller tick
ui.set_auto_update(5)
// Proc: Topic()
// Parameters: 2 (standard Topic arguments)
// Description: Responds to NanoUI button presses.
/obj/item/device/communicator/Topic(href, href_list)
if(..())
return 1
if(href_list["rename"])
var/new_name = sanitizeSafe(input(usr,"Please enter your name.","Communicator",usr.name) )
if(new_name)
register_device(new_name)
if(href_list["toggle_visibility"])
switch(network_visibility)
if(1) //Visible, becoming invisbile
network_visibility = 0
if(camera)
camera.remove_network(NETWORK_COMMUNICATORS)
if(0) //Invisible, becoming visible
network_visibility = 1
if(camera)
camera.add_network(NETWORK_COMMUNICATORS)
if(href_list["toggle_ringer"])
ringer = !ringer
if(href_list["add_hex"])
var/hex = href_list["add_hex"]
add_to_EPv2(hex)
if(href_list["write_target_address"])
var/new_address = sanitizeSafe(input(usr,"Please enter the desired target EPv2 address. Note that you must write the colons \
yourself.","Communicator",src.target_address) )
if(new_address)
target_address = new_address
if(href_list["clear_target_address"])
target_address = ""
if(href_list["dial"])
if(!get_connection_to_tcomms())
to_chat(usr, "<span class='danger'>Error: Cannot connect to Exonet node.</span>")
return
var/their_address = href_list["dial"]
exonet.send_message(their_address, "voice")
if(href_list["decline"])
var/ref_to_remove = href_list["decline"]
var/atom/decline = locate(ref_to_remove)
if(decline)
del_request(decline)
if(href_list["message"])
if(!get_connection_to_tcomms())
to_chat(usr, "<span class='danger'>Error: Cannot connect to Exonet node.</span>")
return
var/their_address = href_list["message"]
var/text = sanitizeSafe(input(usr,"Enter your message.","Text Message"))
if(text)
exonet.send_message(their_address, "text", text)
im_list += list(list("address" = exonet.address, "to_address" = their_address, "im" = text))
log_pda("(COMM: [src]) sent \"[text]\" to [exonet.get_atom_from_address(their_address)]", usr)
for(var/mob/M in player_list)
if(M.stat == DEAD && M.is_preference_enabled(/datum/client_preference/ghost_ears))
if(istype(M, /mob/new_player) || M.forbid_seeing_deadchat)
continue
if(exonet.get_atom_from_address(their_address) == M)
continue
M.show_message("Comm IM - [src] -> [exonet.get_atom_from_address(their_address)]: [text]")
if(href_list["disconnect"])
var/name_to_disconnect = href_list["disconnect"]
for(var/mob/living/voice/V in contents)
if(name_to_disconnect == V.name)
close_connection(usr, V, "[usr] hung up")
for(var/obj/item/device/communicator/comm in communicating)
if(name_to_disconnect == comm.name)
close_connection(usr, comm, "[usr] hung up")
if(href_list["startvideo"])
var/ref_to_video = href_list["startvideo"]
var/obj/item/device/communicator/comm = locate(ref_to_video)
if(comm)
connect_video(usr, comm)
if(href_list["endvideo"])
if(video_source)
end_video()
if(href_list["watchvideo"])
if(video_source)
watch_video(usr,video_source.loc)
if(href_list["copy"])
target_address = href_list["copy"]
if(href_list["copy_name"])
target_address_name = href_list["copy_name"]
if(href_list["hang_up"])
for(var/mob/living/voice/V in contents)
close_connection(usr, V, "[usr] hung up")
for(var/obj/item/device/communicator/comm in communicating)
close_connection(usr, comm, "[usr] hung up")
if(href_list["switch_tab"])
selected_tab = href_list["switch_tab"]
if(href_list["edit"])
var/n = input(usr, "Please enter message", name, notehtml)
n = sanitizeSafe(n, extra = 0)
if(n)
note = html_decode(n)
notehtml = note
note = replacetext(note, "\n", "<br>")
else
note = ""
notehtml = note
if(href_list["switch_template"])
var/datum/nanoui/ui = SSnanoui.get_open_ui(usr, src, "main")
if(ui)
ui.add_template("Body", href_list["switch_template"])
if(href_list["Light"])
fon = !fon
set_light(fon * flum)
if(href_list["toggle_device"])
var/obj/O = cartridge.internal_devices[text2num(href_list["toggle_device"])]
cartridge.active_devices ^= list(O) // Exclusive or, will toggle its presence
if(href_list["newsfeed"])
newsfeed_channel = text2num(href_list["newsfeed"])
if(href_list["cartridge_topic"] && cartridge) // Has to have a cartridge to perform these functions
cartridge.Topic(href, href_list)
SSnanoui.update_uis(src)
add_fingerprint(usr)
@@ -0,0 +1,326 @@
// Proc: tgui_state()
// Parameters: User
// Description: This tells TGUI to only allow us to be interacted with while in a mob inventory.
/obj/item/device/communicator/tgui_state(mob/user)
return GLOB.tgui_inventory_state
// Proc: tgui_interact()
// Parameters: User, UI, Parent UI
// Description: This proc handles opening the UI. It's basically just a standard stub.
/obj/item/device/communicator/tgui_interact(mob/user, datum/tgui/ui, datum/tgui/parent_ui, datum/tgui_state/custom_state)
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
ui = new(user, src, "Communicator", name)
if(custom_state)
ui.set_state(custom_state)
ui.open()
if(custom_state) // Just in case
ui.set_state(custom_state)
// Proc: tgui_data()
// Parameters: User, UI, State
// Description: Uses a bunch of for loops to turn lists into lists of lists, so they can be displayed in nanoUI, then displays various buttons to the user.
/obj/item/device/communicator/tgui_data(mob/user, datum/tgui/ui, datum/tgui_state/state)
// this is the data which will be sent to the ui
var/list/data = list() //General nanoUI information
var/list/communicators = list() //List of communicators
var/list/invites = list() //Communicators and ghosts we've invited to our communicator.
var/list/requests = list() //Communicators and ghosts wanting to go in our communicator.
var/list/voices = list() //Current /mob/living/voice s inside the device.
var/list/connected_communicators = list() //Current communicators connected to the device.
var/list/im_contacts_ui = list() //List of communicators that have been messaged.
var/list/im_list_ui = list() //List of messages.
var/list/weather = list()
var/list/modules_ui = list() //Home screen info.
//First we add other 'local' communicators.
for(var/obj/item/device/communicator/comm in known_devices)
if(comm.network_visibility && comm.exonet)
communicators.Add(list(list(
"name" = sanitize(comm.name),
"address" = comm.exonet.address
)))
//Now for ghosts who we pretend have communicators.
for(var/mob/observer/dead/O in known_devices)
if(O.client && O.client.prefs.communicator_visibility == 1 && O.exonet)
communicators.Add(list(list(
"name" = sanitize("[O.client.prefs.real_name]'s communicator"),
"address" = O.exonet.address,
"ref" = "\ref[O]"
)))
//Lists all the other communicators that we invited.
for(var/obj/item/device/communicator/comm in voice_invites)
if(comm.exonet)
invites.Add(list(list(
"name" = sanitize(comm.name),
"address" = comm.exonet.address,
"ref" = "\ref[comm]"
)))
//Ghosts we invited.
for(var/mob/observer/dead/O in voice_invites)
if(O.exonet && O.client)
invites.Add(list(list(
"name" = sanitize("[O.client.prefs.real_name]'s communicator"),
"address" = O.exonet.address,
"ref" = "\ref[O]"
)))
//Communicators that want to talk to us.
for(var/obj/item/device/communicator/comm in voice_requests)
if(comm.exonet)
requests.Add(list(list(
"name" = sanitize(comm.name),
"address" = comm.exonet.address,
"ref" = "\ref[comm]"
)))
//Ghosts that want to talk to us.
for(var/mob/observer/dead/O in voice_requests)
if(O.exonet && O.client)
requests.Add(list(list(
"name" = sanitize("[O.client.prefs.real_name]'s communicator"),
"address" = O.exonet.address,
"ref" = "\ref[O]"
)))
//Now for all the voice mobs inside the communicator.
for(var/mob/living/voice/voice in contents)
voices.Add(list(list(
"name" = sanitize("[voice.name]'s communicator"),
"true_name" = sanitize(voice.name),
)))
//Finally, all the communicators linked to this one.
for(var/obj/item/device/communicator/comm in communicating)
connected_communicators.Add(list(list(
"name" = sanitize(comm.name),
"true_name" = sanitize(comm.name),
"ref" = "\ref[comm]",
)))
//Devices that have been messaged or recieved messages from.
for(var/obj/item/device/communicator/comm in im_contacts)
if(comm.exonet)
im_contacts_ui.Add(list(list(
"name" = sanitize(comm.name),
"address" = comm.exonet.address,
"ref" = "\ref[comm]"
)))
for(var/mob/observer/dead/ghost in im_contacts)
if(ghost.exonet)
im_contacts_ui.Add(list(list(
"name" = sanitize(ghost.name),
"address" = ghost.exonet.address,
"ref" = "\ref[ghost]"
)))
for(var/obj/item/integrated_circuit/input/EPv2/CIRC in im_contacts)
if(CIRC.exonet && CIRC.assembly)
im_contacts_ui.Add(list(list(
"name" = sanitize(CIRC.assembly.name),
"address" = CIRC.exonet.address,
"ref" = "\ref[CIRC]"
)))
//Actual messages.
for(var/I in im_list)
im_list_ui.Add(list(list(
"address" = I["address"],
"to_address" = I["to_address"],
"im" = I["im"]
)))
//Weather reports.
for(var/datum/planet/planet in SSplanets.planets)
if(planet.weather_holder && planet.weather_holder.current_weather)
var/list/W = list(
"Planet" = planet.name,
"Time" = planet.current_time.show_time("hh:mm"),
"Weather" = planet.weather_holder.current_weather.name,
"Temperature" = planet.weather_holder.temperature - T0C,
"High" = planet.weather_holder.current_weather.temp_high - T0C,
"Low" = planet.weather_holder.current_weather.temp_low - T0C,
"WindDir" = planet.weather_holder.wind_dir ? dir2text(planet.weather_holder.wind_dir) : "None",
"WindSpeed" = planet.weather_holder.wind_speed ? "[planet.weather_holder.wind_speed > 2 ? "Severe" : "Normal"]" : "None",
"Forecast" = english_list(planet.weather_holder.forecast, and_text = "&#8594;", comma_text = "&#8594;", final_comma_text = "&#8594;") // Unicode RIGHTWARDS ARROW.
)
weather.Add(list(W))
//Modules for homescreen.
for(var/list/R in modules)
modules_ui.Add(list(R))
data["user"] = "\ref[user]" // For receiving input() via topic, because input(usr,...) wasn't working on cartridges
data["owner"] = owner ? owner : "Unset"
data["occupation"] = occupation ? occupation : "Swipe ID to set."
data["connectionStatus"] = get_connection_to_tcomms()
data["visible"] = network_visibility
data["address"] = exonet.address ? exonet.address : "Unallocated"
data["targetAddress"] = target_address
data["targetAddressName"] = target_address_name
data["currentTab"] = selected_tab
data["knownDevices"] = communicators
data["invitesSent"] = invites
data["requestsReceived"] = requests
data["voice_mobs"] = voices
data["communicating"] = connected_communicators
data["video_comm"] = video_source ? "\ref[video_source.loc]" : null
data["imContacts"] = im_contacts_ui
data["imList"] = im_list_ui
data["time"] = stationtime2text()
data["ring"] = ringer
data["homeScreen"] = modules_ui
data["note"] = note // current notes
data["weather"] = weather
data["aircontents"] = src.analyze_air()
data["flashlight"] = fon
data["feeds"] = compile_news()
data["latest_news"] = get_recent_news()
if(newsfeed_channel)
data["target_feed"] = data["feeds"][newsfeed_channel]
else
data["target_feed"] = null
return data
// Proc: tgui_static_data()
// Parameters: User, UI, State
// Description: Just like tgui_data, except it only gets called once when the user opens the UI, not every tick.
/obj/item/device/communicator/tgui_static_data(mob/user, datum/tgui/ui, datum/tgui_state/state)
var/list/data = ..()
// Update manifest'
if(data_core)
data_core.get_manifest_list()
data["manifest"] = PDA_Manifest
return data
// Proc: tgui-act()
// Parameters: 4 (standard tgui_act arguments)
// Description: Responds to UI button presses.
/obj/item/device/communicator/tgui_act(action, list/params, datum/tgui/ui, datum/tgui_state/state)
if(..())
return TRUE
add_fingerprint(usr)
. = TRUE
switch(action)
if("rename")
var/new_name = sanitizeSafe(input(usr,"Please enter your name.","Communicator",usr.name) )
if(new_name)
register_device(new_name)
if("toggle_visibility")
switch(network_visibility)
if(1) //Visible, becoming invisbile
network_visibility = 0
if(camera)
camera.remove_network(NETWORK_COMMUNICATORS)
if(0) //Invisible, becoming visible
network_visibility = 1
if(camera)
camera.add_network(NETWORK_COMMUNICATORS)
if("toggle_ringer")
ringer = !ringer
if("add_hex")
var/hex = params["add_hex"]
add_to_EPv2(hex)
if("write_target_address")
target_address = sanitizeSafe(params["val"])
if("clear_target_address")
target_address = ""
if("dial")
if(!get_connection_to_tcomms())
to_chat(usr, "<span class='danger'>Error: Cannot connect to Exonet node.</span>")
return FALSE
var/their_address = params["dial"]
exonet.send_message(their_address, "voice")
if("decline")
var/ref_to_remove = params["decline"]
var/atom/decline = locate(ref_to_remove)
if(decline)
del_request(decline)
if("message")
if(!get_connection_to_tcomms())
to_chat(usr, "<span class='danger'>Error: Cannot connect to Exonet node.</span>")
return FALSE
var/their_address = params["message"]
var/text = sanitizeSafe(input(usr,"Enter your message.","Text Message"))
if(text)
exonet.send_message(their_address, "text", text)
im_list += list(list("address" = exonet.address, "to_address" = their_address, "im" = text))
log_pda("(COMM: [src]) sent \"[text]\" to [exonet.get_atom_from_address(their_address)]", usr)
for(var/mob/M in player_list)
if(M.stat == DEAD && M.is_preference_enabled(/datum/client_preference/ghost_ears))
if(istype(M, /mob/new_player) || M.forbid_seeing_deadchat)
continue
if(exonet.get_atom_from_address(their_address) == M)
continue
M.show_message("Comm IM - [src] -> [exonet.get_atom_from_address(their_address)]: [text]")
if("disconnect")
var/name_to_disconnect = params["disconnect"]
for(var/mob/living/voice/V in contents)
if(name_to_disconnect == sanitize(V.name))
close_connection(usr, V, "[usr] hung up")
for(var/obj/item/device/communicator/comm in communicating)
if(name_to_disconnect == sanitize(comm.name))
close_connection(usr, comm, "[usr] hung up")
if("startvideo")
var/ref_to_video = params["startvideo"]
var/obj/item/device/communicator/comm = locate(ref_to_video)
if(comm)
connect_video(usr, comm)
if("endvideo")
if(video_source)
end_video()
if("copy")
target_address = params["copy"]
if("copy_name")
target_address_name = params["copy_name"]
if("hang_up")
for(var/mob/living/voice/V in contents)
close_connection(usr, V, "[usr] hung up")
for(var/obj/item/device/communicator/comm in communicating)
close_connection(usr, comm, "[usr] hung up")
if("switch_tab")
selected_tab = params["switch_tab"]
if("edit")
var/n = input(usr, "Please enter message", name, notehtml) as message|null
n = sanitizeSafe(n, extra = 0)
if(n)
note = html_decode(n)
notehtml = note
note = replacetext(note, "\n", "<br>")
else
note = ""
notehtml = note
if("Light")
fon = !fon
set_light(fon * flum)
if("newsfeed")
newsfeed_channel = text2num(params["newsfeed"])
@@ -1,952 +0,0 @@
// Communicator peripheral devices
// Internal devices that attack() can be relayed to
// Additional UI menus for added functionality
/obj/item/weapon/commcard
name = "generic commcard"
desc = "A peripheral plug-in for personal communicators."
icon = 'icons/obj/pda.dmi'
icon_state = "cart"
item_state = "electronic"
w_class = ITEMSIZE_TINY
var/list/internal_devices = list() // Devices that can be toggled on to trigger on attack()
var/list/active_devices = list() // Devices that will be triggered on attack()
var/list/ui_templates = list() // List of ui templates the commcard can access
var/list/internal_data = list() // Data that shouldn't be updated every time nanoUI updates, or needs to persist between updates
/obj/item/weapon/commcard/proc/get_device_status()
var/list/L = list()
var/i = 1
for(var/obj/I in internal_devices)
if(I in active_devices)
L[++L.len] = list("name" = "\proper[I.name]", "active" = 1, "index" = i++)
else
L[++L.len] = list("name" = I.name, "active" = 0, "index" = i++)
return L
// cartridge.get_data() returns a list of tuples:
// The field element is the tag used to access the information by the template
// The value element is the actual data, and can take any form necessary for the template
/obj/item/weapon/commcard/proc/get_data()
return list()
// Handles cartridge-specific functions
// The helper.link() MUST HAVE 'cartridge_topic' passed into the href in order for cartridge functions to be processed.
// Doesn't matter what the value of it is for now, it's just a flag to say, "Hey, there's cartridge data to change!"
/obj/item/weapon/commcard/Topic(href, href_list)
// Signalers
if(href_list["signaler_target"])
var/obj/item/device/assembly/signaler/S = locate(href_list["signaler_target"]) // Should locate the correct signaler
if(!istype(S)) // Ref is no longer valid
return
if(S.loc != src) // No longer within the cartridge
return
switch(href_list["signaler_action"])
if("Pulse")
S.activate()
if("Edit")
var/mob/user = locate(href_list["user"])
if(!istype(user)) // Ref no longer valid
return
var/newVal = input(user, "Input a new [href_list["signaler_value"]].", href_list["signaler_value"], (href_list["signaler_value"] == "Code" ? S.code : S.frequency)) as num|null
if(newVal)
switch(href_list["signaler_value"])
if("Code")
S.code = newVal
if("Frequency")
S.frequency = newVal
// Refresh list of powernet sensors
if(href_list["powernet_refresh"])
internal_data["grid_sensors"] = find_powernet_sensors()
// Load apc's on targeted powernet
if(href_list["powernet_target"])
internal_data["powernet_target"] = href_list["powernet_target"]
// GPS units
if(href_list["gps_target"])
var/obj/item/device/gps/G = locate(href_list["gps_target"])
if(!istype(G)) // Ref is no longer valid
return
if(G.loc != src) // No longer within the cartridge
return
switch(href_list["gps_action"])
if("Power")
G.tracking = text2num(href_list["value"])
if("Long_Range")
G.local_mode = text2num(href_list["value"])
if("Hide_Signal")
G.hide_signal = text2num(href_list["value"])
if("Tag")
var/mob/user = locate(href_list["user"])
if(!istype(user)) // Ref no longer valid
return
var/newTag = input(user, "Please enter desired tag.", G.tag) as text|null
if(newTag)
G.tag = newTag
if(href_list["active_category"])
internal_data["supply_category"] = href_list["active_category"]
// Supply topic
// Copied from /obj/machinery/computer/supplycomp/Topic()
// code\game\machinery\computer\supply.dm, line 188
// Unfortunately, in order to support complete functionality, the whole thing is necessary
if(href_list["pack_ref"])
var/datum/supply_pack/S = locate(href_list["pack_ref"])
// Invalid ref
if(!istype(S))
return
// Expand the supply pack's contents
if(href_list["expand"])
internal_data["supply_pack_expanded"] ^= S
// Make a request for the pack
if(href_list["request"])
var/mob/user = locate(href_list["user"])
if(!istype(user)) // Invalid ref
return
if(world.time < internal_data["supply_reqtime"])
visible_message("<span class='warning'>[src] flashes, \"[internal_data["supply_reqtime"] - world.time] seconds remaining until another requisition form may be printed.\"</span>")
return
var/timeout = world.time + 600
var/reason = sanitize(input(user, "Reason:","Why do you require this item?","") as null|text)
if(world.time > timeout)
to_chat(user, "<span class='warning'>Error. Request timed out.</span>")
return
if(!reason)
return
SSsupply.create_order(S, user, reason)
internal_data["supply_reqtime"] = (world.time + 5) % 1e5
if(href_list["order_ref"])
var/datum/supply_order/O = locate(href_list["order_ref"])
// Invalid ref
if(!istype(O))
return
var/mob/user = locate(href_list["user"])
if(!istype(user)) // Invalid ref
return
if(href_list["edit"])
var/new_val = sanitize(input(user, href_list["edit"], "Enter the new value for this field:", href_list["default"]) as null|text)
if(!new_val)
return
switch(href_list["edit"])
if("Supply Pack")
O.name = new_val
if("Cost")
var/num = text2num(new_val)
if(num)
O.cost = num
if("Index")
var/num = text2num(new_val)
if(num)
O.index = num
if("Reason")
O.comment = new_val
if("Ordered by")
O.ordered_by = new_val
if("Ordered at")
O.ordered_at = new_val
if("Approved by")
O.approved_by = new_val
if("Approved at")
O.approved_at = new_val
if(href_list["approve"])
SSsupply.approve_order(O, user)
if(href_list["deny"])
SSsupply.deny_order(O, user)
if(href_list["delete"])
SSsupply.delete_order(O, user)
if(href_list["clear_all_requests"])
var/mob/user = locate(href_list["user"])
if(!istype(user)) // Invalid ref
return
SSsupply.deny_all_pending(user)
if(href_list["export_ref"])
var/datum/exported_crate/E = locate(href_list["export_ref"])
// Invalid ref
if(!istype(E))
return
var/mob/user = locate(href_list["user"])
if(!istype(user)) // Invalid ref
return
if(href_list["index"])
var/list/L = E.contents[href_list["index"]]
if(href_list["edit"])
var/field = alert(user, "Select which field to edit", , "Name", "Quantity", "Value")
var/new_val = sanitize(input(user, href_list["edit"], "Enter the new value for this field:", href_list["default"]) as null|text)
if(!new_val)
return
switch(field)
if("Name")
L["object"] = new_val
if("Quantity")
var/num = text2num(new_val)
if(num)
L["quantity"] = num
if("Value")
var/num = text2num(new_val)
if(num)
L["value"] = num
if(href_list["delete"])
E.contents.Cut(href_list["index"], href_list["index"] + 1)
// Else clause means they're editing/deleting the whole export report, rather than a specific item in it
else if(href_list["edit"])
var/new_val = sanitize(input(user, href_list["edit"], "Enter the new value for this field:", href_list["default"]) as null|text)
if(!new_val)
return
switch(href_list["edit"])
if("Name")
E.name = new_val
if("Value")
var/num = text2num(new_val)
if(num)
E.value = num
else if(href_list["delete"])
SSsupply.delete_export(E, user)
else if(href_list["add_item"])
SSsupply.add_export_item(E, user)
if(SSsupply && SSsupply.shuttle)
switch(href_list["send_shuttle"])
if("send_away")
if(SSsupply.shuttle.forbidden_atoms_check())
to_chat(usr, "<span class='warning'>For safety reasons the automated supply shuttle cannot transport live organisms, classified nuclear weaponry or homing beacons.</span>")
else
SSsupply.shuttle.launch(src)
to_chat(usr, "<span class='notice'>Initiating launch sequence.</span>")
if("send_to_station")
SSsupply.shuttle.launch(src)
to_chat(usr, "<span class='notice'>The supply shuttle has been called and will arrive in approximately [round(SSsupply.movetime/600,1)] minutes.</span>")
if("cancel_shuttle")
SSsupply.shuttle.cancel_launch(src)
if("force_shuttle")
SSsupply.shuttle.force_launch(src)
// Status display
switch(href_list["stat_display"])
if("message")
post_status("message", internal_data["stat_display_line1"], internal_data["stat_display_line2"])
internal_data["stat_display_special"] = "message"
if("alert")
post_status("alert", href_list["alert"])
internal_data["stat_display_special"] = href_list["alert"]
if("setmsg")
internal_data["stat_display_line[href_list["line"]]"] = reject_bad_text(sanitize(input("Line 1", "Enter Message Text", internal_data["stat_display_line[href_list["line"]]"]) as text|null, 40), 40)
else
post_status(href_list["stat_display"])
internal_data["stat_display_special"] = href_list["stat_display"]
// Merc shuttle blast door controls
switch(href_list["all_blast_doors"])
if("open")
for(var/obj/machinery/door/blast/B in internal_data["shuttle_doors"])
B.open()
if("close")
for(var/obj/machinery/door/blast/B in internal_data["shuttle_doors"])
B.close()
if(href_list["scan_blast_doors"])
internal_data["shuttle_doors"] = find_blast_doors()
if(href_list["toggle_blast_door"])
var/obj/machinery/door/blast/B = locate(href_list["toggle_blast_door"])
if(!B)
return
spawn(0)
if(B.density)
B.open()
else
B.close()
// Updates status displays with a new message
// Copied from /obj/item/weapon/cartridge/proc/post_status(),
// code/game/objects/items/devices/PDA/cart.dm, line 251
/obj/item/weapon/commcard/proc/post_status(var/command, var/data1, var/data2)
var/datum/radio_frequency/frequency = radio_controller.return_frequency(1435)
if(!frequency)
return
var/datum/signal/status_signal = new
status_signal.source = src
status_signal.transmission_method = TRANSMISSION_RADIO
status_signal.data["command"] = command
switch(command)
if("message")
status_signal.data["msg1"] = data1
status_signal.data["msg2"] = data2
internal_data["stat_display_active1"] = data1 // Update the internally stored message, we won't get receive_signal if we're the sender
internal_data["stat_display_active2"] = data2
if(loc)
var/obj/item/PDA = loc
var/mob/user = PDA.fingerprintslast
log_admin("STATUS: [user] set status screen with [src]. Message: [data1] [data2]")
message_admins("STATUS: [user] set status screen with [src]. Message: [data1] [data2]")
if("alert")
status_signal.data["picture_state"] = data1
frequency.post_signal(src, status_signal)
// Receives updates by external devices to the status displays
/obj/item/weapon/commcard/receive_signal(var/datum/signal/signal, var/receive_method, var/receive_param)
internal_data["stat_display_special"] = signal.data["command"]
switch(signal.data["command"])
if("message")
internal_data["stat_display_active1"] = signal.data["msg1"]
internal_data["stat_display_active2"] = signal.data["msg2"]
if("alert")
internal_data["stat_display_special"] = signal.data["picture_state"]
///////////////////////////
// SUBTYPES
///////////////////////////
// Engineering Cartridge:
// Devices
// *- Halogen Counter
// Templates
// *- Power Monitor
/obj/item/weapon/commcard/engineering
name = "\improper Power-ON cartridge"
icon_state = "cart-e"
ui_templates = list(list("name" = "Power Monitor", "template" = "comm_power_monitor.tmpl"))
/obj/item/weapon/commcard/engineering/New()
..()
internal_devices |= new /obj/item/device/halogen_counter(src)
/obj/item/weapon/commcard/engineering/Initialize()
internal_data["grid_sensors"] = find_powernet_sensors()
internal_data["powernet_target"] = ""
/obj/item/weapon/commcard/engineering/get_data()
return list(
list("field" = "powernet_monitoring", "value" = get_powernet_monitoring_list()),
list("field" = "powernet_target", "value" = get_powernet_target(internal_data["powernet_target"]))
)
// Atmospherics Cartridge:
// Devices
// *- Gas scanner
/obj/item/weapon/commcard/atmos
name = "\improper BreatheDeep cartridge"
icon_state = "cart-a"
/obj/item/weapon/commcard/atmos/New()
..()
internal_devices |= new /obj/item/device/analyzer(src)
// Medical Cartridge:
// Devices
// *- Halogen Counter
// *- Health Analyzer
// Templates
// *- Medical Records
/obj/item/weapon/commcard/medical
name = "\improper Med-U cartridge"
icon_state = "cart-m"
ui_templates = list(list("name" = "Medical Records", "template" = "med_records.tmpl"))
/obj/item/weapon/commcard/medical/New()
..()
internal_devices |= new /obj/item/device/healthanalyzer(src)
internal_devices |= new /obj/item/device/halogen_counter(src)
/obj/item/weapon/commcard/medical/get_data()
return list(list("field" = "med_records", "value" = get_med_records()))
// Chemistry Cartridge:
// Devices
// *- Halogen Counter
// *- Health Analyzer
// *- Reagent Scanner
// Templates
// *- Medical Records
/obj/item/weapon/commcard/medical/chemistry
name = "\improper ChemWhiz cartridge"
icon_state = "cart-chem"
/obj/item/weapon/commcard/medical/chemistry/New()
..()
internal_devices |= new /obj/item/device/reagent_scanner(src)
// Detective Cartridge:
// Devices
// *- Halogen Counter
// *- Health Analyzer
// Templates
// *- Medical Records
// *- Security Records
/obj/item/weapon/commcard/medical/detective
name = "\improper D.E.T.E.C.T. cartridge"
icon_state = "cart-s"
ui_templates = list(
list("name" = "Medical Records", "template" = "med_records.tmpl"),
list("name" = "Security Records", "template" = "sec_records.tmpl")
)
/obj/item/weapon/commcard/medical/detective/get_data()
var/list/data = ..()
data[++data.len] = list("field" = "sec_records", "value" = get_sec_records())
return data
// Internal Affairs Cartridge:
// Templates
// *- Security Records
// *- Employment Records
/obj/item/weapon/commcard/int_aff
name = "\improper P.R.O.V.E. cartridge"
icon_state = "cart-s"
ui_templates = list(
list("name" = "Employment Records", "template" = "emp_records.tmpl"),
list("name" = "Security Records", "template" = "sec_records.tmpl")
)
/obj/item/weapon/commcard/int_aff/get_data()
return list(
list("field" = "emp_records", "value" = get_emp_records()),
list("field" = "sec_records", "value" = get_sec_records())
)
// Security Cartridge:
// Templates
// *- Security Records
// *- Security Bot Access
/obj/item/weapon/commcard/security
name = "\improper R.O.B.U.S.T. cartridge"
icon_state = "cart-s"
ui_templates = list(
list("name" = "Security Records", "template" = "sec_records.tmpl"),
list("name" = "Security Bot Control", "template" = "sec_bot_access.tmpl")
)
/obj/item/weapon/commcard/security/get_data()
return list(
list("field" = "sec_records", "value" = get_sec_records()),
list("field" = "sec_bot_access", "value" = get_sec_bot_access())
)
// Janitor Cartridge:
// Templates
// *- Janitorial Locator Magicbox
/obj/item/weapon/commcard/janitor
name = "\improper CustodiPRO cartridge"
desc = "The ultimate in clean-room design."
ui_templates = list(
list("name" = "Janitorial Supply Locator", "template" = "janitorialLocator.tmpl")
)
/obj/item/weapon/commcard/janitor/get_data()
return list(
list("field" = "janidata", "value" = get_janitorial_locations())
)
// Signal Cartridge:
// Devices
// *- Signaler
// Templates
// *- Signaler Access
/obj/item/weapon/commcard/signal
name = "generic signaler cartridge"
desc = "A data cartridge with an integrated radio signaler module."
ui_templates = list(
list("name" = "Integrated Signaler Control", "template" = "signaler_access.tmpl")
)
/obj/item/weapon/commcard/signal/New()
..()
internal_devices |= new /obj/item/device/assembly/signaler(src)
/obj/item/weapon/commcard/signal/get_data()
return list(
list("field" = "signaler_access", "value" = get_int_signalers())
)
// Science Cartridge:
// Devices
// *- Signaler
// *- Reagent Scanner
// *- Gas Scanner
// Templates
// *- Signaler Access
/obj/item/weapon/commcard/signal/science
name = "\improper Signal Ace 2 cartridge"
desc = "Complete with integrated radio signaler!"
icon_state = "cart-tox"
// UI templates inherited
/obj/item/weapon/commcard/signal/science/New()
..()
internal_devices |= new /obj/item/device/reagent_scanner(src)
internal_devices |= new /obj/item/device/analyzer(src)
// Supply Cartridge:
// Templates
// *- Supply Records
/obj/item/weapon/commcard/supply
name = "\improper Space Parts & Space Vendors cartridge"
desc = "Perfect for the Quartermaster on the go!"
icon_state = "cart-q"
ui_templates = list(
list("name" = "Supply Records", "template" = "supply_records.tmpl")
)
/obj/item/weapon/commcard/supply/New()
..()
internal_data["supply_category"] = null
internal_data["supply_controls"] = FALSE // Cannot control the supply shuttle, cannot accept orders
internal_data["supply_pack_expanded"] = list()
internal_data["supply_reqtime"] = -1
/obj/item/weapon/commcard/supply/get_data()
// Supply records data
var/list/shuttle_status = get_supply_shuttle_status()
var/list/orders = get_supply_orders()
var/list/receipts = get_supply_receipts()
var/list/misc_supply_data = get_misc_supply_data() // Packaging this stuff externally so it's less hardcoded into the specific cartridge
var/list/pack_list = list() // List of supply packs within the currently selected category
if(internal_data["supply_category"])
pack_list = get_supply_pack_list()
return list(
list("field" = "shuttle_auth", "value" = misc_supply_data["shuttle_auth"]),
list("field" = "order_auth", "value" = misc_supply_data["order_auth"]),
list("field" = "supply_points", "value" = misc_supply_data["supply_points"]),
list("field" = "categories", "value" = misc_supply_data["supply_categories"]),
list("field" = "contraband", "value" = misc_supply_data["contraband"]),
list("field" = "active_category", "value" = internal_data["supply_category"]),
list("field" = "shuttle", "value" = shuttle_status),
list("field" = "orders", "value" = orders),
list("field" = "receipts", "value" = receipts),
list("field" = "supply_packs", "value" = pack_list)
)
// Command Cartridge:
// Templates
// *- Status Display Access
// *- Employment Records
/obj/item/weapon/commcard/head
name = "\improper Easy-Record DELUXE"
icon_state = "cart-h"
ui_templates = list(
list("name" = "Status Display Access", "template" = "stat_display_access.tmpl"),
list("name" = "Employment Records", "template" = "emp_records.tmpl")
)
/obj/item/weapon/commcard/head/New()
..()
internal_data["stat_display_line1"] = null
internal_data["stat_display_line2"] = null
internal_data["stat_display_active1"] = null
internal_data["stat_display_active2"] = null
internal_data["stat_display_special"] = null
/obj/item/weapon/commcard/head/Initialize()
// Have to register the commcard with the Radio controller to receive updates to the status displays
radio_controller.add_object(src, 1435)
..()
/obj/item/weapon/commcard/head/Destroy()
// Have to unregister the commcard for proper bookkeeping
radio_controller.remove_object(src, 1435)
..()
/obj/item/weapon/commcard/head/get_data()
return list(
list("field" = "emp_records", "value" = get_emp_records()),
list("field" = "stat_display", "value" = get_status_display())
)
// Head of Personnel Cartridge:
// Templates
// *- Status Display Access
// *- Employment Records
// *- Security Records
// *- Supply Records
// ?- Supply Bot Access
// *- Janitorial Locator Magicbox
/obj/item/weapon/commcard/head/hop
name = "\improper HumanResources9001 cartridge"
icon_state = "cart-h"
ui_templates = list(
list("name" = "Status Display Access", "template" = "stat_display_access.tmpl"),
list("name" = "Employment Records", "template" = "emp_records.tmpl"),
list("name" = "Security Records", "template" = "sec_records.tmpl"),
list("name" = "Supply Records", "template" = "supply_records.tmpl"),
list("name" = "Janitorial Supply Locator", "template" = "janitorialLocator.tmpl")
)
/obj/item/weapon/commcard/head/hop/get_data()
var/list/data = ..()
// Sec records
data[++data.len] = list("field" = "sec_records", "value" = get_sec_records())
// Supply records data
var/list/shuttle_status = get_supply_shuttle_status()
var/list/orders = get_supply_orders()
var/list/receipts = get_supply_receipts()
var/list/misc_supply_data = get_misc_supply_data() // Packaging this stuff externally so it's less hardcoded into the specific cartridge
var/list/pack_list = list() // List of supply packs within the currently selected category
if(internal_data["supply_category"])
pack_list = get_supply_pack_list()
data[++data.len] = list("field" = "shuttle_auth", "value" = misc_supply_data["shuttle_auth"])
data[++data.len] = list("field" = "order_auth", "value" = misc_supply_data["order_auth"])
data[++data.len] = list("field" = "supply_points", "value" = misc_supply_data["supply_points"])
data[++data.len] = list("field" = "categories", "value" = misc_supply_data["supply_categories"])
data[++data.len] = list("field" = "contraband", "value" = misc_supply_data["contraband"])
data[++data.len] = list("field" = "active_category", "value" = internal_data["supply_category"])
data[++data.len] = list("field" = "shuttle", "value" = shuttle_status)
data[++data.len] = list("field" = "orders", "value" = orders)
data[++data.len] = list("field" = "receipts", "value" = receipts)
data[++data.len] = list("field" = "supply_packs", "value" = pack_list)
// Janitorial locator magicbox
data[++data.len] = list("field" = "janidata", "value" = get_janitorial_locations())
return data
// Head of Security Cartridge:
// Templates
// *- Status Display Access
// *- Employment Records
// *- Security Records
// *- Security Bot Access
/obj/item/weapon/commcard/head/hos
name = "\improper R.O.B.U.S.T. DELUXE"
icon_state = "cart-hos"
ui_templates = list(
list("name" = "Status Display Access", "template" = "stat_display_access.tmpl"),
list("name" = "Employment Records", "template" = "emp_records.tmpl"),
list("name" = "Security Records", "template" = "sec_records.tmpl"),
list("name" = "Security Bot Control", "template" = "sec_bot_access.tmpl")
)
/obj/item/weapon/commcard/head/hos/get_data()
var/list/data = ..()
// Sec records
data[++data.len] = list("field" = "sec_records", "value" = get_sec_records())
// Sec bot access
data[++data.len] = list("field" = "sec_bot_access", "value" = get_sec_bot_access())
return data
// Research Director Cartridge:
// Devices
// *- Signaler
// *- Gas Scanner
// *- Reagent Scanner
// Templates
// *- Status Display Access
// *- Employment Records
// *- Signaler Access
/obj/item/weapon/commcard/head/rd
name = "\improper Signal Ace DELUXE"
icon_state = "cart-rd"
ui_templates = list(
list("name" = "Status Display Access", "template" = "stat_display_access.tmpl"),
list("name" = "Employment Records", "template" = "emp_records.tmpl"),
list("name" = "Integrated Signaler Control", "template" = "signaler_access.tmpl")
)
/obj/item/weapon/commcard/head/rd/New()
..()
internal_devices |= new /obj/item/device/analyzer(src)
internal_devices |= new /obj/item/device/reagent_scanner(src)
internal_devices |= new /obj/item/device/assembly/signaler(src)
/obj/item/weapon/commcard/head/rd/get_data()
var/list/data = ..()
// Signaler access
data[++data.len] = list("field" = "signaler_access", "value" = get_int_signalers())
return data
// Chief Medical Officer Cartridge:
// Devices
// *- Health Analyzer
// *- Reagent Scanner
// *- Halogen Counter
// Templates
// *- Status Display Access
// *- Employment Records
// *- Medical Records
/obj/item/weapon/commcard/head/cmo
name = "\improper Med-U DELUXE"
icon_state = "cart-cmo"
ui_templates = list(
list("name" = "Status Display Access", "template" = "stat_display_access.tmpl"),
list("name" = "Employment Records", "template" = "emp_records.tmpl"),
list("name" = "Medical Records", "template" = "med_records.tmpl")
)
/obj/item/weapon/commcard/head/cmo/New()
..()
internal_devices |= new /obj/item/device/healthanalyzer(src)
internal_devices |= new /obj/item/device/reagent_scanner(src)
internal_devices |= new /obj/item/device/halogen_counter(src)
/obj/item/weapon/commcard/head/cmo/get_data()
var/list/data = ..()
// Med records
data[++data.len] = list("field" = "med_records", "value" = get_med_records())
return data
// Chief Engineer Cartridge:
// Devices
// *- Gas Scanner
// *- Halogen Counter
// Templates
// *- Status Display Access
// *- Employment Records
// *- Power Monitoring
/obj/item/weapon/commcard/head/ce
name = "\improper Power-On DELUXE"
icon_state = "cart-ce"
ui_templates = list(
list("name" = "Status Display Access", "template" = "stat_display_access.tmpl"),
list("name" = "Employment Records", "template" = "emp_records.tmpl"),
list("name" = "Power Monitor", "template" = "comm_power_monitor.tmpl")
)
/obj/item/weapon/commcard/head/ce/New()
..()
internal_devices |= new /obj.item/device/analyzer(src)
internal_devices |= new /obj/item/device/halogen_counter(src)
/obj/item/weapon/commcard/head/ce/Initialize()
internal_data["grid_sensors"] = find_powernet_sensors()
internal_data["powernet_target"] = ""
/obj/item/weapon/commcard/head/ce/get_data()
var/list/data = ..()
// Add power monitoring data
data[++data.len] = list("field" = "powernet_monitoring", "value" = get_powernet_monitoring_list())
data[++data.len] = list("field" = "powernet_target", "value" = get_powernet_target(internal_data["powernet_target"]))
return data
// Captain Cartridge:
// Devices
// *- Health analyzer
// *- Gas Scanner
// *- Reagent Scanner
// *- Halogen Counter
// X- GPS - Balance
// *- Signaler
// Templates
// *- Status Display Access
// *- Employment Records
// *- Medical Records
// *- Security Records
// *- Power Monitoring
// *- Supply Records
// X- Supply Bot Access - Mulebots usually break when used
// *- Security Bot Access
// *- Janitorial Locator Magicbox
// X- GPS Access - Balance
// *- Signaler Access
/obj/item/weapon/commcard/head/captain
name = "\improper Value-PAK cartridge"
desc = "Now with 200% more value!"
icon_state = "cart-c"
ui_templates = list(
list("name" = "Status Display Access", "template" = "stat_display_access.tmpl"),
list("name" = "Employment Records", "template" = "emp_records.tmpl"),
list("name" = "Medical Records", "template" = "med_records.tmpl"),
list("name" = "Security Records", "template" = "sec_records.tmpl"),
list("name" = "Security Bot Control", "template" = "sec_bot_access.tmpl"),
list("name" = "Power Monitor", "template" = "comm_power_monitor.tmpl"),
list("name" = "Supply Records", "template" = "supply_records.tmpl"),
list("name" = "Janitorial Supply Locator", "template" = "janitorialLocator.tmpl"),
list("name" = "Integrated Signaler Control", "template" = "signaler_access.tmpl")
)
/obj/item/weapon/commcard/head/captain/New()
..()
internal_devices |= new /obj.item/device/analyzer(src)
internal_devices |= new /obj/item/device/healthanalyzer(src)
internal_devices |= new /obj/item/device/reagent_scanner(src)
internal_devices |= new /obj/item/device/halogen_counter(src)
internal_devices |= new /obj/item/device/assembly/signaler(src)
/obj/item/weapon/commcard/head/captain/get_data()
var/list/data = ..()
//Med records
data[++data.len] = list("field" = "med_records", "value" = get_med_records())
// Sec records
data[++data.len] = list("field" = "sec_records", "value" = get_sec_records())
// Sec bot access
data[++data.len] = list("field" = "sec_bot_access", "value" = get_sec_bot_access())
// Power Monitoring
data[++data.len] = list("field" = "powernet_monitoring", "value" = get_powernet_monitoring_list())
data[++data.len] = list("field" = "powernet_target", "value" = get_powernet_target(internal_data["powernet_target"]))
// Supply records data
var/list/shuttle_status = get_supply_shuttle_status()
var/list/orders = get_supply_orders()
var/list/receipts = get_supply_receipts()
var/list/misc_supply_data = get_misc_supply_data() // Packaging this stuff externally so it's less hardcoded into the specific cartridge
var/list/pack_list = list() // List of supply packs within the currently selected category
if(internal_data["supply_category"])
pack_list = get_supply_pack_list()
data[++data.len] = list("field" = "shuttle_auth", "value" = misc_supply_data["shuttle_auth"])
data[++data.len] = list("field" = "order_auth", "value" = misc_supply_data["order_auth"])
data[++data.len] = list("field" = "supply_points", "value" = misc_supply_data["supply_points"])
data[++data.len] = list("field" = "categories", "value" = misc_supply_data["supply_categories"])
data[++data.len] = list("field" = "contraband", "value" = misc_supply_data["contraband"])
data[++data.len] = list("field" = "active_category", "value" = internal_data["supply_category"])
data[++data.len] = list("field" = "shuttle", "value" = shuttle_status)
data[++data.len] = list("field" = "orders", "value" = orders)
data[++data.len] = list("field" = "receipts", "value" = receipts)
data[++data.len] = list("field" = "supply_packs", "value" = pack_list)
// Janitorial locator magicbox
data[++data.len] = list("field" = "janidata", "value" = get_janitorial_locations())
// Signaler access
data[++data.len] = list("field" = "signaler_access", "value" = get_int_signalers())
return data
// Mercenary Cartridge
// Templates
// *- Merc Shuttle Door Controller
/obj/item/weapon/commcard/mercenary
name = "\improper Detomatix cartridge"
icon_state = "cart"
ui_templates = list(
list("name" = "Shuttle Blast Door Control", "template" = "merc_blast_door_control.tmpl")
)
/obj/item/weapon/commcard/mercenary/Initialize()
internal_data["shuttle_door_code"] = "smindicate" // Copied from PDA code
internal_data["shuttle_doors"] = find_blast_doors()
/obj/item/weapon/commcard/mercenary/get_data()
var/door_status[0]
for(var/obj/machinery/door/blast/B in internal_data["shuttle_doors"])
door_status[++door_status.len] += list(
"open" = B.density,
"name" = B.name,
"ref" = "\ref[B]"
)
return list(
list("field" = "blast_door", "value" = door_status)
)
// Explorer Cartridge
// Devices
// *- GPS
// Templates
// *- GPS Access
// IMPORTANT: NOT MAPPED IN DUE TO BALANCE CONCERNS RE: FINDING THE VICTIMS OF ANTAGS.
// See suit sensors, specifically ease of turning them off, and variable level of settings which may or may not give location
// A GPS in your phone that is either broadcasting position or totally off, and can be hidden in pockets, coats, bags, boxes, etc, is much harder to disable
/obj/item/weapon/commcard/explorer
name = "\improper Explorator cartridge"
icon_state = "cart-tox"
ui_templates = list(
list("name" = "Integrated GPS", "template" = "gps_access.tmpl")
)
/obj/item/weapon/commcard/explorer/New()
..()
internal_devices |= new /obj/item/device/gps/explorer(src)
/obj/item/weapon/commcard/explorer/get_data()
var/list/GPS = get_GPS_lists()
return list(
list("field" = "gps_access", "value" = GPS[1]),
list("field" = "gps_signal", "value" = GPS[2]),
list("field" = "gps_status", "value" = GPS[3])
)
@@ -14,7 +14,6 @@ var/global/list/obj/item/device/communicator/all_communicators = list()
#define WTHRTAB 7
#define MANITAB 8
#define SETTTAB 9
#define EXTRTAB 10
/obj/item/device/communicator
name = "communicator"
@@ -43,19 +42,18 @@ var/global/list/obj/item/device/communicator/all_communicators = list()
var/note = "Thank you for choosing the T-14.2 Communicator, this is your notepad!" //Current note in the notepad function
var/notehtml = ""
var/obj/item/weapon/commcard/cartridge = null //current cartridge
var/fon = 0 // Internal light
var/flum = 2 // Brightness
var/list/modules = list(
list("module" = "Phone", "icon" = "phone64", "number" = PHONTAB),
list("module" = "Contacts", "icon" = "person64", "number" = CONTTAB),
list("module" = "Messaging", "icon" = "comment64", "number" = MESSTAB),
list("module" = "News", "icon" = "note64", "number" = NEWSTAB), // Need a different icon,
list("module" = "Note", "icon" = "note64", "number" = NOTETAB),
list("module" = "Weather", "icon" = "sun64", "number" = WTHRTAB),
list("module" = "Crew Manifest", "icon" = "note64", "number" = MANITAB), // Need a different icon,
list("module" = "Settings", "icon" = "gear64", "number" = SETTTAB),
list("module" = "Phone", "icon" = "phone", "number" = PHONTAB),
list("module" = "Contacts", "icon" = "user", "number" = CONTTAB),
list("module" = "Messaging", "icon" = "comment-alt", "number" = MESSTAB),
list("module" = "News", "icon" = "newspaper", "number" = NEWSTAB), // Need a different icon,
list("module" = "Note", "icon" = "sticky-note", "number" = NOTETAB),
list("module" = "Weather", "icon" = "sun", "number" = WTHRTAB),
list("module" = "Crew Manifest", "icon" = "crown", "number" = MANITAB), // Need a different icon,
list("module" = "Settings", "icon" = "cog", "number" = SETTTAB),
) //list("module" = "Name of Module", "icon" = "icon name64", "number" = "what tab is the module")
var/selected_tab = HOMETAB
@@ -104,13 +102,6 @@ var/global/list/obj/item/device/communicator/all_communicators = list()
register_device(S.loc.name)
initialize_exonet(S.loc)
// Proc: examine()
// Parameters: user - the user doing the examining
// Description: Allows the user to click a link when examining to look at video if one is going.
/obj/item/device/communicator/examine(mob/user)
. = ..()
if(Adjacent(user) && video_source)
. += "<span class='notice'>It looks like it's on a video call: <a href='?src=\ref[src];watchvideo=1'>\[view\]</a></span>"
// Proc: initialize_exonet()
// Parameters: 1 (user - the person the communicator belongs to)
@@ -132,6 +123,9 @@ var/global/list/obj/item/device/communicator/all_communicators = list()
// Description: Shows all the voice mobs inside the device, and their status.
/obj/item/device/communicator/examine(mob/user)
. = ..()
if(Adjacent(user) && video_source)
. += "<span class='notice'>It looks like it's on a video call: <a href='?src=\ref[src];watchvideo=1'>\[view\]</a></span>"
for(var/mob/living/voice/voice in contents)
. += "<span class='notice'>On the screen, you can see a image feed of [voice].</span>"
@@ -148,6 +142,17 @@ var/global/list/obj/item/device/communicator/all_communicators = list()
else
. += "<span class='notice'>The device doesn't appear to be transmitting any data.</span>"
// Proc: Topic()
// Parameters: href, href_list - Data from a link
// Description: Used by the above examine.
/obj/item/device/communicator/Topic(href, href_list)
if(..())
return 1
if(href_list["watchvideo"])
if(video_source)
watch_video(usr)
// Proc: emp_act()
// Parameters: None
// Description: Drops all calls when EMPed, so the holder can then get murdered by the antagonist.
@@ -203,17 +208,6 @@ var/global/list/obj/item/device/communicator/all_communicators = list()
if(!get_connection_to_tcomms())
close_connection(reason = "Connection timed out")
// Proc: attack()
// Parameters: 2 (M - what is being attacked. user - the mob that has the communicator)
// Description: When the communicator has an attached commcard with internal devices, relay the attack() through to those devices.
// Contents of the for loop are copied from gripper code, because that does approximately what we want to do.
/obj/item/device/communicator/attack(mob/living/carbon/M as mob, mob/living/carbon/user as mob)
if(cartridge && cartridge.active_devices)
for(var/obj/item/wrapped in cartridge.active_devices)
if(wrapped) //The force of the wrapped obj gets set to zero during the attack() and afterattack().
wrapped.attack(M,user)
return 0
// Proc: attackby()
// Parameters: 2 (C - what is used on the communicator. user - the mob that has the communicator)
// Description: When an ID is swiped on the communicator, the communicator reads the job and checks it against the Owner name, if success, the occupation is added.
@@ -229,13 +223,6 @@ var/global/list/obj/item/device/communicator/all_communicators = list()
occupation = idcard.assignment
to_chat(user, "<span class='notice'>Occupation updated.</span>")
if(istype(C, /obj/item/weapon/commcard) && !cartridge)
cartridge = C
user.drop_item()
cartridge.forceMove(src)
to_chat(usr, "<span class='notice'>You slot \the [cartridge] into \the [src].</span>")
modules[++modules.len] = list("module" = "External Device", "icon" = "external64", "number" = EXTRTAB)
SSnanoui.update_uis(src) // update all UIs attached to src
return
// Proc: attack_self()
@@ -246,7 +233,7 @@ var/global/list/obj/item/device/communicator/all_communicators = list()
initialize_exonet(user)
alert_called = 0
update_icon()
ui_interact(user)
tgui_interact(user)
if(video_source)
watch_video(user)
@@ -358,38 +345,6 @@ var/global/list/obj/item/device/communicator/all_communicators = list()
client_huds |= global_hud.whitense
client_huds |= global_hud.darkMask
/obj/item/device/communicator/verb/verb_remove_cartridge()
set category = "Object"
set name = "Remove commcard"
set src in usr
// Can't remove what isn't there
if(!cartridge)
to_chat(usr, "<span class='notice'>There isn't a commcard to remove!</span>")
return
// Can't remove if you're physically unable to
if(usr.stat || usr.restrained() || usr.paralysis || usr.stunned || usr.weakened)
to_chat(usr, "<span class='notice'>You cannot do this while restrained.</span>")
return
var/turf/T = get_turf(src)
cartridge.loc = T
// If it's in someone, put the cartridge in their hands
if (ismob(loc))
var/mob/M = loc
M.put_in_hands(cartridge)
// Else just set it on the ground
else
cartridge.loc = get_turf(src)
cartridge = null
// We have to iterate through the modules to find EXTRTAB, because list procs don't play nice with a list of lists
for(var/i = 1, i <= modules.len, i++)
if(modules[i]["number"] == EXTRTAB)
modules.Cut(i, i+1)
break
to_chat(usr, "<span class='notice'>You remove \the [cartridge] from the [name].</span>")
//It's the 26th century. We should have smart watches by now.
/obj/item/device/communicator/watch
name = "communicator watch"
@@ -20,7 +20,7 @@
// Values were extracted from the template itself
results = list(
list("entry" = "Pressure", "units" = "kPa", "val" = "[round(pressure,0.1)]", "bad_high" = 120, "poor_high" = 110, "poor_low" = 95, "bad_low" = 80),
list("entry" = "Temperature", "units" = "&degC", "val" = "[round(environment.temperature-T0C,0.1)]", "bad_high" = 35, "poor_high" = 25, "poor_low" = 15, "bad_low" = 5),
list("entry" = "Temperature", "units" = "&deg;C", "val" = "[round(environment.temperature-T0C,0.1)]", "bad_high" = 35, "poor_high" = 25, "poor_low" = 15, "bad_low" = 5),
list("entry" = "Oxygen", "units" = "kPa", "val" = "[round(o2_level*100,0.1)]", "bad_high" = 140, "poor_high" = 135, "poor_low" = 19, "bad_low" = 17),
list("entry" = "Nitrogen", "units" = "kPa", "val" = "[round(n2_level*100,0.1)]", "bad_high" = 105, "poor_high" = 85, "poor_low" = 50, "bad_low" = 40),
list("entry" = "Carbon Dioxide", "units" = "kPa", "val" = "[round(co2_level*100,0.1)]", "bad_high" = 10, "poor_high" = 5, "poor_low" = 0, "bad_low" = 0),
@@ -44,19 +44,18 @@
var/index = 0
for(var/datum/feed_message/FM in channel.messages)
index++
var/list/msgdata = list(
"author" = FM.author,
"body" = FM.body,
"img" = null,
"message_type" = FM.message_type,
"time_stamp" = FM.time_stamp,
"caption" = FM.caption,
"index" = index
)
if(FM.img)
usr << browse_rsc(FM.img, "pda_news_tmp_photo_[feeds["channel"]]_[index].png")
// News stories are HTML-stripped but require newline replacement to be properly displayed in NanoUI
var/body = replacetext(FM.body, "\n", "<br>")
messages[++messages.len] = list(
"author" = FM.author,
"body" = body,
"message_type" = FM.message_type,
"time_stamp" = FM.time_stamp,
"has_image" = (FM.img != null),
"caption" = FM.caption,
"index" = index
)
msgdata["img"] = icon2base64(FM.img)
messages[++messages.len] = msgdata
feeds[++feeds.len] = list(
"name" = channel.channel_name,
@@ -96,448 +95,3 @@
news.Swap(1, 3) // List is sorted in ascending order of timestamp, we want descending
return news
// Putting the commcard data harvesting helpers here
// Not ideal to put all the procs on the base type
// but it may open options for adminbus,
// And it saves duplicated code
// Medical records
/obj/item/weapon/commcard/proc/get_med_records()
var/med_records[0]
for(var/datum/data/record/M in sortRecord(data_core.medical))
var/record[0]
record[++record.len] = list("tab" = "Name", "val" = M.fields["name"])
record[++record.len] = list("tab" = "ID", "val" = M.fields["id"])
record[++record.len] = list("tab" = "Blood Type", "val" = M.fields["b_type"])
record[++record.len] = list("tab" = "DNA #", "val" = M.fields["b_dna"])
record[++record.len] = list("tab" = "Gender", "val" = M.fields["id_gender"])
record[++record.len] = list("tab" = "Entity Classification", "val" = M.fields["brain_type"])
record[++record.len] = list("tab" = "Minor Disorders", "val" = M.fields["mi_dis"])
record[++record.len] = list("tab" = "Major Disorders", "val" = M.fields["ma_dis"])
record[++record.len] = list("tab" = "Allergies", "val" = M.fields["alg"])
record[++record.len] = list("tab" = "Condition", "val" = M.fields["cdi"])
record[++record.len] = list("tab" = "Notes", "val" = M.fields["notes"])
med_records[++med_records.len] = list("name" = M.fields["name"], "record" = record)
return med_records
// Employment records
/obj/item/weapon/commcard/proc/get_emp_records()
var/emp_records[0]
for(var/datum/data/record/G in sortRecord(data_core.general))
var/record[0]
record[++record.len] = list("tab" = "Name", "val" = G.fields["name"])
record[++record.len] = list("tab" = "ID", "val" = G.fields["id"])
record[++record.len] = list("tab" = "Rank", "val" = G.fields["rank"])
record[++record.len] = list("tab" = "Fingerprint", "val" = G.fields["fingerprint"])
record[++record.len] = list("tab" = "Entity Classification", "val" = G.fields["brain_type"])
record[++record.len] = list("tab" = "Sex", "val" = G.fields["sex"])
record[++record.len] = list("tab" = "Species", "val" = G.fields["species"])
record[++record.len] = list("tab" = "Age", "val" = G.fields["age"])
record[++record.len] = list("tab" = "Notes", "val" = G.fields["notes"])
emp_records[++emp_records.len] = list("name" = G.fields["name"], "record" = record)
return emp_records
// Security records
/obj/item/weapon/commcard/proc/get_sec_records()
var/sec_records[0]
for(var/datum/data/record/G in sortRecord(data_core.general))
var/record[0]
record[++record.len] = list("tab" = "Name", "val" = G.fields[""])
record[++record.len] = list("tab" = "Sex", "val" = G.fields[""])
record[++record.len] = list("tab" = "Species", "val" = G.fields[""])
record[++record.len] = list("tab" = "Age", "val" = G.fields[""])
record[++record.len] = list("tab" = "Rank", "val" = G.fields[""])
record[++record.len] = list("tab" = "Fingerprint", "val" = G.fields[""])
record[++record.len] = list("tab" = "Physical Status", "val" = G.fields[""])
record[++record.len] = list("tab" = "Mental Status", "val" = G.fields[""])
record[++record.len] = list("tab" = "Criminal Status", "val" = G.fields[""])
record[++record.len] = list("tab" = "Major Crimes", "val" = G.fields[""])
record[++record.len] = list("tab" = "Minor Crimes", "val" = G.fields[""])
record[++record.len] = list("tab" = "Notes", "val" = G.fields["notes"])
sec_records[++sec_records.len] = list("name" = G.fields["name"], "record" = record)
return sec_records
// Status of all secbots
// Weaker than what PDAs appear to do, but as of 7/1/2018 PDA secbot access is nonfunctional
/obj/item/weapon/commcard/proc/get_sec_bot_access()
var/sec_bots[0]
for(var/mob/living/bot/secbot/S in mob_list)
// Get new bot
var/status[0]
status[++status.len] = list("tab" = "Name", "val" = sanitize(S.name))
// If it's turned off, then it shouldn't be broadcasting any further info
if(!S.on)
status[++status.len] = list("tab" = "Power", "val" = "<span class='bad'>Off</span>") // Encoding the span classes here so I don't have to do complicated switches in the ui template
continue
status[++status.len] = list("tab" = "Power", "val" = "<span class='good'>On</span>")
// -- What it's doing
// If it's engaged, then say who it thinks it's engaging
if(S.target)
status[++status.len] = list("tab" = "Status", "val" = "<span class='bad'>Apprehending Target</span>")
status[++status.len] = list("tab" = "Target", "val" = S.target_name(S.target))
// Else if it's patrolling
else if(S.will_patrol)
status[++status.len] = list("tab" = "Status", "val" = "<span class='good'>Patrolling</span>")
// Otherwise we don't know what it's doing
else
status[++status.len] = list("tab" = "Status", "val" = "<span class='average'>Idle</span>")
// Where it is
status[++status.len] = list("tab" = "Location", "val" = sanitize("[get_area(S.loc)]"))
// Append bot to the list
sec_bots[++sec_bots.len] = list("bot" = S.name, "status" = status)
return sec_bots
// Code and frequency of stored signalers
// Supports multiple signalers within the device
/obj/item/weapon/commcard/proc/get_int_signalers()
var/signalers[0]
for(var/obj/item/device/assembly/signaler/S in internal_devices)
var/unit[0]
unit[++unit.len] = list("tab" = "Code", "val" = S.code)
unit[++unit.len] = list("tab" = "Frequency", "val" = S.frequency)
signalers[++signalers.len] = list("ref" = "\ref[S]", "status" = unit)
return signalers
// Returns list of all powernet sensors currently visible to the commcard
/obj/item/weapon/commcard/proc/find_powernet_sensors()
var/grid_sensors[0]
// Find all the powernet sensors we need to pull data from
// Copied from /datum/nano_module/power_monitor/proc/refresh_sensors(),
// located in '/code/modules/nano/modules/power_monitor.dm'
// Minor tweaks for efficiency and cleanliness
var/turf/T = get_turf(src)
if(T)
var/list/levels = using_map.get_map_levels(T.z, FALSE)
for(var/obj/machinery/power/sensor/S in machines)
if((S.long_range) || (S.loc.z in levels) || (S.loc.z == T.z)) // Consoles have range on their Z-Level. Sensors with long_range var will work between Z levels.
if(S.name_tag == "#UNKN#") // Default name. Shouldn't happen!
warning("Powernet sensor with unset ID Tag! [S.x]X [S.y]Y [S.z]Z")
else
grid_sensors += S
return grid_sensors
// List of powernets
/obj/item/weapon/commcard/proc/get_powernet_monitoring_list()
// Fetch power monitor data
var/sensors[0]
for(var/obj/machinery/power/sensor/S in internal_data["grid_sensors"])
var/list/focus = S.return_reading_data()
sensors[++sensors.len] = list(
"name" = S.name_tag,
"alarm" = focus["alarm"]
)
return sensors
// Information about the targeted powernet
/obj/item/weapon/commcard/proc/get_powernet_target(var/target_sensor)
if(!target_sensor)
return
var/powernet_target[0]
for(var/obj/machinery/power/sensor/S in internal_data["grid_sensors"])
var/list/focus = S.return_reading_data()
// Packages the span class here so it doesn't need to be interpreted w/in the for loop in the ui template
var/load_stat = "<span class='good'>Optimal</span>"
if(focus["load_percentage"] >= 95)
load_stat = "<span class='bad'>DANGER: Overload</span>"
else if(focus["load_percentage"] >= 85)
load_stat = "<span class='average'>WARNING: High Load</span>"
var/alarm_stat = focus["alarm"] ? "<span class='bad'>WARNING: Abnormal activity detected!</span>" : "<span class='good'>Secure</span>"
if(target_sensor == S.name_tag)
powernet_target = list(
"name" = S.name_tag,
"alarm" = focus["alarm"],
"error" = focus["error"],
"apc_data" = focus["apc_data"],
"status" = list(
list("field" = "Network Load Status", "statval" = load_stat),
list("field" = "Network Security Status", "statval" = alarm_stat),
list("field" = "Load Percentage", "statval" = focus["load_percentage"]),
list("field" = "Available Power", "statval" = focus["total_avail"]),
list("field" = "APC Power Usage", "statval" = focus["total_used_apc"]),
list("field" = "Other Power Usage", "statval" = focus["total_used_other"]),
list("field" = "Total Usage", "statval" = focus["total_used_all"])
)
)
return powernet_target
// Compiles the locations of all janitorial paraphernalia, as used by janitorialLocator.tmpl
/obj/item/weapon/commcard/proc/get_janitorial_locations()
// Fetch janitorial locator
var/janidata[0]
var/list/cleaningList = list()
cleaningList += all_mops + all_mopbuckets + all_janitorial_carts
// User's location
var/turf/userloc = get_turf(src)
if(isturf(userloc))
janidata[++janidata.len] = list("field" = "Current Location", "val" = "<span class='good'>[userloc.x], [userloc.y], [using_map.get_zlevel_name(userloc.z)]</span>")
else
janidata[++janidata.len] = list("field" = "Current Location", "val" = "<span class='bad'>Unknown</span>")
return janidata // If the user isn't on a valid turf, then it shouldn't be able to find anything anyways
// Mops, mop buckets, janitorial carts.
for(var/obj/C in cleaningList)
var/turf/T = get_turf(C)
if(isturf(T) )//&& T.z in using_map.get_map_levels(userloc, FALSE))
if(T.z == userloc.z)
janidata[++janidata.len] = list("field" = apply_text_macros("\proper [C.name]"), "val" = "<span class='good'>[T.x], [T.y], [using_map.get_zlevel_name(T.z)]</span>")
else
janidata[++janidata.len] = list("field" = apply_text_macros("\proper [C.name]"), "val" = "<span class='average'>[T.x], [T.y], [using_map.get_zlevel_name(T.z)]</span>")
// Cleanbots
for(var/mob/living/bot/cleanbot/B in living_mob_list)
var/turf/T = get_turf(B)
if(isturf(T) )//&& T.z in using_map.get_map_levels(userloc, FALSE))
var/textout = ""
if(B.on)
textout += "Status: <span class='good'>Online</span><br>"
if(T.z == userloc.z)
textout += "<span class='good'>[T.x], [T.y], [using_map.get_zlevel_name(T.z)]</span>"
else
textout += "<span class='average'>[T.x], [T.y], [using_map.get_zlevel_name(T.z)]</span>"
else
textout += "Status: <span class='bad'>Offline</span>"
janidata[++janidata.len] = list("field" = "[B.name]", "val" = textout)
return janidata
// Compiles the three lists used by GPS_access.tmpl
// The contents of the three lists are inherently related, so separating them into different procs would be largely redundant
/obj/item/weapon/commcard/proc/get_GPS_lists()
// GPS Access
var/intgps[0] // Gps devices within the commcard -- Allow tag edits, turning on/off, etc
var/extgps[0] // Gps devices not inside the commcard -- Print locations if a gps is on
var/stagps[0] // Gps net status, location, whether it's on, if it's got long range
var/obj/item/device/gps/cumulative = new(src)
cumulative.tracking = FALSE
cumulative.local_mode = TRUE // Won't detect long-range signals automatically
cumulative.long_range = FALSE
var/list/toggled_gps = list() // List of GPS units that are turned off before display_list() is called
for(var/obj/item/device/gps/G in internal_devices)
var/gpsdata[0]
if(G.tracking && !G.emped)
cumulative.tracking = TRUE // Turn it on
if(G.long_range)
cumulative.long_range = TRUE // It can detect long-range
if(!G.local_mode)
cumulative.local_mode = FALSE // It is detecting long-range
gpsdata["ref"] = "\ref[G]"
gpsdata["tag"] = G.gps_tag
gpsdata["power"] = G.tracking
gpsdata["local_mode"] = G.local_mode
gpsdata["long_range"] = G.long_range
gpsdata["hide_signal"] = G.hide_signal
gpsdata["can_hide"] = G.can_hide_signal
intgps[++intgps.len] = gpsdata // Add it to the list
if(G.tracking)
G.tracking = FALSE // Disable the internal gps units so they don't show up in the report
toggled_gps += G
var/list/remote_gps = cumulative.display_list() // Fetch information for all units except the ones inside of this device
for(var/obj/item/device/gps/G in toggled_gps) // Reenable any internal GPS units
G.tracking = TRUE
stagps["enabled"] = cumulative.tracking
stagps["long_range_en"] = (cumulative.long_range && !cumulative.local_mode)
stagps["my_area_name"] = remote_gps["my_area_name"]
stagps["curr_x"] = remote_gps["curr_x"]
stagps["curr_y"] = remote_gps["curr_y"]
stagps["curr_z"] = remote_gps["curr_z"]
stagps["curr_z_name"] = remote_gps["curr_z_name"]
extgps = remote_gps["gps_list"] // Compiled by the GPS
qdel(cumulative) // Don't want spare GPS units building up in the contents
return list(
intgps,
extgps,
stagps
)
// Collects the current status of the supply shuttle
// Copied from /obj/machinery/computer/supplycomp/ui_interact(),
// code\game\machinery\computer\supply.dm, starting at line 55
/obj/item/weapon/commcard/proc/get_supply_shuttle_status()
var/shuttle_status[0]
var/datum/shuttle/autodock/ferry/supply/shuttle = SSsupply.shuttle
if(shuttle)
if(shuttle.has_arrive_time())
shuttle_status["location"] = "In transit"
shuttle_status["mode"] = SUP_SHUTTLE_TRANSIT
shuttle_status["time"] = shuttle.eta_minutes()
else
shuttle_status["time"] = 0
if(shuttle.at_station())
if(shuttle.shuttle_docking_controller)
switch(shuttle.shuttle_docking_controller.get_docking_status())
if("docked")
shuttle_status["location"] = "Docked"
shuttle_status["mode"] = SUP_SHUTTLE_DOCKED
if("undocked")
shuttle_status["location"] = "Undocked"
shuttle_status["mode"] = SUP_SHUTTLE_UNDOCKED
if("docking")
shuttle_status["location"] = "Docking"
shuttle_status["mode"] = SUP_SHUTTLE_DOCKING
shuttle_status["force"] = shuttle.can_force()
if("undocking")
shuttle_status["location"] = "Undocking"
shuttle_status["mode"] = SUP_SHUTTLE_UNDOCKING
shuttle_status["force"] = shuttle.can_force()
else
shuttle_status["location"] = "Station"
shuttle_status["mode"] = SUP_SHUTTLE_DOCKED
else
shuttle_status["location"] = "Away"
shuttle_status["mode"] = SUP_SHUTTLE_AWAY
if(shuttle.can_launch())
shuttle_status["launch"] = 1
else if(shuttle.can_cancel())
shuttle_status["launch"] = 2
else
shuttle_status["launch"] = 0
switch(shuttle.moving_status)
if(SHUTTLE_IDLE)
shuttle_status["engine"] = "Idle"
if(SHUTTLE_WARMUP)
shuttle_status["engine"] = "Warming up"
if(SHUTTLE_INTRANSIT)
shuttle_status["engine"] = "Engaged"
else
shuttle["mode"] = SUP_SHUTTLE_ERROR
return shuttle_status
// Compiles the list of supply orders
// Copied from /obj/machinery/computer/supplycomp/ui_interact(),
// code\game\machinery\computer\supply.dm, starting at line 130
/obj/item/weapon/commcard/proc/get_supply_orders()
var/orders[0]
for(var/datum/supply_order/S in SSsupply.order_history)
orders[++orders.len] = list(
"ref" = "\ref[S]",
"status" = S.status,
"entries" = list(
list("field" = "Supply Pack", "entry" = S.name),
list("field" = "Cost", "entry" = S.cost),
list("field" = "Index", "entry" = S.index),
list("field" = "Reason", "entry" = S.comment),
list("field" = "Ordered by", "entry" = S.ordered_by),
list("field" = "Ordered at", "entry" = S.ordered_at),
list("field" = "Approved by", "entry" = S.approved_by),
list("field" = "Approved at", "entry" = S.approved_at)
)
)
return orders
// Compiles the list of supply export receipts
// Copied from /obj/machinery/computer/supplycomp/ui_interact(),
// code\game\machinery\computer\supply.dm, starting at line 147
/obj/item/weapon/commcard/proc/get_supply_receipts()
var/receipts[0]
for(var/datum/exported_crate/E in SSsupply.exported_crates)
receipts[++receipts.len] = list(
"ref" = "\ref[E]",
"contents" = E.contents,
"error" = E.contents["error"],
"title" = list(
list("field" = "Name", "entry" = E.name),
list("field" = "Value", "entry" = E.value)
)
)
return receipts
// Compiles the list of supply packs for the category currently stored in internal_data["supply_category"]
// Copied from /obj/machinery/computer/supplycomp/ui_interact(),
// code\game\machinery\computer\supply.dm, starting at line 147
/obj/item/weapon/commcard/proc/get_supply_pack_list()
var/supply_packs[0]
for(var/pack_name in SSsupply.supply_pack)
var/datum/supply_pack/P = SSsupply.supply_pack[pack_name]
if(P.group == internal_data["supply_category"])
var/list/pack = list(
"name" = P.name,
"cost" = P.cost,
"contraband" = P.contraband,
"manifest" = uniquelist(P.manifest),
"random" = P.num_contained,
"expand" = 0,
"ref" = "\ref[P]"
)
if(P in internal_data["supply_pack_expanded"])
pack["expand"] = 1
supply_packs[++supply_packs.len] = pack
return supply_packs
// Compiles miscellaneous data and permissions used by the supply template
/obj/item/weapon/commcard/proc/get_misc_supply_data()
return list(
"shuttle_auth" = (internal_data["supply_controls"] & SUP_SEND_SHUTTLE),
"order_auth" = (internal_data["supply_controls"] & SUP_ACCEPT_ORDERS),
"supply_points" = SSsupply.points,
"supply_categories" = all_supply_groups
)
/obj/item/weapon/commcard/proc/get_status_display()
return list(
"line1" = internal_data["stat_display_line1"],
"line2" = internal_data["stat_display_line2"],
"active_line1" = internal_data["stat_display_active1"],
"active_line2" = internal_data["stat_display_active2"],
"active" = internal_data["stat_display_special"]
)
/obj/item/weapon/commcard/proc/find_blast_doors()
var/target_doors[0]
for(var/obj/machinery/door/blast/B in machines)
if(B.id == internal_data["shuttle_door_code"])
target_doors += B
return target_doors
+8 -7
View File
@@ -5,7 +5,7 @@
var/in_hack_mode = 0
var/list/known_targets
var/list/supported_types
var/datum/topic_state/default/must_hack/hack_state
var/datum/tgui_state/default/must_hack/hack_state
/obj/item/device/multitool/hacktool/New()
..()
@@ -30,7 +30,7 @@
else
..()
/obj/item/device/multitool/hacktool/resolve_attackby(atom/A, mob/user)
/obj/item/device/multitool/hacktool/afterattack(atom/A, mob/user)
sanity_check()
if(!in_hack_mode)
@@ -39,7 +39,8 @@
if(!attempt_hack(user, A))
return 0
A.ui_interact(user, state = hack_state)
// Note, if you ever want to expand supported_types, you must manually add the custom state argument to their tgui_interact
A.tgui_interact(user, custom_state = hack_state)
return 1
/obj/item/device/multitool/hacktool/proc/attempt_hack(var/mob/user, var/atom/target)
@@ -83,18 +84,18 @@
/obj/item/device/multitool/hacktool/proc/on_target_destroy(var/target)
known_targets -= target
/datum/topic_state/default/must_hack
/datum/tgui_state/default/must_hack
var/obj/item/device/multitool/hacktool/hacktool
/datum/topic_state/default/must_hack/New(var/hacktool)
/datum/tgui_state/default/must_hack/New(var/hacktool)
src.hacktool = hacktool
..()
/datum/topic_state/default/must_hack/Destroy()
/datum/tgui_state/default/must_hack/Destroy()
hacktool = null
return ..()
/datum/topic_state/default/must_hack/can_use_topic(var/src_object, var/mob/user)
/datum/tgui_state/default/must_hack/can_use_topic(src_object, mob/user)
if(!hacktool || !hacktool.in_hack_mode || !(src_object in hacktool.known_targets))
return STATUS_CLOSE
return ..()
@@ -33,6 +33,24 @@ GLOBAL_LIST_BOILERPLATE(all_pai_cards, /obj/item/device/paicard)
QDEL_NULL(radio)
return ..()
/obj/item/device/paicard/attack_ghost(mob/observer/dead/user)
if(istype(user) && user.can_admin_interact())
switch(alert(user, "Would you like to become a pAI by force? (Admin)", "pAI Creation", "Yes", "No"))
if("Yes")
// Copied from paiController/Topic
var/mob/living/silicon/pai/pai = new(src)
pai.name = user.name
pai.real_name = pai.name
pai.key = user.key
setPersonality(pai)
looking_for_personality = FALSE
if(pai.mind)
update_antag_icons(pai.mind)
return ..()
/obj/item/device/paicard/attack_self(mob/user)
if (!in_range(src, user))
return
+2 -10
View File
@@ -151,18 +151,10 @@ var/global/list/default_medbay_channels = list(
return tgui_interact(user)
/obj/item/device/radio/ui_interact(mob/user, ui_key, datum/nanoui/ui, force_open, datum/nano_ui/master_ui, datum/topic_state/state)
log_runtime(EXCEPTION("Warning: [user] attempted to call ui_interact on radio [src] [type]. This is deprecated. Please update the caller to tgui_interact."))
/obj/item/device/radio/Topic(href, href_list)
if(href_list["track"])
log_runtime(EXCEPTION("Warning: Topic() was improperly called on radio [src] [type], with the track href and \[[href] [json_encode(href_list)]]. Please update the caller to use tgui_act."))
. = ..()
/obj/item/device/radio/tgui_interact(mob/user, datum/tgui/ui)
/obj/item/device/radio/tgui_interact(mob/user, datum/tgui/ui, datum/tgui/parent_ui)
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
ui = new(user, src, "Radio", name)
ui = new(user, src, "Radio", name, parent_ui)
ui.open()
/obj/item/device/radio/tgui_data(mob/user)
+1 -1
View File
@@ -54,7 +54,7 @@
popup.set_content(jointext(dat,null))
popup.open()
/obj/item/device/tvcamera/Topic(bred, href_list, state = physical_state)
/obj/item/device/tvcamera/Topic(bred, href_list, state = GLOB.tgui_physical_state)
if(..())
return 1
if(href_list["channel"])
+128 -122
View File
@@ -1,13 +1,23 @@
GLOBAL_LIST_BOILERPLATE(world_uplinks, /obj/item/device/uplink)
// I placed this here because of how relevant it is.
// You place this in your uplinkable item to check if an uplink is active or not.
// If it is, it will display the uplink menu and return 1, else it'll return false.
// If it returns true, I recommend closing the item's normal menu with "user << browse(null, "window=name")"
/obj/item/proc/active_uplink_check(mob/user as mob)
// Activates the uplink if it's active
if(hidden_uplink)
if(hidden_uplink.active)
hidden_uplink.trigger(user)
return TRUE
return FALSE
/obj/item/device/uplink
var/welcome = "Welcome, Operative" // Welcoming menu message
var/uses // Numbers of crystals
var/list/ItemsCategory // List of categories with lists of items
var/list/ItemsReference // List of references with an associated item
var/list/nanoui_items // List of items for NanoUI use
var/nanoui_menu = 0 // The current menu we are in
var/list/nanoui_data = new // Additional data for NanoUI use
var/faction = "" //Antag faction holder.
var/list/purchase_log = new
@@ -17,9 +27,7 @@ GLOBAL_LIST_BOILERPLATE(world_uplinks, /obj/item/device/uplink)
var/next_offer_time
var/datum/uplink_item/discount_item //The item to be discounted
var/discount_amount //The amount as a percent the item will be discounted by
/obj/item/device/uplink/nano_host()
return loc
var/compact_mode = FALSE
/obj/item/device/uplink/Initialize(var/mapload, var/datum/mind/owner = null, var/telecrystals = DEFAULT_TELECRYSTAL_AMOUNT)
. = ..()
@@ -53,23 +61,20 @@ GLOBAL_LIST_BOILERPLATE(world_uplinks, /obj/item/device/uplink)
name = "hidden uplink"
desc = "There is something wrong if you're examining this."
var/active = 0
var/datum/uplink_category/category = 0 // The current category we are in
var/exploit_id // Id of the current exploit record we are viewing
var/selected_cat
// The hidden uplink MUST be inside an obj/item's contents.
/obj/item/device/uplink/hidden/Initialize()
. = ..()
if(!isitem(loc))
return INITIALIZE_HINT_QDEL
nanoui_data = list()
update_nano_data()
/obj/item/device/uplink/hidden/next_offer()
discount_item = default_uplink_selection.get_random_item(INFINITY)
discount_amount = pick(90;0.9, 80;0.8, 70;0.7, 60;0.6, 50;0.5, 40;0.4, 30;0.3, 20;0.2, 10;0.1)
update_nano_data()
SSnanoui.update_uis(src)
next_offer_time = world.time + offer_time
SStgui.update_uis(src)
addtimer(CALLBACK(src, .proc/next_offer), offer_time)
// Toggles the uplink on and off. Normally this will bypass the item's normal functions and go to the uplink menu, if activated.
@@ -91,136 +96,137 @@ GLOBAL_LIST_BOILERPLATE(world_uplinks, /obj/item/device/uplink)
return 1
return 0
/*
NANO UI FOR UPLINK WOOP WOOP
*/
/obj/item/device/uplink/hidden/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1)
var/title = "Remote Uplink"
var/data[0]
uses = user.mind.tcrystals
if(ishuman(user))
var/mob/living/carbon/human/H = user
faction = H.antag_faction
// Legacy
/obj/item/device/uplink/hidden/interact(mob/user)
tgui_interact(user)
data["welcome"] = welcome
data["crystals"] = uses
data["menu"] = nanoui_menu
data += nanoui_data
/*****************
* Uplink TGUI
*****************/
/obj/item/device/uplink/tgui_host()
return loc
// update the ui if it exists, returns null if no ui is passed/found
ui = SSnanoui.try_update_ui(user, src, ui_key, ui, data, force_open)
if (!ui) // No auto-refresh
ui = new(user, src, ui_key, "uplink.tmpl", title, 630, 700, state = inventory_state)
data["menu"] = 0
ui.set_initial_data(data)
/obj/item/device/uplink/hidden/tgui_state(mob/user)
return GLOB.tgui_inventory_state
/obj/item/device/uplink/hidden/tgui_interact(mob/user, datum/tgui/ui, datum/tgui/parent_ui)
if(!active)
toggle()
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
ui = new(user, src, "Uplink", "Remote Uplink")
// This UI is only ever opened by one person,
// and never is updated outside of user input.
ui.set_autoupdate(FALSE)
ui.open()
/obj/item/device/uplink/hidden/tgui_data(mob/user, datum/tgui/ui, datum/tgui_state/state)
if(!user.mind)
return
// Interaction code. Gathers a list of items purchasable from the paren't uplink and displays it. It also adds a lock button.
/obj/item/device/uplink/hidden/interact(mob/user)
ui_interact(user)
var/list/data = ..()
/obj/item/device/uplink/hidden/CanUseTopic()
data["telecrystals"] = uses
data["lockable"] = TRUE
data["compactMode"] = compact_mode
data["discount_name"] = discount_item ? discount_item.name : ""
data["discount_amount"] = (1-discount_amount)*100
data["offer_expiry"] = worldtime2stationtime(next_offer_time)
data["exploit"] = null
data["locked_records"] = null
if(exploit_id)
for(var/datum/data/record/L in data_core.locked)
if(L.fields["id"] == exploit_id)
data["exploit"] = list() // Setting this to equal L.fields passes it's variables that are lists as reference instead of value.
// We trade off being able to automatically add shit for more control over what gets passed to json
// and if it's sanitized for html.
data["exploit"]["nanoui_exploit_record"] = html_encode(L.fields["exploit_record"]) // Change stuff into html
data["exploit"]["nanoui_exploit_record"] = replacetext(data["exploit"]["nanoui_exploit_record"], "\n", "<br>") // change line breaks into <br>
data["exploit"]["name"] = html_encode(L.fields["name"])
data["exploit"]["sex"] = html_encode(L.fields["sex"])
data["exploit"]["age"] = html_encode(L.fields["age"])
data["exploit"]["species"] = html_encode(L.fields["species"])
data["exploit"]["rank"] = html_encode(L.fields["rank"])
data["exploit"]["home_system"] = html_encode(L.fields["home_system"])
data["exploit"]["citizenship"] = html_encode(L.fields["citizenship"])
data["exploit"]["faction"] = html_encode(L.fields["faction"])
data["exploit"]["religion"] = html_encode(L.fields["religion"])
data["exploit"]["fingerprint"] = html_encode(L.fields["fingerprint"])
if(L.fields["antagvis"] == ANTAG_KNOWN || (faction == L.fields["antagfac"] && (L.fields["antagvis"] == ANTAG_SHARED)))
data["exploit"]["antagfaction"] = html_encode(L.fields["antagfac"])
else
data["exploit"]["antagfaction"] = html_encode("None")
break
else
var/list/permanentData = list()
for(var/datum/data/record/L in sortRecord(data_core.locked))
permanentData.Add(list(list(
"name" = L.fields["name"],
"id" = L.fields["id"]
)))
data["locked_records"] = permanentData
return data
/obj/item/device/uplink/hidden/tgui_static_data(mob/user)
var/list/data = ..()
data["categories"] = list()
for(var/datum/uplink_category/category in uplink.categories)
if(category.can_view(src))
var/list/cat = list(
"name" = category.name,
"items" = (category == selected_cat ? list() : null)
)
for(var/datum/uplink_item/item in category.items)
if(!item.can_view(src))
continue
var/cost = item.cost(uses, src) || "???"
cat["items"] += list(list(
"name" = item.name,
"cost" = cost,
"desc" = item.description(),
"ref" = REF(item),
))
data["categories"] += list(cat)
return data
/obj/item/device/uplink/hidden/tgui_status(mob/user, datum/tgui_state/state)
if(!active)
return STATUS_CLOSE
return ..()
// The purchasing code.
/obj/item/device/uplink/hidden/Topic(href, href_list)
/obj/item/device/uplink/hidden/tgui_act(action, list/params, datum/tgui/ui, datum/tgui_state/state)
if(..())
return 1
return TRUE
var/mob/user = usr
if(href_list["buy_item"])
var/datum/uplink_item/UI = (locate(href_list["buy_item"]) in uplink.items)
UI.buy(src, usr)
else if(href_list["lock"])
toggle()
var/datum/nanoui/ui = SSnanoui.get_open_ui(user, src, "main")
ui.close()
else if(href_list["return"])
nanoui_menu = round(nanoui_menu/10)
else if(href_list["menu"])
nanoui_menu = text2num(href_list["menu"])
if(href_list["id"])
exploit_id = href_list["id"]
else if(href_list["category"])
category = locate(href_list["category"]) in uplink.categories
update_nano_data()
return 1
/obj/item/device/uplink/hidden/proc/update_nano_data()
if(nanoui_menu == 0)
var/categories[0]
for(var/datum/uplink_category/category in uplink.categories)
if(category.can_view(src))
categories[++categories.len] = list("name" = category.name, "ref" = "\ref[category]")
nanoui_data["categories"] = categories
nanoui_data["discount_name"] = discount_item ? discount_item.name : ""
nanoui_data["discount_amount"] = (1-discount_amount)*100
nanoui_data["offer_expiry"] = worldtime2stationtime(next_offer_time)
if(category)
nanoui_data["current_category"] = category.name
var/items[0]
for(var/datum/uplink_item/item in category.items)
if(item.can_view(src))
var/cost = item.cost(uses, src)
if(!cost) cost = "???"
items[++items.len] = list("name" = item.name, "description" = replacetext(item.description(), "\n", "<br>"), "can_buy" = item.can_buy(src), "cost" = cost, "ref" = "\ref[item]")
nanoui_data["items"] = items
else if(nanoui_menu == 2)
var/permanentData[0]
for(var/datum/data/record/L in sortRecord(data_core.locked))
permanentData[++permanentData.len] = list(Name = L.fields["name"],"id" = L.fields["id"])
nanoui_data["exploit_records"] = permanentData
else if(nanoui_menu == 21)
nanoui_data["exploit_exists"] = 0
for(var/datum/data/record/L in data_core.locked)
if(L.fields["id"] == exploit_id)
nanoui_data["exploit"] = list() // Setting this to equal L.fields passes it's variables that are lists as reference instead of value.
// We trade off being able to automatically add shit for more control over what gets passed to json
// and if it's sanitized for html.
nanoui_data["exploit"]["nanoui_exploit_record"] = html_encode(L.fields["exploit_record"]) // Change stuff into html
nanoui_data["exploit"]["nanoui_exploit_record"] = replacetext(nanoui_data["exploit"]["nanoui_exploit_record"], "\n", "<br>") // change line breaks into <br>
nanoui_data["exploit"]["name"] = html_encode(L.fields["name"])
nanoui_data["exploit"]["sex"] = html_encode(L.fields["sex"])
nanoui_data["exploit"]["age"] = html_encode(L.fields["age"])
nanoui_data["exploit"]["species"] = html_encode(L.fields["species"])
nanoui_data["exploit"]["rank"] = html_encode(L.fields["rank"])
nanoui_data["exploit"]["home_system"] = html_encode(L.fields["home_system"])
nanoui_data["exploit"]["citizenship"] = html_encode(L.fields["citizenship"])
nanoui_data["exploit"]["faction"] = html_encode(L.fields["faction"])
nanoui_data["exploit"]["religion"] = html_encode(L.fields["religion"])
nanoui_data["exploit"]["fingerprint"] = html_encode(L.fields["fingerprint"])
if(L.fields["antagvis"] == ANTAG_KNOWN || (faction == L.fields["antagfac"] && (L.fields["antagvis"] == ANTAG_SHARED)))
nanoui_data["exploit"]["antagfaction"] = html_encode(L.fields["antagfac"])
else
nanoui_data["exploit"]["antagfaction"] = html_encode("None")
nanoui_data["exploit_exists"] = 1
break
// I placed this here because of how relevant it is.
// You place this in your uplinkable item to check if an uplink is active or not.
// If it is, it will display the uplink menu and return 1, else it'll return false.
// If it returns true, I recommend closing the item's normal menu with "user << browse(null, "window=name")"
/obj/item/proc/active_uplink_check(mob/user as mob)
// Activates the uplink if it's active
if(src.hidden_uplink)
if(src.hidden_uplink.active)
src.hidden_uplink.trigger(user)
return 1
return 0
switch(action)
if("buy")
var/datum/uplink_item/UI = (locate(params["ref"]) in uplink.items)
UI.buy(src, usr)
return TRUE
if("lock")
toggle()
SStgui.close_uis(src)
if("select")
selected_cat = params["category"]
return TRUE
if("compact_toggle")
compact_mode = !compact_mode
return TRUE
if("view_exploits")
exploit_id = params["id"]
return TRUE
// PRESET UPLINKS
// A collection of preset uplinks.
//
// Includes normal radio uplink, multitool uplink,
// implant uplink (not the implant tool) and a preset headset uplink.
/obj/item/device/radio/uplink/New(atom/loc, datum/mind/target_mind, telecrystals)
..(loc)
hidden_uplink = new(src, target_mind, telecrystals)
@@ -4,8 +4,8 @@
singular_name = "human skin piece"
icon_state = "sheet-hide"
no_variants = FALSE
drop_sound = 'sound/items/drop/cloth.ogg'
pickup_sound = 'sound/items/pickup/cloth.ogg'
drop_sound = 'sound/items/drop/leather.ogg'
pickup_sound = 'sound/items/pickup/leather.ogg'
/obj/item/stack/animalhide/human
amount = 50
+70 -81
View File
@@ -66,63 +66,81 @@
else
. += "There is enough charge for [get_amount()]."
/obj/item/stack/attack_self(mob/user as mob)
list_recipes(user)
/obj/item/stack/attack_self(mob/user)
tgui_interact(user)
/obj/item/stack/proc/list_recipes(mob/user as mob, recipes_sublist)
if (!recipes)
return
if (!src || get_amount() <= 0)
user << browse(null, "window=stack")
user.set_machine(src) //for correct work of onclose
var/list/recipe_list = recipes
if (recipes_sublist && recipe_list[recipes_sublist] && istype(recipe_list[recipes_sublist], /datum/stack_recipe_list))
var/datum/stack_recipe_list/srl = recipe_list[recipes_sublist]
recipe_list = srl.recipes
var/t1 = text("<HTML><HEAD><title>Constructions from []</title></HEAD><body><TT>Amount Left: []<br>", src, src.get_amount())
for(var/i=1;i<=recipe_list.len,i++)
var/E = recipe_list[i]
if (isnull(E))
t1 += "<hr>"
continue
/obj/item/stack/tgui_interact(mob/user, datum/tgui/ui, datum/tgui/parent_ui)
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
ui = new(user, src, "Stack", name)
ui.open()
if (i>1 && !isnull(recipe_list[i-1]))
t1+="<br>"
/obj/item/stack/tgui_data(mob/user, datum/tgui/ui, datum/tgui_state/state)
var/list/data = ..()
data["amount"] = get_amount()
if (istype(E, /datum/stack_recipe_list))
var/datum/stack_recipe_list/srl = E
t1 += "<a href='?src=\ref[src];sublist=[i]'>[srl.title]</a>"
return data
if (istype(E, /datum/stack_recipe))
var/datum/stack_recipe/R = E
var/max_multiplier = round(src.get_amount() / R.req_amount)
var/title as text
var/can_build = 1
can_build = can_build && (max_multiplier>0)
if (R.res_amount>1)
title+= "[R.res_amount]x [R.title]\s"
else
title+= "[R.title]"
title+= " ([R.req_amount] [src.singular_name]\s)"
if (can_build)
t1 += text("<A href='?src=\ref[src];sublist=[recipes_sublist];make=[i];multiplier=1'>[title]</A> ")
else
t1 += text("[]", title)
continue
if (R.max_res_amount>1 && max_multiplier>1)
max_multiplier = min(max_multiplier, round(R.max_res_amount/R.res_amount))
t1 += " |"
var/list/multipliers = list(5,10,25)
for (var/n in multipliers)
if (max_multiplier>=n)
t1 += " <A href='?src=\ref[src];make=[i];multiplier=[n]'>[n*R.res_amount]x</A>"
if (!(max_multiplier in multipliers))
t1 += " <A href='?src=\ref[src];make=[i];multiplier=[max_multiplier]'>[max_multiplier*R.res_amount]x</A>"
/obj/item/stack/tgui_static_data(mob/user, datum/tgui/ui, datum/tgui_state/state)
var/list/data = ..()
t1 += "</TT></body></HTML>"
user << browse(t1, "window=stack")
onclose(user, "stack")
return
data["recipes"] = recursively_build_recipes(recipes)
return data
/obj/item/stack/proc/recursively_build_recipes(list/recipe_to_iterate)
var/list/L = list()
for(var/recipe in recipe_to_iterate)
if(istype(recipe, /datum/stack_recipe_list))
var/datum/stack_recipe_list/R = recipe
L["[R.title]"] = recursively_build_recipes(R.recipes)
if(istype(recipe, /datum/stack_recipe))
var/datum/stack_recipe/R = recipe
L["[R.title]"] = build_recipe(R)
return L
/obj/item/stack/proc/build_recipe(datum/stack_recipe/R)
return list(
"res_amount" = R.res_amount,
"max_res_amount" = R.max_res_amount,
"req_amount" = R.req_amount,
"ref" = "\ref[R]",
)
/obj/item/stack/tgui_state(mob/user)
return GLOB.tgui_hands_state
/obj/item/stack/tgui_act(action, list/params, datum/tgui/ui, datum/tgui_state/state)
if(..())
return TRUE
switch(action)
if("make")
if(get_amount() < 1)
qdel(src)
return
var/datum/stack_recipe/R = locate(params["ref"])
if(!is_valid_recipe(R, recipes)) //href exploit protection
return FALSE
var/multiplier = text2num(params["multiplier"])
if(!multiplier || (multiplier <= 0)) //href exploit protection
return
produce_recipe(R, multiplier, usr)
return TRUE
/obj/item/stack/proc/is_valid_recipe(datum/stack_recipe/R, list/recipe_list)
for(var/S in recipe_list)
if(S == R)
return TRUE
if(istype(S, /datum/stack_recipe_list))
var/datum/stack_recipe_list/L = S
if(is_valid_recipe(R, L.recipes))
return TRUE
return FALSE
/obj/item/stack/proc/produce_recipe(datum/stack_recipe/recipe, var/quantity, mob/user)
var/required = quantity*recipe.req_amount
@@ -177,35 +195,6 @@
else
O.color = color
/obj/item/stack/Topic(href, href_list)
..()
if ((usr.restrained() || usr.stat || usr.get_active_hand() != src))
return
if (href_list["sublist"] && !href_list["make"])
list_recipes(usr, text2num(href_list["sublist"]))
if (href_list["make"])
if (src.get_amount() < 1) qdel(src) //Never should happen
var/list/recipes_list = recipes
if (href_list["sublist"])
var/datum/stack_recipe_list/srl = recipes_list[text2num(href_list["sublist"])]
recipes_list = srl.recipes
var/datum/stack_recipe/R = recipes_list[text2num(href_list["make"])]
var/multiplier = text2num(href_list["multiplier"])
if (!multiplier || (multiplier <= 0)) //href exploit protection
return
src.produce_recipe(R, multiplier, usr)
if (src && usr.machine==src) //do not reopen closed window
spawn( 0 )
src.interact(usr)
return
return
//Return 1 if an immediate subsequent call to use() would succeed.
//Ensures that code dealing with stacks uses the same logic
/obj/item/stack/proc/can_use(var/used)
+32
View File
@@ -0,0 +1,32 @@
/obj/item/stack/arcadeticket
name = "arcade tickets"
desc = "Wow! With enough of these, you could buy a bike! ...Pssh, yeah right."
singular_name = "arcade ticket"
icon_state = "arcade-ticket"
item_state = "tickets"
w_class = ITEMSIZE_TINY
max_amount = 30
/obj/item/stack/arcadeticket/New(loc, amount = null)
. = ..()
update_icon()
/obj/item/stack/arcadeticket/update_icon()
var/amount = get_amount()
switch(amount)
if(12 to INFINITY)
icon_state = "arcade-ticket_4"
if(6 to 12)
icon_state = "arcade-ticket_3"
if(2 to 6)
icon_state = "arcade-ticket_2"
else
icon_state = "arcade-ticket"
/obj/item/stack/arcadeticket/proc/pay_tickets()
amount -= 2
if(amount == 0)
qdel(src)
/obj/item/stack/arcadeticket/thirty
amount = 30
+16
View File
@@ -126,11 +126,13 @@
name = "empty cup"
icon_state = "coffee_vended"
drop_sound = 'sound/items/drop/papercup.ogg'
pickup_sound = 'sound/items/pickup/papercup.ogg'
/obj/item/trash/ramen
name = "cup ramen"
icon_state = "ramen"
drop_sound = 'sound/items/drop/papercup.ogg'
pickup_sound = 'sound/items/pickup/papercup.ogg'
/obj/item/trash/tray
name = "tray"
@@ -141,6 +143,8 @@
name = "candle"
icon = 'icons/obj/candle.dmi'
icon_state = "candle4"
drop_sound = 'sound/items/drop/gloves.ogg'
pickup_sound = 'sound/items/pickup/gloves.ogg'
/obj/item/trash/liquidfood
name = "\improper \"LiquidFood\" ration packet"
@@ -162,18 +166,26 @@
/obj/item/trash/brownies
name = "brownie tray"
icon_state = "brownies"
drop_sound = 'sound/items/drop/soda.ogg'
pickup_sound = 'sound/items/pickup/soda.ogg'
/obj/item/trash/snacktray
name = "snacktray"
icon_state = "snacktray"
drop_sound = 'sound/items/drop/soda.ogg'
pickup_sound = 'sound/items/pickup/soda.ogg'
/obj/item/trash/dipbowl
name = "dip bowl"
icon_state = "dipbowl"
drop_sound = 'sound/items/drop/food.ogg'
pickup_sound = 'sound/items/pickup/food.ogg'
/obj/item/trash/chipbasket
name = "empty basket"
icon_state = "chipbasket_empty"
drop_sound = 'sound/items/drop/food.ogg'
pickup_sound = 'sound/items/pickup/food.ogg'
/obj/item/trash/spitgum
name = "old gum"
@@ -181,12 +193,15 @@
icon = 'icons/obj/clothing/masks.dmi'
icon_state = "spit-gum"
drop_sound = 'sound/items/drop/flesh.ogg'
pickup_sound = 'sound/items/pickup/flesh.ogg'
/obj/item/trash/lollibutt
name = "lollipop stick"
desc = "A lollipop stick devoid of pop."
icon = 'icons/obj/clothing/masks.dmi'
icon_state = "pop-stick"
drop_sound = 'sound/items/drop/component.ogg'
pickup_sound = 'sound/items/pickup/component.ogg'
/obj/item/trash/spitwad
name = "spit wad"
@@ -194,6 +209,7 @@
icon = 'icons/obj/clothing/masks.dmi'
icon_state = "spit-chew"
drop_sound = 'sound/items/drop/flesh.ogg'
pickup_sound = 'sound/items/pickup/flesh.ogg'
slot_flags = SLOT_EARS | SLOT_MASK
/obj/item/trash/attack(mob/M as mob, mob/living/user as mob)
@@ -0,0 +1,37 @@
// **For augment items that aren't subtypes of other things.**
/obj/item/weapon/melee/augment
name = "integrated item"
desc = "A surprisingly non-descript item, integrated into its user. You probably shouldn't be seeing this."
icon = 'icons/obj/surgery.dmi'
icon_state = "augment_box"
/obj/item/weapon/melee/augment/blade
name = "handblade"
desc = "A sleek-looking telescopic blade that fits inside the hand. Favored by infiltration specialists and assassins."
icon_state = "augment_handblade"
item_icons = list(
slot_l_hand_str = 'icons/mob/items/lefthand_melee.dmi',
slot_r_hand_str = 'icons/mob/items/righthand_melee.dmi',
)
w_class = ITEMSIZE_SMALL
force = 15
armor_penetration = 25
sharp = 1
attack_verb = list("attacked", "slashed", "stabbed", "sliced", "torn", "ripped", "diced", "cut")
defend_chance = 10
projectile_parry_chance = 5
hitsound = 'sound/weapons/bladeslice.ogg'
/obj/item/weapon/melee/augment/blade/arm
name = "armblade"
desc = "A sleek-looking cybernetic blade that cleaves through people like butter. Favored by psychopaths and assassins."
icon_state = "augment_armblade"
w_class = ITEMSIZE_HUGE
force = 30
armor_penetration = 15
edge = 1
pry = 1
defend_chance = 40
projectile_parry_chance = 20
@@ -14,6 +14,8 @@
var/list/datum/autopsy_data_scanner/chemtraces = list()
var/target_name = null
var/timeofdeath = null
drop_sound = 'sound/items/drop/device.ogg'
pickup_sound = 'sound/items/pickup/device.ogg'
/datum/autopsy_data_scanner
var/weapon = null // this is the DEFINITE weapon type that was used
@@ -20,6 +20,8 @@
var/board_type = new /datum/frame/frame_types/computer
var/list/req_components = null
var/contain_parts = 1
drop_sound = 'sound/items/drop/device.ogg'
pickup_sound = 'sound/items/pickup/device.ogg'
//Called when the circuitboard is used to contruct a new machine.
/obj/item/weapon/circuitboard/proc/construct(var/obj/machinery/M)
@@ -110,10 +110,6 @@
update_icon()
return
if(istype(W, /obj/item/device/analyzer))
var/obj/item/device/analyzer/A = W
A.analyze_gases(src, user)
return
..()
return
@@ -6,8 +6,11 @@
var/electronic_warfare = 1
var/mob/registered_user = null
var/datum/tgui_module/agentcard/agentcard_module
/obj/item/weapon/card/id/syndicate/Initialize()
. = ..()
agentcard_module = new(src)
access = syndicate_access.Copy()
/obj/item/weapon/card/id/syndicate/station_access/Initialize()
@@ -15,6 +18,7 @@
access |= get_all_station_access()
/obj/item/weapon/card/id/syndicate/Destroy()
QDEL_NULL(agentcard_module)
unset_registered_user(registered_user)
return ..()
@@ -36,33 +40,12 @@
if(registered_user == user)
switch(alert("Would you like edit the ID, or show it?","Show or Edit?", "Edit","Show"))
if("Edit")
ui_interact(user)
agentcard_module.tgui_interact(user)
if("Show")
..()
else
..()
/obj/item/weapon/card/id/syndicate/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1)
var/data[0]
var/entries[0]
entries[++entries.len] = list("name" = "Age", "value" = age)
entries[++entries.len] = list("name" = "Appearance", "value" = "Set")
entries[++entries.len] = list("name" = "Assignment", "value" = assignment)
entries[++entries.len] = list("name" = "Blood Type", "value" = blood_type)
entries[++entries.len] = list("name" = "DNA Hash", "value" = dna_hash)
entries[++entries.len] = list("name" = "Fingerprint Hash", "value" = fingerprint_hash)
entries[++entries.len] = list("name" = "Name", "value" = registered_name)
entries[++entries.len] = list("name" = "Photo", "value" = "Update")
entries[++entries.len] = list("name" = "Sex", "value" = sex)
entries[++entries.len] = list("name" = "Factory Reset", "value" = "Use With Care")
data["electronic_warfare"] = electronic_warfare
data["entries"] = entries
ui = SSnanoui.try_update_ui(user, src, ui_key, ui, data, force_open)
if (!ui)
ui = new(user, src, ui_key, "agent_id_card.tmpl", "Fake ID", 600, 400)
ui.set_initial_data(data)
ui.open()
/obj/item/weapon/card/id/syndicate/proc/register_user(var/mob/user)
if(!istype(user) || user == registered_user)
@@ -79,114 +62,6 @@
registered_user.unregister(OBSERVER_EVENT_DESTROY, src)
registered_user = null
/obj/item/weapon/card/id/syndicate/CanUseTopic(mob/user)
if(user != registered_user)
return STATUS_CLOSE
return ..()
/obj/item/weapon/card/id/syndicate/Topic(href, href_list, var/datum/topic_state/state)
if(..())
return 1
var/user = usr
if(href_list["electronic_warfare"])
electronic_warfare = text2num(href_list["electronic_warfare"])
to_chat(user, "<span class='notice'>Electronic warfare [electronic_warfare ? "enabled" : "disabled"].</span>")
else if(href_list["set"])
switch(href_list["set"])
if("Age")
var/new_age = input(user,"What age would you like to put on this card?","Agent Card Age", age) as null|num
if(!isnull(new_age) && CanUseTopic(user, state))
if(new_age < 0)
age = initial(age)
else
age = new_age
to_chat(user, "<span class='notice'>Age has been set to '[age]'.</span>")
. = 1
if("Appearance")
var/datum/card_state/choice = input(user, "Select the appearance for this card.", "Agent Card Appearance") as null|anything in id_card_states()
if(choice && CanUseTopic(user, state))
src.icon_state = choice.icon_state
src.item_state = choice.item_state
to_chat(usr, "<span class='notice'>Appearance changed to [choice].</span>")
. = 1
if("Assignment")
var/new_job = sanitize(input(user,"What assignment would you like to put on this card?\nChanging assignment will not grant or remove any access levels.","Agent Card Assignment", assignment) as null|text)
if(!isnull(new_job) && CanUseTopic(user, state))
src.assignment = new_job
to_chat(user, "<span class='notice'>Occupation changed to '[new_job]'.</span>")
update_name()
. = 1
if("Blood Type")
var/default = blood_type
if(default == initial(blood_type) && ishuman(user))
var/mob/living/carbon/human/H = user
if(H.dna)
default = H.dna.b_type
var/new_blood_type = sanitize(input(user,"What blood type would you like to be written on this card?","Agent Card Blood Type",default) as null|text)
if(!isnull(new_blood_type) && CanUseTopic(user, state))
src.blood_type = new_blood_type
to_chat(user, "<span class='notice'>Blood type changed to '[new_blood_type]'.</span>")
. = 1
if("DNA Hash")
var/default = dna_hash
if(default == initial(dna_hash) && ishuman(user))
var/mob/living/carbon/human/H = user
if(H.dna)
default = H.dna.unique_enzymes
var/new_dna_hash = sanitize(input(user,"What DNA hash would you like to be written on this card?","Agent Card DNA Hash",default) as null|text)
if(!isnull(new_dna_hash) && CanUseTopic(user, state))
src.dna_hash = new_dna_hash
to_chat(user, "<span class='notice'>DNA hash changed to '[new_dna_hash]'.</span>")
. = 1
if("Fingerprint Hash")
var/default = fingerprint_hash
if(default == initial(fingerprint_hash) && ishuman(user))
var/mob/living/carbon/human/H = user
if(H.dna)
default = md5(H.dna.uni_identity)
var/new_fingerprint_hash = sanitize(input(user,"What fingerprint hash would you like to be written on this card?","Agent Card Fingerprint Hash",default) as null|text)
if(!isnull(new_fingerprint_hash) && CanUseTopic(user, state))
src.fingerprint_hash = new_fingerprint_hash
to_chat(user, "<span class='notice'>Fingerprint hash changed to '[new_fingerprint_hash]'.</span>")
. = 1
if("Name")
var/new_name = sanitizeName(input(user,"What name would you like to put on this card?","Agent Card Name", registered_name) as null|text)
if(!isnull(new_name) && CanUseTopic(user, state))
src.registered_name = new_name
update_name()
to_chat(user, "<span class='notice'>Name changed to '[new_name]'.</span>")
. = 1
if("Photo")
set_id_photo(user)
to_chat(user, "<span class='notice'>Photo changed.</span>")
. = 1
if("Sex")
var/new_sex = sanitize(input(user,"What sex would you like to put on this card?","Agent Card Sex", sex) as null|text)
if(!isnull(new_sex) && CanUseTopic(user, state))
src.sex = new_sex
to_chat(user, "<span class='notice'>Sex changed to '[new_sex]'.</span>")
. = 1
if("Factory Reset")
if(alert("This will factory reset the card, including access and owner. Continue?", "Factory Reset", "No", "Yes") == "Yes" && CanUseTopic(user, state))
age = initial(age)
access = syndicate_access.Copy()
assignment = initial(assignment)
blood_type = initial(blood_type)
dna_hash = initial(dna_hash)
electronic_warfare = initial(electronic_warfare)
fingerprint_hash = initial(fingerprint_hash)
icon_state = initial(icon_state)
name = initial(name)
registered_name = initial(registered_name)
unset_registered_user()
sex = initial(sex)
to_chat(user, "<span class='notice'>All information has been deleted from \the [src].</span>")
. = 1
// Always update the UI, or buttons will spin indefinitely
SSnanoui.update_uis(src)
/var/global/list/id_card_states
/proc/id_card_states()
if(!id_card_states)
@@ -169,6 +169,10 @@
organ_to_implant = /obj/item/organ/internal/augment/armmounted/hand/sword
organ_display_name = "weapon augment"
/obj/item/weapon/implant/organ/limbaugment/wrist/blade
organ_to_implant = /obj/item/organ/internal/augment/armmounted/hand/blade
organ_display_name = "weapon augment"
// Fore-arm
/obj/item/weapon/implant/organ/limbaugment/laser
organ_to_implant = /obj/item/organ/internal/augment/armmounted
@@ -185,6 +189,10 @@
/obj/item/weapon/implant/organ/limbaugment/upperarm/surge
organ_to_implant = /obj/item/organ/internal/augment/armmounted/shoulder/surge
/obj/item/weapon/implant/organ/limbaugment/upperarm/blade
organ_to_implant = /obj/item/organ/internal/augment/armmounted/shoulder/blade
organ_display_name = "weapon augment"
/*
* Others
*/
@@ -279,3 +279,23 @@
src.imp = new /obj/item/weapon/implant/organ/pelvic( src )
..()
return
/obj/item/weapon/implantcase/armblade
name = "glass case - 'Armblade'"
desc = "A case containing a nanite fabricator implant."
icon_state = "implantcase-b"
/obj/item/weapon/implantcase/armblade/New()
src.imp = new /obj/item/weapon/implant/organ/limbaugment/upperarm/blade( src )
..()
return
/obj/item/weapon/implantcase/handblade
name = "glass case - 'Handblade'"
desc = "A case containing a nanite fabricator implant."
icon_state = "implantcase-b"
/obj/item/weapon/implantcase/handblade/New()
src.imp = new /obj/item/weapon/implant/organ/limbaugment/wrist/blade( src )
..()
return
@@ -362,6 +362,8 @@
usr.client.screen -= W
W.dropped(usr)
add_fingerprint(usr)
if (use_sound)
playsound(src, src.use_sound, 50, 0, -5) //Something broke "add item to container" sounds, this is a hacky fix.
if(!prevent_warning)
for(var/mob/M in viewers(usr, null))
@@ -128,6 +128,12 @@
/obj/item/weapon/storage/box/syndie_kit/imp_aug/sprinter
case_type = /obj/item/weapon/implantcase/sprinter
/obj/item/weapon/storage/box/syndie_kit/imp_aug/armblade
case_type = /obj/item/weapon/implantcase/armblade
/obj/item/weapon/storage/box/syndie_kit/imp_aug/handblade
case_type = /obj/item/weapon/implantcase/handblade
/obj/item/weapon/storage/box/syndie_kit/space
name = "boxed space suit and helmet"
@@ -42,9 +42,9 @@
slot_flags = SLOT_ID
var/obj/item/weapon/card/id/front_id = null
drop_sound = 'sound/items/drop/cloth.ogg'
pickup_sound = 'sound/items/pickup/cloth.ogg'
drop_sound = 'sound/items/drop/leather.ogg'
pickup_sound = 'sound/items/pickup/leather.ogg'
/obj/item/weapon/storage/wallet/remove_from_storage(obj/item/W as obj, atom/new_location)
. = ..(W, new_location)
@@ -120,9 +120,6 @@ var/list/global/tank_gauge_cache = list()
if (istype(src.loc, /obj/item/assembly))
icon = src.loc
if ((istype(W, /obj/item/device/analyzer)) && get_dist(user, src) <= 1)
var/obj/item/device/analyzer/A = W
A.analyze_gases(src, user)
else if (istype(W,/obj/item/latexballon))
var/obj/item/latexballon/LB = W
LB.blow(src)
+3 -4
View File
@@ -42,7 +42,7 @@
old_turf.unregister_dangerous_object(src)
new_turf.register_dangerous_object(src)
/obj/Topic(href, href_list, var/datum/topic_state/state = default_state)
/obj/Topic(href, href_list, var/datum/tgui_state/state = GLOB.tgui_default_state)
if(usr && ..())
return 1
@@ -55,7 +55,7 @@
CouldNotUseTopic(usr)
return 1
/obj/CanUseTopic(var/mob/user, var/datum/topic_state/state = default_state)
/obj/CanUseTopic(var/mob/user, var/datum/tgui_state/state = GLOB.tgui_default_state)
if(user.CanUseObjTopic(src))
return ..()
to_chat(user, "<span class='danger'>[bicon(src)]Access Denied!</span>")
@@ -69,7 +69,7 @@
return 1
/obj/proc/CouldUseTopic(var/mob/user)
var/atom/host = nano_host()
var/atom/host = tgui_host()
host.add_hiddenprint(user)
/obj/proc/CouldNotUseTopic(var/mob/user)
@@ -135,7 +135,6 @@
in_use = 0
/obj/attack_ghost(mob/user)
ui_interact(user)
tgui_interact(user)
..()
+59
View File
@@ -153,6 +153,65 @@
prob(2);/obj/item/ammo_magazine/m9mmt,
prob(6);/obj/item/ammo_magazine/m9mmt/rubber)
/obj/random/grenade
name = "Random Grenade"
desc = "This is random thrown grenades (no C4/etc.)."
icon = 'icons/obj/grenade.dmi'
icon_state = "clusterbang_segment"
/obj/random/grenade/item_to_spawn()
return pick( prob(15);/obj/item/weapon/grenade/concussion,
prob(5);/obj/item/weapon/grenade/empgrenade,
prob(15);/obj/item/weapon/grenade/empgrenade/low_yield,
prob(5);/obj/item/weapon/grenade/chem_grenade/metalfoam,
prob(2);/obj/item/weapon/grenade/chem_grenade/incendiary,
prob(10);/obj/item/weapon/grenade/chem_grenade/antiweed,
prob(10);/obj/item/weapon/grenade/chem_grenade/cleaner,
prob(10);/obj/item/weapon/grenade/chem_grenade/teargas,
prob(5);/obj/item/weapon/grenade/explosive,
prob(10);/obj/item/weapon/grenade/explosive/mini,
prob(2);/obj/item/weapon/grenade/explosive/frag,
prob(15);/obj/item/weapon/grenade/flashbang,
prob(1);/obj/item/weapon/grenade/flashbang/clusterbang, //I can't not do this.
prob(15);/obj/item/weapon/grenade/shooter/rubber,
prob(10);/obj/item/weapon/grenade/shooter/energy/flash,
prob(15);/obj/item/weapon/grenade/smokebomb
)
/obj/random/grenade/less_lethal
name = "Random Security Grenade"
desc = "This is a random thrown grenade that shouldn't kill anyone."
icon = 'icons/obj/grenade.dmi'
icon_state = "clusterbang_segment"
/obj/random/grenade/less_lethal/item_to_spawn()
return pick( prob(20);/obj/item/weapon/grenade/concussion,
prob(15);/obj/item/weapon/grenade/empgrenade/low_yield,
prob(15);/obj/item/weapon/grenade/chem_grenade/metalfoam,
prob(20);/obj/item/weapon/grenade/chem_grenade/teargas,
prob(20);/obj/item/weapon/grenade/flashbang,
prob(1);/obj/item/weapon/grenade/flashbang/clusterbang, //I *still* can't not do this.
prob(15);/obj/item/weapon/grenade/shooter/rubber,
prob(10);/obj/item/weapon/grenade/shooter/energy/flash
)
/obj/random/grenade/box
name = "Random Grenade Box"
desc = "This is a random box of grenades. Not to be mistaken for a box of random grenades. Or a grenade of random boxes - but that would just be silly."
icon = 'icons/obj/grenade.dmi'
icon_state = "clusterbang_segment"
/obj/random/grenade/box/item_to_spawn()
return pick( prob(20);/obj/item/weapon/storage/box/flashbangs,
prob(10);/obj/item/weapon/storage/box/emps,
prob(20);/obj/item/weapon/storage/box/empslite,
prob(15);/obj/item/weapon/storage/box/smokes,
prob(5);/obj/item/weapon/storage/box/anti_photons,
prob(5);/obj/item/weapon/storage/box/frags,
prob(10);/obj/item/weapon/storage/box/metalfoam,
prob(15);/obj/item/weapon/storage/box/teargas
)
/obj/random/projectile/random
name = "Random Projectile Weapon"
desc = "This is a random weapon."
+459 -14
View File
@@ -585,7 +585,7 @@
/obj/item/clothing/mask/breath,
/obj/structure/closet/crate/aether //AETHER AIRSUPPLY
),
prob(10);list(
prob(5);list(
/obj/random/multiple/voidsuit/vintage,
/obj/random/multiple/voidsuit/vintage,
/obj/random/tank,
@@ -625,13 +625,20 @@
/obj/random/powercell,
/obj/structure/closet/crate/einstein //EINSTEIN BATTERYPACK
),
prob(10);list(
prob(5);list(
/obj/item/weapon/circuitboard/smes,
/obj/random/smes_coil,
/obj/random/smes_coil,
/obj/structure/closet/crate/focalpoint //FOCAL SMES
),
prob(15);list(
prob(10);list(
/obj/item/weapon/module/power_control,
/obj/item/stack/cable_coil,
/obj/item/frame/apc,
/obj/item/weapon/cell/apc,
/obj/structure/closet/crate/focalpoint //FOCAL APC
),
prob(5);list(
/obj/random/drinkbottle,
/obj/random/drinkbottle,
/obj/random/drinkbottle,
@@ -640,7 +647,7 @@
/obj/random/cigarettes,
/obj/structure/closet/crate/gilthari //GILTHARI LUXURY
),
prob(15);list(
prob(10);list(
/obj/random/tech_supply/nofail,
/obj/random/tech_supply/component/nofail,
/obj/random/tech_supply/component/nofail,
@@ -655,7 +662,7 @@
/obj/random/multiple/ore_pile,
/obj/structure/closet/crate/grayson //GRAYSON ORES
),
prob(15);list(
prob(10);list(
/obj/random/material/refined,
/obj/random/material/refined,
/obj/random/material/refined,
@@ -671,24 +678,48 @@
/obj/item/weapon/cell/device/weapon,
/obj/structure/closet/crate/secure/heph //HEPHAESTUS ENERGY
),
prob(2);list(
/obj/random/projectile/random,
/obj/random/projectile/random,
/obj/structure/closet/crate/secure/heph //HEPHAESTUS PROJECTILE
prob(1);list(
/obj/random/grenade/box,
/obj/random/grenade/box,
/obj/structure/closet/crate/secure/heph //HEPHAESTUS GRENADES
),
prob(2);list(
/obj/random/projectile/random,
/obj/random/projectile/random,
/obj/structure/closet/crate/secure/lawson //LAWSON PROJECTILE
),
prob(3);list(
/obj/random/grenade/less_lethal,
/obj/random/grenade/less_lethal,
/obj/random/grenade/less_lethal,
/obj/random/grenade/less_lethal,
/obj/structure/closet/crate/secure/nanotrasen //NTSEC CROWD GRENADES
),
prob(5);list(
/obj/random/multiple/voidsuit/security,
/obj/random/tank,
/obj/item/clothing/mask/breath,
/obj/structure/closet/crate/secure/nanotrasen //NTSEC SUIT
),
prob(2);list(
prob(5);list(
/obj/random/multiple/voidsuit/medical,
/obj/random/tank,
/obj/item/clothing/mask/breath,
/obj/structure/closet/crate/secure/veymed //VM SUIT
),
prob(5);list(
/obj/random/multiple/voidsuit/mining,
/obj/random/tank,
/obj/item/clothing/mask/breath,
/obj/structure/closet/crate/grayson //GRAYSON SUIT
),
prob(5);list(
/obj/random/multiple/voidsuit/engineering,
/obj/random/tank,
/obj/item/clothing/mask/breath,
/obj/structure/closet/crate/xion //XION SUIT
),
prob(10);list(
/obj/random/firstaid,
/obj/random/medical,
/obj/random/medical,
@@ -697,11 +728,13 @@
/obj/random/medical/lite,
/obj/structure/closet/crate/veymed //VM GRABBAG
),
prob(5);list(
prob(10);list(
/obj/random/firstaid,
/obj/random/firstaid,
/obj/random/firstaid,
/obj/random/firstaid,
/obj/random/unidentified_medicine/fresh_medicine,
/obj/random/unidentified_medicine/fresh_medicine,
/obj/structure/closet/crate/veymed //VM FAKS
),
prob(10);list(
@@ -726,19 +759,337 @@
/obj/random/medical/pillbottle,
/obj/random/medical/pillbottle,
/obj/random/medical/pillbottle,
/obj/random/medical/pillbottle,
/obj/random/unidentified_medicine/fresh_medicine,
/obj/random/unidentified_medicine/fresh_medicine,
/obj/structure/closet/crate/zenghu //ZENGHU PILLS
),
prob(10);list(
/obj/item/device/toner,
/obj/item/device/toner,
/obj/item/device/toner,
/obj/item/weapon/clipboard,
/obj/item/weapon/clipboard,
/obj/item/weapon/pen/red,
/obj/item/weapon/pen/blue,
/obj/item/weapon/pen/blue,
/obj/item/device/camera_film,
/obj/item/weapon/folder/blue,
/obj/item/weapon/folder/red,
/obj/item/weapon/folder/yellow,
/obj/item/weapon/hand_labeler,
/obj/item/weapon/tape_roll,
/obj/item/weapon/paper_bin,
/obj/item/sticky_pad/random,
/obj/structure/closet/crate/ummarcar //UMMARCAR OFFICE TRASH
),
prob(5);list(
/obj/item/weapon/reagent_containers/food/snacks/unajerky,
/obj/item/weapon/reagent_containers/food/snacks/unajerky,
/obj/item/weapon/reagent_containers/food/snacks/unajerky,
/obj/item/weapon/reagent_containers/food/snacks/unajerky,
/obj/item/weapon/reagent_containers/food/snacks/unajerky,
/obj/item/weapon/reagent_containers/food/snacks/unajerky,
/obj/item/weapon/reagent_containers/food/snacks/unajerky,
/obj/item/weapon/reagent_containers/food/snacks/unajerky,
/obj/structure/closet/crate/unathi //UNAJERKY
),
prob(10);list(
/obj/item/weapon/reagent_containers/glass/bucket,
/obj/item/weapon/mop,
/obj/item/clothing/under/rank/janitor,
/obj/item/weapon/cartridge/janitor,
/obj/item/clothing/gloves/black,
/obj/item/clothing/head/soft/purple,
/obj/item/weapon/storage/belt/janitor,
/obj/item/clothing/shoes/galoshes,
/obj/item/weapon/storage/bag/trash,
/obj/item/device/lightreplacer,
/obj/item/weapon/reagent_containers/spray/cleaner,
/obj/item/weapon/reagent_containers/glass/rag,
/obj/item/weapon/grenade/chem_grenade/cleaner,
/obj/item/weapon/grenade/chem_grenade/cleaner,
/obj/item/weapon/grenade/chem_grenade/cleaner,
/obj/structure/closet/crate/galaksi //GALAKSI JANITOR SUPPLIES
),
prob(5);list(
/obj/item/weapon/reagent_containers/food/snacks/candy/gummy,
/obj/item/weapon/reagent_containers/food/snacks/candy/gummy,
/obj/item/weapon/reagent_containers/food/snacks/candy/gummy,
/obj/item/weapon/reagent_containers/food/snacks/candy/gummy,
/obj/item/weapon/reagent_containers/food/snacks/candy/gummy,
/obj/item/weapon/reagent_containers/food/snacks/candy/gummy,
/obj/item/weapon/reagent_containers/food/snacks/candy/gummy,
/obj/item/weapon/reagent_containers/food/snacks/candy/gummy,
/obj/structure/closet/crate/allico //GUMMIES
),
prob(2);list(
/obj/item/weapon/tank/phoron/pressurized,
/obj/item/weapon/tank/phoron/pressurized,
/obj/structure/closet/crate/secure/phoron //HQ FUEL TANKS
),
prob(1);list(
/obj/random/contraband/nofail,
/obj/random/contraband/nofail,
/obj/random/contraband/nofail,
/obj/random/unidentified_medicine/combat_medicine,
/obj/random/unidentified_medicine/combat_medicine,
/obj/random/projectile/random,
/obj/random/projectile/random,
/obj/random/mre,
/obj/random/mre,
/obj/structure/closet/crate/secure/saare //SAARE GRAB BAG
),
prob(2);list(
/obj/random/grenade,
/obj/random/grenade,
/obj/random/grenade,
/obj/random/grenade,
/obj/random/grenade,
/obj/random/grenade,
/obj/structure/closet/crate/secure/saare //SAARE GRENADES
),
prob(1);list(
/obj/random/cash/big,
/obj/random/cash/big,
/obj/random/cash/big,
/obj/random/cash/huge,
/obj/random/cash/huge,
/obj/random/cash/huge,
/obj/structure/closet/crate/secure/saare //SAARE CASH CRATE
)
)
/obj/random/multiple/corp_crate/no_weapons
name = "random corporate crate (no weapons)"
desc = "A random corporate crate with thematic contents. No weapons."
icon = 'icons/obj/storage.dmi'
icon_state = "crate"
/obj/random/multiple/corp_crate/no_weapons/item_to_spawn()
return pick(
prob(10);list(
/obj/random/tank,
/obj/random/tank,
/obj/random/tank,
/obj/item/clothing/mask/breath,
/obj/item/clothing/mask/breath,
/obj/item/clothing/mask/breath,
/obj/structure/closet/crate/aether //AETHER AIRSUPPLY
),
prob(5);list(
/obj/random/multiple/voidsuit/vintage,
/obj/random/multiple/voidsuit/vintage,
/obj/random/tank,
/obj/random/tank,
/obj/item/clothing/mask/breath,
/obj/item/clothing/mask/breath,
/obj/structure/closet/crate/aether //AETHER OLDSUITS
),
prob(10);list(
/obj/random/mre,
/obj/structure/closet/crate/secure/saare //SAARE GUNS
/obj/random/mre,
/obj/random/mre,
/obj/random/mre,
/obj/random/mre,
/obj/structure/closet/crate/centauri //CENTAURI MRES
),
prob(10);list(
/obj/random/drinksoft,
/obj/random/drinksoft,
/obj/random/drinksoft,
/obj/random/drinksoft,
/obj/random/drinksoft,
/obj/structure/closet/crate/freezer/centauri //CENTAURI SODA
),
prob(10);list(
/obj/random/snack,
/obj/random/snack,
/obj/random/snack,
/obj/random/snack,
/obj/random/snack,
/obj/structure/closet/crate/freezer/centauri //CENTAURI SNACKS
),
prob(10);list(
/obj/random/powercell,
/obj/random/powercell,
/obj/random/powercell,
/obj/random/powercell,
/obj/structure/closet/crate/einstein //EINSTEIN BATTERYPACK
),
prob(5);list(
/obj/item/weapon/circuitboard/smes,
/obj/random/smes_coil,
/obj/random/smes_coil,
/obj/structure/closet/crate/focalpoint //FOCAL SMES
),
prob(10);list(
/obj/item/weapon/module/power_control,
/obj/item/stack/cable_coil,
/obj/item/frame/apc,
/obj/item/weapon/cell/apc,
/obj/structure/closet/crate/focalpoint //FOCAL APC
),
prob(5);list(
/obj/random/drinkbottle,
/obj/random/drinkbottle,
/obj/random/drinkbottle,
/obj/random/cigarettes,
/obj/random/cigarettes,
/obj/random/cigarettes,
/obj/structure/closet/crate/gilthari //GILTHARI LUXURY
),
prob(10);list(
/obj/random/tech_supply/nofail,
/obj/random/tech_supply/component/nofail,
/obj/random/tech_supply/component/nofail,
/obj/random/tech_supply/component/nofail,
/obj/random/tech_supply/component/nofail,
/obj/structure/closet/crate/grayson //GRAYSON TECH
),
prob(15);list(
/obj/random/multiple/ore_pile,
/obj/random/multiple/ore_pile,
/obj/random/multiple/ore_pile,
/obj/random/multiple/ore_pile,
/obj/structure/closet/crate/grayson //GRAYSON ORES
),
prob(10);list(
/obj/random/material/refined,
/obj/random/material/refined,
/obj/random/material/refined,
/obj/random/material/refined,
/obj/structure/closet/crate/grayson //GRAYSON MATS
),
prob(5);list(
/obj/random/multiple/voidsuit/security,
/obj/random/tank,
/obj/item/clothing/mask/breath,
/obj/structure/closet/crate/secure/nanotrasen //NTSEC SUIT
),
prob(5);list(
/obj/random/multiple/voidsuit/medical,
/obj/random/tank,
/obj/item/clothing/mask/breath,
/obj/structure/closet/crate/secure/veymed //VM SUIT
),
prob(5);list(
/obj/random/multiple/voidsuit/mining,
/obj/random/tank,
/obj/item/clothing/mask/breath,
/obj/structure/closet/crate/grayson //GRAYSON SUIT
),
prob(5);list(
/obj/random/multiple/voidsuit/engineering,
/obj/random/tank,
/obj/item/clothing/mask/breath,
/obj/structure/closet/crate/xion //XION SUIT
),
prob(10);list(
/obj/random/firstaid,
/obj/random/medical,
/obj/random/medical,
/obj/random/medical,
/obj/random/medical/lite,
/obj/random/medical/lite,
/obj/structure/closet/crate/veymed //VM GRABBAG
),
prob(10);list(
/obj/random/firstaid,
/obj/random/firstaid,
/obj/random/firstaid,
/obj/random/firstaid,
/obj/random/unidentified_medicine/fresh_medicine,
/obj/random/unidentified_medicine/fresh_medicine,
/obj/structure/closet/crate/veymed //VM FAKS
),
prob(10);list(
/obj/random/tech_supply/nofail,
/obj/random/tech_supply/nofail,
/obj/random/tech_supply/nofail,
/obj/random/tech_supply/nofail,
/obj/random/tech_supply/nofail,
/obj/structure/closet/crate/xion //XION SUPPLY
),
prob(10);list(
/obj/random/firstaid,
/obj/random/medical,
/obj/random/medical/pillbottle,
/obj/random/medical/pillbottle,
/obj/random/medical/lite,
/obj/random/medical/lite,
/obj/structure/closet/crate/zenghu //ZENGHU GRABBAG
),
prob(10);list(
/obj/random/medical/pillbottle,
/obj/random/medical/pillbottle,
/obj/random/medical/pillbottle,
/obj/random/medical/pillbottle,
/obj/random/unidentified_medicine/fresh_medicine,
/obj/random/unidentified_medicine/fresh_medicine,
/obj/structure/closet/crate/zenghu //ZENGHU PILLS
),
prob(10);list(
/obj/item/device/toner,
/obj/item/device/toner,
/obj/item/device/toner,
/obj/item/weapon/clipboard,
/obj/item/weapon/clipboard,
/obj/item/weapon/pen/red,
/obj/item/weapon/pen/blue,
/obj/item/weapon/pen/blue,
/obj/item/device/camera_film,
/obj/item/weapon/folder/blue,
/obj/item/weapon/folder/red,
/obj/item/weapon/folder/yellow,
/obj/item/weapon/hand_labeler,
/obj/item/weapon/tape_roll,
/obj/item/weapon/paper_bin,
/obj/item/sticky_pad/random,
/obj/structure/closet/crate/ummarcar //UMMARCAR OFFICE TRASH
),
prob(5);list(
/obj/item/weapon/reagent_containers/food/snacks/unajerky,
/obj/item/weapon/reagent_containers/food/snacks/unajerky,
/obj/item/weapon/reagent_containers/food/snacks/unajerky,
/obj/item/weapon/reagent_containers/food/snacks/unajerky,
/obj/item/weapon/reagent_containers/food/snacks/unajerky,
/obj/item/weapon/reagent_containers/food/snacks/unajerky,
/obj/item/weapon/reagent_containers/food/snacks/unajerky,
/obj/item/weapon/reagent_containers/food/snacks/unajerky,
/obj/structure/closet/crate/unathi //UNAJERKY
),
prob(10);list(
/obj/item/weapon/reagent_containers/glass/bucket,
/obj/item/weapon/mop,
/obj/item/clothing/under/rank/janitor,
/obj/item/weapon/cartridge/janitor,
/obj/item/clothing/gloves/black,
/obj/item/clothing/head/soft/purple,
/obj/item/weapon/storage/belt/janitor,
/obj/item/clothing/shoes/galoshes,
/obj/item/weapon/storage/bag/trash,
/obj/item/device/lightreplacer,
/obj/item/weapon/reagent_containers/spray/cleaner,
/obj/item/weapon/reagent_containers/glass/rag,
/obj/item/weapon/grenade/chem_grenade/cleaner,
/obj/item/weapon/grenade/chem_grenade/cleaner,
/obj/item/weapon/grenade/chem_grenade/cleaner,
/obj/structure/closet/crate/galaksi //GALAKSI JANITOR SUPPLIES
),
prob(5);list(
/obj/item/weapon/reagent_containers/food/snacks/candy/gummy,
/obj/item/weapon/reagent_containers/food/snacks/candy/gummy,
/obj/item/weapon/reagent_containers/food/snacks/candy/gummy,
/obj/item/weapon/reagent_containers/food/snacks/candy/gummy,
/obj/item/weapon/reagent_containers/food/snacks/candy/gummy,
/obj/item/weapon/reagent_containers/food/snacks/candy/gummy,
/obj/item/weapon/reagent_containers/food/snacks/candy/gummy,
/obj/item/weapon/reagent_containers/food/snacks/candy/gummy,
/obj/structure/closet/crate/allico //GUMMIES
),
prob(2);list(
/obj/item/weapon/tank/phoron/pressurized,
/obj/item/weapon/tank/phoron/pressurized,
/obj/structure/closet/crate/secure/phoron //HQ FUEL TANKS
),
prob(1);list(
/obj/random/cash/big,
@@ -849,6 +1200,100 @@
/obj/structure/closet/crate/large/secure/xion //XION TECH COMPS
)
)
/obj/random/multiple/large_corp_crate/no_weapons
name = "random large corporate crate (no weapons)"
desc = "A random large corporate crate with thematic contents. No weapons."
icon = 'icons/obj/storage.dmi'
icon_state = "largermetal"
/obj/random/multiple/large_corp_crate/no_weapons/item_to_spawn()
return pick(
prob(30);list(
/obj/random/multiple/voidsuit/vintage,
/obj/random/multiple/voidsuit/vintage,
/obj/random/tank,
/obj/random/tank,
/obj/item/clothing/mask/breath,
/obj/item/clothing/mask/breath,
/obj/random/multiple/voidsuit/vintage,
/obj/random/multiple/voidsuit/vintage,
/obj/random/tank,
/obj/random/tank,
/obj/item/clothing/mask/breath,
/obj/item/clothing/mask/breath,
/obj/structure/closet/crate/large/aether //AETHER SUITSBOX
),
prob(30);list(
/obj/random/powercell,
/obj/random/powercell,
/obj/random/powercell,
/obj/random/powercell,
/obj/random/powercell,
/obj/random/powercell,
/obj/random/powercell,
/obj/random/powercell,
/obj/random/powercell,
/obj/random/powercell,
/obj/random/powercell,
/obj/random/powercell,
/obj/structure/closet/crate/large/einstein //EIN BATTERY MEGAPACK
),
prob(20);list(
/obj/item/weapon/circuitboard/smes,
/obj/item/weapon/circuitboard/smes,
/obj/random/smes_coil,
/obj/random/smes_coil,
/obj/random/smes_coil,
/obj/random/smes_coil,
/obj/random/smes_coil,
/obj/random/smes_coil,
/obj/structure/closet/crate/large/einstein //EIN SMESBOX
),
prob(20);list(
/obj/random/tech_supply/nofail,
/obj/random/tech_supply/nofail,
/obj/random/tech_supply/nofail,
/obj/random/tech_supply/nofail,
/obj/random/tech_supply/nofail,
/obj/random/tech_supply/nofail,
/obj/random/tech_supply/nofail,
/obj/random/tech_supply/nofail,
/obj/random/tech_supply/nofail,
/obj/random/tech_supply/nofail,
/obj/structure/closet/crate/large/xion //XION TECH SUPPLY
),
prob(20);list(
/obj/random/tech_supply/component/nofail,
/obj/random/tech_supply/component/nofail,
/obj/random/tech_supply/component/nofail,
/obj/random/tech_supply/component/nofail,
/obj/random/tech_supply/component/nofail,
/obj/random/tech_supply/component/nofail,
/obj/random/tech_supply/component/nofail,
/obj/random/tech_supply/component/nofail,
/obj/random/tech_supply/component/nofail,
/obj/random/tech_supply/component/nofail,
/obj/structure/closet/crate/large/secure/xion //XION TECH COMPS
)
)
//recursion crate!
/obj/random/multiple/random_size_crate
name = "random size corporate crate"
desc = "A random size corporate crate with thematic contents: prefers small crates."
icon = 'icons/obj/storage.dmi'
icon_state = "largermetal"
/obj/random/multiple/random_size_crate/item_to_spawn()
return pick(
prob(85);list(
/obj/random/multiple/corp_crate
),
prob(15);list(
/obj/random/multiple/large_corp_crate
)
)
/*
* Turf swappers.
*/
+10
View File
@@ -0,0 +1,10 @@
/obj/random/empty_or_lootable_crate
name = "random crate"
desc = "Spawns a random crate which may or may not have contents. Sometimes spawns nothing."
icon = 'icons/obj/storage.dmi'
icon_state = "moneybag"
spawn_nothing_percentage = 20
/obj/random/empty_or_lootable_crate/item_to_spawn()
return pick(/obj/random/crate,
/obj/random/multiple/corp_crate)
+32
View File
@@ -29,6 +29,10 @@
/obj/item/clothing/suit/space/void/engineering/alt,
/obj/item/clothing/head/helmet/space/void/engineering/alt
),
prob(5);list(
/obj/item/clothing/suit/space/void/engineering/hazmat,
/obj/item/clothing/head/helmet/space/void/engineering/hazmat
),
prob(5);list(
/obj/item/clothing/suit/space/void/engineering/construction,
/obj/item/clothing/head/helmet/space/void/engineering/construction
@@ -109,7 +113,35 @@
)
)
/obj/random/multiple/voidsuit/engineering
name = "Random Engineering Voidsuit"
desc = "This is a random engineering voidsuit."
icon = 'icons/obj/clothing/spacesuits.dmi'
icon_state = "rig-engineering"
/obj/random/multiple/voidsuit/engineering/item_to_spawn()
return pick(
prob(35);list(
/obj/item/clothing/suit/space/void/engineering,
/obj/item/clothing/head/helmet/space/void/engineering
),
prob(5);list(
/obj/item/clothing/suit/space/void/engineering/alt,
/obj/item/clothing/head/helmet/space/void/engineering/alt
),
prob(15);list(
/obj/item/clothing/suit/space/void/engineering/hazmat,
/obj/item/clothing/head/helmet/space/void/engineering/hazmat
),
prob(15);list(
/obj/item/clothing/suit/space/void/engineering/construction,
/obj/item/clothing/head/helmet/space/void/engineering/construction
),
prob(5);list(
/obj/item/clothing/suit/space/void/engineering/salvage,
/obj/item/clothing/head/helmet/space/void/engineering/salvage
)
)
/obj/random/multiple/voidsuit/security
name = "Random Security Voidsuit"
+2 -2
View File
@@ -16,8 +16,8 @@ LINEN BINS
throw_speed = 1
throw_range = 2
w_class = ITEMSIZE_SMALL
drop_sound = 'sound/items/drop/cloth.ogg'
pickup_sound = 'sound/items/pickup/cloth.ogg'
drop_sound = 'sound/items/drop/clothing.ogg'
pickup_sound = 'sound/items/pickup/clothing.ogg'
/obj/item/weapon/bedsheet/attack_self(mob/user as mob)
user.drop_item()
+176 -104
View File
@@ -20,8 +20,90 @@ GLOBAL_LIST_BOILERPLATE(all_janitorial_carts, /obj/structure/janitorialcart)
var/has_items = FALSE
var/dismantled = TRUE
var/signs = 0 //maximum capacity hardcoded below
var/list/tgui_icons = list()
var/static/list/equippable_item_whitelist
/obj/structure/janitorialcart/proc/equip_janicart_item(mob/user, obj/item/I)
if(!equippable_item_whitelist)
equippable_item_whitelist = typecacheof(list(
/obj/item/weapon/storage/bag/trash,
/obj/item/weapon/mop,
/obj/item/weapon/reagent_containers/spray,
/obj/item/device/lightreplacer,
/obj/item/clothing/suit/caution,
))
if(!is_type_in_typecache(I, equippable_item_whitelist))
to_chat(user, "<span class='warning'>There's no room in [src] for [I].</span>")
return FALSE
if(!user.unEquip(I, 0, src))
to_chat(user, "<span class='warning'>[I] is stuck to your hand.</span>")
return FALSE
if(istype(I, /obj/item/weapon/storage/bag/trash))
if(mybag)
to_chat(user, "<span class='warning'>[src] already has \an [I].</span>")
return FALSE
mybag = I
setTguiIcon("mybag", mybag)
else if(istype(I, /obj/item/weapon/mop))
if(mymop)
to_chat(user, "<span class='warning'>[src] already has \an [I].</span>")
return FALSE
mymop = I
setTguiIcon("mymop", mymop)
else if(istype(I, /obj/item/weapon/reagent_containers/spray))
if(myspray)
to_chat(user, "<span class='warning'>[src] already has \an [I].</span>")
return FALSE
myspray = I
setTguiIcon("myspray", myspray)
else if(istype(I, /obj/item/device/lightreplacer))
if(myreplacer)
to_chat(user, "<span class='warning'>[src] already has \an [I].</span>")
return FALSE
myreplacer = I
setTguiIcon("myreplacer", myreplacer)
else if(istype(I, /obj/item/clothing/suit/caution))
if(signs < 4)
signs++
setTguiIcon("signs", I)
else
to_chat(user, "<span class='notice'>[src] can't hold any more signs.</span>")
return FALSE
else
// This may look like duplicate code, but it's important that we don't call unEquip *and* warn the user if
// something horrible goes wrong. (this else is never supposed to happen)
to_chat(user, "<span class='warning'>There's no room in [src] for [I].</span>")
return FALSE
update_icon()
to_chat(user, "<span class='notice'>You put [I] into [src].</span>")
return TRUE
/obj/structure/janitorialcart/proc/setTguiIcon(key, atom/A)
if(!istype(A) || !key)
return
var/icon/F = getFlatIcon(A, defdir = SOUTH, no_anim = TRUE)
tgui_icons["[key]"] = "'data:image/png;base64,[icon2base64(F)]'"
SStgui.update_uis(src)
/obj/structure/janitorialcart/proc/nullTguiIcon(key)
if(!key)
return
tgui_icons.Remove(key)
SStgui.update_uis(src)
/obj/structure/janitorialcart/proc/clearTguiIcons()
tgui_icons.Cut()
SStgui.update_uis(src)
/obj/structure/janitorialcart/Destroy()
QDEL_NULL(mybag)
@@ -29,20 +111,22 @@ GLOBAL_LIST_BOILERPLATE(all_janitorial_carts, /obj/structure/janitorialcart)
QDEL_NULL(myspray)
QDEL_NULL(myreplacer)
QDEL_NULL(mybucket)
clearTguiIcons()
return ..()
/obj/structure/janitorialcart/examine(mob/user)
if(..(user, 1))
if (mybucket)
var/contains = mybucket.reagents.total_volume
to_chat(user, "\icon[src] The bucket contains [contains] unit\s of liquid!")
else
to_chat(user, "\icon[src] There is no bucket mounted on it!")
. = ..(user)
if(istype(mybucket))
var/contains = mybucket.reagents.total_volume
. += "[bicon(src)] The bucket contains [contains] unit\s of liquid!"
else
. += "[bicon(src)] There is no bucket mounted on it!"
/obj/structure/janitorialcart/MouseDrop_T(atom/movable/O as mob|obj, mob/living/user as mob)
if (istype(O, /obj/structure/mopbucket) && !mybucket)
O.forceMove(src)
mybucket = O
setTguiIcon("mybucket", mybucket)
to_chat(user, "You mount the [O] on the janicart.")
update_icon()
else
@@ -70,38 +154,19 @@ GLOBAL_LIST_BOILERPLATE(all_janitorial_carts, /obj/structure/janitorialcart)
return 1
else if(istype(I, /obj/item/weapon/reagent_containers/spray) && !myspray)
user.unEquip(I, 0, src)
myspray = I
update_icon()
updateUsrDialog()
to_chat(user, "<span class='notice'>You put [I] into [src].</span>")
equip_janicart_item(user, I)
return 1
else if(istype(I, /obj/item/device/lightreplacer) && !myreplacer)
user.unEquip(I, 0, src)
myreplacer = I
update_icon()
updateUsrDialog()
to_chat(user, "<span class='notice'>You put [I] into [src].</span>")
equip_janicart_item(user, I)
return 1
else if(istype(I, /obj/item/weapon/storage/bag/trash) && !mybag)
user.unEquip(I, 0, src)
mybag = I
update_icon()
updateUsrDialog()
to_chat(user, "<span class='notice'>You put [I] into [src].</span>")
equip_janicart_item(user, I)
return 1
else if(istype(I, /obj/item/clothing/suit/caution))
if(signs < 4)
user.unEquip(I, 0, src)
signs++
update_icon()
updateUsrDialog()
to_chat(user, "<span class='notice'>You put [I] into [src].</span>")
else
to_chat(user, "<span class='notice'>[src] can't hold any more signs.</span>")
equip_janicart_item(user, I)
return 1
else if(mybag)
@@ -124,16 +189,7 @@ GLOBAL_LIST_BOILERPLATE(all_janitorial_carts, /obj/structure/janitorialcart)
if(user.incapacitated() || !Adjacent(user)) return
var/obj/I = usr.get_active_hand()
if(istype(I, /obj/item/weapon/mop))
if(!mymop)
usr.drop_from_inventory(I,src)
mymop = I
update_icon()
updateUsrDialog()
to_chat(usr, "<span class='notice'>You put [I] into [src].</span>")
update_icon()
else
to_chat(usr, "<span class='notice'>The cart already has a mop attached</span>")
return
equip_janicart_item(user, I)
else if(istype(I, /obj/item/weapon/reagent_containers) && mybucket)
var/obj/item/weapon/reagent_containers/C = I
C.afterattack(mybucket, usr, 1)
@@ -141,75 +197,95 @@ GLOBAL_LIST_BOILERPLATE(all_janitorial_carts, /obj/structure/janitorialcart)
/obj/structure/janitorialcart/attack_hand(mob/user)
ui_interact(user)
tgui_interact(user)
return
/obj/structure/janitorialcart/ui_interact(var/mob/user, var/ui_key = "main", var/datum/nanoui/ui = null, var/force_open = TRUE)
var/data[0]
data["name"] = capitalize(name)
data["bag"] = mybag ? capitalize(mybag.name) : null
data["bucket"] = mybucket ? capitalize(mybucket.name) : null
data["mop"] = mymop ? capitalize(mymop.name) : null
data["spray"] = myspray ? capitalize(myspray.name) : null
data["replacer"] = myreplacer ? capitalize(myreplacer.name) : null
data["signs"] = signs ? "[signs] sign\s" : null
ui = SSnanoui.try_update_ui(user, src, ui_key, ui, data, force_open)
/obj/structure/janitorialcart/tgui_interact(mob/user, datum/tgui/ui)
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
ui = new(user, src, ui_key, "janitorcart.tmpl", "Janitorial cart", 240, 160)
ui.set_initial_data(data)
ui = new(user, src, "JanitorCart", name) // 240, 160
ui.set_autoupdate(FALSE)
ui.open()
/obj/structure/janitorialcart/tgui_data(mob/user, datum/tgui/ui, datum/tgui_state/state)
var/list/data = ..()
/obj/structure/janitorialcart/Topic(href, href_list)
if(!in_range(src, usr))
return
if(!isliving(usr))
return
var/mob/living/user = usr
data["mybag"] = mybag ? capitalize(mybag.name) : null
data["mybucket"] = mybucket ? capitalize(mybucket.name) : null
data["mymop"] = mymop ? capitalize(mymop.name) : null
data["myspray"] = myspray ? capitalize(myspray.name) : null
data["myreplacer"] = myreplacer ? capitalize(myreplacer.name) : null
data["signs"] = signs ? "[signs] sign\s" : null
if(href_list["take"])
switch(href_list["take"])
if("garbage")
if(mybag)
user.put_in_hands(mybag)
to_chat(user, "<span class='notice'>You take [mybag] from [src].</span>")
mybag = null
if("mop")
if(mymop)
user.put_in_hands(mymop)
to_chat(user, "<span class='notice'>You take [mymop] from [src].</span>")
mymop = null
if("spray")
if(myspray)
user.put_in_hands(myspray)
to_chat(user, "<span class='notice'>You take [myspray] from [src].</span>")
myspray = null
if("replacer")
if(myreplacer)
user.put_in_hands(myreplacer)
to_chat(user, "<span class='notice'>You take [myreplacer] from [src].</span>")
myreplacer = null
if("sign")
if(signs)
var/obj/item/clothing/suit/caution/Sign = locate() in src
if(Sign)
user.put_in_hands(Sign)
to_chat(user, "<span class='notice'>You take \a [Sign] from [src].</span>")
signs--
else
warning("[src] signs ([signs]) didn't match contents")
signs = 0
if("bucket")
if(mybucket)
mybucket.forceMove(get_turf(user))
to_chat(user, "<span class='notice'>You unmount [mybucket] from [src].</span>")
mybucket = null
data["icons"] = tgui_icons
return data
/obj/structure/janitorialcart/tgui_act(action, list/params, datum/tgui/ui, datum/tgui_state/state)
if(..())
return TRUE
var/obj/item/I = usr.get_active_hand()
switch(action)
if("bag")
if(mybag)
usr.put_in_hands(mybag)
to_chat(usr, "<span class='notice'>You take [mybag] from [src].</span>")
mybag = null
nullTguiIcon("mybag")
else if(is_type_in_typecache(I, equippable_item_whitelist))
equip_janicart_item(usr, I)
if("mop")
if(mymop)
usr.put_in_hands(mymop)
to_chat(usr, "<span class='notice'>You take [mymop] from [src].</span>")
mymop = null
nullTguiIcon("mymop")
else if(is_type_in_typecache(I, equippable_item_whitelist))
equip_janicart_item(usr, I)
if("spray")
if(myspray)
usr.put_in_hands(myspray)
to_chat(usr, "<span class='notice'>You take [myspray] from [src].</span>")
myspray = null
nullTguiIcon("myspray")
else if(is_type_in_typecache(I, equippable_item_whitelist))
equip_janicart_item(usr, I)
if("replacer")
if(myreplacer)
usr.put_in_hands(myreplacer)
to_chat(usr, "<span class='notice'>You take [myreplacer] from [src].</span>")
myreplacer = null
nullTguiIcon("myreplacer")
else if(is_type_in_typecache(I, equippable_item_whitelist))
equip_janicart_item(usr, I)
if("sign")
if(istype(I, /obj/item/clothing/suit/caution) && signs < 4)
equip_janicart_item(usr, I)
else if(signs)
var/obj/item/clothing/suit/caution/sign = locate() in src
if(sign)
usr.put_in_hands(sign)
to_chat(usr, "<span class='notice'>You take \a [sign] from [src].</span>")
signs--
if(!signs)
nullTguiIcon("signs")
else
to_chat(usr, "<span class='notice'>[src] doesn't have any signs left.</span>")
if("bucket")
if(mybucket)
mybucket.forceMove(get_turf(usr))
to_chat(usr, "<span class='notice'>You unmount [mybucket] from [src].</span>")
mybucket = null
nullTguiIcon("mybucket")
else
to_chat(usr, "<span class='notice'>((Drag and drop a mop bucket onto [src] to equip it.))</span>")
return FALSE
else
return FALSE
update_icon()
updateUsrDialog()
return TRUE
/obj/structure/janitorialcart/update_icon()
overlays.Cut()
@@ -229,11 +305,6 @@ GLOBAL_LIST_BOILERPLATE(all_janitorial_carts, /obj/structure/janitorialcart)
if(signs)
overlays += "cart_sign[signs]"
//This is called if the cart is caught in an explosion, or destroyed by weapon fire
/obj/structure/janitorialcart/proc/spill(var/chance = 100)
var/turf/dropspot = get_turf(src)
@@ -275,6 +346,7 @@ GLOBAL_LIST_BOILERPLATE(all_janitorial_carts, /obj/structure/janitorialcart)
mybag = null
update_icon()
clearTguiIcons()
+1 -1
View File
@@ -172,7 +172,7 @@ obj/structure/safe/ex_act(severity)
icon_state = "floorsafe"
density = 0
level = 1 //underfloor
plane = TURF_PLANE
plane = PLATING_PLANE
layer = ABOVE_UTILITY
/obj/structure/safe/floor/Initialize()
@@ -67,7 +67,7 @@
if(!UWC)
return
var/datum/category_item/underwear/selected_underwear = input(H, "Choose underwear:", "Choose underwear", H.all_underwear[UWC.name]) as null|anything in UWC.items
if(selected_underwear && CanUseTopic(H, default_state))
if(selected_underwear && CanUseTopic(H, GLOB.tgui_default_state))
H.all_underwear[UWC.name] = selected_underwear
H.hide_underwear[UWC.name] = FALSE
. = TRUE
+2
View File
@@ -36,6 +36,8 @@
continue
if(!SM.Adjacent(user) || !SM.Adjacent(target)) // Cleaving only hits mobs near the target mob and user.
continue
if(!attack_can_reach(user, SM, 1))
continue
if(resolve_attackby(SM, user, attack_modifier = 0.5)) // Hit them with the weapon. This won't cause recursive cleaving due to the cleaving variable being set to true.
hit_mobs++