From 84b99292820a96c3eb81a0b3d4ae71a52a9994a7 Mon Sep 17 00:00:00 2001 From: "petethegoat@gmail.com" Date: Thu, 5 Jul 2012 22:47:30 +0000 Subject: [PATCH] Comitting for Giacom! In short: AI messaging Time of death for health scanners Most lists are sorted alphabetically See http://nanotrasen.com/phpBB3/viewtopic.php?f=16&t=9220 for detailed information. I wasn't able to test this as thoroughly as I'd like, but what I could test seems fine. I don't forsee any issues popping up with this stuff. git-svn-id: http://tgstation13.googlecode.com/svn/trunk@3993 316c924e-a436-60f5-8080-3fe189b3f50e --- code/defines/mob/living/living.dm | 1 + code/defines/mob/living/silicon/ai.dm | 1 + code/defines/procs/helpers.dm | 26 ++ .../gamemodes/changeling/changeling_powers.dm | 3 + code/game/gamemodes/events/ninja_equipment.dm | 2 +- code/game/machinery/camera.dm | 2 + code/game/machinery/computer/card.dm | 18 +- code/game/machinery/computer/crew.dm | 16 +- code/game/machinery/computer/medical.dm | 2 +- code/game/machinery/computer/security.dm | 26 +- code/game/objects/devices/PDA/PDA.dm | 286 ++++++++++-------- code/game/objects/devices/PDA/cart.dm | 6 +- code/game/objects/devices/scanners.dm | 4 +- code/modules/chemical/Chemistry-Reagents.dm | 1 + code/modules/mob/dead/observer/observer.dm | 2 +- .../mob/living/carbon/alien/humanoid/death.dm | 2 +- .../mob/living/carbon/alien/larva/death.dm | 2 +- code/modules/mob/living/carbon/brain/death.dm | 2 +- code/modules/mob/living/carbon/human/death.dm | 2 +- code/modules/mob/living/silicon/ai/ai.dm | 15 +- code/modules/mob/living/silicon/ai/death.dm | 2 +- code/modules/mob/living/silicon/ai/life.dm | 4 + .../mob/living/silicon/pai/software.dm | 14 +- .../modules/mob/living/silicon/robot/death.dm | 2 +- icons/obj/ammo.dmi | Bin 9521 -> 9339 bytes 25 files changed, 281 insertions(+), 160 deletions(-) diff --git a/code/defines/mob/living/living.dm b/code/defines/mob/living/living.dm index d4709674483..8e6d241673a 100644 --- a/code/defines/mob/living/living.dm +++ b/code/defines/mob/living/living.dm @@ -5,3 +5,4 @@ var/t_n2 = null var/now_pushing = null var/cameraFollow = null + var/tod = null // Time of death diff --git a/code/defines/mob/living/silicon/ai.dm b/code/defines/mob/living/silicon/ai.dm index e9fc9c75502..c916c51a904 100644 --- a/code/defines/mob/living/silicon/ai.dm +++ b/code/defines/mob/living/silicon/ai.dm @@ -15,6 +15,7 @@ var/lawcheck[1] var/ioncheck[1] var/icon/holo_icon//Default is assigned when AI is created. + var/obj/item/device/pda/ai/aiPDA = null //MALFUNCTION var/datum/AI_Module/module_picker/malf_picker diff --git a/code/defines/procs/helpers.dm b/code/defines/procs/helpers.dm index 4be223c0988..8107839b324 100644 --- a/code/defines/procs/helpers.dm +++ b/code/defines/procs/helpers.dm @@ -246,6 +246,29 @@ /proc/capitalize(var/t as text) return uppertext(copytext(t, 1, 2)) + copytext(t, 2) +/proc/sortRecord(var/list/datum/data/record/L, var/field = "name", var/order = 1) + if(L.len < 2) + return L + var/middle = L.len / 2 + 1 + return mergeRecordLists(sortRecord(L.Copy(0, middle), field, order), sortRecord(L.Copy(middle), field, order), field, order) + + +/proc/mergeRecordLists(var/list/datum/data/record/L, var/list/datum/data/record/R, var/field = "name", var/order = 1) + var/Li=1 + var/Ri=1 + var/list/result = new() + while(Li <= L.len && Ri <= R.len) + var/datum/data/record/rL = L[Li] + var/datum/data/record/rR = R[Ri] + if(sorttext(rL.fields[field], rR.fields[field]) == order) + result += L[Li++] + else + result += R[Ri++] + + if(Li <= L.len) + return (result + L.Copy(Li, 0)) + return (result + R.Copy(Ri, 0)) + /proc/sortList(var/list/L) if(L.len < 2) return L @@ -1846,3 +1869,6 @@ proc/get_mob_with_client_list() if (M.client) mobs += M return mobs + +proc/worldtime2text() + return "[round(world.time / 36000)+12]:[(world.time / 600 % 60) < 10 ? add_zero(world.time / 600 % 60, 1) : world.time / 600 % 60]" diff --git a/code/game/gamemodes/changeling/changeling_powers.dm b/code/game/gamemodes/changeling/changeling_powers.dm index ea5b5ead99d..9084174db6d 100644 --- a/code/game/gamemodes/changeling/changeling_powers.dm +++ b/code/game/gamemodes/changeling/changeling_powers.dm @@ -560,10 +560,13 @@ Tarjan shit, not recoding this -Sieve{R}*/ L.remove_changeling_powers() L.emote("gasp") + if(isnull(L.tod)) // If we weren't already dead + L.tod = worldtime2text() spawn(1200) L.stat = 0 //usr.fireloss = 0 + L.tod = null L.setToxLoss(0) //usr.bruteloss = 0 L.setOxyLoss(0) diff --git a/code/game/gamemodes/events/ninja_equipment.dm b/code/game/gamemodes/events/ninja_equipment.dm index ddbad486468..3f33707ab7e 100644 --- a/code/game/gamemodes/events/ninja_equipment.dm +++ b/code/game/gamemodes/events/ninja_equipment.dm @@ -255,7 +255,7 @@ ________________________________________________________________________________ else dat += "

SpiderOS v.ERR-RR00123

" dat += "
" - dat += " Current Time: [round(world.time / 36000)+12]:[(world.time / 600 % 60) < 10 ? add_zero(world.time / 600 % 60, 1) : world.time / 600 % 60]
" + dat += " Current Time: [worldtime2text()]
" dat += " Battery Life: [round(cell.charge/100)]%
" dat += " Smoke Bombs: \Roman [s_bombs]
" dat += " pai Device: " diff --git a/code/game/machinery/camera.dm b/code/game/machinery/camera.dm index 0a5e693731a..e6f458cbeee 100644 --- a/code/game/machinery/camera.dm +++ b/code/game/machinery/camera.dm @@ -77,6 +77,8 @@ creatures[name] = M + creatures = sortList(creatures) + var/target_name = input(usr, "Which creature should you track?") as null|anything in creatures if (!target_name) diff --git a/code/game/machinery/computer/card.dm b/code/game/machinery/computer/card.dm index a1c1c6d1a33..1415497fbaf 100644 --- a/code/game/machinery/computer/card.dm +++ b/code/game/machinery/computer/card.dm @@ -52,9 +52,13 @@ return if (mode) // accessing crew manifest var/crew = "" - for(var/datum/data/record/t in data_core.general) - crew += "[t.fields["name"]] - [t.fields["rank"]]
" - dat = "Crew Manifest:
Please use security record computer to modify entries.
[crew]Print

Access ID modification console.
" + var/list/L = list() + for (var/datum/data/record/t in data_core.general) + var/R = t.fields["name"] + " - " + t.fields["rank"] + L += R + for(var/R in sortList(L)) + crew += "[R]
" + dat = "Crew Manifest:
Please use security record computer to modify entries.

[crew]Print

Access ID modification console.
" else var/header = "
Identification Card Modifier
" @@ -248,8 +252,12 @@ sleep(50) var/obj/item/weapon/paper/P = new /obj/item/weapon/paper( loc ) var/t1 = "Crew Manifest:
" - for(var/datum/data/record/t in data_core.general) - t1 += "[t.fields["name"]] - [t.fields["rank"]]
" + var/list/L = list() + for (var/datum/data/record/t in data_core.general) + var/R = t.fields["name"] + " - " + t.fields["rank"] + L += R + for(var/R in sortList(L)) + t1 += "[R]
" P.info = t1 P.name = "paper- 'Crew Manifest'" printing = null diff --git a/code/game/machinery/computer/crew.dm b/code/game/machinery/computer/crew.dm index 2b6d0c627a6..d1646749e77 100644 --- a/code/game/machinery/computer/crew.dm +++ b/code/game/machinery/computer/crew.dm @@ -67,7 +67,9 @@ t += "
Refresh" t += "
Close" t += "" + var/list/logs = list() for(var/obj/item/clothing/under/C in src.tracked) + var/log = "" if((C) && (C.has_sensor) && (C.loc) && (C.loc.z == 1) && C.sensor_mode) if(istype(C.loc, /mob/living/carbon/human)) var/mob/living/carbon/human/H = C.loc @@ -77,16 +79,20 @@ var/dam4 = round(H.getBruteLoss(),1) if(H.wear_id) - t += "" + log += "" else - t += "" + log += "" switch(C.sensor_mode) if(1) - t+= "" + log+= "" if(2) - t += "" + log += "" if(3) - t += "" + log+= "" + logs += log + logs = sortList(logs) + for(var/log in logs) + t += log t += "
NameVitalsPosition
[H.wear_id.name]
[H.wear_id.name]
Unknown:
Unknown:[H.stat > 1 ? "Deceased" : "Living"]Not Available
[H.stat > 1 ? "Deceased" : "Living"]Not Available
[H.stat > 1 ? "Deceased" : "Living"], [dam1] - [dam2] - [dam3] - [dam4]Not Available
[H.stat > 1 ? "Deceased" : "Living"], [dam1] - [dam2] - [dam3] - [dam4]Not Available
[H.stat > 1 ? "Deceased" : "Living"], [dam2] - [dam2] - [dam3] - [dam4][get_area(H)] ([H.x], [H.y])
[H.stat > 1 ? "Deceased" : "Living"], [dam2] - [dam2] - [dam3] - [dam4][get_area(H)] ([H.x], [H.y])
" t += "" user << browse(t, "window=crewcomp;size=900x600") diff --git a/code/game/machinery/computer/medical.dm b/code/game/machinery/computer/medical.dm index 2aa4ccbb4ae..828a55d1f1f 100644 --- a/code/game/machinery/computer/medical.dm +++ b/code/game/machinery/computer/medical.dm @@ -45,7 +45,7 @@ "} if(2.0) dat += "Record List:
" - for(var/datum/data/record/R in data_core.general) + for(var/datum/data/record/R in sortRecord(data_core.general)) dat += text("[]: []
", src, R, R.fields["id"], R.fields["name"]) //Foreach goto(132) dat += text("
Back", src) diff --git a/code/game/machinery/computer/security.dm b/code/game/machinery/computer/security.dm index 5eaa46470d5..a77d9ed4779 100644 --- a/code/game/machinery/computer/security.dm +++ b/code/game/machinery/computer/security.dm @@ -18,6 +18,9 @@ var/can_change_id = 0 var/list/Perp var/tempname = null + //Sorting Variables + var/sortBy = "name" + var/order = 1 // -1 = Descending - 1 = Ascending /obj/machinery/computer/secure_data/attackby(obj/item/O as obj, user as mob) @@ -60,13 +63,13 @@ - - - - + + + +"} - for(var/datum/data/record/R in data_core.general) + for(var/datum/data/record/R in sortRecord(data_core.general, sortBy, order)) var/crimstat = "" for(var/datum/data/record/E in data_core.security) if ((E.fields["name"] == R.fields["name"] && E.fields["id"] == R.fields["id"])) @@ -182,6 +185,18 @@ What a mess.*/ if ((usr.contents.Find(src) || (in_range(src, usr) && istype(loc, /turf))) || (istype(usr, /mob/living/silicon))) usr.machine = src switch(href_list["choice"]) +// SORTING! + if("Sorting") + // Reverse the order if clicked twice + if(sortBy == href_list["sort"]) + if(order == 1) + order = -1 + else + order = 1 + else + // New sorting order! + sortBy = href_list["sort"] + order = initial(order) //BASIC FUNCTIONS if("Clear Screen") temp = null @@ -502,6 +517,7 @@ What a mess.*/ del(active2) else temp = "This function does not appear to be working at the moment. Our apologies." + add_fingerprint(usr) updateUsrDialog() return diff --git a/code/game/objects/devices/PDA/PDA.dm b/code/game/objects/devices/PDA/PDA.dm index e4e4902cdcf..aff5cfdf240 100644 --- a/code/game/objects/devices/PDA/PDA.dm +++ b/code/game/objects/devices/PDA/PDA.dm @@ -171,6 +171,17 @@ var/global/list/obj/item/device/pda/PDAs = list() default_cartridge = /obj/item/weapon/cartridge/medical icon_state = "pda-gene" +// Special AI PDA that cannot explode. +/obj/item/device/pda/ai + icon_state = "NONE" + ttone = "data" + +/obj/item/device/pda/ai/attack_self(mob/user as mob) + if ((honkamt > 0) && (prob(60)))//For clown virus. + honkamt-- + playsound(loc, 'bikehorn.ogg', 30, 1) + return + /* * The Actual PDA */ @@ -196,15 +207,14 @@ var/global/list/obj/item/device/pda/PDAs = list() return 0 var/mob/M = loc - if(!M.canmove) + if(!M.canmove && !isAI(M)) return 0 - if((src in M.contents) || ( istype(loc, /turf) && in_range(src, M) ) ) + if((src in M.contents) || ( istype(loc, /turf) && in_range(src, M) )) return 1 else return 0 - /obj/item/device/pda/MouseDrop(obj/over_object as obj, src_location, over_location) var/mob/M = usr if((!istype(over_object, /obj/screen)) && !M.restrained() && !M.stat && can_use()) @@ -213,6 +223,7 @@ var/global/list/obj/item/device/pda/PDAs = list() //NOTE: graphic resources are loaded on client login /obj/item/device/pda/attack_self(mob/user as mob) + user.machine = src var/dat = "Personal Data Assistant" @@ -238,7 +249,7 @@ var/global/list/obj/item/device/pda/PDAs = list() dat += text("ID: [id ? "[id.registered_name], [id.assignment]" : "----------"]") dat += text("
[id ? "Update PDA Info" : ""]
") - dat += "Station Time: [round(world.time / 36000)+12]:[(world.time / 600 % 60) < 10 ? add_zero(world.time / 600 % 60, 1) : world.time / 600 % 60]"//:[world.time / 100 % 6][world.time / 100 % 10]" + dat += "Station Time: [worldtime2text()]"//:[world.time / 100 % 6][world.time / 100 % 10]" dat += "

" @@ -339,7 +350,7 @@ var/global/list/obj/item/device/pda/PDAs = list() for (var/obj/item/device/pda/P in PDAs) if (!P.owner||P.toff||P == src) continue dat += "
  • [P]" - if (istype(cartridge, /obj/item/weapon/cartridge/syndicate)) + if (istype(cartridge, /obj/item/weapon/cartridge/syndicate) && !istype(P, /obj/item/device/pda/ai)) dat += " (*Detonate*)" if (istype(cartridge, /obj/item/weapon/cartridge/clown)) dat += " (*Send Virus*)" @@ -544,94 +555,8 @@ var/global/list/obj/item/device/pda/PDAs = list() U << browse(null, "window=pda") return if("Message") - var/t = input(U, "Please enter message", name, null) as text - t = copytext(sanitize(t), 1, MAX_MESSAGE_LEN) - if (!t) - return - if (!in_range(src, U) && loc != U) - return var/obj/item/device/pda/P = locate(href_list["target"]) - if(!istype(P)) return - - if(istype(P, /obj/item/device/pda)) - if (isnull(P)||P.toff || toff) - return - - if (last_text && world.time < last_text + 5) - return - - last_text = world.time - // check if telecomms I/O route 1459 is stable - //var/telecomms_intact = telecomms_process(P.owner, owner, t) - var/obj/machinery/message_server/useMS = null - if(message_servers) - for (var/obj/machinery/message_server/MS in message_servers) - //PDAs are now dependant on the Message Server. - if(MS.active) - useMS = MS - break - if(useMS) // only send the message if it's stable - useMS.send_pda_message("[P.owner]","[owner]","[t]") - - tnote += "→ To [P.owner]:
    [t]
    " - P.tnote += "← From [owner] ([ownjob]):
    [t]
    " - - if (prob(15)) //Give the AI a chance of intercepting the message - var/who = src.owner - if(prob(50)) - who = P:owner - for(var/mob/living/silicon/ai/ai in world) - ai.show_message("Intercepted message from [who]: [t]") - - if (!P.silent) - playsound(P.loc, 'twobeep.ogg', 50, 1) - for (var/mob/O in hearers(3, P.loc)) - O.show_message(text("\icon[P] *[P.ttone]*")) - if( P.loc && ishuman(P.loc) ) - var/mob/living/carbon/human/H = P.loc - H << "\icon[P] Message from [src.owner] ([ownjob]), \"[t]\" (Reply)" - log_pda("[usr] (PDA: [src.name]) sent \"[t]\" to [P.name]") - P.overlays = null - P.overlays += image('pda.dmi', "pda-r") - else - U << "ERROR: Server isn't responding." - - // pAI Message - else - - //var/telecomms_intact = telecomms_process(P.owner, owner, t) - var/obj/machinery/message_server/useMS = null - if(message_servers) - for (var/obj/machinery/message_server/MS in message_servers) - //PDAs are now dependant on the Message Server. - if(MS.active) - useMS = MS - break - if(useMS) // only send the message if it's stable - useMS.send_pda_message("[P.owner]","[owner]","[t]") - tnote += "→ To [P]:
    [t]
    " - P.tnote += "← From [src]:
    [t]
    " - - - if (prob(15)) //Give the AI a chance of intercepting the message - var/who = src - if(prob(50)) - who = P - for (var/mob/living/silicon/ai/ai in world) - ai.show_message("Intercepted message from [who]: [t]") - - if (!P.silent) - playsound(P.loc, 'twobeep.ogg', 50, 1) - for (var/mob/O in hearers(3, P.loc)) - O.show_message(text("\icon[P] *[P.ttone]*")) - if( P.loc && ishuman(P.loc) ) - var/mob/living/carbon/human/H = P.loc - H << "\icon[P] Message from [src.owner] ([ownjob]), \"[t]\" (Reply)" - log_pda("[usr] (PDA: [src.name]) sent \"[t]\" to [P.name]") - else - U << "ERROR: Server isn't responding." - - + src.create_message(U, P) if("Send Honk")//Honk virus if(istype(cartridge, /obj/item/weapon/cartridge/clown))//Cartridge checks are kind of unnecessary since everything is done through switch. @@ -678,6 +603,7 @@ var/global/list/obj/item/device/pda/PDAs = list() if(uplink) uplink.active = 0 note = uplink.orignote + mode = 0 // To stop people metagaming that PDAs on the note screen means it is an uplink PDA. if("Detonate")//Detonate PDA if(istype(cartridge, /obj/item/weapon/cartridge/syndicate)) var/obj/item/device/pda/P = locate(href_list["target"]) @@ -794,6 +720,99 @@ var/global/list/obj/item/device/pda/PDAs = list() return telecomms_intact +/obj/item/device/pda/proc/create_message(var/mob/living/U = usr, var/obj/item/device/pda/P) + + var/t = input(U, "Please enter message", name, null) as text + t = copytext(sanitize(t), 1, MAX_MESSAGE_LEN) + if (!t) + return + if (!in_range(src, U) && loc != U) + return + + if(!istype(P)) return + + if(istype(P, /obj/item/device/pda)) + if (isnull(P)||P.toff || toff) + return + + if (last_text && world.time < last_text + 5) + return + + last_text = world.time + // check if telecomms I/O route 1459 is stable + //var/telecomms_intact = telecomms_process(P.owner, owner, t) + var/obj/machinery/message_server/useMS = null + if(message_servers) + for (var/obj/machinery/message_server/MS in message_servers) + //PDAs are now dependant on the Message Server. + if(MS.active) + useMS = MS + break + if(useMS) // only send the message if it's stable + useMS.send_pda_message("[P.owner]","[owner]","[t]") + + tnote += "→ To [P.owner]:
    [t]
    " + P.tnote += "← From [owner] ([ownjob]):
    [t]
    " + + if (prob(15)) //Give the AI a chance of intercepting the message + var/who = src.owner + if(prob(50)) + who = P:owner + for(var/mob/living/silicon/ai/ai in world) + // Allows other AIs to intercept the message but the AI won't intercept their own message. + if(ai.aiPDA != P && ai.aiPDA != src) + ai.show_message("Intercepted message from [who]: [t]") + + if (!P.silent) + playsound(P.loc, 'twobeep.ogg', 50, 1) + for (var/mob/O in hearers(3, P.loc)) + if(!P.silent) O.show_message(text("\icon[P] *[P.ttone]*")) + if( P.loc && isliving(P.loc) ) + var/mob/living/L = P.loc + L << "\icon[P] Message from [src.owner] ([ownjob]), \"[t]\" (Reply)" + + log_pda("[usr] (PDA: [src.name]) sent \"[t]\" to [P.name]") + P.overlays = null + P.overlays += image('pda.dmi', "pda-r") + else + U << "ERROR: Server isn't responding." + + // pAI Message + else + + //var/telecomms_intact = telecomms_process(P.owner, owner, t) + var/obj/machinery/message_server/useMS = null + if(message_servers) + for (var/obj/machinery/message_server/MS in message_servers) + //PDAs are now dependant on the Message Server. + if(MS.active) + useMS = MS + break + if(useMS) // only send the message if it's stable + useMS.send_pda_message("[P.owner]","[owner]","[t]") + tnote += "→ To [P]:
    [t]
    " + P.tnote += "← From [src]:
    [t]
    " + + + if (prob(15)) //Give the AI a chance of intercepting the message + var/who = src + if(prob(50)) + who = P + for (var/mob/living/silicon/ai/ai in world) + // Allows other AIs to intercept the message but the AI won't intercept their own message. + if(ai.aiPDA != P && ai.aiPDA != src) + ai.show_message("Intercepted message from [who]: [t]") + + if (!P.silent) + playsound(P.loc, 'twobeep.ogg', 50, 1) + for (var/mob/O in hearers(3, P.loc)) + if(!P.silent) O.show_message(text("\icon[P] *[P.ttone]*")) + if( P.loc && isliving(P.loc) ) + var/mob/living/L = P.loc + L << "\icon[P] Message from [src.owner] ([ownjob]), \"[t]\" (Reply)" + log_pda("[usr] (PDA: [src.name]) sent \"[t]\" to [P.name]") + else + U << "ERROR: Server isn't responding." /obj/item/device/pda/verb/verb_remove_id() set category = "Object" @@ -904,7 +923,8 @@ var/global/list/obj/item/device/pda/PDAs = list() user.show_message("\blue \t Damage Specifics: [C.getOxyLoss() > 50 ? "\red" : "\blue"][C.getOxyLoss()]-[C.getToxLoss() > 50 ? "\red" : "\blue"][C.getToxLoss()]-[C.getFireLoss() > 50 ? "\red" : "\blue"][C.getFireLoss()]-[C.getBruteLoss() > 50 ? "\red" : "\blue"][C.getBruteLoss()]", 1) user.show_message("\blue \t Key: Suffocation/Toxin/Burns/Brute", 1) user.show_message("\blue \t Body Temperature: [C.bodytemperature-T0C]°C ([C.bodytemperature*1.8-459.67]°F)", 1) - + if(!isnull(C.tod) && (C.stat == 2 || (C.reagents && C.reagents.has_reagent("zombiepowder")) || (C.changeling && C.changeling.changeling_fakedeath))) + user.show_message("\blue \t Time of Death: [C.tod]") if(istype(C, /mob/living/carbon/human)) var/mob/living/carbon/human/H = C var/list/damaged = H.get_damaged_organs(1,1) @@ -990,6 +1010,7 @@ var/global/list/obj/item/device/pda/PDAs = list() note = A:info user << "\blue Paper scanned." //concept of scanning paper copyright brainoblivion 2009 + /obj/item/device/pda/proc/explode() //This needs tuning. var/turf/T = get_turf(src.loc) @@ -1006,6 +1027,9 @@ var/global/list/obj/item/device/pda/PDAs = list() del(src) return +/obj/item/device/pda/ai/explode() + return // No explosions for the AI pda! + /obj/item/device/pda/Del() PDAs -= src if (src.id) @@ -1033,7 +1057,7 @@ var/global/list/obj/item/device/pda/PDAs = list() /mob/living/silicon/ai/verb/cmd_send_pdamesg() set category = "AI Commands" - set name = "Send PDA Message" + set name = "PDA - Send Message" var/list/names = list() var/list/plist = list() var/list/namecounts = list() @@ -1042,6 +1066,10 @@ var/global/list/obj/item/device/pda/PDAs = list() usr << "You can't send PDA messages because you are dead!" return + if(src.aiPDA.toff) + usr << "Turn on your receiver in order to send messages." + return + for (var/obj/item/device/pda/P in PDAs) if (!P.owner) continue @@ -1049,6 +1077,8 @@ var/global/list/obj/item/device/pda/PDAs = list() continue else if (P.toff) continue + else if (P == src.aiPDA) + continue var/name = P.owner if (name in names) @@ -1060,44 +1090,52 @@ var/global/list/obj/item/device/pda/PDAs = list() plist[text("[name]")] = P - var/c = input(usr, "Please select a PDA") as null|anything in plist + var/c = input(usr, "Please select a PDA") as null|anything in sortList(plist) if (!c) return var/selected = plist[c] - ai_send_pdamesg(selected) + src.aiPDA.create_message(src, selected) -/mob/living/silicon/ai/proc/ai_send_pdamesg(obj/selected as obj) - var/t = input(usr, "Please enter message", src.name, null) as text - t = copytext(sanitize(t), 1, MAX_MESSAGE_LEN) - if (!t) + +/mob/living/silicon/ai/verb/cmd_toggle_pda_receiver() + set category = "AI Commands" + set name = "PDA - Toggle Sender/Receiver" + if(usr.stat == 2) + usr << "You can't do that because you are dead!" return - - if (selected:toff) - return - var/obj/machinery/message_server/useMS = null - if(!isnull(message_servers)) - for (var/obj/machinery/message_server/MS in message_servers) - //PDAs are now dependant on the Message Server. - if(MS.active) - useMS = MS - break - if(!isnull(useMS)) // only send the message if it's stable - useMS.send_pda_message("[selected:owner]","[usr.name]","[t]") - - usr.show_message("PDA message to [selected:owner]: [t]") - selected:tnote += "← From (AI) [usr.name]:
    [t]
    " - - if (!selected:silent) - playsound(selected.loc, 'twobeep.ogg', 50, 1) - for (var/mob/O in hearers(3, selected.loc)) - O.show_message(text("\icon[selected] *[selected:ttone]*")) - - selected.overlays = null - selected.overlays += image('pda.dmi', "pda-r") + if(!isnull(aiPDA)) + aiPDA.toff = !aiPDA.toff + usr << "PDA sender/receiver toggled [(aiPDA.toff ? "Off" : "On")]!" else - usr << "ERROR: Server isn't responding." + usr << "You do not have a PDA. You should make an issue report about this." + +/mob/living/silicon/ai/verb/cmd_toggle_pda_silent() + set category = "AI Commands" + set name = "PDA - Toggle Ringer" + if(usr.stat == 2) + usr << "You can't do that because you are dead!" + return + if(!isnull(aiPDA)) + aiPDA.silent = !aiPDA.silent + usr << "PDA ringer toggled [(aiPDA.silent ? "Off" : "On")]!" + else + usr << "You do not have a PDA. You should make an issue report about this." + +/mob/living/silicon/ai/verb/cmd_show_message_log() + set category = "AI Commands" + set name = "PDA - Show Message Log" + if(usr.stat == 2) + usr << "You can't do that because you are dead!" + return + if(!isnull(aiPDA)) + var/HTML = "AI PDA Message Log[aiPDA.tnote]" + usr << browse(HTML, "window=log;size=400x444;border=1;can_resize=1;can_close=1;can_minimize=0") + else + usr << "You do not have a PDA. You should make an issue report about this." + + //Some spare PDAs in a box diff --git a/code/game/objects/devices/PDA/cart.dm b/code/game/objects/devices/PDA/cart.dm index 2e188ff6693..643231bb193 100644 --- a/code/game/objects/devices/PDA/cart.dm +++ b/code/game/objects/devices/PDA/cart.dm @@ -261,7 +261,7 @@ Code: menu = "

    Crew Manifest

    " menu += "Entries cannot be modified from this terminal.

    " - for (var/datum/data/record/t in data_core.general) + for (var/datum/data/record/t in sortRecord(data_core.general)) menu += "[t.fields["name"]] - [t.fields["rank"]]
    " menu += "
    " @@ -335,7 +335,7 @@ Code: if (44) //medical records //This thing only displays a single screen so it's hard to really get the sub-menu stuff working. menu = "

    Medical Record List

    " - for (var/datum/data/record/R in data_core.general) + for (var/datum/data/record/R in sortRecord(data_core.general)) menu += "[R.fields["id"]]: [R.fields["name"]]
    " menu += "
    " if(441) @@ -378,7 +378,7 @@ Code: if (45) //security records menu = "

    Security Record List

    " - for (var/datum/data/record/R in data_core.general) + for (var/datum/data/record/R in sortRecord(data_core.general)) menu += "
    [R.fields["id"]]: [R.fields["name"]]
    " menu += "
    " diff --git a/code/game/objects/devices/scanners.dm b/code/game/objects/devices/scanners.dm index 6673546f2bd..c57e92fb3e8 100644 --- a/code/game/objects/devices/scanners.dm +++ b/code/game/objects/devices/scanners.dm @@ -101,7 +101,9 @@ MASS SPECTROMETER 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]°C ([M.bodytemperature*1.8-459.67]°F)", 1) - if(mode == 1 && istype(M, /mob/living/carbon/human)) + if(!isnull(M.tod) && (M.stat == 2 || (M.reagents && M.reagents.has_reagent("zombiepowder")) || (M.changeling && M.changeling.changeling_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) diff --git a/code/modules/chemical/Chemistry-Reagents.dm b/code/modules/chemical/Chemistry-Reagents.dm index 113e9fdf398..86a42679ea7 100644 --- a/code/modules/chemical/Chemistry-Reagents.dm +++ b/code/modules/chemical/Chemistry-Reagents.dm @@ -1481,6 +1481,7 @@ datum M.adjustToxLoss(0.5) M.Weaken(10) M.silent = max(M.silent, 10) + M.tod = worldtime2text() ..() return diff --git a/code/modules/mob/dead/observer/observer.dm b/code/modules/mob/dead/observer/observer.dm index 8325b6c7509..ccf6540413f 100644 --- a/code/modules/mob/dead/observer/observer.dm +++ b/code/modules/mob/dead/observer/observer.dm @@ -181,7 +181,7 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp var/target = null //Chosen target. dest += getmobs() //Fill list, prompt user with list - target = input("Please, select a player!", "Jump to Mob", null, null) as null|anything in dest + target = input("Please, select a player!", "Jump to Mob", null, null) as null|anything in sortList(dest) if (!target)//Make sure we actually have a target return diff --git a/code/modules/mob/living/carbon/alien/humanoid/death.dm b/code/modules/mob/living/carbon/alien/humanoid/death.dm index 01eb6e2f257..3a48378c4c1 100644 --- a/code/modules/mob/living/carbon/alien/humanoid/death.dm +++ b/code/modules/mob/living/carbon/alien/humanoid/death.dm @@ -27,7 +27,7 @@ if(src.key && src.stat == 2) src.verbs += /mob/proc/ghost - var/tod = time2text(world.realtime,"hh:mm:ss") //weasellos time of death patch + tod = worldtime2text() //weasellos time of death patch if (mind) mind.store_memory("Time of death: [tod]", 0) else src << "We seem to have misplaced your mind datum, so we can't add this to your memory, but you died at [tod]" diff --git a/code/modules/mob/living/carbon/alien/larva/death.dm b/code/modules/mob/living/carbon/alien/larva/death.dm index 86d32617808..8e2fe185497 100644 --- a/code/modules/mob/living/carbon/alien/larva/death.dm +++ b/code/modules/mob/living/carbon/alien/larva/death.dm @@ -26,7 +26,7 @@ src.verbs += /mob/proc/ghost if(mind) // Skie - Added check that there's someone controlling the alien - var/tod = time2text(world.realtime,"hh:mm:ss") //weasellos time of death patch + tod = worldtime2text() //weasellos time of death patch mind.store_memory("Time of death: [tod]", 0) return ..(gibbed) diff --git a/code/modules/mob/living/carbon/brain/death.dm b/code/modules/mob/living/carbon/brain/death.dm index 021ef285d97..7564ad46272 100644 --- a/code/modules/mob/living/carbon/brain/death.dm +++ b/code/modules/mob/living/carbon/brain/death.dm @@ -14,7 +14,7 @@ see_in_dark = 8 see_invisible = 2 - var/tod = time2text(world.realtime,"hh:mm:ss") //weasellos time of death patch + tod = worldtime2text() //weasellos time of death patch store_memory("Time of death: [tod]", 0) if (key) diff --git a/code/modules/mob/living/carbon/human/death.dm b/code/modules/mob/living/carbon/human/death.dm index 0a42cb9e11f..945266c4c38 100644 --- a/code/modules/mob/living/carbon/human/death.dm +++ b/code/modules/mob/living/carbon/human/death.dm @@ -83,7 +83,7 @@ if(client && src.stat == 2) verbs += /mob/proc/ghost - var/tod = time2text(world.realtime,"hh:mm:ss") //weasellos time of death patch + tod = worldtime2text() //weasellos time of death patch if(mind) mind.store_memory("Time of death: [tod]", 0) sql_report_death(src) diff --git a/code/modules/mob/living/silicon/ai/ai.dm b/code/modules/mob/living/silicon/ai/ai.dm index 1ee631741d0..37471dba251 100644 --- a/code/modules/mob/living/silicon/ai/ai.dm +++ b/code/modules/mob/living/silicon/ai/ai.dm @@ -27,6 +27,11 @@ verbs += /mob/living/silicon/ai/proc/show_laws_verb + aiPDA = new/obj/item/device/pda/ai(src) + aiPDA.owner = name + aiPDA.ownjob = "AI" + aiPDA.name = name + " (" + aiPDA.ownjob + ")" + if (istype(loc, /turf)) verbs.Add(/mob/living/silicon/ai/proc/ai_call_shuttle,/mob/living/silicon/ai/proc/ai_camera_track, \ /mob/living/silicon/ai/proc/ai_camera_list, /mob/living/silicon/ai/proc/ai_network_change, \ @@ -147,12 +152,14 @@ /mob/living/silicon/ai/proc/ai_roster() set category = "AI Commands" set name = "Show Crew Manifest" - var/dat = "Crew RosterCrew Roster:

    " + var/list/L = list() for (var/datum/data/record/t in data_core.general) - dat += "[t.fields["name"]] - [t.fields["rank"]]
    " - + var/R = t.fields["name"] + " - " + t.fields["rank"] + L += R + for(var/R in sortList(L)) + dat += "[R]
    " dat += "" src << browse(dat, "window=airoster") @@ -454,6 +461,8 @@ cameralist[C.network] = C.network network = input(usr, "Which network would you like to view?") as null|anything in cameralist + if(isnull(network)) + network = initial(network) // If nothing is selected, default to SS13 (or the initial network) src << "\blue Switched to [network] camera network." //End of code by Mord_Sith diff --git a/code/modules/mob/living/silicon/ai/death.dm b/code/modules/mob/living/silicon/ai/death.dm index 79c4a7783c4..385ebfe1b6d 100644 --- a/code/modules/mob/living/silicon/ai/death.dm +++ b/code/modules/mob/living/silicon/ai/death.dm @@ -47,7 +47,7 @@ if (istype(loc, /obj/item/device/aicard)) loc.icon_state = "aicard-404" - var/tod = time2text(world.realtime,"hh:mm:ss") //weasellos time of death patch + tod = worldtime2text() //weasellos time of death patch if(mind) mind.store_memory("Time of death: [tod]", 0) if (key) diff --git a/code/modules/mob/living/silicon/ai/life.dm b/code/modules/mob/living/silicon/ai/life.dm index 8096b9681f3..37b0513ba5d 100644 --- a/code/modules/mob/living/silicon/ai/life.dm +++ b/code/modules/mob/living/silicon/ai/life.dm @@ -14,6 +14,10 @@ src.update_mind() + if(aiPDA && aiPDA.name != name) + aiPDA.owner = name + aiPDA.name = name + " (" + aiPDA.ownjob + ")" + if (src.malfhack) if (src.malfhack.aidisabled) src << "\red ERROR: APC access disabled, hack attempt canceled." diff --git a/code/modules/mob/living/silicon/pai/software.dm b/code/modules/mob/living/silicon/pai/software.dm index ab035c15923..641a4d84b58 100644 --- a/code/modules/mob/living/silicon/pai/software.dm +++ b/code/modules/mob/living/silicon/pai/software.dm @@ -238,7 +238,6 @@ if(!AnsweringMS) return alert("ERROR: No response from server!") - tnote += "→ To [P]:
    [t]
    " P.tnote += "← From
    [src]:
    [t]
    " @@ -443,8 +442,13 @@ /mob/living/silicon/pai/proc/softwareManifest() var/dat = "" dat += "

    Crew Manifest



    " - for (var/datum/data/record/t in data_core.general) - dat += "[t.fields["name"]] - [t.fields["rank"]]
    " + var/list/L = list() + for (var/datum/data/record/t in sortRecord(data_core.general)) + var/R = t.fields["name"] + " - " + t.fields["rank"] + L += R + for(var/R in sortList(L)) + dat += "[R]
    " + dat += "" return dat // Medical Records @@ -452,7 +456,7 @@ var/dat = "" if(src.subscreen == 0) dat += "

    Medical Records


    " - for(var/datum/data/record/R in data_core.general) + for(var/datum/data/record/R in sortRecord(data_core.general)) dat += text("[]: []
    ", src, R, R.fields["id"], R.fields["name"]) //dat += text("
    Back", src) if(src.subscreen == 1) @@ -474,7 +478,7 @@ var/dat = "" if(src.subscreen == 0) dat += "

    Security Records


    " - for(var/datum/data/record/R in data_core.general) + for(var/datum/data/record/R in sortRecord(data_core.general)) dat += text("[]: []
    ", src, R, R.fields["id"], R.fields["name"]) if(src.subscreen == 1) dat += "

    Security Record

    " diff --git a/code/modules/mob/living/silicon/robot/death.dm b/code/modules/mob/living/silicon/robot/death.dm index fefedcfe593..397a403a2b8 100644 --- a/code/modules/mob/living/silicon/robot/death.dm +++ b/code/modules/mob/living/silicon/robot/death.dm @@ -64,7 +64,7 @@ src.see_invisible = 2 src.updateicon() - var/tod = time2text(world.realtime,"hh:mm:ss") //weasellos time of death patch + tod = worldtime2text() //weasellos time of death patch store_memory("Time of death: [tod]", 0) sql_report_cyborg_death(src) diff --git a/icons/obj/ammo.dmi b/icons/obj/ammo.dmi index 1c23b6c25bcd6f96dad88401514892c9d88fadf7..ea9bd39b416805a7ee770720503a0db1342466eb 100644 GIT binary patch literal 9339 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 Ipthm^13iGuw*UYD
  • NameIDRankFingerprintsNameIDRankFingerprints Criminal Status