Merge tgstation13 r4570 into bs12_with_tgport

Conflicts:
	baystation12.dme
	code/defines/obj.dm
	code/defines/procs/helpers.dm
	code/defines/turf.dm
	code/game/gamemodes/changeling/modularchangling.dm
	code/game/gamemodes/cult/cult_structures.dm
	code/game/gamemodes/events.dm
	code/game/machinery/telecomms/machine_interactions.dm
	code/game/master_controller.dm
	code/game/objects/items/blueprints.dm
	code/game/objects/items/devices/uplinks.dm
	code/game/objects/items/item.dm
	code/game/objects/items/weapons/gift_wrappaper.dm
	code/game/objects/items/weapons/wires.dm
	code/game/objects/weapons.dm
	code/game/turfs/turf.dm
	code/modules/clothing/head/hardhat.dm
	code/modules/mining/mine_items.dm
	code/modules/mining/mine_turfs.dm
	code/modules/mob/living/silicon/robot/life.dm
	code/modules/mob/mob_defines.dm
	code/modules/mob/new_player/login.dm
	code/modules/paperwork/pen.dm
	code/modules/paperwork/stamps.dm
	code/unused/toilets.dm
	html/changelog.html
	icons/effects/alert.dmi

Signed-off-by: Cael_Aislinn <cael_aislinn@yahoo.com.au>
This commit is contained in:
Cael_Aislinn
2012-08-28 19:57:11 +10:00
269 changed files with 14389 additions and 13349 deletions
File diff suppressed because it is too large Load Diff
+712
View File
@@ -0,0 +1,712 @@
/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 = 1
var/obj/item/radio/integrated/radio = null
var/access_security = 0
var/access_engine = 0
var/access_medical = 0
var/access_manifest = 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_hydroponics = 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/obj/machinery/power/monitor/powmonitor = null // Power Monitor
var/list/powermonitors = list()
var/message1 // used for status_displays
var/message2
var/list/stored_data = list()
engineering
name = "Power-ON Cartridge"
icon_state = "cart-e"
access_engine = 1
medical
name = "Med-U Cartridge"
icon_state = "cart-m"
access_medical = 1
chemistry
name = "ChemWhiz Cartridge"
icon_state = "cart-chem"
access_reagent_scanner = 1
security
name = "R.O.B.U.S.T. Cartridge"
icon_state = "cart-s"
access_security = 1
New()
..()
spawn(5)
radio = new /obj/item/radio/integrated/beepsky(src)
detective
name = "D.E.T.E.C.T. Cartridge"
icon_state = "cart-s"
access_security = 1
access_medical = 1
access_manifest = 1
janitor
name = "CustodiPRO Cartridge"
desc = "The ultimate in clean-room design."
icon_state = "cart-j"
access_janitor = 1
lawyer
name = "P.R.O.V.E. Cartridge"
icon_state = "cart-s"
access_security = 1
clown
name = "Honkworks 5.0"
icon_state = "cart-clown"
access_clown = 1
var/honk_charges = 5
mime
name = "Gestur-O 1000"
icon_state = "cart-mi"
access_mime = 1
var/mime_charges = 5
/*
botanist
name = "Green Thumb v4.20"
icon_state = "cart-b"
access_flora = 1
*/
signal
name = "generic signaler cartridge"
desc = "A data cartridge with an integrated radio signaler module."
toxins
name = "Signal Ace 2"
desc = "Complete with integrated radio signaler!"
icon_state = "cart-tox"
// access_reagent_scanner = 1
New()
..()
spawn(5)
radio = new /obj/item/radio/integrated/signal(src)
quartermaster
name = "Space Parts & Space Vendors Cartridge"
desc = "Perfect for the Quartermaster on the go!"
icon_state = "cart-q"
access_quartermaster = 1
New()
..()
spawn(5)
radio = new /obj/item/radio/integrated/mule(src)
head
name = "Easy-Record DELUXE"
icon_state = "cart-h"
access_manifest = 1
access_status_display = 1
hop
name = "HumanResources9001"
icon_state = "cart-h"
access_manifest = 1
access_status_display = 1
access_quartermaster = 1
New()
..()
spawn(5)
radio = new /obj/item/radio/integrated/mule(src)
hos
name = "R.O.B.U.S.T. DELUXE"
icon_state = "cart-hos"
access_manifest = 1
access_status_display = 1
access_security = 1
New()
..()
spawn(5)
radio = new /obj/item/radio/integrated/beepsky(src)
ce
name = "Power-On DELUXE"
icon_state = "cart-ce"
access_manifest = 1
access_status_display = 1
access_engine = 1
cmo
name = "Med-U DELUXE"
icon_state = "cart-cmo"
access_manifest = 1
access_status_display = 1
access_reagent_scanner = 1
access_medical = 1
rd
name = "Signal Ace DELUXE"
icon_state = "cart-rd"
access_manifest = 1
access_status_display = 1
// access_reagent_scanner = 1
New()
..()
spawn(5)
radio = new /obj/item/radio/integrated/signal(src)
captain
name = "Value-PAK Cartridge"
desc = "Now with 200% more value!"
icon_state = "cart-c"
access_manifest = 1
access_engine = 1
access_security = 1
access_medical = 1
access_reagent_scanner = 1
access_status_display = 1
syndicate
name = "Detomatix Cartridge"
icon_state = "cart"
access_remote_door = 1
remote_door_id = "syndicate" //Make sure this matches the syndicate shuttle's shield/door id!!
var/shock_charges = 4
proc/unlock()
if (!istype(loc, /obj/item/device/pda))
return
generate_menu()
print_to_host(menu)
return
proc/print_to_host(var/text)
if (!istype(loc, /obj/item/device/pda))
return
loc:cart = text
for (var/mob/M in viewers(1, loc.loc))
if (M.client && M.machine == loc)
loc:attack_self(M)
return
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 = 1
status_signal.data["command"] = command
switch(command)
if("message")
status_signal.data["msg1"] = data1
status_signal.data["msg2"] = data2
if("alert")
status_signal.data["picture_state"] = data1
frequency.post_signal(src, status_signal)
proc/generate_menu()
switch(mode)
if(40) //signaller
menu = "<h4><img src=pda_signaler.png> Remote Signaling System</h4>"
menu += {"
<a href='byond://?src=\ref[src];choice=Send Signal'>Send Signal</A><BR>
Frequency:
<a href='byond://?src=\ref[src];choice=Signal Frequency;sfreq=-10'>-</a>
<a href='byond://?src=\ref[src];choice=Signal Frequency;sfreq=-2'>-</a>
[format_frequency(radio:frequency)]
<a href='byond://?src=\ref[src];choice=Signal Frequency;sfreq=2'>+</a>
<a href='byond://?src=\ref[src];choice=Signal Frequency;sfreq=10'>+</a><br>
<br>
Code:
<a href='byond://?src=\ref[src];choice=Signal Code;scode=-5'>-</a>
<a href='byond://?src=\ref[src];choice=Signal Code;scode=-1'>-</a>
[radio:code]
<a href='byond://?src=\ref[src];choice=Signal Code;scode=1'>+</a>
<a href='byond://?src=\ref[src];choice=Signal Code;scode=5'>+</a><br>"}
if (41) //crew manifest
menu = "<h4><img src=pda_notes.png> Crew Manifest</h4>"
menu += "Entries cannot be modified from this terminal.<br><br>"
if(!isnull(data_core.general))
for (var/datum/data/record/t in sortRecord(data_core.general))
menu += "[t.fields["name"]] - [t.fields["rank"]]<br>"
menu += "<br>"
if (42) //status displays
menu = "<h4><img src=pda_status.png> Station Status Display Interlink</h4>"
menu += "\[ <A HREF='?src=\ref[src];choice=Status;statdisp=blank'>Clear</A> \]<BR>"
menu += "\[ <A HREF='?src=\ref[src];choice=Status;statdisp=shuttle'>Shuttle ETA</A> \]<BR>"
menu += "\[ <A HREF='?src=\ref[src];choice=Status;statdisp=message'>Message</A> \]"
menu += "<ul><li> Line 1: <A HREF='?src=\ref[src];choice=Status;statdisp=setmsg1'>[ message1 ? message1 : "(none)"]</A>"
menu += "<li> Line 2: <A HREF='?src=\ref[src];choice=Status;statdisp=setmsg2'>[ message2 ? message2 : "(none)"]</A></ul><br>"
menu += "\[ Alert: <A HREF='?src=\ref[src];choice=Status;statdisp=alert;alert=default'>None</A> |"
menu += " <A HREF='?src=\ref[src];choice=Status;statdisp=alert;alert=redalert'>Red Alert</A> |"
menu += " <A HREF='?src=\ref[src];choice=Status;statdisp=alert;alert=lockdown'>Lockdown</A> |"
menu += " <A HREF='?src=\ref[src];choice=Status;statdisp=alert;alert=biohazard'>Biohazard</A> \]<BR>"
if (43) //Muskets' and Rockdtben's power monitor :D
menu = "<h4><img src=pda_power.png> Power Monitors - Please select one</h4><BR>"
powmonitor = null
powermonitors = null
powermonitors = list()
var/powercount = 0
for(var/obj/machinery/power/monitor/pMon in world)
if(!(pMon.stat & (NOPOWER|BROKEN)) )
powercount++
powermonitors += pMon
if(!powercount)
menu += "\red No connection<BR>"
else
menu += "<FONT SIZE=-1>"
var/count = 0
for(var/obj/machinery/power/monitor/pMon in powermonitors)
count++
menu += "<a href='byond://?src=\ref[src];choice=Power Select;target=[count]'> [pMon] </a><BR>"
menu += "</FONT>"
if (433) //Muskets' and Rockdtben's power monitor :D
menu = "<h4><img src=pda_power.png> Power Monitor </h4><BR>"
if(!powmonitor)
menu += "\red No connection<BR>"
else
var/list/L = list()
for(var/obj/machinery/power/terminal/term in powmonitor.powernet.nodes)
if(istype(term.master, /obj/machinery/power/apc))
var/obj/machinery/power/apc/A = term.master
L += A
menu += "<PRE>Total power: [powmonitor.powernet.avail] W<BR>Total load: [num2text(powmonitor.powernet.viewload,10)] W<BR>"
menu += "<FONT SIZE=-1>"
if(L.len > 0)
menu += "Area Eqp./Lgt./Env. Load Cell<HR>"
var/list/S = list(" Off","AOff"," On", " AOn")
var/list/chg = list("N","C","F")
for(var/obj/machinery/power/apc/A in L)
menu += copytext(add_tspace(A.area.name, 30), 1, 30)
menu += " [S[A.equipment+1]] [S[A.lighting+1]] [S[A.environ+1]] [add_lspace(A.lastused_total, 6)] [A.cell ? "[add_lspace(round(A.cell.percent()), 3)]% [chg[A.charging+1]]" : " N/C"]<BR>"
menu += "</FONT></PRE>"
if (44) //medical records //This thing only displays a single screen so it's hard to really get the sub-menu stuff working.
menu = "<h4><img src=pda_medical.png> Medical Record List</h4>"
if(!isnull(data_core.general))
for (var/datum/data/record/R in sortRecord(data_core.general))
menu += "<a href='byond://?src=\ref[src];choice=Medical Records;target=\ref[R]'>[R.fields["id"]]: [R.fields["name"]]<br>"
menu += "<br>"
if(441)
menu = "<h4><img src=pda_medical.png> Medical Record</h4>"
if (istype(active1, /datum/data/record) && (active1 in data_core.general))
menu += "Name: [active1.fields["name"]] ID: [active1.fields["id"]]<br>"
menu += "Sex: [active1.fields["sex"]]<br>"
menu += "Age: [active1.fields["age"]]<br>"
menu += "Rank: [active1.fields["rank"]]<br>"
menu += "Fingerprint: [active1.fields["fingerprint"]]<br>"
menu += "Physical Status: [active1.fields["p_stat"]]<br>"
menu += "Mental Status: [active1.fields["m_stat"]]<br>"
else
menu += "<b>Record Lost!</b><br>"
menu += "<br>"
menu += "<h4><img src=pda_medical.png> Medical Data</h4>"
if (istype(active2, /datum/data/record) && (active2 in data_core.medical))
menu += "Blood Type: [active2.fields["b_type"]]<br><br>"
menu += "Minor Disabilities: [active2.fields["mi_dis"]]<br>"
menu += "Details: [active2.fields["mi_dis_d"]]<br><br>"
menu += "Major Disabilities: [active2.fields["ma_dis"]]<br>"
menu += "Details: [active2.fields["ma_dis_d"]]<br><br>"
menu += "Allergies: [active2.fields["alg"]]<br>"
menu += "Details: [active2.fields["alg_d"]]<br><br>"
menu += "Current Diseases: [active2.fields["cdi"]]<br>"
menu += "Details: [active2.fields["cdi_d"]]<br><br>"
menu += "Important Notes: [active2.fields["notes"]]<br>"
else
menu += "<b>Record Lost!</b><br>"
menu += "<br>"
if (45) //security records
menu = "<h4><img src=pda_cuffs.png> Security Record List</h4>"
if(!isnull(data_core.general))
for (var/datum/data/record/R in sortRecord(data_core.general))
menu += "<a href='byond://?src=\ref[src];choice=Security Records;target=\ref[R]'>[R.fields["id"]]: [R.fields["name"]]<br>"
menu += "<br>"
if(451)
menu = "<h4><img src=pda_cuffs.png> Security Record</h4>"
if (istype(active1, /datum/data/record) && (active1 in data_core.general))
menu += "Name: [active1.fields["name"]] ID: [active1.fields["id"]]<br>"
menu += "Sex: [active1.fields["sex"]]<br>"
menu += "Age: [active1.fields["age"]]<br>"
menu += "Rank: [active1.fields["rank"]]<br>"
menu += "Fingerprint: [active1.fields["fingerprint"]]<br>"
menu += "Physical Status: [active1.fields["p_stat"]]<br>"
menu += "Mental Status: [active1.fields["m_stat"]]<br>"
else
menu += "<b>Record Lost!</b><br>"
menu += "<br>"
menu += "<h4><img src=pda_cuffs.png> Security Data</h4>"
if (istype(active3, /datum/data/record) && (active3 in data_core.security))
menu += "Criminal Status: [active3.fields["criminal"]]<br>"
menu += "Minor Crimes: [active3.fields["mi_crim"]]<br>"
menu += "Details: [active3.fields["mi_crim"]]<br><br>"
menu += "Major Crimes: [active3.fields["ma_crim"]]<br>"
menu += "Details: [active3.fields["ma_crim_d"]]<br><br>"
menu += "Important Notes:<br>"
menu += "[active3.fields["notes"]]"
else
menu += "<b>Record Lost!</b><br>"
menu += "<br>"
if (46) //beepsky control
var/obj/item/radio/integrated/beepsky/SC = radio
if(!SC)
menu = "Interlink Error - Please reinsert cartridge."
return
menu = "<h4><img src=pda_cuffs.png> Securitron Interlink</h4>"
if(!SC.active)
// list of bots
if(!SC.botlist || (SC.botlist && SC.botlist.len==0))
menu += "No bots found.<BR>"
else
for(var/obj/machinery/bot/secbot/B in SC.botlist)
menu += "<A href='byond://?src=\ref[SC];op=control;bot=\ref[B]'>[B] at [B.loc.loc]</A><BR>"
menu += "<BR><A href='byond://?src=\ref[SC];op=scanbots'><img src=pda_scanner.png> Scan for active bots</A><BR>"
else // bot selected, control it
menu += "<B>[SC.active]</B><BR> Status: (<A href='byond://?src=\ref[SC];op=control;bot=\ref[SC.active]'><img src=pda_refresh.png><i>refresh</i></A>)<BR>"
if(!SC.botstatus)
menu += "Waiting for response...<BR>"
else
menu += "Location: [SC.botstatus["loca"] ]<BR>"
menu += "Mode: "
switch(SC.botstatus["mode"])
if(0)
menu += "Ready"
if(1)
menu += "Apprehending target"
if(2,3)
menu += "Arresting target"
if(4)
menu += "Starting patrol"
if(5)
menu += "On patrol"
if(6)
menu += "Responding to summons"
menu += "<BR>\[<A href='byond://?src=\ref[SC];op=stop'>Stop Patrol</A>\] "
menu += "\[<A href='byond://?src=\ref[SC];op=go'>Start Patrol</A>\] "
menu += "\[<A href='byond://?src=\ref[SC];op=summon'>Summon Bot</A>\]<BR>"
menu += "<HR><A href='byond://?src=\ref[SC];op=botlist'><img src=pda_back.png>Return to bot list</A>"
if (47) //quartermaster order records
menu = "<h4><img src=pda_crate.png> Supply Record Interlink</h4>"
menu += "<BR><B>Supply shuttle</B><BR>"
menu += "Location: [supply_shuttle.moving ? "Moving to station ([supply_shuttle.eta] Mins.)":supply_shuttle.at_station ? "Station":"Dock"]<BR>"
menu += "Current approved orders: <BR><ol>"
for(var/S in supply_shuttle.shoppinglist)
var/datum/supply_order/SO = S
menu += "<li>#[SO.ordernum] - [SO.object.name] approved by [SO.orderedby] [SO.comment ? "([SO.comment])":""]</li>"
menu += "</ol>"
menu += "Current requests: <BR><ol>"
for(var/S in supply_shuttle.requestlist)
var/datum/supply_order/SO = S
menu += "<li>#[SO.ordernum] - [SO.object.name] requested by [SO.orderedby]</li>"
menu += "</ol><font size=\"-3\">Upgrade NOW to Space Parts & Space Vendors PLUS for full remote order control and inventory management."
if (48) //mulebot control
var/obj/item/radio/integrated/mule/QC = radio
if(!QC)
menu = "Interlink Error - Please reinsert cartridge."
return
menu = "<h4><img src=pda_mule.png> M.U.L.E. bot Interlink V0.8</h4>"
if(!QC.active)
// list of bots
if(!QC.botlist || (QC.botlist && QC.botlist.len==0))
menu += "No bots found.<BR>"
else
for(var/obj/machinery/bot/mulebot/B in QC.botlist)
menu += "<A href='byond://?src=\ref[QC];op=control;bot=\ref[B]'>[B] at [B.loc.loc]</A><BR>"
menu += "<BR><A href='byond://?src=\ref[QC];op=scanbots'><img src=pda_scanner.png> Scan for active bots</A><BR>"
else // bot selected, control it
menu += "<B>[QC.active]</B><BR> Status: (<A href='byond://?src=\ref[QC];op=control;bot=\ref[QC.active]'><img src=pda_refresh.png><i>refresh</i></A>)<BR>"
if(!QC.botstatus)
menu += "Waiting for response...<BR>"
else
menu += "Location: [QC.botstatus["loca"] ]<BR>"
menu += "Mode: "
switch(QC.botstatus["mode"])
if(0)
menu += "Ready"
if(1)
menu += "Loading/Unloading"
if(2)
menu += "Navigating to Delivery Location"
if(3)
menu += "Navigating to Home"
if(4)
menu += "Waiting for clear path"
if(5,6)
menu += "Calculating navigation path"
if(7)
menu += "Unable to locate destination"
var/obj/structure/closet/crate/C = QC.botstatus["load"]
menu += "<BR>Current Load: [ !C ? "<i>none</i>" : "[C.name] (<A href='byond://?src=\ref[QC];op=unload'><i>unload</i></A>)" ]<BR>"
menu += "Destination: [!QC.botstatus["dest"] ? "<i>none</i>" : QC.botstatus["dest"] ] (<A href='byond://?src=\ref[QC];op=setdest'><i>set</i></A>)<BR>"
menu += "Power: [QC.botstatus["powr"]]%<BR>"
menu += "Home: [!QC.botstatus["home"] ? "<i>none</i>" : QC.botstatus["home"] ]<BR>"
menu += "Auto Return Home: [QC.botstatus["retn"] ? "<B>On</B> <A href='byond://?src=\ref[QC];op=retoff'>Off</A>" : "(<A href='byond://?src=\ref[QC];op=reton'><i>On</i></A>) <B>Off</B>"]<BR>"
menu += "Auto Pickup Crate: [QC.botstatus["pick"] ? "<B>On</B> <A href='byond://?src=\ref[QC];op=pickoff'>Off</A>" : "(<A href='byond://?src=\ref[QC];op=pickon'><i>On</i></A>) <B>Off</B>"]<BR><BR>"
menu += "\[<A href='byond://?src=\ref[QC];op=stop'>Stop</A>\] "
menu += "\[<A href='byond://?src=\ref[QC];op=go'>Proceed</A>\] "
menu += "\[<A href='byond://?src=\ref[QC];op=home'>Return Home</A>\]<BR>"
menu += "<HR><A href='byond://?src=\ref[QC];op=botlist'><img src=pda_back.png>Return to bot list</A>"
if (49) //janitorial locator
menu = "<h4><img src=pda_bucket.png> Persistent Custodial Object Locator</h4>"
var/turf/cl = get_turf(src)
if (cl)
menu += "Current Orbital Location: <b>\[[cl.x],[cl.y]\]</b>"
menu += "<h4>Located Mops:</h4>"
var/ldat
for (var/obj/item/weapon/mop/M in world)
var/turf/ml = get_turf(M)
if(ml)
if (ml.z != cl.z)
continue
var/direction = get_dir(src, M)
ldat += "Mop - <b>\[[ml.x],[ml.y] ([uppertext(dir2text(direction))])\]</b> - [M.reagents.total_volume ? "Wet" : "Dry"]<br>"
if (!ldat)
menu += "None"
else
menu += "[ldat]"
menu += "<h4>Located Mop Buckets:</h4>"
ldat = null
for (var/obj/structure/mopbucket/B in world)
var/turf/bl = get_turf(B)
if(bl)
if (bl.z != cl.z)
continue
var/direction = get_dir(src, B)
ldat += "Bucket - <b>\[[bl.x],[bl.y] ([uppertext(dir2text(direction))])\]</b> - Water level: [B.reagents.total_volume]/100<br>"
if (!ldat)
menu += "None"
else
menu += "[ldat]"
menu += "<h4>Located Cleanbots:</h4>"
ldat = null
for (var/obj/machinery/bot/cleanbot/B in world)
var/turf/bl = get_turf(B)
if(bl)
if (bl.z != cl.z)
continue
var/direction = get_dir(src, B)
ldat += "Cleanbot - <b>\[[bl.x],[bl.y] ([uppertext(dir2text(direction))])\]</b> - [B.on ? "Online" : "Offline"]<br>"
if (!ldat)
menu += "None"
else
menu += "[ldat]"
else
menu += "ERROR: Unable to determine current location."
menu += "<br><br><A href='byond://?src=\ref[src];choice=49'>Refresh GPS Locator</a>"
proc/add_data(atom/A as mob|obj|turf|area)
//I love hashtables.
var/list/data_entry = stored_data["\ref [A]"]
if(islist(data_entry)) //Yay, it was already stored!
//Merge the fingerprints.
var/list/data_prints = data_entry[1]
for(var/print in A.fingerprints)
var/merged_print = data_prints[print]
if(!merged_print)
data_prints[print] = A.fingerprints[print]
else
data_prints[print] = stringmerge(data_prints[print],A.fingerprints[print])
//Now the fibers
var/list/fibers = data_entry[2]
if(!fibers)
fibers = list()
if(A.suit_fibers && A.suit_fibers.len)
for(var/j = 1, j <= A.suit_fibers.len, j++) //Fibers~~~
if(!fibers.Find(A.suit_fibers[j])) //It isn't! Add!
fibers += A.suit_fibers[j]
var/list/blood = data_entry[3]
if(!blood)
blood = list()
if(A.blood_DNA && A.blood_DNA.len)
for(var/main_blood in A.blood_DNA)
if(!blood[main_blood])
blood[main_blood] = A.blood_DNA[blood]
return 1
var/list/sum_list[4] //Pack it back up!
sum_list[1] = A.fingerprints
sum_list[2] = A.suit_fibers
sum_list[3] = A.blood_DNA
sum_list[4] = "\The [A] in \the [get_area(A)]"
stored_data["\ref [A]"] = sum_list
return 0
/obj/item/weapon/cartridge/Topic(href, href_list)
..()
if (!usr.canmove || usr.stat || usr.restrained() || !in_range(loc, usr))
usr.machine = null
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")
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 = input("Line 1", "Enter Message Text", message1) as text|null
updateSelfDialog()
if("setmsg2")
message2 = input("Line 2", "Enter Message Text", message2) as text|null
updateSelfDialog()
else
post_status(href_list["statdisp"])
if("Power Select")
var/pnum = text2num(href_list["target"])
powmonitor = powermonitors[pnum]
loc:mode = 433
mode = 433
generate_menu()
print_to_host(menu)
@@ -0,0 +1,16 @@
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
@@ -0,0 +1,259 @@
/obj/item/radio/integrated
name = "PDA radio module"
desc = "An electronic radio system of nanotrasen origin."
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)
//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 = 1
signal.data[key] = value
if(key2)
signal.data[key2] = value2
if(key3)
signal.data[key3] = value3
frequency.post_signal(src, signal, filter = s_filter)
proc/print_to_host(var/text)
if (isnull(src.hostpda))
return
src.hostpda.cart = text
for (var/mob/M in viewers(1, src.hostpda.loc))
if (M.client && M.machine == src.hostpda)
src.hostpda.cartridge.unlock()
return
proc/generate_menu()
/obj/item/radio/integrated/beepsky
var/list/botlist = null // list of bots
var/obj/machinery/bot/secbot/active // the active bot; if null, show bot list
var/list/botstatus // the status signal sent by the bot
var/control_freq = 1447
// 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, 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
/*
world << "recvd:[P] : [signal.source]"
for(var/d in signal.data)
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)
PDA.cartridge.unlock()
/obj/item/radio/integrated/mule
var/list/botlist = null // list of bots
var/obj/machinery/bot/mulebot/active // the active bot; if null, show bot list
var/list/botstatus // the status signal sent by the bot
var/list/beacons
var/beacon_freq = 1400
var/control_freq = 1447
// 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, filter = RADIO_MULEBOT)
radio_controller.add_object(src, beacon_freq, filter = RADIO_NAVBEACONS)
spawn(10)
post_signal(beacon_freq, "findbeacon", "delivery", s_filter = RADIO_NAVBEACONS)
// receive radio signals
// can detect bot status signals
// and beacon locations
// create/populate lists as they are recvd
receive_signal(datum/signal/signal)
// var/obj/item/device/pda/P = src.loc
/*
world << "recvd:[P] : [signal.source]"
for(var/d in signal.data)
world << "- [d] = [signal.data[d]]"
*/
if(signal.data["type"] == "mulebot")
if(!botlist)
botlist = new()
if(!(signal.source in botlist))
botlist += signal.source
if(active == signal.source)
var/list/b = signal.data
botstatus = b.Copy()
else if(signal.data["beacon"])
if(!beacons)
beacons = new()
beacons[signal.data["beacon"] ] = signal.source
// if(istype(P)) P.updateSelfDialog()
Topic(href, href_list)
..()
var/obj/item/device/pda/PDA = src.hostpda
var/cmd = "command"
if(active) cmd = "command [active.suffix]"
switch(href_list["op"])
if("control")
active = locate(href_list["bot"])
post_signal(control_freq, cmd, "bot_status", s_filter = RADIO_MULEBOT)
if("scanbots") // find all bots
botlist = null
post_signal(control_freq, "command", "bot_status", s_filter = RADIO_MULEBOT)
if("botlist")
active = null
if("unload")
post_signal(control_freq, cmd, "unload", s_filter = RADIO_MULEBOT)
post_signal(control_freq, cmd, "bot_status", s_filter = RADIO_MULEBOT)
if("setdest")
if(beacons)
var/dest = input("Select Bot Destination", "Mulebot [active.suffix] Interlink", active.destination) as null|anything in beacons
if(dest)
post_signal(control_freq, cmd, "target", "destination", dest, s_filter = RADIO_MULEBOT)
post_signal(control_freq, cmd, "bot_status", s_filter = RADIO_MULEBOT)
if("retoff")
post_signal(control_freq, cmd, "autoret", "value", 0, s_filter = RADIO_MULEBOT)
post_signal(control_freq, cmd, "bot_status", s_filter = RADIO_MULEBOT)
if("reton")
post_signal(control_freq, cmd, "autoret", "value", 1, s_filter = RADIO_MULEBOT)
post_signal(control_freq, cmd, "bot_status", s_filter = RADIO_MULEBOT)
if("pickoff")
post_signal(control_freq, cmd, "autopick", "value", 0, s_filter = RADIO_MULEBOT)
post_signal(control_freq, cmd, "bot_status", s_filter = RADIO_MULEBOT)
if("pickon")
post_signal(control_freq, cmd, "autopick", "value", 1, s_filter = RADIO_MULEBOT)
post_signal(control_freq, cmd, "bot_status", s_filter = RADIO_MULEBOT)
if("stop", "go", "home")
post_signal(control_freq, cmd, href_list["op"], s_filter = RADIO_MULEBOT)
post_signal(control_freq, cmd, "bot_status", s_filter = RADIO_MULEBOT)
PDA.cartridge.unlock()
/*
* 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
New()
..()
if(radio_controller)
initialize()
initialize()
if (src.frequency < 1441 || src.frequency > 1489)
src.frequency = sanitize_frequency(src.frequency)
set_frequency(frequency)
proc/set_frequency(new_frequency)
radio_controller.remove_object(src, frequency)
frequency = new_frequency
radio_connection = radio_controller.add_object(src, frequency)
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)
return
+128
View File
@@ -0,0 +1,128 @@
/obj/item/device/aicard
name = "inteliCard"
icon = 'icons/obj/pda.dmi'
icon_state = "aicard" // aicard-full
item_state = "electronic"
w_class = 2.0
flags = FPRINT | TABLEPASS
slot_flags = SLOT_BELT
var/flush = null
origin_tech = "programming=4;materials=4"
attack(mob/living/silicon/ai/M as mob, mob/user as mob)
if(!istype(M, /mob/living/silicon/ai))//If target is not an AI.
return ..()
M.attack_log += text("\[[time_stamp()]\] <font color='orange'>Has been carded with [src.name] by [user.name] ([user.ckey])</font>")
user.attack_log += text("\[[time_stamp()]\] <font color='red'>Used the [src.name] to card [M.name] ([M.ckey])</font>")
log_attack("<font color='red'>[user.name] ([user.ckey]) used the [src.name] to card [M.name] ([M.ckey])</font>")
transfer_ai("AICORE", "AICARD", M, user)
return
attack(mob/living/silicon/decoy/M as mob, mob/user as mob)
if (!istype (M, /mob/living/silicon/decoy))
return ..()
else
M.death()
user << "<b>ERROR ERROR ERROR</b>"
attack_self(mob/user)
if (!in_range(src, user))
return
user.machine = src
var/dat = "<TT><B>Intelicard</B><BR>"
var/laws
for(var/mob/living/silicon/ai/A in src)
dat += "Stored AI: [A.name]<br>System integrity: [(A.health+100)/2]%<br>"
for (var/index = 1, index <= A.laws.ion.len, index++)
var/law = A.laws.ion[index]
if (length(law) > 0)
var/num = ionnum()
laws += "[num]. [law]"
if (A.laws.zeroth)
laws += "0: [A.laws.zeroth]<BR>"
var/number = 1
for (var/index = 1, index <= A.laws.inherent.len, index++)
var/law = A.laws.inherent[index]
if (length(law) > 0)
laws += "[number]: [law]<BR>"
number++
for (var/index = 1, index <= A.laws.supplied.len, index++)
var/law = A.laws.supplied[index]
if (length(law) > 0)
laws += "[number]: [law]<BR>"
number++
dat += "Laws:<br>[laws]<br>"
if (A.stat == 2)
dat += "<b>AI nonfunctional</b>"
else
if (!src.flush)
dat += {"<A href='byond://?src=\ref[src];choice=Wipe'>Wipe AI</A>"}
else
dat += "<b>Wipe in progress</b>"
dat += "<br>"
dat += {"<a href='byond://?src=\ref[src];choice=Wireless'>[A.control_disabled ? "Enable" : "Disable"] Wireless Activity</a>"}
dat += "<br>"
dat += {"<a href='byond://?src=\ref[src];choice=Close'> Close</a>"}
user << browse(dat, "window=aicard")
onclose(user, "aicard")
return
Topic(href, href_list)
var/mob/U = usr
if (!in_range(src, U)||U.machine!=src)//If they are not in range of 1 or less or their machine is not the card (ie, clicked on something else).
U << browse(null, "window=aicard")
U.machine = null
return
add_fingerprint(U)
U.machine = src
switch(href_list["choice"])//Now we switch based on choice.
if ("Close")
U << browse(null, "window=aicard")
U.machine = null
return
if ("Wipe")
var/confirm = alert("Are you sure you want to wipe this card's memory? This cannot be undone once started.", "Confirm Wipe", "Yes", "No")
if(confirm == "Yes")
if(isnull(src)||!in_range(src, U)||U.machine!=src)
U << browse(null, "window=aicard")
U.machine = null
return
else
flush = 1
for(var/mob/living/silicon/ai/A in src)
A.suiciding = 1
A << "Your core files are being wiped!"
while (A.stat != 2)
A.adjustOxyLoss(2)
A.updatehealth()
sleep(10)
flush = 0
if ("Wireless")
for(var/mob/living/silicon/ai/A in src)
A.control_disabled = !A.control_disabled
A << "The intelicard's wireless port has been [A.control_disabled ? "disabled" : "enabled"]!"
if (A.control_disabled)
overlays -= image('icons/obj/pda.dmi', "aicard-on")
else
overlays += image('icons/obj/pda.dmi', "aicard-on")
attack_self(U)
@@ -0,0 +1,122 @@
/obj/item/device/chameleon
name = "chameleon-projector"
icon_state = "shield0"
flags = FPRINT | TABLEPASS| CONDUCT | USEDELAY
slot_flags = SLOT_BELT
item_state = "electronic"
throwforce = 5.0
throw_speed = 1
throw_range = 5
w_class = 2.0
origin_tech = "syndicate=4;magnets=4"
var/can_use = 1
var/obj/effect/dummy/chameleon/active_dummy = null
var/saved_item = "/obj/item/weapon/cigbutt"
dropped()
disrupt()
attack_self()
toggle()
afterattack(atom/target, mob/user , flag)
if(istype(target,/obj/item))
playsound(src, 'sound/weapons/flash.ogg', 100, 1, 1)
user << "\blue Scanned [target]."
saved_item = target.type
proc/toggle()
if(!can_use || !saved_item) return
if(active_dummy)
playsound(src, 'sound/effects/pop.ogg', 100, 1, 1)
for(var/atom/movable/A in active_dummy)
A.loc = active_dummy.loc
if(ismob(A))
if(A:client)
A:client:eye = A
del(active_dummy)
active_dummy = null
usr << "\blue You deactivate the [src]."
var/obj/effect/overlay/T = new/obj/effect/overlay(get_turf(src))
T.icon = 'icons/effects/effects.dmi'
flick("emppulse",T)
spawn(8) del(T)
else
playsound(src, 'sound/effects/pop.ogg', 100, 1, 1)
var/obj/O = new saved_item(src)
if(!O) return
var/obj/effect/dummy/chameleon/C = new/obj/effect/dummy/chameleon(usr.loc)
C.name = O.name
C.desc = O.desc
C.icon = O.icon
C.icon_state = O.icon_state
C.dir = O.dir
usr.loc = C
C.master = src
src.active_dummy = C
del(O)
usr << "\blue You activate the [src]."
var/obj/effect/overlay/T = new/obj/effect/overlay(get_turf(src))
T.icon = 'icons/effects/effects.dmi'
flick("emppulse",T)
spawn(8) del(T)
proc/disrupt()
if(active_dummy)
var/datum/effect/effect/system/spark_spread/spark_system = new /datum/effect/effect/system/spark_spread
spark_system.set_up(5, 0, src)
spark_system.attach(src)
spark_system.start()
for(var/atom/movable/A in active_dummy)
A.loc = active_dummy.loc
if(ismob(A))
if(A:client)
A:client:eye = A
del(active_dummy)
active_dummy = null
can_use = 0
spawn(100) can_use = 1
/obj/effect/dummy/chameleon
name = ""
desc = ""
density = 0
anchored = 1
var/can_move = 1
var/obj/item/device/chameleon/master = null
attackby()
for(var/mob/M in src)
M << "\red Your chameleon-projector deactivates."
master.disrupt()
attack_hand()
for(var/mob/M in src)
M << "\red Your chameleon-projector deactivates."
master.disrupt()
ex_act()
for(var/mob/M in src)
M << "\red Your chameleon-projector deactivates."
master.disrupt()
bullet_act()
for(var/mob/M in src)
M << "\red Your chameleon-projector deactivates."
..()
master.disrupt()
relaymove(var/mob/user, direction)
if(istype(loc, /turf/space)) return //No magical space movement!
if(can_move)
can_move = 0
switch(usr.bodytemperature)
if(300 to INFINITY)
spawn(10) can_move = 1
if(295 to 300)
spawn(13) can_move = 1
if(280 to 295)
spawn(16) can_move = 1
if(260 to 280)
spawn(20) can_move = 1
else
spawn(25) can_move = 1
step(src,direction)
return
+214
View File
@@ -0,0 +1,214 @@
/obj/item/device/flash
name = "flash"
desc = "Used for blinding and being an asshole."
icon_state = "flash"
item_state = "flashbang" //looks exactly like a flash (and nothing like a flashbang)
throwforce = 5
w_class = 1.0
throw_speed = 4
throw_range = 10
flags = FPRINT | TABLEPASS| CONDUCT
origin_tech = "magnets=2;combat=1"
var/times_used = 0 //Number of times it's been used.
var/broken = 0 //Is the flash burnt out?
var/last_used = 0 //last world.time it was used.
/obj/item/device/flash/proc/clown_check(var/mob/user)
if(user && (CLUMSY in user.mutations) && prob(50))
user << "\red \The [src] slips out of your hand."
user.drop_item()
return 0
return 1
/obj/item/device/flash/proc/flash_recharge()
//capacitor recharges over time
for(var/i=0, i<3, i++)
if(last_used+600 > world.time)
break
last_used += 600
times_used -= 2
last_used = world.time
times_used = max(0,round(times_used)) //sanity
/obj/item/device/flash/attack(mob/living/M as mob, mob/user as mob)
if(!user || !M) return //sanity
M.attack_log += text("\[[time_stamp()]\] <font color='orange'>Has been flashed (attempt) with [src.name] by [user.name] ([user.ckey])</font>")
user.attack_log += text("\[[time_stamp()]\] <font color='red'>Used the [src.name] to flash [M.name] ([M.ckey])</font>")
log_attack("<font color='red'>[user.name] ([user.ckey]) Used the [src.name] to flash [M.name] ([M.ckey])</font>")
if(!clown_check(user)) return
if(broken)
user << "<span class='warning'>\The [src] is broken.</span>"
return
flash_recharge()
//spamming the flash before it's fully charged (60seconds) increases the chance of it breaking
//It will never break on the first use.
switch(times_used)
if(0 to 5)
last_used = world.time
if(prob(times_used)) //if you use it 5 times in a minute it has a 10% chance to break!
broken = 1
user << "<span class='warning'>The bulb has burnt out!</span>"
icon_state = "flashburnt"
return
times_used++
else //can only use it 5 times a minute
user << "<span class='warning'>*click* *click*</span>"
return
playsound(src.loc, 'sound/weapons/flash.ogg', 100, 1)
var/flashfail = 0
if(iscarbon(M))
var/safety = M:eyecheck()
if(safety <= 0)
M.Weaken(10)
flick("e_flash", M.flash)
if(ishuman(M) && ishuman(user) && M.stat!=DEAD)
if(user.mind && user.mind in ticker.mode.head_revolutionaries)
var/revsafe = 0
for(var/obj/item/weapon/implant/loyalty/L in M)
if(L && L.implanted)
revsafe = 1
break
M.mind_initialize() //give them a mind datum if they don't have one.
if(M.mind.has_been_rev)
revsafe = 2
if(!revsafe)
M.mind.has_been_rev = 1
ticker.mode.add_revolutionary(M.mind)
else if(revsafe == 1)
user << "<span class='warning'>Something seems to be blocking the flash!</span>"
else
user << "<span class='warning'>This mind seems resistant to the flash!</span>"
user << "<span class='warning'>This mind is so vacant that it is not susceptible to influence!</span>"
else
flashfail = 1
else if(issilicon(M))
M.Weaken(rand(5,10))
else
flashfail = 1
if(isrobot(user))
spawn(0)
var/atom/movable/overlay/animation = new(user.loc)
animation.layer = user.layer + 1
animation.icon_state = "blank"
animation.icon = 'icons/mob/mob.dmi'
animation.master = user
flick("blspell", animation)
sleep(5)
del(animation)
if(!flashfail)
flick("flash2", src)
if(!issilicon(M))
user.visible_message("<span class='disarm'>[user] blinds [M] with the flash!</span>")
else
user.visible_message("<span class='notice'>[user] overloads [M]'s sensors with the flash!</span>")
else
user.visible_message("<span class='notice'>[user] fails to blind [M] with the flash!</span>")
return
/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
flash_recharge()
//spamming the flash before it's fully charged (60seconds) increases the chance of it breaking
//It will never break on the first use.
switch(times_used)
if(0 to 5)
if(prob(2*times_used)) //if you use it 5 times in a minute it has a 10% chance to break!
broken = 1
user << "<span class='warning'>The bulb has burnt out!</span>"
icon_state = "flashburnt"
return
times_used++
else //can only use it 5 times a minute
user.show_message("<span class='warning'>*click* *click*</span>", 2)
return
playsound(src.loc, 'sound/weapons/flash.ogg', 100, 1)
flick("flash2", src)
if(user && isrobot(user))
spawn(0)
var/atom/movable/overlay/animation = new(user.loc)
animation.layer = user.layer + 1
animation.icon_state = "blank"
animation.icon = 'icons/mob/mob.dmi'
animation.master = user
flick("blspell", animation)
sleep(5)
del(animation)
for(var/mob/living/carbon/M in oviewers(3, null))
if(prob(50))
if (locate(/obj/item/weapon/cloaking_device, M))
for(var/obj/item/weapon/cloaking_device/S in M)
S.active = 0
S.icon_state = "shield0"
var/safety = M:eyecheck()
if(!safety)
if(!M.blinded)
flick("flash", M.flash)
return
/obj/item/device/flash/emp_act(severity)
if(broken) return
flash_recharge()
switch(times_used)
if(0 to 5)
if(prob(2*times_used))
broken = 1
icon_state = "flashburnt"
return
times_used++
if(istype(loc, /mob/living/carbon))
var/mob/living/carbon/M = loc
var/safety = M.eyecheck()
if(safety <= 0)
M.Weaken(10)
flick("e_flash", M.flash)
for(var/mob/O in viewers(M, null))
O.show_message("<span class='disarm'>[M] is blinded by the flash!</span>")
..()
/obj/item/device/flash/synthetic
name = "synthetic flash"
desc = "When a problem arises, SCIENCE is the solution."
icon_state = "sflash"
origin_tech = "magnets=2;combat=1"
var/construction_cost = list("metal"=750,"glass"=750)
var/construction_time=100
/obj/item/device/flash/synthetic/attack(mob/living/M as mob, mob/user as mob)
..()
if(!broken)
broken = 1
user << "\red The bulb has burnt out!"
icon_state = "flashburnt"
/obj/item/device/flash/synthetic/attack_self(mob/living/carbon/user as mob, flag = 0, emp = 0)
..()
if(!broken)
broken = 1
user << "\red The bulb has burnt out!"
icon_state = "flashburnt"
@@ -0,0 +1,167 @@
/obj/item/device/flashlight
name = "flashlight"
desc = "A hand-held emergency light."
icon_state = "flight0"
w_class = 2
item_state = "flight"
flags = FPRINT | TABLEPASS | CONDUCT
slot_flags = SLOT_BELT
m_amt = 50
g_amt = 20
icon_action_button = "action_flashlight"
var/on = 0
var/brightness_on = 4 //luminosity when on
var/icon_on = "flight1"
var/icon_off = "flight0"
/obj/item/device/flashlight/initialize()
..()
if (on)
icon_state = icon_on
src.SetLuminosity(brightness_on)
else
icon_state = icon_off
src.SetLuminosity(0)
/obj/item/device/flashlight/proc/update_brightness(var/mob/user = null)
if(on)
icon_state = icon_on
if(src.loc == user)
user.SetLuminosity(user.luminosity + brightness_on)
else if(isturf(loc))
SetLuminosity(brightness_on)
else
icon_state = icon_off
if(src.loc == user)
user.SetLuminosity(user.luminosity - brightness_on)
else if(isturf(loc))
SetLuminosity(0)
/obj/item/device/flashlight/attack_self(mob/user)
if(!isturf(user.loc))
user << "You cannot turn the light on while in this [user.loc]" //To prevent some lighting anomalities.
return
on = !on
update_brightness(user)
return
/obj/item/device/flashlight/attack(mob/living/M as mob, mob/living/user as mob)
src.add_fingerprint(user)
if(src.on && user.zone_sel.selecting == "eyes")
if (((CLUMSY in user.mutations) || user.getBrainLoss() >= 60) && prob(50))//too dumb to use flashlight properly
return ..()//just hit them in the head
if (!(istype(usr, /mob/living/carbon/human) || ticker) && ticker.mode.name != "monkey")//don't have dexterity
usr.show_message("\red You don't have the dexterity to do this!",1)
return
var/mob/living/carbon/human/H = M//mob has protective eyewear
if(istype(M, /mob/living/carbon/human) && ((H.head && H.head.flags & HEADCOVERSEYES) || (H.wear_mask && H.wear_mask.flags & MASKCOVERSEYES) || (H.glasses && H.glasses.flags & GLASSESCOVERSEYES)))
user << text("\blue You're going to need to remove that [] first.", ((H.head && H.head.flags & HEADCOVERSEYES) ? "helmet" : ((H.wear_mask && H.wear_mask.flags & MASKCOVERSEYES) ? "mask": "glasses")))
return
for(var/mob/O in viewers(M, null))//echo message
if ((O.client && !(O.blinded )))
O.show_message("\blue [(O==user?"You direct":"[user] directs")] [src] to [(M==user? "your":"[M]")] eyes", 1)
if(istype(M, /mob/living/carbon/human) || istype(M, /mob/living/carbon/monkey))//robots and aliens are unaffected
if(M.stat == DEAD || M.sdisabilities & BLIND)//mob is dead or fully blind
if(M!=user)
user.show_message("\red [M] pupils does not react to the light!",1)
else if(XRAY in M.mutations)//mob has X-RAY vision
if(M!=user)
user.show_message("\red [M] pupils give an eerie glow!",1)
else //nothing wrong
if(!M.blinded)
flick("flash", M.flash)//flash the affected mob
if(M!=user)
user.show_message("\blue [M] pupils narrow",1)
else
return ..()
/obj/item/device/flashlight/pickup(mob/user)
if(on)
user.SetLuminosity(user.luminosity + brightness_on)
SetLuminosity(0)
/obj/item/device/flashlight/dropped(mob/user)
if(on)
user.SetLuminosity(user.luminosity - brightness_on)
SetLuminosity(brightness_on)
/obj/item/device/flashlight/pen
name = "penlight"
desc = "A pen-sized light. It shines as well as a flashlight."
icon_state = "plight0"
flags = FPRINT | TABLEPASS | CONDUCT
item_state = ""
icon_on = "plight1"
icon_off = "plight0"
brightness_on = 3
/obj/item/device/flashlight/pen/paralysis/attack(mob/M as mob, mob/user as mob)
if(!ismob(M))
return
user << "\red You stab [M] with the pen."
M << "\red You feel a tiny prick!"
M.attack_log += text("\[[time_stamp()]\] <font color='orange'>Has been stabbed with [src.name] by [user.name] ([user.ckey])</font>")
user.attack_log += text("\[[time_stamp()]\] <font color='red'>Used the [src.name] to stab [M.name] ([M.ckey])</font>")
log_attack("<font color='red'>[user.name] ([user.ckey]) Used the [src.name] to stab [M.name] ([M.ckey])</font>")
..()
return
/obj/item/device/flashlight/pen/paralysis/New()
var/datum/reagents/R = new/datum/reagents(15)
reagents = R
R.my_atom = src
R.add_reagent("zombiepowder", 15)
..()
return
/obj/item/device/flashlight/pen/paralysis/attack(mob/M as mob, mob/user as mob)
if (!( istype(M, /mob) ))
return
..()
if (reagents.total_volume)
if(M.reagents) reagents.trans_to(M, 15)
return
// the desk lamps are a bit special
/obj/item/device/flashlight/lamp
name = "desk lamp"
desc = "A desk lamp"
icon = 'icons/obj/lighting.dmi'
icon_state = "lamp0"
brightness_on = 5
icon_on = "lamp1"
icon_off = "lamp0"
w_class = 4
flags = FPRINT | TABLEPASS | CONDUCT
m_amt = 0
g_amt = 0
on = 1
// green-shaded desk lamp
/obj/item/device/flashlight/lamp/green
icon_state = "green0"
icon_on = "green1"
icon_off = "green0"
desc = "A green-shaded desk lamp"
/obj/item/device/flashlight/lamp/verb/toggle_light()
set name = "Toggle light"
set category = "Object"
set src in oview(1)
if(!usr.stat)
attack_self(usr)
@@ -0,0 +1,210 @@
// Light Replacer (LR)
//
// ABOUT THE DEVICE
//
// This is a device supposedly to be used by Janitors and Janitor Cyborgs which will
// allow them to easily replace lights. This was mostly designed for Janitor Cyborgs since
// they don't have hands or a way to replace lightbulbs.
//
// HOW IT WORKS
//
// You attack a light fixture with it, if the light fixture is broken it will replace the
// light fixture with a working light; the broken light is then placed on the floor for the
// user to then pickup with a trash bag. If it's empty then it will just place a light in the fixture.
//
// HOW TO REFILL THE DEVICE
//
// It will need to be manually refilled with lights.
// If it's part of a robot module, it will charge when the Robot is inside a Recharge Station.
//
// EMAGGED FEATURES
//
// NOTICE: The Cyborg cannot use the emagged Light Replacer and the light's explosion was nerfed. It cannot create holes in the station anymore.
//
// I'm not sure everyone will react the emag's features so please say what your opinions are of it.
//
// When emagged it will rig every light it replaces, which will explode when the light is on.
// This is VERY noticable, even the device's name changes when you emag it so if anyone
// examines you when you're holding it in your hand, you will be discovered.
// It will also be very obvious who is setting all these lights off, since only Janitor Borgs and Janitors have easy
// access to them, and only one of them can emag their device.
//
// The explosion cannot insta-kill anyone with 30% or more health.
#define LIGHT_OK 0
#define LIGHT_EMPTY 1
#define LIGHT_BROKEN 2
#define LIGHT_BURNED 3
/obj/item/device/lightreplacer
name = "light replacer"
desc = "A device to automatically replace lights. Refill with working lightbulbs."
icon = 'icons/obj/janitor.dmi'
icon_state = "lightreplacer0"
item_state = "electronic"
flags = FPRINT | CONDUCT
slot_flags = SLOT_BELT
origin_tech = "magnets=3;materials=2"
var/max_uses = 20
var/uses = 0
var/inuse = 0
var/emagged = 0
var/failmsg = ""
// How much to increase per each glass?
var/increment = 5
// How much to take from the glass?
var/decrement = 1
var/charge = 1
/obj/item/device/lightreplacer/New()
uses = max_uses / 2
failmsg = "The [name]'s refill light blinks red."
..()
/obj/item/device/lightreplacer/examine()
set src in view(2)
..()
usr << "It has [uses] lights remaining."
/obj/item/device/lightreplacer/attackby(obj/item/W, mob/user)
if(istype(W, /obj/item/weapon/card/emag) && emagged == 0)
Emag()
return
if(istype(W, /obj/item/stack/sheet/glass))
var/obj/item/stack/sheet/glass/G = W
if(G.amount - decrement >= 0 && uses < max_uses)
var/remaining = max(G.amount - decrement, 0)
if(!remaining && !(G.amount - decrement) == 0)
user << "There isn't enough glass."
return
G.amount = remaining
if(!G.amount)
user.drop_item()
del(G)
AddUses(increment)
user << "You insert a piece of glass into the [src.name]. You have [uses] lights remaining."
return
if(istype(W, /obj/item/weapon/light))
var/obj/item/weapon/light/L = W
if(L.status == 0) // LIGHT OKAY
if(uses < max_uses)
AddUses(1)
user << "You insert the [L.name] into the [src.name]. You have [uses] lights remaining."
user.drop_item()
del(L)
return
else
user << "You need a working light."
return
/obj/item/device/lightreplacer/attack_self(mob/user)
/* // This would probably be a bit OP. If you want it though, uncomment the code.
if(isrobot(user))
var/mob/living/silicon/robot/R = user
if(R.emagged)
src.Emag()
usr << "You shortcircuit the [src]."
return
*/
usr << "It has [uses] lights remaining."
/obj/item/device/lightreplacer/update_icon()
icon_state = "lightreplacer[emagged]"
/obj/item/device/lightreplacer/proc/Use(var/mob/user)
if(inuse) return
playsound(src.loc, 'sound/machines/click.ogg', 50, 1)
var/pass = 0
inuse = 1
if(do_after(user, 30))
playsound(src.loc, 'sound/items/Deconstruct.ogg', 50, 1)
AddUses(-1)
pass = 1
inuse = 0
return pass
// Negative numbers will subtract
/obj/item/device/lightreplacer/proc/AddUses(var/amount = 1)
uses = min(max(uses + amount, 0), max_uses)
/obj/item/device/lightreplacer/proc/Charge(var/mob/user)
charge += 1
if(charge > 7)
AddUses(1)
charge = 1
/obj/item/device/lightreplacer/proc/ReplaceLight(var/obj/machinery/light/target, var/mob/living/U)
if(target.status != LIGHT_OK)
if(CanUse(U))
if(!Use(U)) return
U << "<span class='notice'>You replace the [target.fitting] with the [src].</span>"
if(target.status != LIGHT_EMPTY)
var/obj/item/weapon/light/L1 = new target.light_type(target.loc)
L1.status = target.status
L1.rigged = target.rigged
L1.brightness = target.brightness
L1.switchcount = target.switchcount
target.switchcount = 0
L1.update()
target.status = LIGHT_EMPTY
target.update()
var/obj/item/weapon/light/L2 = new target.light_type()
target.status = L2.status
target.switchcount = L2.switchcount
target.rigged = emagged
target.brightness = L2.brightness
target.on = target.has_power()
target.update()
del(L2)
if(target.on && target.rigged)
target.explode()
return
else
U << failmsg
return
else
U << "There is a working [target.fitting] already inserted."
return
/obj/item/device/lightreplacer/proc/Emag()
emagged = !emagged
playsound(src.loc, "sparks", 100, 1)
if(emagged)
name = "Shortcircuited [initial(name)]"
else
name = initial(name)
update_icon()
//Can you use it?
/obj/item/device/lightreplacer/proc/CanUse(var/mob/living/user)
src.add_fingerprint(user)
//Not sure what else to check for. Maybe if clumsy?
if(uses > 0)
return 1
else
return 0
#undef LIGHT_OK
#undef LIGHT_EMPTY
#undef LIGHT_BROKEN
#undef LIGHT_BURNED
@@ -0,0 +1,18 @@
/**
* Multitool -- A multitool is used for hacking electronic devices.
* TO-DO -- Using it as a power measurement tool for cables etc. Nannek.
*
*/
/obj/item/device/multitool
name = "multitool"
icon_state = "multitool"
flags = FPRINT | TABLEPASS| CONDUCT
force = 5.0
w_class = 2.0
throwforce = 5.0
throw_range = 15
throw_speed = 3
desc = "You can use this on airlocks or APCs to try to hack them without cutting wires."
m_amt = 50
g_amt = 20
origin_tech = "magnets=1"
+136
View File
@@ -0,0 +1,136 @@
/obj/item/device/paicard
name = "personal AI device"
icon = 'icons/obj/pda.dmi'
icon_state = "pai"
item_state = "electronic"
w_class = 2.0
flags = FPRINT | TABLEPASS
slot_flags = SLOT_BELT
origin_tech = "programming=2"
var/obj/item/device/radio/radio
var/looking_for_personality = 0
var/mob/living/silicon/pai/pai
/obj/item/device/paicard/New()
..()
overlays += "pai-off"
/obj/item/device/paicard/Del()
//Will stop people throwing friend pAIs into the singularity so they can respawn
if(!isnull(pai))
pai.death(0)
..()
/obj/item/device/paicard/attack_self(mob/user)
if (!in_range(src, user))
return
user.machine = src
var/dat = "<TT><B>Personal AI Device</B><BR>"
if(pai && (!pai.master_dna || !pai.master))
dat += "<a href='byond://?src=\ref[src];setdna=1'>Imprint Master DNA</a><br>"
if(pai)
dat += "Installed Personality: [pai.name]<br>"
dat += "Prime directive: <br>[pai.pai_law0]<br>"
dat += "Additional directives: <br>[pai.pai_laws]<br>"
dat += "<a href='byond://?src=\ref[src];setlaws=1'>Configure Directives</a><br>"
dat += "<br>"
dat += "<h3>Device Settings</h3><br>"
if(radio)
dat += "<b>Radio Uplink</b><br>"
dat += "Transmit: <A href='byond://?src=\ref[src];wires=4'>[(radio.wires & 4) ? "Enabled" : "Disabled"]</A><br>"
dat += "Receive: <A href='byond://?src=\ref[src];wires=2'>[(radio.wires & 2) ? "Enabled" : "Disabled"]</A><br>"
dat += "Signal Pulser: <A href='byond://?src=\ref[src];wires=1'>[(radio.wires & 1) ? "Enabled" : "Disabled"]</A><br>"
else
dat += "<b>Radio Uplink</b><br>"
dat += "<font color=red><i>Radio firmware not loaded. Please install a pAI personality to load firmware.</i></font><br>"
dat += "<A href='byond://?src=\ref[src];wipe=1'>\[Wipe current pAI personality\]</a><br>"
else
if(looking_for_personality)
dat += "Searching for a personality..."
dat += "<A href='byond://?src=\ref[src];request=1'>\[View available personalities\]</a><br>"
else
dat += "No personality is installed.<br>"
dat += "<A href='byond://?src=\ref[src];request=1'>\[Request personal AI personality\]</a><br>"
dat += "Each time this button is pressed, a request will be sent out to any available personalities. Check back often and alot time for personalities to respond. This process could take anywhere from 15 seconds to several minutes, depending on the available personalities' timeliness."
user << browse(dat, "window=paicard")
onclose(user, "paicard")
return
/obj/item/device/paicard/Topic(href, href_list)
if(href_list["setdna"])
if(pai.master_dna)
return
var/mob/M = usr
if(!istype(M, /mob/living/carbon))
usr << "<font color=blue>You don't have any DNA, or your DNA is incompatible with this device.</font>"
else
var/datum/dna/dna = usr.dna
pai.master = M.real_name
pai.master_dna = dna.unique_enzymes
pai << "<font color = red><h3>You have been bound to a new master.</h3></font>"
if(href_list["request"])
src.looking_for_personality = 1
paiController.findPAI(src, usr)
if(href_list["wipe"])
var/confirm = input("Are you CERTAIN you wish to delete the current personality? This action cannot be undone.", "Personality Wipe") in list("Yes", "No")
if(confirm == "Yes")
for(var/mob/M in src)
M << "<font color = #ff0000><h2>You feel yourself slipping away from reality.</h2></font>"
M << "<font color = #ff4d4d><h3>Byte by byte you lose your sense of self.</h3></font>"
M << "<font color = #ff8787><h4>Your mental faculties leave you.</h4></font>"
M << "<font color = #ffc4c4><h5>oblivion... </h5></font>"
M.death(0)
removePersonality()
if(href_list["wires"])
var/t1 = text2num(href_list["wires"])
if (radio.wires & t1)
radio.wires &= ~t1
else
radio.wires |= t1
if(href_list["setlaws"])
var/newlaws = copytext(sanitize(input("Enter any additional directives you would like your pAI personality to follow. Note that these directives will not override the personality's allegiance to its imprinted master. Conflicting directives will be ignored.", "pAI Directive Configuration", pai.pai_laws) as message),1,MAX_MESSAGE_LEN)
if(newlaws)
pai.pai_laws = newlaws
pai << "Your supplemental directives have been updated. Your new directives are:"
pai << "Prime Directive : <br>[pai.pai_law0]"
pai << "Supplemental Directives: <br>[pai.pai_laws]"
attack_self(usr)
// WIRE_SIGNAL = 1
// WIRE_RECEIVE = 2
// WIRE_TRANSMIT = 4
/obj/item/device/paicard/proc/setPersonality(mob/living/silicon/pai/personality)
src.pai = personality
src.overlays += "pai-happy"
/obj/item/device/paicard/proc/removePersonality()
src.pai = null
src.overlays = null
src.overlays += "pai-off"
/obj/item/device/paicard/proc/setEmotion(var/emotion)
if(pai)
src.overlays = null
switch(emotion)
if(1) src.overlays += "pai-happy"
if(2) src.overlays += "pai-cat"
if(3) src.overlays += "pai-extremely-happy"
if(4) src.overlays += "pai-face"
if(5) src.overlays += "pai-laugh"
if(6) src.overlays += "pai-off"
if(7) src.overlays += "pai-sad"
if(8) src.overlays += "pai-angry"
if(9) src.overlays += "pai-what"
/obj/item/device/paicard/proc/alertUpdate()
var/turf/T = get_turf_or_move(src.loc)
for (var/mob/M in viewers(T))
M.show_message("\blue [src] flashes a message across its screen, \"Additional personalities available for download.\"", 3, "\blue [src] bleeps electronically.", 2)
/obj/item/device/paicard/emp_act(severity)
for(var/mob/M in src)
M.emp_act(severity)
..()
@@ -0,0 +1,120 @@
// Powersink - used to drain station power
/obj/item/device/powersink
desc = "A nulling power sink which drains energy from electrical systems."
name = "power sink"
icon_state = "powersink0"
item_state = "electronic"
w_class = 4.0
flags = FPRINT | TABLEPASS | CONDUCT
throwforce = 5
throw_speed = 1
throw_range = 2
m_amt = 750
w_amt = 750
origin_tech = "powerstorage=3;syndicate=5"
var/drain_rate = 600000 // amount of power to drain per tick
var/power_drained = 0 // has drained this much power
var/max_power = 1e8 // maximum power that can be drained before exploding
var/mode = 0 // 0 = off, 1=clamped (off), 2=operating
var/obj/structure/cable/attached // the attached cable
attackby(var/obj/item/I, var/mob/user)
if(istype(I, /obj/item/weapon/screwdriver))
if(mode == 0)
var/turf/T = loc
if(isturf(T) && !T.intact)
attached = locate() in T
if(!attached)
user << "No exposed cable here to attach to."
return
else
anchored = 1
mode = 1
user << "You attach the device to the cable."
for(var/mob/M in viewers(user))
if(M == user) continue
M << "[user] attaches the power sink to the cable."
return
else
user << "Device must be placed over an exposed cable to attach to it."
return
else
if (mode == 2)
processing_objects.Remove(src) // Now the power sink actually stops draining the station's power if you unhook it. --NeoFite
anchored = 0
mode = 0
user << "You detach the device from the cable."
for(var/mob/M in viewers(user))
if(M == user) continue
M << "[user] detaches the power sink from the cable."
SetLuminosity(0)
icon_state = "powersink0"
return
else
..()
attack_paw()
return
attack_ai()
return
attack_hand(var/mob/user)
switch(mode)
if(0)
..()
if(1)
user << "You activate the device!"
for(var/mob/M in viewers(user))
if(M == user) continue
M << "[user] activates the power sink!"
mode = 2
icon_state = "powersink1"
processing_objects.Add(src)
if(2) //This switch option wasn't originally included. It exists now. --NeoFite
user << "You deactivate the device!"
for(var/mob/M in viewers(user))
if(M == user) continue
M << "[user] deactivates the power sink!"
mode = 1
SetLuminosity(0)
icon_state = "powersink0"
processing_objects.Remove(src)
process()
if(attached)
var/datum/powernet/PN = attached.get_powernet()
if(PN)
SetLuminosity(12)
// found a powernet, so drain up to max power from it
var/drained = min ( drain_rate, PN.avail )
PN.newload += drained
power_drained += drained
// if tried to drain more than available on powernet
// now look for APCs and drain their cells
if(drained < drain_rate)
for(var/obj/machinery/power/terminal/T in PN.nodes)
if(istype(T.master, /obj/machinery/power/apc))
var/obj/machinery/power/apc/A = T.master
if(A.operating && A.cell)
A.cell.charge = max(0, A.cell.charge - 50)
power_drained += 50
if(power_drained > max_power * 0.95)
playsound(src, 'sound/effects/screech.ogg', 100, 1, 1)
if(power_drained >= max_power)
processing_objects.Remove(src)
explosion(src.loc, 3,6,9,12)
del(src)
@@ -0,0 +1,49 @@
/obj/item/device/radio/beacon
name = "Tracking Beacon"
desc = "A beacon used by a teleporter."
icon_state = "beacon"
item_state = "signaler"
var/code = "electronic"
origin_tech = "bluespace=1"
/obj/item/device/radio/beacon/hear_talk()
return
/obj/item/device/radio/beacon/send_hear()
return null
/obj/item/device/radio/beacon/verb/alter_signal(t as text)
set name = "Alter Beacon's Signal"
set category = "Object"
set src in usr
if ((usr.canmove && !( usr.restrained() )))
src.code = t
if (!( src.code ))
src.code = "beacon"
src.add_fingerprint(usr)
return
/obj/item/device/radio/beacon/bacon //Probably a better way of doing this, I'm lazy.
proc/digest_delay()
spawn(600)
del(src)
// SINGULO BEACON SPAWNER
/obj/item/device/radio/beacon/syndicate
name = "suspicious beacon"
desc = "A label on it reads: <i>Activate to have a singularity beacon teleported to your location</i>."
origin_tech = "bluespace=1;syndicate=7"
/obj/item/device/radio/beacon/syndicate/attack_self(mob/user as mob)
if(user)
user << "\blue Locked In"
new /obj/machinery/singularity_beacon/syndicate( user.loc )
playsound(src, 'sound/effects/pop.ogg', 100, 1, 1)
del(src)
return
@@ -0,0 +1,164 @@
/obj/item/device/radio/electropack
name = "Electropack"
desc = "Dance my monkeys! DANCE!!!"
icon_state = "electropack0"
var/code = 2
var/e_pads = 0.0
g_amt = 2500
m_amt = 10000
frequency = 1449
w_class = 5.0
flags = FPRINT | CONDUCT | TABLEPASS
slot_flags = SLOT_BACK
item_state = "electropack"
/obj/item/device/radio/electropack/examine()
set src in view()
..()
if ((in_range(src, usr) || src.loc == usr))
if (src.e_pads)
usr << "\blue The electric pads are exposed!"
return
/obj/item/device/radio/electropack/attack_paw(mob/user as mob)
return src.attack_hand(user)
return
/obj/item/device/radio/electropack/attack_hand(mob/user as mob)
if (src == user.back)
user << "\blue You need help taking this off!"
return
else
..()
return
/obj/item/device/radio/electropack/attackby(obj/item/weapon/W as obj, mob/user as mob)
..()
if (istype(W, /obj/item/weapon/screwdriver))
src.e_pads = !( src.e_pads )
if (src.e_pads)
user.show_message("\blue The electric pads have been exposed!")
else
user.show_message("\blue The electric pads have been reinserted!")
src.add_fingerprint(user)
return
else
if (istype(W, /obj/item/clothing/head/helmet))
var/obj/item/assembly/shock_kit/A = new /obj/item/assembly/shock_kit( user )
A.icon = 'icons/obj/assemblies.dmi'
user.drop_from_inventory(W)
W.loc = A
W.master = A
A.part1 = W
user.drop_from_inventory(src)
src.loc = A
src.master = A
A.part2 = src
user.put_in_hands(A)
A.add_fingerprint(user)
return
/obj/item/device/radio/electropack/Topic(href, href_list)
//..()
if (usr.stat || usr.restrained())
return
if (((istype(usr, /mob/living/carbon/human) && ((!( ticker ) || (ticker && ticker.mode != "monkey")) && usr.contents.Find(src))) || (usr.contents.Find(src.master) || (in_range(src, usr) && istype(src.loc, /turf)))))
usr.machine = src
if (href_list["freq"])
var/new_frequency = sanitize_frequency(frequency + text2num(href_list["freq"]))
set_frequency(new_frequency)
else
if (href_list["code"])
src.code += text2num(href_list["code"])
src.code = round(src.code)
src.code = min(100, src.code)
src.code = max(1, src.code)
else
if (href_list["power"])
src.on = !( src.on )
src.icon_state = text("electropack[]", src.on)
if (!( src.master ))
if (istype(src.loc, /mob))
attack_self(src.loc)
else
for(var/mob/M in viewers(1, src))
if (M.client)
src.attack_self(M)
//Foreach goto(308)
else
if (istype(src.master.loc, /mob))
src.attack_self(src.master.loc)
else
for(var/mob/M in viewers(1, src.master))
if (M.client)
src.attack_self(M)
//Foreach goto(384)
else
usr << browse(null, "window=radio")
return
return
/*
/obj/item/device/radio/electropack/accept_rad(obj/item/device/radio/signaler/R as obj, message)
if ((istype(R, /obj/item/device/radio/signaler) && R.frequency == src.frequency && R.code == src.code))
return 1
else
return null
return*/
/obj/item/device/radio/electropack/receive_signal(datum/signal/signal)
if(!signal || (signal.encryption != code))
return
if ((ismob(src.loc) && src.on))
var/mob/M = src.loc
var/turf/T = M.loc
if ((istype(T, /turf)))
if (!M.moved_recently && M.last_move)
M.moved_recently = 1
step(M, M.last_move)
sleep 50
if(M)
M.moved_recently = 0
M.show_message("\red <B>You feel a sharp shock!</B>")
var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread
s.set_up(3, 1, M)
s.start()
M.Weaken(10)
if ((src.master && src.wires & 1))
src.master.receive_signal()
return
/obj/item/device/radio/electropack/attack_self(mob/user as mob, flag1)
if (!( istype(user, /mob/living/carbon/human) ))
return
user.machine = src
var/dat = {"<TT>
<A href='?src=\ref[src];power=1'>Turn [src.on ? "Off" : "On"]</A><BR>
<B>Frequency/Code</B> for electropack:<BR>
Frequency:
<A href='byond://?src=\ref[src];freq=-10'>-</A>
<A href='byond://?src=\ref[src];freq=-2'>-</A> [format_frequency(src.frequency)]
<A href='byond://?src=\ref[src];freq=2'>+</A>
<A href='byond://?src=\ref[src];freq=10'>+</A><BR>
Code:
<A href='byond://?src=\ref[src];code=-5'>-</A>
<A href='byond://?src=\ref[src];code=-1'>-</A> [src.code]
<A href='byond://?src=\ref[src];code=1'>+</A>
<A href='byond://?src=\ref[src];code=5'>+</A><BR>
</TT>"}
user << browse(dat, "window=radio")
onclose(user, "radio")
return
@@ -0,0 +1,128 @@
/obj/item/device/encryptionkey/
name = "Standard Encrpytion Key"
desc = "An encyption key for a radio headset. Has no special codes in it. WHY DOES IT EXIST? ASK NANOTRASEN."
icon = 'icons/obj/radio.dmi'
icon_state = "cypherkey"
item_state = ""
var/translate_binary = 0
var/translate_hive = 0
var/syndie = 0
var/list/channels = list()
/obj/item/device/encryptionkey/New()
/obj/item/device/encryptionkey/attackby(obj/item/weapon/W as obj, mob/user as mob)
/obj/item/device/encryptionkey/syndicate
icon_state = "cypherkey"
channels = list("Syndicate" = 1)
origin_tech = "syndicate=3"
syndie = 1//Signifies that it de-crypts Syndicate transmissions
/obj/item/device/encryptionkey/binary
icon_state = "cypherkey"
translate_binary = 1
origin_tech = "syndicate=3"
/obj/item/device/encryptionkey/headset_sec
name = "Security Radio Encryption Key"
desc = "An encyption key for a radio headset. Contains cypherkeys."
icon_state = "sec_cypherkey"
channels = list("Security" = 1)
/obj/item/device/encryptionkey/headset_eng
name = "Engineering Radio Encryption Key"
desc = "An encyption key for a radio headset. Contains cypherkeys."
icon_state = "eng_cypherkey"
channels = list("Engineering" = 1)
/obj/item/device/encryptionkey/headset_rob
name = "Robotics Radio Encryption Key"
desc = "An encyption key for a radio headset. Contains cypherkeys."
icon_state = "rob_cypherkey"
channels = list("Engineering" = 1, "Science" = 1)
/obj/item/device/encryptionkey/headset_med
name = "Medical Radio Encryption Key"
desc = "An encyption key for a radio headset. Contains cypherkeys."
icon_state = "med_cypherkey"
channels = list("Medical" = 1)
/obj/item/device/encryptionkey/headset_sci
name = "Science Radio Encryption Key"
desc = "An encyption key for a radio headset. Contains cypherkeys."
icon_state = "sci_cypherkey"
channels = list("Science" = 1)
/obj/item/device/encryptionkey/headset_medsci
name = "Medical Research Radio Encryption Key"
desc = "An encyption key for a radio headset. Contains cypherkeys."
icon_state = "medsci_cypherkey"
channels = list("Medical" = 1, "Science" = 1)
/obj/item/device/encryptionkey/headset_com
name = "Command Radio Encryption Key"
desc = "An encyption key for a radio headset. Contains cypherkeys."
icon_state = "com_cypherkey"
channels = list("Command" = 1)
/obj/item/device/encryptionkey/heads/captain
name = "Captain's Encryption Key"
desc = "An encyption key for a radio headset. Contains cypherkeys."
icon_state = "cap_cypherkey"
channels = list("Command" = 1, "Science" = 0, "Medical" = 0, "Security" = 1, "Engineering" = 0, "Mining" = 0, "Cargo" = 0)
/obj/item/device/encryptionkey/heads/rd
name = "Research Director's Encryption Key"
desc = "An encyption key for a radio headset. Contains cypherkeys."
icon_state = "rd_cypherkey"
channels = list("Science" = 1, "Command" = 1)
/obj/item/device/encryptionkey/heads/hos
name = "Head of Security's Encryption Key"
desc = "An encyption key for a radio headset. Contains cypherkeys."
icon_state = "hos_cypherkey"
channels = list("Security" = 1, "Command" = 1)
/obj/item/device/encryptionkey/heads/ce
name = "Chief Engineer's Encryption Key"
desc = "An encyption key for a radio headset. Contains cypherkeys."
icon_state = "ce_cypherkey"
channels = list("Engineering" = 1, "Command" = 1)
/obj/item/device/encryptionkey/heads/cmo
name = "Chief Medical Officer's Encryption Key"
desc = "An encyption key for a radio headset. Contains cypherkeys."
icon_state = "cmo_cypherkey"
channels = list("Medical" = 1, "Command" = 1)
/obj/item/device/encryptionkey/heads/hop
name = "Head of Personnel's Encryption Key"
desc = "An encyption key for a radio headset. Contains cypherkeys."
icon_state = "hop_cypherkey"
channels = list("Command" = 1, "Security" = 0, "Cargo" = 1, "Mining" = 0)
/obj/item/device/encryptionkey/headset_mine
name = "Mining Radio Encryption Key"
desc = "An encyption key for a radio headset. Contains cypherkeys."
icon_state = "mine_cypherkey"
channels = list("Mining" = 1)
/obj/item/device/encryptionkey/heads/qm
name = "Quartermaster's Encryption Key"
desc = "An encyption key for a radio headset. Contains cypherkeys."
icon_state = "qm_cypherkey"
channels = list("Cargo" = 1, "Mining" = 1)
/obj/item/device/encryptionkey/headset_cargo
name = "Cargo Radio Encryption Key"
desc = "An encyption key for a radio headset. Contains cypherkeys."
icon_state = "cargo_cypherkey"
channels = list("Cargo" = 1)
/obj/item/device/encryptionkey/ert
name = "NanoTrasen ERT Radio Encryption Key"
desc = "An encyption key for a radio headset. Contains cypherkeys."
channels = list("Response Team" = 1, "Science" = 1, "Command" = 1, "Medical" = 1, "Engineering" = 1, "Security" = 1, "Mining" = 1, "Cargo" = 1,)
@@ -0,0 +1,264 @@
/obj/item/device/radio/headset
name = "radio headset"
desc = "An updated, modular intercom that fits over the head. Takes encryption keys"
icon_state = "headset"
item_state = "headset"
g_amt = 0
m_amt = 75
subspace_transmission = 1
canhear_range = 1 // can't hear headsets from very far away
slot_flags = SLOT_EARS
var/translate_binary = 0
var/translate_hive = 0
var/obj/item/device/encryptionkey/keyslot1 = null
var/obj/item/device/encryptionkey/keyslot2 = null
maxf = 1489
/obj/item/device/radio/headset/New()
..()
keyslot1 = new /obj/item/device/encryptionkey/
recalculateChannels()
/obj/item/device/radio/headset/syndicate
origin_tech = "syndicate=3"
/obj/item/device/radio/headset/syndicate/New()
..()
del(keyslot1)
keyslot1 = new /obj/item/device/encryptionkey/syndicate
syndie = 1
recalculateChannels()
/obj/item/device/radio/headset/binary
origin_tech = "syndicate=3"
/obj/item/device/radio/headset/binary/New()
..()
del(keyslot1)
keyslot1 = new /obj/item/device/encryptionkey/binary
recalculateChannels()
/obj/item/device/radio/headset/headset_sec
name = "security radio headset"
desc = "This is used by your elite security force. To access the security channel, use :s."
icon_state = "sec_headset"
item_state = "headset"
keyslot2 = new /obj/item/device/encryptionkey/headset_sec
/obj/item/device/radio/headset/headset_eng
name = "engineering radio headset"
desc = "When the engineers wish to chat like girls. To access the engineering channel, use :e. "
icon_state = "eng_headset"
item_state = "headset"
keyslot2 = new /obj/item/device/encryptionkey/headset_eng
/obj/item/device/radio/headset/headset_rob
name = "robotics radio headset"
desc = "Made specifically for the roboticists who cannot decide between departments. To access the engineering channel, use :e. For research, use :n."
icon_state = "rob_headset"
item_state = "headset"
keyslot2 = new /obj/item/device/encryptionkey/headset_rob
/obj/item/device/radio/headset/headset_med
name = "medical radio headset"
desc = "A headset for the trained staff of the medbay. To access the medical channel, use :m."
icon_state = "med_headset"
item_state = "headset"
keyslot2 = new /obj/item/device/encryptionkey/headset_med
/obj/item/device/radio/headset/headset_sci
name = "science radio headset"
desc = "A sciency headset. Like usual. To access the science channel, use :n."
icon_state = "com_headset"
item_state = "headset"
keyslot2 = new /obj/item/device/encryptionkey/headset_sci
/obj/item/device/radio/headset/headset_medsci
name = "medical research radio headset"
desc = "A headset that is a result of the mating between medical and science. To access the medical channel, use :m. For science, use :n."
icon_state = "med_headset"
item_state = "headset"
keyslot2 = new /obj/item/device/encryptionkey/headset_medsci
/obj/item/device/radio/headset/headset_com
name = "command radio headset"
desc = "A headset with a commanding channel. To access the command channel, use :c."
icon_state = "com_headset"
item_state = "headset"
keyslot2 = new /obj/item/device/encryptionkey/headset_com
/obj/item/device/radio/headset/heads/captain
name = "captain's headset"
desc = "The headset of the boss. Channels are as follows: :c - command, :s - security, :e - engineering, :d - mining, :q - cargo, :m - medical, :n - science."
icon_state = "com_headset"
item_state = "headset"
keyslot2 = new /obj/item/device/encryptionkey/heads/captain
/obj/item/device/radio/headset/heads/rd
name = "Research Director's headset"
desc = "Headset of the researching God. To access the science channel, use :n. For command, use :c."
icon_state = "com_headset"
item_state = "headset"
keyslot2 = new /obj/item/device/encryptionkey/heads/rd
/obj/item/device/radio/headset/heads/hos
name = "head of security's headset"
desc = "The headset of the man who protects your worthless lifes. To access the security channel, use :s. For command, use :c."
icon_state = "com_headset"
item_state = "headset"
keyslot2 = new /obj/item/device/encryptionkey/heads/hos
/obj/item/device/radio/headset/heads/ce
name = "chief engineer's headset"
desc = "The headset of the guy who is in charge of morons. To access the engineering channel, use :e. For command, use :c."
icon_state = "com_headset"
item_state = "headset"
keyslot2 = new /obj/item/device/encryptionkey/heads/ce
/obj/item/device/radio/headset/heads/cmo
name = "chief medical officer's headset"
desc = "The headset of the highly trained medical chief. To access the medical channel, use :m. For command, use :c."
icon_state = "com_headset"
item_state = "headset"
keyslot2 = new /obj/item/device/encryptionkey/heads/cmo
/obj/item/device/radio/headset/heads/hop
name = "head of personnel's headset"
desc = "The headset of the guy who will one day be captain. Channels are as follows: :c - command, :s - security, :q - cargo, :d - mining."
icon_state = "com_headset"
item_state = "headset"
keyslot2 = new /obj/item/device/encryptionkey/heads/hop
/obj/item/device/radio/headset/headset_mine
name = "mining radio headset"
desc = "Headset used by miners. How useless. To access the mining channel, use :d."
icon_state = "mine_headset"
item_state = "headset"
keyslot2 = new /obj/item/device/encryptionkey/headset_mine
/obj/item/device/radio/headset/heads/qm
name = "quartermaster's headset"
desc = "The headset of the man who control your toiletpaper supply. To access the cargo channel, use :q. For mining, use :d."
icon_state = "cargo_headset"
item_state = "headset"
keyslot2 = new /obj/item/device/encryptionkey/heads/qm
/obj/item/device/radio/headset/headset_cargo
name = "cargo radio headset"
desc = "Headset used by the QM's slaves. To access the cargo channel, use :q."
icon_state = "cargo_headset"
item_state = "headset"
keyslot2 = new /obj/item/device/encryptionkey/headset_cargo
/obj/item/device/radio/headset/ert
name = "CentCom Response Team headset"
desc = "The headset of the boss's boss. Channels are as follows: :h - Response Team :c - command, :s - security, :e - engineering, :d - mining, :q - cargo, :m - medical, :n - science."
icon_state = "com_headset"
item_state = "headset"
freerange = 1
keyslot2 = new /obj/item/device/encryptionkey/ert
/obj/item/device/radio/headset/attackby(obj/item/weapon/W as obj, mob/user as mob)
// ..()
user.machine = src
if (!( istype(W, /obj/item/weapon/screwdriver) || (istype(W, /obj/item/device/encryptionkey/ ))))
return
if(istype(W, /obj/item/weapon/screwdriver))
if(keyslot1 || keyslot2)
for(var/ch_name in channels)
radio_controller.remove_object(src, radiochannels[ch_name])
secure_radio_connections[ch_name] = null
if(keyslot1)
var/turf/T = get_turf(user)
if(T)
keyslot1.loc = T
keyslot1 = null
if(keyslot2)
var/turf/T = get_turf(user)
if(T)
keyslot2.loc = T
keyslot2 = null
recalculateChannels()
user << "You pop out the encryption keys in the headset!"
else
user << "This headset doesn't have any encryption keys! How useless..."
if(istype(W, /obj/item/device/encryptionkey/))
if(keyslot1 && keyslot2)
user << "The headset can't hold another key!"
return
if(!keyslot1)
user.drop_item()
W.loc = src
keyslot1 = W
else
user.drop_item()
W.loc = src
keyslot2 = W
recalculateChannels()
return
/obj/item/device/radio/headset/proc/recalculateChannels()
src.channels = list()
src.translate_binary = 0
src.translate_hive = 0
src.syndie = 0
if(keyslot1)
for(var/ch_name in keyslot1.channels)
if(ch_name in src.channels)
continue
src.channels += ch_name
src.channels[ch_name] = keyslot1.channels[ch_name]
if(keyslot1.translate_binary)
src.translate_binary = 1
if(keyslot1.translate_hive)
src.translate_hive = 1
if(keyslot1.syndie)
src.syndie = 1
if(keyslot2)
for(var/ch_name in keyslot2.channels)
if(ch_name in src.channels)
continue
src.channels += ch_name
src.channels[ch_name] = keyslot2.channels[ch_name]
if(keyslot2.translate_binary)
src.translate_binary = 1
if(keyslot2.translate_hive)
src.translate_hive = 1
if(keyslot2.syndie)
src.syndie = 1
for (var/ch_name in channels)
if(!radio_controller)
sleep(30) // Waiting for the radio_controller to be created.
if(!radio_controller)
src.name = "broken radio headset"
return
secure_radio_connections[ch_name] = radio_controller.add_object(src, radiochannels[ch_name], RADIO_CHAT)
return
@@ -0,0 +1,73 @@
/obj/item/device/radio/intercom
name = "station intercom"
desc = "Talk through this."
icon_state = "intercom"
anchored = 1
w_class = 4.0
canhear_range = 4
var/number = 0
var/anyai = 1
var/mob/living/silicon/ai/ai = list()
/obj/item/device/radio/intercom/New()
spawn(5)
checkpower()
..()
/obj/item/device/radio/intercom/attack_ai(mob/user as mob)
src.add_fingerprint(user)
spawn (0)
attack_self(user)
/obj/item/device/radio/intercom/attack_paw(mob/user as mob)
return src.attack_hand(user)
/obj/item/device/radio/intercom/attack_hand(mob/user as mob)
src.add_fingerprint(user)
spawn (0)
attack_self(user)
/obj/item/device/radio/intercom/receive_range(freq, level)
if (!on)
return 0
if (!(src.wires & WIRE_RECEIVE))
return 0
if(level != 0)
var/turf/position = get_turf(src)
if(isnull(position) || position.z != level)
return 0
if (!src.listening)
return 0
if(freq == SYND_FREQ)
if(!(src.syndie))
return 0//Prevents broadcast of messages over devices lacking the encryption
return canhear_range
/obj/item/device/radio/intercom/hear_talk(mob/M as mob, msg)
if(!src.anyai && !(M in src.ai))
return
..()
/obj/item/device/radio/intercom/proc/checkpower()
// Simple loop, checks for power. Strictly for intercoms
while(src)
if(!src.loc)
on = 0
else
var/area/A = src.loc.loc
if(!A || !isarea(A) || !A.master)
on = 0
else
on = A.master.powered(EQUIP) // set "on" to the power status
if(!on)
icon_state = "intercom-p"
else
icon_state = "intercom"
sleep(30)
@@ -0,0 +1,779 @@
var/GLOBAL_RADIO_TYPE = 1 // radio type to use
// 0 = old radios
// 1 = new radios (subspace technology)
/obj/item/device/radio
icon = 'icons/obj/radio.dmi'
name = "station bounced radio"
suffix = "\[3\]"
icon_state = "walkietalkie"
item_state = "walkietalkie"
var/on = 1 // 0 for off
var/last_transmission
var/frequency = 1459 //common chat
var/traitor_frequency = 0 //tune to frequency to unlock traitor supplies
var/canhear_range = 3 // the range which mobs can hear this radio from
var/obj/item/device/radio/patch_link = null
var/wires = WIRE_SIGNAL | WIRE_RECEIVE | WIRE_TRANSMIT
var/b_stat = 0
var/broadcasting = 0
var/listening = 1
var/freerange = 0 // 0 - Sanitize frequencies, 1 - Full range
var/list/channels = list() //see communications.dm for full list. First channes is a "default" for :h
var/subspace_transmission = 0
var/syndie = 0//Holder to see if it's a syndicate encrpyed radio
var/maxf = 1499
// "Example" = FREQ_LISTENING|FREQ_BROADCASTING
flags = FPRINT | CONDUCT | TABLEPASS
slot_flags = SLOT_BELT
throw_speed = 2
throw_range = 9
w_class = 2
g_amt = 25
m_amt = 75
var/const/WIRE_SIGNAL = 1 //sends a signal, like to set off a bomb or electrocute someone
var/const/WIRE_RECEIVE = 2
var/const/WIRE_TRANSMIT = 4
var/const/TRANSMISSION_DELAY = 5 // only 2/second/radio
var/const/FREQ_LISTENING = 1
//FREQ_BROADCASTING = 2
/obj/item/device/radio
var/datum/radio_frequency/radio_connection
var/list/datum/radio_frequency/secure_radio_connections = new
proc/set_frequency(new_frequency)
radio_controller.remove_object(src, frequency)
frequency = new_frequency
radio_connection = radio_controller.add_object(src, frequency, RADIO_CHAT)
/obj/item/device/radio/New()
..()
if(radio_controller)
initialize()
/obj/item/device/radio/initialize()
if(freerange)
if(frequency < 1200 || frequency > 1600)
frequency = sanitize_frequency(frequency, maxf)
// The max freq is higher than a regular headset to decrease the chance of people listening in, if you use the higher channels.
else if (frequency < 1441 || frequency > maxf)
//world.log << "[src] ([type]) has a frequency of [frequency], sanitizing."
frequency = sanitize_frequency(frequency, maxf)
set_frequency(frequency)
for (var/ch_name in channels)
secure_radio_connections[ch_name] = radio_controller.add_object(src, radiochannels[ch_name], RADIO_CHAT)
/obj/item/device/radio/attack_self(mob/user as mob)
user.machine = src
interact(user)
/obj/item/device/radio/proc/interact(mob/user as mob)
if(!on)
return
if(active_uplink_check(user))
return
var/dat = "<html><head><title>[src]</title></head><body><TT>"
if(!istype(src, /obj/item/device/radio/headset)) //Headsets dont get a mic button
dat += "Microphone: [broadcasting ? "<A href='byond://?src=\ref[src];talk=0'>Engaged</A>" : "<A href='byond://?src=\ref[src];talk=1'>Disengaged</A>"]<BR>"
dat += {"
Speaker: [listening ? "<A href='byond://?src=\ref[src];listen=0'>Engaged</A>" : "<A href='byond://?src=\ref[src];listen=1'>Disengaged</A>"]<BR>
Frequency:
<A href='byond://?src=\ref[src];freq=-10'>-</A>
<A href='byond://?src=\ref[src];freq=-2'>-</A>
[format_frequency(frequency)]
<A href='byond://?src=\ref[src];freq=2'>+</A>
<A href='byond://?src=\ref[src];freq=10'>+</A><BR>
"}
for (var/ch_name in channels)
dat+=text_sec_channel(ch_name, channels[ch_name])
dat+={"[text_wires()]</TT></body></html>"}
user << browse(dat, "window=radio")
onclose(user, "radio")
return
/obj/item/device/radio/proc/text_wires()
if (!b_stat)
return ""
return {"
<hr>
Green Wire: <A href='byond://?src=\ref[src];wires=4'>[(wires & 4) ? "Cut" : "Mend"] Wire</A><BR>
Red Wire: <A href='byond://?src=\ref[src];wires=2'>[(wires & 2) ? "Cut" : "Mend"] Wire</A><BR>
Blue Wire: <A href='byond://?src=\ref[src];wires=1'>[(wires & 1) ? "Cut" : "Mend"] Wire</A><BR>
"}
/obj/item/device/radio/proc/text_sec_channel(var/chan_name, var/chan_stat)
var/list = !!(chan_stat&FREQ_LISTENING)!=0
return {"
<B>[chan_name]</B><br>
Speaker: <A href='byond://?src=\ref[src];ch_name=[chan_name];listen=[!list]'>[list ? "Engaged" : "Disengaged"]</A><BR>
"}
/obj/item/device/radio/Topic(href, href_list)
//..()
if (usr.stat || !on)
return
if (!(issilicon(usr) || (usr.contents.Find(src) || ( in_range(src, usr) && istype(loc, /turf) ))))
usr << browse(null, "window=radio")
return
usr.machine = src
if (href_list["track"])
var/mob/target = locate(href_list["track"])
var/mob/living/silicon/ai/A = locate(href_list["track2"])
if(A && target)
A.ai_actual_track(target)
return
else if (href_list["faketrack"])
var/mob/target = locate(href_list["track"])
var/mob/living/silicon/ai/A = locate(href_list["track2"])
if(A && target)
A:cameraFollow = target
A << text("Now tracking [] on camera.", target.name)
if (usr.machine == null)
usr.machine = usr
while (usr:cameraFollow == target)
usr << "Target is not on or near any active cameras on the station. We'll check again in 5 seconds (unless you use the cancel-camera verb)."
sleep(40)
continue
return
else if (href_list["freq"])
var/new_frequency = (frequency + text2num(href_list["freq"]))
if (!freerange || (frequency < 1200 || frequency > 1600))
new_frequency = sanitize_frequency(new_frequency, maxf)
set_frequency(new_frequency)
if(hidden_uplink)
if(hidden_uplink.check_trigger(usr, frequency, traitor_frequency))
usr << browse(null, "window=radio")
return
else if (href_list["talk"])
broadcasting = text2num(href_list["talk"])
else if (href_list["listen"])
var/chan_name = href_list["ch_name"]
if (!chan_name)
listening = text2num(href_list["listen"])
else
if (channels[chan_name] & FREQ_LISTENING)
channels[chan_name] &= ~FREQ_LISTENING
else
channels[chan_name] |= FREQ_LISTENING
else if (href_list["wires"])
var/t1 = text2num(href_list["wires"])
if (!( istype(usr.get_active_hand(), /obj/item/weapon/wirecutters) ))
return
if (wires & t1)
wires &= ~t1
else
wires |= t1
if (!( master ))
if (istype(loc, /mob))
interact(loc)
else
updateDialog()
else
if (istype(master.loc, /mob))
interact(master.loc)
else
updateDialog()
add_fingerprint(usr)
/obj/item/device/radio/talk_into(mob/M as mob, message, channel)
if(!on) return // the device has to be on
// Fix for permacell radios, but kinda eh about actually fixing them.
// Uncommenting this. To the above comment:
// The permacell radios aren't suppose to be able to transmit, this isn't a bug and this "fix" is just making radio wires useless. -Giacom
if(!(src.wires & WIRE_TRANSMIT)) // The device has to have all its wires and shit intact
return
if(GLOBAL_RADIO_TYPE == 1) // NEW RADIO SYSTEMS: By Doohl
/* Quick introduction:
This new radio system uses a very robust FTL signaling technology unoriginally
dubbed "subspace" which is somewhat similar to 'blue-space' but can't
actually transmit large mass. Headsets are the only radio devices capable
of sending subspace transmissions to the Communications Satellite.
A headset sends a signal to a subspace listener/reciever elsewhere in space,
the signal gets processed and logged, and an audible transmission gets sent
to each individual headset.
*/
//#### Grab the connection datum ####//
var/datum/radio_frequency/connection = null
if(channel && channels && channels.len > 0)
if (channel == "department")
//world << "DEBUG: channel=\"[channel]\" switching to \"[channels[1]]\""
channel = channels[1]
connection = secure_radio_connections[channel]
else
connection = radio_connection
channel = null
if (!istype(connection))
return
if (!connection)
return
var/turf/position = get_turf(src)
//#### Tagging the signal with all appropriate identity values ####//
// ||-- The mob's name identity --||
var/displayname = M.name // grab the display name (name you get when you hover over someone's icon)
var/real_name = M.real_name // mob's real name
var/mobkey = "none" // player key associated with mob
var/voicemask = 0 // the speaker is wearing a voice mask
if(M.client)
mobkey = M.key // assign the mob's key
var/jobname // the mob's "job"
// --- Human: use their actual job ---
if (ishuman(M))
jobname = M:get_assignment()
// --- Carbon Nonhuman ---
else if (iscarbon(M)) // Nonhuman carbon mob
jobname = "No id"
// --- AI ---
else if (isAI(M))
jobname = "AI"
// --- Cyborg ---
else if (isrobot(M))
jobname = "Cyborg"
// --- Personal AI (pAI) ---
else if (istype(M, /mob/living/silicon/pai))
jobname = "Personal AI"
// --- Unidentifiable mob ---
else
jobname = "Unknown"
// --- Modifications to the mob's identity ---
// The mob is disguising their identity:
if (istype(M.wear_mask, /obj/item/clothing/mask/gas/voice))
if(M.wear_mask:vchange)
displayname = M.wear_mask:voice
jobname = "Unknown"
voicemask = 1
/* ###### Radio headsets can only broadcast through subspace ###### */
if(subspace_transmission)
// First, we want to generate a new radio signal
var/datum/signal/signal = new
signal.transmission_method = 2 // 2 would be a subspace transmission.
// transmission_method could probably be enumerated through #define. Would be neater.
// --- Finally, tag the actual signal with the appropriate values ---
signal.data = list(
// Identity-associated tags:
"mob" = M, // store a reference to the mob
"mobtype" = M.type, // the mob's type
"realname" = real_name, // the mob's real name
"name" = displayname, // the mob's display name
"job" = jobname, // the mob's job
"key" = mobkey, // the mob's key
"vmessage" = M.voice_message, // the message to display if the voice wasn't understood
"vname" = M.voice_name, // the name to display if the voice wasn't understood
"vmask" = voicemask, // 1 if the mob is using a voice gas mask
// We store things that would otherwise be kept in the actual mob
// so that they can be logged even AFTER the mob is deleted or something
// Other tags:
"compression" = rand(45,50), // compressed radio signal
"message" = message, // the actual sent message
"connection" = connection, // the radio connection to use
"radio" = src, // stores the radio used for transmission
"slow" = 0, // how much to sleep() before broadcasting - simulates net lag
"traffic" = 0, // dictates the total traffic sum that the signal went through
"type" = 0, // determines what type of radio input it is: normal broadcast
"server" = null, // the last server to log this signal
"reject" = 0, // if nonzero, the signal will not be accepted by any broadcasting machinery
"level" = position.z // The source's z level
)
signal.frequency = connection.frequency // Quick frequency set
//#### Sending the signal to all subspace receivers ####//
for(var/obj/machinery/telecomms/receiver/R in telecomms_list)
R.receive_signal(signal)
// Allinone can act as receivers.
for(var/obj/machinery/telecomms/allinone/R in telecomms_list)
R.receive_signal(signal)
// Receiving code can be located in Telecommunications.dm
return
/* ###### Intercoms and station-bounced radios ###### */
var/filter_type = 2
/* --- Intercoms can only broadcast to other intercoms, but bounced radios can broadcast to bounced radios and intercoms --- */
if(istype(src, /obj/item/device/radio/intercom))
filter_type = 1
var/datum/signal/signal = new
signal.transmission_method = 2
/* --- Try to send a normal subspace broadcast first */
signal.data = list(
"mob" = M, // store a reference to the mob
"mobtype" = M.type, // the mob's type
"realname" = real_name, // the mob's real name
"name" = displayname, // the mob's display name
"job" = jobname, // the mob's job
"key" = mobkey, // the mob's key
"vmessage" = M.voice_message, // the message to display if the voice wasn't understood
"vname" = M.voice_name, // the name to display if the voice wasn't understood
"vmask" = voicemask, // 1 if the mob is using a voice gas mas
"compression" = 0, // uncompressed radio signal
"message" = message, // the actual sent message
"connection" = connection, // the radio connection to use
"radio" = src, // stores the radio used for transmission
"slow" = 0,
"traffic" = 0,
"type" = 0,
"server" = null,
"reject" = 0,
"level" = position.z
)
signal.frequency = connection.frequency // Quick frequency set
for(var/obj/machinery/telecomms/receiver/R in telecomms_list)
R.receive_signal(signal)
sleep(rand(10,25)) // wait a little...
if(signal.data["done"])
// we're done here.
return
// Oh my god; the comms are down or something because the signal hasn't been broadcasted yet.
// Send a mundane broadcast with limited targets:
//THIS IS TEMPORARY.
if(!connection) return //~Carn
Broadcast_Message(connection, M, voicemask, M.voice_message,
src, message, displayname, jobname, real_name, M.voice_name,
filter_type, signal.data["compression"], position.z)
else // OLD RADIO SYSTEMS: By Goons?
var/datum/radio_frequency/connection = null
if(channel && channels && channels.len > 0)
if (channel == "department")
//world << "DEBUG: channel=\"[channel]\" switching to \"[channels[1]]\""
channel = channels[1]
connection = secure_radio_connections[channel]
else
connection = radio_connection
channel = null
if (!istype(connection))
return
var/display_freq = connection.frequency
//world << "DEBUG: used channel=\"[channel]\" frequency= \"[display_freq]\" connection.devices.len = [connection.devices.len]"
var/eqjobname
if (ishuman(M))
eqjobname = M:get_assignment()
else if (iscarbon(M))
eqjobname = "No id" //only humans can wear ID
else if (isAI(M))
eqjobname = "AI"
else if (isrobot(M))
eqjobname = "Cyborg"//Androids don't really describe these too well, in my opinion.
else if (istype(M, /mob/living/silicon/pai))
eqjobname = "Personal AI"
else
eqjobname = "Unknown"
if (!(wires & WIRE_TRANSMIT))
return
var/list/receive = list()
//for (var/obj/item/device/radio/R in radio_connection.devices)
for (var/obj/item/device/radio/R in connection.devices["[RADIO_CHAT]"]) // Modified for security headset code -- TLE
//if(R.accept_rad(src, message))
receive |= R.send_hear(display_freq, 0)
//world << "DEBUG: receive.len=[receive.len]"
var/list/heard_masked = list() // masked name or no real name
var/list/heard_normal = list() // normal message
var/list/heard_voice = list() // voice message
var/list/heard_garbled = list() // garbled message
for (var/mob/R in receive)
if (R.client && R.client.STFU_radio) //Adminning with 80 people on can be fun when you're trying to talk and all you can hear is radios.
continue
if (R.say_understands(M))
if (!ishuman(M) || istype(M.wear_mask, /obj/item/clothing/mask/gas/voice))
heard_masked += R
else
heard_normal += R
else
if (M.voice_message)
heard_voice += R
else
heard_garbled += R
if (length(heard_masked) || length(heard_normal) || length(heard_voice) || length(heard_garbled))
var/part_a = "<span class='radio'><span class='name'>"
//var/part_b = "</span><b> \icon[src]\[[format_frequency(frequency)]\]</b> <span class='message'>"
var/freq_text
switch(display_freq)
if(SYND_FREQ)
freq_text = "#unkn"
if(COMM_FREQ)
freq_text = "Command"
if(1351)
freq_text = "Science"
if(1355)
freq_text = "Medical"
if(1357)
freq_text = "Engineering"
if(1359)
freq_text = "Security"
if(1349)
freq_text = "Mining"
if(1347)
freq_text = "Cargo"
//There's probably a way to use the list var of channels in code\game\communications.dm to make the dept channels non-hardcoded, but I wasn't in an experimentive mood. --NEO
if(!freq_text)
freq_text = format_frequency(display_freq)
var/part_b = "</span><b> \icon[src]\[[freq_text]\]</b> <span class='message'>" // Tweaked for security headsets -- TLE
var/part_c = "</span></span>"
if (display_freq==SYND_FREQ)
part_a = "<span class='syndradio'><span class='name'>"
else if (display_freq==COMM_FREQ)
part_a = "<span class='comradio'><span class='name'>"
else if (display_freq in DEPT_FREQS)
part_a = "<span class='deptradio'><span class='name'>"
var/quotedmsg = M.say_quote(message)
//This following recording is intended for research and feedback in the use of department radio channels.
var/part_blackbox_b = "</span><b> \[[freq_text]\]</b> <span class='message'>" // Tweaked for security headsets -- TLE
var/blackbox_msg = "[part_a][M.name][part_blackbox_b][quotedmsg][part_c]"
//var/blackbox_admin_msg = "[part_a][M.name] (Real name: [M.real_name])[part_blackbox_b][quotedmsg][part_c]"
if(istype(blackbox))
//BR.messages_admin += blackbox_admin_msg
switch(display_freq)
if(1459)
blackbox.msg_common += blackbox_msg
if(1351)
blackbox.msg_science += blackbox_msg
if(1353)
blackbox.msg_command += blackbox_msg
if(1355)
blackbox.msg_medical += blackbox_msg
if(1357)
blackbox.msg_engineering += blackbox_msg
if(1359)
blackbox.msg_security += blackbox_msg
if(1441)
blackbox.msg_deathsquad += blackbox_msg
if(1213)
blackbox.msg_syndicate += blackbox_msg
if(1349)
blackbox.msg_mining += blackbox_msg
if(1347)
blackbox.msg_cargo += blackbox_msg
else
blackbox.messages += blackbox_msg
//End of research and feedback code.
if (length(heard_masked))
var/N = M.name
var/J = eqjobname
if (istype(M.wear_mask, /obj/item/clothing/mask/gas/voice)&&M.wear_mask:vchange)
//To properly have the ninja show up on radio. Could also be useful for similar items.
//Would not be necessary but the mob could be wearing a mask that is not a voice changer.
N = M.wear_mask:voice
J = "Unknown"
var/rendered = "[part_a][N][part_b][quotedmsg][part_c]"
for (var/mob/R in heard_masked)
if(istype(R, /mob/living/silicon/ai))
R.show_message("[part_a]<a href='byond://?src=\ref[src];track2=\ref[R];track=\ref[M]'>[N] ([J]) </a>[part_b][quotedmsg][part_c]", 2)
else
R.show_message(rendered, 2)
if (length(heard_normal))
var/rendered = "[part_a][M.real_name][part_b][quotedmsg][part_c]"
for (var/mob/R in heard_normal)
if(istype(R, /mob/living/silicon/ai))
R.show_message("[part_a]<a href='byond://?src=\ref[src];track2=\ref[R];track=\ref[M]'>[M.real_name] ([eqjobname]) </a>[part_b][quotedmsg][part_c]", 2)
else
R.show_message(rendered, 2)
if (length(heard_voice))
var/rendered = "[part_a][M.voice_name][part_b][M.voice_message][part_c]"
for (var/mob/R in heard_voice)
if(istype(R, /mob/living/silicon/ai))
R.show_message("[part_a]<a href='byond://?src=\ref[src];track2=\ref[R];track=\ref[M]'>[M.voice_name] ([eqjobname]) </a>[part_b][M.voice_message][part_c]", 2)
else
R.show_message(rendered, 2)
if (length(heard_garbled))
quotedmsg = M.say_quote(stars(message))
var/rendered = "[part_a][M.voice_name][part_b][quotedmsg][part_c]"
for (var/mob/R in heard_voice)
if(istype(R, /mob/living/silicon/ai))
R.show_message("[part_a]<a href='byond://?src=\ref[src];track2=\ref[R];track=\ref[M]'>[M.voice_name]</a>[part_b][quotedmsg][part_c]", 2)
else
R.show_message(rendered, 2)
/obj/item/device/radio/hear_talk(mob/M as mob, msg)
if (broadcasting)
talk_into(M, msg)
/*
/obj/item/device/radio/proc/accept_rad(obj/item/device/radio/R as obj, message)
if ((R.frequency == frequency && message))
return 1
else if
else
return null
return
*/
/obj/item/device/radio/proc/receive_range(freq, level)
// check if this radio can receive on the given frequency, and if so,
// what the range is in which mobs will hear the radio
// returns: 0 if can't receive, range otherwise
if (!(wires & WIRE_RECEIVE))
return 0
if(!listening)
return 0
if(level != 0)
var/turf/position = get_turf(src)
if(isnull(position) || position.z != level)
return 0
if(freq == SYND_FREQ)
if(!(src.syndie))//Checks to see if it's allowed on that frequency, based on the encryption keys
return 0
if (!on)
return 0
if (!freq) //recieved on main frequency
if (!listening)
return 0
else
var/accept = (freq==frequency && listening)
if (!accept)
for (var/ch_name in channels)
var/datum/radio_frequency/RF = secure_radio_connections[ch_name]
if (RF.frequency==freq && (channels[ch_name]&FREQ_LISTENING))
accept = 1
break
if (!accept)
return 0
return canhear_range
/obj/item/device/radio/proc/send_hear(freq, level)
var/range = receive_range(freq, level)
if(range > 0)
return get_mobs_in_view(canhear_range, src)
/obj/item/device/radio/examine()
set src in view()
..()
if ((in_range(src, usr) || loc == usr))
if (b_stat)
usr.show_message("\blue \the [src] can be attached and modified!")
else
usr.show_message("\blue \the [src] can not be modified or attached!")
return
/obj/item/device/radio/attackby(obj/item/weapon/W as obj, mob/user as mob)
..()
user.machine = src
if (!( istype(W, /obj/item/weapon/screwdriver) ))
return
b_stat = !( b_stat )
if(!istype(src, /obj/item/device/radio/beacon))
if (b_stat)
user.show_message("\blue The radio can now be attached and modified!")
else
user.show_message("\blue The radio can no longer be modified or attached!")
updateDialog()
//Foreach goto(83)
add_fingerprint(user)
return
else return
/obj/item/device/radio/emp_act(severity)
broadcasting = 0
listening = 0
for (var/ch_name in channels)
channels[ch_name] = 0
..()
///////////////////////////////
//////////Borg Radios//////////
///////////////////////////////
//Giving borgs their own radio to have some more room to work with -Sieve
/obj/item/device/radio/borg
var/obj/item/device/encryptionkey/keyslot = null//Borg radios can handle a single encryption key
/obj/item/device/radio/borg/attackby(obj/item/weapon/W as obj, mob/user as mob)
// ..()
user.machine = src
if (!( istype(W, /obj/item/weapon/screwdriver) || (istype(W, /obj/item/device/encryptionkey/ ))))
return
if(istype(W, /obj/item/weapon/screwdriver))
if(keyslot)
for(var/ch_name in channels)
radio_controller.remove_object(src, radiochannels[ch_name])
secure_radio_connections[ch_name] = null
if(keyslot)
var/turf/T = get_turf(user)
if(T)
keyslot.loc = T
keyslot = null
recalculateChannels()
user << "You pop out the encryption key in the radio!"
else
user << "This radio doesn't have any encryption keys!"
if(istype(W, /obj/item/device/encryptionkey/))
if(keyslot)
user << "The radio can't hold another key!"
return
if(!keyslot)
user.drop_item()
W.loc = src
keyslot = W
recalculateChannels()
return
/obj/item/device/radio/borg/proc/recalculateChannels()
src.channels = list()
src.syndie = 0
if(keyslot)
for(var/ch_name in keyslot.channels)
if(ch_name in src.channels)
continue
src.channels += ch_name
src.channels[ch_name] = keyslot.channels[ch_name]
if(keyslot.syndie)
src.syndie = 1
for (var/ch_name in channels)
if(!radio_controller)
sleep(30) // Waiting for the radio_controller to be created.
if(!radio_controller)
src.name = "broken radio"
return
secure_radio_connections[ch_name] = radio_controller.add_object(src, radiochannels[ch_name], RADIO_CHAT)
return
/obj/item/device/radio/borg/Topic(href, href_list)
if(usr.stat || !on)
return
if (href_list["mode"])
subspace_transmission = !subspace_transmission
if(!subspace_transmission)//Simple as fuck, clears the channel list to prevent talking/listening over them if subspace transmission is disabled
channels = list()
else
recalculateChannels()
usr << "Subspace Transmission is [(subspace_transmission) ? "enabled" : "disabled"]"
..()
/obj/item/device/radio/borg/interact(mob/user as mob)
if(!on)
return
var/dat = "<html><head><title>[src]</title></head><body><TT>"
dat += {"
Speaker: [listening ? "<A href='byond://?src=\ref[src];listen=0'>Engaged</A>" : "<A href='byond://?src=\ref[src];listen=1'>Disengaged</A>"]<BR>
Frequency:
<A href='byond://?src=\ref[src];freq=-10'>-</A>
<A href='byond://?src=\ref[src];freq=-2'>-</A>
[format_frequency(frequency)]
<A href='byond://?src=\ref[src];freq=2'>+</A>
<A href='byond://?src=\ref[src];freq=10'>+</A><BR>
<A href='byond://?src=\ref[src];mode=1'>Toggle Broadcast Mode</A><BR>
"}
if(subspace_transmission)//Don't even bother if subspace isn't turned on
for (var/ch_name in channels)
dat+=text_sec_channel(ch_name, channels[ch_name])
dat+={"[text_wires()]</TT></body></html>"}
user << browse(dat, "window=radio")
onclose(user, "radio")
return
+267
View File
@@ -0,0 +1,267 @@
/*
CONTAINS:
T-RAY
DETECTIVE SCANNER
HEALTH ANALYZER
GAS ANALYZER
PLANT ANALYZER
MASS SPECTROMETER
*/
/obj/item/device/t_scanner
name = "T-ray scanner"
desc = "A terahertz-ray emitter and scanner used to detect underfloor objects such as cables and pipes."
icon_state = "t-ray0"
var/on = 0
flags = FPRINT | TABLEPASS
slot_flags = SLOT_BELT
w_class = 2
item_state = "electronic"
m_amt = 150
origin_tech = "magnets=1;engineering=1"
/obj/item/device/t_scanner/attack_self(mob/user)
on = !on
icon_state = "t-ray[on]"
if(on)
processing_objects.Add(src)
/obj/item/device/t_scanner/process()
if(!on)
processing_objects.Remove(src)
return null
for(var/turf/T in range(1, src.loc) )
if(!T.intact)
continue
for(var/obj/O in T.contents)
if(O.level != 1)
continue
if(O.invisibility == 101)
O.invisibility = 0
spawn(10)
if(O)
var/turf/U = O.loc
if(U.intact)
O.invisibility = 101
var/mob/living/M = locate() in T
if(M && M.invisibility == 2)
M.invisibility = 0
spawn(2)
if(M)
M.invisibility = INVISIBILITY_LEVEL_TWO
/obj/item/device/healthanalyzer
name = "Health Analyzer"
icon_state = "health"
item_state = "analyzer"
desc = "A hand-held body scanner able to distinguish vital signs of the subject."
flags = FPRINT | TABLEPASS | CONDUCT
slot_flags = SLOT_BELT
throwforce = 3
w_class = 1.0
throw_speed = 5
throw_range = 10
m_amt = 200
origin_tech = "magnets=1;biotech=1"
var/mode = 1;
/obj/item/device/healthanalyzer/attack(mob/living/M as mob, mob/living/user as mob)
if (( (CLUMSY in user.mutations) || user.getBrainLoss() >= 60) && prob(50))
user << text("\red You try to analyze the floor's vitals!")
for(var/mob/O in viewers(M, null))
O.show_message(text("\red [user] has analyzed the floor's vitals!"), 1)
user.show_message(text("\blue Analyzing Results for The floor:\n\t Overall Status: Healthy"), 1)
user.show_message(text("\blue \t Damage Specifics: [0]-[0]-[0]-[0]"), 1)
user.show_message("\blue Key: Suffocation/Toxin/Burns/Brute", 1)
user.show_message("\blue Body Temperature: ???", 1)
return
if (!(istype(usr, /mob/living/carbon/human) || ticker) && ticker.mode.name != "monkey")
usr << "\red You don't have the dexterity to do this!"
return
for(var/mob/O in viewers(M, null))
O.show_message(text("\red [] has analyzed []'s vitals!", user, M), 1)
//Foreach goto(67)
var/fake_oxy = max(rand(1,40), M.getOxyLoss(), (300 - (M.getToxLoss() + M.getFireLoss() + M.getBruteLoss())))
if(M.status_flags & FAKEDEATH)
user.show_message(text("\blue Analyzing Results for []:\n\t Overall Status: []", M, "dead"), 1)
user.show_message(text("\blue \t Damage Specifics: []-[]-[]-[]", fake_oxy < 50 ? "\red [fake_oxy]" : fake_oxy , M.getToxLoss() > 50 ? "\red [M.getToxLoss()]" : M.getToxLoss(), M.getFireLoss() > 50 ? "\red[M.getFireLoss()]" : M.getFireLoss(), M.getBruteLoss() > 50 ? "\red[M.getBruteLoss()]" : M.getBruteLoss()), 1)
else
user.show_message(text("\blue Analyzing Results for []:\n\t Overall Status: []", M, (M.stat > 1 ? "dead" : text("[]% healthy", M.health - M.halloss))), 1)
user.show_message(text("\blue \t Damage Specifics: []-[]-[]-[]", M.getOxyLoss() > 50 ? "\red [M.getOxyLoss()]" : M.getOxyLoss(), M.getToxLoss() > 50 ? "\red [M.getToxLoss()]" : M.getToxLoss(), M.getFireLoss() > 50 ? "\red[M.getFireLoss()]" : M.getFireLoss(), M.getBruteLoss() > 50 ? "\red[M.getBruteLoss()]" : M.getBruteLoss()), 1)
user.show_message("\blue Key: Suffocation/Toxin/Burns/Brute", 1)
user.show_message("\blue Body Temperature: [M.bodytemperature-T0C]&deg;C ([M.bodytemperature*1.8-459.67]&deg;F)", 1)
if(M.tod && (M.stat == DEAD || (M.status_flags & FAKEDEATH)))
user.show_message("\blue Time of Death: [M.tod]")
if(istype(M, /mob/living/carbon/human) && mode == 1)
var/mob/living/carbon/human/H = M
var/list/damaged = H.get_damaged_organs(1,1)
user.show_message("\blue Localized Damage, Brute/Burn:",1)
if(length(damaged)>0)
for(var/datum/organ/external/org in damaged)
user.show_message(text("\blue \t []: []\blue-[]",capitalize(org.getDisplayName()),(org.brute_dam > 0)?"\red [org.brute_dam]":0,(org.burn_dam > 0)?"\red [org.burn_dam]":0),1)
else
user.show_message("\blue \t Limbs are OK.",1)
if(M.status_flags & FAKEDEATH)
user.show_message(text("\blue [] | [] | [] | []", fake_oxy > 50 ? "\red Severe oxygen deprivation detected\blue" : "Subject bloodstream oxygen level normal", M.getToxLoss() > 50 ? "\red Dangerous amount of toxins detected\blue" : "Subject bloodstream toxin level minimal", M.getFireLoss() > 50 ? "\red Severe burn damage detected\blue" : "Subject burn injury status O.K", M.getBruteLoss() > 50 ? "\red Severe anatomical damage detected\blue" : "Subject brute-force injury status O.K"), 1)
else
user.show_message(text("\blue [] | [] | [] | []", M.getOxyLoss() > 50 ? "\red Severe oxygen deprivation detected\blue" : "Subject bloodstream oxygen level normal", M.getToxLoss() > 50 ? "\red Dangerous amount of toxins detected\blue" : "Subject bloodstream toxin level minimal", M.getFireLoss() > 50 ? "\red Severe burn damage detected\blue" : "Subject burn injury status O.K", M.getBruteLoss() > 50 ? "\red Severe anatomical damage detected\blue" : "Subject brute-force injury status O.K"), 1)
if (M.getCloneLoss())
user.show_message(text("\red Subject appears to have been imperfectly cloned."), 1)
for(var/datum/disease/D in M.viruses)
if(!D.hidden[SCANNER])
user.show_message(text("\red <b>Warning: [D.form] Detected</b>\nName: [D.name].\nType: [D.spread].\nStage: [D.stage]/[D.max_stages].\nPossible Cure: [D.cure]"))
if (M.reagents && M.reagents.get_reagent_amount("inaprovaline"))
user.show_message(text("\blue Bloodstream Analysis located [M.reagents:get_reagent_amount("inaprovaline")] units of rejuvenation chemicals."), 1)
if (M.getBrainLoss() >= 100 || istype(M, /mob/living/carbon/human) && M:brain_op_stage == 4.0)
user.show_message(text("\red Subject is brain dead."), 1)
else if (M.getBrainLoss() >= 60)
user.show_message(text("\red Severe brain damage detected. Subject likely to have mental retardation."), 1)
else if (M.getBrainLoss() >= 10)
user.show_message(text("\red Significant brain damage detected. Subject may have had a concussion."), 1)
src.add_fingerprint(user)
return
/obj/item/device/healthanalyzer/verb/toggle_mode()
set name = "Switch Verbosity"
set category = "Object"
mode = !mode
switch (mode)
if(1)
usr << "The scanner now shows specific limb damage."
if(0)
usr << "The scanner no longer shows limb damage."
/obj/item/device/analyzer
desc = "A hand-held environmental scanner which reports current gas levels."
name = "analyzer"
icon_state = "atmos"
item_state = "analyzer"
w_class = 2.0
flags = FPRINT | TABLEPASS| CONDUCT
slot_flags = SLOT_BELT
throwforce = 5
throw_speed = 4
throw_range = 20
m_amt = 30
g_amt = 20
origin_tech = "magnets=1;engineering=1"
/obj/item/device/analyzer/attack_self(mob/user as mob)
if (user.stat)
return
if (!(istype(usr, /mob/living/carbon/human) || ticker) && ticker.mode.name != "monkey")
usr << "\red You don't have the dexterity to do this!"
return
var/turf/location = user.loc
if (!( istype(location, /turf) ))
return
var/datum/gas_mixture/environment = location.return_air()
var/pressure = environment.return_pressure()
var/total_moles = environment.total_moles()
user.show_message("\blue <B>Results:</B>", 1)
if(abs(pressure - ONE_ATMOSPHERE) < 10)
user.show_message("\blue Pressure: [round(pressure,0.1)] kPa", 1)
else
user.show_message("\red Pressure: [round(pressure,0.1)] kPa", 1)
if(total_moles)
var/o2_concentration = environment.oxygen/total_moles
var/n2_concentration = environment.nitrogen/total_moles
var/co2_concentration = environment.carbon_dioxide/total_moles
var/plasma_concentration = environment.toxins/total_moles
var/unknown_concentration = 1-(o2_concentration+n2_concentration+co2_concentration+plasma_concentration)
if(abs(n2_concentration - N2STANDARD) < 20)
user.show_message("\blue Nitrogen: [round(n2_concentration*100)]%", 1)
else
user.show_message("\red Nitrogen: [round(n2_concentration*100)]%", 1)
if(abs(o2_concentration - O2STANDARD) < 2)
user.show_message("\blue Oxygen: [round(o2_concentration*100)]%", 1)
else
user.show_message("\red Oxygen: [round(o2_concentration*100)]%", 1)
if(co2_concentration > 0.01)
user.show_message("\red CO2: [round(co2_concentration*100)]%", 1)
else
user.show_message("\blue CO2: [round(co2_concentration*100)]%", 1)
if(plasma_concentration > 0.01)
user.show_message("\red Plasma: [round(plasma_concentration*100)]%", 1)
if(unknown_concentration > 0.01)
user.show_message("\red Unknown: [round(unknown_concentration*100)]%", 1)
user.show_message("\blue Temperature: [round(environment.temperature-T0C)]&deg;C", 1)
src.add_fingerprint(user)
return
/obj/item/device/mass_spectrometer/New()
..()
var/datum/reagents/R = new/datum/reagents(5)
reagents = R
R.my_atom = src
/obj/item/device/mass_spectrometer/on_reagent_change()
if(reagents.total_volume)
icon_state = initial(icon_state) + "_s"
else
icon_state = initial(icon_state)
/obj/item/device/mass_spectrometer/attack_self(mob/user as mob)
if (user.stat)
return
if (crit_fail)
user << "\red This device has critically failed and is no longer functional!"
return
if (!(istype(user, /mob/living/carbon/human) || ticker) && ticker.mode.name != "monkey")
user << "\red You don't have the dexterity to do this!"
return
if(reagents.total_volume)
var/list/blood_traces = list()
for(var/datum/reagent/R in reagents.reagent_list)
if(R.id != "blood")
reagents.clear_reagents()
user << "\red The sample was contaminated! Please insert another sample"
return
else
blood_traces = params2list(R.data["trace_chem"])
break
var/dat = "Trace Chemicals Found: "
for(var/R in blood_traces)
if(prob(reliability))
if(details)
dat += "[R] ([blood_traces[R]] units) "
else
dat += "[R] "
recent_fail = 0
else
if(recent_fail)
crit_fail = 1
reagents.clear_reagents()
return
else
recent_fail = 1
user << "[dat]"
reagents.clear_reagents()
return
@@ -0,0 +1,32 @@
/obj/item/weapon/cloaking_device
name = "cloaking device"
desc = "Use this to become invisible to the human eyesocket."
icon = 'icons/obj/device.dmi'
icon_state = "shield0"
var/active = 0.0
flags = FPRINT | TABLEPASS| CONDUCT
item_state = "electronic"
throwforce = 10.0
throw_speed = 2
throw_range = 10
w_class = 2.0
origin_tech = "magnets=3;syndicate=4"
/obj/item/weapon/cloaking_device/attack_self(mob/user as mob)
src.active = !( src.active )
if (src.active)
user << "\blue The cloaking device is now active."
src.icon_state = "shield1"
else
user << "\blue The cloaking device is now inactive."
src.icon_state = "shield0"
src.add_fingerprint(user)
return
/obj/item/weapon/cloaking_device/emp_act(severity)
active = 0
icon_state = "shield0"
if(ismob(loc))
loc:update_icons()
..()
@@ -0,0 +1,263 @@
/obj/item/device/taperecorder
desc = "A device that can record up to an hour of dialogue and play it back. It automatically translates the content in playback."
name = "universal recorder"
icon_state = "taperecorderidle"
item_state = "analyzer"
w_class = 1.0
m_amt = 60
g_amt = 30
var/emagged = 0.0
var/recording = 0.0
var/playing = 0.0
var/timerecorded = 0.0
var/playsleepseconds = 0.0
var/list/storedinfo = new/list()
var/list/timestamp = new/list()
var/canprint = 1
flags = FPRINT | TABLEPASS| CONDUCT
throwforce = 2
throw_speed = 4
throw_range = 20
/obj/item/device/taperecorder/hear_talk(mob/living/M as mob, msg)
if (recording)
var/ending = copytext(msg, length(msg))
src.timestamp+= src.timerecorded
if (M.stuttering)
src.storedinfo += "\[[time2text(src.timerecorded*10,"mm:ss")]\] [M.name] stammers, \"[msg]\""
return
if (M.getBrainLoss() >= 60)
src.storedinfo += "\[[time2text(src.timerecorded*10,"mm:ss")]\] [M.name] gibbers, \"[msg]\""
return
if (ending == "?")
src.storedinfo += "\[[time2text(src.timerecorded*10,"mm:ss")]\] [M.name] asks, \"[msg]\""
return
else if (ending == "!")
src.storedinfo += "\[[time2text(src.timerecorded*10,"mm:ss")]\] [M.name] exclaims, \"[msg]\""
return
src.storedinfo += "\[[time2text(src.timerecorded*10,"mm:ss")]\] [M.name] says, \"[msg]\""
return
/obj/item/device/taperecorder/attackby(obj/item/weapon/W as obj, mob/user as mob)
..()
if (istype(W, /obj/item/weapon/card/emag))
if (src.emagged == 0)
src.emagged = 1
src.recording = 0
user << "\red PZZTTPFFFT"
src.icon_state = "taperecorderidle"
else
user << "\red That is already emagged!"
/obj/item/device/taperecorder/proc/explode()
var/turf/T = get_turf(src.loc)
if (ismob(src.loc))
var/mob/M = src.loc
M.show_message("\red The [src] explodes!", 1)
if(T)
T.hotspot_expose(700,125)
explosion(T, -1, -1, 0, 4)
del(src)
return
/obj/item/device/taperecorder/verb/record()
set name = "Start Recording"
set category = "Object"
if(usr.stat)
usr << "Not when you're incapacitated."
return
if(src.emagged == 1)
usr << "\red The tape recorder makes a scratchy noise."
return
src.icon_state = "taperecorderrecording"
if(src.timerecorded < 3600 && src.playing == 0)
usr << "\blue Recording started."
src.recording = 1
src.timestamp+= src.timerecorded
src.storedinfo += "\[[time2text(src.timerecorded*10,"mm:ss")]\] Recording started."
for(src.timerecorded, src.timerecorded<3600)
if(src.recording == 0)
break
src.timerecorded++
sleep(10)
src.recording = 0
src.icon_state = "taperecorderidle"
return
else
usr << "\red Either your tape recorder's memory is full, or it is currently playing back its memory."
/obj/item/device/taperecorder/verb/stop()
set name = "Stop"
set category = "Object"
if(usr.stat)
usr << "Not when you're incapacitated."
return
if (src.recording == 1)
src.recording = 0
src.timestamp+= src.timerecorded
src.storedinfo += "\[[time2text(src.timerecorded*10,"mm:ss")]\] Recording stopped."
usr << "\blue Recording stopped."
src.icon_state = "taperecorderidle"
return
else if (src.playing == 1)
src.playing = 0
var/turf/T = get_turf(src)
for(var/mob/O in hearers(world.view-1, T))
O.show_message("<font color=Maroon><B>Tape Recorder</B>: Playback stopped.</font>",2)
src.icon_state = "taperecorderidle"
return
else
usr << "\red Stop what?"
return
/obj/item/device/taperecorder/verb/clear_memory()
set name = "Clear Memory"
set category = "Object"
if(usr.stat)
usr << "Not when you're incapicated."
return
if(src.emagged == 1)
usr << "\red The tape recorder makes a scratchy noise."
return
if (src.recording == 1 || src.playing == 1)
usr << "\red You can't clear the memory while playing or recording!"
return
else
src.storedinfo -= src.storedinfo
src.timestamp -= src.timestamp
src.timerecorded = 0
usr << "\blue Memory cleared."
return
/obj/item/device/taperecorder/verb/playback_memory()
set name = "Playback Memory"
set category = "Object"
if(usr.stat)
usr << "Not when you're incapicated."
return
if (src.recording == 1)
usr << "\red You can't playback when recording!"
return
if (src.playing == 1)
usr << "\red You're already playing!"
return
src.playing = 1
src.icon_state = "taperecorderplaying"
usr << "\blue Playing started."
for(var/i=1,src.timerecorded<3600,sleep(10 * (src.playsleepseconds) ))
if (src.playing == 0)
break
if (src.storedinfo.len < i)
break
var/turf/T = get_turf(src)
for(var/mob/O in hearers(world.view-1, T))
O.show_message("<font color=Maroon><B>Tape Recorder</B>: [src.storedinfo[i]]</font>",2)
if (src.storedinfo.len < i+1)
src.playsleepseconds = 1
sleep(10)
T = get_turf(src)
for(var/mob/O in hearers(world.view-1, T))
O.show_message("<font color=Maroon><B>Tape Recorder</B>: End of recording.</font>",2)
else
src.playsleepseconds = src.timestamp[i+1] - src.timestamp[i]
if (src.playsleepseconds > 19)
sleep(10)
T = get_turf(src)
for(var/mob/O in hearers(world.view-1, T))
O.show_message("<font color=Maroon><B>Tape Recorder</B>: Skipping [src.playsleepseconds] seconds of silence</font>",2)
src.playsleepseconds = 1
i++
src.icon_state = "taperecorderidle"
src.playing = 0
if (src.emagged == 1.0)
for(var/mob/O in hearers(world.view-1, get_turf(src)))
O.show_message("Tape Recorder: This tape recorder will self destruct in <B>5</B>",2)
sleep(10)
for(var/mob/O in hearers(world.view-1, get_turf(src)))
O.show_message("<B>4</B>",2)
sleep(10)
for(var/mob/O in hearers(world.view-1, get_turf(src)))
O.show_message("<B>3</B>",2)
sleep(10)
for(var/mob/O in hearers(world.view-1, get_turf(src)))
O.show_message("<B>2</B>",2)
sleep(10)
for(var/mob/O in hearers(world.view-1, get_turf(src)))
O.show_message("<B>1</B>",2)
sleep(10)
src.explode()
/obj/item/device/taperecorder/verb/print_transcript()
set name = "Print Transcript"
set category = "Object"
if (!canprint)
usr << "\red The recorder can't print that fast!"
return
if (src.recording == 1 || src.playing == 1)
usr << "\red You can't print the transcript while playing or recording!"
return
usr << "\blue Transcript printed."
var/obj/item/weapon/paper/P = new /obj/item/weapon/paper(get_turf(src))
var/t1 = "<B>Transcript:</B><BR><BR>"
for(var/i=1,src.storedinfo.len >= i,i++)
t1 += "[src.storedinfo[i]]<BR>"
P.info = t1
P.name = "paper- 'Transcript'"
canprint = 0
sleep(300)
canprint = 1
/obj/item/device/taperecorder/attack_self(mob/user)
if(src.recording == 0 && src.playing == 0)
if(usr.stat)
usr << "Not when you're incapacitated."
return
if(src.emagged == 1)
usr << "\red The tape recorder makes a scratchy noise."
return
src.icon_state = "taperecorderrecording"
if(src.timerecorded < 3600 && src.playing == 0)
usr << "\blue Recording started."
src.recording = 1
src.timestamp+= src.timerecorded
src.storedinfo += "\[[time2text(src.timerecorded*10,"mm:ss")]\] Recording started."
for(src.timerecorded, src.timerecorded<3600)
if(src.recording == 0)
break
src.timerecorded++
sleep(10)
src.recording = 0
src.icon_state = "taperecorderidle"
return
else
usr << "\red Either your tape recorder's memory is full, or it is currently playing back its memory."
else
if(usr.stat)
usr << "Not when you're incapacitated."
return
if (src.recording == 1)
src.recording = 0
src.timestamp+= src.timerecorded
src.storedinfo += "\[[time2text(src.timerecorded*10,"mm:ss")]\] Recording stopped."
usr << "\blue Recording stopped."
src.icon_state = "taperecorderidle"
return
else if (src.playing == 1)
src.playing = 0
var/turf/T = get_turf(src)
for(var/mob/O in hearers(world.view-1, T))
O.show_message("<font color=Maroon><B>Tape Recorder</B>: Playback stopped.</font>",2)
src.icon_state = "taperecorderidle"
return
else
usr << "\red Stop what?"
return
@@ -0,0 +1,61 @@
/*
Miscellaneous traitor devices
BATTERER
*/
/*
The Batterer, like a flashbang but 50% chance to knock people over. Can be either very
effective or pretty fucking useless.
*/
/obj/item/device/batterer
name = "mind batterer"
desc = "A strange device with twin antennas."
icon_state = "batterer"
throwforce = 5
w_class = 1.0
throw_speed = 4
throw_range = 10
flags = FPRINT | TABLEPASS| CONDUCT
item_state = "electronic"
origin_tech = "magnets=3;combat=3;syndicate=3"
var/times_used = 0 //Number of times it's been used.
var/max_uses = 2
/obj/item/device/batterer/attack_self(mob/living/carbon/user as mob, flag = 0, emp = 0)
if(!user) return
if(times_used >= max_uses)
user << "\red The mind batterer has been burnt out!"
return
user.attack_log += text("\[[time_stamp()]\] <font color='red'>Used [src] to knock down people in the area.</font>")
for(var/mob/living/carbon/human/M in orange(10, user))
spawn()
if(prob(50))
M.Weaken(rand(10,20))
if(prob(25))
M.Stun(rand(5,10))
M << "\red <b>You feel a tremendous, paralyzing wave flood your mind.</b>"
else
M << "\red <b>You feel a sudden, electric jolt travel through your head.</b>"
playsound(src.loc, 'sound/misc/interference.ogg', 50, 1)
user << "\blue You trigger [src]."
times_used += 1
if(times_used >= max_uses)
icon_state = "battererburnt"
@@ -0,0 +1,179 @@
/obj/item/device/transfer_valve
icon = 'icons/obj/assemblies.dmi'
name = "tank transfer valve"
icon_state = "valve_1"
desc = "Regulates the transfer of air between two tanks"
var/obj/item/weapon/tank/tank_one
var/obj/item/weapon/tank/tank_two
var/obj/item/device/attached_device
var/mob/attacher = "Unknown"
var/valve_open = 0
var/toggle = 1
/obj/item/device/transfer_valve/proc/process_activation(var/obj/item/device/D)
/obj/item/device/transfer_valve/IsAssemblyHolder()
return 1
/obj/item/device/transfer_valve/attackby(obj/item/item, mob/user)
if(istype(item, /obj/item/weapon/tank))
if(tank_one && tank_two)
user << "<span class='warning'>There are already two tanks attached, remove one first.</span>"
return
if(!tank_one)
tank_one = item
user.drop_item()
item.loc = src
user << "<span class='notice'>You attach the tank to the transfer valve.</span>"
else if(!tank_two)
tank_two = item
user.drop_item()
item.loc = src
user << "<span class='notice'>You attach the tank to the transfer valve.</span>"
update_icon()
//TODO: Have this take an assemblyholder
else if(isassembly(item))
var/obj/item/device/assembly/A = item
if(A.secured)
user << "<span class='notice'>The device is secured.</span>"
return
if(attached_device)
user << "<span class='warning'>There is already an device attached to the valve, remove it first.</span>"
return
user.remove_from_mob(item)
attached_device = A
A.loc = src
user << "<span class='notice'>You attach the [item] to the valve controls and secure it.</span>"
A.holder = src
A.toggle_secure()
bombers += "[key_name(user)] attached a [item] to a transfer valve."
message_admins("[key_name_admin(user)] attached a [item] to a transfer valve.")
log_game("[key_name_admin(user)] attached a [item] to a transfer valve.")
attacher = key_name(user)
return
/obj/item/device/transfer_valve/HasProximity(atom/movable/AM as mob|obj)
if(!attached_device) return
attached_device.HasProximity(AM)
return
/obj/item/device/transfer_valve/attack_self(mob/user as mob)
user.machine = src
var/dat = {"<B> Valve properties: </B>
<BR> <B> Attachment one:</B> [tank_one] [tank_one ? "<A href='?src=\ref[src];tankone=1'>Remove</A>" : ""]
<BR> <B> Attachment two:</B> [tank_two] [tank_two ? "<A href='?src=\ref[src];tanktwo=1'>Remove</A>" : ""]
<BR> <B> Valve attachment:</B> [attached_device ? "<A href='?src=\ref[src];device=1'>[attached_device]</A>" : "None"] [attached_device ? "<A href='?src=\ref[src];rem_device=1'>Remove</A>" : ""]
<BR> <B> Valve status: </B> [ valve_open ? "<A href='?src=\ref[src];open=1'>Closed</A> <B>Open</B>" : "<B>Closed</B> <A href='?src=\ref[src];open=1'>Open</A>"]"}
user << browse(dat, "window=trans_valve;size=600x300")
onclose(user, "trans_valve")
return
/obj/item/device/transfer_valve/Topic(href, href_list)
..()
if ( usr.stat || usr.restrained() )
return
if (src.loc == usr)
if(tank_one && href_list["tankone"])
split_gases()
valve_open = 0
tank_one.loc = get_turf(src)
tank_one = null
update_icon()
else if(tank_two && href_list["tanktwo"])
split_gases()
valve_open = 0
tank_two.loc = get_turf(src)
tank_two = null
update_icon()
else if(href_list["open"])
toggle_valve()
else if(attached_device)
if(href_list["rem_device"])
attached_device.loc = get_turf(src)
attached_device:holder = null
attached_device = null
update_icon()
if(href_list["device"])
attached_device.attack_self(usr)
src.attack_self(usr)
src.add_fingerprint(usr)
return
return
/obj/item/device/transfer_valve/process_activation(var/obj/item/device/D)
if(toggle)
toggle = 0
toggle_valve()
spawn(50) // To stop a signal being spammed from a proxy sensor constantly going off or whatever
toggle = 1
/obj/item/device/transfer_valve/update_icon()
overlays = null
underlays = null
if(!tank_one && !tank_two && !attached_device)
icon_state = "valve_1"
return
icon_state = "valve"
if(tank_one)
overlays += "[tank_one.icon_state]"
if(tank_two)
var/icon/J = new(icon, icon_state = "[tank_two.icon_state]")
J.Shift(WEST, 13)
underlays += J
if(attached_device)
overlays += "device"
/obj/item/device/transfer_valve/proc/merge_gases()
tank_two.air_contents.volume += tank_one.air_contents.volume
var/datum/gas_mixture/temp
temp = tank_one.air_contents.remove_ratio(1)
tank_two.air_contents.merge(temp)
/obj/item/device/transfer_valve/proc/split_gases()
if (!valve_open || !tank_one || !tank_two)
return
var/ratio1 = tank_one.air_contents.volume/tank_two.air_contents.volume
var/datum/gas_mixture/temp
temp = tank_two.air_contents.remove_ratio(ratio1)
tank_one.air_contents.merge(temp)
tank_two.air_contents.volume -= tank_one.air_contents.volume
/*
Exadv1: I know this isn't how it's going to work, but this was just to check
it explodes properly when it gets a signal (and it does).
*/
/obj/item/device/transfer_valve/proc/toggle_valve()
if(valve_open==0 && (tank_one && tank_two))
valve_open = 1
var/turf/bombturf = get_turf(src)
var/bombarea = bombturf.loc.name
var/log_str = "Bomb valve opened in [bombarea] with device attacher: [attacher]. Last touched by: [src.fingerprintslast]"
bombers += log_str
message_admins(log_str)
log_game(log_str)
merge_gases()
spawn(20) // In case one tank bursts
for (var/i=0,i<5,i++)
src.update_icon()
sleep(10)
src.update_icon()
else if(valve_open==1 && (tank_one && tank_two))
split_gases()
valve_open = 0
src.update_icon()
// this doesn't do anything but the timer etc. expects it to be here
// eventually maybe have it update icon to show state (timer, prox etc.) like old bombs
/obj/item/device/transfer_valve/proc/c_state()
return
+385
View File
@@ -0,0 +1,385 @@
//This could either be split into the proper DM files or placed somewhere else all together, but it'll do for now -Nodrak
/*
SYNDICATE UPLINKS
TO-DO:
Once wizard is fixed, make sure the uplinks work correctly for it. wizard.dm is right now uncompiled and with broken code in it.
Clean the code up and comment it. Part of it is right now copy-pasted, with the general Topic() and modifications by Abi79.
I should take a more in-depth look at both the copy-pasted code for the individual uplinks below, and at each gamemode's code
to see how uplinks are assigned and if there are any bugs with those.
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 // Welcoming menu message
var/items // List of items
var/item_data // raw item text
var/list/ItemList // Parsed list of items
var/uses // Numbers of crystals
// List of items not to shove in their hands.
var/list/NotInHand = list(/obj/machinery/singularity_beacon/syndicate)
/obj/item/device/uplink/New()
welcome = ticker.mode.uplink_welcome
if(!item_data)
items = dd_replacetext(ticker.mode.uplink_items, "\n", "") // Getting the text string of items
else
items = dd_replacetext(item_data)
ItemList = dd_text2list(src.items, ";") // Parsing the items text string
uses = ticker.mode.uplink_uses
//Let's build a menu!
/obj/item/device/uplink/proc/generate_menu()
var/dat = "<B>[src.welcome]</B><BR>"
dat += "Tele-Crystals left: [src.uses]<BR>"
dat += "<HR>"
dat += "<B>Request item:</B><BR>"
dat += "<I>Each item costs a number of tele-crystals as indicated by the number following their name.</I><br><BR>"
var/cost
var/item
var/name
var/path_obj
var/path_text
var/category_items = 1 //To prevent stupid :P
for(var/D in ItemList)
var/list/O = stringsplit(D, ":")
if(O.len != 3) //If it is not an actual item, make a break in the menu.
if(O.len == 1) //If there is one item, it's probably a title
dat += "<b>[O[1]]</b><br>"
category_items = 0
else //Else, it's a white space.
if(category_items < 1) //If there were no itens in the last category...
dat += "<i>We apologize, as you could not afford anything from this category.</i><br>"
dat += "<br>"
continue
path_text = O[1]
cost = text2num(O[2])
if(cost>uses)
continue
path_obj = text2path(path_text)
item = new path_obj()
name = O[3]
del item
dat += "<A href='byond://?src=\ref[src];buy_item=[path_text];cost=[cost]'>[name]</A> ([cost])<BR>"
category_items++
dat += "<A href='byond://?src=\ref[src];buy_item=random'>Random Item (??)</A><br>"
dat += "<HR>"
return dat
//If 'random' was selected
/obj/item/device/uplink/proc/chooseRandomItem()
var/list/randomItems = list()
//Sorry for all the ifs, but it makes it 1000 times easier for other people/servers to add or remove items from this list
//Add only items the player can afford:
if(uses > 19)
randomItems.Add("/obj/item/weapon/circuitboard/teleporter") //Teleporter Circuit Board (costs 20, for nuke ops)
if(uses > 9)
randomItems.Add("/obj/item/toy/syndicateballoon")//Syndicate Balloon
randomItems.Add("/obj/item/weapon/storage/syndie_kit/imp_uplink") //Uplink Implanter
randomItems.Add("/obj/item/weapon/storage/box/syndicate") //Syndicate bundle
//if(uses > 8) //Nothing... yet.
//if(uses > 7) //Nothing... yet.
if(uses > 6)
randomItems.Add("/obj/item/weapon/aiModule/syndicate") //Hacked AI Upload Module
randomItems.Add("/obj/item/device/radio/beacon/syndicate") //Singularity Beacon
if(uses > 5)
randomItems.Add("/obj/item/weapon/gun/projectile") //Revolver
if(uses > 4)
randomItems.Add("/obj/item/weapon/gun/energy/crossbow") //Energy Crossbow
randomItems.Add("/obj/item/device/powersink") //Powersink
if(uses > 3)
randomItems.Add("/obj/item/weapon/melee/energy/sword") //Energy Sword
randomItems.Add("/obj/item/clothing/mask/gas/voice") //Voice Changer
randomItems.Add("/obj/item/device/chameleon") //Chameleon Projector
if(uses > 2)
randomItems.Add("/obj/item/weapon/storage/emp_kit") //EMP Grenades
randomItems.Add("/obj/item/weapon/pen/paralysis") //Paralysis Pen
randomItems.Add("/obj/item/weapon/cartridge/syndicate") //Detomatix Cartridge
randomItems.Add("/obj/item/clothing/under/chameleon") //Chameleon Jumpsuit
randomItems.Add("/obj/item/weapon/card/id/syndicate") //Agent ID Card
randomItems.Add("/obj/item/weapon/card/emag") //Cryptographic Sequencer
randomItems.Add("/obj/item/weapon/storage/syndie_kit/space") //Syndicate Space Suit
randomItems.Add("/obj/item/device/encryptionkey/binary") //Binary Translator Key
randomItems.Add("/obj/item/weapon/storage/syndie_kit/imp_freedom") //Freedom Implant
randomItems.Add("/obj/item/clothing/glasses/thermal/syndi") //Thermal Imaging Goggles
if(uses > 1)
/*
var/list/usrItems = usr.get_contents() //Checks to see if the user has a revolver before giving ammo
var/hasRevolver = 0
for(var/obj/I in usrItems) //Only add revolver ammo if the user has a gun that can shoot it
if(istype(I,/obj/item/weapon/gun/projectile))
hasRevolver = 1
if(hasRevolver) randomItems.Add("/obj/item/ammo_magazine/a357") //Revolver ammo
*/
randomItems.Add("/obj/item/ammo_magazine/a357") //Revolver ammo
randomItems.Add("/obj/item/clothing/shoes/syndigaloshes") //No-Slip Syndicate Shoes
randomItems.Add("/obj/item/weapon/plastique") //C4
if(uses > 0)
randomItems.Add("/obj/item/weapon/soap/syndie") //Syndicate Soap
randomItems.Add("/obj/item/weapon/storage/toolbox/syndicate") //Syndicate Toolbox
if(!randomItems.len)
del(randomItems)
return 0
else
var/buyItem = pick(randomItems)
switch(buyItem) //Ok, this gets a little messy, sorry.
if("/obj/item/weapon/circuitboard/teleporter")
uses -= 20
if("/obj/item/toy/syndicateballoon" , "/obj/item/weapon/storage/syndie_kit/imp_uplink" , "/obj/item/weapon/storage/box/syndicate")
uses -= 10
if("/obj/item/weapon/aiModule/syndicate" , "/obj/item/device/radio/beacon/syndicate")
uses -= 7
if("/obj/item/weapon/gun/projectile")
uses -= 6
if("/obj/item/weapon/gun/energy/crossbow" , "/obj/item/device/powersink")
uses -= 5
if("/obj/item/weapon/melee/energy/sword" , "/obj/item/clothing/mask/gas/voice" , "/obj/item/device/chameleon")
uses -= 4
if("/obj/item/weapon/storage/emp_kit" , "/obj/item/weapon/pen/paralysis" , "/obj/item/weapon/cartridge/syndicate" , "/obj/item/clothing/under/chameleon" , \
"/obj/item/weapon/card/id/syndicate" , "/obj/item/weapon/card/emag" , "/obj/item/weapon/storage/syndie_kit/space" , "/obj/item/device/encryptionkey/binary" , \
"/obj/item/weapon/storage/syndie_kit/imp_freedom" , "/obj/item/clothing/glasses/thermal/syndi")
uses -= 3
if("/obj/item/ammo_magazine/a357" , "/obj/item/clothing/shoes/syndigaloshes" , "/obj/item/weapon/plastique")
uses -= 2
if("/obj/item/weapon/soap/syndie" , "/obj/item/weapon/storage/toolbox/syndicate")
uses -= 1
del(randomItems)
return buyItem
/obj/item/device/uplink/proc/handleStatTracking(var/boughtItem)
//For stat tracking, sorry for making it so ugly
if(!boughtItem) return
switch(boughtItem)
if("/obj/item/weapon/circuitboard/teleporter")
feedback_add_details("traitor_uplink_items_bought","TP")
if("/obj/item/toy/syndicateballoon")
feedback_add_details("traitor_uplink_items_bought","BS")
if("/obj/item/weapon/storage/syndie_kit/imp_uplink")
feedback_add_details("traitor_uplink_items_bought","UI")
if("/obj/item/weapon/storage/box/syndicate")
feedback_add_details("traitor_uplink_items_bought","BU")
if("/obj/item/weapon/aiModule/syndicate")
feedback_add_details("traitor_uplink_items_bought","AI")
if("/obj/item/device/radio/beacon/syndicate")
feedback_add_details("traitor_uplink_items_bought","SB")
if("/obj/item/weapon/gun/projectile")
feedback_add_details("traitor_uplink_items_bought","RE")
if("/obj/item/weapon/gun/energy/crossbow")
feedback_add_details("traitor_uplink_items_bought","XB")
if("/obj/item/device/powersink")
feedback_add_details("traitor_uplink_items_bought","PS")
if("/obj/item/weapon/melee/energy/sword")
feedback_add_details("traitor_uplink_items_bought","ES")
if("/obj/item/clothing/mask/gas/voice")
feedback_add_details("traitor_uplink_items_bought","VC")
if("/obj/item/device/chameleon")
feedback_add_details("traitor_uplink_items_bought","CP")
if("/obj/item/weapon/storage/emp_kit")
feedback_add_details("traitor_uplink_items_bought","EM")
if("/obj/item/weapon/pen/paralysis")
feedback_add_details("traitor_uplink_items_bought","PP")
if("/obj/item/weapon/cartridge/syndicate")
feedback_add_details("traitor_uplink_items_bought","DC")
if("/obj/item/clothing/under/chameleon")
feedback_add_details("traitor_uplink_items_bought","CJ")
if("/obj/item/weapon/card/id/syndicate")
feedback_add_details("traitor_uplink_items_bought","AC")
if("/obj/item/weapon/card/emag")
feedback_add_details("traitor_uplink_items_bought","EC")
if("/obj/item/weapon/storage/syndie_kit/space")
feedback_add_details("traitor_uplink_items_bought","SS")
if("/obj/item/device/encryptionkey/binary")
feedback_add_details("traitor_uplink_items_bought","BT")
if("/obj/item/weapon/storage/syndie_kit/imp_freedom")
feedback_add_details("traitor_uplink_items_bought","FI")
if("/obj/item/clothing/glasses/thermal/syndi")
feedback_add_details("traitor_uplink_items_bought","TM")
if("/obj/item/ammo_magazine/a357")
feedback_add_details("traitor_uplink_items_bought","RA")
if("/obj/item/clothing/shoes/syndigaloshes")
feedback_add_details("traitor_uplink_items_bought","SH")
if("/obj/item/weapon/plastique")
feedback_add_details("traitor_uplink_items_bought","C4")
if("/obj/item/weapon/soap/syndie")
feedback_add_details("traitor_uplink_items_bought","SP")
if("/obj/item/weapon/storage/toolbox/syndicate")
feedback_add_details("traitor_uplink_items_bought","ST")
/obj/item/device/uplink/Topic(href, href_list)
if (href_list["buy_item"])
if(href_list["buy_item"] == "random")
var/boughtItem = chooseRandomItem()
if(boughtItem)
href_list["buy_item"] = boughtItem
feedback_add_details("traitor_uplink_items_bought","RN")
return 1
else
return 0
else
if(text2num(href_list["cost"]) > uses) // Not enough crystals for the item
return 0
//if(usr:mind && ticker.mode.traitors[usr:mind])
//var/datum/traitorinfo/info = ticker.mode.traitors[usr:mind]
//info.spawnlist += href_list["buy_item"]
uses -= text2num(href_list["cost"])
handleStatTracking(href_list["buy_item"]) //Note: chooseRandomItem handles it's own stat tracking. This proc is not meant for 'random'.
return 1
// 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!
1. All obj/item 's have a hidden_uplink var. By default it's null. Give the item one with "new(src)", it must be in it's contents. Feel free to add "uses".
2. Code in the triggers. Use check_trigger for this, I recommend closing the item's menu with "usr << browse(null, "window=windowname") if it returns true.
The var/value is the value that will be compared with the var/target. If they are equal it will activate the menu.
3. If you want the menu to stay until the users locks his uplink, add an active_uplink_check(mob/user as mob) in your interact/attack_hand proc.
Then check if it's true, if true return. This will stop the normal menu appearing and will instead show the uplink menu.
*/
/obj/item/device/uplink/hidden
name = "Hidden Uplink."
desc = "There is something wrong if you're examining this."
var/active = 0
var/list/purchase_log = list()
// The hidden uplink MUST be inside an obj/item's contents.
/obj/item/device/uplink/hidden/New()
spawn(2)
if(!istype(src.loc, /obj/item))
del(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
// Directly trigger the uplink. Turn on if it isn't already.
/obj/item/device/uplink/hidden/proc/trigger(mob/user as mob)
if(!active)
toggle()
interact(user)
// Checks to see if the value meets the target. Like a frequency being a traitor_frequency, in order to unlock a headset.
// If true, it accesses trigger() and returns 1. If it fails, it returns false. Use this to see if you need to close the
// current item's menu.
/obj/item/device/uplink/hidden/proc/check_trigger(mob/user as mob, var/value, var/target)
if(value == target)
trigger(user)
return 1
return 0
// 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/proc/interact(mob/user as mob)
var/dat = "<body link='yellow' alink='white' bgcolor='#601414'><font color='white'>"
dat += src.generate_menu()
dat += "<A href='byond://?src=\ref[src];lock=1'>Lock</a>"
dat += "</font></body>"
user << browse(dat, "window=hidden")
onclose(user, "hidden")
return
// The purchasing code.
/obj/item/device/uplink/hidden/Topic(href, href_list)
if (usr.stat || usr.restrained())
return
if (!( istype(usr, /mob/living/carbon/human)))
return 0
if ((usr.contents.Find(src.loc) || (in_range(src.loc, usr) && istype(src.loc.loc, /turf))))
usr.machine = src
if(href_list["lock"])
toggle()
usr << browse(null, "window=hidden")
return 1
if(..(href, href_list) == 1)
var/path_obj = text2path(href_list["buy_item"])
var/obj/I = new path_obj(get_turf(usr))
if(ishuman(usr))
var/mob/living/carbon/human/A = usr
A.put_in_any_hand_if_possible(I)
purchase_log += "[usr] ([usr.ckey]) bought [I]."
interact(usr)
return
// 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
// 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()
hidden_uplink = new(src)
/obj/item/device/radio/uplink/attack_self(mob/user as mob)
if(hidden_uplink)
hidden_uplink.trigger(user)
/obj/item/device/multitool/uplink/New()
hidden_uplink = new(src)
/obj/item/device/multitool/uplink/attack_self(mob/user as mob)
if(hidden_uplink)
hidden_uplink.trigger(user)
/obj/item/device/radio/headset/uplink
traitor_frequency = 1445
/obj/item/device/radio/headset/uplink/New()
..()
hidden_uplink = new(src)
hidden_uplink.uses = 10