From 30c1960fe8d58494cdbbf0d523c87686cfaa104b Mon Sep 17 00:00:00 2001 From: Markolie Date: Sun, 23 Nov 2014 07:52:38 +0100 Subject: [PATCH] Adds Syndiborg to NukeOps, enables shortcuts for borgs/drones, notifies the AI of borg changes --- baystation12.dme | 1 + code/__HELPERS/unsorted.dm | 7 + code/_onclick/cyborg.dm | 51 ++++-- code/_onclick/hud/screen_objects.dm | 2 +- code/datums/uplink_item.dm | 13 ++ code/datums/wires/robot.dm | 1 + code/game/gamemodes/antag_spawner.dm | 42 +++++ code/game/machinery/transformer.dm | 1 + .../game/objects/items/devices/radio/radio.dm | 10 +- code/game/objects/items/devices/uplinks.dm | 21 +++ code/game/objects/items/robot/robot_parts.dm | 3 +- .../objects/items/robot/robot_upgrades.dm | 5 + .../objects/items/weapons/implants/implant.dm | 2 +- .../objects/items/weapons/melee/energy.dm | 14 ++ code/modules/mob/living/silicon/robot/life.dm | 2 + .../modules/mob/living/silicon/robot/robot.dm | 40 ++++- .../mob/living/silicon/robot/robot_modules.dm | 18 ++- .../living/silicon/robot/robot_upgrades.dm | 145 ------------------ code/modules/mob/living/silicon/say.dm | 16 +- code/modules/mob/living/silicon/silicon.dm | 1 + code/modules/mob/transform_procs.dm | 1 + code/modules/projectiles/guns/energy/stun.dm | 87 ++++++----- icons/mob/robots.dmi | Bin 148608 -> 153429 bytes maps/cyberiad.dmm.backup | 6 +- 24 files changed, 275 insertions(+), 214 deletions(-) create mode 100644 code/game/gamemodes/antag_spawner.dm delete mode 100644 code/modules/mob/living/silicon/robot/robot_upgrades.dm 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 b5a93c40940708cdf23e45b84b6eb1c0e962fc3d..a93050ba21be3b3ab81b51266b9c2602f5875f2d 100644 GIT binary patch delta 10776 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 delta 5917 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