-Including the .dm that I forgot from r4525

-Changed the air assimilation for ReplaceWithFloor() and ReplaceWithPlating() so that it doesn't count non-floors/non-space turfs against the average.
-Commented them as well
Fixes Issue 851
-Standardized AIbots a bit, primarily with vars, attackby(), emag() and such (Mostly excludes M.U.L.E.'s though)
-AIbots now have a maintenece panel on them, which can be opened after unlocking the access panel by using a screwdriver
-The bots are now repaired by opening the maint panel and using a welder
-Emagging the access panel will unlock it permanatly, and emagging it with the maint panel open will trigger the emag behavior
-Floorbots will actually pull up tiles when emagged, 90% to just pull up the plating (And add it to the tile stock), and 10% to replace the floor with lattice
-When destroyed, floorbots will actually drop all the tiles they have stored, not just 1

git-svn-id: http://tgstation13.googlecode.com/svn/trunk@4528 316c924e-a436-60f5-8080-3fe189b3f50e
This commit is contained in:
sieve32@gmail.com
2012-08-24 23:16:34 +00:00
parent c2f2416171
commit b64d5c71e9
10 changed files with 192 additions and 109 deletions

View File

@@ -9,6 +9,8 @@
var/maxhealth = 0
var/fire_dam_coeff = 1.0
var/brute_dam_coeff = 1.0
var/open = 0//Maint panel
var/locked = 1
//var/emagged = 0 //Urist: Moving that var to the general /bot tree as it's used by most bots
@@ -29,7 +31,12 @@
src.explode()
/obj/machinery/bot/proc/Emag(mob/user as mob)
if(!emagged) emagged = 1
if(locked)
locked = 0
emagged = 1
user << "<span class='warning'>You bypass [src]'s controls.</span>"
if(!locked && open)
emagged = 2
/obj/machinery/bot/examine()
set src in view()
@@ -70,16 +77,20 @@
/obj/machinery/bot/attackby(obj/item/weapon/W as obj, mob/user as mob)
if (istype(W, /obj/item/weapon/screwdriver))
if (src.health < maxhealth)
src.health = min(maxhealth, src.health+25)
user.visible_message(
"\red [user] repairs [src]!",
"\blue You repair [src]!"
)
if(istype(W, /obj/item/weapon/screwdriver))
if(!locked)
open = !open
user << "<span class='notice'>Maintenance panel is now [src.open ? "opened" : "closed"].</span>"
else if(istype(W, /obj/item/weapon/weldingtool))
if(health < maxhealth)
if(open)
health = min(maxhealth, health+10)
user.visible_message("\red [user] repairs [src]!","\blue You repair [src]!")
else
user << "<span class='notice'>Unable to repair with the maintenance panel closed.</span>"
else
user << "<span class='notice'>[src] does not need a repair.</span>"
else if (istype(W, /obj/item/weapon/card/emag) && !emagged)
else if (istype(W, /obj/item/weapon/card/emag) && emagged < 2)
Emag(user)
else
switch(W.damtype)

View File

@@ -26,11 +26,9 @@
health = 25
maxhealth = 25
var/cleaning = 0
var/locked = 1
var/screwloose = 0
var/oddbutton = 0
var/blood = 1
var/panelopen = 0
var/list/target_types = list()
var/obj/effect/decal/cleanable/target
var/obj/effect/decal/cleanable/oldtarget
@@ -86,13 +84,14 @@
dat += text({"
<TT><B>Automatic Station Cleaner v1.0</B></TT><BR><BR>
Status: []<BR>
Behaviour controls are [src.locked ? "locked" : "unlocked"]"},
Behaviour controls are [src.locked ? "locked" : "unlocked"]<BR>
Maintenance panel panel is [src.open ? "opened" : "closed"]"},
text("<A href='?src=\ref[src];operation=start'>[src.on ? "On" : "Off"]</A>"))
if(!src.locked)
dat += text({"<BR>Cleans Blood: []<BR>"}, text("<A href='?src=\ref[src];operation=blood'>[src.blood ? "Yes" : "No"]</A>"))
dat += text({"<BR>Patrol station: []<BR>"}, text("<A href='?src=\ref[src];operation=patrol'>[src.should_patrol ? "Yes" : "No"]</A>"))
// dat += text({"<BR>Beacon frequency: []<BR>"}, text("<A href='?src=\ref[src];operation=freq'>[src.beacon_freq]</A>"))
if(src.panelopen && !src.locked)
if(src.open && !src.locked)
dat += text({"
Odd looking screw twiddled: []<BR>
Weird button pressed: []"},
@@ -138,25 +137,25 @@ text("<A href='?src=\ref[src];operation=oddbutton'>[src.oddbutton ? "Yes" : "No"
/obj/machinery/bot/cleanbot/attackby(obj/item/weapon/W, mob/user as mob)
if (istype(W, /obj/item/weapon/card/id)||istype(W, /obj/item/device/pda))
if(src.allowed(usr))
if(src.allowed(usr) && !open && !emagged)
src.locked = !src.locked
user << "<span class='notice'>You [ src.locked ? "lock" : "unlock"] the [src] behaviour controls.</span>"
else
user << "<span class='notice'>This [src] doesn't seem to respect your authority.</span>"
else if (istype(W, /obj/item/weapon/screwdriver))
if(!src.locked)
src.panelopen = !src.panelopen
user << "<span class='notice'>You [ src.panelopen ? "open" : "close"] the hidden panel on [src].</span>"
if(emagged)
user << "<span class='warning'>ERROR</span>"
if(open)
user << "<span class='warning'>Please close the access panel before locking it.</span>"
else
user << "<span class='notice'>This [src] doesn't seem to respect your authority.</span>"
else
return ..()
/obj/machinery/bot/cleanbot/Emag(mob/user as mob)
..()
if(user) user << "<span class='notice'>The [src] buzzes and beeps.</span>"
src.oddbutton = 1
src.screwloose = 1
src.panelopen = 0
src.locked = 1
if(open && !locked)
if(user) user << "<span class='notice'>The [src] buzzes and beeps.</span>"
src.oddbutton = 1
src.screwloose = 1
/obj/machinery/bot/cleanbot/process()
set background = 1

View File

@@ -20,7 +20,6 @@
//var/lasers = 0
var/locked = 1 //Behavior Controls lock
var/mob/living/carbon/target
var/oldtarget_name
var/threatlevel = 0
@@ -124,7 +123,8 @@
dat += text({"
<TT><B>Automatic Security Unit v2.5</B></TT><BR><BR>
Status: []<BR>
Behaviour controls are [src.locked ? "locked" : "unlocked"]"},
Behaviour controls are [src.locked ? "locked" : "unlocked"]<BR>
Maintenance panel panel is [src.open ? "opened" : "closed"]"},
"<A href='?src=\ref[src];power=1'>[src.on ? "On" : "Off"]</A>" )
@@ -186,11 +186,16 @@ Auto Patrol: []"},
/obj/machinery/bot/ed209/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))
if (src.allowed(user) && !open && !emagged)
src.locked = !src.locked
user << "<span class='notice'>Controls are now [src.locked ? "locked" : "unlocked"].</span>"
else
user << "<span class='warning'>Access denied.</span>"
if(emagged)
user << "<span class='warning'>ERROR</span>"
if(open)
user << "<span class='warning'>Please close the access panel before locking it.</span>"
else
user << "<span class='notice'>Access denied.</span>"
else
..()
if (!istype(W, /obj/item/weapon/screwdriver) && (W.force) && (!src.target))
@@ -201,19 +206,20 @@ Auto Patrol: []"},
/obj/machinery/bot/ed209/Emag(mob/user as mob)
..()
if(user) user << "<span class='warning'>You short out [src]'s target assessment circuits.</span>"
spawn(0)
for(var/mob/O in hearers(src, null))
O.show_message("\red <B>[src] buzzes oddly!</B>", 1)
src.target = null
if(user) src.oldtarget_name = user.name
src.last_found = world.time
src.anchored = 0
src.emagged = 1
src.on = 1
src.icon_state = "[lasercolor]ed209[src.on]"
src.projectile = null
mode = SECBOT_IDLE
if(open && !locked)
if(user) user << "<span class='warning'>You short out [src]'s target assessment circuits.</span>"
spawn(0)
for(var/mob/O in hearers(src, null))
O.show_message("\red <B>[src] buzzes oddly!</B>", 1)
src.target = null
if(user) src.oldtarget_name = user.name
src.last_found = world.time
src.anchored = 0
src.emagged = 2
src.on = 1
src.icon_state = "[lasercolor]ed209[src.on]"
src.projectile = null
mode = SECBOT_IDLE
/obj/machinery/bot/ed209/process()
set background = 1
@@ -654,7 +660,7 @@ Auto Patrol: []"},
/obj/machinery/bot/ed209/proc/assess_perp(mob/living/carbon/human/perp as mob)
var/threatcount = 0
if(src.emagged) return 10 //Everyone is a criminal!
if(src.emagged == 2) return 10 //Everyone is a criminal!
if((src.idcheck) || (isnull(perp:wear_id)) || (istype(perp:wear_id, /obj/item/weapon/card/id/syndicate)))
@@ -814,17 +820,17 @@ Auto Patrol: []"},
if(!projectile)
if(!lasercolor)
if (src.emagged)
if (src.emagged == 2)
projectile = /obj/item/projectile/beam
else
projectile = /obj/item/projectile/energy/electrode
else if(lasercolor == "b")
if (src.emagged)
if (src.emagged == 2)
projectile = /obj/item/projectile/omnitag
else
projectile = /obj/item/projectile/bluetag
else if(lasercolor == "r")
if (src.emagged)
if (src.emagged == 2)
projectile = /obj/item/projectile/omnitag
else
projectile = /obj/item/projectile/redtag
@@ -871,8 +877,8 @@ Auto Patrol: []"},
var/mob/toshoot = pick(targets)
if (toshoot)
targets-=toshoot
if (prob(50) && !emagged)
emagged = 1
if (prob(50) && emagged < 2)
emagged = 2
shootAt(toshoot)
emagged = 0
else

View File

@@ -42,7 +42,6 @@
var/improvefloors = 0
var/eattiles = 0
var/maketiles = 0
var/locked = 1
var/turf/target
var/turf/oldtarget
var/oldloc = null
@@ -80,6 +79,7 @@
var/dat
dat += "<TT><B>Automatic Station Floor Repairer v1.0</B></TT><BR><BR>"
dat += "Status: <A href='?src=\ref[src];operation=start'>[src.on ? "On" : "Off"]</A><BR>"
dat += "Maintenance panel panel is [src.open ? "opened" : "closed"]<BR>"
dat += "Tiles left: [src.amount]<BR>"
dat += "Behvaiour controls are [src.locked ? "locked" : "unlocked"]<BR>"
if(!src.locked)
@@ -109,15 +109,24 @@
user << "<span class='notice'>You load [loaded] tiles into the floorbot. He now contains [src.amount] tiles.</span>"
src.updateicon()
else if(istype(W, /obj/item/weapon/card/id)||istype(W, /obj/item/device/pda))
if(src.allowed(usr))
if(src.allowed(usr) && !open && !emagged)
src.locked = !src.locked
user << "<span class='notice'>You [src.locked ? "lock" : "unlock"] the [src] behaviour controls.</span>"
else
user << "<span class='notice'>The [src] doesn't seem to respect your authority.</span>"
if(emagged)
user << "<span class='warning'>ERROR</span>"
if(open)
user << "<span class='warning'>Please close the access panel before locking it.</span>"
else
user << "<span class='warning'>Access denied.</span>"
src.updateUsrDialog()
else
..()
/obj/machinery/bot/floorbot/Emag(mob/user as mob)
..()
if(open && !locked)
if(user) user << "<span class='notice'>The [src] buzzes and beeps.</span>"
/obj/machinery/bot/floorbot/Topic(href, href_list)
if(..())
@@ -184,7 +193,7 @@
for(var/mob/O in viewers(src, null))
O.show_message(text("[src] makes an excited booping beeping sound!"), 1)
if(!src.target || src.target == null)
if((!src.target || src.target == null) && emagged < 2)
if(targetdirection != null)
/*
for (var/turf/space/D in view(7,src))
@@ -217,6 +226,14 @@
src.target = T
break
if((!src.target || src.target == null) && emagged == 2)
if(!src.target || src.target == null)
for (var/turf/simulated/floor/D in view(7,src))
if(!(D in floorbottargets) && D != src.oldtarget && D.floor_tile)
src.oldtarget = D
src.target = D
break
if(!src.target || src.target == null)
if(src.loc != src.oldloc)
src.oldtarget = null
@@ -245,8 +262,23 @@
src.eattile(src.target)
else if(istype(src.target, /obj/item/stack/sheet/metal))
src.maketile(src.target)
else if(istype(src.target, /turf/))
else if(istype(src.target, /turf/) && emagged < 2)
repair(src.target)
else if(emagged == 2 && istype(src.target,/turf/simulated/floor))
var/turf/simulated/floor/F = src.target
src.anchored = 1
src.repairing = 1
if(prob(90))
F.break_tile_to_plating()
else
F.ReplaceWithLattice()
for(var/mob/O in viewers(src, null))
O.show_message(text("\red [src] makes an excited booping sound."), 1)
spawn(50)
src.amount ++
src.anchored = 0
src.repairing = 0
src.target = null
src.path = new()
return
@@ -348,8 +380,15 @@
if (prob(50))
new /obj/item/robot_parts/l_arm(Tsec)
if (amount)
new /obj/item/stack/tile/plasteel(Tsec) // only one tile, yes
while (amount)//Dumps the tiles into the appropriate sized stacks
if(amount >= 16)
var/obj/item/stack/tile/plasteel/T = new (Tsec)
T.amount = 16
amount -= 16
else
var/obj/item/stack/tile/plasteel/T = new (Tsec)
T.amount = src.amount
amount = 0
var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread
s.set_up(3, 1, src)

View File

@@ -15,7 +15,6 @@
maxhealth = 20
req_access =list(access_medical)
var/stunned = 0 //It can be stunned by tasers. Delicate circuits.
var/locked = 1
//var/emagged = 0
var/obj/machinery/camera/cam = null
var/list/botcard_access = list(access_medical, access_morgue, access_genetics, access_robotics)
@@ -106,6 +105,7 @@
var/dat
dat += "<TT><B>Automatic Medical Unit v1.0</B></TT><BR><BR>"
dat += "Status: <A href='?src=\ref[src];power=1'>[src.on ? "On" : "Off"]</A><BR>"
dat += "Maintenance panel panel is [src.open ? "opened" : "closed"]<BR>"
dat += "Beaker: "
if (src.reagent_glass)
dat += "<A href='?src=\ref[src];eject=1'>Loaded \[[src.reagent_glass.reagents.total_volume]/[src.reagent_glass.reagents.maximum_volume]\]</a>"
@@ -181,12 +181,17 @@
/obj/machinery/bot/medbot/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))
if (src.allowed(user) && !open && !emagged)
src.locked = !src.locked
user << "<span class='notice'>Controls are now [src.locked ? "locked." : "unlocked."]</span>"
src.updateUsrDialog()
else
user << "<span class='warning'>Access denied.</span>"
if(emagged)
user << "<span class='warning'>ERROR</span>"
if(open)
user << "<span class='warning'>Please close the access panel before locking it.</span>"
else
user << "<span class='warning'>Access denied.</span>"
else if (istype(W, /obj/item/weapon/reagent_containers/glass))
if(src.locked)
@@ -210,19 +215,20 @@
/obj/machinery/bot/medbot/Emag(mob/user as mob)
..()
if(user) user << "<span class='warning'>You short out [src]'s reagent synthesis circuits.</span>"
spawn(0)
for(var/mob/O in hearers(src, null))
O.show_message("\red <B>[src] buzzes oddly!</B>", 1)
flick("medibot_spark", src)
src.patient = null
if(user) src.oldpatient = user
src.currently_healing = 0
src.last_found = world.time
src.anchored = 0
src.emagged = 1
src.on = 1
src.icon_state = "medibot[src.on]"
if(open && !locked)
if(user) user << "<span class='warning'>You short out [src]'s reagent synthesis circuits.</span>"
spawn(0)
for(var/mob/O in hearers(src, null))
O.show_message("\red <B>[src] buzzes oddly!</B>", 1)
flick("medibot_spark", src)
src.patient = null
if(user) src.oldpatient = user
src.currently_healing = 0
src.last_found = world.time
src.anchored = 0
src.emagged = 2
src.on = 1
src.icon_state = "medibot[src.on]"
/obj/machinery/bot/medbot/process()
set background = 1
@@ -322,7 +328,7 @@
if(C.suiciding)
return 0 //Kevorkian school of robotic medical assistants.
if(src.emagged) //Everyone needs our medicine. (Our medicine is toxins)
if(src.emagged == 2) //Everyone needs our medicine. (Our medicine is toxins)
return 1
//If they're injured, we're using a beaker, and don't have one of our WONDERCHEMS.
@@ -380,7 +386,7 @@
if((src.use_beaker) && (src.reagent_glass) && (src.reagent_glass.reagents.total_volume))
reagent_id = "internal_beaker"
if(src.emagged) //Emagged! Time to poison everybody.
if(src.emagged == 2) //Emagged! Time to poison everybody.
reagent_id = "toxin"
var/virus = 0

View File

@@ -17,9 +17,7 @@
maxhealth = 150
fire_dam_coeff = 0.7
brute_dam_coeff = 0.5
var/locked = 1
var/atom/movable/load = null // the loaded crate (usually)
var/beacon_freq = 1400
var/control_freq = 1447
@@ -49,7 +47,6 @@
var/auto_return = 1 // true if auto return to home beacon after unload
var/auto_pickup = 1 // true if auto-pickup at beacon
var/open = 0 // true if maint hatch is open
var/obj/item/weapon/cell/cell
// the installed power cell

View File

@@ -12,7 +12,6 @@
brute_dam_coeff = 0.5
// weight = 1.0E7
req_access = list(access_security)
var/locked = 1 //Behavior Controls lock
var/mob/living/carbon/target
var/oldtarget_name
var/threatlevel = 0
@@ -114,7 +113,8 @@
dat += text({"
<TT><B>Automatic Security Unit v1.3</B></TT><BR><BR>
Status: []<BR>
Behaviour controls are [src.locked ? "locked" : "unlocked"]"},
Behaviour controls are [src.locked ? "locked" : "unlocked"]<BR>
Maintenance panel panel is [src.open ? "opened" : "closed"]"},
"<A href='?src=\ref[src];power=1'>[src.on ? "On" : "Off"]</A>" )
@@ -162,11 +162,16 @@ Auto Patrol: []"},
/obj/machinery/bot/secbot/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))
if(src.allowed(user) && !open && !emagged)
src.locked = !src.locked
user << "Controls are now [src.locked ? "locked." : "unlocked."]"
else
user << "\red Access denied."
if(emagged)
user << "<span class='warning'>ERROR</span>"
if(open)
user << "\red Please close the access panel before locking it."
else
user << "\red Access denied."
else
..()
if(!istype(W, /obj/item/weapon/screwdriver) && (W.force) && (!src.target))
@@ -174,18 +179,20 @@ Auto Patrol: []"},
src.mode = SECBOT_HUNT
/obj/machinery/bot/secbot/Emag(mob/user as mob)
if(user) user << "\red You short out [src]'s target assessment circuits."
spawn(0)
for(var/mob/O in hearers(src, null))
O.show_message("\red <B>[src] buzzes oddly!</B>", 1)
src.target = null
if(user) src.oldtarget_name = user.name
src.last_found = world.time
src.anchored = 0
src.emagged = 1
src.on = 1
src.icon_state = "secbot[src.on]"
mode = SECBOT_IDLE
..()
if(open && !locked)
if(user) user << "\red You short out [src]'s target assessment circuits."
spawn(0)
for(var/mob/O in hearers(src, null))
O.show_message("\red <B>[src] buzzes oddly!</B>", 1)
src.target = null
if(user) src.oldtarget_name = user.name
src.last_found = world.time
src.anchored = 0
src.emagged = 2
src.on = 1
src.icon_state = "secbot[src.on]"
mode = SECBOT_IDLE
/obj/machinery/bot/secbot/process()
set background = 1
@@ -586,7 +593,7 @@ Auto Patrol: []"},
/obj/machinery/bot/secbot/proc/assess_perp(mob/living/carbon/human/perp as mob)
var/threatcount = 0
if(src.emagged) return 10 //Everyone is a criminal!
if(src.emagged == 2) return 10 //Everyone is a criminal!
if(src.idcheck && !src.allowed(perp))

View File

@@ -156,26 +156,30 @@
var/aco = 0
var/atox = 0
var/atemp = 0
var/turf_count = 0
var/turf/simulated/floor/W = new /turf/simulated/floor( locate(src.x, src.y, src.z) )
for(var/direction in cardinal)
//////Assimilate Air//////
for(var/direction in cardinal)//Only use cardinals to cut down on lag
var/turf/T = get_step(src,direction)
if(istype(T,/turf/space))
if(istype(T,/turf/space))//Counted as no air
turf_count++//Considered a valid turf for air calcs
continue
else if(istype(T,/turf/simulated))
else if(istype(T,/turf/simulated/floor))
var/turf/simulated/S = T
if(S.air)
if(S.air)//Add the air's contents to the holders
aoxy += S.air.oxygen
anitro += S.air.nitrogen
aco += S.air.carbon_dioxide
atox += S.air.toxins
atemp += S.air.temperature
W.air.oxygen = (aoxy/4)
W.air.nitrogen = (anitro/4)
W.air.carbon_dioxide = (aco/4)
W.air.toxins = (atox/4)
W.air.temperature = (atemp/4)
turf_count ++
W.air.oxygen = (aoxy/max(turf_count,1))//Averages contents of the turfs, ignoring walls and the like
W.air.nitrogen = (anitro/max(turf_count,1))
W.air.carbon_dioxide = (aco/max(turf_count,1))
W.air.toxins = (atox/max(turf_count,1))
W.air.temperature = (atemp/max(turf_count,1))//Trace gases can get bant
W.RemoveLattice()
W.dir = old_dir
@@ -197,13 +201,16 @@
var/aco = 0
var/atox = 0
var/atemp = 0
var/turf_count = 0
//////Assimilate Air//////
var/turf/simulated/floor/plating/W = new /turf/simulated/floor/plating( locate(src.x, src.y, src.z) )
for(var/direction in cardinal)
var/turf/T = get_step(src,direction)
if(istype(T,/turf/space))
turf_count++
continue
else if(istype(T,/turf/simulated))
else if(istype(T,/turf/simulated/floor))
var/turf/simulated/S = T
if(S.air)
aoxy += S.air.oxygen
@@ -211,12 +218,12 @@
aco += S.air.carbon_dioxide
atox += S.air.toxins
atemp += S.air.temperature
W.air.oxygen = (aoxy/4)
W.air.oxygen = (aoxy/4)
W.air.nitrogen = (anitro/4)
W.air.carbon_dioxide = (aco/4)
W.air.toxins = (atox/4)
W.air.temperature = (atemp/4)
turf_count++
W.air.oxygen = (aoxy/max(turf_count,1))
W.air.nitrogen = (anitro/max(turf_count,1))
W.air.carbon_dioxide = (aco/max(turf_count,1))
W.air.toxins = (atox/max(turf_count,1))
W.air.temperature = (atemp/max(turf_count,1))
W.RemoveLattice()
W.dir = old_dir

View File

@@ -262,7 +262,6 @@ proc/move_mining_shuttle()
icon_state = "diamonddrill"
item_state = "jackhammer"
digspeed = 15
force = 3
desc = ""
/*****************************Shovel********************************/

View File

@@ -48,6 +48,18 @@ Stuff which is in development and not yet visible to players or just code relate
should be listed in the changelog upon commit tho. Thanks. -->
<!-- To take advantage of the pretty new format (well it was new when I wrote this anyway), open the "add-to-changelog.html" file in any browser and add the stuff and then generate the html code and paste it here -->
<div class="commit sansserif">
<h2 class="date">August 24, 2012</h2>
<h3 class="author">Sieve updated:</h3>
<ul class="changes bgimages16">
<li class="rscadd">Floorbots now actually pull up tiles when emagged</li>
<li class="tweak">All helper bots (excluding MULEs) have an access panel and maint panel, access being for behavior and maint for internal work</li>
<li class="tweak">To open the maint panel, the access panel needs to be unlocked, then you use a screwdriver. There you can emag/repair it to your heart's content. (Emagging the access panel will also unlock it permanently)</li>
<li class="tweak">Helper bots are now repaired by using a welder when their maint panel is open</li>
</ul>
</div>
<div class="commit sansserif">
<h2 class="date">August 23, 2012</h2>
<h3 class="author">Nodrak updated:</h3>