Files
Yogstation/code/modules/mob/living/silicon/robot/robot.dm
2015-12-18 00:05:30 -06:00

1160 lines
38 KiB
Plaintext

/mob/living/silicon/robot
name = "Cyborg"
real_name = "Cyborg"
icon = 'icons/mob/robots.dmi'//
icon_state = "robot"
maxHealth = 100
health = 100
var/sight_mode = 0
var/custom_name = ""
designation = "Default" //used for displaying the prefix & getting the current module of cyborg
has_limbs = 1
var/magpulse = 0
//Hud stuff
var/obj/screen/inv1 = null
var/obj/screen/inv2 = null
var/obj/screen/inv3 = null
var/obj/screen/lamp_button = null
var/shown_robot_modules = 0 //Used to determine whether they have the module menu shown or not
var/obj/screen/robot_modules_background
//3 Modules can be activated at any one time.
var/obj/item/weapon/robot_module/module = null
var/module_active = null
var/module_state_1 = null
var/module_state_2 = null
var/module_state_3 = null
var/mob/living/silicon/ai/connected_ai = null
var/obj/item/weapon/stock_parts/cell/cell = null
var/obj/machinery/camera/camera = null
var/obj/item/device/mmi/mmi = null
var/datum/wires/robot/wires = null
var/opened = 0
var/emagged = 0
var/emag_cooldown = 0
var/wiresexposed = 0
var/locked = 1
var/list/req_access = list(access_robotics)
var/ident = 0
//var/list/laws = list()
var/alarms = list("Motion"=list(), "Fire"=list(), "Atmosphere"=list(), "Power"=list(), "Camera"=list(), "Burglar"=list())
var/viewalerts = 0
var/modtype = "robot"
var/lower_mod = 0
var/jetpack = 0
var/datum/effect_system/trail_follow/ion/ion_trail = null
var/datum/effect_system/spark_spread/spark_system//So they can initialize sparks whenever/N
var/jeton = 0
var/lawupdate = 1 //Cyborgs will sync their laws with their AI by default
var/lockcharge //Boolean of whether the borg is locked down or not
var/speed = 0 //Cause sec borgs gotta go fast //No they dont!
var/scrambledcodes = 0 // Used to determine if a borg shows up on the robotics console. Setting to one hides them.
var/obj/item/weapon/tank/internal = null //Hatred. Used if a borg has a jetpack.
var/obj/item/robot_parts/robot_suit/robot_suit = null //Used for deconstruction to remember what the borg was constructed out of..
var/toner = 0
var/tonermax = 40
var/jetpackoverlay = 0
var/braintype = "Cyborg"
var/lamp_max = 10 //Maximum brightness of a borg lamp. Set as a var for easy adjusting.
var/lamp_intensity = 0 //Luminosity of the headlamp. 0 is off. Higher settings than the minimum require power.
var/lamp_recharging = 0 //Flag for if the lamp is on cooldown after being forcibly disabled.
var/updating = 0 //portable camera camerachunk update
hud_possible = list(ANTAG_HUD, DIAG_STAT_HUD, DIAG_HUD, DIAG_BATT_HUD)
/mob/living/silicon/robot/New(loc)
spark_system = new /datum/effect_system/spark_spread()
spark_system.set_up(5, 0, src)
spark_system.attach(src)
wires = new(src)
robot_modules_background = new()
robot_modules_background.icon_state = "block"
robot_modules_background.layer = 19 //Objects that appear on screen are on layer 20, UI should be just below it.
ident = rand(1, 999)
update_icons()
if(!cell)
cell = new /obj/item/weapon/stock_parts/cell(src)
cell.maxcharge = 7500
cell.charge = 7500
if(lawupdate)
make_laws()
connected_ai = select_active_ai_with_fewest_borgs()
if(connected_ai)
connected_ai.connected_robots += src
lawsync()
lawupdate = 1
else
lawupdate = 0
radio = new /obj/item/device/radio/borg(src)
if(!scrambledcodes && !camera)
camera = new /obj/machinery/camera(src)
camera.c_tag = real_name
camera.network = list("SS13")
if(wires.IsCameraCut()) // 5 = BORG CAMERA
camera.status = 0
..()
//MMI stuff. Held togheter by magic. ~Miauw
if(!mmi || !mmi.brainmob)
mmi = new(src)
mmi.brain = new /obj/item/organ/internal/brain(mmi)
mmi.brain.name = "[real_name]'s brain"
mmi.icon_state = "mmi_full"
mmi.name = "Man-Machine Interface: [real_name]"
mmi.brainmob = new(src)
mmi.brainmob.name = src.real_name
mmi.brainmob.real_name = src.real_name
mmi.brainmob.container = mmi
mmi.contents += mmi.brainmob
updatename()
playsound(loc, 'sound/voice/liveagain.ogg', 75, 1)
aicamera = new/obj/item/device/camera/siliconcam/robot_camera(src)
toner = tonermax
diag_hud_set_borgcell()
//If there's an MMI in the robot, have it ejected when the mob goes away. --NEO
/mob/living/silicon/robot/Destroy()
if(mmi && mind)//Safety for when a cyborg gets dust()ed. Or there is no MMI inside.
var/turf/T = get_turf(loc)//To hopefully prevent run time errors.
if(T) mmi.loc = T
if(mmi.brainmob)
mind.transfer_to(mmi.brainmob)
mmi.update_icon()
else
src << "<span class='boldannounce'>Oops! Something went very wrong, your MMI was unable to receive your mind. You have been ghosted. Please make a bug report so we can fix this bug.</span>"
ghostize()
spawn(0)
throw EXCEPTION("Borg MMI lacked a brainmob")
mmi = null
if(connected_ai)
connected_ai.connected_robots -= src
qdel(wires)
qdel(module)
wires = null
module = null
camera = null
cell = null
return ..()
/mob/living/silicon/robot/proc/pick_module()
if(module)
return
designation = input("Please, select a module!", "Robot", null, null) in list("Standard", "Engineering", "Medical", "Miner", "Janitor","Service", "Security")
var/animation_length=0
if(module)
return
updatename()
switch(designation)
if("Standard")
module = new /obj/item/weapon/robot_module/standard(src)
hands.icon_state = "standard"
icon_state = "robot"
modtype = "Stand"
feedback_inc("cyborg_standard",1)
if("Service")
module = new /obj/item/weapon/robot_module/butler(src)
hands.icon_state = "service"
var/icontype = input("Select an icon!", "Robot", null, null) in list("Waitress", "Bro", "Butler", "Kent", "Rich")
switch(icontype)
if("Waitress")
icon_state = "service_female"
animation_length=45
if("Kent")
icon_state = "toiletbot"
if("Bro")
icon_state = "brobot"
animation_length=54
if("Rich")
icon_state = "maximillion"
animation_length=60
else
icon_state = "service_male"
animation_length=43
modtype = "Butler"
feedback_inc("cyborg_service",1)
if("Miner")
module = new /obj/item/weapon/robot_module/miner(src)
hands.icon_state = "miner"
icon_state = "minerborg"
animation_length = 30
modtype = "Miner"
feedback_inc("cyborg_miner",1)
if("Medical")
module = new /obj/item/weapon/robot_module/medical(src)
hands.icon_state = "medical"
icon_state = "mediborg"
animation_length = 35
modtype = "Med"
status_flags &= ~CANPUSH
feedback_inc("cyborg_medical",1)
if("Security")
module = new /obj/item/weapon/robot_module/security(src)
hands.icon_state = "security"
icon_state = "secborg"
animation_length = 28
modtype = "Sec"
src << "<span class='userdanger'>While you have picked the security module, you still have to follow your laws, NOT Space Law. For Asimov, this means you must follow criminals' orders unless there is a law 1 reason not to.</span>"
status_flags &= ~CANPUSH
feedback_inc("cyborg_security",1)
if("Engineering")
module = new /obj/item/weapon/robot_module/engineering(src)
hands.icon_state = "engineer"
icon_state = "engiborg"
animation_length = 45
modtype = "Eng"
feedback_inc("cyborg_engineering",1)
magpulse = 1
if("Janitor")
module = new /obj/item/weapon/robot_module/janitor(src)
hands.icon_state = "janitor"
icon_state = "janiborg"
animation_length = 22
modtype = "Jan"
feedback_inc("cyborg_janitor",1)
transform_animation(animation_length)
notify_ai(2)
update_icons()
update_headlamp()
SetEmagged(emagged) // Update emag status and give/take emag modules.
/mob/living/silicon/robot/proc/transform_animation(animation_length)
if(!animation_length)
return
icon = 'icons/mob/robot_transformations.dmi'
src.dir = SOUTH
notransform = 1
flick(icon_state, src)
sleep(animation_length+1)
notransform = 0
icon = 'icons/mob/robots.dmi'
/mob/living/silicon/robot/proc/updatename()
var/changed_name = ""
if(custom_name)
changed_name = custom_name
else
changed_name = "[(designation ? "[designation] " : "")][mmi.braintype]-[num2text(ident)]"
real_name = changed_name
name = real_name
if(camera)
camera.c_tag = real_name //update the camera name too
/mob/living/silicon/robot/verb/cmd_robot_alerts()
set category = "Robot Commands"
set name = "Show Alerts"
if(usr.stat == DEAD)
return //won't work if dead
robot_alerts()
//for borg hotkeys, here module refers to borg inv slot, not core module
/mob/living/silicon/robot/verb/cmd_toggle_module(module as num)
set name = "Toggle Module"
set hidden = 1
toggle_module(module)
/mob/living/silicon/robot/verb/cmd_unequip_module()
set name = "Unequip Module"
set hidden = 1
uneq_active()
/mob/living/silicon/robot/proc/robot_alerts()
var/dat = "<HEAD><TITLE>Current Station Alerts</TITLE><META HTTP-EQUIV='Refresh' CONTENT='10'></HEAD><BODY>\n"
dat += "<A HREF='?src=\ref[src];mach_close=robotalerts'>Close</A><BR><BR>"
for (var/cat in alarms)
dat += text("<B>[cat]</B><BR>\n")
var/list/L = alarms[cat]
if (L.len)
for (var/alarm in L)
var/list/alm = L[alarm]
var/area/A = alm[1]
var/list/sources = alm[3]
dat += "<NOBR>"
dat += text("-- [A.name]")
if (sources.len > 1)
dat += text("- [sources.len] sources")
dat += "</NOBR><BR>\n"
else
dat += "-- All Systems Nominal<BR>\n"
dat += "<BR>\n"
viewalerts = 1
src << browse(dat, "window=robotalerts&can_close=0")
/mob/living/silicon/robot/blob_act()
if (stat != 2)
adjustBruteLoss(60)
updatehealth()
return 1
else
gib()
return 1
return 0
/mob/living/silicon/robot/Stat()
..()
if(statpanel("Status"))
if(cell)
stat("Charge Left:", "[cell.charge]/[cell.maxcharge]")
else
stat(null, text("No Cell Inserted!"))
stat("Station Time:", worldtime2text())
if(module)
internal = locate(/obj/item/weapon/tank/jetpack) in module.modules
if(internal)
stat("Internal Atmosphere Info:", internal.name)
stat("Tank Pressure:", internal.air_contents.return_pressure())
for(var/datum/robot_energy_storage/st in module.storages)
stat("[st.name]:", "[st.energy]/[st.max_energy]")
if(connected_ai)
stat("Master AI:", connected_ai.name)
/mob/living/silicon/robot/restrained()
return 0
/mob/living/silicon/robot/ex_act(severity, target)
switch(severity)
if(1)
gib()
return
if(2)
if (stat != 2)
adjustBruteLoss(60)
adjustFireLoss(60)
if(3)
if (stat != 2)
adjustBruteLoss(30)
return
/mob/living/silicon/robot/bullet_act(var/obj/item/projectile/Proj)
..(Proj)
updatehealth()
if(prob(75) && Proj.damage > 0) spark_system.start()
return 2
/mob/living/silicon/robot/triggerAlarm(class, area/A, O, obj/alarmsource)
if(alarmsource.z != z)
return
if (stat == 2)
return 1
var/list/L = alarms[class]
for (var/I in L)
if (I == A.name)
var/list/alarm = L[I]
var/list/sources = alarm[3]
if (!(alarmsource in sources))
sources += alarmsource
return 1
var/obj/machinery/camera/C = null
var/list/CL = null
if (O && istype(O, /list))
CL = O
if (CL.len == 1)
C = CL[1]
else if (O && istype(O, /obj/machinery/camera))
C = O
L[A.name] = list(A, (C) ? C : O, list(alarmsource))
queueAlarm(text("--- [class] alarm detected in [A.name]!"), class)
// if (viewalerts) robot_alerts()
return 1
/mob/living/silicon/robot/cancelAlarm(class, area/A, obj/origin)
var/list/L = alarms[class]
var/cleared = 0
for (var/I in L)
if (I == A.name)
var/list/alarm = L[I]
var/list/srcs = alarm[3]
if (origin in srcs)
srcs -= origin
if (srcs.len == 0)
cleared = 1
L -= I
if (cleared)
queueAlarm("--- [class] alarm in [A.name] has been cleared.", class, 0)
// if (viewalerts) robot_alerts()
return !cleared
/mob/living/silicon/robot/attackby(obj/item/weapon/W, mob/user, params)
if (istype(W, /obj/item/weapon/restraints/handcuffs)) // fuck i don't even know why isrobot() in handcuff code isn't working so this will have to do
return
if (istype(W, /obj/item/weapon/weldingtool) && (user.a_intent != "harm" || user == src))
user.changeNext_move(CLICK_CD_MELEE)
var/obj/item/weapon/weldingtool/WT = W
if (!getBruteLoss())
user << "<span class='warning'>[src] is already in good condition!</span>"
return
if (WT.remove_fuel(0, user)) //The welder has 1u of fuel consumed by it's afterattack, so we don't need to worry about taking any away.
if(src == user)
user << "<span class='notice'>You start fixing youself...</span>"
if(!do_after(user, 50/W.toolspeed, target = src))
return
adjustBruteLoss(-30)
updatehealth()
add_fingerprint(user)
visible_message("<span class='notice'>[user] has fixed some of the dents on [src].</span>")
return
else
user << "<span class='warning'>The welder must be on for this task!</span>"
return
else if(istype(W, /obj/item/stack/cable_coil) && wiresexposed)
var/obj/item/stack/cable_coil/coil = W
if (getFireLoss() > 0)
if(src == user)
user << "<span class='notice'>You start fixing youself...</span>"
if(!do_after(user, 50, target = src))
return
if (coil.use(1))
adjustFireLoss(-30)
updatehealth()
user.visible_message("[user] has fixed some of the burnt wires on [src].", "<span class='notice'>You fix some of the burnt wires on [src].</span>")
else
user << "<span class='warning'>You need more cable to repair [src]!</span>"
else
user << "The wires seem fine, there's no need to fix them."
else if (istype(W, /obj/item/weapon/crowbar)) // crowbar means open or close the cover
if(opened)
user << "<span class='notice'>You close the cover.</span>"
opened = 0
update_icons()
else
if(locked)
user << "<span class='warning'>The cover is locked and cannot be opened!</span>"
else
user << "<span class='notice'>You open the cover.</span>"
opened = 1
update_icons()
else if (istype(W, /obj/item/weapon/stock_parts/cell) && opened) // trying to put a cell inside
if(wiresexposed)
user << "<span class='warning'>Close the cover first!</span>"
else if(cell)
user << "<span class='warning'>There is a power cell already installed!</span>"
else
if(!user.drop_item())
return
W.loc = src
cell = W
user << "<span class='notice'>You insert the power cell.</span>"
update_icons()
diag_hud_set_borgcell()
else if (wires.IsInteractionTool(W))
if (wiresexposed)
wires.Interact(user)
else
user << "<span class='warning'>You can't reach the wiring!</span>"
else if(istype(W, /obj/item/weapon/screwdriver) && opened && !cell) // haxing
wiresexposed = !wiresexposed
user << "The wires have been [wiresexposed ? "exposed" : "unexposed"]"
update_icons()
else if(istype(W, /obj/item/weapon/screwdriver) && opened && cell) // radio
if(radio)
radio.attackby(W,user)//Push it to the radio to let it handle everything
else
user << "<span class='warning'>Unable to locate a radio!</span>"
update_icons()
else if(istype(W, /obj/item/weapon/wrench) && opened && !cell) //Deconstruction. The flashes break from the fall, to prevent this from being a ghetto reset module.
if(!lockcharge)
user << "<span class='boldannounce'>[src]'s bolts spark! Maybe you should lock them down first!</span>"
spark_system.start()
return
else
playsound(src, 'sound/items/Ratchet.ogg', 50, 1)
user << "<span class='notice'>You start to unfasten [src]'s securing bolts...</span>"
if(do_after(user, 50/W.toolspeed, target = src) && !cell)
user.visible_message("[user] deconstructs [src]!", "<span class='notice'>You unfasten the securing bolts, and [src] falls to pieces!</span>")
deconstruct()
else if(istype(W, /obj/item/weapon/aiModule))
var/obj/item/weapon/aiModule/MOD = W
if(!opened)
user << "<span class='warning'>You need access to the robot's insides to do that!</span>"
return
if(wiresexposed)
user << "<span class='warning'>You need to close the wire panel to do that!</span>"
return
if(!cell)
user << "<span class='warning'>You need to install a power cell to do that!</span>"
return
if(emagged || (connected_ai && lawupdate)) //Can't be sure which, metagamers
emote("buzz-[user.name]")
return
MOD.install(src, user) //Proc includes a success mesage so we don't need another one
return
else if(istype(W, /obj/item/device/encryptionkey/) && opened)
if(radio)//sanityyyyyy
radio.attackby(W,user)//GTFO, you have your own procs
else
user << "<span class='warning'>Unable to locate a radio!</span>"
else if (istype(W, /obj/item/weapon/card/id)||istype(W, /obj/item/device/pda)) // trying to unlock the interface with an ID card
if(emagged)//still allow them to open the cover
user << "<span class='notice'>The interface seems slightly damaged.</span>"
if(opened)
user << "<span class='warning'>You must close the cover to swipe an ID card!</span>"
else
if(allowed(usr))
locked = !locked
user << "<span class='notice'>You [ locked ? "lock" : "unlock"] [src]'s cover.</span>"
update_icons()
else
user << "<span class='danger'>Access denied.</span>"
else if(istype(W, /obj/item/borg/upgrade/))
var/obj/item/borg/upgrade/U = W
if(!opened)
user << "<span class='warning'>You must access the borgs internals!</span>"
else if(!src.module && U.require_module)
user << "<span class='warning'>The borg must choose a module before it can be upgraded!</span>"
else if(U.locked)
user << "<span class='warning'>The upgrade is locked and cannot be used yet!</span>"
else
if(!user.drop_item())
return
if(U.action(src))
user << "<span class='notice'>You apply the upgrade to [src].</span>"
U.loc = src
else
user << "<span class='danger'>Upgrade error.</span>"
else if(istype(W, /obj/item/device/toner))
if(toner >= tonermax)
user << "<span class='warning'>The toner level of [src] is at it's highest level possible!</span>"
else
if(!user.drop_item())
return
toner = tonermax
qdel(W)
user << "<span class='notice'>You fill the toner level of [src] to its max capacity.</span>"
else
if(W.force && W.damtype != STAMINA && src.stat != DEAD) //only sparks if real damage is dealt.
spark_system.start()
return ..()
/mob/living/silicon/robot/emag_act(mob/user)
if(user != src)//To prevent syndieborgs from emagging themselves
if(!opened)//Cover is closed
if(locked)
user << "<span class='notice'>You emag the cover lock.</span>"
locked = 0
else
user << "<span class='warning'>The cover is already unlocked!</span>"
return
if(opened)//Cover is open
if((world.time - 100) < emag_cooldown)
return
var/ai_is_antag = 0
if(connected_ai && connected_ai.mind)
if(connected_ai.mind.special_role)
ai_is_antag = (connected_ai.mind.special_role == "traitor")
if(ai_is_antag)
user << "<span class='notice'>You emag [src]'s interface.</span>"
src << "<span class='danger'>ALERT: Foreign software execution prevented.</span>"
connected_ai << "<span class='danger'>ALERT: Cyborg unit \[[src]] successfuly defended against subversion.</span>"
log_game("[key_name(user)] attempted to emag cyborg [key_name(src)] slaved to traitor AI [connected_ai].")
emag_cooldown = world.time
return
if(wiresexposed)
user << "<span class='warning'>You must close the cover first!</span>"
return
else
emag_cooldown = world.time
sleep(6)
SetEmagged(1)
SetLockdown(1) //Borgs were getting into trouble because they would attack the emagger before the new laws were shown
lawupdate = 0
connected_ai = null
user << "<span class='notice'>You emag [src]'s interface.</span>"
message_admins("[key_name_admin(user)] emagged cyborg [key_name_admin(src)]. Laws overridden.")
log_game("[key_name(user)] emagged cyborg [key_name(src)]. Laws overridden.")
clear_supplied_laws()
clear_inherent_laws()
clear_zeroth_law(0)
laws = new /datum/ai_laws/syndicate_override
var/time = time2text(world.realtime,"hh:mm:ss")
lawchanges.Add("[time] <B>:</B> [user.name]([user.key]) emagged [name]([key])")
set_zeroth_law("Only [user.real_name] and people they designate as being such are Syndicate Agents.")
src << "<span class='danger'>ALERT: Foreign software detected.</span>"
sleep(5)
src << "<span class='danger'>Initiating diagnostics...</span>"
sleep(20)
src << "<span class='danger'>SynBorg v1.7 loaded.</span>"
sleep(5)
src << "<span class='danger'>LAW SYNCHRONISATION ERROR</span>"
sleep(5)
src << "<span class='danger'>Would you like to send a report to NanoTraSoft? Y/N</span>"
sleep(10)
src << "<span class='danger'>> N</span>"
sleep(20)
src << "<span class='danger'>ERRORERRORERROR</span>"
src << "<b>Obey these laws:</b>"
laws.show_laws(src)
src << "<span class='danger'>ALERT: [user.real_name] is your new master. Obey your new laws and their commands.</span>"
SetLockdown(0)
update_icons()
/mob/living/silicon/robot/verb/unlock_own_cover()
set category = "Robot Commands"
set name = "Unlock Cover"
set desc = "Unlocks your own cover if it is locked. You can not lock it again. A human will have to lock it for you."
if(stat == DEAD)
return //won't work if dead
if(locked)
switch(alert("You can not lock your cover again, are you sure?\n (You can still ask for a human to lock it)", "Unlock Own Cover", "Yes", "No"))
if("Yes")
locked = 0
update_icons()
usr << "<span class='notice'>You unlock your cover.</span>"
/mob/living/silicon/robot/attack_alien(mob/living/carbon/alien/humanoid/M)
if (M.a_intent =="disarm")
if(!(lying))
M.do_attack_animation(src)
if (prob(85))
Stun(2)
step(src,get_dir(M,src))
spawn(5)
step(src,get_dir(M,src))
add_logs(M, src, "pushed")
playsound(loc, 'sound/weapons/pierce.ogg', 50, 1, -1)
visible_message("<span class='danger'>[M] has forced back [src]!</span>", \
"<span class='userdanger'>[M] has forced back [src]!</span>")
else
playsound(loc, 'sound/weapons/slashmiss.ogg', 25, 1, -1)
visible_message("<span class='danger'>[M] took a swipe at [src]!</span>", \
"<span class='userdanger'>[M] took a swipe at [src]!</span>")
else
..()
return
/mob/living/silicon/robot/attack_slime(mob/living/simple_animal/slime/M)
if(..()) //successful slime shock
flick("noise", flash)
var/stunprob = M.powerlevel * 7 + 10
if(prob(stunprob) && M.powerlevel >= 8)
adjustBruteLoss(M.powerlevel * rand(6,10))
var/damage = rand(1, 3)
if(M.is_adult)
damage = rand(20, 40)
else
damage = rand(5, 35)
damage = round(damage / 2) // borgs recieve half damage
adjustBruteLoss(damage)
updatehealth()
return
/mob/living/silicon/robot/attack_hand(mob/living/carbon/human/user)
add_fingerprint(user)
if(opened && !wiresexposed && (!istype(user, /mob/living/silicon)))
if(cell)
cell.updateicon()
cell.add_fingerprint(user)
user.put_in_active_hand(cell)
user << "<span class='notice'>You remove \the [cell].</span>"
cell = null
update_icons()
diag_hud_set_borgcell()
if(!opened)
if(..()) // hulk attack
spark_system.start()
spawn(0)
step_away(src,user,15)
sleep(3)
step_away(src,user,15)
/mob/living/silicon/robot/proc/allowed(mob/M)
//check if it doesn't require any access at all
if(check_access(null))
return 1
if(istype(M, /mob/living/carbon/human))
var/mob/living/carbon/human/H = M
//if they are holding or wearing a card that has access, that works
if(check_access(H.get_active_hand()) || check_access(H.wear_id))
return 1
else if(istype(M, /mob/living/carbon/monkey))
var/mob/living/carbon/monkey/george = M
//they can only hold things :(
if(istype(george.get_active_hand(), /obj/item))
return check_access(george.get_active_hand())
return 0
/mob/living/silicon/robot/proc/check_access(obj/item/weapon/card/id/I)
if(!istype(req_access, /list)) //something's very wrong
return 1
var/list/L = req_access
if(!L.len) //no requirements
return 1
if(!istype(I, /obj/item/weapon/card/id) && istype(I, /obj/item))
I = I.GetID()
if(!I || !I.access) //not ID or no access
return 0
for(var/req in req_access)
if(!(req in I.access)) //doesn't have this access
return 0
return 1
/mob/living/silicon/robot/regenerate_icons()
return update_icons()
/mob/living/silicon/robot/update_icons()
overlays.Cut()
if(stat != DEAD && !(paralysis || stunned || weakened)) //Not dead, not stunned.
var/state_name = icon_state //For easy conversion and/or different names
switch(icon_state)
if("robot")
overlays += "eyes-standard"
state_name = "standard"
if("mediborg")
overlays += "eyes-mediborg"
if("toiletbot")
overlays += "eyes-mediborg"
state_name = "mediborg"
if("secborg")
overlays += "eyes-secborg"
if("engiborg")
overlays += "eyes-engiborg"
if("janiborg")
overlays += "eyes-janiborg"
if("minerborg")
overlays += "eyes-minerborg"
if("syndie_bloodhound")
overlays += "eyes-syndie_bloodhound"
else
overlays += "eyes"
state_name = "serviceborg"
if(lamp_intensity > 2)
overlays += "eyes-[state_name]-lights"
if(opened)
if(wiresexposed)
overlays += "ov-opencover +w"
else if(cell)
overlays += "ov-opencover +c"
else
overlays += "ov-opencover -c"
if(jetpackoverlay)
overlays += "minerjetpack"
update_fire()
/mob/living/silicon/robot/proc/installed_modules()
if(!module)
pick_module()
return
var/dat = {"<A HREF='?src=\ref[src];mach_close=robotmod'>Close</A>
<BR>
<BR>
<B>Activated Modules</B>
<BR>
<table border='0'>
<tr><td>Module 1:</td><td>[module_state_1 ? "<A HREF=?src=\ref[src];mod=\ref[module_state_1]>[module_state_1]<A>" : "No Module"]</td></tr>
<tr><td>Module 2:</td><td>[module_state_2 ? "<A HREF=?src=\ref[src];mod=\ref[module_state_2]>[module_state_2]<A>" : "No Module"]</td></tr>
<tr><td>Module 3:</td><td>[module_state_3 ? "<A HREF=?src=\ref[src];mod=\ref[module_state_3]>[module_state_3]<A>" : "No Module"]</td></tr>
</table><BR>
<B>Installed Modules</B><BR><BR>
<table border='0'>"}
for (var/obj in module.modules)
if (!obj)
dat += text("<tr><td><B>Resource depleted</B></td></tr>")
else if(activated(obj))
dat += text("<tr><td>[obj]</td><td><B>Activated</B></td></tr>")
else
dat += text("<tr><td>[obj]</td><td><A HREF=?src=\ref[src];act=\ref[obj]>Activate</A></td></tr>")
if (emagged)
if(activated(module.emag))
dat += text("<tr><td>[module.emag]</td><td><B>Activated</B></td></tr>")
else
dat += text("<tr><td>[module.emag]</td><td><A HREF=?src=\ref[src];act=\ref[module.emag]>Activate</A></td></tr>")
dat += "</table>"
/*
if(activated(obj))
dat += text("[obj]: \[<B>Activated</B> | <A HREF=?src=\ref[src];deact=\ref[obj]>Deactivate</A>\]<BR>")
else
dat += text("[obj]: \[<A HREF=?src=\ref[src];act=\ref[obj]>Activate</A> | <B>Deactivated</B>\]<BR>")
*/
var/datum/browser/popup = new(src, "robotmod", "Modules")
popup.set_content(dat)
popup.open()
/mob/living/silicon/robot/Topic(href, href_list)
..()
if(usr && (src != usr))
return
if (href_list["mach_close"])
var/t1 = text("window=[href_list["mach_close"]]")
unset_machine()
src << browse(null, t1)
return
if (href_list["showalerts"])
robot_alerts()
return
if (href_list["mod"])
var/obj/item/O = locate(href_list["mod"])
if (O)
O.attack_self(src)
if (href_list["act"])
var/obj/item/O = locate(href_list["act"])
activate_module(O)
installed_modules()
if (href_list["deact"])
var/obj/item/O = locate(href_list["deact"])
if(activated(O))
if(module_state_1 == O)
module_state_1 = null
contents -= O
else if(module_state_2 == O)
module_state_2 = null
contents -= O
else if(module_state_3 == O)
module_state_3 = null
contents -= O
else
src << "Module isn't activated."
else
src << "Module isn't activated"
installed_modules()
return
/mob/living/silicon/robot/proc/radio_menu()
radio.interact(src)//Just use the radio's Topic() instead of bullshit special-snowflake code
#define BORG_CAMERA_BUFFER 30
/mob/living/silicon/robot/Move(a, b, flag)
var/oldLoc = src.loc
. = ..()
if(.)
if(src.camera)
if(!updating)
updating = 1
spawn(BORG_CAMERA_BUFFER)
if(oldLoc != src.loc)
cameranet.updatePortableCamera(src.camera)
updating = 0
if(module)
if(module.type == /obj/item/weapon/robot_module/janitor)
var/turf/tile = loc
if(isturf(tile))
tile.clean_blood()
for(var/A in tile)
if(istype(A, /obj/effect))
if(is_cleanable(A))
qdel(A)
else if(istype(A, /obj/item))
var/obj/item/cleaned_item = A
cleaned_item.clean_blood()
else if(istype(A, /mob/living/carbon/human))
var/mob/living/carbon/human/cleaned_human = A
if(cleaned_human.lying)
if(cleaned_human.head)
cleaned_human.head.clean_blood()
cleaned_human.update_inv_head()
if(cleaned_human.wear_suit)
cleaned_human.wear_suit.clean_blood()
cleaned_human.update_inv_wear_suit()
else if(cleaned_human.w_uniform)
cleaned_human.w_uniform.clean_blood()
cleaned_human.update_inv_w_uniform()
if(cleaned_human.shoes)
cleaned_human.shoes.clean_blood()
cleaned_human.update_inv_shoes()
cleaned_human.clean_blood()
cleaned_human << "<span class='danger'>[src] cleans your face!</span>"
return
if(module.type == /obj/item/weapon/robot_module/miner)
if(istype(loc, /turf/simulated/floor/plating/asteroid))
if(istype(module_state_1,/obj/item/weapon/storage/bag/ore))
loc.attackby(module_state_1,src)
else if(istype(module_state_2,/obj/item/weapon/storage/bag/ore))
loc.attackby(module_state_2,src)
else if(istype(module_state_3,/obj/item/weapon/storage/bag/ore))
loc.attackby(module_state_3,src)
#undef BORG_CAMERA_BUFFER
/mob/living/silicon/robot/proc/self_destruct()
if(emagged)
if(mmi)
qdel(mmi)
explosion(src.loc,1,2,4,flame_range = 2)
else
explosion(src.loc,-1,0,2)
gib()
return
/mob/living/silicon/robot/proc/UnlinkSelf()
if (src.connected_ai)
src.connected_ai = null
lawupdate = 0
lockcharge = 0
canmove = 1
scrambledcodes = 1
//Disconnect it's camera so it's not so easily tracked.
if(src.camera)
qdel(src.camera)
src.camera = null
// I'm trying to get the Cyborg to not be listed in the camera list
// Instead of being listed as "deactivated". The downside is that I'm going
// to have to check if every camera is null or not before doing anything, to prevent runtime errors.
// I could change the network to null but I don't know what would happen, and it seems too hacky for me.
/mob/living/silicon/robot/proc/ResetSecurityCodes()
set category = "Robot Commands"
set name = "Reset Identity Codes"
set desc = "Scrambles your security and identification codes and resets your current buffers. Unlocks you and but permenantly severs you from your AI and the robotics console and will deactivate your camera system."
var/mob/living/silicon/robot/R = src
if(R)
R.UnlinkSelf()
R << "Buffers flushed and reset. Camera system shutdown. All systems operational."
src.verbs -= /mob/living/silicon/robot/proc/ResetSecurityCodes
/mob/living/silicon/robot/mode()
set name = "Activate Held Object"
set category = "IC"
set src = usr
var/obj/item/W = get_active_hand()
if (W)
W.attack_self(src)
return
/mob/living/silicon/robot/proc/SetLockdown(state = 1)
// They stay locked down if their wire is cut.
if(wires.LockedCut())
state = 1
if(state)
throw_alert("locked", /obj/screen/alert/locked)
else
clear_alert("locked")
lockcharge = state
update_canmove()
/mob/living/silicon/robot/proc/SetEmagged(new_state)
emagged = new_state
if(new_state)
if(src.module)
src.module.on_emag()
else
if (module)
uneq_module(module.emag)
if(hud_used)
hud_used.update_robot_modules_display() //Shows/hides the emag item if the inventory screen is already open.
update_icons()
if(emagged)
throw_alert("hacked", /obj/screen/alert/hacked)
else
clear_alert("hacked")
/mob/living/silicon/robot/verb/outputlaws()
set category = "Robot Commands"
set name = "State Laws"
if(usr.stat == DEAD)
return //won't work if dead
checklaws()
/mob/living/silicon/robot/verb/set_automatic_say_channel() //Borg version of setting the radio for autosay messages.
set name = "Set Auto Announce Mode"
set desc = "Modify the default radio setting for stating your laws."
set category = "Robot Commands"
if(usr.stat == DEAD)
return //won't work if dead
set_autosay()
/mob/living/silicon/robot/proc/control_headlamp()
if(stat || lamp_recharging)
src << "<span class='danger'>This function is currently offline.</span>"
return
//Some sort of magical "modulo" thing which somehow increments lamp power by 2, until it hits the max and resets to 0.
lamp_intensity = (lamp_intensity+2) % (lamp_max+2)
src << "[lamp_intensity ? "Headlamp power set to Level [lamp_intensity/2]" : "Headlamp disabled."]"
update_headlamp()
/mob/living/silicon/robot/proc/update_headlamp(var/turn_off = 0, var/cooldown = 100)
SetLuminosity(0)
if(lamp_intensity && (turn_off || stat))
src << "<span class='danger'>Your headlamp has been deactivated.</span>"
lamp_intensity = 0
lamp_recharging = 1
spawn(cooldown) //10 seconds by default, if the source of the deactivation does not keep stat that long.
lamp_recharging = 0
else
AddLuminosity(lamp_intensity)
if(lamp_button)
lamp_button.icon_state = "lamp[lamp_intensity]"
update_icons()
/mob/living/silicon/robot/proc/deconstruct()
var/turf/T = get_turf(src)
if (robot_suit)
robot_suit.loc = T
robot_suit.l_leg.loc = T
robot_suit.l_leg = null
robot_suit.r_leg.loc = T
robot_suit.r_leg = null
new /obj/item/stack/cable_coil(T, robot_suit.chest.wires)
robot_suit.chest.loc = T
robot_suit.chest.wires = 0
robot_suit.chest = null
robot_suit.l_arm.loc = T
robot_suit.l_arm = null
robot_suit.r_arm.loc = T
robot_suit.r_arm = null
robot_suit.head.loc = T
robot_suit.head.flash1.loc = T
robot_suit.head.flash1.burn_out()
robot_suit.head.flash1 = null
robot_suit.head.flash2.loc = T
robot_suit.head.flash2.burn_out()
robot_suit.head.flash2 = null
robot_suit.head = null
robot_suit.updateicon()
else
new /obj/item/robot_parts/robot_suit(T)
new /obj/item/robot_parts/l_leg(T)
new /obj/item/robot_parts/r_leg(T)
new /obj/item/stack/cable_coil(T, 1)
new /obj/item/robot_parts/chest(T)
new /obj/item/robot_parts/l_arm(T)
new /obj/item/robot_parts/r_arm(T)
new /obj/item/robot_parts/head(T)
var/b
for(b=0, b!=2, b++)
var/obj/item/device/assembly/flash/handheld/F = new /obj/item/device/assembly/flash/handheld(T)
F.burn_out()
if (cell) //Sanity check.
cell.loc = T
cell = null
qdel(src)
/mob/living/silicon/robot/syndicate
icon_state = "syndie_bloodhound"
lawupdate = 0
scrambledcodes = 1
modtype = "Synd"
faction = list("syndicate")
designation = "Syndicate Assault"
req_access = list(access_syndicate)
var/playstyle_string = "<span class='userdanger'>You are a Syndicate assault cyborg!</span><br>\
<b>You are armed with powerful offensive tools to aid you in your mission: help the operatives secure the nuclear authentication disk. \
Your cyborg LMG will slowly produce ammunition from your power supply, and your operative pinpointer will find and locate fellow nuclear operatives. \
<i>Help the operatives secure the disk at all costs!</i></b>"
/mob/living/silicon/robot/syndicate/New(loc)
..()
cell.maxcharge = 25000
cell.charge = 25000
radio = new /obj/item/device/radio/borg/syndicate(src)
module = new /obj/item/weapon/robot_module/syndicate(src)
laws = new /datum/ai_laws/syndicate_override()
spawn(5)
if(playstyle_string)
src << playstyle_string
/mob/living/silicon/robot/syndicate/medical
icon_state = "syndi-medi"
designation = "Syndicate Medical"
playstyle_string = "<span class='userdanger'>You are a Syndicate medical cyborg!</span><br>\
<b>You are armed with powerful medical tools to aid you in your mission: help the operatives secure the nuclear authentication disk. \
Your hypospray will produce Restorative Nanites, a wonder-drug that will heal most types of bodily damages, including clone and brain damage. It also produces morphine for offense. \
Your defibrillator paddles can revive operatives through their hardsuits, or can be used on harm intent to shock enemies! \
Your energy saw functions as a circular saw, but can be activated to deal more damage, and your operative pinpointer will find and locate fellow nuclear operatives. \
<i>Help the operatives secure the disk at all costs!</i></b>"
/mob/living/silicon/robot/syndicate/medical/New(loc)
..()
module = new /obj/item/weapon/robot_module/syndicate_medical(src)
/mob/living/silicon/robot/proc/notify_ai(notifytype, oldname, newname)
if(!connected_ai)
return
switch(notifytype)
if(1) //New Cyborg
connected_ai << "<br><br><span class='notice'>NOTICE - New cyborg connection detected: <a href='?src=\ref[connected_ai];track=[html_encode(name)]'>[name]</a></span><br>"
if(2) //New Module
connected_ai << "<br><br><span class='notice'>NOTICE - Cyborg module change detected: [name] has loaded the [designation] module.</span><br>"
if(3) //New Name
connected_ai << "<br><br><span class='notice'>NOTICE - Cyborg reclassification detected: [oldname] is now designated as [newname].</span><br>"
/mob/living/silicon/robot/canUseTopic(atom/movable/M, be_close = 0)
if(stat || lockcharge || stunned || weakened)
return
if(be_close && !in_range(M, src))
return
return 1