diff --git a/baystation12.dme b/baystation12.dme
index 9491f9c9b5a..85e8e0e4a6f 100644
--- a/baystation12.dme
+++ b/baystation12.dme
@@ -267,6 +267,7 @@
#include "code\game\dna\genes\powers.dm"
#include "code\game\dna\genes\vg_disabilities.dm"
#include "code\game\dna\genes\vg_powers.dm"
+#include "code\game\gamemodes\antag_spawner.dm"
#include "code\game\gamemodes\events.dm"
#include "code\game\gamemodes\factions.dm"
#include "code\game\gamemodes\game_mode.dm"
diff --git a/code/__HELPERS/unsorted.dm b/code/__HELPERS/unsorted.dm
index 23dc8639ab4..e641d8c773f 100644
--- a/code/__HELPERS/unsorted.dm
+++ b/code/__HELPERS/unsorted.dm
@@ -326,6 +326,13 @@ Turf and target are seperate in case you want to teleport some distance from a t
if(dna)
dna.real_name = real_name
+ if(isrobot(src))
+ var/mob/living/silicon/robot/R = src
+ if(oldname != real_name)
+ R.notify_ai(3, oldname, newname)
+ if(R.camera)
+ R.camera.c_tag = real_name
+
if(oldname)
//update the datacore records! This is goig to be a bit costly.
for(var/list/L in list(data_core.general,data_core.medical,data_core.security,data_core.locked))
diff --git a/code/_onclick/cyborg.dm b/code/_onclick/cyborg.dm
index 4dd6ae31655..5abc22d87ae 100644
--- a/code/_onclick/cyborg.dm
+++ b/code/_onclick/cyborg.dm
@@ -15,9 +15,6 @@
build_click(src, client.buildmode, params, A)
return
- if(stat || lockcharge || weakened || stunned || paralysis)
- return
-
var/list/modifiers = params2list(params)
if(modifiers["middle"])
MiddleClickOn(A)
@@ -32,19 +29,14 @@
CtrlClickOn(A)
return
+ if(stat || lockcharge || weakened || stunned || paralysis)
+ return
+
if(next_move >= world.time)
return
face_atom(A) // change direction to face what you clicked on
- if(aiCamera.in_camera_mode)
- aiCamera.camera_mode_off()
- if(is_component_functioning("camera"))
- aiCamera.captureimage(A, usr)
- else
- src << "Your camera isn't functional."
- return
-
/*
cyborg restrained() currently does nothing
if(restrained())
@@ -109,6 +101,43 @@
cycle_modules()
return
+//Give cyborgs hotkey clicks without breaking existing uses of hotkey clicks
+// for non-doors/apcs
+/mob/living/silicon/robot/ShiftClickOn(var/atom/A)
+ A.BorgShiftClick(src)
+/mob/living/silicon/robot/CtrlClickOn(var/atom/A)
+ A.BorgCtrlClick(src)
+/mob/living/silicon/robot/AltClickOn(var/atom/A)
+ A.BorgAltClick(src)
+
+/atom/proc/BorgShiftClick()
+ return
+
+/obj/machinery/door/airlock/BorgShiftClick() // Opens and closes doors! Forwards to AI code.
+ AIShiftClick()
+
+/atom/proc/BorgCtrlClick(var/mob/living/silicon/robot/user) //forward to human click if not overriden
+ CtrlClick(user)
+
+/obj/machinery/door/airlock/BorgCtrlClick() // Bolts doors. Forwards to AI code.
+ AICtrlClick()
+
+/obj/machinery/power/apc/BorgCtrlClick() // turns off/on APCs. Forwards to AI code.
+ AICtrlClick()
+
+/obj/machinery/turretid/BorgCtrlClick() //turret control on/off. Forwards to AI code.
+ AICtrlClick()
+
+/atom/proc/BorgAltClick(var/mob/living/silicon/robot/user)
+ AltClick(user)
+ return
+
+/obj/machinery/door/airlock/BorgAltClick() // Eletrifies doors. Forwards to AI code.
+ AIAltClick()
+
+/obj/machinery/turretid/BorgAltClick() //turret lethal on/off. Forwards to AI code.
+ AIAltClick()
+
/*
As with AI, these are not used in click code,
because the code for robots is specific, not generic.
diff --git a/code/_onclick/hud/screen_objects.dm b/code/_onclick/hud/screen_objects.dm
index e2ccc88cd2c..feee4923883 100644
--- a/code/_onclick/hud/screen_objects.dm
+++ b/code/_onclick/hud/screen_objects.dm
@@ -498,7 +498,7 @@
var/mob/living/silicon/ai/AI = usr
AI.toggle_camera_light()
- if("Crew Monitorting")
+ if("Crew Monitoring")
if(isAI(usr))
var/mob/living/silicon/ai/AI = usr
var/obj/machinery/computer/crew/C = locate(/obj/machinery/computer/crew)
diff --git a/code/datums/uplink_item.dm b/code/datums/uplink_item.dm
index 7aa4804b361..89bfe35d7de 100644
--- a/code/datums/uplink_item.dm
+++ b/code/datums/uplink_item.dm
@@ -285,6 +285,19 @@ var/list/uplink_items = list()
item = /obj/mecha/combat/marauder/mauler/loaded
cost = 140
gamemodes = list("nuclear emergency")
+
+/datum/uplink_item/dangerous/syndieborg
+ name = "Syndicate Cyborg"
+ desc = "A cyborg designed and programmed for systematic extermination of non-Syndicate personnel."
+ item = /obj/item/weapon/antag_spawner/borg_tele
+ cost = 50
+ gamemodes = list("nuclear emergency")
+
+//for refunding the syndieborg teleporter
+/datum/uplink_item/dangerous/syndieborg/spawn_item()
+ var/obj/item/weapon/antag_spawner/borg_tele/T = ..()
+ if(istype(T))
+ T.TC_cost = cost
// Ammunition
diff --git a/code/datums/wires/robot.dm b/code/datums/wires/robot.dm
index e05b543d420..6d839d77770 100644
--- a/code/datums/wires/robot.dm
+++ b/code/datums/wires/robot.dm
@@ -66,6 +66,7 @@ var/const/BORG_WIRE_LAWCHECK = 16 // Not used on MoMMIs
if (BORG_WIRE_AI_CONTROL) //pulse the AI wire to make the borg reselect an AI
if(!R.emagged)
R.connected_ai = select_active_ai()
+ R.notify_ai(1)
if (BORG_WIRE_CAMERA)
if(!isnull(R.camera) && R.camera.can_use() && !R.scrambledcodes)
diff --git a/code/game/gamemodes/antag_spawner.dm b/code/game/gamemodes/antag_spawner.dm
new file mode 100644
index 00000000000..16b94310c64
--- /dev/null
+++ b/code/game/gamemodes/antag_spawner.dm
@@ -0,0 +1,42 @@
+/obj/item/weapon/antag_spawner
+ throw_speed = 1
+ throw_range = 5
+ w_class = 1.0
+ var/used = 0
+
+/obj/item/weapon/antag_spawner/proc/spawn_antag(var/client/C, var/turf/T, var/type = "")
+ return
+
+/obj/item/weapon/antag_spawner/proc/equip_antag(mob/target as mob)
+ return
+
+
+/obj/item/weapon/antag_spawner/borg_tele
+ name = "Syndicate Cyborg Teleporter"
+ desc = "A single-use teleporter used to deploy a Syndicate Cyborg on the field."
+ icon = 'icons/obj/device.dmi'
+ icon_state = "locator"
+ var/TC_cost = 0
+
+/obj/item/weapon/antag_spawner/borg_tele/attack_self(mob/user as mob)
+ if(used)
+ user << "The teleporter is out of power."
+ return
+ var/list/borg_candicates = get_candidates(BE_OPERATIVE)
+ if(borg_candicates.len > 0)
+ used = 1
+ var/client/C = pick(borg_candicates)
+ spawn_antag(C, get_turf(src.loc), "syndieborg")
+ else
+ user << "Unable to connect to Syndicate Command. Please wait and try again later or use the teleporter on your uplink to get your points refunded."
+
+/obj/item/weapon/antag_spawner/borg_tele/spawn_antag(var/client/C, var/turf/T, var/type = "")
+ var/datum/effect/effect/system/spark_spread/S = new /datum/effect/effect/system/spark_spread
+ S.set_up(4, 1, src)
+ S.start()
+ var/mob/living/silicon/robot/R = new /mob/living/silicon/robot/syndicate(T)
+ R.key = C.key
+ ticker.mode.syndicates += R.mind
+ ticker.mode.update_synd_icons_added(R.mind)
+ R.mind.special_role = "syndicate"
+ R.faction = list("syndicate")
\ No newline at end of file
diff --git a/code/game/machinery/transformer.dm b/code/game/machinery/transformer.dm
index b0621c77926..b92d6086211 100644
--- a/code/game/machinery/transformer.dm
+++ b/code/game/machinery/transformer.dm
@@ -73,6 +73,7 @@
sleep(30)
if(R)
R.lockcharge = !R.lockcharge
+ R.notify_ai(1)
// Activate the cooldown
cooldown = 1
diff --git a/code/game/objects/items/devices/radio/radio.dm b/code/game/objects/items/devices/radio/radio.dm
index 23367fcd5e9..5427766c9dd 100644
--- a/code/game/objects/items/devices/radio/radio.dm
+++ b/code/game/objects/items/devices/radio/radio.dm
@@ -296,7 +296,8 @@ var/GLOBAL_RADIO_TYPE = 1 // radio type to use
// --- Cyborg ---
else if (isrobot(M))
- jobname = "Cyborg"
+ var/mob/living/silicon/robot/B = M
+ jobname = "[B.designation] Cyborg"
// --- Personal AI (pAI) ---
else if (istype(M, /mob/living/silicon/pai))
@@ -698,6 +699,13 @@ var/GLOBAL_RADIO_TYPE = 1 // radio type to use
/obj/item/device/radio/borg
var/obj/item/device/encryptionkey/keyslot = null//Borg radios can handle a single encryption key
+/obj/item/device/radio/borg/syndicate
+ syndie = 1
+ keyslot = new /obj/item/device/encryptionkey/syndicate
+/obj/item/device/radio/borg/syndicate/New()
+ ..()
+ set_frequency(SYND_FREQ)
+
/obj/item/device/radio/borg/attackby(obj/item/weapon/W as obj, mob/user as mob)
// ..()
user.set_machine(src)
diff --git a/code/game/objects/items/devices/uplinks.dm b/code/game/objects/items/devices/uplinks.dm
index de6dcdb21e3..17552882d66 100644
--- a/code/game/objects/items/devices/uplinks.dm
+++ b/code/game/objects/items/devices/uplinks.dm
@@ -249,6 +249,27 @@ var/list/world_uplinks = list()
src.hidden_uplink.trigger(user)
return 1
return 0
+
+//Refund proc for the borg teleporter (later I'll make a general refund proc if there is demand for it)
+/obj/item/device/radio/headset/syndicate/attackby(obj/item/weapon/W as obj, mob/user as mob)
+ if(istype(W, /obj/item/weapon/antag_spawner/borg_tele))
+ var/obj/item/weapon/antag_spawner/borg_tele/S = W
+ if(!S.used)
+ hidden_uplink.uses += S.TC_cost
+ qdel(S)
+ user << "Teleporter refunded."
+ else
+ user << "This teleporter is already used."
+
+/obj/item/device/radio/uplink/attackby(obj/item/weapon/W as obj, mob/user as mob)
+ if(istype(W, /obj/item/weapon/antag_spawner/borg_tele))
+ var/obj/item/weapon/antag_spawner/borg_tele/S = W
+ if(!S.used)
+ hidden_uplink.uses += S.TC_cost
+ qdel(S)
+ user << "Teleporter refunded."
+ else
+ user << "This teleporter is already used."
// PRESET UPLINKS
// A collection of preset uplinks.
diff --git a/code/game/objects/items/robot/robot_parts.dm b/code/game/objects/items/robot/robot_parts.dm
index 3538cfa18b8..43edfb5cf0b 100644
--- a/code/game/objects/items/robot/robot_parts.dm
+++ b/code/game/objects/items/robot/robot_parts.dm
@@ -211,7 +211,8 @@
O.invisibility = 0
O.custom_name = created_name
O.updatename("Default")
-
+ if(O.connected_ai)
+ O.notify_ai(1)
M.brainmob.mind.transfer_to(O)
if(O.mind && O.mind.special_role)
diff --git a/code/game/objects/items/robot/robot_upgrades.dm b/code/game/objects/items/robot/robot_upgrades.dm
index 315d9103dd4..66db8bfb189 100644
--- a/code/game/objects/items/robot/robot_upgrades.dm
+++ b/code/game/objects/items/robot/robot_upgrades.dm
@@ -35,6 +35,7 @@
R.camera.network.Remove(list("Engineering","Medical","MINE"))
R.updatename("Default")
R.status_flags |= CANPUSH
+ R.notify_ai(2)
R.updateicon()
return 1
@@ -51,6 +52,7 @@
/obj/item/borg/upgrade/rename/action(var/mob/living/silicon/robot/R)
if(..()) return 0
+ R.notify_ai(3, R.name, heldname)
R.name = heldname
R.custom_name = heldname
R.real_name = heldname
@@ -75,6 +77,9 @@
R.key = ghost.key
R.stat = CONSCIOUS
+ dead_mob_list -= R //please never forget this ever kthx
+ living_mob_list += R
+ R.notify_ai(1)
return 1
diff --git a/code/game/objects/items/weapons/implants/implant.dm b/code/game/objects/items/weapons/implants/implant.dm
index 5d2a35e4f21..cb07e4acd89 100644
--- a/code/game/objects/items/weapons/implants/implant.dm
+++ b/code/game/objects/items/weapons/implants/implant.dm
@@ -371,7 +371,7 @@ the implant may become unstable and either pre-maturely inject the subject or si
if(isliving(user))
user:brainloss += 20
return
- if(locate(/obj/item/weapon/implant/traitor) in H.contents || locate(/obj/item/weapon/implant/traitor) in H.contents)
+ if(locate(/obj/item/weapon/implant/traitor) in H.contents || locate(/obj/item/weapon/implant/loyalty) in H.contents)
H.visible_message("[H] seems to resist the implant!", "You feel a strange sensation in your head that quickly dissipates.")
return 0
else if(H.mind in ticker.mode.traitors)
diff --git a/code/game/objects/items/weapons/melee/energy.dm b/code/game/objects/items/weapons/melee/energy.dm
index 1443ebdc671..57ab498d97f 100644
--- a/code/game/objects/items/weapons/melee/energy.dm
+++ b/code/game/objects/items/weapons/melee/energy.dm
@@ -49,6 +49,20 @@
sharp = 1
edge = 1
+/obj/item/weapon/melee/energy/sword/cyborg
+ var/hitcost = 500
+
+/obj/item/weapon/melee/energy/sword/cyborg/attack(mob/M, var/mob/living/silicon/robot/R)
+ if(R.cell)
+ var/obj/item/weapon/cell/C = R.cell
+ if(active && !(C.use(hitcost)))
+ attack_self()
+ R << "It's out of charge!"
+ return
+ C.use(hitcost)
+ ..()
+ return
+
/obj/item/weapon/melee/energy/sword/pirate
name = "energy cutlass"
desc = "Arrrr matey."
diff --git a/code/modules/mob/living/silicon/robot/life.dm b/code/modules/mob/living/silicon/robot/life.dm
index 1eb397d48c6..7a30a91b8f4 100644
--- a/code/modules/mob/living/silicon/robot/life.dm
+++ b/code/modules/mob/living/silicon/robot/life.dm
@@ -39,6 +39,7 @@
uneq_all()
src.stat = 1
Paralyse(3)
+ has_power = 0
else
if(src.module_state_1)
src.cell.use(3)
@@ -55,6 +56,7 @@
Paralyse(3)
src.stat = 0
+ has_power = 1
else
uneq_all()
src.stat = 1
diff --git a/code/modules/mob/living/silicon/robot/robot.dm b/code/modules/mob/living/silicon/robot/robot.dm
index 1042f57f7bf..c63352389fe 100644
--- a/code/modules/mob/living/silicon/robot/robot.dm
+++ b/code/modules/mob/living/silicon/robot/robot.dm
@@ -72,6 +72,7 @@
var/pose
var/base_icon = ""
var/crisis = 0
+ var/syndicateborg = 0
/mob/living/silicon/robot/New(loc,var/syndie = 0,var/unfinished = 0, var/alien = 0)
spark_system = new /datum/effect/effect/system/spark_spread()
@@ -143,6 +144,9 @@
hud_list[NATIONS_HUD] = image('icons/mob/hud.dmi', src, "hudblank")
/mob/living/silicon/robot/proc/init(var/alien=0)
+ if(syndicateborg)
+ playsound(loc, 'sound/voice/liveagain.ogg', 75, 1)
+ return
aiCamera = new/obj/item/device/camera/siliconcam/robot_camera(src)
if(mmi.alien || alien)
laws = new /datum/ai_laws/alienmov()
@@ -187,7 +191,7 @@
if(mmi != null && mmi.alien)
modules="Hunter"
modtype = input("Please, select a module!", "Robot", null, null) in modules
-
+ designation = modtype
var/module_sprites[0] //Used to store the associations between sprite names and sprite index.
var/channels = list()
@@ -306,6 +310,7 @@
choose_icon(6,module_sprites)
radio.config(channels)
+ notify_ai(2)
/mob/living/silicon/robot/proc/updatename(var/prefix as text)
if(prefix)
@@ -359,6 +364,7 @@
var/newname
newname = copytext(sanitize(input(src,"You are a robot. Enter a name, or leave blank for the default name.", "Name change","") as text),1,MAX_NAME_LEN)
if (newname != "")
+ notify_ai(3, name, newname)
custom_name = newname
updatename()
@@ -1395,3 +1401,35 @@
return
else
src << "Your icon has been set. You now require a module reset to change it."
+
+/mob/living/silicon/robot/syndicate
+ icon_state = "syndie_bloodhound"
+ lawupdate = 0
+ scrambledcodes = 1
+ syndicateborg = 1
+ modtype = "Synd"
+ faction = list("syndicate")
+ designation = "Syndicate"
+ req_access = list(access_syndicate)
+
+
+/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()
+
+ Namepick()
+
+/mob/living/silicon/robot/proc/notify_ai(var/notifytype, var/oldname, var/newname)
+ if(!connected_ai)
+ return
+ switch(notifytype)
+ if(1) //New Cyborg
+ connected_ai << "
NOTICE - New cyborg connection detected: [name]
"
+ if(2) //New Module
+ connected_ai << "
NOTICE - Cyborg module change detected: [name] has loaded the [designation] module.
"
+ if(3) //New Name
+ connected_ai << "
NOTICE - Cyborg reclassification detected: [oldname] is now designated as [newname].
"
\ No newline at end of file
diff --git a/code/modules/mob/living/silicon/robot/robot_modules.dm b/code/modules/mob/living/silicon/robot/robot_modules.dm
index 69d5bde666b..408a0316ced 100644
--- a/code/modules/mob/living/silicon/robot/robot_modules.dm
+++ b/code/modules/mob/living/silicon/robot/robot_modules.dm
@@ -331,14 +331,16 @@
/obj/item/weapon/robot_module/syndicate
name = "syndicate robot module"
-
- New()
- src.modules += new /obj/item/device/flashlight(src)
- src.modules += new /obj/item/device/flash(src)
- src.modules += new /obj/item/weapon/melee/energy/sword(src)
- src.modules += new /obj/item/weapon/gun/energy/pulse_rifle/destroyer(src)
- src.modules += new /obj/item/weapon/card/emag(src)
- return
+/obj/item/weapon/robot_module/syndicate/New()
+ ..()
+ src.modules += new /obj/item/weapon/melee/energy/sword/cyborg(src)
+ src.modules += new /obj/item/weapon/gun/energy/crossbow/cyborg(src)
+ src.modules += new /obj/item/weapon/card/emag(src)
+ src.modules += new /obj/item/weapon/gun/energy/laser/cyborg(src)
+ src.modules += new /obj/item/weapon/tank/jetpack/carbondioxide(src)
+ src.modules += new /obj/item/weapon/crowbar(src)
+ emag = null
+ return
/obj/item/weapon/robot_module/combat
name = "combat robot module"
diff --git a/code/modules/mob/living/silicon/robot/robot_upgrades.dm b/code/modules/mob/living/silicon/robot/robot_upgrades.dm
deleted file mode 100644
index e512a6cccee..00000000000
--- a/code/modules/mob/living/silicon/robot/robot_upgrades.dm
+++ /dev/null
@@ -1,145 +0,0 @@
-// robot_upgrades.dm
-// Contains various borg upgrades.
-
-/obj/item/borg/upgrade/
- name = "A borg upgrade module."
- desc = "Protected by FRM."
- icon = 'icons/obj/module.dmi'
- icon_state = "cyborg_upgrade"
- var/construction_time = 120
- var/construction_cost = list("metal"=10000)
- var/locked = 0
- var/require_module = 0
- var/installed = 0
-
-/obj/item/borg/upgrade/proc/action()
- return
-
-
-/obj/item/borg/upgrade/reset/
- name = "Borg module reset board"
- desc = "Used to reset a borg's module. Destroys any other upgrades applied to the borg."
- icon_state = "cyborg_upgrade1"
- require_module = 1
-
-/obj/item/borg/upgrade/reset/action(var/mob/living/silicon/robot/R)
- R.uneq_all()
- del(R.module)
- R.module = null
- R.modtype = "robot"
- R.real_name = "Cyborg [R.ident]"
- R.name = R.real_name
- R.nopush = 0
- R.hands.icon_state = "nomod"
- R.base_icon = "robot"
- R.icon_state = "robot"
- R.updateicon()
-
- return 1
-
-
-
-/obj/item/borg/upgrade/flashproof/
- name = "Borg Flash-Supression"
- desc = "A highly advanced, complicated system for supressing incoming flashes directed at the borg's optical processing system."
- construction_cost = list("metal"=10000,"gold"=2000,"silver"=3000,"glass"=2000, "diamond"=5000)
- icon_state = "cyborg_upgrade4"
- require_module = 1
-
-
-/obj/item/borg/upgrade/flashproof/New() // Why the fuck does the fabricator make a new instance of all the items?
- //desc = "Sunglasses with duct tape." // Why? D:
-
-/obj/item/borg/upgrade/flashproof/action(var/mob/living/silicon/robot/R)
- if(R.module)
- R.module += src
-
- return 1
-
-/obj/item/borg/upgrade/restart/
- name = "Borg emergancy restart module"
- desc = "Used to force a restart of a disabled-but-repaired borg, bringing it back online."
- construction_cost = list("metal"=60000 , "glass"=5000)
- icon_state = "cyborg_upgrade1"
-
-
-/obj/item/borg/upgrade/restart/action(var/mob/living/silicon/robot/R)
- if(!R.key)
- for(var/mob/dead/observer/ghost in world)
- if(ghost.corpse == R && ghost.client)
- ghost.client.mob = ghost.corpse
-
- if(R.health < 0)
- usr << "You have to repair the borg before using this module!"
- return 0
-
- R.stat = 0
- return 1
-
-
-/obj/item/borg/upgrade/vtec/
- name = "Borg VTEC Module"
- desc = "Used to kick in a borgs VTEC systems, increasing their speed."
- construction_cost = list("metal"=80000 , "glass"=6000 , "gold"= 5000)
- icon_state = "cyborg_upgrade2"
- require_module = 1
-
-/obj/item/borg/upgrade/vtec/action(var/mob/living/silicon/robot/R)
- if(R.speed == -1)
- return 0
-
- R.speed--
- return 1
-
-
-/obj/item/borg/upgrade/tasercooler/
- name = "Borg Rapid Taser Cooling Module"
- desc = "Used to cool a mounted taser, increasing the potential current in it and thus its recharge rate.."
- construction_cost = list("metal"=80000 , "glass"=6000 , "gold"= 2000, "diamond" = 500)
- icon_state = "cyborg_upgrade3"
- require_module = 1
-
-
-/obj/item/borg/upgrade/tasercooler/action(var/mob/living/silicon/robot/R)
- if(!istype(R.module, /obj/item/weapon/robot_module/security))
- R << "Upgrade mounting error! No suitable hardpoint detected!"
- usr << "There's no mounting point for the module!"
- return 0
-
- var/obj/item/weapon/gun/energy/taser/cyborg/T = locate() in R.module
- if(!T)
- T = locate() in R.module.contents
- if(!T)
- T = locate() in R.module.modules
- if(!T)
- usr << "This cyborg has had its taser removed!"
- return 0
-
- if(T.recharge_time <= 2)
- R << "Maximum cooling achieved for this hardpoint!"
- usr << "There's no room for another cooling unit!"
- return 0
-
- else
- T.recharge_time = max(2 , T.recharge_time - 4)
-
- return 1
-
-/obj/item/borg/upgrade/jetpack/
- name = "Mining Borg Jetpack"
- desc = "A carbon dioxide jetpack suitable for low-gravity mining operations"
- construction_cost = list("metal"=10000,"plasma"=15000,"uranium" = 20000)
- icon_state = "cyborg_upgrade3"
- require_module = 1
-
-/obj/item/borg/upgrade/jetpack/action(var/mob/living/silicon/robot/R)
- if(!istype(R.module, /obj/item/weapon/robot_module/miner))
- R << "Upgrade mounting error! No suitable hardpoint detected!"
- usr << "There's no mounting point for the module!"
- return 0
- else
- R.module.modules += new/obj/item/weapon/tank/jetpack/carbondioxide
- for(var/obj/item/weapon/tank/jetpack/carbondioxide in R.module.modules)
- R.internals = src
- R.icon_state="Miner+j"
- return 1
diff --git a/code/modules/mob/living/silicon/say.dm b/code/modules/mob/living/silicon/say.dm
index 02e88982c40..04d55d5bd9b 100644
--- a/code/modules/mob/living/silicon/say.dm
+++ b/code/modules/mob/living/silicon/say.dm
@@ -111,21 +111,31 @@
log_say("[key_name(src)] : [message]")
+ var/desig = "Unknown" //ezmode for taters
+ if(isrobot(src))
+ var/mob/living/silicon/S = src
+ if(S.designation)
+ desig = trim_left(S.designation)
+ else
+ desig = "Default"
+ else if(isAI(src))
+ desig = "AI"
+
message = trim(message)
if (!message)
return
var/message_a = say_quote(message)
- var/rendered = "Robotic Talk, [name] [message_a]"
+ var/rendered = "Robotic Talk, [name] ([desig]) [message_a]"
for (var/mob/living/S in living_mob_list)
if(S.robot_talk_understand && (S.robot_talk_understand == robot_talk_understand)) // This SHOULD catch everything caught by the one below, but I'm not going to change it.
if(istype(S , /mob/living/silicon/ai))
- var/renderedAI = "Robotic Talk, [name] [message_a]"
+ var/renderedAI = "Robotic Talk, [name] ([desig]) [message_a]"
S.show_message(renderedAI, 2)
else if(istype(S , /mob/dead/observer) && S.stat == DEAD)
- var/rendered2 = "Robotic Talk, [name] (Follow) [message_a]"
+ var/rendered2 = "Robotic Talk, [name] ([desig]) (Follow) [message_a]"
S.show_message(rendered2, 2)
else
S.show_message(rendered, 2)
diff --git a/code/modules/mob/living/silicon/silicon.dm b/code/modules/mob/living/silicon/silicon.dm
index 8ef2da11ce4..9289de9139b 100644
--- a/code/modules/mob/living/silicon/silicon.dm
+++ b/code/modules/mob/living/silicon/silicon.dm
@@ -10,6 +10,7 @@
var/list/hud_list[10]
var/list/alarm_types_show = list("Motion" = 0, "Fire" = 0, "Atmosphere" = 0, "Power" = 0, "Camera" = 0)
var/list/alarm_types_clear = list("Motion" = 0, "Fire" = 0, "Atmosphere" = 0, "Power" = 0, "Camera" = 0)
+ var/designation = ""
var/obj/item/device/camera/siliconcam/aiCamera = null //photography
/mob/living/silicon/proc/cancelAlarm()
diff --git a/code/modules/mob/transform_procs.dm b/code/modules/mob/transform_procs.dm
index f192d7a7e6a..1bb1e451923 100644
--- a/code/modules/mob/transform_procs.dm
+++ b/code/modules/mob/transform_procs.dm
@@ -223,6 +223,7 @@
O.loc = loc
O.job = "Cyborg"
+ O.notify_ai(1)
if(O.mind.assigned_role == "Cyborg")
if(O.mind.role_alt_title == "Android")
diff --git a/code/modules/projectiles/guns/energy/stun.dm b/code/modules/projectiles/guns/energy/stun.dm
index 44ff7ab85b7..3bcce305294 100644
--- a/code/modules/projectiles/guns/energy/stun.dm
+++ b/code/modules/projectiles/guns/energy/stun.dm
@@ -18,31 +18,31 @@
var/charge_tick = 0
var/recharge_time = 10 //Time it takes for shots to recharge (in ticks)
- New()
- ..()
- processing_objects.Add(src)
+/obj/item/weapon/gun/energy/taser/cyborg/New()
+ ..()
+ processing_objects.Add(src)
- Destroy()
- processing_objects.Remove(src)
- ..()
+/obj/item/weapon/gun/energy/taser/cyborg/Destroy()
+ processing_objects.Remove(src)
+ ..()
- process() //Every [recharge_time] ticks, recharge a shot for the cyborg
- charge_tick++
- if(charge_tick < recharge_time) return 0
- charge_tick = 0
+/obj/item/weapon/gun/energy/taser/cyborg/process() //Every [recharge_time] ticks, recharge a shot for the cyborg
+ charge_tick++
+ if(charge_tick < recharge_time) return 0
+ charge_tick = 0
- if(!power_supply) return 0 //sanity
- if(power_supply.charge >= power_supply.maxcharge) return 0 // check if we actually need to recharge
+ if(!power_supply) return 0 //sanity
+ if(power_supply.charge >= power_supply.maxcharge) return 0 // check if we actually need to recharge
- if(isrobot(src.loc))
- var/mob/living/silicon/robot/R = src.loc
- if(R && R.cell)
- R.cell.use(charge_cost) //Take power from the borg...
- power_supply.give(charge_cost) //... to recharge the shot
+ if(isrobot(src.loc))
+ var/mob/living/silicon/robot/R = src.loc
+ if(R && R.cell)
+ R.cell.use(charge_cost) //Take power from the borg...
+ power_supply.give(charge_cost) //... to recharge the shot
- update_icon()
- return 1
+ update_icon()
+ return 1
/obj/item/weapon/gun/energy/stunrevolver
@@ -70,30 +70,39 @@
cell_type = "/obj/item/weapon/cell/crap"
var/charge_tick = 0
+/obj/item/weapon/gun/energy/crossbow/New()
+ ..()
+ processing_objects.Add(src)
- New()
- ..()
- processing_objects.Add(src)
+/obj/item/weapon/gun/energy/crossbow/Destroy()
+ processing_objects.Remove(src)
+ ..()
+/obj/item/weapon/gun/energy/crossbow/process()
+ charge_tick++
+ if(charge_tick < 4) return 0
+ charge_tick = 0
+ if(!power_supply) return 0
+ power_supply.give(1000)
+ return 1
- Destroy()
- processing_objects.Remove(src)
- ..()
-
-
- process()
- charge_tick++
- if(charge_tick < 4) return 0
- charge_tick = 0
- if(!power_supply) return 0
- power_supply.give(1000)
+/obj/item/weapon/gun/energy/crossbow/update_icon()
+ return
+
+/obj/item/weapon/gun/energy/crossbow/cyborg/process()
+ ..()
+ return
+
+/obj/item/weapon/gun/energy/crossbow/cyborg/process_chambered()
+ if(in_chamber)
return 1
-
-
- update_icon()
- return
-
-
+ if(isrobot(src.loc))
+ var/mob/living/silicon/robot/R = src.loc
+ if(R && R.cell)
+ R.cell.use(100)
+ in_chamber = new /obj/item/projectile/energy/bolt(src)
+ return 1
+ return 0
/obj/item/weapon/gun/energy/crossbow/largecrossbow
name = "Energy Crossbow"
diff --git a/icons/mob/robots.dmi b/icons/mob/robots.dmi
index b5a93c40940..a93050ba21b 100644
Binary files a/icons/mob/robots.dmi and b/icons/mob/robots.dmi differ
diff --git a/maps/cyberiad.dmm.backup b/maps/cyberiad.dmm.backup
index 190b5b7ee65..7c05f0b84ee 100644
--- a/maps/cyberiad.dmm.backup
+++ b/maps/cyberiad.dmm.backup
@@ -4973,8 +4973,8 @@
"bRG" = (/obj/machinery/atmospherics/pipe/simple{icon_state = "intact"; level = 2},/turf/simulated/floor,/area/medical/cryo)
"bRH" = (/obj/structure/table/woodentable,/obj/machinery/light/small/lamp/green,/turf/simulated/floor/wood,/area/medical/psych)
"bRI" = (/obj/structure/table/woodentable,/obj/machinery/computer/med_data/laptop,/obj/machinery/camera{c_tag = "Medbay Psych Office North"; network = list("SS13")},/turf/simulated/floor/wood,/area/medical/psych)
-"bRJ" = (/obj/structure/table/woodentable,/obj/item/weapon/storage/briefcase,/turf/simulated/floor/wood,/area/medical/psych)
-"bRK" = (/obj/machinery/light{dir = 1; on = 1},/obj/structure/flora/kirbyplants,/turf/simulated/floor/wood,/area/medical/psych)
+"bRJ" = (/obj/structure/closet/secure_closet/psychiatrist,/turf/simulated/floor/wood,/area/medical/psych)
+"bRK" = (/obj/structure/table/woodentable,/obj/item/weapon/storage/briefcase,/obj/machinery/light{dir = 1; on = 1},/turf/simulated/floor/wood,/area/medical/psych)
"bRL" = (/obj/machinery/atmospherics/pipe/simple/supply/hidden,/turf/simulated/floor/carpet,/area/medical/psych)
"bRM" = (/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden,/obj/structure/stool/bed/chair/comfy/black{dir = 4},/turf/simulated/floor/carpet,/area/medical/psych)
"bRN" = (/obj/structure/table/woodentable,/obj/machinery/light/small/lamp/green,/turf/simulated/floor/carpet,/area/medical/psych)
@@ -12549,7 +12549,7 @@ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabyLbyLbyLbyLbyLbyLbyLbyLby
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabyLbyLbyLbyLbyLbyLbyLbyLbyLaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabDZbDZbDZbDZbDZbDZbDZbHaanFbalbMfbFObFQbFObMgbMhbMibMibMibMjbMibMibMibMkbMibMibMlbMibMibMmbMnbMobMibBRbMqbMrbMsbMtbMsbMubMvbMwbMxbMybMzaaqbMAaaqbMBaaqaaqbGjeAibGjaaqaaqaaqbGbeAfbGiaaqaaqbMHbHGbHGbMIaaqaaqaaqanpbMJaaqaaqaaqbDXaaqaaqbwhaaqbRjanpaaqbMObHQbJEaaqbMRbBJbJCbThaaibMTbMUbMVbMWaaibzBbJKbMXaaqbMYbMZbNabNbbNcbNdabHbNebNfbNgbNhbNibNjbNkaaiaaiaaiaaiaaiaaiaaiaaiaaiaaibNlbNmbNnbNnaaqbNobNpbNqaaiaaiaaiaaiaaiaaiaaiaaibFCaaiaaabNrbNrbNraaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaiaaiaaiaaaaaaaabaaaaaaaaaaaaaaaaaaaaaaabbNsbNtbNtbNuaaqaaqaaiaaiaaiaaibNvaabaabaaaaaaaaaaagaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabyLbyLbyLbyLbyLbyLbyLbyLbyLaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabDZbDZbDZbDZbDZbDZbDZbKwbKxbKwbNwbHcbHebHcbNxbNybNzbNAbNAbNBbNAbNAbNCbNDbNAbNAbNEbNAbNAbNAbNAbNFbNGayObNHbNIbNJbNKbNJbNLbNMbNNbNObNPbKSaaqaaqaaqbNQayObNRbNSbNTbNUbNVaaqcvWbNXbNYbNZcvXaaqbObbOcbOdaaqbOebOfbOgbOhbOibOjbOkbOlbJGayObJJbJIbLvbLsbLpayObOtbOubOvbLobOxbOybOzbJDbOAbOBbOCbODbOEbOFbzJbOGbOHbOIbOJbOKbOKbOLbOMbONaaqbOObOPbOQbORbOSbOTbOUaaicfQbOWbOXaaibOYbOZbPabPbaaibPcbPdbPebPeaaqbPfbPgbGJaaibPhbPibPjbPkbPkbPjbPkbPlaaiaaabNrbPmbNraaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabaabaabbPnbPobPpbPoaaqaaiaaibPqbPrbPqbPsaaiaabaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabyLbyLbyLbyLbyLbyLbyLbyLbyLaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabDZbDZbDZbDZbDZbDZbDZbPtbPubPtbPvbPvbPwbPvbPvbPxbPvbPvbPvbPybPvbPvbPvbPzbPvbPvbPAbPvbPvbPvbPvbPvbPvbPBbPCbPDbMxbMxbMxbMxbMxbPEbPFbPGbPHbCzacvaaqbPIaaqeApbPKbPKbPKbPJaaqeAqbPMbPMbPMbPNbPObPPbPQbPRayObPSbPTbPUbPUbPVbPWaaqaaqbPXaaqbQcbQbbRpbRobRqaaqeAnbHPbUIbUGbQdbQebQfbQgactbRwbRzbQjbQiaaibQlbQmbQnbQobQpbQqbQrbQsbQtbQuaaqaaqaaqaaqaaqaaJaBpanlaaibQvbQwbQwbQxbPbbQybPbbQzaaibQAbKfbQBbQBaaqbGHbQCbGJaaiaaibQDaaiaaiaaiaaiaaiaaiaaiaaiaaibQEaaiaaiaaiaaiaaiaaiaaiaaiaacaacaacaacaacaacaacaacaacaacaacaacaacaacaacaacaacbQFbPobPobQGaaiaaibPqbPqbQHbPqbPqaaiaaiaabaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
-aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabyLbyLbyLbyLbyLbyLbyLbyLbyLaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabDZbDZbDZbDZbDZbDZbDZbHaanFaDGctmbEcbQIbEcbQJbQKbQLbFObFObQMbFObFObEcbQNbFObFObQObFObFObFObFOcrWbEfaaqcqPbQQbQRbQSbQTbQUbQVbQWbQXbQYbQZbRabCzaaqbPIaaqbPJbPKbRbbPKbSxaaqbPLbPMbRcbPMbPLaaqbRdbRebRfaaqbRgbRhbRibRtbRkbRlabHbRmbRnabHchhbRrbSMbSJbRAaaqbRsbHPbHPbSRbQdbQebRubRvbQkbOBbSObRyczAbRxbRBbRCbRDaaqcuzbRFbQrbRGbRGbRGaaqbRHbRIbRJbRKbRLbRMbRNaaibQwbQwbQwbRObPbbRPbPbbRQaaibRRbKfbRSbRSaaqbRTbRUbGJaaibRVbRWbRXactbRYbRZbSabSbbScbSdbSebSfbSgbShbSibSjbSkbSlbSmaaiaaiaaiaaiaaiaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabaaaaaabSnaaibQFaaiaaibPqbPqbPqbPqbPqbPqbPqaaiaaiaabaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabyLbyLbyLbyLbyLbyLbyLbyLbyLaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabDZbDZbDZbDZbDZbDZbDZbHaanFaDGctmbEcbQIbEcbQJbQKbQLbFObFObQMbFObFObEcbQNbFObFObQObFObFObFObFOcrWbEfaaqcqPbQQbQRbQSbQTbQUbQVbQWbQXbQYbQZbRabCzaaqbPIaaqbPJbPKbRbbPKbSxaaqbPLbPMbRcbPMbPLaaqbRdbRebRfaaqbRgbRhbRibRtbRkbRlabHbRmbRnabHchhbRrbSMbSJbRAaaqbRsbHPbHPbSRbQdbQebRubRvbQkbOBbSObRyczAbRxbRBbRCbRDaaqcuzbRFbQrbRGbRGbRGaaqbRHbRIbRKbRJbRLbRMbRNaaibQwbQwbQwbRObPbbRPbPbbRQaaibRRbKfbRSbRSaaqbRTbRUbGJaaibRVbRWbRXactbRYbRZbSabSbbScbSdbSebSfbSgbShbSibSjbSkbSlbSmaaiaaiaaiaaiaaiaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabaaaaaabSnaaibQFaaiaaibPqbPqbPqbPqbPqbPqbPqaaiaaiaabaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabyLbyLbyLbyLbyLbyLbyLbyLbyLaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabDZbDZbDZbDZbDZbDZbDZaaaaaiaaiaaqayGbSoayHbxgbSpaaqaaqayGanFayHaaqaaqbSqaaqaaqaaqaaqbxgaaqaaqaaqaaqaaqaaqaaqaaqaaqaaqaaqaaqbSraaqaaqaaqbSsbStbSubSvaaqbPJbSwbPKbPKbPJaaqbSybSzbPMbSAbSBabHbSCbSDbSEaaqaaqaaqaaqaaqbSFaaqaaqbSGbSHaaqaaqaaJaaqanpaaqaaqbSIbOqbOqaaqaaqbSKbSLbMLbOpbSNbQhbSPbSQbOoaaqbSSbSTaaqbREbRFbQrbRGbRGbRGaaqbSYbSZbTabTbbTcbTdbTeaaibQwbQwbQwbTfbPbbQybTgbVdactbTibTjbTkbTkayObTlbTmbLXbTnbTobTpbTqbTrbTsbShbShbTtbTubShbTvbShbTwbTxbTybTzbTAbTBbTCacdcogbTEbTFcoYaabaabaabaabaabaabaabaabaabaabaabaabaabaaqaaibTHbTIbTIbPqbPqbPqbPqbPqbPqbPqbPqaaiaaiaabaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabyLbyLbyLbyLbyLbyLbyLbyLbyLaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabDZbDZbDZbDZbDZbDZbDZaaaaaibTJbTKbTLbTMbTNbTObTPbTQaaibTRbTSbTTbTUbTVbTWbTXbTYbTZbTYbTYbTYbTYbTYbTYbTYbTYbTYbTYbTYbTYbTYbTYbUabTYbTYbTYbUbbUcbUdbUeaaqeAobUgbUhbUibUjabHbUkbUlbUmbUnbUoaaqbUpbUqbUrbUsbUtbUtbUtbUtbUubUvbUwbUxbUxbUybUybUzbUAbUBaaqaaqbUCbUDbUEbPYcbhbQebUHbMLbOwbOsaFWbUKbLwbQaaFWbUMbUNanccxjcxkcxhcxicwdcxgaaqcqxbUVbUWbUXbUYbUZbVaaaibVbbQwbQwaaibVcbYdbVeaaiaaqbVfbVgbIwaaqaaqbVhbQCbViaaibVjbVkbVlaaibVmbVnbVnbVobVpbVqbVrbVnbVsbVtbVnbVnbVubVvbVwcpcbVybVzbVAcqoaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaabaaaaaaaaiaaibVCbPqbPqbPqbPqbPqbPqbPqbPqbPqbPqbPqaaiaaiaabaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabyLbyLbyLbyLbyLbyLbyLbyLbyLaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabDZbDZbDZbDZbDZaaaaaaaaibVDbVEbVEbVFbVEbVEbVGbVHaaibVIbVJbVKbVJbVJbVLaaiaaiaaiaaiaaiaaiaaiaaiaaiaaiaaiaaiaaiaaiaaiaaiaaiaaiaaiaaiaaqbVMaaqaaqbVNaaqbVObVPbVQbVRbVSaaqbVTbVUbVVbVWbVXaMRbVYbVZbWaabHacdacdacdacdbWbatQbzlayObWcayOayObWdbWebWfbWgbWhbWibWjbWkbWlbsobWnbWobWpbWqbWrbWsbWtbWubWvbWwbWxbWyaaqaaqaCZayOayOayObWzaaqaaqeBvaaqalrbqIboGbnUaaibWEbQwbQwbWFbWGbWHbWIbWJaaqaaqbWKaaqaaqbWLbWMbQCbrYaaiaaibWNaaiaaibWObsnbWPbWQbWRbVnbWSbVwbWTbVwbVwbVwbWUbSfbIIaaibWVbWWbWXcdiaabaabaabaabaabaabaabaabaabaabaabaabaabaaibPqbPqbPqbPqbPqbPqbWZbPqbXabPqbPqbPqbPqbPqaaiaaiaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa