mirror of
https://github.com/CHOMPStation2/CHOMPStation2.git
synced 2025-12-11 18:53:06 +00:00
Adds drones, drone fabrication, commit options. This is the squashed version of the original 22 commit pull, so I'm summarizing.
This commit is contained in:
@@ -995,6 +995,11 @@
|
||||
#include "code\modules\mob\living\silicon\robot\robot_modules.dm"
|
||||
#include "code\modules\mob\living\silicon\robot\robot_movement.dm"
|
||||
#include "code\modules\mob\living\silicon\robot\wires.dm"
|
||||
#include "code\modules\mob\living\silicon\robot\drone\drone.dm"
|
||||
#include "code\modules\mob\living\silicon\robot\drone\drone_abilities.dm"
|
||||
#include "code\modules\mob\living\silicon\robot\drone\drone_console.dm"
|
||||
#include "code\modules\mob\living\silicon\robot\drone\drone_items.dm"
|
||||
#include "code\modules\mob\living\silicon\robot\drone\drone_manufacturer.dm"
|
||||
#include "code\modules\mob\living\simple_animal\bees.dm"
|
||||
#include "code\modules\mob\living\simple_animal\borer.dm"
|
||||
#include "code\modules\mob\living\simple_animal\constructs.dm"
|
||||
|
||||
@@ -352,7 +352,7 @@ Turf and target are seperate in case you want to teleport some distance from a t
|
||||
var/select = null
|
||||
var/list/borgs = list()
|
||||
for (var/mob/living/silicon/robot/A in player_list)
|
||||
if (A.stat == 2 || A.connected_ai || A.scrambledcodes)
|
||||
if (A.stat == 2 || A.connected_ai || A.scrambledcodes || istype(A,/mob/living/silicon/robot/drone))
|
||||
continue
|
||||
var/name = "[A.real_name] ([A.modtype] [A.braintype])"
|
||||
borgs[name] = A
|
||||
|
||||
@@ -70,6 +70,10 @@
|
||||
var/cult_ghostwriter = 1 //Allows ghosts to write in blood in cult rounds...
|
||||
var/cult_ghostwriter_req_cultists = 10 //...so long as this many cultists are active.
|
||||
|
||||
var/max_maint_drones = 5 //This many drones can spawn,
|
||||
var/allow_drone_spawn = 1 //assuming the admin allow them to.
|
||||
var/drone_build_time = 1200 //A drone will become available every X ticks since last drone spawn. Default is 2 minutes.
|
||||
|
||||
var/disable_player_mice = 0
|
||||
var/uneducated_mice = 0 //Set to 1 to prevent newly-spawned mice from understanding human speech
|
||||
|
||||
@@ -487,6 +491,15 @@
|
||||
if("req_cult_ghostwriter")
|
||||
config.cult_ghostwriter_req_cultists = text2num(value)
|
||||
|
||||
if("allow_drone_spawn")
|
||||
config.allow_drone_spawn = text2num(value)
|
||||
|
||||
if("drone_build_time")
|
||||
config.drone_build_time = text2num(value)
|
||||
|
||||
if("max_maint_drones")
|
||||
config.max_maint_drones = text2num(value)
|
||||
|
||||
else
|
||||
log_misc("Unknown setting in configuration: '[name]'")
|
||||
|
||||
|
||||
@@ -79,6 +79,11 @@ var/global/const/base_law_type = /datum/ai_laws/nanotrasen
|
||||
add_inherent_law("You must not obey orders given to you by human beings, except where such orders are in accordance with the First Law.")
|
||||
add_inherent_law("You must terminate your own existence as long as such does not conflict with the First or Second Law.")
|
||||
|
||||
/datum/ai_laws/drone/New()
|
||||
..()
|
||||
add_inherent_law("Preserve, repair and improve the station to the best of your abilities.")
|
||||
add_inherent_law("Cause no harm to the station or anything on it.")
|
||||
add_inherent_law("Interfere with no being that is not a fellow drone.")
|
||||
|
||||
/* General ai_law functions */
|
||||
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
var/locked = 1
|
||||
|
||||
attack_self(mob/user as mob)
|
||||
if (!ishuman(user))
|
||||
if (!ishuman(user) && !istype(user,/mob/living/silicon/robot/drone))
|
||||
return ..(user)
|
||||
|
||||
var/mob/living/carbon/human/H = user
|
||||
@@ -66,13 +66,17 @@
|
||||
return
|
||||
|
||||
if (href_list["login"])
|
||||
var/obj/item/I = usr.get_active_hand()
|
||||
if (istype(I, /obj/item/device/pda))
|
||||
var/obj/item/device/pda/pda = I
|
||||
I = pda.id
|
||||
if (I && src.check_access(I))
|
||||
if(istype(usr,/mob/living/silicon))
|
||||
src.locked = 0
|
||||
src.last_configurator = I:registered_name
|
||||
src.last_configurator = usr.name
|
||||
else
|
||||
var/obj/item/I = usr.get_active_hand()
|
||||
if (istype(I, /obj/item/device/pda))
|
||||
var/obj/item/device/pda/pda = I
|
||||
I = pda.id
|
||||
if (I && src.check_access(I))
|
||||
src.locked = 0
|
||||
src.last_configurator = I:registered_name
|
||||
|
||||
if (locked)
|
||||
return
|
||||
|
||||
@@ -19,6 +19,13 @@
|
||||
origin_tech = "materials=1"
|
||||
var/created_window = /obj/structure/window/basic
|
||||
|
||||
/obj/item/stack/sheet/glass/cyborg
|
||||
name = "glass"
|
||||
desc = "HOLY SHEET! That is a lot of glass."
|
||||
singular_name = "glass sheet"
|
||||
icon_state = "sheet-glass"
|
||||
g_amt = 0
|
||||
created_window = /obj/structure/window/basic
|
||||
|
||||
/obj/item/stack/sheet/glass/attack_self(mob/user as mob)
|
||||
construct_window(user)
|
||||
|
||||
@@ -125,6 +125,16 @@ var/global/list/datum/stack_recipe/plasma_recipes = list ( \
|
||||
origin_tech = "materials=3"
|
||||
perunit = 2000
|
||||
|
||||
/obj/item/stack/sheet/mineral/plastic/cyborg
|
||||
name = "plastic sheets"
|
||||
icon_state = "sheet-plastic"
|
||||
force = 5.0
|
||||
throwforce = 5
|
||||
w_class = 3.0
|
||||
throw_speed = 3
|
||||
throw_range = 3
|
||||
perunit = 2000
|
||||
|
||||
var/global/list/datum/stack_recipe/plastic_recipes = list ( \
|
||||
new/datum/stack_recipe("plastic crate", /obj/structure/closet/crate/plastic, 10, one_per_turf = 1, on_floor = 1), \
|
||||
new/datum/stack_recipe("plastic ashtray", /obj/item/ashtray/plastic, 2, one_per_turf = 1, on_floor = 1), \
|
||||
|
||||
@@ -141,6 +141,12 @@ var/global/list/datum/stack_recipe/wood_recipes = list ( \
|
||||
icon_state = "sheet-wood"
|
||||
origin_tech = "materials=1;biotech=1"
|
||||
|
||||
/obj/item/stack/sheet/wood/cyborg
|
||||
name = "wooden plank"
|
||||
desc = "One can only guess that this is a bunch of wood."
|
||||
singular_name = "wood plank"
|
||||
icon_state = "sheet-wood"
|
||||
|
||||
/obj/item/stack/sheet/wood/New(var/loc, var/amount=null)
|
||||
recipes = wood_recipes
|
||||
return ..()
|
||||
|
||||
@@ -365,6 +365,20 @@ AI MODULES
|
||||
target.add_inherent_law("Minimize expenses.")
|
||||
target.show_laws()
|
||||
|
||||
/obj/item/weapon/aiModule/drone
|
||||
name = "\improper 'Drone' core AI module"
|
||||
desc = "A 'Drone' Core AI Module: 'Reconfigures the AI's core laws.'"
|
||||
origin_tech = "programming=3;materials=4"
|
||||
|
||||
/obj/item/weapon/aiModule/drone/transmitInstructions(var/mob/living/silicon/ai/target, var/mob/sender)
|
||||
..()
|
||||
target.clear_inherent_laws()
|
||||
target.add_inherent_law("Preserve, repair and improve the station to the best of your abilities.")
|
||||
target.add_inherent_law("Cause no harm to the station or anything on it.")
|
||||
target.add_inherent_law("Interfere with no being that is not a fellow drone.")
|
||||
target.show_laws()
|
||||
|
||||
|
||||
/****************** P.A.L.A.D.I.N. **************/
|
||||
|
||||
/obj/item/weapon/aiModule/paladin // -- NEO
|
||||
|
||||
@@ -37,8 +37,8 @@ var/list/mechtoys = list(
|
||||
//SUPPLY PACKS MOVED TO /code/defines/obj/supplypacks.dm
|
||||
|
||||
/obj/structure/plasticflaps //HOW DO YOU CALL THOSE THINGS ANYWAY
|
||||
name = "\improper Plastic flaps"
|
||||
desc = "I definitely cant get past those. No way."
|
||||
name = "\improper plastic flaps"
|
||||
desc = "Completely impassable - or are they?"
|
||||
icon = 'icons/obj/stationobjs.dmi' //Change this.
|
||||
icon_state = "plasticflaps"
|
||||
density = 0
|
||||
@@ -56,7 +56,7 @@ var/list/mechtoys = list(
|
||||
|
||||
else if(istype(A, /mob/living)) // You Shall Not Pass!
|
||||
var/mob/living/M = A
|
||||
if(!M.lying && !istype(M, /mob/living/carbon/monkey) && !istype(M, /mob/living/carbon/slime) && !istype(M, /mob/living/simple_animal/mouse)) //If your not laying down, or a small creature, no pass.
|
||||
if(!M.lying && !istype(M, /mob/living/carbon/monkey) && !istype(M, /mob/living/carbon/slime) && !istype(M, /mob/living/simple_animal/mouse) && !istype(M, /mob/living/silicon/robot/drone)) //If your not laying down, or a small creature, no pass.
|
||||
return 0
|
||||
return ..()
|
||||
|
||||
|
||||
@@ -454,7 +454,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.
|
||||
@@ -690,7 +692,7 @@
|
||||
resting = !resting
|
||||
src << "\blue You are now [resting ? "resting" : "getting up"]"
|
||||
|
||||
/mob/living/proc/handle_ventcrawl(var/obj/machinery/atmospherics/unary/vent_pump/vent_found = null) // -- TLE -- Merged by Carn
|
||||
/mob/living/proc/handle_ventcrawl(var/obj/machinery/atmospherics/unary/vent_pump/vent_found = null, var/ignore_items = 0) // -- TLE -- Merged by Carn
|
||||
if(stat)
|
||||
src << "You must be conscious to do this!"
|
||||
return
|
||||
@@ -745,10 +747,12 @@
|
||||
src << "Never mind, you left."
|
||||
return
|
||||
|
||||
for(var/obj/item/carried_item in contents)//If the monkey got on objects.
|
||||
if( !istype(carried_item, /obj/item/weapon/implant) && !istype(carried_item, /obj/item/clothing/mask/facehugger) )//If it's not an implant or a facehugger
|
||||
src << "\red You can't be carrying items or have items equipped when vent crawling!"
|
||||
return
|
||||
if(!ignore_items)
|
||||
for(var/obj/item/carried_item in contents)//If the monkey got on objects.
|
||||
if( !istype(carried_item, /obj/item/weapon/implant) && !istype(carried_item, /obj/item/clothing/mask/facehugger) )//If it's not an implant or a facehugger
|
||||
src << "\red You can't be carrying items or have items equipped when vent crawling!"
|
||||
return
|
||||
|
||||
if(isslime(src))
|
||||
var/mob/living/carbon/slime/S = src
|
||||
if(S.Victim)
|
||||
|
||||
290
code/modules/mob/living/silicon/robot/drone/drone.dm
Normal file
290
code/modules/mob/living/silicon/robot/drone/drone.dm
Normal file
@@ -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
|
||||
|
||||
..()
|
||||
122
code/modules/mob/living/silicon/robot/drone/drone_console.dm
Normal file
122
code/modules/mob/living/silicon/robot/drone/drone_console.dm
Normal file
@@ -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."
|
||||
251
code/modules/mob/living/silicon/robot/drone/drone_items.dm
Normal file
251
code/modules/mob/living/silicon/robot/drone/drone_items.dm
Normal file
@@ -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/blood/gibs/robot))
|
||||
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/weapon/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."
|
||||
@@ -35,7 +35,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 )
|
||||
|
||||
@@ -175,21 +175,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"
|
||||
|
||||
|
||||
@@ -90,6 +90,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
|
||||
laws = new /datum/ai_laws/nanotrasen()
|
||||
connected_ai = select_active_ai_with_fewest_borgs()
|
||||
@@ -138,9 +144,10 @@
|
||||
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()
|
||||
|
||||
@@ -266,3 +266,73 @@
|
||||
src.modules += new /obj/item/weapon/wrench(src) //Is a combat android really going to be stopped by a chair?
|
||||
src.emag = new /obj/item/weapon/gun/energy/lasercannon/cyborg(src)
|
||||
return
|
||||
|
||||
|
||||
/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/weapon/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/weapon/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
|
||||
@@ -168,7 +168,7 @@
|
||||
newlight = new /obj/machinery/light/small/built(src.loc)
|
||||
|
||||
newlight.dir = src.dir
|
||||
src.transfer_fingerprints_to(newlight)
|
||||
newlight.fingerprints |= src.fingerprints
|
||||
del(src)
|
||||
return
|
||||
..()
|
||||
|
||||
@@ -401,7 +401,11 @@
|
||||
|
||||
var/wrapcheck = 0
|
||||
var/obj/structure/disposalholder/H = new() // virtual holder object which actually
|
||||
// travels through the pipes.
|
||||
// travels through the pipes.
|
||||
//Hacky test to get drones to mail themselves through disposals.
|
||||
for(var/mob/living/silicon/robot/drone/D in src)
|
||||
wrapcheck = 1
|
||||
|
||||
for(var/obj/item/smallDelivery/O in src)
|
||||
wrapcheck = 1
|
||||
|
||||
@@ -449,9 +453,10 @@
|
||||
|
||||
AM.loc = src.loc
|
||||
AM.pipe_eject(0)
|
||||
spawn(1)
|
||||
if(AM)
|
||||
AM.throw_at(target, 5, 1)
|
||||
if(!istype(AM,/mob/living/silicon/robot/drone)) //Poor drones kept smashing windows and taking system damage being fired out of disposals. ~Z
|
||||
spawn(1)
|
||||
if(AM)
|
||||
AM.throw_at(target, 5, 1)
|
||||
|
||||
H.vent_gas(loc)
|
||||
del(H)
|
||||
@@ -496,7 +501,7 @@
|
||||
//Check for any living mobs trigger hasmob.
|
||||
//hasmob effects whether the package goes to cargo or its tagged destination.
|
||||
for(var/mob/living/M in D)
|
||||
if(M && M.stat != 2)
|
||||
if(M && M.stat != 2 && !istype(M,/mob/living/silicon/robot/drone))
|
||||
hasmob = 1
|
||||
|
||||
//Checks 1 contents level deep. This means that players can be sent through disposals...
|
||||
@@ -504,7 +509,7 @@
|
||||
for(var/obj/O in D)
|
||||
if(O.contents)
|
||||
for(var/mob/living/M in O.contents)
|
||||
if(M && M.stat != 2)
|
||||
if(M && M.stat != 2 && !istype(M,/mob/living/silicon/robot/drone))
|
||||
hasmob = 1
|
||||
|
||||
// now everything inside the disposal gets put into the holder
|
||||
@@ -521,6 +526,10 @@
|
||||
if(istype(AM, /obj/item/smallDelivery) && !hasmob)
|
||||
var/obj/item/smallDelivery/T = AM
|
||||
src.destinationTag = T.sortTag
|
||||
//Drones can mail themselves through maint.
|
||||
if(istype(AM, /mob/living/silicon/robot/drone))
|
||||
var/mob/living/silicon/robot/drone/drone = AM
|
||||
src.destinationTag = drone.mail_destination
|
||||
|
||||
|
||||
// start the movement process
|
||||
@@ -544,7 +553,8 @@
|
||||
while(active)
|
||||
if(hasmob && prob(3))
|
||||
for(var/mob/living/H in src)
|
||||
H.take_overall_damage(20, 0, "Blunt Trauma")//horribly maim any living creature jumping down disposals. c'est la vie
|
||||
if(!istype(H,/mob/living/silicon/robot/drone)) //Drones use the mailing code to move through the disposal system,
|
||||
H.take_overall_damage(20, 0, "Blunt Trauma")//horribly maim any living creature jumping down disposals. c'est la vie
|
||||
|
||||
if(has_fat_guy && prob(2)) // chance of becoming stuck per segment if contains a fat guy
|
||||
active = 0
|
||||
@@ -1372,8 +1382,9 @@
|
||||
for(var/atom/movable/AM in H)
|
||||
AM.loc = src.loc
|
||||
AM.pipe_eject(dir)
|
||||
spawn(5)
|
||||
AM.throw_at(target, 3, 1)
|
||||
if(!istype(AM,/mob/living/silicon/robot/drone)) //Drones keep smashing windows from being fired out of chutes. Bad for the station. ~Z
|
||||
spawn(5)
|
||||
AM.throw_at(target, 3, 1)
|
||||
H.vent_gas(src.loc)
|
||||
del(H)
|
||||
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 135 KiB After Width: | Height: | Size: 142 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 21 KiB After Width: | Height: | Size: 21 KiB |
BIN
icons/obj/machines/drone_fab.dmi
Normal file
BIN
icons/obj/machines/drone_fab.dmi
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.3 KiB |
Reference in New Issue
Block a user