diff --git a/code/__HELPERS/lists.dm b/code/__HELPERS/lists.dm
index b7caf86669..a1f13c18ab 100644
--- a/code/__HELPERS/lists.dm
+++ b/code/__HELPERS/lists.dm
@@ -30,6 +30,13 @@
return "[output][and_text][input[index]]"
+
+/proc/ConvertReqString2List(var/list/source_list)
+ var/list/temp_list = params2list(source_list)
+ for(var/O in temp_list)
+ temp_list[O] = text2num(temp_list[O])
+ return temp_list
+
//Returns list element or null. Should prevent "index out of bounds" error.
proc/listgetindex(var/list/list,index)
if(istype(list) && list.len)
diff --git a/code/game/machinery/OpTable.dm b/code/game/machinery/OpTable.dm
index b01b0bbda6..6e1ecdf4ca 100644
--- a/code/game/machinery/OpTable.dm
+++ b/code/game/machinery/OpTable.dm
@@ -105,6 +105,16 @@
else
icon_state = "table2-idle"
+/obj/machinery/optable/MouseDrop_T(mob/target, mob/user)
+
+ var/mob/living/M = user
+ if(user.stat || user.restrained() || !check_table(user) || !iscarbon(target))
+ return
+ if(istype(M))
+ take_victim(target,user)
+ else
+ return ..()
+
/obj/machinery/optable/verb/climb_on()
set name = "Climb On Table"
set category = "Object"
diff --git a/code/game/machinery/kitchen/microwave.dm b/code/game/machinery/kitchen/microwave.dm
index fbdcfd2760..fe75dff633 100644
--- a/code/game/machinery/kitchen/microwave.dm
+++ b/code/game/machinery/kitchen/microwave.dm
@@ -135,11 +135,12 @@
return 1
else
user << "\red You have no idea what you can cook with this [O]."
- return 1
+ ..()
src.updateUsrDialog()
/obj/machinery/microwave/attack_ai(mob/user as mob)
- return 0
+ if(istype(user, /mob/living/silicon/robot) && Adjacent(user))
+ attack_hand(user)
/obj/machinery/microwave/attack_hand(mob/user as mob)
user.set_machine(src)
diff --git a/code/game/machinery/kitchen/smartfridge.dm b/code/game/machinery/kitchen/smartfridge.dm
index 1b1bb9bfb5..f4e910a47d 100644
--- a/code/game/machinery/kitchen/smartfridge.dm
+++ b/code/game/machinery/kitchen/smartfridge.dm
@@ -244,7 +244,7 @@
..()
/obj/machinery/smartfridge/attack_ai(mob/user as mob)
- return 0
+ attack_hand(user)
/obj/machinery/smartfridge/attack_hand(mob/user as mob)
if(stat & (NOPOWER|BROKEN))
diff --git a/code/game/machinery/vending.dm b/code/game/machinery/vending.dm
index 88819e492f..794fb0a887 100644
--- a/code/game/machinery/vending.dm
+++ b/code/game/machinery/vending.dm
@@ -479,17 +479,6 @@
if ((usr.contents.Find(src) || (in_range(src, usr) && istype(src.loc, /turf))))
if ((href_list["vend"]) && (src.vend_ready) && (!currently_vending))
-
- if(istype(usr,/mob/living/silicon))
- if(istype(usr,/mob/living/silicon/robot))
- var/mob/living/silicon/robot/R = usr
- if(!(R.module && istype(R.module,/obj/item/weapon/robot_module/butler) ))
- usr << "\red The vending machine refuses to interface with you, as you are not in its target demographic!"
- return
- else
- usr << "\red The vending machine refuses to interface with you, as you are not in its target demographic!"
- return
-
if((!allowed(usr)) && !emagged && scan_id) //For SECURE VENDING MACHINES YEAH
usr << "Access denied." //Unless emagged of course
flick(icon_deny,src)
@@ -504,6 +493,9 @@
if(R.price <= 0)
src.vend(R, usr)
+ else if(istype(usr,/mob/living/silicon)) //If the item is not free, provide feedback if a synth is trying to buy something.
+ usr << "Artificial unit recognized. Artificial units cannot complete this transaction. Purchase canceled."
+ return
else
src.currently_vending = R
if(!vendor_account || vendor_account.suspended)
diff --git a/code/game/objects/items/robot/robot_parts.dm b/code/game/objects/items/robot/robot_parts.dm
index 9c262243c6..da508a8a31 100644
--- a/code/game/objects/items/robot/robot_parts.dm
+++ b/code/game/objects/items/robot/robot_parts.dm
@@ -291,21 +291,14 @@
..()
if(istype(W, /obj/item/device/flash))
if(istype(user,/mob/living/silicon/robot))
- user << "\red How do you propose to do that?"
- return
- else if(src.flash1 && src.flash2)
- user << "\blue You have already inserted the eyes!"
- return
- else if(src.flash1)
- user.drop_item()
- W.loc = src
- src.flash2 = W
- user << "\blue You insert the flash into the eye socket!"
+ var/current_module = user.get_active_hand()
+ if(current_module == W)
+ user << "How do you propose to do that?"
+ return
+ else
+ add_flashes(W,user)
else
- user.drop_item()
- W.loc = src
- src.flash1 = W
- user << "\blue You insert the flash into the eye socket!"
+ add_flashes(W,user)
else if(istype(W, /obj/item/weapon/stock_parts/manipulator))
user << "\blue You install some manipulators and modify the head, creating a functional spider-bot!"
new /mob/living/simple_animal/spiderbot(get_turf(loc))
@@ -315,6 +308,22 @@
return
return
+/obj/item/robot_parts/head/proc/add_flashes(obj/item/W as obj, mob/user as mob) //Made into a seperate proc to avoid copypasta
+ if(src.flash1 && src.flash2)
+ user << "You have already inserted the eyes!"
+ return
+ else if(src.flash1)
+ user.drop_item()
+ W.loc = src
+ src.flash2 = W
+ user << "You insert the flash into the eye socket!"
+ else
+ user.drop_item()
+ W.loc = src
+ src.flash1 = W
+ user << "You insert the flash into the eye socket!"
+
+
/obj/item/robot_parts/attackby(obj/item/W as obj, mob/user as mob)
if(istype(W,/obj/item/weapon/card/emag))
if(sabotaged)
diff --git a/code/game/objects/items/stacks/matter_synth.dm b/code/game/objects/items/stacks/matter_synth.dm
index 0842f70d66..3483dfbc61 100644
--- a/code/game/objects/items/stacks/matter_synth.dm
+++ b/code/game/objects/items/stacks/matter_synth.dm
@@ -28,6 +28,9 @@
/datum/matter_synth/medicine
name = "Medicine Synthesizer"
+/datum/matter_synth/nanite
+ name = "Nanite Synthesizer"
+
/datum/matter_synth/metal
name = "Metal Synthesizer"
diff --git a/code/game/objects/items/weapons/RSF.dm b/code/game/objects/items/weapons/RSF.dm
index 596675a094..d3dc598cc3 100644
--- a/code/game/objects/items/weapons/RSF.dm
+++ b/code/game/objects/items/weapons/RSF.dm
@@ -54,14 +54,9 @@ RSF
user << "Changed dispensing mode to 'Dice Pack'"
return
if (mode == 5)
- mode = 6
+ mode = 1
user << "Changed dispensing mode to 'Cigarette'"
return
- if (mode == 6)
- mode = 1
- user << "Changed dispensing mode to 'Dosh'"
- return
- // Change mode
/obj/item/weapon/rsf/afterattack(atom/A, mob/user as mob, proximity)
@@ -84,8 +79,8 @@ RSF
switch(mode)
if(1)
- product = new /obj/item/weapon/spacecash/c10()
- used_energy = 200
+ product = new /obj/item/clothing/mask/smokable/cigarette()
+ used_energy = 10
if(2)
product = new /obj/item/weapon/reagent_containers/food/drinks/drinkingglass()
used_energy = 50
@@ -98,9 +93,6 @@ RSF
if(5)
product = new /obj/item/weapon/storage/pill_bottle/dice()
used_energy = 200
- if(6)
- product = new /obj/item/clothing/mask/smokable/cigarette()
- used_energy = 10
user << "Dispensing [product ? product : "product"]..."
product.loc = get_turf(A)
diff --git a/code/game/objects/structures/crates_lockers/closets.dm b/code/game/objects/structures/crates_lockers/closets.dm
index 40163e7c78..08abff9c2b 100644
--- a/code/game/objects/structures/crates_lockers/closets.dm
+++ b/code/game/objects/structures/crates_lockers/closets.dm
@@ -249,6 +249,10 @@
src.add_fingerprint(user)
return
+/obj/structure/closet/attack_ai(mob/user)
+ if(istype(user, /mob/living/silicon/robot) && Adjacent(user)) // Robots can open/close it, but not the AI.
+ attack_hand(user)
+
/obj/structure/closet/relaymove(mob/user as mob)
if(user.stat || !isturf(src.loc))
return
diff --git a/code/global.dm b/code/global.dm
index c7a1738127..86386e6b0e 100644
--- a/code/global.dm
+++ b/code/global.dm
@@ -231,7 +231,8 @@ var/list/cheartstopper = list("potassium_chloride") // Thi
// Used by robots and robot preferences.
var/list/robot_module_types = list(
"Standard", "Engineering", "Construction", "Surgeon", "Crisis",
- "Miner", "Janitor", "Service", "Clerical", "Security"
+ "Miner", "Janitor", "Service", "Clerical", "Security",
+ "Research"
)
// Some scary sounds.
@@ -264,4 +265,4 @@ var/global/obj/item/device/radio/intercom/global_announcer = new(null)
var/list/station_departments = list("Command", "Medical", "Engineering", "Science", "Security", "Cargo", "Civilian")
var/global/const/TICKS_IN_DAY = 864000
-var/global/const/TICKS_IN_SECOND = 10
\ No newline at end of file
+var/global/const/TICKS_IN_SECOND = 10
diff --git a/code/modules/mob/living/silicon/robot/drone/drone_items.dm b/code/modules/mob/living/silicon/robot/drone/drone_items.dm
index 68df16d020..8353972ba2 100644
--- a/code/modules/mob/living/silicon/robot/drone/drone_items.dm
+++ b/code/modules/mob/living/silicon/robot/drone/drone_items.dm
@@ -2,10 +2,12 @@
//Limited use.
/obj/item/weapon/gripper
name = "magnetic gripper"
- desc = "A simple grasping tool for synthetic assets."
+ desc = "A simple grasping tool specialized in construction and engineering work."
icon = 'icons/obj/device.dmi'
icon_state = "gripper"
+ flags = NOBLUDGEON
+
//Has a list of items that it can hold.
var/list/can_hold = list(
/obj/item/weapon/cell,
@@ -28,8 +30,14 @@
var/obj/item/wrapped = null // Item currently being held.
+ var/force_holder = null //
+
// VEEEEERY limited version for mining borgs. Basically only for swapping cells and upgrading the drills.
/obj/item/weapon/gripper/miner
+ name = "drill maintenance gripper"
+ desc = "A simple grasping tool for the maintenance of heavy drilling machines."
+ icon_state = "gripper-mining"
+
can_hold = list(
/obj/item/weapon/cell,
/obj/item/weapon/stock_parts
@@ -38,14 +46,58 @@
/obj/item/weapon/gripper/paperwork
name = "paperwork gripper"
desc = "A simple grasping tool for clerical work."
- icon = 'icons/obj/device.dmi'
- icon_state = "gripper"
can_hold = list(
/obj/item/weapon/clipboard,
/obj/item/weapon/paper,
/obj/item/weapon/paper_bundle,
- /obj/item/weapon/card/id
+ /obj/item/weapon/card/id,
+ /obj/item/weapon/book,
+ /obj/item/weapon/newspaper
+ )
+
+/obj/item/weapon/gripper/research //A general usage gripper, used for toxins/robotics/xenobio/etc
+ name = "scientific gripper"
+ icon_state = "gripper-sci"
+ desc = "A simple grasping tool suited to assist in a wide array of research applications."
+
+ can_hold = list(
+ /obj/item/weapon/cell,
+ /obj/item/weapon/stock_parts,
+ /obj/item/device/mmi,
+ /obj/item/robot_parts,
+ /obj/item/borg/upgrade,
+ /obj/item/device/flash, //to build borgs
+ /obj/item/organ/brain, //to insert into MMIs.
+ /obj/item/stack/cable_coil, //again, for borg building
+ /obj/item/weapon/circuitboard,
+ /obj/item/slime_extract,
+ /obj/item/weapon/reagent_containers/glass,
+ /obj/item/weapon/reagent_containers/food/snacks/monkeycube
+
+ )
+
+/obj/item/weapon/gripper/service //Used to handle food, drinks, and seeds.
+ name = "service gripper"
+ icon_state = "gripper"
+ desc = "A simple grasping tool used to perform tasks in the service sector, such as handling food, drinks, and seeds."
+
+ can_hold = list(
+ /obj/item/weapon/reagent_containers/glass,
+ /obj/item/weapon/reagent_containers/food,
+ /obj/item/seeds,
+ /obj/item/weapon/grown
+ )
+
+/obj/item/weapon/gripper/no_use //Used when you want to hold and put items in other things, but not able to 'use' the item
+
+/obj/item/weapon/gripper/no_use/loader //This is used to disallow building with metal.
+ name = "sheet loader"
+ desc = "A specialized loading device, designed to pick up and insert sheets of materials inside machines."
+ icon_state = "gripper-sheet"
+
+ can_hold = list(
+ /obj/item/stack/sheet
)
/obj/item/weapon/gripper/attack_self(mob/user as mob)
@@ -53,6 +105,9 @@
return wrapped.attack_self(user)
return ..()
+/obj/item/weapon/gripper/no_use/attack_self(mob/user as mob)
+ return
+
/obj/item/weapon/gripper/verb/drop_item()
set name = "Drop Item"
@@ -75,7 +130,12 @@
//update_icon()
/obj/item/weapon/gripper/attack(mob/living/carbon/M as mob, mob/living/carbon/user as mob)
- return (wrapped ? wrapped.attack(M,user) : 0)
+ if(wrapped) //The force of the wrapped obj gets set to zero during the attack() and afterattack().
+ force_holder = wrapped.force
+ wrapped.force = 0.0
+ wrapped.attack(M,user)
+ return 1
+ return 0
/obj/item/weapon/gripper/afterattack(var/atom/target, var/mob/living/user, proximity, params)
@@ -97,6 +157,9 @@
if(!resolved && wrapped && target)
wrapped.afterattack(target,user,1)
+ //wrapped's force was set to zero. This resets it to the value it had before.
+ wrapped.force = force_holder
+ force_holder = null
//If wrapped was neither deleted nor put into target, put it back into the gripper.
if(wrapped && user && (wrapped.loc == user))
wrapped.loc = src
@@ -145,6 +208,21 @@
user.visible_message("[user] removes the power cell from [A]!", "You remove the power cell.")
+ else if(istype(target,/mob/living/silicon/robot))
+ var/mob/living/silicon/robot/A = target
+ if(A.opened)
+ if(A.cell)
+
+ wrapped = A.cell
+
+ A.cell.add_fingerprint(user)
+ A.cell.updateicon()
+ A.updateicon()
+ A.cell.loc = src
+ A.cell = null
+
+ user.visible_message("[user] removes the power cell from [A]!", "You remove the power cell.")
+
//TODO: Matter decompiler.
/obj/item/weapon/matter_decompiler
diff --git a/code/modules/mob/living/silicon/robot/robot.dm b/code/modules/mob/living/silicon/robot/robot.dm
index 5ff1c23213..cab055696d 100644
--- a/code/modules/mob/living/silicon/robot/robot.dm
+++ b/code/modules/mob/living/silicon/robot/robot.dm
@@ -265,7 +265,8 @@
module_sprites["Bro"] = "Brobot"
module_sprites["Rich"] = "maximillion"
module_sprites["Default"] = "Service2"
- module_sprites["Drone"] = "drone-service" // How does this even work...? Oh well.
+ module_sprites["Drone - Service"] = "drone-service"
+ module_sprites["Drone - Hydro"] = "drone-hydro"
if("Clerical")
module = new /obj/item/weapon/robot_module/clerical(src)
@@ -277,6 +278,12 @@
module_sprites["Default"] = "Service2"
module_sprites["Drone"] = "drone-service"
+ if("Research")
+ module = new /obj/item/weapon/robot_module/research(src)
+ module.channels = list("Science" = 1)
+ module_sprites["Droid"] = "droid-science"
+ module_sprites["Drone"] = "drone-science"
+
if("Miner")
module = new /obj/item/weapon/robot_module/miner(src)
module.channels = list("Supply" = 1)
@@ -296,7 +303,8 @@
module_sprites["Standard"] = "surgeon"
module_sprites["Advanced Droid"] = "droid-medical"
module_sprites["Needles"] = "medicalrobot"
- module_sprites["Drone" ] = "drone-medical"
+ module_sprites["Drone - Medical" ] = "drone-medical"
+ module_sprites["Drone - Chemistry" ] = "drone-chemistry"
if("Surgeon")
module = new /obj/item/weapon/robot_module/surgeon(src)
@@ -731,7 +739,7 @@
else
user << "Unable to locate a radio."
- else if (istype(W, /obj/item/weapon/card/id)||istype(W, /obj/item/device/pda)) // trying to unlock the interface with an ID card
+ else if (istype(W, /obj/item/weapon/card/id)||istype(W, /obj/item/device/pda)||istype(W, /obj/item/weapon/card/robot)) // trying to unlock the interface with an ID card
if(emagged)//still allow them to open the cover
user << "The interface seems slightly damaged"
if(opened)
@@ -868,6 +876,10 @@
//if they are holding or wearing a card that has access, that works
if(check_access(H.get_active_hand()) || check_access(H.wear_id))
return 1
+ else if(istype(M, /mob/living/silicon/robot))
+ var/mob/living/silicon/robot/R = M
+ if(check_access(R.get_active_hand()) || istype(R.get_active_hand(), /obj/item/weapon/card/robot))
+ return 1
return 0
/mob/living/silicon/robot/proc/check_access(obj/item/weapon/card/id/I)
diff --git a/code/modules/mob/living/silicon/robot/robot_items.dm b/code/modules/mob/living/silicon/robot/robot_items.dm
index 0d40f0954a..d18ca506cc 100644
--- a/code/modules/mob/living/silicon/robot/robot_items.dm
+++ b/code/modules/mob/living/silicon/robot/robot_items.dm
@@ -1,3 +1,138 @@
+//A portable analyzer, for research borgs. This is better then giving them a gripper which can hold anything and letting them use the normal analyzer.
+/obj/item/weapon/portable_destructive_analyzer
+ name = "Portable Destructive Analyzer"
+ icon = 'icons/obj/items.dmi'
+ icon_state = "portable_analyzer"
+ desc = "Similar to the stationary version, this rather unwieldy device allows you to break down objects in the name of science."
+
+ var/min_reliability = 90 //Can't upgrade, call it laziness or a drawback
+
+ var/datum/research/techonly/files //The device uses the same datum structure as the R&D computer/server.
+ //This analyzer can only store tech levels, however.
+
+ var/obj/item/weapon/loaded_item //What is currently inside the analyzer.
+
+/obj/item/weapon/portable_destructive_analyzer/New()
+ ..()
+ files = new /datum/research/techonly(src) //Setup the research data holder.
+
+/obj/item/weapon/portable_destructive_analyzer/attack_self(user as mob)
+ var/response = alert(user, "Analyzing the item inside will *DESTROY* the item for good.\n\
+ Syncing to the research server will send the data that is stored inside to research.\n\
+ Ejecting will place the loaded item onto the floor.",
+ "What would you like to do?", "Analyze", "Sync", "Eject")
+ if(response == "Analyze")
+ if(loaded_item)
+ var/confirm = alert(user, "This will destroy the item inside forever. Are you sure?","Confirm Analyze","Yes","No")
+ if(confirm == "Yes") //This is pretty copypasta-y
+ user << "You activate the analyzer's microlaser, analyzing \the [loaded_item] and breaking it down."
+ flick("portable_analyzer_scan", src)
+ playsound(src.loc, 'sound/items/Welder2.ogg', 50, 1)
+ if(loaded_item.reliability >= min_reliability)
+ var/list/temp_tech = ConvertReqString2List(loaded_item.origin_tech)
+ for(var/T in temp_tech)
+ files.UpdateTech(T, temp_tech[T])
+ user << "\The [loaded_item] had level [temp_tech[T]] in [T]."
+ loaded_item = null
+ for(var/obj/I in contents)
+ for(var/mob/M in I.contents)
+ M.death()
+ if(istype(I,/obj/item/stack/sheet))//Only deconsturcts one sheet at a time instead of the entire stack
+ var/obj/item/stack/sheet/S = I
+ if(S.get_amount() > 1)
+ S.use(1)
+ loaded_item = S
+ else
+ del(S)
+ desc = initial(desc)
+ icon_state = initial(icon_state)
+ else
+ del(I)
+ desc = initial(desc)
+ icon_state = initial(icon_state)
+ else
+ return
+ else
+ user << "The [src] is empty. Put something inside it first."
+ if(response == "Sync")
+ var/success = 0
+ for(var/obj/machinery/r_n_d/server/S in machines)
+ if(S.disabled)
+ continue
+ for(var/datum/tech/T in files.known_tech) //Uploading
+ S.files.AddTech2Known(T)
+ for(var/datum/tech/T in S.files.known_tech) //Downloading
+ files.AddTech2Known(T)
+ success = 1
+ files.RefreshResearch()
+ if(success)
+ user << "You connect to the research server, push your data upstream to it, then pull the resulting merged data from the master branch."
+ playsound(src.loc, 'sound/machines/twobeep.ogg', 50, 1)
+ else
+ user << "Reserch server ping response timed out. Unable to connect. Please contact the system administrator."
+ playsound(src.loc, 'sound/machines/buzz-two.ogg', 50, 1)
+ if(response == "Eject")
+ if(loaded_item)
+ loaded_item.loc = get_turf(src)
+ desc = initial(desc)
+ icon_state = initial(icon_state)
+ loaded_item = null
+ else
+ user << "The [src] is already empty."
+
+
+/obj/item/weapon/portable_destructive_analyzer/afterattack(var/atom/target, var/mob/living/user, proximity)
+ if(!target)
+ return
+ if(!proximity)
+ return
+ if(!isturf(target.loc)) // Don't load up stuff if it's inside a container or mob!
+ return
+ if(istype(target,/obj/item))
+ if(loaded_item)
+ user << "Your [src] already has something inside. Analyze or eject it first."
+ return
+ var/obj/item/I = target
+ I.loc = src
+ loaded_item = I
+ for(var/mob/M in viewers())
+ M.show_message(text("[user] adds the [I] to the [src]."), 1)
+ desc = initial(desc) + "
It is holding \the [loaded_item]."
+ flick("portable_analyzer_load", src)
+ icon_state = "portable_analyzer_full"
+
+//This is used to unlock other borg covers.
+/obj/item/weapon/card/robot //This is not a child of id cards, as to avoid dumb typechecks on computers.
+ name = "access code transmission device"
+ icon_state = "id-robot"
+ desc = "A circuit grafted onto the bottom of an ID card. It is used to transmit access codes into other robot chassis, \
+ allowing you to lock and unlock other robots' panels."
+
+/obj/item/weapon/card/id/robot/attack_self() //override so borgs can't flash their IDs.
+ return
+
+/obj/item/weapon/card/id/robot/read()
+ usr << "The ID card does not appear to have any writing on it."
+ return
+
+//A harvest item for serviceborgs.
+/obj/item/weapon/robot_harvester
+ name = "auto harvester"
+ desc = "A hand-held harvest tool that resembles a sickle. It uses energy to cut plant matter very efficently."
+ icon = 'icons/obj/weapons.dmi'
+ icon_state = "autoharvester"
+
+/obj/item/weapon/robot_harvester/afterattack(var/atom/target, var/mob/living/user, proximity)
+ if(!target)
+ return
+ if(!proximity)
+ return
+ if(istype(target,/obj/machinery/portable_atmospherics/hydroponics))
+ var/obj/machinery/portable_atmospherics/hydroponics/T = target
+ T.harvest(user)
+ else
+ user << "Harvesting \a [target] is not the purpose of this tool. The [src] is for plants being grown."
+
// A special tray for the service droid. Allow droid to pick up and drop items as if they were using the tray normally
// Click on table to unload, click on item to load. Otherwise works identically to a tray.
// Unlike the base item "tray", robotrays ONLY pick up food, drinks and condiments.
diff --git a/code/modules/mob/living/silicon/robot/robot_modules.dm b/code/modules/mob/living/silicon/robot/robot_modules.dm
index 12565f4ea4..418860c0e1 100644
--- a/code/modules/mob/living/silicon/robot/robot_modules.dm
+++ b/code/modules/mob/living/silicon/robot/robot_modules.dm
@@ -314,8 +314,13 @@
/obj/item/weapon/robot_module/butler/New()
..()
src.modules += new /obj/item/device/flash(src)
- src.modules += new /obj/item/weapon/reagent_containers/food/drinks/cans/beer(src)
- src.modules += new /obj/item/weapon/reagent_containers/food/condiment/enzyme(src)
+ src.modules += new /obj/item/weapon/gripper/service(src)
+ src.modules += new /obj/item/weapon/reagent_containers/glass/bucket(src)
+ src.modules += new /obj/item/weapon/minihoe(src)
+ src.modules += new /obj/item/weapon/hatchet(src)
+ src.modules += new /obj/item/device/analyzer/plant_analyzer(src)
+ src.modules += new /obj/item/weapon/storage/bag/plants(src)
+ src.modules += new /obj/item/weapon/robot_harvester(src)
var/obj/item/weapon/rsf/M = new /obj/item/weapon/rsf(src)
M.stored_matter = 30
@@ -358,6 +363,7 @@
src.modules += new /obj/item/weapon/pen/robopen(src)
src.modules += new /obj/item/weapon/form_printer(src)
src.modules += new /obj/item/weapon/gripper/paperwork(src)
+ src.modules += new /obj/item/weapon/hand_labeler(src)
src.emag = new /obj/item/weapon/stamp/denied(src)
/obj/item/weapon/robot_module/clerical/add_languages(var/mob/living/silicon/robot/R)
@@ -395,6 +401,38 @@
src.emag = new /obj/item/weapon/pickaxe/plasmacutter(src)
return
+/obj/item/weapon/robot_module/research
+ name = "research module"
+
+/obj/item/weapon/robot_module/research/New()
+ ..()
+ src.modules += new /obj/item/device/flash(src)
+ src.modules += new /obj/item/weapon/portable_destructive_analyzer(src)
+ src.modules += new /obj/item/weapon/gripper/research(src)
+ src.modules += new /obj/item/weapon/gripper/no_use/loader(src)
+ src.modules += new /obj/item/device/robotanalyzer(src)
+ src.modules += new /obj/item/weapon/card/robot(src)
+ src.modules += new /obj/item/weapon/wrench(src)
+ src.modules += new /obj/item/weapon/screwdriver(src)
+ src.modules += new /obj/item/weapon/crowbar(src)
+ src.modules += new /obj/item/weapon/scalpel(src)
+ src.modules += new /obj/item/weapon/circular_saw(src)
+ src.modules += new /obj/item/weapon/extinguisher/mini(src)
+ src.modules += new /obj/item/weapon/reagent_containers/syringe(src)
+ src.modules += new /obj/item/weapon/reagent_containers/glass/beaker/large(src)
+ src.emag = new /obj/item/weapon/hand_tele(src)
+
+ var/datum/matter_synth/nanite = new /datum/matter_synth/nanite(10000)
+ synths += nanite
+
+ var/obj/item/stack/nanopaste/N = new /obj/item/stack/nanopaste(src)
+ N.uses_charge = 1
+ N.charge_costs = list(1000)
+ N.synths = list(nanite)
+ src.modules += N
+
+ return
+
/obj/item/weapon/robot_module/syndicate
name = "illegal robot module"
diff --git a/code/modules/research/circuitprinter.dm b/code/modules/research/circuitprinter.dm
index a16e5653a9..e1e63c08dc 100644
--- a/code/modules/research/circuitprinter.dm
+++ b/code/modules/research/circuitprinter.dm
@@ -104,46 +104,51 @@ using metal and glass, it uses glass and reagents (usually sulfuric acis).
return 1
if(O.is_open_container())
return 0
- if(!istype(O, /obj/item/stack/sheet/glass) && !istype(O, /obj/item/stack/sheet/mineral/gold) && !istype(O, /obj/item/stack/sheet/mineral/diamond) && !istype(O, /obj/item/stack/sheet/mineral/uranium))
- user << "You cannot insert this item into \the [src]!"
- return 1
+// if(!istype(O, /obj/item/stack/sheet/glass) && !istype(O, /obj/item/stack/sheet/mineral/gold) && !istype(O, /obj/item/stack/sheet/mineral/diamond) && !istype(O, /obj/item/stack/sheet/mineral/uranium))
+// user << "You cannot insert this item into \the [src]!"
+// return 1
if(stat)
return 1
if(busy)
user << "\The [src] is busy. Please wait for completion of previous operation."
return 1
- var/obj/item/stack/sheet/stack = O
- if((TotalMaterials() + stack.perunit) > max_material_amount)
- user << "\The [src] is full. Please remove glass from \the [src] in order to insert more."
- return 1
- var/amount = round(input("How many sheets do you want to add?") as num)
- if(amount < 0)
- amount = 0
- if(amount == 0)
- return
- if(amount > stack.amount)
- amount = min(stack.amount, round((max_material_amount - TotalMaterials()) / stack.perunit))
+ if(istype(O, /obj/item/stack/sheet/glass) || istype(O, /obj/item/stack/sheet/mineral/gold) || istype(O, /obj/item/stack/sheet/mineral/diamond) || istype(O, /obj/item/stack/sheet/mineral/uranium))
- busy = 1
- use_power(max(1000, (3750 * amount / 10)))
- var/stacktype = stack.type
- stack.use(amount)
- if(do_after(usr, 16))
- user << "You add [amount] sheets to \the [src]."
- switch(stacktype)
- if(/obj/item/stack/sheet/glass)
- g_amount += amount * 3750
- if(/obj/item/stack/sheet/mineral/gold)
- gold_amount += amount * 2000
- if(/obj/item/stack/sheet/mineral/diamond)
- diamond_amount += amount * 2000
- if(/obj/item/stack/sheet/mineral/uranium)
- uranium_amount += amount * 2000
- else
- new stacktype(loc, amount)
- busy = 0
- updateUsrDialog()
+ var/obj/item/stack/sheet/stack = O
+ if((TotalMaterials() + stack.perunit) > max_material_amount)
+ user << "\The [src] is full. Please remove glass from \the [src] in order to insert more."
+ return 1
+
+ var/amount = round(input("How many sheets do you want to add?") as num)
+ if(amount < 0)
+ amount = 0
+ if(amount == 0)
+ return
+ if(amount > stack.amount)
+ amount = min(stack.amount, round((max_material_amount - TotalMaterials()) / stack.perunit))
+
+ busy = 1
+ use_power(max(1000, (3750 * amount / 10)))
+ var/stacktype = stack.type
+ stack.use(amount)
+ if(do_after(usr, 16))
+ user << "You add [amount] sheets to \the [src]."
+ switch(stacktype)
+ if(/obj/item/stack/sheet/glass)
+ g_amount += amount * 3750
+ if(/obj/item/stack/sheet/mineral/gold)
+ gold_amount += amount * 2000
+ if(/obj/item/stack/sheet/mineral/diamond)
+ diamond_amount += amount * 2000
+ if(/obj/item/stack/sheet/mineral/uranium)
+ uranium_amount += amount * 2000
+ else
+ new stacktype(loc, amount)
+ busy = 0
+ updateUsrDialog()
+
+ ..()
//This is to stop these machines being hackable via clicking.
/obj/machinery/r_n_d/circuit_imprinter/attack_hand(mob/user as mob)
diff --git a/code/modules/research/destructive_analyzer.dm b/code/modules/research/destructive_analyzer.dm
index 7b7445f099..3fc97cc6ab 100644
--- a/code/modules/research/destructive_analyzer.dm
+++ b/code/modules/research/destructive_analyzer.dm
@@ -13,7 +13,7 @@ Note: Must be placed within 3 tiles of the R&D Console
var/obj/item/weapon/loaded_item = null
var/decon_mod = 1
var/min_reliability = 90
-
+
use_power = 1
idle_power_usage = 30
active_power_usage = 2500
@@ -38,12 +38,6 @@ Note: Must be placed within 3 tiles of the R&D Console
del(src)
return
-/obj/machinery/r_n_d/destructive_analyzer/proc/ConvertReqString2List(var/list/source_list)
- var/list/temp_list = params2list(source_list)
- for(var/O in temp_list)
- temp_list[O] = text2num(temp_list[O])
- return temp_list
-
/obj/machinery/r_n_d/destructive_analyzer/update_icon()
if(panel_open)
icon_state = "d_analyzer_t"
diff --git a/code/modules/research/protolathe.dm b/code/modules/research/protolathe.dm
index 22df4b82dd..06f3f7b760 100644
--- a/code/modules/research/protolathe.dm
+++ b/code/modules/research/protolathe.dm
@@ -116,9 +116,6 @@ Note: Must be placed west/left of and R&D console to function.
if(busy)
user << "\The [src] is busy. Please wait for completion of previous operation."
return 1
- if(!istype(O, /obj/item/stack/sheet))
- user << "You cannot insert this item into \the [src]!"
- return 1
if(stat)
return 1
if(istype(O,/obj/item/stack/sheet))
@@ -127,51 +124,52 @@ Note: Must be placed west/left of and R&D console to function.
user << "\The [src]'s material bin is full. Please remove material before adding more."
return 1
- var/obj/item/stack/sheet/stack = O
- var/amount = round(input("How many sheets do you want to add?") as num)//No decimals
- if(!O)
- return
- if(amount < 0)//No negative numbers
- amount = 0
- if(amount == 0)
- return
- if(amount > stack.get_amount())
- amount = stack.get_amount()
- if(max_material_storage - TotalMaterials() < (amount * stack.perunit))//Can't overfill
- amount = min(stack.amount, round((max_material_storage - TotalMaterials()) / stack.perunit))
+ var/obj/item/stack/sheet/stack = O
+ var/amount = round(input("How many sheets do you want to add?") as num)//No decimals
+ if(!O)
+ return
+ if(amount < 0)//No negative numbers
+ amount = 0
+ if(amount == 0)
+ return
+ if(amount > stack.get_amount())
+ amount = stack.get_amount()
+ if(max_material_storage - TotalMaterials() < (amount * stack.perunit))//Can't overfill
+ amount = min(stack.amount, round((max_material_storage - TotalMaterials()) / stack.perunit))
- overlays += "protolathe_[stack.name]"
- sleep(10)
- overlays -= "protolathe_[stack.name]"
+ overlays += "protolathe_[stack.name]"
+ sleep(10)
+ overlays -= "protolathe_[stack.name]"
- icon_state = "protolathe"
- busy = 1
- use_power(max(1000, (3750 * amount / 10)))
- var/stacktype = stack.type
- stack.use(amount)
- if(do_after(user, 16))
- user << "You add [amount] sheets to \the [src]."
icon_state = "protolathe"
- switch(stacktype)
- if(/obj/item/stack/sheet/metal)
- m_amount += amount * 3750
- if(/obj/item/stack/sheet/glass)
- g_amount += amount * 3750
- if(/obj/item/stack/sheet/mineral/gold)
- gold_amount += amount * 2000
- if(/obj/item/stack/sheet/mineral/silver)
- silver_amount += amount * 2000
- if(/obj/item/stack/sheet/mineral/phoron)
- phoron_amount += amount * 2000
- if(/obj/item/stack/sheet/mineral/uranium)
- uranium_amount += amount * 2000
- if(/obj/item/stack/sheet/mineral/diamond)
- diamond_amount += amount * 2000
- else
- new stacktype(loc, amount)
- busy = 0
- updateUsrDialog()
- return
+ busy = 1
+ use_power(max(1000, (3750 * amount / 10)))
+ var/stacktype = stack.type
+ stack.use(amount)
+ if(do_after(user, 16))
+ user << "You add [amount] sheets to \the [src]."
+ icon_state = "protolathe"
+ switch(stacktype)
+ if(/obj/item/stack/sheet/metal)
+ m_amount += amount * 3750
+ if(/obj/item/stack/sheet/glass)
+ g_amount += amount * 3750
+ if(/obj/item/stack/sheet/mineral/gold)
+ gold_amount += amount * 2000
+ if(/obj/item/stack/sheet/mineral/silver)
+ silver_amount += amount * 2000
+ if(/obj/item/stack/sheet/mineral/phoron)
+ phoron_amount += amount * 2000
+ if(/obj/item/stack/sheet/mineral/uranium)
+ uranium_amount += amount * 2000
+ if(/obj/item/stack/sheet/mineral/diamond)
+ diamond_amount += amount * 2000
+ else
+ new stacktype(loc, amount)
+ busy = 0
+ updateUsrDialog()
+ return
+ ..()
//This is to stop these machines being hackable via clicking.
/obj/machinery/r_n_d/protolathe/attack_hand(mob/user as mob)
diff --git a/code/modules/research/rdconsole.dm b/code/modules/research/rdconsole.dm
index 1ad86378b0..89e31574d2 100644
--- a/code/modules/research/rdconsole.dm
+++ b/code/modules/research/rdconsole.dm
@@ -256,7 +256,7 @@ won't update every console in existence) but it's more of a hassle to do. Also,
screen = 1.0
return
if(linked_destroy.loaded_item.reliability >= linked_destroy.min_reliability)
- var/list/temp_tech = linked_destroy.ConvertReqString2List(linked_destroy.loaded_item.origin_tech)
+ var/list/temp_tech = ConvertReqString2List(linked_destroy.loaded_item.origin_tech)
for(var/T in temp_tech)
files.UpdateTech(T, temp_tech[T])
if(linked_destroy.loaded_item.reliability < 100 && linked_destroy.loaded_item.crit_fail)
@@ -753,7 +753,7 @@ won't update every console in existence) but it's more of a hassle to do. Also,
dat += "Name: [linked_destroy.loaded_item.name]
"
dat += "Origin Tech:"
dat += "