Adds drones, drone fabrication, commit options. This is the squashed version of the original 22 commit pull, so I'm summarizing.

Conflicts:
	baystation12.dme
	code/controllers/configuration.dm
	code/game/objects/items/weapons/AI_modules.dm
	code/modules/mob/living/living.dm
	code/modules/mob/living/silicon/robot/examine.dm
	code/modules/mob/living/silicon/robot/life.dm
	code/modules/mob/living/silicon/robot/robot.dm
	code/modules/mob/living/silicon/robot/robot_modules.dm
	code/modules/recycling/disposal.dm
	icons/mob/robots.dmi
	icons/obj/device.dmi
This commit is contained in:
Zuhayr
2014-05-10 01:40:11 +09:30
committed by ZomgPonies
parent c6d481f00a
commit d606d774d8
29 changed files with 1082 additions and 121 deletions
+3 -1
View File
@@ -458,7 +458,9 @@
M.drop_from_inventory(H)
M << "[H] wriggles out of your grip!"
src << "You wriggle out of [M]'s grip!"
else if(istype(H.loc,/obj/item))
src << "You struggle free of [H.loc]."
H.loc = get_turf(H)
return
//Resisting control by an alien mind.
@@ -0,0 +1,290 @@
/mob/living/silicon/robot/drone
name = "drone"
real_name = "drone"
icon = 'icons/mob/robots.dmi'
icon_state = "repairbot"
maxHealth = 35
health = 35
universal_speak = 0
universal_understand = 1
gender = NEUTER
pass_flags = PASSTABLE
braintype = "Robot"
lawupdate = 0
density = 0
// We need to keep track of a few module items so we don't need to do list operations
// every time we need them. These get set in New() after the module is chosen.
var/obj/item/stack/sheet/metal/cyborg/stack_metal = null
var/obj/item/stack/sheet/wood/cyborg/stack_wood = null
var/obj/item/stack/sheet/glass/cyborg/stack_glass = null
var/obj/item/stack/sheet/mineral/plastic/cyborg/stack_plastic = null
var/obj/item/weapon/matter_decompiler/decompiler = null
//Used for self-mailing.
var/mail_destination = 0
/mob/living/silicon/robot/drone/New()
..()
//They are unable to be upgraded, so let's give them a bit of a better battery.
cell.maxcharge = 10000
cell.charge = 10000
// NO BRAIN.
mmi = null
//We need to screw with their HP a bit. They have around one fifth as much HP as a full borg.
for(var/V in components) if(V != "power cell")
var/datum/robot_component/C = components[V]
C.max_damage = 10
verbs -= /mob/living/silicon/robot/verb/Namepick
module = new /obj/item/weapon/robot_module/drone(src)
//Grab stacks.
stack_metal = locate(/obj/item/stack/sheet/metal/cyborg) in src.module
stack_wood = locate(/obj/item/stack/sheet/wood/cyborg) in src.module
stack_glass = locate(/obj/item/stack/sheet/glass/cyborg) in src.module
stack_plastic = locate(/obj/item/stack/sheet/mineral/plastic/cyborg) in src.module
//Grab decompiler.
decompiler = locate(/obj/item/weapon/matter_decompiler) in src.module
//Some tidying-up.
flavor_text = "It's a tiny little repair drone. The casing is stamped with an NT log and the subscript: 'NanoTrasen Recursive Repair Systems: Fixing Tomorrow's Problem, Today!'"
updatename()
updateicon()
//Redefining some robot procs...
/mob/living/silicon/robot/drone/updatename()
real_name = "maintenance drone ([rand(100,999)])"
name = real_name
/mob/living/silicon/robot/drone/updateicon()
overlays.Cut()
if(stat == 0)
overlays += "eyes-[icon_state]"
else
overlays -= "eyes"
/mob/living/silicon/robot/drone/choose_icon()
return
/mob/living/silicon/robot/drone/pick_module()
return
//Drones can only use binary and say emotes. NOTHING else.
//TBD, fix up boilerplate. ~ Z
/mob/living/silicon/robot/drone/say(var/message)
if (!message)
return
if (src.client)
if(client.prefs.muted & MUTE_IC)
src << "You cannot send IC messages (muted)."
return
if (src.client.handle_spam_prevention(message,MUTE_IC))
return
message = trim(copytext(sanitize(message), 1, MAX_MESSAGE_LEN))
if (stat == 2)
return say_dead(message)
if(copytext(message,1,2) == "*")
return emote(copytext(message,2))
else if(length(message) >= 2)
if(copytext(message, 1 ,3) == ":b" || copytext(message, 1 ,3) == ":B")
if(!is_component_functioning("comms"))
src << "\red Your binary communications component isn't functional."
return
robot_talk(trim(copytext(message,3)))
//Sick of trying to get this to display properly without redefining it.
/mob/living/silicon/robot/drone/show_system_integrity()
if(!src.stat)
var/temphealth = health+35 //Brings it to 0.
if(temphealth<0) temphealth = 0
//Convert to percentage.
temphealth = (temphealth / (maxHealth*2)) * 100
stat(null, text("System integrity: [temphealth]%"))
else
stat(null, text("Systems nonfunctional"))
//Drones cannot be upgraded with borg modules so we need to catch some items before they get used in ..().
/mob/living/silicon/robot/drone/attackby(obj/item/weapon/W as obj, mob/user as mob)
if(istype(W, /obj/item/borg/upgrade/))
user << "\red The maintenance drone chassis not compatible with \the [W]."
return
else if (istype(W, /obj/item/weapon/crowbar))
user << "The machine is hermetically sealed. You can't open the case."
return
else if (istype(W, /obj/item/weapon/card/emag))
if(!client || stat == 2)
user << "\red There's not much point subverting this heap of junk."
return
if(emagged)
src << "\red [user] attempts to load subversive software into you, but your hacked subroutined ignore the attempt."
user << "\red You attempt to subvert [src], but the sequencer has no effect."
return
user << "\red You swipe the sequencer across [src]'s interface and watch its eyes flicker."
src << "\red You feel a sudden burst of malware loaded into your execute-as-root buffer. Your tiny brain methodically parses, loads and executes the script."
var/obj/item/weapon/card/emag/emag = W
emag.uses--
message_admins("[key_name_admin(user)] emagged drone [key_name_admin(src)]. Laws overridden.")
log_game("[key_name(user)] emagged drone [key_name(src)]. Laws overridden.")
var/time = time2text(world.realtime,"hh:mm:ss")
lawchanges.Add("[time] <B>:</B> [user.name]([user.key]) emagged [name]([key])")
emagged = 1
lawupdate = 0
connected_ai = null
clear_supplied_laws()
clear_inherent_laws()
laws = new /datum/ai_laws/syndicate_override
set_zeroth_law("Only [user.real_name] and people he designates as being such are Syndicate Agents.")
src << "<b>Obey these laws:</b>"
laws.show_laws(src)
src << "\red \b ALERT: [user.real_name] is your new master. Obey your new laws and his commands."
return
else if (istype(W, /obj/item/weapon/card/id)||istype(W, /obj/item/device/pda))
if(stat == 2)
user << "\red You swipe your ID card through [src], attempting to reboot it."
if(!config.allow_drone_spawn || emagged || health < -35) //It's dead, Dave.
user << "\red The interface is fried, and a distressing burned smell wafts from the robot's interior. You're not rebooting this one."
return
var/drones = 0
for(var/mob/living/silicon/robot/drone/D in world)
if(D.key && D.client)
drones++
if(drones < config.max_maint_drones)
request_player()
return
else
src << "\red [user] swipes an ID card through your card reader."
user << "\red You swipe your ID card through [src], attempting to shut it down."
if(emagged)
return
if(allowed(usr))
shut_down()
return
..()
//DRONE LIFE/DEATH
//For some goddamn reason robots have this hardcoded. Redefining it for our fragile friends here.
/mob/living/silicon/robot/drone/updatehealth()
if(status_flags & GODMODE)
health = 35
stat = CONSCIOUS
return
health = 35 - (getBruteLoss() + getFireLoss())
return
//Easiest to check this here, then check again in the robot proc.
//Standard robots use config for crit, which is somewhat excessive for these guys.
//Drones killed by damage will gib.
/mob/living/silicon/robot/drone/handle_regular_status_updates()
if(health <= -35 && src.stat != 2)
gib()
return
..()
/mob/living/silicon/robot/drone/death(gibbed)
if(module)
var/obj/item/weapon/gripper/G = locate(/obj/item/weapon/gripper) in module
if(G) G.drop_item()
..(gibbed)
//DRONE MOVEMENT.
/mob/living/silicon/robot/drone/Process_Spaceslipping(var/prob_slip)
//TODO: Consider making a magboot item for drones to equip. ~Z
return 0
//CONSOLE PROCS
/mob/living/silicon/robot/drone/proc/law_resync()
if(stat != 2)
if(emagged)
src << "\red You feel something attempting to modify your programming, but your hacked subroutines are unaffected."
else
src << "\red A reset-to-factory directive packet filters through your data connection, and you obediently modify your programming to suit it."
full_law_reset()
show_laws()
/mob/living/silicon/robot/drone/proc/shut_down()
if(stat != 2)
if(emagged)
src << "\red You feel a system kill order percolate through your tiny brain, but it doesn't seem like a good idea to you."
else
src << "\red You feel a system kill order percolate through your tiny brain, and you obediently destroy yourself."
death()
/mob/living/silicon/robot/drone/proc/full_law_reset()
clear_supplied_laws()
clear_inherent_laws()
clear_ion_laws()
laws = new /datum/ai_laws/drone
//Reboot procs.
/mob/living/silicon/robot/drone/proc/request_player()
for(var/mob/dead/observer/O in player_list)
if(jobban_isbanned(O, "Maintenance Drone"))
continue
if(O.client)
if(O.client.prefs.be_special & BE_PAI)
question(O.client)
/mob/living/silicon/robot/drone/proc/question(var/client/C)
spawn(0)
if(!C) return
var/response = alert(C, "Someone is attempting to reboot a maintenance drone. Would you like to play as one?", "Maintenance drone reboot", "Yes", "No", "Never for this round.")
if(!C || ckey)
return
if(response == "Yes")
transfer_personality(C)
else if (response == "Never for this round")
C.prefs.be_special ^= BE_PAI
/mob/living/silicon/robot/drone/proc/transfer_personality(var/client/player)
if(!player) return
src.ckey = player.ckey
if(player.mob && player.mob.mind)
player.mob.mind.transfer_to(src)
emagged = 0
lawupdate = 0
src << "<b>Systems rebooted</b>. Loading base pattern maintenance protocol... <b>loaded</b>."
full_law_reset()
@@ -0,0 +1,60 @@
// DRONE ABILITIES
/mob/living/silicon/robot/drone/verb/set_mail_tag()
set name = "Set Mail Tag"
set desc = "Tag yourself for delivery through the disposals system."
set category = "Drone"
var/tag = input("Select the desired destination.", "Set Mail Tag", null) as null|anything in TAGGERLOCATIONS
if(!tag || TAGGERLOCATIONS[tag])
mail_destination = 0
return
src << "\blue You configure your internal beacon, tagging yourself for delivery to '[tag]'."
mail_destination = TAGGERLOCATIONS.Find(tag)
//Auto flush if we use this verb inside a disposal chute.
var/obj/machinery/disposal/D = src.loc
if(istype(D))
src << "\blue \The [D] acknowledges your signal."
D.flush_count = D.flush_every_ticks
return
/mob/living/silicon/robot/drone/verb/hide()
set name = "Hide"
set desc = "Allows you to hide beneath tables or certain items. Toggled on or off."
set category = "Drone"
if (layer != TURF_LAYER+0.2)
layer = TURF_LAYER+0.2
src << text("\blue You are now hiding.")
else
layer = MOB_LAYER
src << text("\blue You have stopped hiding.")
//DRONE PICKUP.
//Item holder.
/obj/item/weapon/holder/drone
name = "maintenance bot"
desc = "It's a small maintenance robot."
icon = 'icons/obj/objects.dmi'
icon_state = "drone"
slot_flags = SLOT_HEAD
origin_tech = "magnets=3;engineering=5"
//Actual picking-up event.
/mob/living/silicon/robot/drone/attack_hand(mob/living/carbon/human/M as mob)
if(M.a_intent == "help")
var/obj/item/weapon/holder/drone/D = new(loc)
src.loc = D
D.name = loc.name
D.attack_hand(M)
M << "You scoop up [src]."
src << "[M] scoops you up."
return
..()
@@ -0,0 +1,122 @@
/obj/machinery/computer/drone_control
name = "Maintenance Drone Control"
desc = "Used to monitor the station's drone population and the assembler that services them."
icon = 'icons/obj/computer.dmi'
icon_state = "power"
req_access = list(access_engine_equip)
circuit = "/obj/item/weapon/circuitboard/robotics"
//Used when pinging drones.
var/drone_call_area = "Engineering"
//Used to enable or disable drone fabrication.
var/obj/machinery/drone_fabricator/dronefab
/obj/machinery/computer/drone_control/attack_ai(var/mob/user as mob)
return src.attack_hand(user)
/obj/machinery/computer/drone_control/attack_paw(var/mob/user as mob)
return src.attack_hand(user)
return
/obj/machinery/computer/drone_control/attack_hand(var/mob/user as mob)
if(..())
return
if(!allowed(user))
user << "\red Access denied."
return
user.set_machine(src)
var/dat
dat += "<B>Maintenance Units</B><BR>"
for(var/mob/living/silicon/robot/drone/D in world)
dat += "<BR>[D.real_name] ([D.stat == 2 ? "<font color='red'>INACTIVE" : "<font color='green'>ACTIVE"]</FONT>)"
dat += "<font dize = 9><BR>Cell charge: [D.cell.charge]/[D.cell.maxcharge]."
dat += "<BR>Currently located in: [get_area(D)]."
dat += "<BR><A href='?src=\ref[src];resync=\ref[D]'>Resync</A> | <A href='?src=\ref[src];shutdown=\ref[D]'>Shutdown</A></font>"
dat += "<BR><BR><B>Request drone presence in area:</B> <A href='?src=\ref[src];setarea=1'>[drone_call_area]</A> (<A href='?src=\ref[src];ping=1'>Send ping</A>)"
dat += "<BR><BR><B>Drone fabricator</B>: "
dat += "[dronefab ? "<A href='?src=\ref[src];toggle_fab=1'>[(dronefab.produce_drones && !(dronefab.stat & NOPOWER)) ? "ACTIVE" : "INACTIVE"]</A>" : "<font color='red'><b>FABRICATOR NOT DETECTED.</b></font> (<A href='?src=\ref[src];search_fab=1'>search</a>)"]"
user << browse(dat, "window=computer;size=400x500")
onclose(user, "computer")
return
/obj/machinery/computer/drone_control/Topic(href, href_list)
if(..())
return
if(!allowed(usr))
usr << "\red Access denied."
return
if ((usr.contents.Find(src) || (in_range(src, usr) && istype(src.loc, /turf))) || (istype(usr, /mob/living/silicon)))
usr.set_machine(src)
if (href_list["setarea"])
//Probably should consider using another list, but this one will do.
var/t_area = input("Select the area to ping.", "Set Target Area", null) as null|anything in TAGGERLOCATIONS
if(!t_area || TAGGERLOCATIONS[t_area])
return
drone_call_area = t_area
usr << "\blue You set the area selector to [drone_call_area]."
else if (href_list["ping"])
usr << "\blue You issue a maintenance request for all active drones, highlighting [drone_call_area]."
for(var/mob/living/silicon/robot/drone/D in world)
if(D.client && D.stat == 0)
D << "-- Maintenance drone presence requested in: [drone_call_area]."
else if (href_list["resync"])
var/mob/living/silicon/robot/drone/D = locate(href_list["resync"])
if(D.stat != 2)
usr << "\red You issue a law synchronization directive for the drone."
D.law_resync()
else if (href_list["shutdown"])
var/mob/living/silicon/robot/drone/D = locate(href_list["shutdown"])
if(D.stat != 2)
usr << "\red You issue a kill command for the unfortunate drone."
message_admins("[key_name_admin(usr)] issued kill order for drone [key_name_admin(D)] from control console.")
log_game("[key_name(usr)] issued kill order for [key_name(src)] from control console.")
D.shut_down()
else if (href_list["search_fab"])
if(dronefab)
return
for(var/obj/machinery/drone_fabricator/fab in oview(3,src))
if(fab.stat & NOPOWER)
continue
dronefab = fab
usr << "\blue Drone fabricator located."
return
usr << "\red Unable to locate drone fabricator."
else if (href_list["toggle_fab"])
if(!dronefab)
return
if(get_dist(src,dronefab) > 3)
dronefab = null
usr << "\red Unable to locate drone fabricator."
return
dronefab.produce_drones = !dronefab.produce_drones
usr << "\blue You [dronefab.produce_drones ? "enable" : "disable"] drone production in the nearby fabricator."
@@ -0,0 +1,251 @@
//Simple borg hand.
//Limited use.
/obj/item/weapon/gripper
name = "magnetic gripper"
desc = "A simple grasping tool for synthetic assets."
icon = 'icons/obj/device.dmi'
icon_state = "gripper"
//Has a list of items that it can hold.
var/list/can_hold = list(
/obj/item/weapon/cell,
/obj/item/weapon/firealarm_electronics,
/obj/item/weapon/airalarm_electronics,
/obj/item/weapon/airlock_electronics,
/obj/item/weapon/module/power_control,
/obj/item/weapon/stock_parts,
/obj/item/light_fixture_frame,
/obj/item/apc_frame,
/obj/item/alarm_frame,
/obj/item/firealarm_frame,
/obj/item/weapon/table_parts,
/obj/item/weapon/rack_parts,
/obj/item/weapon/camera_assembly,
)
//Item currently being held.
var/obj/item/wrapped = null
/obj/item/weapon/gripper/attack_self(mob/user as mob)
if(wrapped)
wrapped.attack_self(user)
/obj/item/weapon/gripper/verb/drop_item()
set name = "Drop Item"
set desc = "Release an item from your magnetic gripper."
set category = "Drone"
if(!wrapped)
//There's some weirdness with items being lost inside the arm. Trying to fix all cases. ~Z
for(var/obj/item/thing in src.contents)
thing.loc = get_turf(src)
return
if(wrapped.loc != src)
wrapped = null
return
src.loc << "\red You drop \the [wrapped]."
wrapped.loc = get_turf(src)
wrapped = null
//update_icon()
/obj/item/weapon/gripper/afterattack(atom/target, mob/user as mob)
if(!target) //Target is invalid.
return
//There's some weirdness with items being lost inside the arm. Trying to fix all cases. ~Z
if(!wrapped)
for(var/obj/item/thing in src.contents)
wrapped = thing
break
if(wrapped) //Already have an item.
wrapped.loc = user
//Pass the attack on to the target.
target.attackby(wrapped,user)
if(wrapped && src && wrapped.loc == user)
wrapped.loc = src
//Sanity/item use checks.
if(!wrapped || !user)
return
if(wrapped.loc != src.loc)
wrapped = null
return
if(istype(target,/obj/item)) //Check that we're not pocketing a mob.
//...and that the item is not in a container.
if(!isturf(target.loc))
return
var/obj/item/I = target
//Check if the item is blacklisted.
var/grab = 0
for(var/typepath in can_hold)
if(istype(I,typepath))
grab = 1
break
//We can grab the item, finally.
if(grab)
user << "You collect \the [I]."
I.loc = src
wrapped = I
return
else
user << "\red Your gripper cannot hold \the [target]."
//TODO: Matter decompiler.
/obj/item/weapon/matter_decompiler
name = "matter decompiler"
desc = "Eating trash, bits of glass, or other debris will replenish your stores."
icon = 'icons/obj/device.dmi'
icon_state = "decompiler"
//Metal, glass, wood, plastic.
var/list/stored_comms = list(
"metal" = 0,
"glass" = 0,
"wood" = 0,
"plastic" = 0
)
/obj/item/weapon/matter_decompiler/afterattack(atom/target, mob/user as mob)
//We only want to deal with using this on turfs. Specific items aren't important.
var/turf/T = get_turf(target)
if(!istype(T))
return
//Used to give the right message.
var/grabbed_something = 0
for(var/obj/item/W in T)
//Different classes of items give different commodities.
if(istype(W,/obj/item/trash))
stored_comms["metal"]++
stored_comms["plastic"]++
else if(istype(W,/obj/effect/decal/cleanable/robot_debris))
stored_comms["metal"]++
stored_comms["glass"]++
else if(istype(W,/obj/item/ammo_casing))
stored_comms["metal"]++
else if(istype(W,/obj/item/weapon/shard/shrapnel))
stored_comms["metal"]++
else if(istype(W,/obj/item/weapon/shard))
stored_comms["glass"]++
else if(istype(W,/obj/item/weapon/reagent_containers/food/snacks/grown))
stored_comms["wood"]++
else
continue
del(W)
grabbed_something = 1
if(grabbed_something)
user << "\blue You deploy your decompiler and clear out the contents of \the [T]."
else
user << "\red Nothing on \the [T] is useful to you."
return
//PRETTIER TOOL LIST.
/mob/living/silicon/robot/drone/installed_modules()
if(weapon_lock)
src << "\red Weapon lock active, unable to use modules! Count:[weaponlock_time]"
return
if(!module)
module = new /obj/item/weapon/robot_module/drone(src)
var/dat = "<HEAD><TITLE>Drone modules</TITLE><META HTTP-EQUIV='Refresh' CONTENT='10'></HEAD><BODY>\n"
dat += {"<A HREF='?src=\ref[src];mach_close=robotmod'>Close</A>
<BR>
<BR>
<B>Activated Modules</B>
<BR>
Module 1: [module_state_1 ? "<A HREF=?src=\ref[src];mod=\ref[module_state_1]>[module_state_1]<A>" : "No Module"]<BR>
Module 2: [module_state_2 ? "<A HREF=?src=\ref[src];mod=\ref[module_state_2]>[module_state_2]<A>" : "No Module"]<BR>
Module 3: [module_state_3 ? "<A HREF=?src=\ref[src];mod=\ref[module_state_3]>[module_state_3]<A>" : "No Module"]<BR>
<BR>
<B>Installed Modules</B><BR><BR>"}
var/tools = "<B>Tools and devices</B><BR>"
var/resources = "<BR><B>Resources</B><BR>"
for (var/O in module.modules)
var/module_string = ""
if (!O)
module_string += text("<B>Resource depleted</B><BR>")
else if(activated(O))
module_string += text("[O]: <B>Activated</B><BR>")
else
module_string += text("[O]: <A HREF=?src=\ref[src];act=\ref[O]>Activate</A><BR>")
if((istype(O,/obj/item/weapon) || istype(O,/obj/item/device)) && !(istype(O,/obj/item/stack/cable_coil)))
tools += module_string
else
resources += module_string
dat += tools
if (emagged)
if (module.emag)
dat += text("<B>Resource depleted</B><BR>")
else if(activated(module.emag))
dat += text("[module.emag]: <B>Activated</B><BR>")
else
dat += text("[module.emag]: <A HREF=?src=\ref[src];act=\ref[module.emag]>Activate</A><BR>")
dat += resources
src << browse(dat, "window=robotmod&can_close=0")
//Putting the decompiler here to avoid doing list checks every tick.
/mob/living/silicon/robot/drone/use_power()
..()
if(!src.has_power || !decompiler)
return
//The decompiler replenishes drone stores from hoovered-up junk each tick.
for(var/type in decompiler.stored_comms)
if(decompiler.stored_comms[type] > 0)
var/obj/item/stack/sheet/stack
switch(type)
if("metal")
if(!stack_metal)
stack_metal = new(src.module)
stack_metal.amount = 1
stack = stack_metal
if("glass")
if(!stack_glass)
stack_glass = new(src.module)
stack_glass.amount = 1
stack = stack_glass
if("wood")
if(!stack_wood)
stack_wood = new(src.module)
stack_wood.amount = 1
stack = stack_wood
if("plastic")
if(!stack_plastic)
stack_plastic = new(src.module)
stack_plastic.amount = 1
stack = stack_plastic
stack.amount++
decompiler.stored_comms[type]--;
@@ -0,0 +1,129 @@
/obj/machinery/drone_fabricator
name = "drone fabricator"
desc = "A large automated factory for producing maintenance drones."
density = 1
anchored = 1
use_power = 1
idle_power_usage = 20
active_power_usage = 5000
var/drone_progress = 0
var/produce_drones = 0
var/time_last_drone = 500
icon = 'icons/obj/machines/drone_fab.dmi'
icon_state = "drone_fab_idle"
/obj/machinery/drone_fabricator/New()
..()
produce_drones = config.allow_drone_spawn
/obj/machinery/drone_fabricator/power_change()
if (powered())
stat &= ~NOPOWER
else
icon_state = "drone_fab_nopower"
stat |= NOPOWER
/obj/machinery/drone_fabricator/process()
if(stat & NOPOWER || !produce_drones)
icon_state = "drone_fab_nopower"
return
if(drone_progress >= 100)
icon_state = "drone_fab_idle"
return
icon_state = "drone_fab_active"
var/elapsed = world.time - time_last_drone
drone_progress = round((elapsed/config.drone_build_time)*100)
if(drone_progress >= 100)
visible_message("\The [src] voices a strident beep, indicating a drone chassis is prepared.")
/obj/machinery/drone_fabricator/examine()
..()
if(produce_drones && drone_progress >= 100 && istype(usr,/mob/dead) && config.allow_drone_spawn && count_drones() < config.max_maint_drones)
usr << "<BR><B>A drone is prepared. Select 'Join As Drone' from the Ghost tab to spawn as a maintenance drone.</B>"
/obj/machinery/drone_fabricator/proc/count_drones()
var/drones = 0
for(var/mob/living/silicon/robot/drone/D in world)
if(D.key && D.client)
drones++
return drones
/obj/machinery/drone_fabricator/proc/create_drone(var/client/player)
if(stat & NOPOWER)
return
if(!produce_drones || !config.allow_drone_spawn || count_drones() >= config.max_maint_drones)
return
if(!player || !istype(player.mob,/mob/dead))
return
visible_message("\The [src] churns and grinds as it lurches into motion, disgorging a shiny new drone after a few moments.")
flick("h_lathe_leave",src)
time_last_drone = world.time
var/mob/living/silicon/robot/drone/new_drone = new(get_turf(src))
new_drone.transfer_personality(player)
drone_progress = 0
/mob/dead/verb/join_as_drone()
set category = "Ghost"
set name = "Join As Drone"
set desc = "If there is a powered, enabled fabricator in the game world with a prepared chassis, join as a maintenance drone."
if(!(config.allow_drone_spawn))
src << "\red That verb is not currently permitted."
return
if (!src.stat)
return
if (usr != src)
return 0 //something is terribly wrong
var/deathtime = world.time - src.timeofdeath
if(istype(src,/mob/dead/observer))
var/mob/dead/observer/G = src
if(G.has_enabled_antagHUD == 1 && config.antag_hud_restricted)
usr << "\blue <B>Upon using the antagHUD you forfeighted the ability to join the round.</B>"
return
var/deathtimeminutes = round(deathtime / 600)
var/pluralcheck = "minute"
if(deathtimeminutes == 0)
pluralcheck = ""
else if(deathtimeminutes == 1)
pluralcheck = " [deathtimeminutes] minute and"
else if(deathtimeminutes > 1)
pluralcheck = " [deathtimeminutes] minutes and"
var/deathtimeseconds = round((deathtime - deathtimeminutes * 600) / 10,1)
if (deathtime < 6000)
usr << "You have been dead for[pluralcheck] [deathtimeseconds] seconds."
usr << "You must wait 10 minutes to respawn as a drone!"
return
for(var/obj/machinery/drone_fabricator/DF in world)
if(DF.stat & NOPOWER || !DF.produce_drones)
continue
if(DF.count_drones() >= config.max_maint_drones)
src << "\red There are too many active drones in the world for you to spawn."
return
DF.create_drone(src.client)
return
src << "\red There are no available drone spawn points, sorry."
@@ -32,6 +32,9 @@
else
msg += "Its cover is closed.\n"
if(!has_power)
msg += "<span class='warning'>It appears to be running on backup power.</span>\n"
switch(src.stat)
if(CONSCIOUS)
if(!src.client) msg += "It appears to be in stand-by mode.\n" //afk
@@ -39,7 +42,7 @@
if(DEAD) msg += "<span class='deadsay'>It looks completely unsalvageable.</span>\n"
msg += "*---------*</span>"
if(print_flavor_text()) msg += "[print_flavor_text()]\n"
if(print_flavor_text()) msg += "\n[print_flavor_text()]\n"
if (pose)
if( findtext(pose,".",lentext(pose)) == 0 && findtext(pose,"!",lentext(pose)) == 0 && findtext(pose,"?",lentext(pose)) == 0 )
+40 -16
View File
@@ -125,6 +125,10 @@
src.druggy--
src.druggy = max(0, src.druggy)
//update the state of modules and components here
if (src.stat != 0)
uneq_all()
if(!is_component_functioning("radio"))
radio.on = 0
else
@@ -135,6 +139,9 @@
else
src.blinded = 1
if(!is_component_functioning("actuator"))
src.Paralyse(3)
return 1
@@ -175,21 +182,38 @@
if (src.healths)
if (src.stat != 2)
switch(health)
if(200 to INFINITY)
src.healths.icon_state = "health0"
if(150 to 200)
src.healths.icon_state = "health1"
if(100 to 150)
src.healths.icon_state = "health2"
if(50 to 100)
src.healths.icon_state = "health3"
if(0 to 50)
src.healths.icon_state = "health4"
if(config.health_threshold_dead to 0)
src.healths.icon_state = "health5"
else
src.healths.icon_state = "health6"
if(istype(src,/mob/living/silicon/robot/drone))
switch(health)
if(35 to INFINITY)
src.healths.icon_state = "health0"
if(25 to 34)
src.healths.icon_state = "health1"
if(15 to 24)
src.healths.icon_state = "health2"
if(5 to 14)
src.healths.icon_state = "health3"
if(0 to 4)
src.healths.icon_state = "health4"
if(-35 to 0)
src.healths.icon_state = "health5"
else
src.healths.icon_state = "health6"
else
switch(health)
if(200 to INFINITY)
src.healths.icon_state = "health0"
if(150 to 200)
src.healths.icon_state = "health1"
if(100 to 150)
src.healths.icon_state = "health2"
if(50 to 100)
src.healths.icon_state = "health3"
if(0 to 50)
src.healths.icon_state = "health4"
if(config.health_threshold_dead to 0)
src.healths.icon_state = "health5"
else
src.healths.icon_state = "health6"
else
src.healths.icon_state = "health7"
@@ -326,4 +350,4 @@
if(!on_fire) //Silicons don't gain stacks from hotspots, but hotspots can ignite them
IgniteMob()
//Robots on fire
//Robots on fire
+11 -17
View File
@@ -57,7 +57,7 @@
var/datum/effect/effect/system/ion_trail_follow/ion_trail = null
var/datum/effect/effect/system/spark_spread/spark_system//So they can initialize sparks whenever/N
var/jeton = 0
var/has_power = 1
var/killswitch = 0
var/killswitch_time = 60
var/weapon_lock = 0
@@ -100,6 +100,12 @@
hands.icon_state = "standard"
icon_state = "secborg"
modtype = "Security"
else if(istype(src,/mob/living/silicon/robot/drone))
laws = new /datum/ai_laws/drone()
connected_ai = select_active_ai_with_fewest_borgs()
if(connected_ai)
connected_ai.connected_robots += src
lawsync()
else
if(mmi.alien || alien)
laws = new /datum/ai_laws/alienmov()
@@ -152,22 +158,10 @@
hud_list[IMPTRACK_HUD] = image('icons/mob/hud.dmi', src, "hudblank")
hud_list[SPECIALROLE_HUD] = image('icons/mob/hud.dmi', src, "hudblank")
hud_list[HEALTH_HUD] = image('icons/mob/hud.dmi', src, "hudblank")
hud_list[STATUS_HUD] = image('icons/mob/hud.dmi', src, "hudhealth100")
hud_list[ID_HUD] = image('icons/mob/hud.dmi', src, "hudblank")
hud_list[WANTED_HUD] = image('icons/mob/hud.dmi', src, "hudblank")
hud_list[IMPLOYAL_HUD] = image('icons/mob/hud.dmi', src, "hudblank")
hud_list[IMPCHEM_HUD] = image('icons/mob/hud.dmi', src, "hudblank")
hud_list[IMPTRACK_HUD] = image('icons/mob/hud.dmi', src, "hudblank")
hud_list[SPECIALROLE_HUD] = image('icons/mob/hud.dmi', src, "hudblank")
playsound(loc, 'sound/voice/liveagain.ogg', 75, 1)
if(istype(src,/mob/living/silicon/robot/drone))
playsound(src.loc, 'sound/machines/twobeep.ogg', 50, 0)
else
playsound(loc, 'sound/voice/liveagain.ogg', 75, 1)
// setup the PDA and its name
/mob/living/silicon/robot/proc/setup_PDA()
@@ -249,3 +249,72 @@
src.emag = new /obj/item/weapon/reagent_containers/spray/alien/acid(src)
src.emag.reagents.add_reagent("pacid", 125)
src.emag.reagents.add_reagent("sacid", 125)
/obj/item/weapon/robot_module/drone
name = "drone module"
New()
//TODO: Replace with shittier flashlight and work out why we can't remove the flash. ~Z
..()
src.modules += new /obj/item/weapon/weldingtool(src)
src.modules += new /obj/item/weapon/screwdriver(src)
src.modules += new /obj/item/weapon/wrench(src)
src.modules += new /obj/item/weapon/crowbar(src)
src.modules += new /obj/item/weapon/wirecutters(src)
src.modules += new /obj/item/device/multitool(src)
src.modules += new /obj/item/device/lightreplacer(src)
src.modules += new /obj/item/weapon/reagent_containers/spray/cleaner(src)
src.modules += new /obj/item/weapon/gripper(src)
src.modules += new /obj/item/weapon/matter_decompiler(src)
src.emag = new /obj/item/weapon/card/emag(src)
src.emag.name = "Cryptographic Sequencer"
var/list/stacktypes = list(
/obj/item/stack/rods = 10,
/obj/item/stack/tile/plasteel = 10,
/obj/item/stack/sheet/metal/cyborg = 10,
/obj/item/stack/sheet/wood/cyborg = 1,
/obj/item/stack/cable_coil = 30,
/obj/item/stack/sheet/glass/cyborg = 10,
/obj/item/stack/sheet/mineral/plastic/cyborg = 1
)
for(var/T in stacktypes)
var/obj/item/stack/sheet/W = new T(src)
W.amount = stacktypes[T]
src.modules += W
return
/obj/item/weapon/robot_module/drone/respawn_consumable(var/mob/living/silicon/robot/R)
var/obj/item/weapon/reagent_containers/spray/cleaner/C = locate() in src.modules
C.reagents.add_reagent("cleaner", 10)
var/list/stacks = list (
/obj/item/stack/sheet/metal,
/obj/item/stack/cable_coil,
/obj/item/stack/sheet/glass/cyborg,
/obj/item/stack/rods,
/obj/item/stack/tile/plasteel
)
for(var/T in stacks)
var/O = locate(T) in src.modules
var/obj/item/stack/sheet/S = O
if(!S)
src.modules -= null
S = new T(src)
src.modules += S
S.amount = 0
if(istype(S) && S.amount < 15)
S.amount++
var/obj/item/device/lightreplacer/LR = locate() in src.modules
LR.Charge(R)
return