mirror of
https://github.com/yogstation13/Yogstation.git
synced 2025-02-26 09:04:50 +00:00
1314 lines
42 KiB
Plaintext
1314 lines
42 KiB
Plaintext
/mob/living/silicon/robot
|
|
name = "Cyborg"
|
|
real_name = "Cyborg"
|
|
icon = 'icons/mob/robots.dmi'
|
|
icon_state = "robot"
|
|
maxHealth = 100
|
|
health = 100
|
|
macro_default = "robot-default"
|
|
macro_hotkeys = "robot-hotkeys"
|
|
bubble_icon = "robot"
|
|
designation = "Default" //used for displaying the prefix & getting the current module of cyborg
|
|
has_limbs = 1
|
|
|
|
var/custom_name = ""
|
|
var/braintype = "Cyborg"
|
|
var/modtype = "robot"
|
|
var/obj/item/robot_parts/robot_suit/robot_suit = null //Used for deconstruction to remember what the borg was constructed out of..
|
|
var/obj/item/device/mmi/mmi = null
|
|
|
|
//Hud stuff
|
|
|
|
var/obj/screen/inv1 = null
|
|
var/obj/screen/inv2 = null
|
|
var/obj/screen/inv3 = null
|
|
var/obj/screen/lamp_button = null
|
|
var/obj/screen/thruster_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/obj/item/module_active = null
|
|
var/obj/item/module_state_1 = null
|
|
var/obj/item/module_state_2 = null
|
|
var/obj/item/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/opened = 0
|
|
var/emagged = 0
|
|
var/emag_cooldown = 0
|
|
var/wiresexposed = 0
|
|
|
|
var/ident = 0
|
|
var/locked = 1
|
|
var/list/req_access = list(access_robotics)
|
|
|
|
var/alarms = list("Motion"=list(), "Fire"=list(), "Atmosphere"=list(), "Power"=list(), "Camera"=list(), "Burglar"=list())
|
|
var/viewalerts = 0
|
|
|
|
var/speed = 0 // VTEC speed boost.
|
|
var/magpulse = FALSE // Magboot-like effect.
|
|
var/ionpulse = FALSE // Jetpack-like effect.
|
|
var/ionpulse_on = FALSE // Jetpack-like effect.
|
|
var/datum/effect_system/trail_follow/ion/ion_trail // Ionpulse effect.
|
|
|
|
var/low_power_mode = 0 //whether the robot has no charge left.
|
|
var/datum/effect_system/spark_spread/spark_system // So they can initialize sparks whenever/N
|
|
|
|
var/lawupdate = 1 //Cyborgs will sync their laws with their AI by default
|
|
var/scrambledcodes = 0 // Used to determine if a borg shows up on the robotics console. Setting to one hides them.
|
|
var/lockcharge //Boolean of whether the borg is locked down or not
|
|
|
|
var/toner = 0
|
|
var/tonermax = 40
|
|
|
|
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/sight_mode = 0
|
|
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 /datum/wires/robot(src)
|
|
|
|
robot_modules_background = new()
|
|
robot_modules_background.icon_state = "block"
|
|
robot_modules_background.layer = HUD_LAYER //Objects that appear on screen are on layer ABOVE_HUD_LAYER, 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.is_cut(WIRE_CAMERA))
|
|
camera.status = 0
|
|
..()
|
|
|
|
//MMI stuff. Held togheter by magic. ~Miauw
|
|
if(!mmi || !mmi.brainmob)
|
|
mmi = new (src)
|
|
mmi.brain = new /obj/item/organ/brain(mmi)
|
|
mmi.brain.name = "[real_name]'s brain"
|
|
mmi.icon_state = "mmi_full"
|
|
mmi.name = "Man-Machine Interface: [real_name]"
|
|
mmi.brainmob = new(mmi)
|
|
mmi.brainmob.name = src.real_name
|
|
mmi.brainmob.real_name = src.real_name
|
|
mmi.brainmob.container = mmi
|
|
|
|
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)
|
|
if(mmi.brainmob.stat == DEAD)
|
|
mmi.brainmob.stat = CONSCIOUS
|
|
dead_mob_list -= mmi.brainmob
|
|
living_mob_list += 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
|
|
|
|
var/list/modulelist = list("Standard", "Engineering", "Medical", "Miner", "Janitor","Service")
|
|
if(!config.forbid_peaceborg)
|
|
modulelist += "Peacekeeper"
|
|
if(!config.forbid_secborg)
|
|
modulelist += "Security"
|
|
|
|
designation = input("Please, select a module!", "Robot", null, null) in modulelist
|
|
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("Peacekeeper")
|
|
module = new /obj/item/weapon/robot_module/peacekeeper(src)
|
|
hands.icon_state = "standard"
|
|
icon_state = "peaceborg"
|
|
animation_length = 54
|
|
modtype = "Peace"
|
|
src << "<span class='userdanger'>Under ASIMOV, you are an enforcer of the PEACE and preventer of HUMAN HARM. You are not a security module and you are expected to follow orders and prevent harm above all else. Space law means nothing to you.</span>"
|
|
status_flags &= ~CANPUSH
|
|
feedback_inc("cyborg_peacekeeper",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.setDir(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)
|
|
src << "<span class='userdanger'>Alert: You are dead.</span>"
|
|
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/proc/ionpulse()
|
|
if(!ionpulse_on)
|
|
return
|
|
|
|
if(cell.charge <= 50)
|
|
toggle_ionpulse()
|
|
return
|
|
|
|
cell.charge -= 50 // 500 steps on a default cell.
|
|
return 1
|
|
|
|
/mob/living/silicon/robot/proc/toggle_ionpulse()
|
|
if(!ionpulse)
|
|
src << "<span class='notice'>No thrusters are installed!</span>"
|
|
return
|
|
|
|
if(!ion_trail)
|
|
ion_trail = new
|
|
ion_trail.set_up(src)
|
|
|
|
ionpulse_on = !ionpulse_on
|
|
src << "<span class='notice'>You [ionpulse_on ? null :"de"]activate your ion thrusters.</span>"
|
|
if(ionpulse_on)
|
|
ion_trail.start()
|
|
else
|
|
ion_trail.stop()
|
|
if(thruster_button)
|
|
thruster_button.icon_state = "ionpulse[ionpulse_on]"
|
|
|
|
/mob/living/silicon/robot/blob_act(obj/effect/blob/B)
|
|
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)
|
|
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(ignore_grab)
|
|
. = 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 == DEAD)
|
|
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/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, 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)
|
|
user.changeNext_move(CLICK_CD_MELEE)
|
|
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(is_wire_tool(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
|
|
if(!mind) //A player mind is required for law procs to run antag checks.
|
|
user << "<span class='warning'>[src] is entirely unresponsive!</span>"
|
|
return
|
|
MOD.install(laws, 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
|
|
return ..()
|
|
|
|
/mob/living/silicon/robot/attacked_by(obj/item/I, mob/living/user, def_zone)
|
|
if(I.force && I.damtype != STAMINA && 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
|
|
|
|
if(syndicate)
|
|
user << "<span class='notice'>You emag [src]'s interface.</span>"
|
|
src << "<span class='danger'>ALERT: Foreign software execution prevented.</span>"
|
|
log_game("[key_name(user)] attempted to emag cyborg [key_name(src)] but they were a syndicate cyborg.")
|
|
emag_cooldown = world.time
|
|
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 unexpose the wires 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))
|
|
addtimer(src, "step", 5, FALSE, 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
|
|
flash_eyes()
|
|
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()
|
|
cut_overlays()
|
|
if(stat != DEAD && !(paralysis || stunned || weakened || low_power_mode)) //Not dead, not stunned.
|
|
var/state_name = icon_state //For easy conversion and/or different names
|
|
switch(icon_state)
|
|
if("robot")
|
|
add_overlay("eyes-standard[is_servant_of_ratvar(src) ? "_r" : ""]") //Cyborgs converted by Ratvar have yellow eyes rather than blue
|
|
state_name = "standard"
|
|
if("mediborg")
|
|
add_overlay("eyes-mediborg[is_servant_of_ratvar(src) ? "_r" : ""]")
|
|
if("toiletbot")
|
|
add_overlay("eyes-mediborg[is_servant_of_ratvar(src) ? "_r" : ""]")
|
|
state_name = "mediborg"
|
|
if("secborg")
|
|
add_overlay("eyes-secborg[is_servant_of_ratvar(src) ? "_r" : ""]")
|
|
if("engiborg")
|
|
add_overlay("eyes-engiborg[is_servant_of_ratvar(src) ? "_r" : ""]")
|
|
if("janiborg")
|
|
add_overlay("eyes-janiborg[is_servant_of_ratvar(src) ? "_r" : ""]")
|
|
if("minerborg","ashborg")
|
|
add_overlay("eyes-minerborg[is_servant_of_ratvar(src) ? "_r" : ""]")
|
|
state_name = "minerborg"
|
|
if("peaceborg")
|
|
add_overlay("eyes-peaceborg[is_servant_of_ratvar(src) ? "_r" : ""]")
|
|
if("syndie_bloodhound")
|
|
add_overlay("eyes-syndie_bloodhound")
|
|
else
|
|
add_overlay("eyes")
|
|
state_name = "serviceborg"
|
|
if(lamp_intensity > 2)
|
|
add_overlay("eyes-[state_name]-lights")
|
|
|
|
if(opened)
|
|
if(wiresexposed)
|
|
add_overlay("ov-opencover +w")
|
|
else if(cell)
|
|
add_overlay("ov-opencover +c")
|
|
else
|
|
add_overlay("ov-opencover -c")
|
|
|
|
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()
|
|
|
|
#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.wash_cream()
|
|
cleaned_human << "<span class='danger'>[src] cleans your face!</span>"
|
|
return
|
|
|
|
if(module.type == /obj/item/weapon/robot_module/miner)
|
|
if(istype(loc, /turf/open/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)
|
|
connected_ai.connected_robots -= src
|
|
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 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
|
|
|
|
if(incapacitated())
|
|
return
|
|
var/obj/item/W = get_active_hand()
|
|
if(W)
|
|
W.attack_self(src)
|
|
|
|
|
|
/mob/living/silicon/robot/proc/SetLockdown(state = 1)
|
|
// They stay locked down if their wire is cut.
|
|
if(wires.is_cut(WIRE_LOCKDOWN))
|
|
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 || low_power_mode)
|
|
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 || low_power_mode))
|
|
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.wired)
|
|
robot_suit.chest.loc = T
|
|
robot_suit.chest.wired = 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"
|
|
modtype = "Synd"
|
|
faction = list("syndicate")
|
|
bubble_icon = "syndibot"
|
|
designation = "Syndicate Assault"
|
|
req_access = list(access_syndicate)
|
|
lawupdate = FALSE
|
|
scrambledcodes = TRUE // These are rogue borgs.
|
|
ionpulse = TRUE
|
|
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 || low_power_mode)
|
|
return
|
|
if(be_close && !in_range(M, src))
|
|
return
|
|
return 1
|
|
|
|
/mob/living/silicon/robot/updatehealth()
|
|
..()
|
|
if(health < maxHealth*0.5) //Gradual break down of modules as more damage is sustained
|
|
if(uneq_module(module_state_3))
|
|
src << "<span class='warning'>SYSTEM ERROR: Module 3 OFFLINE.</span>"
|
|
if(health < 0)
|
|
if(uneq_module(module_state_2))
|
|
src << "<span class='warning'>SYSTEM ERROR: Module 2 OFFLINE.</span>"
|
|
if(health < -maxHealth*0.5)
|
|
if(uneq_module(module_state_1))
|
|
src << "<span class='warning'>CRITICAL ERROR: All modules OFFLINE.</span>"
|
|
|
|
/mob/living/silicon/robot/update_sight()
|
|
if(!client)
|
|
return
|
|
if(stat == DEAD)
|
|
sight = (SEE_TURFS|SEE_MOBS|SEE_OBJS)
|
|
see_in_dark = 8
|
|
see_invisible = SEE_INVISIBLE_OBSERVER
|
|
return
|
|
|
|
see_invisible = initial(see_invisible)
|
|
see_in_dark = initial(see_in_dark)
|
|
sight = initial(sight)
|
|
|
|
if(client.eye != src)
|
|
var/atom/A = client.eye
|
|
if(A.update_remote_sight(src)) //returns 1 if we override all other sight updates.
|
|
return
|
|
|
|
if(sight_mode & BORGMESON)
|
|
sight |= SEE_TURFS
|
|
see_invisible = min(see_invisible, SEE_INVISIBLE_MINIMUM)
|
|
see_in_dark = 1
|
|
|
|
if(sight_mode & BORGMATERIAL)
|
|
sight |= SEE_OBJS
|
|
see_invisible = min(see_invisible, SEE_INVISIBLE_MINIMUM)
|
|
see_in_dark = 1
|
|
|
|
if(sight_mode & BORGXRAY)
|
|
sight |= (SEE_TURFS|SEE_MOBS|SEE_OBJS)
|
|
see_invisible = SEE_INVISIBLE_LIVING
|
|
see_in_dark = 8
|
|
|
|
if(sight_mode & BORGTHERM)
|
|
sight |= SEE_MOBS
|
|
see_invisible = min(see_invisible, SEE_INVISIBLE_LIVING)
|
|
see_in_dark = 8
|
|
|
|
if(see_override)
|
|
see_invisible = see_override
|
|
|
|
/mob/living/silicon/robot/update_stat()
|
|
if(status_flags & GODMODE)
|
|
return
|
|
if(stat != DEAD)
|
|
if(health <= -maxHealth) //die only once
|
|
death()
|
|
return
|
|
if(paralysis || stunned || weakened || getOxyLoss() > maxHealth*0.5)
|
|
if(stat == CONSCIOUS)
|
|
stat = UNCONSCIOUS
|
|
blind_eyes(1)
|
|
update_canmove()
|
|
update_headlamp()
|
|
else
|
|
if(stat == UNCONSCIOUS)
|
|
stat = CONSCIOUS
|
|
adjust_blindness(-1)
|
|
update_canmove()
|
|
update_headlamp()
|
|
diag_hud_set_status()
|
|
diag_hud_set_health()
|
|
update_health_hud()
|
|
|
|
/mob/living/silicon/robot/fully_replace_character_name(oldname, newname)
|
|
..()
|
|
if(oldname != real_name)
|
|
notify_ai(3, oldname, newname)
|
|
if(camera)
|
|
camera.c_tag = real_name
|
|
custom_name = newname
|
|
|
|
/mob/living/silicon/robot/emp_act(severity)
|
|
switch(severity)
|
|
if(1)
|
|
Stun(8)
|
|
if(2)
|
|
Stun(3)
|
|
..()
|
|
|
|
/mob/living/silicon/robot/revive(full_heal = 0, admin_revive = 0)
|
|
if(..()) //successfully ressuscitated from death
|
|
if(camera && !wires.is_cut(WIRE_CAMERA))
|
|
camera.toggle_cam(src,0)
|
|
update_headlamp()
|
|
if(admin_revive)
|
|
locked = 1
|
|
notify_ai(1)
|
|
. = 1
|