mirror of
https://github.com/CHOMPstation/CHOMPstation.git
synced 2026-08-30 07:26:39 +01:00
Merge branch 'master' of https://github.com/PolarisSS13/Polaris into Slime_Rework_3
# Conflicts: # code/game/objects/items/devices/multitool.dm
This commit is contained in:
@@ -163,6 +163,7 @@ var/global/list/obj/item/device/pda/PDAs = list()
|
||||
|
||||
/obj/item/device/pda/shaftminer
|
||||
icon_state = "pda-miner"
|
||||
default_cartridge = /obj/item/weapon/cartridge/miner
|
||||
|
||||
/obj/item/device/pda/syndicate
|
||||
default_cartridge = /obj/item/weapon/cartridge/syndicate
|
||||
@@ -172,6 +173,7 @@ var/global/list/obj/item/device/pda/PDAs = list()
|
||||
hidden = 1
|
||||
|
||||
/obj/item/device/pda/chaplain
|
||||
default_cartridge = /obj/item/weapon/cartridge/service
|
||||
icon_state = "pda-holy"
|
||||
ttone = "holy"
|
||||
|
||||
@@ -181,13 +183,15 @@ var/global/list/obj/item/device/pda/PDAs = list()
|
||||
ttone = "..."
|
||||
|
||||
/obj/item/device/pda/botanist
|
||||
//default_cartridge = /obj/item/weapon/cartridge/botanist
|
||||
default_cartridge = /obj/item/weapon/cartridge/service
|
||||
icon_state = "pda-hydro"
|
||||
|
||||
/obj/item/device/pda/roboticist
|
||||
default_cartridge = /obj/item/weapon/cartridge/signal/science
|
||||
icon_state = "pda-robot"
|
||||
|
||||
/obj/item/device/pda/librarian
|
||||
default_cartridge = /obj/item/weapon/cartridge/service
|
||||
icon_state = "pda-libb"
|
||||
desc = "A portable microcomputer by Thinktronic Systems, LTD. This is model is a WGW-11 series e-reader."
|
||||
note = "Congratulations, your station has chosen the Thinktronic 5290 WGW-11 Series E-reader and Personal Data Assistant!"
|
||||
@@ -200,9 +204,11 @@ var/global/list/obj/item/device/pda/PDAs = list()
|
||||
note = "Congratulations, you have chosen the Thinktronic 5230 Personal Data Assistant Deluxe Special Max Turbo Limited Edition!"
|
||||
|
||||
/obj/item/device/pda/chef
|
||||
default_cartridge = /obj/item/weapon/cartridge/service
|
||||
icon_state = "pda-chef"
|
||||
|
||||
/obj/item/device/pda/bar
|
||||
default_cartridge = /obj/item/weapon/cartridge/service
|
||||
icon_state = "pda-bar"
|
||||
|
||||
/obj/item/device/pda/atmos
|
||||
@@ -304,6 +310,99 @@ var/global/list/obj/item/device/pda/PDAs = list()
|
||||
ttone = "assist"
|
||||
|
||||
|
||||
// Used for the PDA multicaster, which mirrors messages sent to it to a specific department,
|
||||
/obj/item/device/pda/multicaster
|
||||
ownjob = "Relay"
|
||||
icon_state = "NONE"
|
||||
ttone = "data"
|
||||
detonate = 0
|
||||
news_silent = 1
|
||||
var/list/cartridges_to_send_to = list()
|
||||
|
||||
// This is what actually mirrors the message,
|
||||
/obj/item/device/pda/multicaster/new_message(var/sending_unit, var/sender, var/sender_job, var/message)
|
||||
if(sender)
|
||||
var/list/targets = list()
|
||||
for(var/obj/item/device/pda/pda in PDAs)
|
||||
if(pda.cartridge && pda.owner && is_type_in_list(pda.cartridge, cartridges_to_send_to))
|
||||
targets |= pda
|
||||
if(targets.len)
|
||||
for(var/obj/item/device/pda/target in targets)
|
||||
create_message(target, sender, sender_job, message)
|
||||
|
||||
// This has so much copypasta,
|
||||
/obj/item/device/pda/multicaster/create_message(var/obj/item/device/pda/P, var/original_sender, var/original_job, var/t)
|
||||
t = sanitize(t, MAX_MESSAGE_LEN, 0)
|
||||
t = replace_characters(t, list(""" = "\""))
|
||||
if (!t || !istype(P))
|
||||
return
|
||||
|
||||
if (isnull(P)||P.toff || toff)
|
||||
return
|
||||
|
||||
last_text = world.time
|
||||
var/datum/reception/reception = get_reception(src, P, t)
|
||||
t = reception.message
|
||||
|
||||
if(reception.message_server && (reception.telecomms_reception & TELECOMMS_RECEPTION_SENDER)) // only send the message if it's stable,
|
||||
if(reception.telecomms_reception & TELECOMMS_RECEPTION_RECEIVER == 0) // Does our recipient have a broadcaster on their level?,
|
||||
return
|
||||
var/send_result = reception.message_server.send_pda_message("[P.owner]","[owner]","[t]")
|
||||
if (send_result)
|
||||
return
|
||||
|
||||
P.tnote.Add(list(list("sent" = 0, "owner" = "[owner]", "job" = "[ownjob]", "message" = "[t]", "target" = "\ref[src]")))
|
||||
|
||||
if(!P.conversations.Find("\ref[src]"))
|
||||
P.conversations.Add("\ref[src]")
|
||||
|
||||
P.new_message(src, "[original_sender] \[Relayed\]", original_job, t, 0)
|
||||
|
||||
else
|
||||
return
|
||||
|
||||
/obj/item/device/pda/multicaster/command/New()
|
||||
..()
|
||||
owner = "Command Department"
|
||||
name = "Command Department (Relay)"
|
||||
cartridges_to_send_to = command_cartridges
|
||||
|
||||
/obj/item/device/pda/multicaster/security/New()
|
||||
..()
|
||||
owner = "Security Department"
|
||||
name = "Security Department (Relay)"
|
||||
cartridges_to_send_to = security_cartridges
|
||||
|
||||
/obj/item/device/pda/multicaster/engineering/New()
|
||||
..()
|
||||
owner = "Engineering Department"
|
||||
name = "Engineering Department (Relay)"
|
||||
cartridges_to_send_to = engineering_cartridges
|
||||
|
||||
/obj/item/device/pda/multicaster/medical/New()
|
||||
..()
|
||||
owner = "Medical Department"
|
||||
name = "Medical Department (Relay)"
|
||||
cartridges_to_send_to = medical_cartridges
|
||||
|
||||
/obj/item/device/pda/multicaster/research/New()
|
||||
..()
|
||||
owner = "Research Department"
|
||||
name = "Research Department (Relay)"
|
||||
cartridges_to_send_to = research_cartridges
|
||||
|
||||
/obj/item/device/pda/multicaster/cargo/New()
|
||||
..()
|
||||
owner = "Cargo Department"
|
||||
name = "Cargo Department (Relay)"
|
||||
cartridges_to_send_to = cargo_cartridges
|
||||
|
||||
/obj/item/device/pda/multicaster/civilian/New()
|
||||
..()
|
||||
owner = "Civilian Services Department"
|
||||
name = "Civilian Services Department (Relay)"
|
||||
cartridges_to_send_to = civilian_cartridges
|
||||
|
||||
/*
|
||||
* The Actual PDA
|
||||
*/
|
||||
@@ -932,7 +1031,7 @@ var/global/list/obj/item/device/pda/PDAs = list()
|
||||
message += "Your [P] bleeps loudly."
|
||||
j = prob(10)
|
||||
|
||||
if(j) //This kills the PDA
|
||||
if(j && detonate) //This kills the PDA
|
||||
qdel(P)
|
||||
if(message)
|
||||
message += "It melts in a puddle of plastic."
|
||||
@@ -1046,8 +1145,8 @@ var/global/list/obj/item/device/pda/PDAs = list()
|
||||
/obj/item/device/pda/proc/new_message_from_pda(var/obj/item/device/pda/sending_device, var/message)
|
||||
new_message(sending_device, sending_device.owner, sending_device.ownjob, message)
|
||||
|
||||
/obj/item/device/pda/proc/new_message(var/sending_unit, var/sender, var/sender_job, var/message)
|
||||
var/reception_message = "\icon[src] <b>Message from [sender] ([sender_job]), </b>\"[message]\" (<a href='byond://?src=\ref[src];choice=Message;notap=[istype(loc, /mob/living/silicon)];skiprefresh=1;target=\ref[sending_unit]'>Reply</a>)"
|
||||
/obj/item/device/pda/proc/new_message(var/sending_unit, var/sender, var/sender_job, var/message, var/reply = 1)
|
||||
var/reception_message = "\icon[src] <b>Message from [sender] ([sender_job]), </b>\"[message]\" ([reply ? "<a href='byond://?src=\ref[src];choice=Message;notap=[istype(loc, /mob/living/silicon)];skiprefresh=1;target=\ref[sending_unit]'>Reply</a>" : "Unable to Reply"])"
|
||||
new_info(message_silent, ttone, reception_message)
|
||||
|
||||
log_pda("[usr] (PDA: [sending_unit]) sent \"[message]\" to [name]")
|
||||
|
||||
@@ -1,3 +1,48 @@
|
||||
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/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."
|
||||
@@ -98,6 +143,10 @@
|
||||
access_flora = 1
|
||||
*/
|
||||
|
||||
/obj/item/weapon/cartridge/service
|
||||
name = "\improper Serv-U Pro"
|
||||
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."
|
||||
@@ -124,6 +173,11 @@
|
||||
icon_state = "cart-q"
|
||||
access_quartermaster = 1
|
||||
|
||||
/obj/item/weapon/cartridge/miner
|
||||
name = "\improper Drill-Jockey 4.5"
|
||||
desc = "It's covered in some sort of sand."
|
||||
icon_state = "cart-q"
|
||||
|
||||
/obj/item/weapon/cartridge/head
|
||||
name = "\improper Easy-Record DELUXE"
|
||||
icon_state = "cart-h"
|
||||
|
||||
@@ -20,13 +20,32 @@ var/global/list/obj/item/device/communicator/all_communicators = list()
|
||||
var/list/voice_mobs = list()
|
||||
var/list/voice_requests = list()
|
||||
var/list/voice_invites = list()
|
||||
var/selected_tab = 1 //1 equals dialing, 2 equals reviewing requests/invites.
|
||||
|
||||
var/list/im_contacts = list()
|
||||
var/list/im_list = 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/cartridge/cartridge = null //current cartridge
|
||||
var/list/modules = list(
|
||||
list("module" = "Phone", "icon" = "phone64", "number" = 2),
|
||||
list("module" = "Contacts", "icon" = "person64", "number" = 3),
|
||||
list("module" = "Messaging", "icon" = "comment64", "number" = 4),
|
||||
list("module" = "Note", "icon" = "note64", "number" = 5),
|
||||
list("module" = "Settings", "icon" = "gear64", "number" = 6)
|
||||
) //list("module" = "Name of Module", "icon" = "icon name64", "number" = "what tab is the module")
|
||||
|
||||
var/selected_tab = 1
|
||||
var/owner = ""
|
||||
var/occupation = ""
|
||||
var/alert_called = 0
|
||||
var/obj/machinery/exonet_node/node = null //Reference to the Exonet node, to avoid having to look it up so often.
|
||||
|
||||
var/target_address = ""
|
||||
var/target_address_name = ""
|
||||
var/network_visibility = 1
|
||||
var/ringer = 1
|
||||
var/list/known_devices = list()
|
||||
var/datum/exonet_protocol/exonet = null
|
||||
var/list/communicating = list()
|
||||
@@ -151,6 +170,24 @@ var/global/list/obj/item/device/communicator/all_communicators = list()
|
||||
if(!node || !node.on || !node.allow_external_communicators)
|
||||
close_connection(reason = "Connection timed out")
|
||||
|
||||
// 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.
|
||||
/obj/item/device/communicator/attackby(obj/item/C as obj, mob/user as mob)
|
||||
if(istype(C, /obj/item/weapon/card/id))
|
||||
var/obj/item/weapon/card/id/idcard = C
|
||||
if(!idcard.registered_name || !idcard.assignment)
|
||||
user << "<span class='notice'>\The [src] rejects the ID.</span>"
|
||||
return
|
||||
if(!owner)
|
||||
user << "<span class='notice'>\The [src] rejects the ID.</span>"
|
||||
return
|
||||
if(owner == idcard.registered_name)
|
||||
occupation = idcard.assignment
|
||||
user << "<span class='notice'>Occupation updated.</span>"
|
||||
return
|
||||
else return
|
||||
|
||||
// Proc: attack_self()
|
||||
// Parameters: 1 (user - the mob that clicked the device in their hand)
|
||||
// Description: Makes an exonet datum if one does not exist, allocates an address for it, maintains the lists of all devies, clears the alert icon, and
|
||||
@@ -205,6 +242,11 @@ var/global/list/obj/item/device/communicator/all_communicators = list()
|
||||
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/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)
|
||||
@@ -243,18 +285,38 @@ var/global/list/obj/item/device/communicator/all_communicators = list()
|
||||
for(var/obj/item/device/communicator/comm in communicating)
|
||||
connected_communicators[++connected_communicators.len] = list("name" = sanitize(comm.name), "true_name" = sanitize(comm.name))
|
||||
|
||||
//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)
|
||||
|
||||
//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"])
|
||||
|
||||
//Modules for homescreen.
|
||||
for(var/list/R in modules)
|
||||
modules_ui[++modules_ui.len] = R
|
||||
|
||||
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["imContacts"] = im_contacts_ui
|
||||
data["imList"] = im_list_ui
|
||||
data["time"] = worldtime2text()
|
||||
data["ring"] = ringer
|
||||
data["homeScreen"] = modules_ui
|
||||
data["note"] = note // current notes
|
||||
|
||||
// update the ui if it exists, returns null if no ui is passed/found
|
||||
ui = nanomanager.try_update_ui(user, src, ui_key, ui, data, force_open)
|
||||
@@ -284,6 +346,9 @@ var/global/list/obj/item/device/communicator/all_communicators = list()
|
||||
if(href_list["toggle_visibility"])
|
||||
network_visibility = !network_visibility
|
||||
|
||||
if(href_list["toggle_ringer"])
|
||||
ringer = !ringer
|
||||
|
||||
if(href_list["add_hex"])
|
||||
var/hex = href_list["add_hex"]
|
||||
add_to_EPv2(hex)
|
||||
@@ -304,6 +369,16 @@ var/global/list/obj/item/device/communicator/all_communicators = list()
|
||||
var/their_address = href_list["dial"]
|
||||
exonet.send_message(their_address, "voice")
|
||||
|
||||
if(href_list["message"])
|
||||
if(!get_connection_to_tcomms())
|
||||
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))
|
||||
|
||||
if(href_list["disconnect"])
|
||||
var/name_to_disconnect = href_list["disconnect"]
|
||||
for(var/mob/living/voice/V in contents)
|
||||
@@ -316,6 +391,9 @@ var/global/list/obj/item/device/communicator/all_communicators = list()
|
||||
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.")
|
||||
@@ -325,13 +403,25 @@ var/global/list/obj/item/device/communicator/all_communicators = list()
|
||||
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
|
||||
|
||||
nanomanager.update_uis(src)
|
||||
add_fingerprint(usr)
|
||||
|
||||
// Proc: receive_exonet_message()
|
||||
// Parameters: 3 (origin atom - the source of the message's holder, origin_address - where the message came from, message - the message received)
|
||||
// Description: Handles voice requests and invite messages originating from both real communicators and ghosts. Also includes a ping response.
|
||||
/obj/item/device/communicator/receive_exonet_message(var/atom/origin_atom, origin_address, message)
|
||||
// Parameters: 4 (origin atom - the source of the message's holder, origin_address - where the message came from, message - the message received,
|
||||
// text - message text to send if message is of type "text")
|
||||
// Description: Handles voice requests and invite messages originating from both real communicators and ghosts. Also includes a ping response and IM function.
|
||||
/obj/item/device/communicator/receive_exonet_message(var/atom/origin_atom, origin_address, message, text)
|
||||
if(message == "voice")
|
||||
if(isobserver(origin_atom) || istype(origin_atom, /obj/item/device/communicator))
|
||||
if(origin_atom in voice_invites)
|
||||
@@ -349,6 +439,9 @@ var/global/list/obj/item/device/communicator/all_communicators = list()
|
||||
var/random = rand(200,350)
|
||||
random = random / 10
|
||||
exonet.send_message(origin_address, "64 bytes received from [exonet.address] ecmp_seq=1 ttl=51 time=[random] ms")
|
||||
if(message == "text")
|
||||
request_im(origin_atom, origin_address, text)
|
||||
return
|
||||
|
||||
// Proc: receive_exonet_message()
|
||||
// Parameters: 3 (origin atom - the source of the message's holder, origin_address - where the message came from, message - the message received)
|
||||
@@ -368,6 +461,8 @@ var/global/list/obj/item/device/communicator/all_communicators = list()
|
||||
var/random = rand(450,700)
|
||||
random = random / 10
|
||||
exonet.send_message(origin_address, "64 bytes received from [exonet.address] ecmp_seq=1 ttl=51 time=[random] ms")
|
||||
if(message == "text") //Ghosts don't get texting yet. Mostly for spam prevention by ghosts but also due to ui requirements not sorted out yet.
|
||||
return
|
||||
|
||||
// Proc: register_device()
|
||||
// Parameters: 1 (user - the person to use their name for)
|
||||
@@ -514,9 +609,10 @@ var/global/list/obj/item/device/communicator/all_communicators = list()
|
||||
|
||||
voice_requests |= candidate
|
||||
|
||||
playsound(loc, 'sound/machines/twobeep.ogg', 50, 1)
|
||||
for (var/mob/O in hearers(2, loc))
|
||||
O.show_message(text("\icon[src] *beep*"))
|
||||
if(ringer)
|
||||
playsound(loc, 'sound/machines/twobeep.ogg', 50, 1)
|
||||
for (var/mob/O in hearers(2, loc))
|
||||
O.show_message(text("\icon[src] *beep*"))
|
||||
|
||||
alert_called = 1
|
||||
update_icon()
|
||||
@@ -529,6 +625,42 @@ var/global/list/obj/item/device/communicator/all_communicators = list()
|
||||
if(L)
|
||||
L << "<span class='notice'>\icon[src] Communications request from [who].</span>"
|
||||
|
||||
// Proc: request_im()
|
||||
// Parameters: 3 (candidate - the communicator wanting to message the device, origin_address - the address of the sender, text - the message)
|
||||
// Description: Response to a communicator trying to message the device.
|
||||
// Adds them to the list of people that have messaged this device and adds the message to the message list.
|
||||
/obj/item/device/communicator/proc/request_im(var/atom/candidate, var/origin_address, var/text)
|
||||
var/who = null
|
||||
if(isobserver(candidate))
|
||||
return
|
||||
else if(istype(candidate, /obj/item/device/communicator))
|
||||
var/obj/item/device/communicator/comm = candidate
|
||||
who = comm.owner
|
||||
comm.im_contacts |= src
|
||||
im_list += list(list("address" = origin_address, "to_address" = exonet.address, "im" = text))
|
||||
else return
|
||||
|
||||
im_contacts |= candidate
|
||||
|
||||
if(!who)
|
||||
return
|
||||
|
||||
if(ringer)
|
||||
playsound(loc, 'sound/machines/twobeep.ogg', 50, 1)
|
||||
for (var/mob/O in hearers(2, loc))
|
||||
O.show_message(text("\icon[src] *beep*"))
|
||||
|
||||
alert_called = 1
|
||||
update_icon()
|
||||
|
||||
//Search for holder of the device.
|
||||
var/mob/living/L = null
|
||||
if(loc && isliving(loc))
|
||||
L = loc
|
||||
|
||||
if(L)
|
||||
L << "<span class='notice'>\icon[src] Message from [who].</span>"
|
||||
|
||||
// Proc: Destroy()
|
||||
// Parameters: None
|
||||
// Description: Deletes all the voice mobs, disconnects all linked communicators, and cuts lists to allow successful qdel()
|
||||
|
||||
@@ -60,6 +60,10 @@
|
||||
else //can only use it 5 times a minute
|
||||
user << "<span class='warning'>*click* *click*</span>"
|
||||
return
|
||||
|
||||
user.setClickCooldown(DEFAULT_ATTACK_COOLDOWN)
|
||||
user.do_attack_animation(M)
|
||||
|
||||
playsound(src.loc, 'sound/weapons/flash.ogg', 100, 1)
|
||||
var/flashfail = 0
|
||||
|
||||
@@ -112,6 +116,7 @@
|
||||
|
||||
/obj/item/device/flash/attack_self(mob/living/carbon/user as mob, flag = 0, emp = 0)
|
||||
if(!user || !clown_check(user)) return
|
||||
|
||||
if(broken)
|
||||
user.show_message("<span class='warning'>The [src.name] is broken</span>", 2)
|
||||
return
|
||||
@@ -131,6 +136,7 @@
|
||||
else //can only use it 5 times a minute
|
||||
user.show_message("<span class='warning'>*click* *click*</span>", 2)
|
||||
return
|
||||
user.setClickCooldown(DEFAULT_ATTACK_COOLDOWN)
|
||||
playsound(src.loc, 'sound/weapons/flash.ogg', 100, 1)
|
||||
flick("flash2", src)
|
||||
if(user && isrobot(user))
|
||||
|
||||
@@ -0,0 +1,100 @@
|
||||
/obj/item/device/multitool/hacktool
|
||||
var/is_hacking = 0
|
||||
var/max_known_targets
|
||||
|
||||
var/in_hack_mode = 0
|
||||
var/list/known_targets
|
||||
var/list/supported_types
|
||||
var/datum/topic_state/default/must_hack/hack_state
|
||||
|
||||
/obj/item/device/multitool/hacktool/New()
|
||||
..()
|
||||
known_targets = list()
|
||||
max_known_targets = 5 + rand(1,3)
|
||||
supported_types = list(/obj/machinery/door/airlock)
|
||||
hack_state = new(src)
|
||||
|
||||
/obj/item/device/multitool/hacktool/Destroy()
|
||||
for(var/T in known_targets)
|
||||
var/atom/target = T
|
||||
target.unregister(OBSERVER_EVENT_DESTROY, src)
|
||||
known_targets.Cut()
|
||||
qdel(hack_state)
|
||||
hack_state = null
|
||||
return ..()
|
||||
|
||||
/obj/item/device/multitool/hacktool/attackby(var/obj/W, var/mob/user)
|
||||
if(isscrewdriver(W))
|
||||
in_hack_mode = !in_hack_mode
|
||||
playsound(src.loc, 'sound/items/Screwdriver.ogg', 50, 1)
|
||||
else
|
||||
..()
|
||||
|
||||
/obj/item/device/multitool/hacktool/resolve_attackby(atom/A, mob/user)
|
||||
sanity_check()
|
||||
|
||||
if(!in_hack_mode)
|
||||
return ..()
|
||||
|
||||
if(!attempt_hack(user, A))
|
||||
return 0
|
||||
|
||||
A.ui_interact(user, state = hack_state)
|
||||
return 1
|
||||
|
||||
/obj/item/device/multitool/hacktool/proc/attempt_hack(var/mob/user, var/atom/target)
|
||||
if(is_hacking)
|
||||
user << "<span class='warning'>You are already hacking!</span>"
|
||||
return 0
|
||||
if(!is_type_in_list(target, supported_types))
|
||||
user << "\icon[src] <span class='warning'>Unable to hack this target!</span>"
|
||||
return 0
|
||||
var/found = known_targets.Find(target)
|
||||
if(found)
|
||||
known_targets.Swap(1, found) // Move the last hacked item first
|
||||
return 1
|
||||
|
||||
user << "<span class='notice'>You begin hacking \the [target]...</span>"
|
||||
is_hacking = 1
|
||||
// On average hackin takes ~30 seconds. Fairly small random span to avoid people simply aborting and trying again
|
||||
var/hack_result = do_after(user, (20 SECONDS + rand(0, 10 SECONDS) + rand(0, 10 SECONDS)))
|
||||
is_hacking = 0
|
||||
|
||||
if(hack_result && in_hack_mode)
|
||||
user << "<span class='notice'>Your hacking attempt was succesful!</span>"
|
||||
playsound(src.loc, 'sound/piano/A#6.ogg', 75)
|
||||
else
|
||||
user << "<span class='warning'>Your hacking attempt failed!</span>"
|
||||
return 0
|
||||
|
||||
known_targets.Insert(1, target) // Insert the newly hacked target first,
|
||||
target.register(OBSERVER_EVENT_DESTROY, src, /obj/item/device/multitool/hacktool/proc/on_target_destroy)
|
||||
return 1
|
||||
|
||||
/obj/item/device/multitool/hacktool/proc/sanity_check()
|
||||
if(max_known_targets < 1) max_known_targets = 1
|
||||
// Cut away the oldest items if the capacity has been reached
|
||||
if(known_targets.len > max_known_targets)
|
||||
for(var/i = (max_known_targets + 1) to known_targets.len)
|
||||
var/atom/A = known_targets[i]
|
||||
A.unregister(OBSERVER_EVENT_DESTROY, src)
|
||||
known_targets.Cut(max_known_targets + 1)
|
||||
|
||||
/obj/item/device/multitool/hacktool/proc/on_target_destroy(var/target)
|
||||
known_targets -= target
|
||||
|
||||
/datum/topic_state/default/must_hack
|
||||
var/obj/item/device/multitool/hacktool/hacktool
|
||||
|
||||
/datum/topic_state/default/must_hack/New(var/hacktool)
|
||||
src.hacktool = hacktool
|
||||
..()
|
||||
|
||||
/datum/topic_state/default/must_hack/Destroy()
|
||||
hacktool = null
|
||||
return ..()
|
||||
|
||||
/datum/topic_state/default/must_hack/can_use_topic(var/src_object, var/mob/user)
|
||||
if(!hacktool || !hacktool.in_hack_mode || !(src_object in hacktool.known_targets))
|
||||
return STATUS_CLOSE
|
||||
return ..()
|
||||
@@ -1,11 +1,3 @@
|
||||
//This could either be split into the proper DM files or placed somewhere else all together, but it'll do for now -Nodrak
|
||||
|
||||
/*
|
||||
|
||||
A list of items and costs is stored under the datum of every game mode, alongside the number of crystals, and the welcoming message.
|
||||
|
||||
*/
|
||||
|
||||
/obj/item/device/uplink
|
||||
var/welcome = "Welcome, Operative" // Welcoming menu message
|
||||
var/uses // Numbers of crystals
|
||||
@@ -18,6 +10,10 @@ A list of items and costs is stored under the datum of every game mode, alongsid
|
||||
var/list/purchase_log = new
|
||||
var/datum/mind/uplink_owner = null
|
||||
var/used_TC = 0
|
||||
var/offer_time = 15 MINUTES //The time increment per discount offered
|
||||
var/next_offer_time //The time a discount will next be offered
|
||||
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
|
||||
@@ -28,10 +24,15 @@ A list of items and costs is stored under the datum of every game mode, alongsid
|
||||
purchase_log = list()
|
||||
world_uplinks += src
|
||||
uses = owner.tcrystals
|
||||
processing_objects += src
|
||||
|
||||
/obj/item/device/uplink/Destroy()
|
||||
world_uplinks -= src
|
||||
..()
|
||||
processing_objects -= src
|
||||
return ..()
|
||||
|
||||
/obj/item/device/uplink/get_item_cost(var/item_type, var/item_cost)
|
||||
return (discount_item && (item_type == discount_item)) ? max(1, round(item_cost*discount_amount)) : item_cost
|
||||
|
||||
// HIDDEN UPLINK - Can be stored in anything but the host item has to have a trigger for it.
|
||||
/* How to create an uplink in 3 easy steps!
|
||||
@@ -52,7 +53,6 @@ A list of items and costs is stored under the datum of every game mode, alongsid
|
||||
var/datum/uplink_category/category = 0 // The current category we are in
|
||||
var/exploit_id // Id of the current exploit record we are viewing
|
||||
|
||||
|
||||
// The hidden uplink MUST be inside an obj/item's contents.
|
||||
/obj/item/device/uplink/hidden/New()
|
||||
spawn(2)
|
||||
@@ -62,6 +62,14 @@ A list of items and costs is stored under the datum of every game mode, alongsid
|
||||
nanoui_data = list()
|
||||
update_nano_data()
|
||||
|
||||
/obj/item/device/uplink/hidden/process()
|
||||
if(world.time > next_offer_time)
|
||||
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)
|
||||
next_offer_time = world.time + offer_time
|
||||
update_nano_data()
|
||||
nanomanager.update_uis(src)
|
||||
|
||||
// Toggles the uplink on and off. Normally this will bypass the item's normal functions and go to the uplink menu, if activated.
|
||||
/obj/item/device/uplink/hidden/proc/toggle()
|
||||
active = !active
|
||||
@@ -107,6 +115,11 @@ A list of items and costs is stored under the datum of every game mode, alongsid
|
||||
/obj/item/device/uplink/hidden/interact(mob/user)
|
||||
ui_interact(user)
|
||||
|
||||
/obj/item/device/uplink/hidden/CanUseTopic()
|
||||
if(!active)
|
||||
return STATUS_CLOSE
|
||||
return ..()
|
||||
|
||||
// The purchasing code.
|
||||
/obj/item/device/uplink/hidden/Topic(href, href_list)
|
||||
if(..())
|
||||
@@ -139,11 +152,14 @@ A list of items and costs is stored under the datum of every game mode, alongsid
|
||||
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"] = worldtime2text(next_offer_time)
|
||||
else if(nanoui_menu == 1)
|
||||
var/items[0]
|
||||
for(var/datum/uplink_item/item in category.items)
|
||||
if(item.can_view(src))
|
||||
var/cost = item.cost(uses)
|
||||
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
|
||||
|
||||
@@ -1,49 +0,0 @@
|
||||
/datum/uplink_category
|
||||
var/name = ""
|
||||
var/list/datum/uplink_item/items
|
||||
|
||||
/datum/uplink_category/New()
|
||||
..()
|
||||
items = list()
|
||||
|
||||
/datum/uplink_category/proc/can_view(obj/item/device/uplink/U)
|
||||
for(var/datum/uplink_item/item in items)
|
||||
if(item.can_view(U))
|
||||
return 1
|
||||
return 0
|
||||
|
||||
/datum/uplink_category/ammunition
|
||||
name = "Ammunition"
|
||||
|
||||
/datum/uplink_category/grenades
|
||||
name = "Grenades and Thrown Objects"
|
||||
|
||||
/datum/uplink_category/visible_weapons
|
||||
name = "Highly Visible and Dangerous Weapons"
|
||||
|
||||
/datum/uplink_category/stealthy_weapons
|
||||
name = "Stealthy and Inconspicuous Weapons"
|
||||
|
||||
/datum/uplink_category/stealth_items
|
||||
name = "Stealth and Camouflage Items"
|
||||
|
||||
/datum/uplink_category/armor
|
||||
name = "Armor"
|
||||
|
||||
/datum/uplink_category/tools
|
||||
name = "Devices and Tools"
|
||||
|
||||
/datum/uplink_category/implants
|
||||
name = "Implants"
|
||||
|
||||
/datum/uplink_category/medical
|
||||
name = "Medical"
|
||||
|
||||
/datum/uplink_category/hardsuit_modules
|
||||
name = "Hardsuit Modules"
|
||||
|
||||
/datum/uplink_category/services
|
||||
name = "Services"
|
||||
|
||||
/datum/uplink_category/badassery
|
||||
name = "Badassery"
|
||||
@@ -1,774 +0,0 @@
|
||||
var/datum/uplink/uplink = new()
|
||||
|
||||
/datum/uplink
|
||||
var/list/items_assoc
|
||||
var/list/datum/uplink_item/items
|
||||
var/list/datum/uplink_category/categories
|
||||
|
||||
/datum/uplink/New()
|
||||
items_assoc = list()
|
||||
items = init_subtypes(/datum/uplink_item)
|
||||
categories = init_subtypes(/datum/uplink_category)
|
||||
categories = dd_sortedObjectList(categories)
|
||||
|
||||
for(var/datum/uplink_item/item in items)
|
||||
if(!item.name)
|
||||
items -= item
|
||||
continue
|
||||
|
||||
items_assoc[item.type] = item
|
||||
|
||||
for(var/datum/uplink_category/category in categories)
|
||||
if(item.category == category.type)
|
||||
category.items += item
|
||||
|
||||
for(var/datum/uplink_category/category in categories)
|
||||
category.items = dd_sortedObjectList(category.items)
|
||||
|
||||
/datum/uplink_item
|
||||
var/name
|
||||
var/desc
|
||||
var/item_cost = 0
|
||||
var/datum/uplink_category/category // Item category
|
||||
var/list/datum/antagonist/antag_roles // Antag roles this item is displayed to. If empty, display to all.
|
||||
|
||||
/datum/uplink_item/item
|
||||
var/path = null
|
||||
|
||||
/datum/uplink_item/New()
|
||||
..()
|
||||
antag_roles = list()
|
||||
|
||||
|
||||
|
||||
/datum/uplink_item/proc/buy(var/obj/item/device/uplink/U, var/mob/user)
|
||||
var/extra_args = extra_args(user)
|
||||
if(!extra_args)
|
||||
return
|
||||
|
||||
if(!can_buy(U))
|
||||
return
|
||||
|
||||
var/cost = cost(U.uses)
|
||||
|
||||
var/goods = get_goods(U, get_turf(user), user, extra_args)
|
||||
if(!goods)
|
||||
return
|
||||
|
||||
purchase_log(U)
|
||||
user.mind.tcrystals -= cost
|
||||
U.used_TC += cost
|
||||
return goods
|
||||
|
||||
// Any additional arguments you wish to send to the get_goods
|
||||
/datum/uplink_item/proc/extra_args(var/mob/user)
|
||||
return 1
|
||||
|
||||
/datum/uplink_item/proc/can_buy(obj/item/device/uplink/U)
|
||||
if(cost(U.uses) > U.uses)
|
||||
return 0
|
||||
|
||||
return can_view(U)
|
||||
|
||||
/datum/uplink_item/proc/can_view(obj/item/device/uplink/U)
|
||||
// Making the assumption that if no uplink was supplied, then we don't care about antag roles
|
||||
if(!U || !antag_roles.len)
|
||||
return 1
|
||||
|
||||
// With no owner, there's no need to check antag status.
|
||||
if(!U.uplink_owner)
|
||||
return 0
|
||||
|
||||
for(var/antag_role in antag_roles)
|
||||
var/datum/antagonist/antag = all_antag_types[antag_role]
|
||||
if(antag.is_antagonist(U.uplink_owner))
|
||||
return 1
|
||||
return 0
|
||||
|
||||
/datum/uplink_item/proc/cost(var/telecrystals)
|
||||
return item_cost
|
||||
|
||||
/datum/uplink_item/proc/description()
|
||||
return desc
|
||||
|
||||
// get_goods does not necessarily return physical objects, it is simply a way to acquire the uplink item without paying
|
||||
/datum/uplink_item/proc/get_goods(var/obj/item/device/uplink/U, var/loc)
|
||||
return 0
|
||||
|
||||
/datum/uplink_item/proc/log_icon()
|
||||
return
|
||||
|
||||
/datum/uplink_item/proc/purchase_log(obj/item/device/uplink/U)
|
||||
feedback_add_details("traitor_uplink_items_bought", "[src]")
|
||||
log_and_message_admins("used \the [U.loc] to buy \a [src]")
|
||||
U.purchase_log[src] = U.purchase_log[src] + 1
|
||||
|
||||
datum/uplink_item/dd_SortValue()
|
||||
return cost(INFINITY)
|
||||
|
||||
/********************************
|
||||
* *
|
||||
* Physical Uplink Entries *
|
||||
* *
|
||||
********************************/
|
||||
/datum/uplink_item/item/buy(var/obj/item/device/uplink/U, var/mob/user)
|
||||
var/obj/item/I = ..()
|
||||
if(!I)
|
||||
return
|
||||
|
||||
if(istype(I, /list))
|
||||
var/list/L = I
|
||||
if(L.len) I = L[1]
|
||||
|
||||
if(istype(I) && ishuman(user))
|
||||
var/mob/living/carbon/human/A = user
|
||||
A.put_in_any_hand_if_possible(I)
|
||||
return I
|
||||
|
||||
/datum/uplink_item/item/get_goods(var/obj/item/device/uplink/U, var/loc)
|
||||
var/obj/item/I = new path(loc)
|
||||
return I
|
||||
|
||||
/datum/uplink_item/item/description()
|
||||
if(!desc)
|
||||
// Fallback description
|
||||
var/obj/temp = src.path
|
||||
desc = initial(temp.desc)
|
||||
return ..()
|
||||
|
||||
/datum/uplink_item/item/log_icon()
|
||||
var/obj/I = path
|
||||
return "\icon[I]"
|
||||
|
||||
/*************
|
||||
* Ammunition *
|
||||
*************/
|
||||
/datum/uplink_item/item/ammo
|
||||
item_cost = 2
|
||||
category = /datum/uplink_category/ammunition
|
||||
|
||||
/datum/uplink_item/item/ammo/a357
|
||||
name = ".357"
|
||||
path = /obj/item/ammo_magazine/a357
|
||||
|
||||
/datum/uplink_item/item/ammo/mc9mm
|
||||
name = "9mm"
|
||||
path = /obj/item/ammo_magazine/mc9mm
|
||||
|
||||
/datum/uplink_item/item/ammo/c45m
|
||||
name = ".45"
|
||||
path = /obj/item/ammo_magazine/c45m
|
||||
|
||||
/datum/uplink_item/item/ammo/darts
|
||||
name = "Darts"
|
||||
path = /obj/item/ammo_magazine/chemdart
|
||||
|
||||
/datum/uplink_item/item/ammo/sniperammo
|
||||
name = "14.5mm"
|
||||
path = /obj/item/weapon/storage/box/sniperammo
|
||||
|
||||
/datum/uplink_item/item/ammo/a556
|
||||
name = "5.56mm"
|
||||
path = /obj/item/ammo_magazine/a556
|
||||
|
||||
/datum/uplink_item/item/ammo/a556/ap
|
||||
name = "5.56mm AP"
|
||||
path = /obj/item/ammo_magazine/a556/ap
|
||||
|
||||
/datum/uplink_item/item/ammo/a10mm
|
||||
name = "10mm"
|
||||
path = /obj/item/ammo_magazine/a10mm
|
||||
|
||||
/datum/uplink_item/item/ammo/a762
|
||||
name = "7.62mm"
|
||||
path = /obj/item/ammo_magazine/a762
|
||||
|
||||
/datum/uplink_item/item/ammo/a762/ap
|
||||
name = "7.62mm AP"
|
||||
path = /obj/item/ammo_magazine/a762/ap
|
||||
|
||||
/datum/uplink_item/item/ammo/g12
|
||||
name = "12 gauge"
|
||||
path = /obj/item/ammo_magazine/g12
|
||||
|
||||
/datum/uplink_item/item/ammo/g12/beanbag
|
||||
name = "12 gauge beanbag"
|
||||
path = /obj/item/ammo_magazine/g12/beanbag
|
||||
item_cost = 1 // Discount due to it being LTL.
|
||||
|
||||
/datum/uplink_item/item/ammo/g12/pellet
|
||||
name = "12 gauge pellet"
|
||||
path = /obj/item/ammo_magazine/g12/pellet
|
||||
|
||||
/***************************************
|
||||
* Highly Visible and Dangerous Weapons *
|
||||
***************************************/
|
||||
/datum/uplink_item/item/visible_weapons
|
||||
category = /datum/uplink_category/visible_weapons
|
||||
|
||||
/datum/uplink_item/item/visible_weapons/energy_sword
|
||||
name = "Energy Sword"
|
||||
item_cost = 4
|
||||
path = /obj/item/weapon/melee/energy/sword
|
||||
|
||||
/datum/uplink_item/item/visible_weapons/dartgun
|
||||
name = "Dart Gun"
|
||||
item_cost = 5
|
||||
path = /obj/item/weapon/gun/projectile/dartgun
|
||||
|
||||
/datum/uplink_item/item/visible_weapons/crossbow
|
||||
name = "Energy Crossbow"
|
||||
item_cost = 5
|
||||
path = /obj/item/weapon/gun/energy/crossbow
|
||||
|
||||
/datum/uplink_item/item/visible_weapons/silenced_45
|
||||
name = "Silenced .45"
|
||||
item_cost = 5
|
||||
path = /obj/item/weapon/gun/projectile/silenced
|
||||
|
||||
/datum/uplink_item/item/visible_weapons/riggedlaser
|
||||
name = "Exosuit Rigged Laser"
|
||||
item_cost = 6
|
||||
path = /obj/item/mecha_parts/mecha_equipment/weapon/energy/riggedlaser
|
||||
|
||||
/datum/uplink_item/item/visible_weapons/revolver
|
||||
name = "Revolver"
|
||||
item_cost = 6
|
||||
path = /obj/item/weapon/gun/projectile/revolver
|
||||
|
||||
/datum/uplink_item/item/visible_weapons/heavysniper
|
||||
name = "Anti-materiel Rifle"
|
||||
item_cost = DEFAULT_TELECRYSTAL_AMOUNT
|
||||
path = /obj/item/weapon/gun/projectile/heavysniper
|
||||
|
||||
//These are for traitors (or other antags, perhaps) to have the option of purchasing some merc gear.
|
||||
/datum/uplink_item/item/visible_weapons/submachinegun
|
||||
name = "Submachine Gun"
|
||||
item_cost = 6
|
||||
path = /obj/item/weapon/gun/projectile/automatic/c20r
|
||||
|
||||
/datum/uplink_item/item/visible_weapons/assaultrifle
|
||||
name = "Assault Rifle"
|
||||
item_cost = 7
|
||||
path = /obj/item/weapon/gun/projectile/automatic/sts35
|
||||
|
||||
/datum/uplink_item/item/visible_weapons/combatshotgun
|
||||
name = "Combat Shotgun"
|
||||
item_cost = 7
|
||||
path = /obj/item/weapon/gun/projectile/shotgun/pump/combat
|
||||
|
||||
/datum/uplink_item/item/visible_weapons/egun
|
||||
name = "Energy Gun"
|
||||
item_cost = 5
|
||||
path = /obj/item/weapon/gun/energy/gun
|
||||
|
||||
/datum/uplink_item/item/visible_weapons/lasercannon
|
||||
name = "Laser Cannon"
|
||||
item_cost = 6
|
||||
path = /obj/item/weapon/gun/energy/lasercannon
|
||||
|
||||
/datum/uplink_item/item/visible_weapons/lasercarbine
|
||||
name = "Laser Carbine"
|
||||
item_cost = 7
|
||||
path = /obj/item/weapon/gun/energy/laser
|
||||
|
||||
/datum/uplink_item/item/visible_weapons/ionrifle
|
||||
name = "Ion Rifle"
|
||||
item_cost = 5
|
||||
path = /obj/item/weapon/gun/energy/ionrifle
|
||||
|
||||
/datum/uplink_item/item/visible_weapons/xray
|
||||
name = "Xray Gun"
|
||||
item_cost = 7
|
||||
path = /obj/item/weapon/gun/energy/xray
|
||||
|
||||
/*************************************
|
||||
* Stealthy and Inconspicuous Weapons *
|
||||
*************************************/
|
||||
/datum/uplink_item/item/stealthy_weapons
|
||||
category = /datum/uplink_category/stealthy_weapons
|
||||
|
||||
/datum/uplink_item/item/stealthy_weapons/soap
|
||||
name = "Subversive Soap"
|
||||
item_cost = 1
|
||||
path = /obj/item/weapon/soap/syndie
|
||||
|
||||
/datum/uplink_item/item/stealthy_weapons/concealed_cane
|
||||
name = "Concealed Cane Sword"
|
||||
item_cost = 1
|
||||
path = /obj/item/weapon/cane/concealed
|
||||
|
||||
/datum/uplink_item/item/stealthy_weapons/detomatix
|
||||
name = "Detomatix PDA Cartridge"
|
||||
item_cost = 3
|
||||
path = /obj/item/weapon/cartridge/syndicate
|
||||
|
||||
/datum/uplink_item/item/stealthy_weapons/parapen
|
||||
name = "Paralysis Pen"
|
||||
item_cost = 3
|
||||
path = /obj/item/weapon/pen/reagent/paralysis
|
||||
|
||||
/datum/uplink_item/item/stealthy_weapons/cigarette_kit
|
||||
name = "Cigarette Kit"
|
||||
item_cost = 3
|
||||
path = /obj/item/weapon/storage/box/syndie_kit/cigarette
|
||||
|
||||
/datum/uplink_item/item/stealthy_weapons/random_toxin
|
||||
name = "Random Toxin - Beaker"
|
||||
item_cost = 3
|
||||
path = /obj/item/weapon/storage/box/syndie_kit/toxin
|
||||
|
||||
/*******************************
|
||||
* Stealth and Camouflage Items *
|
||||
*******************************/
|
||||
/datum/uplink_item/item/stealth_items
|
||||
category = /datum/uplink_category/stealth_items
|
||||
|
||||
/datum/uplink_item/item/stealth_items/id
|
||||
name = "Agent ID card"
|
||||
item_cost = 2
|
||||
path = /obj/item/weapon/card/id/syndicate
|
||||
|
||||
/datum/uplink_item/item/stealth_items/syndigaloshes
|
||||
name = "No-Slip Shoes"
|
||||
item_cost = 2
|
||||
path = /obj/item/clothing/shoes/syndigaloshes
|
||||
|
||||
/datum/uplink_item/item/stealth_items/spy
|
||||
name = "Bug Kit"
|
||||
item_cost = 2
|
||||
path = /obj/item/weapon/storage/box/syndie_kit/spy
|
||||
|
||||
/datum/uplink_item/item/stealth_items/chameleon_kit
|
||||
name = "Chameleon Kit"
|
||||
item_cost = 3
|
||||
path = /obj/item/weapon/storage/box/syndie_kit/chameleon
|
||||
|
||||
/datum/uplink_item/item/stealth_items/chameleon_projector
|
||||
name = "Chameleon-Projector"
|
||||
item_cost = 4
|
||||
path = /obj/item/device/chameleon
|
||||
|
||||
/datum/uplink_item/item/stealth_items/chameleon_projector
|
||||
name = "Chameleon-Projector"
|
||||
item_cost = 4
|
||||
path = /obj/item/device/chameleon
|
||||
|
||||
/datum/uplink_item/item/stealth_items/voice
|
||||
name = "Voice Changer"
|
||||
item_cost = 4
|
||||
path = /obj/item/clothing/mask/gas/voice
|
||||
|
||||
/datum/uplink_item/item/stealth_items/camera_floppy
|
||||
name = "Camera Network Access - Floppy"
|
||||
item_cost = 6
|
||||
path = /obj/item/weapon/disk/file/cameras/syndicate
|
||||
|
||||
/********
|
||||
* Armor *
|
||||
********/
|
||||
/datum/uplink_item/item/armor
|
||||
category = /datum/uplink_category/armor
|
||||
|
||||
/datum/uplink_item/item/armor/combat
|
||||
name = "Combat Armor Set"
|
||||
item_cost = 5
|
||||
path = /obj/item/weapon/storage/box/syndie_kit/combat_armor
|
||||
|
||||
/datum/uplink_item/item/armor/heavy_vest
|
||||
name = "Heavy Armor Vest"
|
||||
item_cost = 4
|
||||
path = /obj/item/clothing/suit/storage/vest/heavy/merc
|
||||
|
||||
/********************
|
||||
* Devices and Tools *
|
||||
********************/
|
||||
/datum/uplink_item/item/tools
|
||||
category = /datum/uplink_category/tools
|
||||
|
||||
/datum/uplink_item/item/tools/toolbox
|
||||
name = "Fully Loaded Toolbox"
|
||||
item_cost = 1
|
||||
path = /obj/item/weapon/storage/toolbox/syndicate
|
||||
|
||||
/datum/uplink_item/item/tools/plastique
|
||||
name = "C-4 (Destroys walls)"
|
||||
item_cost = 2
|
||||
path = /obj/item/weapon/plastique
|
||||
|
||||
/datum/uplink_item/item/tools/encryptionkey_radio
|
||||
name = "Encrypted Radio Channel Key"
|
||||
item_cost = 2
|
||||
path = /obj/item/device/encryptionkey/syndicate
|
||||
|
||||
/datum/uplink_item/item/tools/encryptionkey_binary
|
||||
name = "Binary Translator Key"
|
||||
item_cost = 3
|
||||
path = /obj/item/device/encryptionkey/binary
|
||||
|
||||
/datum/uplink_item/item/tools/emag
|
||||
name = "Cryptographic Sequencer"
|
||||
item_cost = 3
|
||||
path = /obj/item/weapon/card/emag
|
||||
|
||||
/datum/uplink_item/item/tools/clerical
|
||||
name = "Morphic Clerical Kit"
|
||||
item_cost = 3
|
||||
path = /obj/item/weapon/storage/box/syndie_kit/clerical
|
||||
|
||||
/datum/uplink_item/item/tools/space_suit
|
||||
name = "Space Suit"
|
||||
item_cost = 3
|
||||
path = /obj/item/weapon/storage/box/syndie_kit/space
|
||||
|
||||
/datum/uplink_item/item/tools/thermal
|
||||
name = "Thermal Imaging Glasses"
|
||||
item_cost = 3
|
||||
path = /obj/item/clothing/glasses/thermal/syndi
|
||||
|
||||
/datum/uplink_item/item/tools/powersink
|
||||
name = "Powersink (DANGER!)"
|
||||
item_cost = 5
|
||||
path = /obj/item/device/powersink
|
||||
|
||||
/datum/uplink_item/item/tools/ai_module
|
||||
name = "Hacked AI Upload Module"
|
||||
item_cost = 7
|
||||
path = /obj/item/weapon/aiModule/syndicate
|
||||
|
||||
/datum/uplink_item/item/tools/supply_beacon
|
||||
name = "Hacked Supply Beacon (DANGER!)"
|
||||
item_cost = 7
|
||||
path = /obj/item/supply_beacon
|
||||
|
||||
/datum/uplink_item/item/tools/teleporter
|
||||
name = "Teleporter Circuit Board"
|
||||
item_cost = 20
|
||||
path = /obj/item/weapon/circuitboard/teleporter
|
||||
|
||||
/datum/uplink_item/item/tools/money
|
||||
name = "Operations Funding"
|
||||
item_cost = 3
|
||||
path = /obj/item/weapon/storage/secure/briefcase/money
|
||||
desc = "A briefcase with 10,000 untraceable thalers for funding your sneaky activities."
|
||||
|
||||
/datum/uplink_item/item/tools/crystal
|
||||
name = "Tradable Crystal"
|
||||
item_cost = 1
|
||||
path = /obj/item/device/telecrystal
|
||||
desc = "A telecrystal that can be transferred from one user to another. Be sure not to give it to just anyone."
|
||||
|
||||
/***********
|
||||
* Implants *
|
||||
***********/
|
||||
/datum/uplink_item/item/implants
|
||||
category = /datum/uplink_category/implants
|
||||
|
||||
/datum/uplink_item/item/implants/imp_freedom
|
||||
name = "Freedom Implant"
|
||||
item_cost = 3
|
||||
path = /obj/item/weapon/storage/box/syndie_kit/imp_freedom
|
||||
|
||||
/datum/uplink_item/item/implants/imp_compress
|
||||
name = "Compressed Matter Implant"
|
||||
item_cost = 4
|
||||
path = /obj/item/weapon/storage/box/syndie_kit/imp_compress
|
||||
|
||||
/datum/uplink_item/item/implants/imp_explosive
|
||||
name = "Explosive Implant (DANGER!)"
|
||||
item_cost = 6
|
||||
path = /obj/item/weapon/storage/box/syndie_kit/imp_explosive
|
||||
|
||||
/datum/uplink_item/item/implants/imp_uplink
|
||||
name = "Uplink Implant" //Original name: "Uplink Implant (Contains 5 Telecrystals)"
|
||||
item_cost = 5 //Original cost: 10
|
||||
path = /obj/item/weapon/storage/box/syndie_kit/imp_uplink
|
||||
|
||||
/**********
|
||||
* Medical *
|
||||
**********/
|
||||
/datum/uplink_item/item/medical
|
||||
category = /datum/uplink_category/medical
|
||||
|
||||
/datum/uplink_item/item/medical/sinpockets
|
||||
name = "Box of Sin-Pockets"
|
||||
item_cost = 1
|
||||
path = /obj/item/weapon/storage/box/sinpockets
|
||||
|
||||
/datum/uplink_item/item/medical/surgery
|
||||
name = "Surgery kit"
|
||||
item_cost = 6
|
||||
path = /obj/item/weapon/storage/firstaid/surgery
|
||||
|
||||
/datum/uplink_item/item/medical/combat
|
||||
name = "Combat medical kit"
|
||||
item_cost = 6
|
||||
path = /obj/item/weapon/storage/firstaid/combat
|
||||
|
||||
/*******************
|
||||
* Hardsuit Modules *
|
||||
*******************/
|
||||
/datum/uplink_item/item/hardsuit_modules
|
||||
category = /datum/uplink_category/hardsuit_modules
|
||||
|
||||
/datum/uplink_item/item/hardsuit_modules/thermal
|
||||
name = "Thermal Scanner"
|
||||
item_cost = 2
|
||||
path = /obj/item/rig_module/vision/thermal
|
||||
|
||||
/datum/uplink_item/item/hardsuit_modules/energy_net
|
||||
name = "Net Projector"
|
||||
item_cost = 3
|
||||
path = /obj/item/rig_module/fabricator/energy_net
|
||||
|
||||
/datum/uplink_item/item/ewar_voice
|
||||
name = "Electrowarfare Suite and Voice Synthesiser"
|
||||
item_cost = 4
|
||||
path = /obj/item/weapon/storage/box/syndie_kit/ewar_voice
|
||||
|
||||
/datum/uplink_item/item/hardsuit_modules/maneuvering_jets
|
||||
name = "Maneuvering Jets"
|
||||
item_cost = 4
|
||||
path = /obj/item/rig_module/maneuvering_jets
|
||||
|
||||
/datum/uplink_item/item/hardsuit_modules/egun
|
||||
name = "Mounted Energy Gun"
|
||||
item_cost = 6
|
||||
path = /obj/item/rig_module/mounted/egun
|
||||
|
||||
/datum/uplink_item/item/hardsuit_modules/power_sink
|
||||
name = "Power Sink"
|
||||
item_cost = 6
|
||||
path = /obj/item/rig_module/power_sink
|
||||
|
||||
/datum/uplink_item/item/hardsuit_modules/laser_canon
|
||||
name = "Mounted Laser Cannon"
|
||||
item_cost = 8
|
||||
path = /obj/item/rig_module/mounted
|
||||
|
||||
/***********
|
||||
* Grenades *
|
||||
************/
|
||||
/datum/uplink_item/item/grenades
|
||||
category = /datum/uplink_category/grenades
|
||||
|
||||
/datum/uplink_item/item/grenades/anti_photon
|
||||
name = "5xPhoton Disruption Grenades"
|
||||
item_cost = 2
|
||||
path = /obj/item/weapon/storage/box/anti_photons
|
||||
|
||||
/datum/uplink_item/item/grenades/emp
|
||||
name = "5xEMP Grenades"
|
||||
item_cost = 3
|
||||
path = /obj/item/weapon/storage/box/emps
|
||||
|
||||
/datum/uplink_item/item/grenades/smoke
|
||||
name = "5xSmoke Grenades"
|
||||
item_cost = 2
|
||||
path = /obj/item/weapon/storage/box/smokes
|
||||
|
||||
/************
|
||||
* Badassery *
|
||||
************/
|
||||
/datum/uplink_item/item/badassery
|
||||
category = /datum/uplink_category/badassery
|
||||
|
||||
/datum/uplink_item/item/badassery/balloon
|
||||
name = "For showing that You Are The BOSS (Useless Balloon)"
|
||||
item_cost = DEFAULT_TELECRYSTAL_AMOUNT
|
||||
path = /obj/item/toy/syndicateballoon
|
||||
|
||||
/datum/uplink_item/item/badassery/balloon/NT
|
||||
name = "For showing that you love NT SOO much (Useless Balloon)"
|
||||
path = /obj/item/toy/nanotrasenballoon
|
||||
|
||||
/**************
|
||||
* Random Item *
|
||||
**************/
|
||||
/datum/uplink_item/item/badassery/random_one
|
||||
name = "Random Item"
|
||||
desc = "Buys you one random item."
|
||||
|
||||
/datum/uplink_item/item/badassery/random_one/buy(var/obj/item/device/uplink/U, var/mob/user)
|
||||
var/datum/uplink_item/item = default_uplink_selection.get_random_item(U.uses)
|
||||
return item.buy(U, user)
|
||||
|
||||
/datum/uplink_item/item/badassery/random_one/can_buy(obj/item/device/uplink/U)
|
||||
return default_uplink_selection.get_random_item(U.uses, U) != null
|
||||
|
||||
/datum/uplink_item/item/badassery/random_many
|
||||
name = "Random Items"
|
||||
desc = "Buys you as many random items you can afford. Convenient packaging NOT included."
|
||||
|
||||
/datum/uplink_item/item/badassery/random_many/cost(var/telecrystals)
|
||||
return max(1, telecrystals)
|
||||
|
||||
/datum/uplink_item/item/badassery/random_many/get_goods(var/obj/item/device/uplink/U, var/loc)
|
||||
var/list/bought_items = list()
|
||||
for(var/datum/uplink_item/UI in get_random_uplink_items(U, U.uses, loc))
|
||||
UI.purchase_log(U)
|
||||
var/obj/item/I = UI.get_goods(U, loc)
|
||||
if(istype(I))
|
||||
bought_items += I
|
||||
|
||||
return bought_items
|
||||
|
||||
/datum/uplink_item/item/badassery/random_many/purchase_log(obj/item/device/uplink/U)
|
||||
feedback_add_details("traitor_uplink_items_bought", "[src]")
|
||||
log_and_message_admins("used \the [U.loc] to buy \a [src]")
|
||||
|
||||
/****************
|
||||
* Surplus Crate *
|
||||
****************/
|
||||
/datum/uplink_item/item/badassery/surplus
|
||||
name = "Surplus Crate"
|
||||
item_cost = 40
|
||||
var/item_worth = 60
|
||||
var/icon
|
||||
|
||||
/datum/uplink_item/item/badassery/surplus/New()
|
||||
..()
|
||||
desc = "A crate containing [item_worth] telecrystal\s worth of surplus leftovers."
|
||||
|
||||
/datum/uplink_item/item/badassery/surplus/get_goods(var/obj/item/device/uplink/U, var/loc)
|
||||
var/obj/structure/largecrate/C = new(loc)
|
||||
var/random_items = get_random_uplink_items(null, item_worth, C)
|
||||
for(var/datum/uplink_item/I in random_items)
|
||||
I.purchase_log(U)
|
||||
I.get_goods(U, C)
|
||||
|
||||
return C
|
||||
|
||||
/datum/uplink_item/item/badassery/surplus/log_icon()
|
||||
if(!icon)
|
||||
var/obj/structure/largecrate/C = /obj/structure/largecrate
|
||||
icon = image(initial(C.icon), initial(C.icon_state))
|
||||
|
||||
return "\icon[icon]"
|
||||
|
||||
/********************************
|
||||
* *
|
||||
* Abstract Uplink Entries *
|
||||
* *
|
||||
********************************/
|
||||
var/image/default_abstract_uplink_icon
|
||||
/datum/uplink_item/abstract/log_icon()
|
||||
if(!default_abstract_uplink_icon)
|
||||
default_abstract_uplink_icon = image('icons/obj/pda.dmi', "pda-syn")
|
||||
|
||||
return "\icon[default_abstract_uplink_icon]"
|
||||
|
||||
/****************
|
||||
* Announcements *
|
||||
*****************/
|
||||
/datum/uplink_item/abstract/announcements
|
||||
category = /datum/uplink_category/services
|
||||
|
||||
/datum/uplink_item/abstract/announcements/buy(var/obj/item/device/uplink/U, var/mob/user)
|
||||
. = ..()
|
||||
if(.)
|
||||
log_and_message_admins("has triggered a falsified [src]", user)
|
||||
|
||||
/datum/uplink_item/abstract/announcements/fake_centcom
|
||||
item_cost = DEFAULT_TELECRYSTAL_AMOUNT / 2
|
||||
|
||||
/datum/uplink_item/abstract/announcements/fake_centcom/New()
|
||||
..()
|
||||
name = "[command_name()] Update Announcement"
|
||||
desc = "Causes a falsified [command_name()] Update. Triggers immediately after supplying additional data."
|
||||
|
||||
/datum/uplink_item/abstract/announcements/fake_centcom/get_goods(var/obj/item/device/uplink/U, var/loc, var/mob/user, var/list/args)
|
||||
command_announcement.Announce(args.["message"], args.["title"])
|
||||
return 1
|
||||
|
||||
/datum/uplink_item/abstract/announcements/fake_crew_arrival
|
||||
name = "Crew Arrival Announcement/Records"
|
||||
desc = "Creates a fake crew arrival announcement as well as fake crew records, using your current appearance (including held items!) and worn id card. Trigger with care!"
|
||||
item_cost = 4
|
||||
|
||||
/datum/uplink_item/abstract/announcements/fake_crew_arrival/get_goods(var/obj/item/device/uplink/U, var/loc, var/mob/user, var/list/args)
|
||||
if(!user)
|
||||
return 0
|
||||
|
||||
var/obj/item/weapon/card/id/I = user.GetIdCard()
|
||||
var/datum/data/record/random_general_record
|
||||
var/datum/data/record/random_medical_record
|
||||
if(data_core.general.len)
|
||||
random_general_record = pick(data_core.general)
|
||||
random_medical_record = find_medical_record("id", random_general_record.fields["id"])
|
||||
|
||||
var/datum/data/record/general = data_core.CreateGeneralRecord(user)
|
||||
if(I)
|
||||
general.fields["age"] = I.age
|
||||
general.fields["rank"] = I.assignment
|
||||
general.fields["real_rank"] = I.assignment
|
||||
general.fields["name"] = I.registered_name
|
||||
general.fields["sex"] = I.sex
|
||||
else
|
||||
var/mob/living/carbon/human/H
|
||||
if(istype(user,/mob/living/carbon/human))
|
||||
H = user
|
||||
general.fields["age"] = H.age
|
||||
else
|
||||
general.fields["age"] = initial(H.age)
|
||||
var/assignment = GetAssignment(user)
|
||||
general.fields["rank"] = assignment
|
||||
general.fields["real_rank"] = assignment
|
||||
general.fields["name"] = user.real_name
|
||||
general.fields["sex"] = capitalize(user.gender)
|
||||
|
||||
general.fields["species"] = user.get_species()
|
||||
var/datum/data/record/medical = data_core.CreateMedicalRecord(general.fields["name"], general.fields["id"])
|
||||
data_core.CreateSecurityRecord(general.fields["name"], general.fields["id"])
|
||||
|
||||
if(!random_general_record)
|
||||
general.fields["citizenship"] = random_general_record.fields["citizenship"]
|
||||
general.fields["faction"] = random_general_record.fields["faction"]
|
||||
general.fields["fingerprint"] = random_general_record.fields["fingerprint"]
|
||||
general.fields["home_system"] = random_general_record.fields["home_system"]
|
||||
general.fields["religion"] = random_general_record.fields["religion"]
|
||||
if(random_medical_record)
|
||||
medical.fields["b_type"] = random_medical_record.fields["b_type"]
|
||||
medical.fields["b_dna"] = random_medical_record.fields["b_type"]
|
||||
|
||||
if(I)
|
||||
general.fields["fingerprint"] = I.fingerprint_hash
|
||||
medical.fields["b_type"] = I.blood_type
|
||||
medical.fields["b_dna"] = I.dna_hash
|
||||
|
||||
AnnounceArrivalSimple(general.fields["name"], general.fields["rank"])
|
||||
return 1
|
||||
|
||||
/datum/uplink_item/abstract/announcements/fake_ion_storm
|
||||
name = "Ion Storm Announcement"
|
||||
desc = "Interferes with the station's ion sensors. Triggers immediately upon investment."
|
||||
item_cost = 1
|
||||
|
||||
/datum/uplink_item/abstract/announcements/fake_ion_storm/get_goods(var/obj/item/device/uplink/U, var/loc)
|
||||
ion_storm_announcement()
|
||||
return 1
|
||||
|
||||
/datum/uplink_item/abstract/announcements/fake_radiation
|
||||
name = "Radiation Storm Announcement"
|
||||
desc = "Interferes with the station's radiation sensors. Triggers immediately upon investment."
|
||||
item_cost = 3
|
||||
|
||||
/datum/uplink_item/abstract/announcements/fake_radiation/get_goods(var/obj/item/device/uplink/U, var/loc)
|
||||
var/datum/event_meta/EM = new(EVENT_LEVEL_MUNDANE, "Fake Radiation Storm", add_to_queue = 0)
|
||||
new/datum/event/radiation_storm/syndicate(EM)
|
||||
return 1
|
||||
|
||||
|
||||
/****************
|
||||
* Support procs *
|
||||
****************/
|
||||
/proc/get_random_uplink_items(var/obj/item/device/uplink/U, var/remaining_TC, var/loc)
|
||||
var/list/bought_items = list()
|
||||
while(remaining_TC)
|
||||
var/datum/uplink_item/I = default_uplink_selection.get_random_item(remaining_TC, U, bought_items)
|
||||
if(!I)
|
||||
break
|
||||
bought_items += I
|
||||
remaining_TC -= I.cost(remaining_TC)
|
||||
|
||||
return bought_items
|
||||
@@ -27,7 +27,7 @@ var/datum/uplink_random_selection/default_uplink_selection = new/datum/uplink_ra
|
||||
if(!prob(RI.keep_probability))
|
||||
continue
|
||||
var/datum/uplink_item/I = uplink.items_assoc[RI.uplink_item]
|
||||
if(I.cost(telecrystals) > telecrystals)
|
||||
if(I.cost(telecrystals, U) > telecrystals)
|
||||
continue
|
||||
if(bought_items && (I in bought_items) && !prob(RI.reselect_probability))
|
||||
continue
|
||||
|
||||
Reference in New Issue
Block a user