diff --git a/code/game/machinery/bots/farmbot.dm b/code/game/machinery/bots/farmbot.dm
deleted file mode 100644
index ef582351570..00000000000
--- a/code/game/machinery/bots/farmbot.dm
+++ /dev/null
@@ -1,590 +0,0 @@
-//Farmbots by GauHelldragon - 12/30/2012
-// A new type of buildable aiBot that helps out in hydroponics
-
-// Made by using a robot arm on a water tank and then adding:
-// A plant analyzer, a bucket, a mini-hoe and then a proximity sensor (in that order)
-
-// Will water, weed and fertilize plants that need it
-// When emagged, it will "water", "weed" and "fertilize" humans instead
-// Holds up to 10 fertilizers (only the type dispensed by the machines, not chemistry bottles)
-// It will fill up it's water tank at a sink when low.
-
-// The behavior panel can be unlocked with hydroponics access and be modified to disable certain behaviors
-// By default, it will ignore weeds and mushrooms, but can be set to tend to these types of plants as well.
-
-
-#define FARMBOT_MODE_WATER 1
-#define FARMBOT_MODE_FERTILIZE 2
-#define FARMBOT_MODE_WEED 3
-#define FARMBOT_MODE_REFILL 4
-#define FARMBOT_MODE_WAITING 5
-
-#define FARMBOT_ANIMATION_TIME 25 //How long it takes to use one of the action animations
-#define FARMBOT_EMAG_DELAY 60 //How long of a delay after doing one of the emagged attack actions
-#define FARMBOT_ACTION_DELAY 35 //How long of a delay after doing one of the normal actions
-
-/obj/machinery/bot/farmbot
- name = "Farmbot"
- desc = "The botanist's best friend."
- icon = 'aibots.dmi'
- icon_state = "farmbot0"
- layer = 5.0
- density = 1
- anchored = 0
- health = 50
- maxhealth = 50
- req_access =list(access_hydroponics)
-
- var/Max_Fertilizers = 10
-
- var/setting_water = 1
- var/setting_refill = 1
- var/setting_fertilize = 1
- var/setting_weed = 1
- var/setting_ignoreWeeds = 1
- var/setting_ignoreMushrooms = 1
-
- var/atom/target //Current target, can be a human, a hydroponics tray, or a sink
- var/mode //Which mode is being used, 0 means it is looking for work
-
- var/obj/structure/reagent_dispensers/watertank/tank // the water tank that was used to make it, remains inside the bot.
-
- var/path[] = new() // used for pathing
- var/frustration
-
-/obj/machinery/bot/farmbot/New()
- ..()
- src.icon_state = "farmbot[src.on]"
- spawn (4)
- src.botcard = new /obj/item/weapon/card/id(src)
- src.botcard.access = req_access
-
- if ( !tank ) //Should be set as part of making it... but lets check anyway
- tank = locate(/obj/structure/reagent_dispensers/watertank/) in contents
- if ( !tank ) //An admin must have spawned the farmbot! Better give it a tank.
- tank = new /obj/structure/reagent_dispensers/watertank(src)
-
-/obj/machinery/bot/farmbot/Bump(M as mob|obj) //Leave no door unopened!
- spawn(0)
- if ((istype(M, /obj/machinery/door)) && (!isnull(src.botcard)))
- var/obj/machinery/door/D = M
- if (!istype(D, /obj/machinery/door/firedoor) && D.check_access(src.botcard))
- D.open()
- src.frustration = 0
- return
- return
-
-/obj/machinery/bot/farmbot/turn_on()
- . = ..()
- src.icon_state = "farmbot[src.on]"
- src.updateUsrDialog()
-
-/obj/machinery/bot/farmbot/turn_off()
- ..()
- src.path = new()
- src.icon_state = "farmbot[src.on]"
- src.updateUsrDialog()
-
-/obj/machinery/bot/farmbot/attack_paw(mob/user as mob)
- return attack_hand(user)
-
-
-/obj/machinery/bot/farmbot/proc/get_total_ferts()
- var total_fert = 0
- for (var/obj/item/nutrient/fert in contents)
- total_fert++
- return total_fert
-
-/obj/machinery/bot/farmbot/attack_hand(mob/user as mob)
- . = ..()
- if (.)
- return
- var/dat
- dat += "Automatic Hyrdoponic Assisting Unit v1.0
"
- dat += "Status: [src.on ? "On" : "Off"]
"
-
- dat += "Water Tank: "
- if ( tank )
- dat += "\[[tank.reagents.total_volume]/[tank.reagents.maximum_volume]\]"
- else
- dat += "Error: Water Tank not Found"
-
- dat += "
Fertilizer Storage: \[[get_total_ferts()]/[Max_Fertilizers]\]"
-
- dat += "
Behaviour controls are [src.locked ? "locked" : "unlocked"]
"
- if(!src.locked)
- dat += "Watering Controls:
"
- dat += " Water Plants : [src.setting_water ? "Yes" : "No"]
"
- dat += " Refill Watertank : [src.setting_refill ? "Yes" : "No"]
"
- dat += "
Fertilizer Controls:
"
- dat += " Fertilize Plants : [src.setting_fertilize ? "Yes" : "No"]
"
- dat += "
Weeding Controls:
"
- dat += " Weed Plants : [src.setting_weed ? "Yes" : "No"]
"
- dat += "
Ignore Weeds : [src.setting_ignoreWeeds ? "Yes" : "No"]
"
- dat += "Ignore Mushrooms : [src.setting_ignoreMushrooms ? "Yes" : "No"]
"
- dat += ""
-
- user << browse("Farmbot v1.0 controls[dat]", "window=autofarm")
- onclose(user, "autofarm")
- return
-
-/obj/machinery/bot/farmbot/Topic(href, href_list)
- if(..())
- return
- usr.machine = src
- src.add_fingerprint(usr)
- if ((href_list["power"]) && (src.allowed(usr)))
- if (src.on)
- turn_off()
- else
- turn_on()
-
- else if((href_list["water"]) && (!src.locked))
- setting_water = !setting_water
- else if((href_list["refill"]) && (!src.locked))
- setting_refill = !setting_refill
- else if((href_list["fertilize"]) && (!src.locked))
- setting_fertilize = !setting_fertilize
- else if((href_list["weed"]) && (!src.locked))
- setting_weed = !setting_weed
- else if((href_list["ignoreWeed"]) && (!src.locked))
- setting_ignoreWeeds = !setting_ignoreWeeds
- else if((href_list["ignoreMush"]) && (!src.locked))
- setting_ignoreMushrooms = !setting_ignoreMushrooms
- else if (href_list["eject"] )
- flick("farmbot_hatch",src)
- for (var/obj/item/nutrient/fert in contents)
- fert.loc = get_turf(src)
-
- src.updateUsrDialog()
- return
-
-/obj/machinery/bot/farmbot/attackby(obj/item/weapon/W as obj, mob/user as mob)
- if (istype(W, /obj/item/weapon/card/id)||istype(W, /obj/item/device/pda))
- if (src.allowed(user))
- src.locked = !src.locked
- user << "Controls are now [src.locked ? "locked." : "unlocked."]"
- src.updateUsrDialog()
- else
- user << "\red Access denied."
-
- else if (istype(W, /obj/item/nutrient))
- if ( get_total_ferts() >= Max_Fertilizers )
- user << "The fertilizer storage is full!"
- return
- user.drop_item()
- W.loc = src
- user << "You insert [W]."
- flick("farmbot_hatch",src)
- src.updateUsrDialog()
- return
-
- else
- ..()
-
-/obj/machinery/bot/farmbot/Emag(mob/user as mob)
- ..()
- if(user) user << "\red You short out [src]'s plant identifier circuits."
- spawn(0)
- for(var/mob/O in hearers(src, null))
- O.show_message("\red [src] buzzes oddly!", 1)
- flick("farmbot_broke", src)
- src.emagged = 1
- src.on = 1
- src.icon_state = "farmbot[src.on]"
- target = null
- mode = FARMBOT_MODE_WAITING //Give the emagger a chance to get away! 15 seconds should be good.
- spawn(150)
- mode = 0
-
-/obj/machinery/bot/farmbot/explode()
- src.on = 0
- visible_message("\red [src] blows apart!", 1)
- var/turf/Tsec = get_turf(src)
-
- new /obj/item/weapon/minihoe(Tsec)
- new /obj/item/weapon/reagent_containers/glass/bucket(Tsec)
- new /obj/item/device/assembly/prox_sensor(Tsec)
- new /obj/item/device/analyzer/plant_analyzer(Tsec)
-
- if ( tank )
- tank.loc = Tsec
-
- for ( var/obj/item/nutrient/fert in contents )
- if ( prob(50) )
- fert.loc = Tsec
-
- if (prob(50))
- new /obj/item/robot_parts/l_arm(Tsec)
-
- var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread
- s.set_up(3, 1, src)
- s.start()
- del(src)
- return
-
-/obj/machinery/bot/farmbot/process()
- set background = 1
-
- if(!src.on)
- return
-
- if ( emagged && prob(1) )
- flick("farmbot_broke", src)
-
- if ( mode == FARMBOT_MODE_WAITING )
- return
-
- if ( !mode || !target || !(target in view(7,src)) ) //Don't bother chasing down targets out of view
-
- mode = 0
- target = null
- if ( !find_target() )
- // Couldn't find a target, wait a while before trying again.
- mode = FARMBOT_MODE_WAITING
- spawn(100)
- mode = 0
- return
-
- if ( mode && target )
- if ( get_dist(target,src) <= 1 || ( emagged && mode == FARMBOT_MODE_FERTILIZE ) )
- // If we are in emagged fertilize mode, we throw the fertilizer, so distance doesn't matter
- frustration = 0
- use_farmbot_item()
- else
- move_to_target()
- return
-
-/obj/machinery/bot/farmbot/proc/use_farmbot_item()
- if ( !target )
- mode = 0
- return 0
-
- if ( emagged && !ismob(target) ) // Humans are plants!
- mode = 0
- target = null
- return 0
-
- if ( !emagged && !istype(target,/obj/machinery/hydroponics) && !istype(target,/obj/structure/sink) ) // Humans are not plants!
- mode = 0
- target = null
- return 0
-
- if ( mode == FARMBOT_MODE_FERTILIZE )
- //Find which fertilizer to use
- var/obj/item/nutrient/fert
- for ( var/obj/item/nutrient/nut in contents )
- fert = nut
- break
- if ( !fert )
- target = null
- mode = 0
- return
- fertilize(fert)
-
- if ( mode == FARMBOT_MODE_WEED )
- weed()
-
- if ( mode == FARMBOT_MODE_WATER )
- water()
-
- if ( mode == FARMBOT_MODE_REFILL )
- refill()
-
-
-
-
-/obj/machinery/bot/farmbot/proc/find_target()
- if ( emagged ) //Find a human and help them!
- for ( var/mob/living/carbon/human/human in view(7,src) )
- if (human.stat == 2)
- continue
-
- var list/options = list(FARMBOT_MODE_WEED)
- if ( get_total_ferts() )
- options.Add(FARMBOT_MODE_FERTILIZE)
- if ( tank && tank.reagents.total_volume >= 1 )
- options.Add(FARMBOT_MODE_WATER)
- mode = pick(options)
- target = human
- return mode
- return 0
- else
- if ( setting_refill && tank && tank.reagents.total_volume < 100 )
- for ( var/obj/structure/sink/source in view(7,src) )
- target = source
- mode = FARMBOT_MODE_REFILL
- return 1
- for ( var/obj/machinery/hydroponics/tray in view(7,src) )
- var newMode = GetNeededMode(tray)
- if ( newMode )
- mode = newMode
- target = tray
- return 1
- return 0
-
-/obj/machinery/bot/farmbot/proc/GetNeededMode(obj/machinery/hydroponics/tray)
- if ( !tray.planted || tray.dead )
- return 0
- if ( tray.myseed.plant_type == 1 && setting_ignoreWeeds )
- return 0
- if ( tray.myseed.plant_type == 2 && setting_ignoreMushrooms )
- return 0
-
- if ( setting_water && tray.waterlevel <= 10 && tank && tank.reagents.total_volume >= 1 )
- return FARMBOT_MODE_WATER
-
- if ( setting_weed && tray.weedlevel >= 5 )
- return FARMBOT_MODE_WEED
-
- if ( setting_fertilize && tray.nutrilevel <= 2 && get_total_ferts() )
- return FARMBOT_MODE_FERTILIZE
-
- return 0
-
-/obj/machinery/bot/farmbot/proc/move_to_target()
- //Mostly copied from medibot code.
-
- if(src.frustration > 8)
- target = null
- mode = 0
- frustration = 0
- src.path = new()
- if(src.target && (src.path.len) && (get_dist(src.target,src.path[src.path.len]) > 2))
- src.path = new()
- if(src.target && src.path.len == 0 && (get_dist(src,src.target) > 1))
- spawn(0)
- var/turf/dest = get_step_towards(target,src) //Can't pathfind to a tray, as it is dense, so pathfind to the spot next to the tray
-
- src.path = AStar(src.loc, dest, /turf/proc/CardinalTurfsWithAccess, /turf/proc/Distance, 0, 30,id=botcard)
- src.path = reverselist(src.path)
- if(src.path.len == 0)
- for ( var/turf/spot in orange(1,target) ) //The closest one is unpathable, try the other spots
- if ( spot == dest ) //We already tried this spot
- continue
- if ( spot.density )
- continue
- src.path = AStar(src.loc, spot, /turf/proc/CardinalTurfsWithAccess, /turf/proc/Distance, 0, 30,id=botcard)
- src.path = reverselist(src.path)
- if ( src.path.len > 0 )
- break
-
- if ( src.path.len == 0 )
- target = null
- mode = 0
- return
-
- if(src.path.len > 0 && src.target)
- step_to(src, src.path[1])
- src.path -= src.path[1]
- spawn(3)
- if(src.path.len)
- step_to(src, src.path[1])
- src.path -= src.path[1]
-
- if(src.path.len > 8 && src.target)
- src.frustration++
-
-
-/obj/machinery/bot/farmbot/proc/fertilize(obj/item/nutrient/fert)
- if ( !fert )
- target = null
- mode = 0
- return 0
-
- if ( emagged ) // Warning, hungry humans detected: throw fertilizer at them
- spawn(0)
- fert.loc = src.loc
- fert.throw_at(target, 16, 3)
- src.visible_message("\red [src] launches [fert.name] at [target.name]!")
- flick("farmbot_broke", src)
- spawn (FARMBOT_EMAG_DELAY)
- mode = 0
- target = null
- return 1
-
- else // feed them plants~
- var /obj/machinery/hydroponics/tray = target
- tray.nutrilevel = 10
- tray.yieldmod = fert.yieldmod
- tray.mutmod = fert.mutmod
- del fert
- tray.updateicon()
- icon_state = "farmbot_fertile"
- mode = FARMBOT_MODE_WAITING
-
- spawn (FARMBOT_ACTION_DELAY)
- mode = 0
- target = null
- spawn (FARMBOT_ANIMATION_TIME)
- icon_state = "farmbot[src.on]"
- return 1
-
-/obj/machinery/bot/farmbot/proc/weed()
- icon_state = "farmbot_hoe"
- spawn(FARMBOT_ANIMATION_TIME)
- icon_state = "farmbot[src.on]"
-
- if ( emagged ) // Warning, humans infested with weeds!
- mode = FARMBOT_MODE_WAITING
- spawn(FARMBOT_EMAG_DELAY)
- mode = 0
-
- if ( prob(50) ) // better luck next time little guy
- src.visible_message("\red [src] swings wildly at [target] with a minihoe, missing completely!")
-
- else // yayyy take that weeds~
- var/attackVerb = pick("slashed", "sliced", "cut", "clawed")
- var /mob/living/carbon/human/human = target
-
- src.visible_message("\red [src] [attackVerb] [human]!")
- var/damage = 5
- var/dam_zone = pick("chest", "l_hand", "r_hand", "l_leg", "r_leg")
- var/datum/organ/external/affecting = human.get_organ(ran_zone(dam_zone))
- var/armor = human.run_armor_check(affecting, "melee")
- human.apply_damage(damage,BRUTE,affecting,armor)
-
- else // warning, plants infested with weeds!
- mode = FARMBOT_MODE_WAITING
- spawn(FARMBOT_ACTION_DELAY)
- mode = 0
-
- var /obj/machinery/hydroponics/tray = target
- tray.weedlevel = 0
- tray.updateicon()
-
-/obj/machinery/bot/farmbot/proc/water()
- if ( !tank || tank.reagents.total_volume < 1 )
- mode = 0
- target = null
- return 0
-
- icon_state = "farmbot_water"
- spawn(FARMBOT_ANIMATION_TIME)
- icon_state = "farmbot[src.on]"
-
- if ( emagged ) // warning, humans are thirsty!
- var splashAmount = min(70,tank.reagents.total_volume)
- src.visible_message("\red [src] splashes [target] with a bucket of water!")
- playsound(src.loc, 'sound/effects/slosh.ogg', 25, 1)
- if ( prob(50) )
- tank.reagents.reaction(target, TOUCH) //splash the human!
- else
- tank.reagents.reaction(target.loc, TOUCH) //splash the human's roots!
- spawn(5)
- tank.reagents.remove_any(splashAmount)
-
- mode = FARMBOT_MODE_WAITING
- spawn(FARMBOT_EMAG_DELAY)
- mode = 0
- else
- var /obj/machinery/hydroponics/tray = target
- var/b_amount = tank.reagents.get_reagent_amount("water")
- if(b_amount > 0 && tray.waterlevel < 100)
- if(b_amount + tray.waterlevel > 100)
- b_amount = 100 - tray.waterlevel
- tank.reagents.remove_reagent("water", b_amount)
- tray.waterlevel += b_amount
- playsound(src.loc, 'sound/effects/slosh.ogg', 25, 1)
-
- // Toxicity dilutation code. The more water you put in, the lesser the toxin concentration.
- tray.toxic -= round(b_amount/4)
- if (tray.toxic < 0 ) // Make sure it won't go overboard
- tray.toxic = 0
-
- tray.updateicon()
- mode = FARMBOT_MODE_WAITING
- spawn(FARMBOT_ACTION_DELAY)
- mode = 0
-
-/obj/machinery/bot/farmbot/proc/refill()
- if ( !tank || !tank.reagents.total_volume > 600 || !istype(target,/obj/structure/sink) )
- mode = 0
- target = null
- return
-
- mode = FARMBOT_MODE_WAITING
- playsound(src.loc, 'sound/effects/slosh.ogg', 25, 1)
- src.visible_message("\blue [src] starts filling it's tank from [target].")
- spawn(300)
- src.visible_message("\blue [src] finishes filling it's tank.")
- src.mode = 0
- tank.reagents.add_reagent("water", tank.reagents.maximum_volume - tank.reagents.total_volume )
- playsound(src.loc, 'sound/effects/slosh.ogg', 25, 1)
-
-
-/obj/item/weapon/farmbot_arm_assembly
- name = "water tank/robot arm assembly"
- desc = "A water tank with a robot arm permanently grafted to it."
- icon = 'aibots.dmi'
- icon_state = "water_arm"
- var/build_step = 0
- var/created_name = "Farmbot" //To preserve the name if it's a unique farmbot I guess
- w_class = 3.0
-
- New()
- ..()
- spawn(4) // If an admin spawned it, it won't have a watertank it, so lets make one for em!
- var tank = locate(/obj/structure/reagent_dispensers/watertank) in contents
- if( !tank )
- new /obj/structure/reagent_dispensers/watertank(src)
-
-
-/obj/structure/reagent_dispensers/watertank/attackby(var/obj/item/robot_parts/S, mob/user as mob)
-
- if ((!istype(S, /obj/item/robot_parts/l_arm)) && (!istype(S, /obj/item/robot_parts/r_arm)))
- ..()
- return
-
- //Making a farmbot!
-
- var/obj/item/weapon/farmbot_arm_assembly/A = new /obj/item/weapon/farmbot_arm_assembly
-
- A.loc = src.loc
- A.layer = 20
- user << "You add the robot arm to the [src]"
- src.loc = A //Place the water tank into the assembly, it will be needed for the finished bot
-
- del(S)
-
-/obj/item/weapon/farmbot_arm_assembly/attackby(obj/item/weapon/W as obj, mob/user as mob)
- ..()
- if((istype(W, /obj/item/device/analyzer/plant_analyzer)) && (!src.build_step))
- src.build_step++
- user << "You add the plant analyzer to [src]!"
- src.name = "farmbot assembly"
- del(W)
-
- else if(( istype(W, /obj/item/weapon/reagent_containers/glass/bucket)) && (src.build_step == 1))
- src.build_step++
- user << "You add a bucket to [src]!"
- src.name = "farmbot assembly with bucket"
- del(W)
-
- else if(( istype(W, /obj/item/weapon/minihoe)) && (src.build_step == 2))
- src.build_step++
- user << "You add a minihoe to [src]!"
- src.name = "farmbot assembly with bucket and minihoe"
- del(W)
-
- else if((isprox(W)) && (src.build_step == 3))
- src.build_step++
- user << "You complete the Farmbot! Beep boop."
- var/obj/machinery/bot/farmbot/S = new /obj/machinery/bot/farmbot
- for ( var/obj/structure/reagent_dispensers/watertank/wTank in src.contents )
- wTank.loc = S
- S.tank = wTank
- S.loc = get_turf(src)
- S.name = src.created_name
- del(W)
- del(src)
-
- else if(istype(W, /obj/item/weapon/pen))
- var/t = input(user, "Enter new robot name", src.name, src.created_name) as text
- t = copytext(sanitize(t), 1, MAX_NAME_LEN)
- if (!t)
- return
- if (!in_range(src, usr) && src.loc != usr)
- return
-
- src.created_name = t
diff --git a/code/game/machinery/computer/ai_core.dm b/code/game/machinery/computer/ai_core.dm
index 616a62c78b6..c3e0941b101 100644
--- a/code/game/machinery/computer/ai_core.dm
+++ b/code/game/machinery/computer/ai_core.dm
@@ -117,16 +117,16 @@
laws.add_inherent_law(M.newFreeFormLaw)
usr << "Added a freeform law."
- if(istype(P, /obj/item/device/mmi))
+ if(istype(P, /obj/item/device/mmi) || istype(P, /obj/item/device/posibrain))
if(!P:brainmob)
- user << "\red Sticking an empty MMI into the frame would sort of defeat the purpose."
+ user << "\red Sticking an empty [P] into the frame would sort of defeat the purpose."
return
if(P:brainmob.stat == 2)
- user << "\red Sticking a dead brain into the frame would sort of defeat the purpose."
+ user << "\red Sticking a dead [P] into the frame would sort of defeat the purpose."
return
if(jobban_isbanned(P:brainmob, "AI"))
- user << "\red This MMI does not seem to fit."
+ user << "\red This [P] does not seem to fit."
return
if(P:brainmob.mind)
@@ -136,7 +136,7 @@
user.drop_item()
P.loc = src
brain = P
- usr << "Added a brain."
+ usr << "Added [P]."
icon_state = "3b"
if(istype(P, /obj/item/weapon/crowbar) && brain)
diff --git a/code/game/mecha/mecha.dm b/code/game/mecha/mecha.dm
index 84fd6c7ae9f..f3e14d0b291 100644
--- a/code/game/mecha/mecha.dm
+++ b/code/game/mecha/mecha.dm
@@ -668,7 +668,7 @@
/obj/mecha/attackby(obj/item/weapon/W as obj, mob/user as mob)
- if(istype(W, /obj/item/device/mmi))
+ if(istype(W, /obj/item/device/mmi) || istype(W, /obj/item/device/posibrain))
if(mmi_move_inside(W,user))
user << "[src]-MMI interface initialized successfuly"
else
@@ -1804,4 +1804,4 @@
//src.health = initial(src.health)/2.2
//src.check_for_internal_damage(list(MECHA_INT_FIRE,MECHA_INT_TEMP_CONTROL,MECHA_INT_TANK_BREACH,MECHA_INT_CONTROL_LOST))
return
-*/
+*/
diff --git a/code/game/objects/items/robot/robot_parts.dm b/code/game/objects/items/robot/robot_parts.dm
index acd210f5ddc..189aad862a7 100644
--- a/code/game/objects/items/robot/robot_parts.dm
+++ b/code/game/objects/items/robot/robot_parts.dm
@@ -161,14 +161,14 @@
else
user << "\blue You need to attach a flash to it first!"
- if(istype(W, /obj/item/device/mmi))
+ if(istype(W, /obj/item/device/mmi) || istype(W, /obj/item/device/posibrain))
var/obj/item/device/mmi/M = W
if(check_completion())
if(!istype(loc,/turf))
- user << "\red You can't put the MMI in, the frame has to be standing on the ground to be perfectly precise."
+ user << "\red You can't put the [W] in, the frame has to be standing on the ground to be perfectly precise."
return
if(!M.brainmob)
- user << "\red Sticking an empty MMI into the frame would sort of defeat the purpose."
+ user << "\red Sticking an empty [W] into the frame would sort of defeat the purpose."
return
if(!M.brainmob.key)
var/ghost_can_reenter = 0
@@ -178,19 +178,19 @@
ghost_can_reenter = 1
break
if(!ghost_can_reenter)
- user << "The mmi indicates that their mind is completely unresponsive; there's no point."
+ user << "The [W] is completely unresponsive; there's no point."
return
if(M.brainmob.stat == DEAD)
- user << "\red Sticking a dead brain into the frame would sort of defeat the purpose."
+ user << "\red Sticking a dead [W] into the frame would sort of defeat the purpose."
return
if(M.brainmob.mind in ticker.mode.head_revolutionaries)
- user << "\red The frame's firmware lets out a shrill sound, and flashes 'Abnormal Memory Engram'. It refuses to accept the MMI."
+ user << "\red The frame's firmware lets out a shrill sound, and flashes 'Abnormal Memory Engram'. It refuses to accept the [W]."
return
if(jobban_isbanned(M.brainmob, "Cyborg"))
- user << "\red This MMI does not seem to fit."
+ user << "\red This [W] does not seem to fit."
return
var/mob/living/silicon/robot/O = new /mob/living/silicon/robot(get_turf(loc))
diff --git a/code/game/objects/items/weapons/cards_ids.dm b/code/game/objects/items/weapons/cards_ids.dm
index 14304c59ad2..33677a3e9a9 100644
--- a/code/game/objects/items/weapons/cards_ids.dm
+++ b/code/game/objects/items/weapons/cards_ids.dm
@@ -69,7 +69,7 @@
if(!src.registered_name)
//Stop giving the players unsanitized unputs! You are giving ways for players to intentionally crash clients! -Nodrak
var t = copytext(sanitize(input(user, "What name would you like to put on this card?", "Agent card name", ishuman(user) ? user.real_name : user.name)),1,26)
- if(!t || t == "Unknown" || t == "floor" || t == "wall" || t == "r-wall") //Same as mob/new_player/prefrences.dm
+ if(!t || t == "Unknown" || t == "floor" || t == "wall" || t == "r-wall" || t == "") //Same as mob/new_player/prefrences.dm
alert("Invalid name.")
return
src.registered_name = t
diff --git a/code/game/objects/structures/crates_lockers/closets/secure/secure_closets.dm b/code/game/objects/structures/crates_lockers/closets/secure/secure_closets.dm
index 87d964ada16..440c3718846 100644
--- a/code/game/objects/structures/crates_lockers/closets/secure/secure_closets.dm
+++ b/code/game/objects/structures/crates_lockers/closets/secure/secure_closets.dm
@@ -63,6 +63,8 @@
src.MouseDrop_T(W:affecting, user) //act like they were dragged onto the closet
else
user << "The locker is too small to stuff [W] into!"
+ if(isrobot(user))
+ return
user.drop_item()
if(W)
W.loc = src.loc
diff --git a/code/modules/mob/living/carbon/brain/posibrain.dm b/code/modules/mob/living/carbon/brain/posibrain.dm
new file mode 100644
index 00000000000..aad1b6ef253
--- /dev/null
+++ b/code/modules/mob/living/carbon/brain/posibrain.dm
@@ -0,0 +1,118 @@
+/obj/item/device/posibrain
+ name = "positronic brain"
+ desc = "A cube of shining metal, four inches to a side and covered in shallow grooves."
+ icon = 'icons/obj/assemblies.dmi'
+ icon_state = "posibrain"
+ w_class = 3
+ origin_tech = "engineering=4;materials=4;bluespace=2;programming=6"
+
+ var/list/construction_cost = list("metal"=500,"glass"=500,"silver"=200,"gold"=200,"plasma"=100,"diamond"=10)
+ var/construction_time = 75
+ var/searching = 0
+ var/askDelay = 10 * 60 * 1
+
+ req_access = list(access_robotics)
+ var/locked = 0
+ var/mob/living/carbon/brain/brainmob = null//The current occupant.
+ var/obj/mecha = null//This does not appear to be used outside of reference in mecha.dm.
+
+ attack_self(mob/user as mob)
+ if(!brainmob && searching == 0)
+ //Start the process of searching for a new user.
+ user << "\blue You carefully locate the manual activation switch and start the positronic brain's boot process."
+ icon_state = "posibrain-searching"
+ src.searching = 1
+ src.request_player()
+
+ proc/request_player()
+ for(var/mob/dead/observer/O in player_list)
+ if(jobban_isbanned(O, "pAI"))
+ continue
+ if(O.client)
+ if(O.client.be_pai)
+ question(O.client)
+
+ proc/question(var/client/C)
+ spawn(0)
+ if(!C) return
+ var/response = alert(C, "Someone is requesting a personality for a positronic brain. Would you like to play as one?", "Positronic brain request", "Yes", "No", "Never for this round")
+ if(!C || brainmob) return //handle logouts that happen whilst the alert is waiting for a response, and responses issued after a brain has been located.
+ if(response == "Yes")
+ transfer_personality(C.mob)
+ else if (response == "Never for this round")
+ C.be_pai = 0
+
+
+ proc/transfer_personality(var/mob/candidate)
+
+ var/mob/living/carbon/brain/B = new(src)
+
+ src.searching = 0
+
+ src.brainmob = B
+ src.brainmob.mind = candidate.mind
+
+ src.brainmob.name = "PBU-[rand(100, 999)]"
+ src.brainmob.real_name = "PBU-[rand(100, 999)]"
+ src.brainmob.loc = src
+ src.brainmob.container = src
+ src.brainmob.stat = 0
+ src.brainmob.silent = 0
+ src.brainmob.brain_op_stage = 4.0
+ src.brainmob.key = candidate.key
+
+ dead_mob_list -= src.brainmob
+ living_mob_list += src.brainmob
+
+ var/turf/T = get_turf_or_move(src.loc)
+ for (var/mob/M in viewers(T))
+ M.show_message("\blue The positronic brain chimes quietly.")
+ icon_state = "posibrain-occupied"
+
+ proc/reset_search() //We give the players sixty seconds to decide, then reset the timer.
+
+ if(brainmob) return
+
+ src.searching = 0
+ icon_state = "posibrain"
+
+ var/turf/T = get_turf_or_move(src.loc)
+ for (var/mob/M in viewers(T))
+ M.show_message("\blue The positronic brain buzzes quietly, and the golden lights fade away. Perhaps you could try again?")
+
+/obj/item/device/posibrain/examine()
+
+ set src in oview()
+
+ if(!usr || !src) return
+ if( (usr.sdisabilities & BLIND || usr.blinded || usr.stat) && !istype(usr,/mob/dead/observer) )
+ usr << "Something is there but you can't see it."
+ return
+
+ var/msg = "*---------*\nThis is \icon[src] \a [src]!\n[desc]\n"
+ msg += ""
+
+ if(src.brainmob)
+ switch(src.brainmob.stat)
+ if(CONSCIOUS)
+ if(!src.brainmob.client) msg += "It appears to be in stand-by mode.\n" //afk
+ if(UNCONSCIOUS) msg += "It doesn't seem to be responsive.\n"
+ if(DEAD) msg += "It appears to be completely inactive.\n"
+ else
+ msg += "[desc]\n"
+ msg += "*---------*"
+ usr << msg
+ return
+
+/obj/item/device/posibrain/emp_act(severity)
+ if(!brainmob)
+ return
+ else
+ switch(severity)
+ if(1)
+ brainmob.emp_damage += rand(20,30)
+ if(2)
+ brainmob.emp_damage += rand(10,20)
+ if(3)
+ brainmob.emp_damage += rand(0,10)
+ ..()
\ No newline at end of file
diff --git a/code/modules/mob/living/carbon/brain/say.dm b/code/modules/mob/living/carbon/brain/say.dm
index 4b8174cc21b..c4d9a865da2 100644
--- a/code/modules/mob/living/carbon/brain/say.dm
+++ b/code/modules/mob/living/carbon/brain/say.dm
@@ -2,7 +2,7 @@
if (silent)
return
- if(!(container && istype(container, /obj/item/device/mmi)))
+ if(!(container && (istype(container, /obj/item/device/mmi) || istype(container, /obj/item/device/posibrain))))
return //No MMI, can't speak, bucko./N
else
if(prob(emp_damage*4))
diff --git a/code/modules/research/destructive_analyzer.dm b/code/modules/research/destructive_analyzer.dm
index 719647ebaba..72430976b84 100644
--- a/code/modules/research/destructive_analyzer.dm
+++ b/code/modules/research/destructive_analyzer.dm
@@ -78,6 +78,8 @@ Note: Must be placed within 3 tiles of the R&D Console
user << "\red The protolathe is busy right now."
return
if (istype(O, /obj/item) && !loaded_item)
+ if(isrobot(user)) //Don't put your module items in there!
+ return
if(!O.origin_tech)
user << "\red This doesn't seem to have a tech origin!"
return
diff --git a/html/changelog.html b/html/changelog.html
index 8087b78fc83..dd89066edf0 100644
--- a/html/changelog.html
+++ b/html/changelog.html
@@ -46,6 +46,8 @@ Header Section
+Visit the bleeding-edge test server at byond://tekkit.fallemmc.com:8000
+
diff --git a/icons/obj/assemblies.dmi b/icons/obj/assemblies.dmi
index a0c27d7816b..a4a72b0a380 100644
Binary files a/icons/obj/assemblies.dmi and b/icons/obj/assemblies.dmi differ