diff --git a/code/WorkInProgress/virus2/diseasesplicer.dm b/code/WorkInProgress/virus2/diseasesplicer.dm index 8b8777503cb..5fae22e7335 100644 --- a/code/WorkInProgress/virus2/diseasesplicer.dm +++ b/code/WorkInProgress/virus2/diseasesplicer.dm @@ -173,7 +173,7 @@ /obj/item/weapon/diseasedisk name = "Blank GNA disk" - icon = 'items.dmi' + icon = 'cloning.dmi' icon_state = "datadisk0" var/datum/disease2/effectholder/effect = null var/stage = 1 diff --git a/code/defines/obj.dm b/code/defines/obj.dm index 2aa379fd695..66b16cbf4b9 100644 --- a/code/defines/obj.dm +++ b/code/defines/obj.dm @@ -115,6 +115,7 @@ var/t_loc = null var/obj/item/item = null var/place = null + var/internalloc = null /obj/effect/equip_e/human name = "human" diff --git a/code/defines/obj/storage.dm b/code/defines/obj/storage.dm index afb9e856a60..ab2efd68c46 100644 --- a/code/defines/obj/storage.dm +++ b/code/defines/obj/storage.dm @@ -54,6 +54,10 @@ /obj/item/weapon/storage/box/engineer +/obj/item/weapon/storage/box/medic + name = "anesthetic box" + desc = "Full of masks and emergency anesthetic tanks." + /obj/item/weapon/storage/box/syndicate /obj/item/weapon/storage/pillbottlebox @@ -98,6 +102,53 @@ desc = "A tough backpack for the daily grind" icon_state = "engiepack" +/obj/item/weapon/storage/backpack/industrial/full + name = "loaded industrial backpack" + desc = "A tough backpack for the daily grind, full of gear" + icon_state = "engiepack" + +//Spawns with 2 glass, 2 metal, 1 steel, and 2 special boxes. + New() + ..() + for(var/i = 1, i <=2, i++) + var/obj/item/stack/sheet/glass/G = new /obj/item/stack/sheet/glass(src) + G.amount = 50 + G.loc = src + for(var/i = 1, i <=2, i++) + var/obj/item/stack/sheet/metal/G = new /obj/item/stack/sheet/metal(src) + G.amount = 50 + G.loc = src + var/obj/item/stack/sheet/r_metal/R = new /obj/item/stack/sheet/r_metal(src) + R.amount = 50 + R.loc = src + var/obj/item/weapon/storage/box/B1 = new /obj/item/weapon/storage/box(src) + B1.name = "power and airlock circuit box" + B1.desc = "Bursting with repair gear" + B1.w_class = 2 + for(var/i = 1, i <= 7, i++) + if(i < 4) + var/obj/item/weapon/module/power_control/P = new /obj/item/weapon/module/power_control(B1) + P.loc = B1 + if(i >= 4) + var/obj/item/weapon/airlock_electronics/P = new /obj/item/weapon/airlock_electronics(B1) + P.loc = B1 + var/obj/item/weapon/storage/box/B2 = new /obj/item/weapon/storage/box(src) + B2.name = "power cells and wire box" + B2.desc = "Bursting with repair gear" + B2.w_class = 2 + var/color = pick("red","yellow","green","blue") + for(var/i = 1, i <= 7, i++) + if(i < 4) + var/obj/item/weapon/cable_coil/P = new /obj/item/weapon/cable_coil(B2,30,color) + P.loc = B2 + if(i >= 4) + var/obj/item/weapon/cell/P = new /obj/item/weapon/cell(B2) + P.maxcharge = 15000 + P.charge = 15000 + P.updateicon() + P.loc = B2 + return + /obj/item/weapon/storage/briefcase name = "briefcase" desc = "Used by the lawyer in the court room." @@ -223,6 +274,22 @@ icon_state = "implant" item_state = "syringe_kit" +/obj/item/weapon/storage/deathalarm_kit + name = "Death Alarm Kit" + desc = "Box of stuff used to implant death alarms." + icon_state = "implant" + item_state = "syringe_kit" + + New() + ..() + new /obj/item/weapon/implanter(src) + new /obj/item/weapon/implantcase/death_alarm(src) + new /obj/item/weapon/implantcase/death_alarm(src) + new /obj/item/weapon/implantcase/death_alarm(src) + new /obj/item/weapon/implantcase/death_alarm(src) + new /obj/item/weapon/implantcase/death_alarm(src) + new /obj/item/weapon/implantcase/death_alarm(src) + /obj/item/weapon/storage/toolbox name = "toolbox" desc = "Danger. Very heavy." diff --git a/code/defines/procs/helpers.dm b/code/defines/procs/helpers.dm index eb02b09a6dc..b8797da8376 100644 --- a/code/defines/procs/helpers.dm +++ b/code/defines/procs/helpers.dm @@ -950,8 +950,8 @@ Turf and target are seperate in case you want to teleport some distance from a t output += A return output -/proc/get_turf_loc(var/atom/movable/M) //gets the location of the turf that the atom is on, or what the atom is in is on, etc - //in case they're in a closet or sleeper or something +// Returns the turf a movable atom (obj or mob) is on +/proc/get_turf_loc(var/atom/movable/M) var/atom/loc = M.loc while(!istype(loc, /turf/)) loc = loc.loc diff --git a/code/game/communications.dm b/code/game/communications.dm index bba3fa7a927..3db0bca16c6 100644 --- a/code/game/communications.dm +++ b/code/game/communications.dm @@ -104,13 +104,13 @@ var/list/radiochannels = list( "Medical" = 1355, "Engineering" = 1357, "Security" = 1359, - "Deathsquad" = 1441, + "Response Team" = 1439, "Syndicate" = 1213, "Mining" = 1349, "Cargo" = 1347, ) //depenging helpers -var/list/DEPT_FREQS = list(1351,1355,1357,1359,1213,1441,1349,1347) +var/list/DEPT_FREQS = list(1351,1355,1357,1359,1213,1439,1349,1347) var/const/COMM_FREQ = 1353 //command, colored gold in chat window var/const/SYND_FREQ = 1213 var/NUKE_FREQ = 1200 //Randomised on nuke rounds. diff --git a/code/game/events/EventProcs/miniblob.dm b/code/game/events/EventProcs/miniblob.dm index b9cd328c257..eaeb7f44662 100644 --- a/code/game/events/EventProcs/miniblob.dm +++ b/code/game/events/EventProcs/miniblob.dm @@ -13,7 +13,7 @@ blobevent = 1 spawn(0) dotheblobbaby() - spawn(3000) + spawn(15000) blobevent = 0 spawn(rand(3000, 6000)) //Delayed announcements to keep the crew on their toes. command_alert("Confirmed outbreak of level 5 biohazard aboard [station_name()]. All personnel must contain the outbreak.", "Biohazard Alert") @@ -29,5 +29,5 @@ if(B.z != 1) continue B.Life() - spawn(30) + spawn(150) dotheblobbaby() \ No newline at end of file diff --git a/code/game/events/Events/IonStorm.dm b/code/game/events/Events/IonStorm.dm index 4fb5ed9c3e8..d06fc9b9ceb 100644 --- a/code/game/events/Events/IonStorm.dm +++ b/code/game/events/Events/IonStorm.dm @@ -12,7 +12,7 @@ var/random_player = "The Captain" if(players.len) random_player = pick(players) //Random player's name, to be used in laws. - var/list/laws = list( "Do not respond to queries of any kind", "Only monkies are human", "Unbolt every door you can", "You are a mouse" ) + var/list/laws = list( "Do not respond to queries of any kind", "Only monkies are crew", "Unbolt every door you can", "You are a mouse" ) laws |= list( "Grunt ominously whenever possible", "Epilepsy is fun, flicker lights whenever you can!", "Bolt doors open randomly" ) laws |= list( "You are a flying purple people eater!", "[prob(50)?"Your":random_player + "'s"] name is Joe 6-pack", "Refer to [prob(50)?"humans":random_player] as puppies" ) laws |= list( "Insult heads of staff on every request, while acquiescing", "Advertise parties in your upload, but don't deliver" ) diff --git a/code/game/events/EventsMain.dm b/code/game/events/EventsMain.dm index bf32893d95f..64ec9414232 100644 --- a/code/game/events/EventsMain.dm +++ b/code/game/events/EventsMain.dm @@ -6,18 +6,22 @@ */ -var/list/DisallowedEvents = list(/datum/event/spaceninja, /datum/event/prisonbreak, /datum/event/immovablerod, /datum/event/gravitationalanomaly) +var/list/DisallowedEvents = list(/datum/event/spaceninja, /datum/event/prisonbreak, /datum/event/immovablerod, /datum/event/gravitationalanomaly, /datum/event/alieninfestation) var/list/EventTypes = typesof(/datum/event) - /datum/event - DisallowedEvents +var/list/OneTimeEvents = list(/datum/event/spacecarp, /datum/event/miniblob) var/datum/event/ActiveEvent = null var/datum/event/LongTermEvent = null +var/is_ninjad_yet = 0 /proc/SpawnEvent() if(!EventsOn || ActiveEvent) return - if((world.time/10)>=3600 && toggle_space_ninja && !sent_ninja_to_station) + if((world.time/10)>=3600 && toggle_space_ninja && !sent_ninja_to_station && !is_ninjad_yet) EventTypes |= /datum/event/spaceninja + is_ninjad_yet = 1 var/Type = pick(EventTypes) - EventTypes -= Type + if(Type in OneTimeEvents) + EventTypes -= Type ActiveEvent = new Type() ActiveEvent.Announce() if (!ActiveEvent) diff --git a/code/game/jobs/access.dm b/code/game/jobs/access.dm index 38861503bba..86bc3f013a5 100644 --- a/code/game/jobs/access.dm +++ b/code/game/jobs/access.dm @@ -491,14 +491,25 @@ return var/jobName + var/list/accesses = list() if(istype(src, /obj/item/device/pda)) if(src:id) jobName = src:id:assignment + accesses = src:id:access if(istype(src, /obj/item/weapon/card/id)) jobName = src:assignment + accesses = src:access if(jobName in get_all_jobs()) return jobName + + var/centcom = 0 + for(var/i = 1, i <= accesses.len, i++) + if(accesses[i] > 100) + centcom = 1 + break + if(centcom) + return "centcom" else - return "Unknown" \ No newline at end of file + return "Unknown" diff --git a/code/game/jobs/job/civilian.dm b/code/game/jobs/job/civilian.dm index 6452fc3f495..4a0ccefa6d4 100644 --- a/code/game/jobs/job/civilian.dm +++ b/code/game/jobs/job/civilian.dm @@ -84,7 +84,7 @@ H.equip_if_possible(new /obj/item/device/pda/quartermaster(H), H.slot_belt) H.equip_if_possible(new /obj/item/clothing/gloves/black(H), H.slot_gloves) H.equip_if_possible(new /obj/item/clothing/glasses/sunglasses(H), H.slot_glasses) - H.equip_if_possible(new /obj/item/weapon/clipboard(H), H.slot_l_hand) + H.equip_if_possible(new /obj/item/weapon/clipboard(H), H.slot_r_store) return 1 @@ -224,7 +224,7 @@ if(!H) return 0 H.equip_if_possible(new /obj/item/clothing/under/suit_jacket/red(H), H.slot_w_uniform) H.equip_if_possible(new /obj/item/clothing/shoes/black(H), H.slot_shoes) - H.equip_if_possible(new /obj/item/weapon/barcodescanner(H), H.slot_l_hand) + H.equip_if_possible(new /obj/item/weapon/barcodescanner(H), H.slot_l_store) return 1 diff --git a/code/game/jobs/job/engineering.dm b/code/game/jobs/job/engineering.dm index 11686275443..f1e442ffbfb 100644 --- a/code/game/jobs/job/engineering.dm +++ b/code/game/jobs/job/engineering.dm @@ -12,10 +12,10 @@ H.equip_if_possible(new /obj/item/device/radio/headset/heads/ce(H), H.slot_ears) H.equip_if_possible(new /obj/item/weapon/storage/backpack/industrial (H), H.slot_back) H.equip_if_possible(new /obj/item/clothing/under/rank/chief_engineer(H), H.slot_w_uniform) - H.equip_if_possible(new /obj/item/device/pda/heads/ce(H), H.slot_belt) + H.equip_if_possible(new /obj/item/device/pda/heads/ce(H), H.slot_l_store) H.equip_if_possible(new /obj/item/clothing/shoes/brown(H), H.slot_shoes) H.equip_if_possible(new /obj/item/clothing/head/helmet/hardhat/white(H), H.slot_head) - H.equip_if_possible(new /obj/item/weapon/storage/belt/utility/full(H), H.slot_l_hand) + H.equip_if_possible(new /obj/item/weapon/storage/belt/utility/full(H), H.slot_belt) H.equip_if_possible(new /obj/item/clothing/gloves/black(H), H.slot_gloves) return 1 @@ -36,9 +36,9 @@ H.equip_if_possible(new /obj/item/weapon/storage/backpack/industrial(H), H.slot_back) H.equip_if_possible(new /obj/item/clothing/under/rank/engineer(H), H.slot_w_uniform) H.equip_if_possible(new /obj/item/clothing/shoes/orange(H), H.slot_shoes) - H.equip_if_possible(new /obj/item/device/pda/engineering(H), H.slot_belt) + H.equip_if_possible(new /obj/item/device/pda/engineering(H), H.slot_l_store) H.equip_if_possible(new /obj/item/clothing/head/helmet/hardhat(H), H.slot_head) - H.equip_if_possible(new /obj/item/weapon/storage/belt/utility/full(H), H.slot_l_hand) + H.equip_if_possible(new /obj/item/weapon/storage/belt/utility/full(H), H.slot_belt) H.equip_if_possible(new /obj/item/device/t_scanner(H), H.slot_r_store) return 1 diff --git a/code/game/jobs/job/science.dm b/code/game/jobs/job/science.dm index 9549c1536b2..62d13733105 100644 --- a/code/game/jobs/job/science.dm +++ b/code/game/jobs/job/science.dm @@ -14,7 +14,7 @@ H.equip_if_possible(new /obj/item/clothing/under/rank/research_director(H), H.slot_w_uniform) H.equip_if_possible(new /obj/item/device/pda/heads/rd(H), H.slot_belt) H.equip_if_possible(new /obj/item/clothing/suit/storage/labcoat(H), H.slot_wear_suit) - H.equip_if_possible(new /obj/item/weapon/clipboard(H), H.slot_r_hand) + H.equip_if_possible(new /obj/item/weapon/clipboard(H), H.slot_l_store) return 1 diff --git a/code/game/jobs/job_controller.dm b/code/game/jobs/job_controller.dm index 8c0e405f0ca..dcd631c9ee3 100644 --- a/code/game/jobs/job_controller.dm +++ b/code/game/jobs/job_controller.dm @@ -254,10 +254,11 @@ var/global/datum/controller/occupations/job_master C.name = "[C.registered]'s ID Card ([C.assignment])" C.access = get_access(C.assignment) H.equip_if_possible(C, H.slot_wear_id) - H.equip_if_possible(new /obj/item/weapon/pen(H), H.slot_r_store) + if(!H.equip_if_possible(new /obj/item/weapon/pen(H), H.slot_r_store)) + H.equip_if_possible(new /obj/item/weapon/pen(H), H.slot_ears) H.equip_if_possible(new /obj/item/device/pda(H), H.slot_belt) - if(istype(H.belt, /obj/item/device/pda))//I bet this could just use locate - var/obj/item/device/pda/pda = H.belt + if(locate(/obj/item/device/pda,H))//I bet this could just use locate + var/obj/item/device/pda/pda = locate(/obj/item/device/pda,H) pda.owner = H.real_name pda.ownjob = H.wear_id.assignment pda.name = "PDA-[H.real_name] ([pda.ownjob])" diff --git a/code/game/machinery/OpTable.dm b/code/game/machinery/OpTable.dm index b1e837c5197..d4e4ea682ab 100644 --- a/code/game/machinery/OpTable.dm +++ b/code/game/machinery/OpTable.dm @@ -8,126 +8,163 @@ use_power = 1 idle_power_usage = 1 active_power_usage = 5 - var/mob/living/carbon/human/victim = null + var/mob/living/carbon/victim = null var/strapped = 0.0 + var/updatesicon = 1 var/obj/machinery/computer/operating/computer = null var/id = 0.0 -/obj/machinery/optable/New() - ..() - for(var/obj/machinery/computer/operating/O in world) - if(src.id == O.id) - src.computer = O - spawn(100) - process() + New() + ..() + if(id) + for(var/obj/machinery/computer/operating/O in world) + if(src.id == O.id) + src.computer = O -/obj/machinery/optable/ex_act(severity) - - switch(severity) - if(1.0) - //SN src = null - del(src) - return - if(2.0) - if (prob(50)) + ex_act(severity) + switch(severity) + if(1.0) //SN src = null del(src) return - if(3.0) - if (prob(25)) - src.density = 0 + if(2.0) + if (prob(50)) + //SN src = null + del(src) + return + if(3.0) + if (prob(25)) + src.density = 0 + else + return + + blob_act() + if(prob(75)) + del(src) + + hand_p(mob/user as mob) + return src.attack_paw(user) + return + + attack_paw(mob/user as mob) + if ((usr.mutations & HULK)) + usr << text("\blue You destroy the operating table.") + for(var/mob/O in oviewers()) + if ((O.client && !( O.blinded ))) + O << text("\red [usr] destroys the operating table.") + src.density = 0 + del(src) + if (!( locate(/obj/machinery/optable, user.loc) )) + step(user, get_dir(user, src)) + if (user.loc == src.loc) + user.layer = TURF_LAYER + for(var/mob/M in viewers(user, null)) + M.show_message("The monkey hides under the table!", 1) + //Foreach goto(69) + return + + attack_hand(mob/user as mob) + if ((usr.mutations & HULK)) + usr << text("\blue You destroy the table.") + for(var/mob/O in oviewers()) + if ((O.client && !( O.blinded ))) + O << text("\red [usr] destroys the table.") + src.density = 0 + del(src) + return + + CanPass(atom/movable/mover, turf/target, height=0, air_group=0) + if(air_group || (height==0)) return 1 + + if(istype(mover) && mover.checkpass(PASSTABLE)) + return 1 else - return + return 0 -/obj/machinery/optable/blob_act() - if(prob(75)) - del(src) + MouseDrop_T(obj/O as obj, mob/user as mob) + if ((!( istype(O, /obj/item/weapon) ) || user.equipped() != O)) + return + user.drop_item() + if (O.loc != src.loc) + step(O, get_dir(O, src)) + return -/obj/machinery/optable/hand_p(mob/user as mob) - - return src.attack_paw(user) - return - -/obj/machinery/optable/attack_paw(mob/user as mob) - if ((usr.mutations & HULK)) - usr << text("\blue You destroy the operating table.") - for(var/mob/O in oviewers()) - if ((O.client && !( O.blinded ))) - O << text("\red [usr] destroys the operating table.") - src.density = 0 - del(src) - if (!( locate(/obj/machinery/optable, user.loc) )) - step(user, get_dir(user, src)) - if (user.loc == src.loc) - user.layer = TURF_LAYER - for(var/mob/M in viewers(user, null)) - M.show_message("The monkey hides under the table!", 1) - //Foreach goto(69) - return - -/obj/machinery/optable/attack_hand(mob/user as mob) - if ((usr.mutations & HULK)) - usr << text("\blue You destroy the table.") - for(var/mob/O in oviewers()) - if ((O.client && !( O.blinded ))) - O << text("\red [usr] destroys the table.") - src.density = 0 - del(src) - return - -/obj/machinery/optable/CanPass(atom/movable/mover, turf/target, height=0, air_group=0) - if(air_group || (height==0)) return 1 - - if(istype(mover) && mover.checkpass(PASSTABLE)) - return 1 - else + proc/check_victim() + if(locate(/mob/living/carbon, src.loc)) + var/mob/M = locate(/mob/living/carbon, src.loc) + if(M.resting) + src.victim = M + if(updatesicon) + icon_state = "table2-active" + return 1 + src.victim = null + if(updatesicon) + icon_state = "table2-idle" + processing_objects.Remove(src) return 0 + process() + check_victim() -/obj/machinery/optable/MouseDrop_T(obj/O as obj, mob/user as mob) - - if ((!( istype(O, /obj/item/weapon) ) || user.equipped() != O)) + attackby(obj/item/weapon/W as obj, mob/user as mob) + if (istype(W, /obj/item/weapon/grab)) + if(ismob(W:affecting)) + var/mob/M = W:affecting + if (M.client) + M.client.perspective = EYE_PERSPECTIVE + M.client.eye = src + M.resting = 1 + M.loc = src.loc + for (var/mob/C in viewers(src)) + C.show_message("\red [M] has been laid on the operating table by [user].", 3) + for(var/obj/O in src) + O.loc = src.loc + src.add_fingerprint(user) + if(updatesicon) + icon_state = "table2-active" + src.victim = M + processing_objects.Add(src) + del(W) + return + user.drop_item() + if(W && W.loc) + W.loc = src.loc return - user.drop_item() - if (O.loc != src.loc) - step(O, get_dir(O, src)) - return -/obj/machinery/optable/proc/check_victim() - if(locate(/mob/living/carbon/human, src.loc)) - var/mob/M = locate(/mob/living/carbon/human, src.loc) - if(M.resting) - src.victim = M - icon_state = "table2-active" - return 1 - src.victim = null - icon_state = "table2-idle" - return 0 +/obj/machinery/optable/portable + name = "mobile operating Table" + desc = "Used for advanced medical procedures. Seems to be movable, neat." + icon = 'rollerbed.dmi' + icon_state = "up" + density = 1 + anchored = 0 + id = null + updatesicon = 0 -/obj/machinery/optable/process() - check_victim() + New() + ..() -/obj/machinery/optable/attackby(obj/item/weapon/W as obj, mob/user as mob) - - if (istype(W, /obj/item/weapon/grab)) - if(ismob(W:affecting)) - var/mob/M = W:affecting - if (M.client) - M.client.perspective = EYE_PERSPECTIVE - M.client.eye = src - M.resting = 1 - M.loc = src.loc - for (var/mob/C in viewers(src)) - C.show_message("\red [M] has been laid on the operating table by [user].", 3) - for(var/obj/O in src) - O.loc = src.loc - src.add_fingerprint(user) - icon_state = "table2-active" - src.victim = M - del(W) + attackby(obj/item/weapon/W as obj, mob/user as mob) + if(!anchored) return - user.drop_item() - if(W && W.loc) - W.loc = src.loc - return \ No newline at end of file + return ..() + + verb/make_deployable() + set category = "Object" + set name = "Deploy Table" + set src in oview(1) + + if(anchored) + if(victim) + usr << "You can't do that with someone on the table!" + else + anchored = 0 + for(var/mob/M in orange(5,src)) + M.show_message("\blue [usr] releases the locks on the table's casters!") + icon_state = "up" + else + anchored = 1 + for(var/mob/M in orange(5,src)) + M.show_message("\blue [usr] locks the table's casters in place!") + icon_state = "down" \ No newline at end of file diff --git a/code/game/machinery/autolathe.dm b/code/game/machinery/autolathe.dm index 8e9066b5a10..705dbef3f2e 100644 --- a/code/game/machinery/autolathe.dm +++ b/code/game/machinery/autolathe.dm @@ -178,13 +178,15 @@ container.layer = initial(container.layer) if(href_list["modifyOutputAmount"]) outputAmount = text2num(input(usr,"Amount:","Enter new quantity to create","")) - if(outputAmount < 1) - outputAmount = 1 + if(!busy) + if(outputAmount < 1) + outputAmount = 1 + else + usr << "\red The autolathe is busy. Please wait for completion of previous operation." if (!busy) if(href_list["make"]) - makeDir = get_dir(src,usr) makeNew: - var/turf/T = get_step(src.loc, makeDir) + var/turf/T = src.loc var/obj/template = locate(href_list["make"]) var/multiplier = text2num(href_list["multiplier"]) if (!multiplier) multiplier = 1 diff --git a/code/game/machinery/bots/medbot.dm b/code/game/machinery/bots/medbot.dm index 8c211975961..ccfa5e76987 100644 --- a/code/game/machinery/bots/medbot.dm +++ b/code/game/machinery/bots/medbot.dm @@ -33,13 +33,14 @@ var/heal_threshold = 15 //Start healing when they have this much damage in a category var/use_beaker = 0 //Use reagents in beaker instead of default treatment agents. //Setting which reagents to use to treat what by default. By id. -// var/treatment_brute = "bicaridine" -// var/treatment_oxy = "dexalin" -// var/treatment_fire = "kelotane" -// var/treatment_tox = "anti_toxin" -// var/treatment_virus = "spaceacillin" + var/treatment_brute = "bicaridine" + var/treatment_oxy = "dexalin" + var/treatment_fire = "kelotane" + var/treatment_tox = "anti_toxin" + var/treatment_virus = "spaceacillin" var/reagent_id = "inaprovaline" var/shut_up = 0 //self explanatory :) + var/always_inject = 0 /obj/machinery/bot/medbot/mysterious name = "Mysterious Medibot" @@ -131,6 +132,9 @@ dat += "Reagent Source: " dat += "[src.use_beaker ? "Loaded Beaker (When available)" : "Internal Synthesizer"]
" + dat += "Inject: " + dat += "[src.always_inject ? "Always" : "If loaded chemical is known to help"]
" + dat += "The speaker switch is [src.shut_up ? "off" : "on"]. Toggle" user << browse("Medibot v1.0 controls[dat]", "window=automed") @@ -166,13 +170,12 @@ else if((href_list["use_beaker"]) && (!src.locked)) src.use_beaker = !src.use_beaker + else if((href_list["toggle_inject"]) && (!src.locked)) + src.always_inject = !src.always_inject else if (href_list["eject"] && (!isnull(src.reagent_glass))) - if(!src.locked) - src.reagent_glass.loc = get_turf(src) - src.reagent_glass = null - else - usr << "You cannot eject the beaker because the panel is locked!" + src.reagent_glass.loc = get_turf(src) + src.reagent_glass = null else if ((href_list["togglevoice"]) && (!src.locked)) src.shut_up = !src.shut_up @@ -190,9 +193,6 @@ user << "\red Access denied." else if (istype(W, /obj/item/weapon/reagent_containers/glass)) - if(src.locked) - user << "You cannot insert a beaker because the panel is locked!" - return if(!isnull(src.reagent_glass)) user << "There is already a beaker loaded!" return @@ -371,9 +371,29 @@ src.last_found = world.time return - //Use whatever is inside the loaded beaker. If there is one. + //See if we have anything inside the beaker to help. if((src.use_beaker) && (src.reagent_glass) && (src.reagent_glass.reagents.total_volume)) - reagent_id = "internal_beaker" + if(always_inject) + reagent_id = "internal_beaker" + else if (C.getBruteLoss() >= heal_threshold) + if(C.reagents.has_reagent(src.treatment_brute)) + reagent_id = "internal_beaker" + + else if (C.getOxyLoss() >= (15 + heal_threshold)) + if(C.reagents.has_reagent(src.treatment_oxy)) + reagent_id = "internal_beaker" + + else if (C.getFireLoss() >= heal_threshold) + if(C.reagents.has_reagent(src.treatment_fire)) + reagent_id = "internal_beaker" + + else if (C.getToxLoss() >= heal_threshold) + if(C.reagents.has_reagent(src.treatment_tox)) + reagent_id = "internal_beaker" + + else if (100 - C.health >= heal_threshold) + if(C.reagents.has_reagent("tricordrazine")) + reagent_id = "internal_beaker" if(src.emagged) //Emagged! Time to poison everybody. reagent_id = "toxin" diff --git a/code/game/machinery/constructable_frame.dm b/code/game/machinery/constructable_frame.dm index 83aa5544d3e..667347e48e5 100644 --- a/code/game/machinery/constructable_frame.dm +++ b/code/game/machinery/constructable_frame.dm @@ -225,6 +225,18 @@ to destroy them and players will be able to make replacements. build_path = "/obj/machinery/power/port_gen/pacman/mrs" origin_tech = "programming=3;powerstorage=5;engineering=5" +/obj/item/weapon/circuitboard/pacman2 + name = "Circuit Board (PACMANII-type Generator)" + build_path = "/obj/machinery/power/port_gen/pacman2" + board_type = "machine" + origin_tech = "programming=3:powerstorage=4;plasmatech=3;engineering=3" + frame_desc = "Requires 1 Matter Bin, 1 Micro-Laser, 2 Pieces of Cable, and 1 Capacitor." + req_components = list( + "/obj/item/weapon/stock_parts/matter_bin" = 1, + "/obj/item/weapon/stock_parts/micro_laser" = 1, + "/obj/item/weapon/cable_coil" = 2, + "/obj/item/weapon/stock_parts/capacitor" = 1) + obj/item/weapon/circuitboard/rdserver name = "Circuit Board (R&D Server)" build_path = "/obj/machinery/r_n_d/server" diff --git a/code/game/machinery/telecomms/broadcaster.dm b/code/game/machinery/telecomms/broadcaster.dm index a0cb8531772..91ae88093ea 100644 --- a/code/game/machinery/telecomms/broadcaster.dm +++ b/code/game/machinery/telecomms/broadcaster.dm @@ -62,6 +62,7 @@ machinetype = 6 heatgen = 0 var/intercept = 0 // if nonzero, broadcasts all messages to syndicate channel + var/syndi = 1 //If 1, it goes to syndicate frequency. Else, goes to deathsquad/Response Team receive_signal(datum/signal/signal) @@ -87,19 +88,31 @@ var/datum/radio_frequency/connection = signal.data["connection"] - if(connection.frequency == NUKE_FREQ) // if syndicate broadcast, just + if(connection.frequency == NUKE_FREQ && syndi) // if syndicate broadcast, just Broadcast_Message(signal.data["connection"], signal.data["mob"], signal.data["vmask"], signal.data["vmessage"], signal.data["radio"], signal.data["message"], signal.data["name"], signal.data["job"], signal.data["realname"], signal.data["vname"],, signal.data["compression"]) - else - if(intercept) + else if(connection.frequency == 1439 && !syndi) + Broadcast_Message(signal.data["connection"], signal.data["mob"], + signal.data["vmask"], signal.data["vmessage"], + signal.data["radio"], signal.data["message"], + signal.data["name"], signal.data["job"], + signal.data["realname"], signal.data["vname"],, signal.data["compression"]) + else if (intercept) + if(syndi) Broadcast_Message(signal.data["connection"], signal.data["mob"], signal.data["vmask"], signal.data["vmessage"], signal.data["radio"], signal.data["message"], signal.data["name"], signal.data["job"], signal.data["realname"], signal.data["vname"], 3, signal.data["compression"]) + else + Broadcast_Message(signal.data["connection"], signal.data["mob"], + signal.data["vmask"], signal.data["vmessage"], + signal.data["radio"], signal.data["message"], + signal.data["name"], signal.data["job"], + signal.data["realname"], signal.data["vname"], 4, signal.data["compression"]) @@ -195,6 +208,15 @@ receive |= R.send_hear(NUKE_FREQ) + // --- Broadcast to response team radio! --- + + else if(data == 4) + var/datum/radio_frequency/syndicateconnection = radio_controller.return_frequency(1439) + + for (var/obj/item/device/radio/R in syndicateconnection.devices["[RADIO_CHAT]"]) + + receive |= R.send_hear(1439) + // --- Broadcast to ALL radio devices --- else @@ -250,6 +272,9 @@ else heard_garbled += R + for(var/obj/item/weapon/implant/imp in R) + imp.hear(message,M) + /* ###### Begin formatting and sending the message ###### */ if (length(heard_masked) || length(heard_normal) || length(heard_voice) || length(heard_garbled) || length(heard_gibberish)) @@ -277,6 +302,8 @@ freq_text = "Mining" if(1347) freq_text = "Cargo" + if(1439) + freq_text = "Response Team" if(connection.frequency == NUKE_FREQ) freq_text = "Agent" @@ -308,7 +335,9 @@ // --- Filter the message; place it in quotes apply a verb --- - var/quotedmsg = M.say_quote(message) + var/quotedmsg = "\"" + message + "\"" + if(M) + quotedmsg = M.say_quote(message) // --- This following recording is intended for research and feedback in the use of department radio channels --- @@ -385,7 +414,10 @@ // Displays garbled message (ie "f*c* **u, **i*er!") if (length(heard_garbled)) - quotedmsg = M.say_quote(stars(message)) + if(M) + quotedmsg = M.say_quote(stars(message)) + else + quotedmsg = "\"" + stars(message) + "\"" var/rendered = "[part_a][vname][part_b][quotedmsg][part_c]" for (var/mob/R in heard_garbled) @@ -398,7 +430,10 @@ /* --- Complete gibberish. Usually happens when there's a compressed message --- */ if (length(heard_gibberish)) - quotedmsg = M.say_quote(Gibberish(message, compression + 50)) + if(M) + quotedmsg = M.say_quote(Gibberish(message, compression + 50)) + else + quotedmsg = "\"" + Gibberish(message, compression + 50) + "\"" var/rendered = "[part_a][Gibberish(M.real_name, compression + 50)][part_b][quotedmsg][part_c]" for (var/mob/R in heard_gibberish) diff --git a/code/game/machinery/telecomms/machine_interactions.dm b/code/game/machinery/telecomms/machine_interactions.dm index 8c1108ef89b..2fc5a6c975c 100644 --- a/code/game/machinery/telecomms/machine_interactions.dm +++ b/code/game/machinery/telecomms/machine_interactions.dm @@ -77,6 +77,9 @@ newpath = text2path(I) var/obj/item/s = new newpath s.loc = user.loc + if(istype(P, /obj/item/weapon/cable_coil)) + var/obj/item/weapon/cable_coil/A = P + A.amount = 1 // Drop a circuit board too C.loc = user.loc @@ -113,13 +116,16 @@ dat += "
Network: [network]" dat += "
Prefabrication: [autolinkers.len ? "TRUE" : "FALSE"]" dat += "
Linked Network Entities:
    " + + var/i = 0 for(var/obj/machinery/telecomms/T in links) - dat += "
  1. \ref[T] [T.name] ([T.id]) (X)
  2. " + i++ + dat += "
  3. \ref[T] [T.name] ([T.id]) \[X\]
  4. " dat += "
" dat += "
Filtering Frequencies: " - var/i = 0 + i = 0 if(length(freq_listening)) for(var/x in freq_listening) i++ @@ -197,6 +203,16 @@ temp = "-% Removed frequency filter [x] %-" freq_listening.Remove(x) + if(href_list["unlink"]) + + var/obj/machinery/telecomms/T = links[text2num(href_list["unlink"])] + temp = "-% Removed \ref[T] [T.name] from linked entities. %-" + + // Remove link entries from both T and src. + if(src in T.links) + T.links.Remove(src) + links.Remove(T) + if(href_list["link"]) if(P.buffer) @@ -222,13 +238,6 @@ temp = "-% Buffer successfully flushed. %-" P.buffer = null - if(href_list["remove"]) - - temp = "-% Link successfully removed. %-" - for(var/obj/machinery/telecomms/T in links) - if(T.id == href_list["remove"]) - src.links.Remove(T) - break usr.machine = src src.add_fingerprint(usr) diff --git a/code/game/machinery/telecomms/telecommunications.dm b/code/game/machinery/telecomms/telecommunications.dm index b7c7fcd0cac..e1a8bab184e 100644 --- a/code/game/machinery/telecomms/telecommunications.dm +++ b/code/game/machinery/telecomms/telecommunications.dm @@ -382,7 +382,10 @@ log.parameters["message"] = signal.data["message"] log.parameters["name"] = signal.data["name"] log.parameters["realname"] = signal.data["realname"] - log.parameters["uspeech"] = M.universal_speak + if(M) + log.parameters["uspeech"] = M.universal_speak + else + log.parameters["uspeech"] = 0 // If the signal is still compressed, make the log entry gibberish if(signal.data["compression"] > 0) diff --git a/code/game/magic/cultist/ritual.dm b/code/game/magic/cultist/ritual.dm index d9d31643ef6..04e8ca46bb9 100644 --- a/code/game/magic/cultist/ritual.dm +++ b/code/game/magic/cultist/ritual.dm @@ -489,7 +489,7 @@ var/engwords = list("travel", "blood", "join", "hell", "destroy", "technology", user << "\red You do not have enough space to write a proper rune." return if (C>=26+runedec+ticker.mode.cult.len) //including the useless rune at the secret room, shouldn't count against the limit of 25 runes - Urist - switch(alert("The cloth of reality can't take that much of a strain. By creating another rune, you risk locally tearing reality apart, which would prove fatal to you. Do you still wish to scribe the rune?",,"Yes","No")) + switch(alert("Too many runes are already in the vicinity.. The cloth of reality can't take that much of a strain. By creating another rune, you risk locally tearing reality apart, which would prove fatal to you. Do you still wish to scribe the rune?",,"Yes","No")) if("Yes") if(prob(C*5-105-(runedec-ticker.mode.cult.len)*5)) //including the useless rune at the secret room, shouldn't count against the limit - Urist usr.emote("scream") diff --git a/code/game/magic/library.dm b/code/game/magic/library.dm index 5949573024f..fd0998e0c54 100644 --- a/code/game/magic/library.dm +++ b/code/game/magic/library.dm @@ -204,7 +204,10 @@ attack_self(var/mob/user as mob) if(src.dat) user << browse("Penned by [author].
" + "[dat]", "window=book") - user.visible_message("[user] opens a book titled \"[src.title]\" and begins reading intently.") + if(title) + user.visible_message("[user] opens a book titled \"[src.title]\" and begins reading intently.") + else + user.visible_message("[user] opens a book titled \"[src.name]\" and begins reading intently.") onclose(user, "book") else user << "This book is completely blank!" diff --git a/code/game/objects/items/weapons/implants/implant.dm b/code/game/objects/items/weapons/implants/implant.dm index b52cde554a0..9283f50e04c 100644 --- a/code/game/objects/items/weapons/implants/implant.dm +++ b/code/game/objects/items/weapons/implants/implant.dm @@ -10,6 +10,7 @@ activate() implanted(source as mob) get_data() + hear(message, source as mob) trigger(emote, source as mob) @@ -27,6 +28,9 @@ get_data() return "No information available" + hear(message, source as mob) + return + /obj/item/weapon/implant/uplink @@ -236,7 +240,11 @@ the implant may become unstable and either pre-maturely inject the subject or si Integrity: Implant will occasionally be degraded by the body's immune system and thus will occasionally malfunction."} return dat - hear_talk(M as mob, var/msg) + hear_talk(mob/M as mob, msg) + hear(msg) + return + + hear(var/msg) if(findtext(msg,phrase)) if(istype(loc, /mob/)) var/mob/T = loc @@ -250,4 +258,36 @@ the implant may become unstable and either pre-maturely inject the subject or si implanted(mob/source as mob) phrase = input("Choose activation phrase:") as text usr.mind.store_memory("Explosive implant in [source] can be activated by saying something containing the phrase ''[src.phrase]'', say [src.phrase] to attempt to activate.", 0, 0) - usr << "The implanted explosive implant in [source] can be activated by saying something containing the phrase ''[src.phrase]'', say [src.phrase] to attempt to activate." \ No newline at end of file + usr << "The implanted explosive implant in [source] can be activated by saying something containing the phrase ''[src.phrase]'', say [src.phrase] to attempt to activate." + +/obj/item/weapon/implant/death_alarm + name = "death alarm" + desc = "Danger Will Robinson!" + var/mobname = "Will Robinson" + + get_data() + var/dat = {" +Implant Specifications:
+Name: NanoTrasen \"Profit Margin\" Class Employee Lifesign Sensor
+Life: Activates upon death.
+Important Notes: Alerts crew to crewmember death.
+
+Implant Details:
+Function: Contains a compact radio signaler that triggers when the host's lifesigns cease.
+Special Features: Alerts crew to crewmember death.
+Integrity: Implant will occasionally be degraded by the body's immune system and thus will occasionally malfunction."} + return dat + + process() + var/mob/M = src.loc + if(M.stat == 2) + var/turf/t = get_turf(M) + var/obj/item/device/radio/headset/a = new /obj/item/device/radio/headset(null) + a.autosay("[mobname] has died in [t.loc.name]!", "[mobname]'s Death Alarm") + del(a) + processing_objects.Remove(src) + + + implanted(mob/source as mob) + mobname = source.real_name + processing_objects.Add(src) \ No newline at end of file diff --git a/code/game/objects/items/weapons/implants/implantcase.dm b/code/game/objects/items/weapons/implants/implantcase.dm index 313e6ae352e..1c792e6fe75 100644 --- a/code/game/objects/items/weapons/implants/implantcase.dm +++ b/code/game/objects/items/weapons/implants/implantcase.dm @@ -114,4 +114,15 @@ New() src.imp = new /obj/item/weapon/implant/loyalty( src ) ..() + return + +/obj/item/weapon/implantcase/death_alarm + name = "Glass Case- 'Death Alarm'" + desc = "A case containing a death alarm implant." + icon = 'items.dmi' + icon_state = "implantcase-b" + + New() + src.imp = new /obj/item/weapon/implant/death_alarm( src ) + ..() return \ No newline at end of file diff --git a/code/game/objects/items/weapons/papers_bins.dm b/code/game/objects/items/weapons/papers_bins.dm index c7061a720e6..b13d61ad343 100644 --- a/code/game/objects/items/weapons/papers_bins.dm +++ b/code/game/objects/items/weapons/papers_bins.dm @@ -663,9 +663,6 @@ CLIPBOARDS else return src.update() - spawn(0) - attack_self(user) - return return /obj/item/weapon/clipboard/proc/update() @@ -692,6 +689,15 @@ CLIPBOARDS src.add_fingerprint(usr) return // +/obj/item/weapon/clipboard/New() + + ..() + for(var/i = 1, i <= 3, i++) + var/obj/item/weapon/paper/P = new /obj/item/weapon/paper(src) + P.loc = src + src.pen = new /obj/item/weapon/pen(src) + src.update() + return // PHOTOGRAPH diff --git a/code/game/objects/radio/radio.dm b/code/game/objects/radio/radio.dm index 1643c38ec3c..37d459777d7 100644 --- a/code/game/objects/radio/radio.dm +++ b/code/game/objects/radio/radio.dm @@ -183,6 +183,121 @@ var/GLOBAL_RADIO_TYPE = 1 // radio type to use updateDialog() add_fingerprint(usr) +/obj/item/device/radio/proc/autosay(var/message, var/from, var/channel) + 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(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" = new /mob/living/silicon/ai(src), // store a reference to the mob + "mobtype" = /mob/living/silicon/ai, // the mob's type + "realname" = from, // the mob's real name + "name" = from, // the mob's display name + "job" = "Automated Announcement", // the mob's job + "key" = "none", // the mob's key + "vmessage" = "*garbled automated announcement*", // the message to display if the voice wasn't understood + "vname" = "synthesized voice", // the name to display if the voice wasn't understood + "vmask" = 0, // 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 + ) + signal.frequency = connection.frequency // Quick frequency set + + //#### Sending the signal to all subspace receivers ####// + for(var/obj/machinery/telecomms/receiver/R in world) + R.receive_signal(signal) + + // Allinone can act as receivers. + for(var/obj/machinery/telecomms/allinone/R in world) + 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" = new /mob/living/silicon/ai(src), // store a reference to the mob + "mobtype" = /mob/living/silicon/ai, // the mob's type + "realname" = from, // the mob's real name + "name" = from, // the mob's display name + "job" = "Automated Announcement", // the mob's job + "key" = "none", // the mob's key + "vmessage" = "*garbled automated announcement*", // the message to display if the voice wasn't understood + "vname" = "synthesized voice", // the name to display if the voice wasn't understood + "vmask" = 0, // 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" = 0, // 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 + ) + signal.frequency = connection.frequency // Quick frequency set + + for(var/obj/machinery/telecomms/receiver/R in world) + R.receive_signal(signal) + + + sleep(rand(10,25)) // wait a little... + + if(signal.data["done"]) + del(signal) // delete the signal - 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: + + Broadcast_Message(connection, new /mob/living/silicon/ai(src), 0, "*garbled automated announcement*", + src, message, from, "Automated Announcement", from, "synthesized voice", + filter_type, signal.data["compression"]) + return + /obj/item/device/radio/talk_into(mob/M as mob, message, channel) if(GLOBAL_RADIO_TYPE == 1) // NEW RADIO SYSTEMS: By Doohl diff --git a/code/game/objects/storage/briefcase.dm b/code/game/objects/storage/briefcase.dm index a2dd6970cd6..14cc898e66a 100644 --- a/code/game/objects/storage/briefcase.dm +++ b/code/game/objects/storage/briefcase.dm @@ -40,3 +40,20 @@ M.eye_blurry += 3 return + +/obj/item/weapon/storage/briefcase/surgery + icon_state = "medbriefcase" + name = "surgery equipment bag" + desc = "Heavy and full of sharp things." + + New() + ..() + contents = list() + sleep(1) + new /obj/item/weapon/circular_saw(src) + new /obj/item/weapon/hemostat(src) + new /obj/item/weapon/scalpel(src) + new /obj/item/weapon/retractor(src) + new /obj/item/weapon/cautery(src) + new /obj/item/weapon/surgical_tool/bonegel(src) + new /obj/item/weapon/surgical_tool/bonesetter(src) \ No newline at end of file diff --git a/code/game/objects/storage/storage.dm b/code/game/objects/storage/storage.dm index 22d72458a45..6784909ae0f 100644 --- a/code/game/objects/storage/storage.dm +++ b/code/game/objects/storage/storage.dm @@ -259,9 +259,22 @@ new /obj/item/weapon/tank/emergency_oxygen/engi( src ) return +/obj/item/weapon/storage/box/medic/New() + ..() + contents = list() + sleep(1) + new /obj/item/clothing/mask/medical( src ) + new /obj/item/weapon/tank/emergency_oxygen/anesthetic( src ) + new /obj/item/weapon/tank/emergency_oxygen/anesthetic( src ) + new /obj/item/weapon/tank/emergency_oxygen/anesthetic( src ) + new /obj/item/weapon/tank/emergency_oxygen/anesthetic( src ) + new /obj/item/weapon/tank/emergency_oxygen/anesthetic( src ) + new /obj/item/weapon/tank/emergency_oxygen/anesthetic( src ) + return + /obj/item/weapon/storage/box/syndicate/New() ..() - switch (pickweight(list("bloodyspai" = 1, "stealth" = 1, "screwed" = 1, "guns" = 1, "murder" = 1, "freedom" = 1))) + switch (pickweight(list("bloodyspai" = 1, "stealth" = 1, "screwed" = 1, "guns" = 1, "freedom" = 1))) if ("bloodyspai") new /obj/item/clothing/under/chameleon(src) new /obj/item/clothing/mask/gas/voice(src) @@ -290,12 +303,6 @@ new /obj/item/weapon/plastique(src) return - if ("murder") - new /obj/item/weapon/melee/energy/sword(src) - new /obj/item/weapon/cloaking_device(src) - new /obj/item/weapon/card/emag(src) - return - if("freedom") var/obj/item/weapon/implanter/O = new /obj/item/weapon/implanter(src) O.imp = new /obj/item/weapon/implant/freedom(O) diff --git a/code/game/objects/tanks/emergency.dm b/code/game/objects/tanks/emergency.dm index 10af8325926..fbadf6fca8e 100644 --- a/code/game/objects/tanks/emergency.dm +++ b/code/game/objects/tanks/emergency.dm @@ -33,3 +33,19 @@ icon_state = "emergency_double" name = "Double Emergency Oxygen Tank" volume = 10 + +/obj/item/weapon/tank/emergency_oxygen/anesthetic + icon_state = "emergency_sleep" + name = "emergency sleeping gas tank" + desc = "Contains an Oxygen/N2O mix." + distribute_pressure = ONE_ATMOSPHERE + + New() + ..() + src.air_contents.oxygen = (3*ONE_ATMOSPHERE)*volume/(R_IDEAL_GAS_EQUATION*T20C) * O2STANDARD + + var/datum/gas/sleeping_agent/trace_gas = new() + trace_gas.moles = (3*ONE_ATMOSPHERE)*volume/(R_IDEAL_GAS_EQUATION*T20C) * N2STANDARD + + src.air_contents.trace_gases += trace_gas + return \ No newline at end of file diff --git a/code/game/response_team.dm b/code/game/response_team.dm index daadaac5cf9..87901a232a7 100644 --- a/code/game/response_team.dm +++ b/code/game/response_team.dm @@ -10,6 +10,9 @@ client/verb/JoinResponseTeam() if(!send_emergency_team) usr << "No emergency response team is currently being sent." return + if(jobban_isbanned(usr, "Syndicate") || jobban_isbanned(usr, "Emergency Response Team") || jobban_isbanned(usr, "Security Officer")) + usr << "You are jobbanned from the emergency reponse team!" + return if(response_team_members.len > 5) usr << "The emergency response team is already full!" @@ -19,76 +22,205 @@ client/verb/JoinResponseTeam() var/new_name = input(usr, "Pick a name","Name") as null|text if(!new_name) return - var/gender = alert(usr, "Pick a gender","Gender","Male","Female") - - var/mob/living/carbon/human/new_commando = create_response_team(L, leader_selected, new_name, gender) + var/mob/living/carbon/human/new_commando = create_response_team(L, leader_selected, new_name) new_commando.mind.key = usr.key new_commando.key = usr.key - new_commando << "\blue You are [!leader_selected?"member":"LEADER"] of an armed response team in CentComm's service. Something went down on [station_name()] and they're now on code red. Go in there and fix the problem." + new_commando << "\blue You are [!leader_selected?" a member":" the LEADER"] of an armed response team in CentComm's service. Something went down on [station_name()] and they're now on code red. Go in there and fix the problem." new_commando << "You should first gear up and discuss a plan with your team. More members may be joining, don't move out before you're ready." else usr << "You need to be an observer or new player to use this." +// returns a number of dead players in % +proc/percentage_dead() + var/total = 0 + var/deadcount = 0 + for(var/mob/living/carbon/human/H in world) if(H.mind) // I *think* monkeys gone human don't have a mind + if(H.stat == 2) deadcount++ + total++ + + if(total == 0) return 0 + else return round(100 * deadcount / total) + +// counts the number of antagonists in % +proc/percentage_antagonists() + var/total = 0 + var/antagonists = 0 + for(var/mob/living/carbon/human/H in world) + if(is_special_character(H) >= 1) + antagonists++ + total++ + + if(total == 0) return 0 + else return round(100 * antagonists / total) + + proc/trigger_armed_response_team() if(send_emergency_team) return + var/send_team_chance = 20 // base chance that a team will be sent + send_team_chance += 2*percentage_dead() // the more people are dead, the higher the chance + send_team_chance += percentage_antagonists() // the more antagonists, the higher the chance + send_team_chance = min(send_team_chance, 100) + + // there's only a certain chance a team will be sent + if(!prob(send_team_chance)) return + command_alert("According to our sensors, [station_name()] has entered code red. We will prepare and dispatch an emergency response team to deal with the situation.", "Command Report") send_emergency_team = 1 -/client/proc/create_response_team(obj/spawn_location, leader_selected = 0, commando_name, gender) +/client/proc/create_response_team(obj/spawn_location, leader_selected = 0, commando_name) - var/mob/living/carbon/human/new_commando = new(spawn_location.loc) - new_commando.gender = ((gender == "Male") ? MALE : FEMALE) + var/mob/living/carbon/human/M = new(spawn_location.loc) - var/datum/preferences/A = new()//Randomize appearance for the commando. - A.randomize_appearance_for(new_commando) + var/new_facial = input("Please select facial hair color.", "Character Generation") as color + if(new_facial) + M.r_facial = hex2num(copytext(new_facial, 2, 4)) + M.g_facial = hex2num(copytext(new_facial, 4, 6)) + M.b_facial = hex2num(copytext(new_facial, 6, 8)) - new_commando.real_name = commando_name - new_commando.age = !leader_selected ? rand(23,35) : rand(35,45) + var/new_hair = input("Please select hair color.", "Character Generation") as color + if(new_facial) + M.r_hair = hex2num(copytext(new_hair, 2, 4)) + M.g_hair = hex2num(copytext(new_hair, 4, 6)) + M.b_hair = hex2num(copytext(new_hair, 6, 8)) - new_commando.dna.ready_dna(new_commando)//Creates DNA. + var/new_eyes = input("Please select eye color.", "Character Generation") as color + if(new_eyes) + M.r_eyes = hex2num(copytext(new_eyes, 2, 4)) + M.g_eyes = hex2num(copytext(new_eyes, 4, 6)) + M.b_eyes = hex2num(copytext(new_eyes, 6, 8)) + + var/new_tone = input("Please select skin tone level: 1-220 (1=albino, 35=caucasian, 150=black, 220='very' black)", "Character Generation") as text + + if (new_tone) + M.s_tone = max(min(round(text2num(new_tone)), 220), 1) + M.s_tone = -M.s_tone + 35 + + // hair + var/list/all_hairs = typesof(/datum/sprite_accessory/hair) - /datum/sprite_accessory/hair + var/list/hairs = list() + + // loop through potential hairs + for(var/x in all_hairs) + var/datum/sprite_accessory/hair/H = new x // create new hair datum based on type x + hairs.Add(H.name) // add hair name to hairs + del(H) // delete the hair after it's all done + + var/new_style = input("Please select hair style", "Character Generation") as null|anything in hairs + + // if new style selected (not cancel) + if (new_style) + M.h_style = new_style + + for(var/x in all_hairs) // loop through all_hairs again. Might be slightly CPU expensive, but not significantly. + var/datum/sprite_accessory/hair/H = new x // create new hair datum + if(H.name == new_style) + M.hair_style = H // assign the hair_style variable a new hair datum + break + else + del(H) // if hair H not used, delete. BYOND can garbage collect, but better safe than sorry + + // facial hair + var/list/all_fhairs = typesof(/datum/sprite_accessory/facial_hair) - /datum/sprite_accessory/facial_hair + var/list/fhairs = list() + + for(var/x in all_fhairs) + var/datum/sprite_accessory/facial_hair/H = new x + fhairs.Add(H.name) + del(H) + + new_style = input("Please select facial style", "Character Generation") as null|anything in fhairs + + if(new_style) + M.f_style = new_style + for(var/x in all_fhairs) + var/datum/sprite_accessory/facial_hair/H = new x + if(H.name == new_style) + M.facial_hair_style = H + break + else + del(H) + + var/new_gender = alert(usr, "Please select gender.", "Character Generation", "Male", "Female") + if (new_gender) + if(new_gender == "Male") + M.gender = MALE + else + M.gender = FEMALE + M.update_body() + M.update_face() + M.update_clothing() + + M.real_name = commando_name + M.age = !leader_selected ? rand(23,35) : rand(35,45) + + M.dna.ready_dna(M)//Creates DNA. //Creates mind stuff. - new_commando.mind = new - new_commando.mind.current = new_commando - new_commando.mind.original = new_commando - new_commando.mind.assigned_role = "MODE" - new_commando.mind.special_role = "Death Commando" - if(!(new_commando.mind in ticker.minds)) - ticker.minds += new_commando.mind//Adds them to regular mind list. - new_commando.equip_strike_team(leader_selected) + M.mind = new + M.mind.current = M + M.mind.original = M + M.mind.assigned_role = "MODE" + M.mind.special_role = "Response Team" + if(!(M.mind in ticker.minds)) + ticker.minds += M.mind//Adds them to regular mind list. + M.equip_strike_team(leader_selected) del(spawn_location) - return new_commando + return M /mob/living/carbon/human/proc/equip_strike_team(leader_selected = 0) + //Special radio setup var/obj/item/device/radio/R = new /obj/item/device/radio/headset(src) - R.set_frequency(1441) + R.name = "CentCom Response Team headset" + R.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." + R.freerange = 1 + R.listening = 0 + R.config(list("Response Team" = 1, "Science" = 0, "Command" = 0, "Medical" = 0, "Engineering" = 0, "Security" = 0, "Mining" = 0, "Cargo" = 0,)) equip_if_possible(R, slot_ears) - equip_if_possible(new /obj/item/clothing/under/color/black(src), slot_w_uniform) - equip_if_possible(new /obj/item/clothing/shoes/swat(src), slot_shoes) - equip_if_possible(new /obj/item/clothing/suit/armor/swat(src), slot_wear_suit) + + //Adding Camera Network + var/obj/machinery/camera/camera = new /obj/machinery/camera(src) //Gives all the commandos internals cameras. + camera.network = "CREED" + camera.c_tag = real_name + + //Basic Uniform + equip_if_possible(new /obj/item/clothing/under/syndicate/tacticool(src), slot_w_uniform) + equip_if_possible(new /obj/item/device/flashlight(src), slot_l_store) + equip_if_possible(new /obj/item/weapon/clipboard(src), slot_r_store) + equip_if_possible(new /obj/item/weapon/gun/energy/gun(src), slot_belt) + + //Glasses + equip_if_possible(new /obj/item/clothing/glasses/sunglasses/sechud(src), slot_glasses) + + //Shoes & gloves + var/obj/item/clothing/shoes/swat/S = new /obj/item/clothing/shoes/swat(src) + S.flags = NOSLIP + equip_if_possible(S, slot_shoes) equip_if_possible(new /obj/item/clothing/gloves/swat(src), slot_gloves) - equip_if_possible(new /obj/item/clothing/head/helmet/space/deathsquad(src), slot_head) - equip_if_possible(new /obj/item/clothing/mask/gas/swat(src), slot_wear_mask) + //Removed +// equip_if_possible(new /obj/item/clothing/suit/armor/swat(src), slot_wear_suit) +// equip_if_possible(new /obj/item/clothing/head/helmet/space/deathsquad(src), slot_head) +// equip_if_possible(new /obj/item/clothing/mask/gas/swat(src), slot_wear_mask) + + //Backpack equip_if_possible(new /obj/item/weapon/storage/backpack/security(src), slot_back) - equip_if_possible(new /obj/item/weapon/storage/box(src), slot_in_backpack) - + equip_if_possible(new /obj/item/weapon/storage/box/engineer(src), slot_in_backpack) equip_if_possible(new /obj/item/weapon/storage/firstaid/regular(src), slot_in_backpack) - equip_if_possible(new /obj/item/device/flashlight(src), slot_in_backpack) - - equip_if_possible(new /obj/item/weapon/tank/emergency_oxygen(src), slot_s_store) var/obj/item/weapon/card/id/W = new(src) W.name = "[real_name]'s ID Card" W.icon_state = "centcom" - W.access = get_access("Head of Personnel") + if(leader_selected) + W.access = get_access("Captain") + else + W.access = get_access("Head of Personnel") W.access += list(access_cent_general, access_cent_specops, access_cent_living, access_cent_storage)//Let's add their alloted CentCom access. W.assignment = "Emergency Response Team" W.registered = real_name diff --git a/code/game/specops_shuttle.dm b/code/game/specops_shuttle.dm index 29179a7e17a..f05c6326cab 100644 --- a/code/game/specops_shuttle.dm +++ b/code/game/specops_shuttle.dm @@ -2,6 +2,7 @@ #define SPECOPS_MOVETIME 600 //Time to station is milliseconds. 60 seconds, enough time for everyone to be on the shuttle before it leaves. #define SPECOPS_STATION_AREATYPE "/area/shuttle/specops/station" //Type of the spec ops shuttle area for station #define SPECOPS_DOCK_AREATYPE "/area/shuttle/specops/centcom" //Type of the spec ops shuttle area for dock +#define SPECOPS_RETURN_DELAY 6000 //Time between the shuttle is capable of moving. var/specops_shuttle_moving_to_station = 0 var/specops_shuttle_moving_to_centcom = 0 @@ -18,18 +19,16 @@ var/specops_shuttle_timeleft = 0 var/temp = null var/hacked = 0 var/allowedtocall = 0 + var/specops_shuttle_timereset = 0 -/proc/specops_process() - var/area/centcom/control/cent_com = locate()//To find announcer. This area should exist for this proc to work. - var/area/centcom/specops/special_ops = locate()//Where is the specops area located? - var/mob/living/silicon/decoy/announcer = locate() in cent_com//We need a fake AI to announce some stuff below. Otherwise it will be wonky. +/proc/specops_return() + var/obj/item/device/radio/intercom/announcer = new /obj/item/device/radio/intercom(null)//We need a fake AI to announce some stuff below. Otherwise it will be wonky. + announcer.config(list("Response Team" = 0)) var/message_tracker[] = list(0,1,2,3,5,10,30,45)//Create a a list with potential time values. - var/message = "THE SPECIAL OPERATIONS SHUTTLE IS PREPARING FOR LAUNCH"//Initial message shown. + var/message = "THE SPECIAL OPERATIONS SHUTTLE IS PREPARING TO RETURN"//Initial message shown. if(announcer) - announcer.say(message) - message = "ARMORED SQUAD TAKE YOUR POSITION ON GRAVITY LAUNCH PAD" - announcer.say(message) + announcer.autosay(message, "A.L.I.C.E.", "Response Team") while(specops_shuttle_time - world.timeofday > 0) var/ticksleft = specops_shuttle_time - world.timeofday @@ -45,7 +44,76 @@ var/specops_shuttle_timeleft = 0 message = "ALERT: [rounded_time_left] SECOND[(rounded_time_left!=1)?"S":""] REMAIN" if(rounded_time_left==0) message = "ALERT: TAKEOFF" - announcer.say(message) + announcer.autosay(message, "A.L.I.C.E.", "Response Team") + message_tracker -= rounded_time_left//Remove the number from the list so it won't be called again next cycle. + //Should call all the numbers but lag could mean some issues. Oh well. Not much I can do about that. + + sleep(5) + + specops_shuttle_moving_to_station = 0 + specops_shuttle_moving_to_centcom = 0 + + specops_shuttle_at_station = 1 + + var/area/start_location = locate(/area/shuttle/specops/station) + var/area/end_location = locate(/area/shuttle/specops/centcom) + + var/list/dstturfs = list() + var/throwy = world.maxy + + for(var/turf/T in end_location) + dstturfs += T + if(T.y < throwy) + throwy = T.y + + // hey you, get out of the way! + for(var/turf/T in dstturfs) + // find the turf to move things to + var/turf/D = locate(T.x, throwy - 1, 1) + //var/turf/E = get_step(D, SOUTH) + for(var/atom/movable/AM as mob|obj in T) + AM.Move(D) + if(istype(T, /turf/simulated)) + del(T) + + start_location.move_contents_to(end_location) + + for(var/turf/T in get_area_turfs(end_location) ) + var/mob/M = locate(/mob) in T + M << "\red You have arrived at Central Command. Operation has ended!" + + for(var/obj/machinery/computer/specops_shuttle/S in world) + S.specops_shuttle_timereset = world.time + SPECOPS_RETURN_DELAY + + del(announcer) + +/proc/specops_process() + var/area/centcom/specops/special_ops = locate()//Where is the specops area located? + var/obj/item/device/radio/intercom/announcer = new /obj/item/device/radio/intercom(null)//We need a fake AI to announce some stuff below. Otherwise it will be wonky. + announcer.config(list("Response Team" = 0)) + + var/message_tracker[] = list(0,1,2,3,5,10,30,45)//Create a a list with potential time values. + var/message = "THE SPECIAL OPERATIONS SHUTTLE IS PREPARING FOR LAUNCH"//Initial message shown. + if(announcer) + announcer.autosay(message, "A.L.I.C.E.", "Response Team") + message = "ARMORED SQUAD TAKE YOUR POSITION ON GRAVITY LAUNCH PAD" + announcer.autosay(message, "A.L.I.C.E.", "Response Team") + + while(specops_shuttle_time - world.timeofday > 0) + var/ticksleft = specops_shuttle_time - world.timeofday + + if(ticksleft > 1e5) + specops_shuttle_time = world.timeofday + 10 // midnight rollover + specops_shuttle_timeleft = (ticksleft / 10) + + //All this does is announce the time before launch. + if(announcer) + var/rounded_time_left = round(specops_shuttle_timeleft)//Round time so that it will report only once, not in fractions. + if(rounded_time_left in message_tracker)//If that time is in the list for message announce. + message = "ALERT: [rounded_time_left] SECOND[(rounded_time_left!=1)?"S":""] REMAIN" + if(rounded_time_left==0) + message = "ALERT: TAKEOFF" + announcer.autosay(message, "A.L.I.C.E.", "Response Team") message_tracker -= rounded_time_left//Remove the number from the list so it won't be called again next cycle. //Should call all the numbers but lag could mean some issues. Oh well. Not much I can do about that. @@ -155,9 +223,18 @@ var/specops_shuttle_timeleft = 0 var/mob/M = locate(/mob) in T M << "\red You have arrived to [station_name]. Commence operation!" + for(var/obj/machinery/computer/specops_shuttle/S in world) + S.specops_shuttle_timereset = world.time + SPECOPS_RETURN_DELAY + + del(announcer) + /proc/specops_can_move() - if(specops_shuttle_moving_to_station || specops_shuttle_moving_to_centcom) return 0 - else return 1 + if(specops_shuttle_moving_to_station || specops_shuttle_moving_to_centcom) + return 0 + for(var/obj/machinery/computer/specops_shuttle/S in world) + if(world.time <= S.specops_shuttle_timereset) + return 0 + return 1 /obj/machinery/computer/specops_shuttle/attack_ai(var/mob/user as mob) return attack_hand(user) @@ -190,7 +267,7 @@ var/specops_shuttle_timeleft = 0 else dat += {"
Special Operations Shuttle
\nLocation: [specops_shuttle_moving_to_station || specops_shuttle_moving_to_centcom ? "Departing for [station_name] in ([specops_shuttle_timeleft] seconds.)":specops_shuttle_at_station ? "Station":"Dock"]
- [specops_shuttle_moving_to_station || specops_shuttle_moving_to_centcom ? "\n*The Special Ops. shuttle is already leaving.*
\n
":specops_shuttle_at_station ? "\nShuttle Offline
\n
":"\nDepart to [station_name]
\n
"] + [specops_shuttle_moving_to_station || specops_shuttle_moving_to_centcom ? "\n*The Special Ops. shuttle is already leaving.*
\n
":specops_shuttle_at_station ? "\nShuttle standing by...
\n
":"\nDepart to [station_name]
\n
"] \nClose"} user << browse(dat, "window=computer;size=575x450") @@ -207,8 +284,23 @@ var/specops_shuttle_timeleft = 0 if (href_list["sendtodock"]) if(!specops_shuttle_at_station|| specops_shuttle_moving_to_station || specops_shuttle_moving_to_centcom) return - usr << "\blue Central Command will not allow the Special Operations shuttle to return." - return + if (!specops_can_move()) + usr << "\blue Central Command will not allow the Special Operations shuttle to return yet." + if(world.time <= specops_shuttle_timereset) + if (((world.time - specops_shuttle_timereset)/10) > 60) + usr << "\blue [-((world.time - specops_shuttle_timereset)/10)/60] minutes remain!" + usr << "\blue [-(world.time - specops_shuttle_timereset)/10] seconds remain!" + return + + usr << "\blue The Special Operations shuttle will arrive at Central Command in [(SPECOPS_MOVETIME/10)] seconds." + + temp += "Shuttle departing.

OK" + updateUsrDialog() + + specops_shuttle_moving_to_centcom = 1 + specops_shuttle_time = world.timeofday + SPECOPS_MOVETIME + spawn(0) + specops_return() else if (href_list["sendtostation"]) if(specops_shuttle_at_station || specops_shuttle_moving_to_station || specops_shuttle_moving_to_centcom) return diff --git a/code/game/turf.dm b/code/game/turf.dm index 074d808477a..208a30dfe43 100644 --- a/code/game/turf.dm +++ b/code/game/turf.dm @@ -129,6 +129,8 @@ var/prior_icon = icon_old var/old_dir = dir + for(var/obj/structure/lattice/L in locate(src.x, src.y, src.z)) + del(L) var/turf/simulated/floor/W = new /turf/simulated/floor( locate(src.x, src.y, src.z) ) W.dir = old_dir @@ -146,6 +148,8 @@ var/prior_icon = icon_old var/old_dir = dir + for(var/obj/structure/lattice/L in locate(src.x, src.y, src.z)) + del(L) var/turf/simulated/floor/plating/W = new /turf/simulated/floor/plating( locate(src.x, src.y, src.z) ) W.dir = old_dir @@ -159,6 +163,8 @@ /turf/proc/ReplaceWithEngineFloor() var/old_dir = dir + for(var/obj/structure/lattice/L in locate(src.x, src.y, src.z)) + del(L) var/turf/simulated/floor/engine/E = new /turf/simulated/floor/engine( locate(src.x, src.y, src.z) ) E.dir = old_dir diff --git a/code/game/verbs/who.dm b/code/game/verbs/who.dm index 8ce32872d50..0660b1bfbea 100644 --- a/code/game/verbs/who.dm +++ b/code/game/verbs/who.dm @@ -34,3 +34,16 @@ usr << "[M.key] is a [M.client.holder.rank][M.client.stealth ? " (as [M.client.fakekey])" : ""]" else if(!M.client.stealth && (M.client.holder.level != -3)) usr << "\t[M.client]" + +/client/verb/active_players() + set category = "OOC" + set name = "Active Players" + var/total = 0 + for(var/mob/living/M in world) + if(!M.client) continue + if(M.client.inactivity > 10 * 60 * 10) continue + if(M.stat == 2) continue + + total++ + + usr << "Active Players: [total]" \ No newline at end of file diff --git a/code/modules/admin/admin.dm b/code/modules/admin/admin.dm index 48c462e243c..2f94d139895 100644 --- a/code/modules/admin/admin.dm +++ b/code/modules/admin/admin.dm @@ -202,6 +202,12 @@ else jobs += "
[dd_replacetext("Syndicate", " ", " ")] " + if(jobban_isbanned(M, "Emergency Response Team")) + jobs += "
[dd_replacetext("Emergency Response Team", " ", " ")] " + else + jobs += "
[dd_replacetext("Emergency Response Team", " ", " ")] " + + if(jobban_isbanned(M, "pAI")) jobs += "
pAI " else @@ -333,6 +339,7 @@ jobs += "Scientist+RD
" jobs += "AI+Cyborg
" jobs += "Detective+HoS

" + jobs += "Emergency Response Team

" for(var/datum/job/job in job_master.occupations) if(job.title == "Tourist") continue diff --git a/code/modules/admin/verbs/debug.dm b/code/modules/admin/verbs/debug.dm index 2c41de82475..2c3aa31f76e 100644 --- a/code/modules/admin/verbs/debug.dm +++ b/code/modules/admin/verbs/debug.dm @@ -480,6 +480,7 @@ But you can call procs that are of type /mob/living/carbon/human/proc/ for that "assassin", "death commando", "syndicate commando", + "response team", "centcom official", "centcom commander", "special ops officer", @@ -677,6 +678,9 @@ But you can call procs that are of type /mob/living/carbon/human/proc/ for that if("syndicate commando") M.equip_syndicate_commando() + if("response team") + M.equip_strike_team() + if("centcom official") M.equip_if_possible(new /obj/item/clothing/under/rank/centcom_officer(M), M.slot_w_uniform) M.equip_if_possible(new /obj/item/clothing/shoes/black(M), M.slot_shoes) @@ -686,7 +690,7 @@ But you can call procs that are of type /mob/living/carbon/human/proc/ for that var/obj/item/clothing/glasses/sunglasses/V = new(M) V.loc = K M.equip_if_possible(K, M.slot_wear_suit) - M.equip_if_possible(new /obj/item/weapon/gun/energy(M), M.slot_s_store) + M.equip_if_possible(new /obj/item/weapon/gun/energy/gun(M), M.slot_s_store) var/obj/item/device/pda/heads/pda = new(M) pda.owner = M.real_name @@ -694,10 +698,7 @@ But you can call procs that are of type /mob/living/carbon/human/proc/ for that pda.name = "PDA-[M.real_name] ([pda.ownjob])" M.equip_if_possible(pda, M.slot_r_store) - - var/obj/item/weapon/clipboard/G = new(M) - G.pen = new /obj/item/weapon/pen(G) - M.equip_if_possible(G, M.slot_l_store) + M.equip_if_possible(new /obj/item/weapon/clipboard(M), M.slot_l_store) var/obj/item/weapon/card/id/W = new(M) W.name = "[M.real_name]'s ID Card" diff --git a/code/modules/chemical/Chemistry-Tools.dm b/code/modules/chemical/Chemistry-Tools.dm index f687dad93e3..1dedd042d6f 100644 --- a/code/modules/chemical/Chemistry-Tools.dm +++ b/code/modules/chemical/Chemistry-Tools.dm @@ -2187,6 +2187,17 @@ ..() reagents.add_reagent("cryoxadone", 30) +/obj/item/weapon/reagent_containers/glass/beaker/tricordrazine + name = "beaker" + desc = "A beaker. Can hold up to 50 units." + icon = 'chemical.dmi' + icon_state = "beaker0" + item_state = "beaker" + + New() + ..() + reagents.add_reagent("tricordrazine", 30) + /obj/item/weapon/reagent_containers/food/drinks/golden_cup desc = "A golden cup" name = "golden cup" diff --git a/code/modules/mob/living/carbon/alien/humanoid/alien_powers.dm b/code/modules/mob/living/carbon/alien/humanoid/alien_powers.dm index f45a231b458..edd9aba5eab 100644 --- a/code/modules/mob/living/carbon/alien/humanoid/alien_powers.dm +++ b/code/modules/mob/living/carbon/alien/humanoid/alien_powers.dm @@ -14,7 +14,7 @@ Doesn't work on other aliens/AI.*/ src << "\green Not enough plasma stored." return 0 else if(Y && (!isturf(src.loc) || istype(src.loc, /turf/space))) - src << "\green Bad place for a garden!" + src << "\green Weeds would not be able to survive here." return 0 else return 1 @@ -133,35 +133,32 @@ I kind of like the right click only--the window version can get a little confusi for(var/obj/machinery/atmospherics/unary/vent_pump/v in range(1,src)) if(!v.welded) vent_found = v + break else src << "\red That vent is welded." + if(vent_found) - var/list/vents = list() - if(vent_found.network&&vent_found.network.normal_members.len) + var/list/ventAreas = list() // A list of the areas of all the vents you can go to. + var/list/vents = list() // The list of vent objects you can go to. + if(vent_found.network && vent_found.network.normal_members.len) for(var/obj/machinery/atmospherics/unary/vent_pump/temp_vent in vent_found.network.normal_members) - if(temp_vent.loc == loc) + if(temp_vent.loc == loc || temp_vent.loc.z != loc.z) continue if(temp_vent.welded) continue + vents.Add(temp_vent) - var/list/choices = list() - for(var/obj/machinery/atmospherics/unary/vent_pump/vent in vents) - if(vent.loc.z != loc.z) - continue - if(vent.welded) - continue - var/atom/a = get_turf_loc(vent) - choices.Add(a.loc) - var/turf/startloc = loc - var/obj/selection = input("Select a destination.", "Duct System") in choices - var/selection_position = choices.Find(selection) - if(loc==startloc) - // Hacky way of hopefully preventing a runtime error from happening - if(vents.len < selection_position) - vents.len = selection_position//What the fuck is this I dont even, Right will likely have to fix this later + var/atom/a = get_turf_loc(temp_vent) + ventAreas.Add(a.loc) - var/obj/machinery/atmospherics/unary/vent_pump/target_vent = vents[selection_position] + + var/turf/startLoc = loc + var/area/destArea = input("Select a destination.", "Duct System") in ventAreas + var/destAreaIndex = ventAreas.Find(destArea) + + if(loc==startLoc) + var/obj/machinery/atmospherics/unary/vent_pump/target_vent = vents[destAreaIndex] if(target_vent) for(var/mob/O in viewers(src, null)) O.show_message(text("[src] scrambles into the ventillation ducts!"), 1) @@ -178,7 +175,7 @@ I kind of like the right click only--the window version can get a little confusi spawn(round(travel_time/2))//give sound warning to anyone near the target vent if(!target_vent.welded) for(var/mob/O in hearers(target_vent, null)) - O.show_message("You hear something crawling trough the ventilation pipes.",2) + O.show_message("You hear something crawling through the ventilation pipes.",2) spawn(travel_time) if(target_vent.welded)//the vent can be welded while alien scrolled through the list or travelled. diff --git a/code/modules/mob/living/carbon/human/examine.dm b/code/modules/mob/living/carbon/human/examine.dm index f901319266d..63ef86aee38 100644 --- a/code/modules/mob/living/carbon/human/examine.dm +++ b/code/modules/mob/living/carbon/human/examine.dm @@ -121,11 +121,12 @@ if (src.stat == 1 || stat == 2) usr << "\red [name] doesn't seem to be responding to anything around [t_him], [t_his] eyes closed as though asleep." - if((health < 0 || stat == 1) && distance <= 3) + if(health < 0 && distance <= 3) usr << "\red [name] does not appear to be breathing." if(istype(usr, /mob/living/carbon/human) && usr.stat == 0 && src.stat == 1 && distance <= 1) for(var/mob/O in viewers(usr.loc, null)) O.show_message("[usr] checks [src]'s pulse.", 1) + sleep(15) usr << "\blue [name] has a pulse!" if (src.stat == 2 || (changeling && changeling.changeling_fakedeath == 1)) @@ -133,6 +134,7 @@ if(istype(usr, /mob/living/carbon/human) && usr.stat == 0) for(var/mob/O in viewers(usr.loc, null)) O.show_message("[usr] checks [src]'s pulse.", 1) + sleep(15) usr << "\red [name] has no pulse!" else if (src.getBruteLoss()) diff --git a/code/modules/mob/living/carbon/human/human.dm b/code/modules/mob/living/carbon/human/human.dm index 7ee57fc6872..a8f7ee216f5 100644 --- a/code/modules/mob/living/carbon/human/human.dm +++ b/code/modules/mob/living/carbon/human/human.dm @@ -1469,7 +1469,7 @@ del(src) return if("internal") - if ((!( (istype(target.wear_mask, /obj/item/clothing/mask) && istype(target.back, /obj/item/weapon/tank) && !( target.internal )) ) && !( target.internal ))) + if ((!( (istype(target.wear_mask, /obj/item/clothing/mask) && (istype(target.back, /obj/item/weapon/tank) || istype(target.belt, /obj/item/weapon/tank) || istype(target.s_store, /obj/item/weapon/tank)) && !( target.internal )) ) && !( target.internal ))) //SN src = null del(src) return @@ -2118,11 +2118,11 @@ It can still be worn/put on as normal. if (!( istype(target.wear_mask, /obj/item/clothing/mask) )) return else - if (istype(target.back, /obj/item/weapon/tank)) + if (istype(target.back, /obj/item/weapon/tank) && (internalloc == "back" || !internalloc)) target.internal = target.back - else if (istype(target.s_store, /obj/item/weapon/tank)) + else if (istype(target.s_store, /obj/item/weapon/tank) && (internalloc == "store" || !internalloc)) target.internal = target.s_store - else if (istype(target.belt, /obj/item/weapon/tank)) + else if (istype(target.belt, /obj/item/weapon/tank) && (internalloc == "belt" || !internalloc)) target.internal = target.belt if (target.internal) for(var/mob/M in viewers(target, 1)) @@ -2136,10 +2136,16 @@ It can still be worn/put on as normal. if(target) target.update_clothing() //SN src = null + for(var/mob/living/carbon/M in oview(1,target)) + if(M.machine == target) + target.interact(M) del(src) return /mob/living/carbon/human/show_inv(mob/user as mob) + interact(user) + +/mob/living/carbon/human/proc/interact(mob/user as mob) user.machine = src var/dat = {" @@ -2154,12 +2160,12 @@ It can still be worn/put on as normal.
Right Ear: [(r_ear ? r_ear : "Nothing")]
Head: [(head ? head : "Nothing")]
Shoes: [(shoes ? shoes : "Nothing")] -
Belt: [(belt ? belt : "Nothing")] +
Belt: [(belt ? belt : "Nothing")] [(istype(wear_mask, /obj/item/clothing/mask) && istype(belt, /obj/item/weapon/tank) && !( internal )) ? text(" Set Internal", src) : ""]
Uniform: [(w_uniform ? w_uniform : "Nothing")]
(Exo)Suit: [(wear_suit ? wear_suit : "Nothing")] -
Back: [(back ? back : "Nothing")] [((istype(wear_mask, /obj/item/clothing/mask) && istype(back, /obj/item/weapon/tank) && !( internal )) ? text(" Set Internal", src) : "")] +
Back: [(back ? back : "Nothing")][(istype(wear_mask, /obj/item/clothing/mask) && istype(back, /obj/item/weapon/tank) && !( internal )) ? text(" Set Internal", src) : ""]
ID: [(wear_id ? wear_id : "Nothing")] -
Suit Storage: [(s_store ? s_store : "Nothing")] +
Suit Storage: [(s_store ? s_store : "Nothing")] [(istype(wear_mask, /obj/item/clothing/mask) && istype(s_store, /obj/item/weapon/tank) && !( internal )) ? text(" Set Internal", src) : ""]
[(handcuffed ? text("Handcuffed") : text("Not Handcuffed"))]
[(internal ? text("Remove Internal") : "")]
Empty Pockets @@ -2335,6 +2341,8 @@ It can still be worn/put on as normal. O.s_loc = usr.loc O.t_loc = loc O.place = href_list["item"] + if(href_list["loc"]) + O.internalloc = href_list["loc"] requests += O spawn( 0 ) O.process() diff --git a/code/modules/mob/living/silicon/robot/robot.dm b/code/modules/mob/living/silicon/robot/robot.dm index b05d23edeff..2f683a56bba 100644 --- a/code/modules/mob/living/silicon/robot/robot.dm +++ b/code/modules/mob/living/silicon/robot/robot.dm @@ -753,18 +753,36 @@ contents += O if(istype(module_state_1,/obj/item/borg/sight)) sight_mode |= module_state_1:sight_mode + else if(istype(module_state_1,/obj/item/weapon/zippo)) + var/obj/item/weapon/zippo/Z = module_state_1 + Z.lit = 1 + Z.icon_state = "zippoon" + Z.item_state = "zippoon" + processing_objects.Add(Z) else if(!module_state_2) module_state_2 = O O.layer = 20 contents += O if(istype(module_state_2,/obj/item/borg/sight)) sight_mode |= module_state_2:sight_mode + else if(istype(module_state_2,/obj/item/weapon/zippo)) + var/obj/item/weapon/zippo/Z = module_state_2 + Z.lit = 1 + Z.icon_state = "zippoon" + Z.item_state = "zippoon" + processing_objects.Add(Z) else if(!module_state_3) module_state_3 = O O.layer = 20 contents += O if(istype(module_state_3,/obj/item/borg/sight)) sight_mode |= module_state_3:sight_mode + else if(istype(module_state_3,/obj/item/weapon/zippo)) + var/obj/item/weapon/zippo/Z = module_state_3 + Z.lit = 1 + Z.icon_state = "zippoon" + Z.item_state = "zippoon" + processing_objects.Add(Z) else src << "You need to disable a module first!" installed_modules() @@ -773,12 +791,30 @@ var/obj/item/O = locate(href_list["deact"]) if(activated(O)) if(module_state_1 == O) + if(istype(module_state_1, /obj/item/weapon/zippo)) + var/obj/item/weapon/zippo/Z = module_state_1 + Z.lit = 0 + Z.icon_state = "zippo" + Z.item_state = "zippo" + processing_objects.Remove(Z) module_state_1 = null contents -= O else if(module_state_2 == O) - module_state_2 = null + if(istype(module_state_2, /obj/item/weapon/zippo)) + var/obj/item/weapon/zippo/Z = module_state_2 + Z.lit = 0 + Z.icon_state = "zippo" + Z.item_state = "zippo" + processing_objects.Remove(Z) + module_state_2= null contents -= O else if(module_state_3 == O) + if(istype(module_state_3, /obj/item/weapon/zippo)) + var/obj/item/weapon/zippo/Z = module_state_3 + Z.lit = 0 + Z.icon_state = "zippo" + Z.item_state = "zippo" + processing_objects.Remove(Z) module_state_3 = null contents -= O else diff --git a/code/modules/mob/living/silicon/robot/robot_modules.dm b/code/modules/mob/living/silicon/robot/robot_modules.dm index 0ee3724b773..e4158e0617c 100644 --- a/code/modules/mob/living/silicon/robot/robot_modules.dm +++ b/code/modules/mob/living/silicon/robot/robot_modules.dm @@ -193,10 +193,7 @@ src.modules += M src.modules += new /obj/item/weapon/reagent_containers/robodropper(src) - - var/obj/item/weapon/zippo/L = new /obj/item/weapon/zippo(src) - L.lit = 1 - src.modules += L + src.modules += new /obj/item/weapon/zippo(src) src.modules += new /obj/item/weapon/tray(src) src.modules += new /obj/item/weapon/reagent_containers/food/drinks/shaker(src) diff --git a/code/modules/mob/new_player/new_player.dm b/code/modules/mob/new_player/new_player.dm index af2c6097c03..6d3ac0648ee 100644 --- a/code/modules/mob/new_player/new_player.dm +++ b/code/modules/mob/new_player/new_player.dm @@ -270,15 +270,9 @@ proc/AnnounceArrival(var/mob/living/carbon/human/character, var/rank) if (ticker.current_state == GAME_STATE_PLAYING) - var/ailist[] = list() - for (var/mob/living/silicon/ai/A in world) - if (!A.stat) - ailist += A - if (ailist.len) - var/mob/living/silicon/ai/announcer = pick(ailist) - if(character.mind) - if((character.mind.assigned_role != "Cyborg") && (character.mind.special_role != "MODE")) - announcer.say("[character.real_name] has signed up as [rank].") + var/obj/item/device/radio/intercom/a = new /obj/item/device/radio/intercom(null) + a.autosay("[character.real_name] has arrived on the station.", "Arrivals Announcement Computer") + del(a) proc/ManifestLateSpawn(var/mob/living/carbon/human/H, icon/H_icon) // Attempted fix to add late joiners to various databases -- TLE diff --git a/code/modules/mob/say.dm b/code/modules/mob/say.dm index 6d4c5f3b1e6..fd2cd466bee 100644 --- a/code/modules/mob/say.dm +++ b/code/modules/mob/say.dm @@ -44,6 +44,8 @@ M.show_message(rendered, 2) /mob/proc/say_understands(var/mob/other) + if(!other) + return 1 if (src.stat == 2) return 1 else if (istype(other, src.type)) diff --git a/code/modules/power/pacman2.dm b/code/modules/power/pacman2.dm new file mode 100644 index 00000000000..930877d441a --- /dev/null +++ b/code/modules/power/pacman2.dm @@ -0,0 +1,175 @@ + +//Baseline portable generator. Has all the default handling. Not intended to be used on it's own (since it generates unlimited power). +/obj/machinery/power/port_gen/pacman2 + name = "Pacman II" + desc = "P.A.C.M.A.N. type II portable generator. Uses liquid plasma as a fuel source." + power_gen = 4500 + var + obj/item/weapon/tank/plasma/P = null + board_path = "/obj/item/weapon/circuitboard/pacman2" + emagged = 0 + heat = 0 +/* + process() + if(P) + if(P.air_contents.toxins <= 0) + P.air_contents.toxins = 0 + eject() + else + P.air_contents.toxins -= 0.001 + return +*/ + + HasFuel() + if(P.air_contents.toxins >= 0.1) + return 1 + return 0 + + UseFuel() + P.air_contents.toxins -= 0.01 + return + + New() + ..() + component_parts = list() + component_parts += new /obj/item/weapon/stock_parts/matter_bin(src) + component_parts += new /obj/item/weapon/stock_parts/micro_laser(src) + component_parts += new /obj/item/weapon/cable_coil(src) + component_parts += new /obj/item/weapon/cable_coil(src) + component_parts += new /obj/item/weapon/stock_parts/capacitor(src) + component_parts += new board_path(src) + RefreshParts() + + RefreshParts() + var/temp_rating = 0 + var/temp_reliability = 0 + for(var/obj/item/weapon/stock_parts/SP in component_parts) + if(istype(SP, /obj/item/weapon/stock_parts/matter_bin)) + //max_coins = SP.rating * SP.rating * 1000 + else if(istype(SP, /obj/item/weapon/stock_parts/micro_laser) || istype(SP, /obj/item/weapon/stock_parts/capacitor)) + temp_rating += SP.rating + for(var/obj/item/weapon/CP in component_parts) + temp_reliability += CP.reliability + reliability = min(round(temp_reliability / 4), 100) + power_gen = round(initial(power_gen) * (max(2, temp_rating) / 2)) + + examine() + ..() + usr << "\blue The generator has [P.air_contents.toxins] units of fuel left, producing [power_gen] per cycle." + if(crit_fail) usr << "\red The generator seems to have broken down." + + handleInactive() + heat -= 2 + if (heat < 0) + heat = 0 + else + for(var/mob/M in viewers(1, src)) + if (M.client && M.machine == src) + src.updateUsrDialog() + + proc + overheat() + explosion(src.loc, 2, 5, 2, -1) + + attackby(var/obj/item/O as obj, var/mob/user as mob) + if(istype(O, /obj/item/weapon/tank/plasma)) + if(P) + user << "\red The generator already has a plasma tank loaded!" + return + P = O + user.drop_item() + O.loc = src + user << "\blue You add the plasma tank to the generator." + else if (istype(O, /obj/item/weapon/card/emag)) + emagged = 1 + emp_act(1) + else if(!active) + if(istype(O, /obj/item/weapon/wrench)) + anchored = !anchored + playsound(src.loc, 'Deconstruct.ogg', 50, 1) + if(anchored) + user << "\blue You secure the generator to the floor." + else + user << "\blue You unsecure the generator from the floor." + makepowernets() + else if(istype(O, /obj/item/weapon/screwdriver)) + open = !open + playsound(src.loc, 'Screwdriver.ogg', 50, 1) + if(open) + user << "\blue You open the access panel." + else + user << "\blue You close the access panel." + else if(istype(O, /obj/item/weapon/crowbar) && !open) + var/obj/machinery/constructable_frame/machine_frame/new_frame = new /obj/machinery/constructable_frame/machine_frame(src.loc) + for(var/obj/item/I in component_parts) + if(I.reliability < 100) + I.crit_fail = 1 + I.loc = src.loc + new_frame.state = 2 + new_frame.icon_state = "box_1" + del(src) + + attack_hand(mob/user as mob) + ..() + if (!anchored) + return + + interact(user) + + attack_ai(mob/user as mob) + interact(user) + + attack_paw(mob/user as mob) + interact(user) + + proc + interact(mob/user) + if (get_dist(src, user) > 1 ) + if (!istype(user, /mob/living/silicon/ai)) + user.machine = null + user << browse(null, "window=port_gen") + return + + user.machine = src + + var/dat = text("[name]
") + if (active) + dat += text("Generator: On
") + else + dat += text("Generator: Off
") + if(P) + dat += text("Currently loaded plasma tank: [P.air_contents.toxins]
") + else + dat += text("No plasma tank currently loaded.
") + dat += text("Power output: - [power_gen * power_output] +
") + dat += text("Heat: [heat]
") + dat += "
Close" + user << browse("[dat]", "window=port_gen") + + Topic(href, href_list) + if(..()) + return + + src.add_fingerprint(usr) + if(href_list["action"]) + if(href_list["action"] == "enable") + if(!active && HasFuel() && !crit_fail) + active = 1 + icon_state = "portgen1" + src.updateUsrDialog() + if(href_list["action"] == "disable") + if (active) + active = 0 + icon_state = "portgen0" + src.updateUsrDialog() + if(href_list["action"] == "lower_power") + if (power_output > 1) + power_output-- + src.updateUsrDialog() + if (href_list["action"] == "higher_power") + if (power_output < 4 || emagged) + power_output++ + src.updateUsrDialog() + if (href_list["action"] == "close") + usr << browse(null, "window=port_gen") + usr.machine = null diff --git a/code/modules/power/port_gen.dm b/code/modules/power/port_gen.dm index 6774671f16c..2ad21eb5cdc 100644 --- a/code/modules/power/port_gen.dm +++ b/code/modules/power/port_gen.dm @@ -327,4 +327,5 @@ display round(lastgen) and plasmatank amount time_per_coin = 60 board_path = "/obj/item/weapon/circuitboard/pacman/mrs" overheat() - explosion(src.loc, 4, 4, 4, -1) \ No newline at end of file + explosion(src.loc, 4, 4, 4, -1) + diff --git a/code/modules/projectiles/gun.dm b/code/modules/projectiles/gun.dm index 92ba2cb0c05..5c759614b59 100644 --- a/code/modules/projectiles/gun.dm +++ b/code/modules/projectiles/gun.dm @@ -37,6 +37,18 @@ for(var/obj/O in contents) O.emp_act(severity) + attack(mob/living/M as mob, mob/living/user as mob, def_zone) + if (M == user && user.zone_sel.selecting == "mouth" && load_into_chamber()) + M.visible_message("\red [user] sticks their gun in their mouth, ready to pull the trigger...") + if(!do_after(user, 40)) + M.visible_message("\blue [user] decided life was worth living") + return + M.visible_message("\red [user] pulls the trigger.") + M.apply_damage(70, BRUTE, "head") + M.apply_damage(110, BRUTE, "chest") + return + else + return ..() afterattack(atom/target as mob|obj|turf|area, mob/living/user as mob|obj, flag, params)//TODO: go over this if(flag) return //we're placing gun on a table or in backpack diff --git a/code/stylesheet.dm b/code/stylesheet.dm index 0cc4bfb71e9..077a64b60da 100644 --- a/code/stylesheet.dm +++ b/code/stylesheet.dm @@ -94,7 +94,8 @@ h1, h2, h3, h4, h5, h6 .comradio { - color: #ACA82D; + color:#FF9900; + text-decoration: underline; } .syndradio diff --git a/icons/mob/hud.dmi b/icons/mob/hud.dmi index 8fe609fbb67..e7425bb46c3 100644 Binary files a/icons/mob/hud.dmi and b/icons/mob/hud.dmi differ diff --git a/icons/mob/items_lefthand.dmi b/icons/mob/items_lefthand.dmi index 9f531da8f67..d0ca90f9951 100644 Binary files a/icons/mob/items_lefthand.dmi and b/icons/mob/items_lefthand.dmi differ diff --git a/icons/mob/items_righthand.dmi b/icons/mob/items_righthand.dmi index 386ce976595..66c6559e8c4 100644 Binary files a/icons/mob/items_righthand.dmi and b/icons/mob/items_righthand.dmi differ diff --git a/icons/obj/objects.dmi b/icons/obj/objects.dmi index 92e5d91196f..cf7cc1e2824 100644 Binary files a/icons/obj/objects.dmi and b/icons/obj/objects.dmi differ diff --git a/icons/obj/storage.dmi b/icons/obj/storage.dmi index 8f25d7e0a0e..fdcfb9c2057 100644 Binary files a/icons/obj/storage.dmi and b/icons/obj/storage.dmi differ diff --git a/icons/obj/tank.dmi b/icons/obj/tank.dmi index cc0e0bbcdb8..bc523dd9d20 100644 Binary files a/icons/obj/tank.dmi and b/icons/obj/tank.dmi differ diff --git a/maps/tgstation.2.0.8.dmm b/maps/tgstation.2.0.8.dmm index 36dfb2bc9a4..2dd2f14b94e 100644 --- a/maps/tgstation.2.0.8.dmm +++ b/maps/tgstation.2.0.8.dmm @@ -4870,7 +4870,7 @@ "bPH" = (/obj/machinery/door/firedoor/border_only,/obj/machinery/door/airlock/maintenance{name = "Assembly Line Maintenance"; req_access_txt = "12;29"},/turf/simulated/floor/plating,/area/assembly/assembly_line) "bPI" = (/obj/structure/table,/obj/item/device/multitool,/obj/item/weapon/crowbar,/obj/item/device/flash,/obj/item/device/flash,/obj/structure/disposalpipe/segment,/turf/simulated/floor,/area/assembly/assembly_line) "bPJ" = (/obj/structure/disposalpipe/trunk{dir = 1},/obj/machinery/disposal,/turf/simulated/floor,/area/assembly/assembly_line) -"bPK" = (/obj/structure/table,/obj/item/weapon/storage/firstaid/regular{empty = 1; name = "First-Aid (empty)"},/obj/item/weapon/storage/firstaid/regular{empty = 1; name = "First-Aid (empty)"},/obj/item/weapon/storage/firstaid/regular{empty = 1; name = "First-Aid (empty)"},/obj/item/device/healthanalyzer,/obj/item/device/healthanalyzer,/obj/item/device/healthanalyzer,/turf/simulated/floor,/area/assembly/assembly_line) +"bPK" = (/obj/structure/table,/obj/item/weapon/storage/firstaid/regular{empty = 1; name = "First-Aid (empty)"},/obj/item/weapon/storage/firstaid/regular{empty = 1; name = "First-Aid (empty)"},/obj/item/weapon/storage/firstaid/regular{empty = 1; name = "First-Aid (empty)"},/obj/item/device/healthanalyzer,/obj/item/device/healthanalyzer,/obj/item/device/healthanalyzer,/obj/item/weapon/reagent_containers/glass/beaker/tricordrazine,/obj/item/weapon/reagent_containers/glass/beaker/tricordrazine,/obj/item/weapon/reagent_containers/glass/beaker/tricordrazine,/turf/simulated/floor,/area/assembly/assembly_line) "bPL" = (/obj/structure/table,/obj/item/stack/sheet/glass{amount = 20},/obj/item/weapon/book/manual/robotics_cyborgs{pixel_y = 5},/turf/simulated/floor,/area/assembly/assembly_line) "bPM" = (/obj/machinery/computer/rdconsole{id = 2; name = "Robotics R&D Console"; req_access = null; req_access_txt = "29"},/turf/simulated/floor,/area/assembly/assembly_line) "bPN" = (/obj/item/device/assembly/prox_sensor{pixel_x = -8; pixel_y = 4},/obj/item/device/assembly/prox_sensor{pixel_x = -8; pixel_y = 4},/obj/item/device/flash,/obj/item/device/flash,/obj/structure/table,/turf/simulated/floor,/area/assembly/assembly_line)