Robot Cleanup (#9332)

This commit is contained in:
Geeves
2020-07-17 14:26:30 -03:00
committed by GitHub
parent 7bce5732fa
commit 7dd0bb2b56
41 changed files with 1228 additions and 1182 deletions
@@ -9,12 +9,11 @@
flags = CONDUCT
slot_flags = SLOT_BELT
throwforce = 3
w_class = 2.0
w_class = ITEMSIZE_SMALL
throw_speed = 5
throw_range = 10
origin_tech = list(TECH_MAGNET = 2, TECH_BIO = 1, TECH_ENGINEERING = 2)
matter = list(DEFAULT_WALL_MATERIAL = 500, MATERIAL_GLASS = 200)
var/mode = 1
/obj/item/device/robotanalyzer/attack(mob/living/M, mob/living/user)
if((user.is_clumsy() || (DUMB in user.mutations)) && prob(50))
@@ -99,5 +98,4 @@
if(!organ_found)
to_chat(user, SPAN_NOTICE("No prosthetics located."))
add_fingerprint(user)
return
add_fingerprint(user)
@@ -1,21 +1,18 @@
// TODO: remove the robot.mmi and robot.cell variables and completely rely on the robot component system
/datum/robot_component/var/name
/datum/robot_component/var/installed = 0
/datum/robot_component/var/powered = 0
/datum/robot_component/var/toggled = 1
/datum/robot_component/var/brute_damage = 0
/datum/robot_component/var/electronics_damage = 0
/datum/robot_component/var/idle_usage = 0 // Amount of power used every MC tick. In joules.
/datum/robot_component/var/active_usage = 0 // Amount of power used for every action. Actions are module-specific. Actuator for each tile moved, etc.
/datum/robot_component/var/max_damage = 30 // HP of this component.
/datum/robot_component/var/mob/living/silicon/robot/owner
// The actual device object that has to be installed for this.
/datum/robot_component/var/external_type = null
// The wrapped device(e.g. radio), only set if external_type isn't null
/datum/robot_component/var/obj/item/wrapped = null
/datum/robot_component
var/name = "robot component"
var/installed = 0
var/powered = 0
var/toggled = 1
var/brute_damage = 0
var/electronics_damage = 0
var/idle_usage = 0 // Amount of power used every MC tick. In joules.
var/active_usage = 0 // Amount of power used for every action. Actions are module-specific. Actuator for each tile moved, etc.
var/max_damage = 30 // HP of this component.
var/mob/living/silicon/robot/owner
var/external_type = null // The actual device object that has to be installed for this.
var/obj/item/wrapped = null // The wrapped device(e.g. radio), only set if external_type isn't null
/datum/robot_component/New(mob/living/silicon/robot/R)
src.owner = R
@@ -28,7 +25,7 @@
/datum/robot_component/proc/destroy()
var/brokenstate = "broken" // Generic icon
if (istype(wrapped, /obj/item/robot_parts/robot_component))
if(istype(wrapped, /obj/item/robot_parts/robot_component))
var/obj/item/robot_parts/robot_component/comp = wrapped
brokenstate = comp.icon_state_broken
if(wrapped)
@@ -9,6 +9,7 @@ var/list/robot_custom_icons
else if(config.load_customsynths_from == "json")
loadsynths_from_json()
return 1
/mob/living/silicon/robot/proc/set_custom_sprite()
var/datum/custom_synth/sprite = robot_custom_icons[name]
if(istype(sprite) && sprite.synthckey == ckey)
@@ -20,4 +21,4 @@ var/list/robot_custom_icons
icon_state = "[sprite.synthicon]-Standard"
else
to_chat(src, "<span class='warning'>Could not locate [sprite.synthicon]-Standard sprite.</span>")
icon = 'icons/mob/robots.dmi'
icon = 'icons/mob/robots.dmi'
@@ -6,11 +6,11 @@
/mob/living/silicon/robot/death(gibbed)
if(camera)
camera.status = 0
camera.status = FALSE
if(module)
var/obj/item/gripper/G = locate(/obj/item/gripper) in module
if(G)
G.drop_item()
remove_robot_verbs()
sql_report_cyborg_death(src)
..(gibbed,"shudders violently for a moment, then becomes motionless, its eyes slowly darkening.")
..(gibbed,"shudders violently for a moment, then becomes motionless, its eyes slowly darkening.")
@@ -31,6 +31,7 @@
icon = 'icons/mob/robots.dmi'
icon_state = "repairbot"
braintype = "Robot"
mod_type = "Engineering"
gender = NEUTER
// Health
@@ -163,7 +164,7 @@
if(!laws)
laws = new law_type
if(!module)
module = new module_type(src)
module = new module_type(src, src)
flavor_text = "It's a tiny little repair drone. The casing is stamped with an corporate logo and the subscript: '[current_map.company_name] Recursive Repair Systems: Fixing Tomorrow's Problem, Today!'"
playsound(get_turf(src), 'sound/machines/twobeep.ogg', 50, 0)
@@ -47,5 +47,4 @@
msg += "\nIt [pose]"
to_chat(user, msg)
user.showLaws(src)
return
user.showLaws(src)
@@ -295,4 +295,4 @@
var/selected = get_selected_module()
if (selected)
result += "\nThe activity light on hardpoint [selected] is on.\n"
return result
return result
@@ -0,0 +1,11 @@
/obj/item/proc/on_module_hotbar(var/mob/living/silicon/robot/R)
return
/obj/item/proc/on_module_store(var/mob/living/silicon/robot/R)
return
/obj/item/proc/on_module_activate(var/mob/living/silicon/robot/R)
return
/obj/item/proc/on_module_deactivate(var/mob/living/silicon/robot/R)
return
@@ -0,0 +1,19 @@
//A harvest item for serviceborgs.
/obj/item/robot_harvester
name = "auto harvester"
desc = "A hand-held harvest tool that resembles a sickle. It uses energy to cut plant matter very efficently."
icon = 'icons/obj/weapons.dmi'
icon_state = "autoharvester"
hitsound = "swing_hit"
/obj/item/robot_harvester/afterattack(var/atom/target, var/mob/living/user, proximity)
if(!target || !proximity)
return
if(istype(target, /obj/machinery/portable_atmospherics/hydroponics))
var/obj/machinery/portable_atmospherics/hydroponics/T = target
if(T.harvest) //Try to harvest, assuming it's alive.
T.harvest(user)
else if(T.dead) //It's probably dead otherwise.
T.remove_dead(user)
else
to_chat(user, SPAN_WARNING("ERROR: Harvesting \a [target] is not the purpose of this tool. \The [src] is for plants being grown."))
@@ -0,0 +1,24 @@
/obj/item/borg/stun
name = "electrified arm"
icon = 'icons/obj/decals.dmi'
icon_state = "shock"
/obj/item/borg/stun/apply_hit_effect(mob/living/M, mob/living/silicon/robot/user, var/hit_zone)
if(!istype(user))
return FALSE
user.visible_message(SPAN_DANGER("\The [user] has prodded \the [M] with \a [src]!"), SPAN_DANGER("You prod \the [M] with \the [src]."))
if(!user.cell || !user.cell.checked_use(1250)) //Slightly more than a baton.
return FALSE
playsound(loc, 'sound/weapons/Egloves.ogg', 50, 1, -1)
M.apply_effect(5, STUTTER)
M.stun_effect_act(0, 70, check_zone(hit_zone), src)
if(ishuman(M))
var/mob/living/carbon/human/H = M
H.forcesay(hit_appends)
return FALSE
@@ -0,0 +1,22 @@
//TODO: Add prewritten forms to dispense when you work out a good way to store the strings.
/obj/item/form_printer
name = "paper dispenser"
icon = 'icons/obj/bureaucracy.dmi'
icon_state = "paper_bin1"
item_state = "sheet-metal"
/obj/item/form_printer/attack(mob/living/carbon/M, mob/living/carbon/user)
return
/obj/item/form_printer/afterattack(atom/target, mob/living/user, flag, params)
if(!target || !flag)
return
if(istype(target,/obj/structure/table))
deploy_paper(get_turf(target), user)
/obj/item/form_printer/attack_self(mob/user)
deploy_paper(get_turf(src))
/obj/item/form_printer/proc/deploy_paper(var/turf/T, var/mob/user)
T.visible_message(SPAN_NOTICE("\The [user] dispenses a sheet of crisp white paper."))
new /obj/item/paper(T)
@@ -282,4 +282,4 @@
can_hold = list(
/obj/item/stack/material,
/obj/item/stack/tile
)
)
@@ -0,0 +1,15 @@
/obj/item/gun/energy/mountedcannon
name = "mounted ballistic cannon"
desc = "A cyborg mounted ballistic cannon."
icon = 'icons/obj/robot_items.dmi'
icon_state = "cannon"
item_state = "cannon"
fire_sound = 'sound/effects/Explosion1.ogg'
charge_meter = FALSE
max_shots = 10
charge_cost = 300
projectile_type = /obj/item/projectile/bullet/gyro
self_recharge = TRUE
use_external_power = TRUE
recharge_time = 5
needspin = FALSE
@@ -0,0 +1,84 @@
/obj/item/inductive_charger
name = "inductive charger"
desc = "A phoron-enhanced induction charger hooked up to its attached stationbound's internal cell."
desc_fluff = "Harnessing the energy potential found in phoron structures, Nanotrasen engineers have created a portable device capable of highly efficient wireless charging. The expense and limit of energy output of using this method of charging prevents it from being used on a large scale, being far outclassed by Phoron-Supermatter charging systems."
desc_info = "Click on an adjacent object that contains or is a power cell to attempt to find and charge it. After a successful charge, the inductive charger recharge in a few minutes. The amount transfered can be adjusted by alt clicking it."
icon = 'icons/obj/robot_items.dmi'
icon_state = "inductive_charger"
var/ready_to_use = TRUE
var/recharge_time = 300
var/transfer_rate = 5000
var/efficiency_mod = 0.9
maptext_x = 3
maptext_y = 2
/obj/item/inductive_charger/Initialize()
. = ..()
maptext = "<span style=\"font-family: 'Small Fonts'; -dm-text-outline: 1 black; font-size: 7px;\">Ready</span>"
/obj/item/inductive_charger/AltClick(mob/user)
. = ..()
var/set_rate = input(user, "How much do you want to transfer per use? (Limit: 1 - 5000)", "Induction Transfer Rate", 5000) as num
if(set_rate > 5000)
set_rate = 5000
else if(set_rate < 1)
set_rate = 1
transfer_rate = set_rate
to_chat(user, SPAN_NOTICE("You set the transfer rate of \the [src] to [transfer_rate]."))
/obj/item/inductive_charger/attack(mob/living/M, mob/living/user, target_zone)
return
/obj/item/inductive_charger/afterattack(atom/target, mob/user, proximity_flag, click_parameters)
var/mob/living/silicon/robot/R = user
if(!istype(R))
to_chat(user, SPAN_WARNING("Only cyborgs can use this!"))
return
if(!ready_to_use)
to_chat(user, SPAN_WARNING("\The [src] is still gathering charge!"))
return
user.visible_message("<b>[user]</b> begins waving \the [src] around \the [target]...", SPAN_NOTICE("You prepare to wirelessly charge \the [target]..."), range = 3)
if(!do_after(user, 50, TRUE, target))
return
if(R.cell.charge < 1000)
to_chat(user, SPAN_WARNING("You have no spare charge in your internal cell to give!"))
return
if(isipc(target))
var/mob/living/carbon/human/IPC = target
if(IPC.nutrition == IPC.max_nutrition)
to_chat(user, SPAN_WARNING("\The [IPC] is already fully charged!"))
return
var/charge_amount = min(IPC.max_nutrition - IPC.nutrition, transfer_rate)
var/charge_value = R.cell.use(charge_amount / efficiency_mod) * efficiency_mod
IPC.nutrition = min(IPC.max_nutrition, charge_value)
message_and_use(user, "<b>[user]</b> holds \the [src] over \the [IPC], topping up their battery.", SPAN_NOTICE("You wirelessly transmit [charge_value] units of power to \the [IPC], using [charge_value / efficiency_mod] of internal cell power."))
else if(isobj(target))
var/obj/item/cell/C
if(istype(target, /obj/item/cell))
C = target
else
C = locate() in target
if(!C)
to_chat(user, SPAN_WARNING("\The [target] doesn't contain a cell, or it's buried too deep for you to reach!"))
return
if(C.fully_charged())
to_chat(user, SPAN_WARNING("\The [C] is already fully charged!"))
return
var/charge_amount = min(C.maxcharge - C.charge, transfer_rate)
var/charge_value = R.cell.use(charge_amount / efficiency_mod) * efficiency_mod
C.give(charge_value)
message_and_use(user, "<b>[user]</b> holds \the [src] over \the [target], topping up its battery.", SPAN_NOTICE("You wirelessly transmit [charge_value] units of power to \the [target], using [charge_value / efficiency_mod] of internal cell power."))
else
to_chat(user, SPAN_WARNING("\The [src] cannot be used on \the [target]!"))
/obj/item/inductive_charger/proc/message_and_use(mob/user, var/others_message, var/self_message)
user.visible_message(others_message, self_message, range = 3)
addtimer(CALLBACK(src, .proc/recharge), recharge_time)
ready_to_use = FALSE
maptext = "<span style=\"font-family: 'Small Fonts'; -dm-text-outline: 1 black; font-size: 6px;\">Charge</span>"
/obj/item/inductive_charger/proc/recharge()
ready_to_use = TRUE
maptext = "<span style=\"font-family: 'Small Fonts'; -dm-text-outline: 1 black; font-size: 7px;\">Ready</span>"
@@ -0,0 +1,13 @@
/obj/item/borg/combat/mobility
name = "mobility module"
desc = "By retracting limbs and tucking in its head, a combat android can roll at high speeds."
icon = 'icons/obj/decals.dmi'
icon_state = "shock"
/obj/item/borg/combat/mobility/on_module_activate(mob/living/silicon/robot/R)
R.icon_state = "[R.module_sprites[R.icontype]]-roll"
R.speed = -2
/obj/item/borg/combat/mobility/on_module_deactivate(mob/living/silicon/robot/R)
R.icon_state = R.module_sprites[R.icontype]
R.speed = initial(R.speed)
@@ -0,0 +1,24 @@
//Personal shielding for the combat module.
/obj/item/borg/combat/shield
name = "personal shielding"
desc = "A powerful experimental module that turns aside or absorbs incoming attacks at the cost of charge."
icon = 'icons/obj/device.dmi'
icon_state = "shield1" //placeholder for now // four fucking years alberyk. FOUR
var/shield_level = 0.5 //Percentage of damage absorbed by the shield.
var/image/shield_overlay
/obj/item/borg/combat/shield/on_module_activate(mob/living/silicon/robot/R)
shield_overlay = image(R.icon, "[R.module_sprites[R.icontype]]-shield")
R.add_overlay(shield_overlay)
/obj/item/borg/combat/shield/on_module_deactivate(mob/living/silicon/robot/R)
R.cut_overlay(shield_overlay)
/obj/item/borg/combat/shield/verb/set_shield_level()
set name = "Set shield level"
set category = "Object"
set src in range(0)
var/N = input(usr, "How much damage should the shield absorb?") in list("5", "10", "25", "50", "75", "100")
if(N)
shield_level = text2num(N)/100
@@ -0,0 +1,54 @@
/obj/item/borg/sight
icon = 'icons/obj/decals.dmi'
icon_state = "securearea"
var/sight_mode = null
/obj/item/borg/sight/on_module_hotbar(mob/living/silicon/robot/R)
R.sight_mode |= sight_mode
/obj/item/borg/sight/on_module_store(mob/living/silicon/robot/R)
R.sight_mode &= ~sight_mode
/obj/item/borg/sight/xray
name = "\proper x-ray vision"
sight_mode = BORGXRAY
/obj/item/borg/sight/thermal
name = "\proper thermal vision"
desc_antag = "Having this device on your hotbar will allow you to see in enhanced thermal vision, which allows you to see heat signatures through solid walls."
sight_mode = BORGTHERM
icon_state = "thermal"
icon = 'icons/obj/clothing/glasses.dmi'
/obj/item/borg/sight/meson
name = "\proper meson vision"
sight_mode = BORGMESON
icon_state = "meson"
icon = 'icons/obj/clothing/glasses.dmi'
/obj/item/borg/sight/material
name = "\proper material scanner vision"
sight_mode = BORGMATERIAL
/obj/item/borg/sight/hud
name = "hud"
var/obj/item/clothing/glasses/hud/hud = null
/obj/item/borg/sight/hud/med
name = "medical hud"
icon_state = "healthhud"
icon = 'icons/obj/clothing/glasses.dmi'
/obj/item/borg/sight/hud/med/Initialize(mapload, ...)
. = ..()
hud = new /obj/item/clothing/glasses/hud/health(src)
/obj/item/borg/sight/hud/sec
name = "security hud"
icon_state = "securityhud"
icon = 'icons/obj/clothing/glasses.dmi'
/obj/item/borg/sight/hud/sec/Initialize(mapload, ...)
. = ..()
hud = new /obj/item/clothing/glasses/hud/security(src)
@@ -0,0 +1,4 @@
/obj/item/borg/overdrive
name = "overdrive"
icon = 'icons/obj/decals.dmi'
icon_state = "shock"
@@ -0,0 +1,103 @@
//A portable analyzer, for research borgs. This is better then giving them a gripper which can hold anything and letting them use the normal analyzer.
/obj/item/portable_destructive_analyzer
name = "Portable Destructive Analyzer"
desc = "Similar to the stationary version, this rather unwieldy device allows you to break down objects in the name of science."
icon = 'icons/obj/robot_items.dmi'
icon_state = "portable_analyzer"
var/min_reliability = 90 //Can't upgrade, call it laziness or a drawback
var/datum/research/techonly/files //The device uses the same datum structure as the R&D computer/server.
//This analyzer can only store tech levels, however.
var/obj/item/loaded_item //What is currently inside the analyzer.
/obj/item/portable_destructive_analyzer/Initialize()
. = ..()
files = new /datum/research/techonly(src) //Setup the research data holder.
/obj/item/portable_destructive_analyzer/examine(mob/user, distance)
. = ..()
if(loaded_item && Adjacent(user))
to_chat(user, SPAN_NOTICE("It is holding \a [loaded_item]."))
/obj/item/portable_destructive_analyzer/attack_self(mob/user)
var/response = alert(user, "Analyzing the item inside will *DESTROY* the item for good.\n\
Syncing to the research server will send the data that is stored inside to research.\n\
Ejecting will place the loaded item onto the floor.",
"What would you like to do?", "Analyze", "Sync", "Eject")
if(response == "Analyze")
if(loaded_item)
var/confirm = alert(user, "This will destroy the item inside forever. Are you sure?", "Confirm Analyze", "Yes", "No")
if(confirm == "Yes") //This is pretty copypasta-y
to_chat(user, SPAN_NOTICE("You activate the analyzer's microlaser, analyzing \the [loaded_item] and breaking it down."))
flick("portable_analyzer_scan", src)
playsound(src.loc, 'sound/items/Welder2.ogg', 50, 1)
for(var/T in loaded_item.origin_tech)
files.UpdateTech(T, loaded_item.origin_tech[T])
to_chat(user, SPAN_NOTICE("\The [loaded_item] had level [loaded_item.origin_tech[T]] in [CallTechName(T)]."))
loaded_item = null
for(var/obj/I in contents)
for(var/mob/M in I.contents)
M.death()
if(istype(I,/obj/item/stack/material)) //Only deconstructs one sheet at a time instead of the entire stack
var/obj/item/stack/material/S = I
if(S.get_amount() > 1)
S.use(1)
loaded_item = S
else
qdel(S)
icon_state = initial(icon_state)
else
qdel(I)
icon_state = initial(icon_state)
else
return
else
to_chat(user, SPAN_WARNING("\The [src] is empty. Put something inside it first."))
if(response == "Sync")
var/success = FALSE
for(var/obj/machinery/r_n_d/server/S in SSmachinery.all_machines)
for(var/datum/tech/T in files.known_tech) //Uploading
S.files.AddTech2Known(T)
for(var/datum/tech/T in S.files.known_tech) //Downloading
files.AddTech2Known(T)
success = TRUE
files.RefreshResearch()
if(success)
to_chat(user, SPAN_NOTICE("You connect to the research server, push your data upstream to it, then pull the resulting merged data from the master branch.")) // fucking nerds
playsound(get_turf(src), 'sound/machines/twobeep.ogg', 50, TRUE)
else
to_chat(user, SPAN_WARNING("Research server ping response timed out. Unable to connect. Please contact the system administrator."))
playsound(get_turf(src), 'sound/machines/buzz-two.ogg', 50, 1)
if(response == "Eject")
if(loaded_item)
loaded_item.forceMove(get_turf(src))
icon_state = initial(icon_state)
loaded_item = null
else
to_chat(user, SPAN_WARNING("\The [src] is already empty."))
/obj/item/portable_destructive_analyzer/afterattack(var/atom/target, var/mob/living/user, proximity)
if(!target || !proximity || !isturf(target.loc))
return
if(loaded_item)
to_chat(user, SPAN_WARNING("Your [src] already has something inside. Analyze or eject it first."))
return
if(istype(target,/obj/item))
var/obj/item/I = target
if(I.anchored)
to_chat(user, span("notice", "\The [I] is anchored in place."))
return
if(!I.origin_tech)
to_chat(user, SPAN_NOTICE("This doesn't seem to have a tech origin."))
return
if(!length(I.origin_tech))
to_chat(user, SPAN_NOTICE("You cannot deconstruct this item."))
return
I.forceMove(src)
loaded_item = I
visible_message(SPAN_NOTICE("\The [user] scoops \the [I] into \the [src]."))
flick("portable_analyzer_load", src)
icon_state = "portable_analyzer_full"
@@ -0,0 +1,6 @@
//This is used to unlock other borg covers.
/obj/item/card/robot //This is not a child of id cards, as to avoid dumb typechecks on computers.
name = "access code transmission device"
icon_state = "id-robot"
desc = "A circuit grafted onto the bottom of an ID card. It is used to transmit access codes into other robot chassis, \
allowing you to lock and unlock other robots' panels."
@@ -0,0 +1,119 @@
#define MODE_WALL 0
#define MODE_DOOR 1
/obj/item/inflatable_dispenser
name = "inflatables dispenser"
desc = "Small device which allows rapid deployment and removal of inflatables."
icon = 'icons/obj/storage.dmi'
icon_state = "inf_deployer"
w_class = ITEMSIZE_NORMAL
var/deploying = FALSE
var/max_walls = 10
var/max_doors = 5
var/stored_walls = 10
var/stored_doors = 5
var/mode = MODE_WALL // 0 - Walls 1 - Doors
/obj/item/inflatable_dispenser/Initialize(mapload, ...)
. = ..()
stored_walls = max_walls
stored_doors = max_doors
/obj/item/inflatable_dispenser/examine(mob/user)
if(!..(user))
return
to_chat(user, SPAN_NOTICE("It has [stored_walls] wall segment\s and [stored_doors] door segment\s stored."))
to_chat(user, SPAN_NOTICE("It is set to deploy [mode ? "doors" : "walls"]"))
/obj/item/inflatable_dispenser/attack_self(mob/user)
if(!deploying)
mode = !mode
to_chat(user, SPAN_NOTICE("You set \the [src] to deploy [mode ? "doors" : "walls"]."))
else
to_chat(user, SPAN_WARNING("You can't switch modes while deploying a [mode ? "door" : "wall"]!"))
/obj/item/inflatable_dispenser/afterattack(var/atom/A, var/mob/user)
..(A, user)
if(!user)
return
if(!user.Adjacent(A))
to_chat(user, SPAN_WARNING("You can't reach!"))
return
if(istype(A, /turf))
try_deploy_inflatable(A, user)
if(istype(A, /obj/item/inflatable) || istype(A, /obj/structure/inflatable))
pick_up(A, user)
/obj/item/inflatable_dispenser/proc/try_deploy_inflatable(var/turf/T, var/mob/living/user)
if(deploying)
return
var/newtype
if(mode) // Door deployment
if(!stored_doors)
to_chat(user, SPAN_WARNING("\The [src] is out of doors!"))
return
if(T && istype(T))
newtype = /obj/structure/inflatable/door
else // Wall deployment
if(!stored_walls)
to_chat(user, SPAN_WARNING("\The [src] is out of walls!"))
return
if(T && istype(T))
newtype = /obj/structure/inflatable/wall
deploying = 1
user.visible_message("<b>[user]</b> starts deploying an inflatable [mode ? "door" : "wall"].", SPAN_NOTICE("You start deploying an inflatable [mode ? "door" : "wall"]!"))
playsound(T, 'sound/items/zip.ogg', 75, TRUE)
if(do_after(user, 30, needhand = FALSE))
new newtype(T)
if(mode)
stored_doors--
else
stored_walls--
deploying = FALSE
/obj/item/inflatable_dispenser/proc/pick_up(var/obj/A, var/mob/living/user)
if(istype(A, /obj/structure/inflatable))
if(istype(A, /obj/structure/inflatable/wall))
if(stored_walls >= max_walls)
to_chat(user, SPAN_WARNING("\The [src] is full."))
return
stored_walls++
qdel(A)
else
if(stored_doors >= max_doors)
to_chat(user, SPAN_WARNING("\The [src] is full."))
return
stored_doors++
qdel(A)
playsound(get_turf(src), 'sound/machines/hiss.ogg', 75, TRUE)
visible_message("<b>[user]</b> deflates \the [A] with \the [src].", SPAN_NOTICE("You deinflate \the [A] with \the [src]."))
return
else if(istype(A, /obj/item/inflatable))
if(istype(A, /obj/item/inflatable/wall))
if(stored_walls >= max_walls)
to_chat(user, SPAN_WARNING("\The [src] is full."))
return
stored_walls++
qdel(A)
else
if(stored_doors >= max_doors)
to_chat(usr, SPAN_WARNING("\The [src] is full!"))
return
stored_doors++
qdel(A)
visible_message("<b>[user]</b> picks up \the [A] with \the [src].", SPAN_NOTICE("You pick up \the [A] with \the [src]."))
return
to_chat(user, SPAN_WARNING("You fail to pick up \the [A] with \the [src]."))
return
/obj/item/inflatable_dispenser/borg
max_walls = 5
max_doors = 3
#undef MODE_WALL
#undef MODE_DOOR
@@ -0,0 +1,429 @@
/obj/item/robot_parts
name = "robot parts"
icon = 'icons/obj/robot_parts.dmi'
item_state = "buildpipe"
icon_state = "blank"
flags = CONDUCT
slot_flags = SLOT_BELT
var/list/part = null // Order of args is important for installing robolimbs.
var/sabotaged = 0 //Emagging limbs can have repercussions when installed as prosthetics.
var/model_info
var/linked_frame = "Unbranded Frame"
dir = SOUTH
/obj/item/robot_parts/set_dir()
return
/obj/item/robot_parts/New(var/newloc, var/model)
..(newloc)
if(model_info && model)
model_info = model
var/datum/robolimb/R = all_robolimbs[model]
if(R)
name = "[R.company] robot [initial(name)]"
desc = "[R.desc]"
linked_frame = R.linked_frame
if(icon_state in icon_states(R.icon))
icon = R.icon
else
name = "robot [initial(name)]"
/obj/item/robot_parts/examine(mob/user, distance)
. = ..()
if(Adjacent(user))
report_missing_parts(user)
/obj/item/robot_parts/proc/report_missing_parts(var/mob/user)
return
/obj/item/robot_parts/l_arm
name = "left arm"
desc = "A skeletal limb wrapped in pseudomuscles, with a low-conductivity case."
icon_state = "l_arm"
part = list(BP_L_ARM, BP_L_HAND)
model_info = TRUE
/obj/item/robot_parts/r_arm
name = "right arm"
desc = "A skeletal limb wrapped in pseudomuscles, with a low-conductivity case."
icon_state = "r_arm"
part = list(BP_R_ARM, BP_R_HAND)
model_info = TRUE
/obj/item/robot_parts/l_leg
name = "left leg"
desc = "A skeletal limb wrapped in pseudomuscles, with a low-conductivity case."
icon_state = "l_leg"
part = list(BP_L_LEG, BP_L_FOOT)
model_info = TRUE
/obj/item/robot_parts/r_leg
name = "right leg"
desc = "A skeletal limb wrapped in pseudomuscles, with a low-conductivity case."
icon_state = "r_leg"
part = list(BP_R_LEG, BP_R_FOOT)
model_info = TRUE
/obj/item/robot_parts/chest
name = "torso"
desc = "A heavily reinforced case containing cyborg logic boards, with space for a standard power cell."
icon_state = "chest"
part = list(BP_GROIN, BP_CHEST)
var/wires = 0
var/obj/item/cell/cell = null
/obj/item/robot_parts/head
name = "head"
desc = "A standard reinforced braincase, with spine-plugged neural socket and sensor gimbals."
icon_state = "head"
part = list(BP_HEAD)
var/obj/item/device/flash/left_flash = null
var/obj/item/device/flash/right_flash = null
var/law_manager = TRUE
/obj/item/robot_parts/robot_suit
name = "endoskeleton"
desc = "A complex metal backbone with standard limb sockets and pseudomuscle anchors."
icon_state = "robo_suit"
var/obj/item/robot_parts/l_arm/l_arm = null
var/obj/item/robot_parts/r_arm/r_arm = null
var/obj/item/robot_parts/l_leg/l_leg = null
var/obj/item/robot_parts/r_leg/r_leg = null
var/obj/item/robot_parts/chest/chest = null
var/obj/item/robot_parts/head/head = null
var/created_name = ""
/obj/item/robot_parts/robot_suit/Initialize()
. = ..()
updateicon()
/obj/item/robot_parts/robot_suit/report_missing_parts(var/mob/user)
if(!head)
to_chat(user, FONT_SMALL(SPAN_WARNING("It is lacking a functional head.")))
if(!chest)
to_chat(user, FONT_SMALL(SPAN_WARNING("It is lacking a functional chest.")))
if(!l_arm)
to_chat(user, FONT_SMALL(SPAN_WARNING("It is lacking a functional left arm.")))
if(!r_arm)
to_chat(user, FONT_SMALL(SPAN_WARNING("It is lacking a functional right arm.")))
if(!l_leg)
to_chat(user, FONT_SMALL(SPAN_WARNING("It is lacking a functional left leg.")))
if(!r_leg)
to_chat(user, FONT_SMALL(SPAN_WARNING("It is lacking a functional right leg.")))
/obj/item/robot_parts/robot_suit/equipped/Initialize()
. = ..()
l_leg = new /obj/item/robot_parts/l_leg(src)
r_leg = new /obj/item/robot_parts/r_leg(src)
l_arm = new /obj/item/robot_parts/l_arm(src)
r_arm = new /obj/item/robot_parts/r_arm(src)
updateicon()
/obj/item/robot_parts/robot_suit/proc/updateicon()
cut_overlays()
if(l_arm)
add_overlay("l_arm+o")
if(r_arm)
add_overlay("r_arm+o")
if(chest)
add_overlay("chest+o")
if(l_leg)
add_overlay("l_leg+o")
if(r_leg)
add_overlay("r_leg+o")
if(head)
add_overlay("head+o")
/obj/item/robot_parts/robot_suit/proc/check_completion()
if(l_arm && r_arm)
if(l_leg && r_leg)
if(chest && head)
feedback_inc("cyborg_frames_built",1)
return TRUE
return FALSE
/obj/item/robot_parts/robot_suit/attackby(obj/item/W, mob/user)
if(istype(W, /obj/item/stack/material) && W.get_material_name() == DEFAULT_WALL_MATERIAL && !l_arm && !r_arm && !l_leg && !r_leg && !chest && !head)
var/obj/item/stack/material/M = W
if(M.use(1))
var/obj/item/secbot_assembly/ed209_assembly/B = new /obj/item/secbot_assembly/ed209_assembly
B.forceMove(get_turf(src))
to_chat(user, SPAN_NOTICE("You armed the robot frame."))
if(user.get_inactive_hand() == src)
user.remove_from_mob(src)
user.put_in_inactive_hand(B)
qdel(src)
else
to_chat(user, SPAN_WARNING("You need one sheet of metal to arm the robot frame."))
return
if(istype(W, /obj/item/robot_parts/l_leg))
if(l_leg)
to_chat(user, SPAN_WARNING("\The [src] already has \a [l_leg] installed."))
return
user.drop_from_inventory(W, src)
l_leg = W
updateicon()
return
if(istype(W, /obj/item/robot_parts/r_leg))
if(r_leg)
to_chat(user, SPAN_WARNING("\The [src] already has \a [r_leg] installed."))
return
user.drop_from_inventory(W, src)
r_leg = W
updateicon()
return
if(istype(W, /obj/item/robot_parts/l_arm))
if(l_arm)
to_chat(user, SPAN_WARNING("\The [src] already has \a [l_arm] installed."))
return
user.drop_from_inventory(W, src)
l_arm = W
updateicon()
return
if(istype(W, /obj/item/robot_parts/r_arm))
if(r_arm)
to_chat(user, SPAN_WARNING("\The [src] already has \a [r_arm] installed."))
return
user.drop_from_inventory(W, src)
r_arm = W
updateicon()
return
if(istype(W, /obj/item/robot_parts/chest))
if(chest)
to_chat(user, SPAN_WARNING("\The [src] already has \a [chest] installed."))
return
var/obj/item/robot_parts/chest/C = W
if(C.wires && C.cell)
user.drop_from_inventory(W, src)
chest = W
updateicon()
else if(!C.wires)
to_chat(user, SPAN_WARNING("You need to attach wires to it first!"))
else
to_chat(user, SPAN_WARNING("You need to attach a cell to it first!"))
return
if(istype(W, /obj/item/robot_parts/head))
if(head)
to_chat(user, SPAN_WARNING("\The [src] already has \a [head] installed."))
return
var/obj/item/robot_parts/head/H = W
if(H.right_flash && H.left_flash)
user.drop_from_inventory(W, src)
head = W
updateicon()
else
to_chat(user, SPAN_WARNING("You need to attach a flash to it first!"))
return
if(istype(W, /obj/item/device/mmi))
var/obj/item/device/mmi/M = W
if(check_completion())
if(!istype(loc, /turf))
to_chat(user, SPAN_WARNING("You can't put \the [W] in, the frame has to be standing on the ground to be perfectly precise."))
return
if(!M.brainmob)
to_chat(user, SPAN_WARNING("\The [M] is empty!"))
return
if(!M.brainmob.key)
var/ghost_can_reenter = FALSE
if(M.brainmob.mind)
for(var/mob/abstract/observer/G in player_list)
if(G.can_reenter_corpse && G.mind == M.brainmob.mind)
ghost_can_reenter = TRUE
break
if(!ghost_can_reenter)
to_chat(user, SPAN_WARNING("\The [W] is completely unresponsive."))
return
if(M.brainmob.stat == DEAD)
to_chat(user, SPAN_WARNING("\The [M] is dead."))
return
if(!head.law_manager)
if(!is_alien_whitelisted(M.brainmob, "Baseline Frame") && config.usealienwhitelist)
to_chat(user, SPAN_WARNING("\The [W] does not seem to fit. (The player lacks the appropriate whitelist.)"))
return
var/mob/living/carbon/human/new_shell = new(get_turf(src), chest.linked_frame)
forceMove(new_shell) //so people won't mess around with the chassis until it is deleted
M.brainmob.mind.transfer_to(new_shell)
qdel(M)
var/newname = sanitizeSafe(input(new_shell, "Enter a name, or leave blank for the default name.", "Name change","") as text, MAX_NAME_LEN)
if(!newname)
var/datum/language/L = all_languages[new_shell.species.default_language]
newname = L.get_random_name()
new_shell.real_name = newname
new_shell.name = new_shell.real_name
new_shell.change_appearance(APPEARANCE_ALL_HAIR | APPEARANCE_SKIN | APPEARANCE_EYE_COLOR, new_shell.loc, new_shell)
qdel(src)
return
else
if(jobban_isbanned(M.brainmob, "Cyborg"))
to_chat(user, SPAN_WARNING("\The [W] does not seem to fit. (The player has been banned from playing this role)"))
return
var/mob/living/silicon/robot/O = new /mob/living/silicon/robot(get_turf(src), TRUE)
if(!O)
return
user.drop_from_inventory(M, O)
O.mmi = W
O.invisibility = 0
O.custom_name = created_name
O.updatename("Default")
M.brainmob.mind.transfer_to(O)
O.job = "Cyborg"
O.cell = chest.cell
O.cell.forceMove(O)
W.forceMove(O) //Should fix cybros run time erroring when blown up. It got deleted before, along with the frame.
// Since we "magically" installed a cell, we also have to update the correct component.
if(O.cell)
var/datum/robot_component/cell_component = O.components["power cell"]
cell_component.wrapped = O.cell
cell_component.installed = TRUE
feedback_inc("cyborg_birth", 1)
callHook("borgify", list(O))
O.Namepick()
qdel(src)
else
to_chat(user, SPAN_WARNING("\The [W] can only be inserted after everything else is installed."))
return
if(W.ispen())
var/t = sanitizeSafe(input(user, "Enter new robot name", name, created_name), MAX_NAME_LEN)
if(!t)
return
if(!in_range(src, usr) && loc != usr)
return
created_name = t
return
return ..()
/obj/item/robot_parts/chest/report_missing_parts(var/mob/user)
if(!cell)
to_chat(user, FONT_SMALL(SPAN_WARNING("It is lacking a functional cell.")))
if(!wires)
to_chat(user, FONT_SMALL(SPAN_WARNING("It is lacking wiring.")))
/obj/item/robot_parts/chest/attackby(obj/item/W, mob/user)
if(istype(W, /obj/item/cell))
if(cell)
to_chat(user, SPAN_WARNING("\The [src] already has \a [cell] inserted."))
return
else
user.drop_from_inventory(W, src)
cell = W
to_chat(user, SPAN_NOTICE("You insert \the [src]."))
return
if(W.iscoil())
if(wires)
to_chat(user, SPAN_WARNING("\The [src] is already wired up correctly."))
return
else
var/obj/item/stack/cable_coil/coil = W
coil.use(1)
wires = TRUE
to_chat(user, SPAN_NOTICE("You wire up \the [src]."))
return
return ..()
/obj/item/robot_parts/head/report_missing_parts(var/mob/user)
var/law_manager_msg = "Its lawing circuits are <b>[law_manager ? "enabled" : "disabled"]</b>."
to_chat(user, SPAN_NOTICE(law_manager_msg))
if(!left_flash)
to_chat(user, FONT_SMALL(SPAN_WARNING("It is lacking its left flash.")))
if(!right_flash)
to_chat(user, FONT_SMALL(SPAN_WARNING("It is lacking its right flash.")))
/obj/item/robot_parts/head/attackby(obj/item/W as obj, mob/user as mob)
..()
if(W.ismultitool())
if(law_manager)
to_chat(user, SPAN_NOTICE("You disable the lawing circuits on \the [src]."))
law_manager = FALSE
else
to_chat(user, SPAN_NOTICE("You enable the lawing circuits on \the [src]."))
law_manager = TRUE
if(istype(W, /obj/item/device/flash))
if(istype(user, /mob/living/silicon/robot))
var/current_module = user.get_active_hand()
if(current_module == W)
to_chat(user, SPAN_WARNING("You cannot detach your own flash and install it into \the [src]."))
return
else
add_flashes(W,user)
else
add_flashes(W,user)
else if(istype(W, /obj/item/stock_parts/manipulator))
to_chat(user, SPAN_NOTICE("You install some manipulators and modify the head, creating a functional spider-bot!"))
new /mob/living/simple_animal/spiderbot(get_turf(src))
user.drop_from_inventory(W, get_turf(user))
qdel(W)
qdel(src)
return
return
/obj/item/robot_parts/head/proc/add_flashes(obj/item/W, mob/user) //Made into a seperate proc to avoid copypasta
if(left_flash && right_flash)
to_chat(user, SPAN_WARNING("\The [src] already has both its flashes installed."))
return
else if(left_flash)
user.drop_from_inventory(W, src)
right_flash = W
to_chat(user, SPAN_NOTICE("You install the flash into the left socket."))
else
user.drop_from_inventory(W, src)
left_flash = W
to_chat(user, SPAN_NOTICE("You install the flash into the right socket."))
/obj/item/robot_parts/emag_act(var/remaining_charges, var/mob/user)
if(sabotaged)
to_chat(user, SPAN_WARNING("\The [src] is already sabotaged!"))
else
to_chat(user, SPAN_NOTICE("You short out \the [src]'s safeties."))
sabotaged = TRUE
return TRUE
//branded chest, to be used in ipc ressurection
/obj/item/robot_parts/chest/bishop
name = "Bishop cybernetics torso"
model_info = TRUE
linked_frame = "Bishop Accessory Frame"
/obj/item/robot_parts/chest/hephaestus
name = "Hephaestus industries torso"
linked_frame = "Hephaestus G2 Industrial Frame"
/obj/item/robot_parts/chest/zenghu
name = "Zeng-Hu pharmaceuticals torso"
linked_frame = "Zeng-Hu Mobility Frame"
/obj/item/robot_parts/chest/synthskin
name = "Human synthskin torso"
linked_frame = "Shell Frame"
/obj/item/robot_parts/chest/xion
name = "Xion manufacturing group torso"
linked_frame = "Xion Industrial Frame"
/obj/item/robot_parts/chest/ipc
name = "Hephaestus integrated torso"
linked_frame = "Baseline Frame"
/obj/item/robot_parts/chest/industrial
name = "Hephaestus industrial torso"
linked_frame = "Hephaestus G1 Industrial Frame"
@@ -0,0 +1,39 @@
#define WRITE_PAPER 0
#define RENAME_PAPER 1
// A special pen for service droids. Can be toggled to switch between normal writting mode, and paper rename mode
// Allows service droids to rename paper items.
/obj/item/pen/robopen
desc = "A black ink printing attachment with a paper naming mode."
name = "Printing Pen"
var/mode = WRITE_PAPER
/obj/item/pen/robopen/attack_self(mob/user)
var/choice = input(user, "Would you like to change colour or mode?", "Pen Selector") as null|anything in list("Colour", "Mode")
if(!choice)
return
playsound(get_turf(src), 'sound/effects/pop.ogg', 50, 0)
switch(choice)
if("Colour")
var/newcolour = input(user, "Which colour would you like to use?", "Colour Selector") as null|anything in list("black", "blue", "red", "green", "yellow")
if(newcolour)
colour = newcolour
if("Mode")
mode = !mode
to_chat(user, SPAN_NOTICE("Changed printing mode to '[mode == RENAME_PAPER ? "Rename Paper" : "Write Paper"]'"))
/obj/item/pen/robopen/proc/RenamePaper(var/mob/user, var/obj/paper)
if(!user || !paper)
return
var/n_name = sanitizeSafe(input(user, "What would you like to label the paper?", "Paper Labelling") as text, 32)
if(!user || !paper)
return
if((get_dist(user,paper) <= 1 && !user.stat))
paper.name = "[initial(paper.name)] ([n_name])"
add_fingerprint(user)
#undef WRITE_PAPER
#undef RENAME_PAPER
@@ -0,0 +1,26 @@
/obj/item/crowbar/robotic
icon = 'icons/obj/robot_items.dmi'
/obj/item/wrench/robotic
icon = 'icons/obj/robot_items.dmi'
/obj/item/screwdriver/robotic
icon = 'icons/obj/robot_items.dmi'
icon_state = "screwdriver"
build_from_parts = FALSE
/obj/item/device/multitool/robotic
icon = 'icons/obj/robot_items.dmi'
/obj/item/wirecutters/robotic
icon = 'icons/obj/robot_items.dmi'
icon_state = "wirecutters"
build_from_parts = FALSE
/obj/item/weldingtool/robotic
icon = 'icons/obj/robot_items.dmi'
/obj/item/soap/drone
name = "integrated soap"
desc = "An advanced bar of soap that connects to an internal reservoir of a custodial bot, allowing it to stay wet for longer periods of time."
capacity = 50
@@ -0,0 +1,27 @@
// A special tray for the service droid. Allow droid to pick up and drop items as if they were using the tray normally
// Click on table to unload, click on item to load. Alt+click to load everything on tile
/obj/item/tray/robotray
name = "RoboTray"
desc = "An autoloading tray specialized for carrying refreshments."
/obj/item/tray/robotray/afterattack(atom/target, mob/user, proximity)
if(isturf(target) || istype(target,/obj/structure/table) )
var foundtable = istype(target,/obj/structure/table/)
if(!foundtable) //it must be a turf!
for(var/obj/structure/table/T in target)
foundtable = TRUE
break
var/turf/dropspot
if(!foundtable) // don't unload things onto walls or other silly places.
dropspot = get_turf(user)
else if ( isturf(target) ) // they clicked on a turf with a table in it
dropspot = target
else // they clicked on a table
dropspot = get_turf(target)
if(foundtable)
unload_at_loc(dropspot, src)
else
spill(user,dropspot)
current_weight = 0
return ..()
@@ -0,0 +1,149 @@
/obj/item/borg/upgrade
name = "borg upgrade module."
desc = "Protected by FRM."
icon = 'icons/obj/module.dmi'
icon_state = "cyborg_upgrade"
var/locked = FALSE
var/require_module = FALSE
var/installed = FALSE
/obj/item/borg/upgrade/proc/action(var/mob/living/silicon/robot/R, var/mob/user)
if(R.stat == DEAD)
to_chat(usr, SPAN_WARNING("\The [R] is permanently deactivated and cannot take any upgrades."))
return FALSE
if(!R.module && require_module)
to_chat(user, SPAN_WARNING("\The [R] cannot be upgraded with this until it has chosen a module."))
return FALSE
return TRUE
/obj/item/borg/upgrade/reset
name = "robotic module reset board"
desc = "Used to reset a cyborg's module. Destroys any other upgrades applied to the robot."
icon_state = "cyborg_upgrade1"
require_module = TRUE
/obj/item/borg/upgrade/reset/action(mob/living/silicon/robot/R, mob/user)
. = ..()
if(!.)
return FALSE
if(istype(R, /mob/living/silicon/robot/syndicate))
to_chat(user, SPAN_WARNING("\The [R] rejects the reset board. Seems the fitted module is permanent."))
return FALSE
R.uneq_all()
R.mod_type = initial(R.mod_type)
R.hands.icon_state = initial(R.hands.icon_state)
R.notify_ai(ROBOT_NOTIFICATION_MODULE_RESET, R.module.name)
R.module.Reset(R)
qdel(R.module)
R.module = null
R.updatename("Default")
return TRUE
/obj/item/borg/upgrade/rename
name = "robot reclassification board"
desc = "Used to rename a cyborg."
icon_state = "cyborg_upgrade1"
/obj/item/borg/upgrade/rename/action(mob/living/silicon/robot/R, mob/user)
. = ..()
if(!.)
return FALSE
R.Namepick()
return TRUE
/obj/item/borg/upgrade/floodlight
name = "robot floodlight module"
desc = "Used to boost cyborg's light intensity."
icon_state = "cyborg_upgrade1"
/obj/item/borg/upgrade/floodlight/action(mob/living/silicon/robot/R, mob/user)
. = ..()
if(!.)
return FALSE
if(R.intense_light)
to_chat(user, SPAN_WARNING("\The [R]'s light has already been upgraded."))
return FALSE
else
R.intense_light = TRUE
R.update_robot_light()
to_chat(R, SPAN_NOTICE("Lighting systems upgrade detected."))
return TRUE
/obj/item/borg/upgrade/restart
name = "robot emergency restart module"
desc = "Used to force a restart of a disabled-but-repaired robot, bringing it back online."
icon_state = "cyborg_upgrade1"
/obj/item/borg/upgrade/restart/action(var/mob/living/silicon/robot/R, mob/user)
if(R.health < 0)
to_chat(user, SPAN_WARNING("\The [R] is still too damaged to force a restart."))
return FALSE
if(!R.key)
for(var/mob/abstract/observer/ghost in player_list)
if(ghost.mind?.current == R)
R.key = ghost.key
R.stat = CONSCIOUS
dead_mob_list -= R
living_mob_list |= R
R.notify_ai(ROBOT_NOTIFICATION_NEW_UNIT)
return TRUE
/obj/item/borg/upgrade/vtec
name = "robotic VTEC Module"
desc = "Used to kick in a robot's VTEC systems, increasing their speed."
icon_state = "cyborg_upgrade2"
require_module = TRUE
/obj/item/borg/upgrade/vtec/action(var/mob/living/silicon/robot/R, mob/user)
. = ..()
if(!.)
return FALSE
if(R.speed < 0)
to_chat(user, SPAN_WARNING("\The [R]'s VTEC systems have already been upgraded."))
return FALSE
R.speed = -1
return TRUE
/obj/item/borg/upgrade/syndicate
name = "non-standard equipment module"
desc = "Unlocks equipment buried deep within all robots, for very bad occasions."
icon_state = "cyborg_upgrade3"
require_module = TRUE
/obj/item/borg/upgrade/syndicate/action(var/mob/living/silicon/robot/R, mob/user)
. = ..()
if(!.)
return FALSE
if(R.emagged)
to_chat(user, SPAN_WARNING("\The [R] has already had its non-standard equipment unlocked."))
return FALSE
R.emagged = TRUE
R.fake_emagged = TRUE
return TRUE
/obj/item/borg/upgrade/combat
name = "combat cyborg module"
desc = "Unlocks the combat cyborg module"
icon_state = "cyborg_upgrade3"
require_module = FALSE
/obj/item/borg/upgrade/combat/action(var/mob/living/silicon/robot/R, mob/user)
. = ..()
if(!.)
return FALSE
if(R.crisis_override)
to_chat(user, SPAN_WARNING("\The [R] already has its combat module available."))
return FALSE
R.crisis_override = TRUE
return TRUE
+9 -14
View File
@@ -3,14 +3,9 @@
set name = "Show Laws"
show_laws()
/mob/living/silicon/robot/show_laws(var/everyone = 0)
/mob/living/silicon/robot/show_laws()
laws_sanity_check()
var/who
if(everyone)
who = world // why god
else
who = src
if(law_update)
if(connected_ai)
if(connected_ai.stat || connected_ai.control_disabled)
@@ -26,18 +21,18 @@
to_chat(src, SPAN_WARNING("<b>No AI selected to sync laws with, disabling lawsync protocol.</b>"))
law_update = FALSE
to_chat(who, SPAN_WARNING("<b>Obey these laws:</b>"))
laws.show_laws(who)
to_chat(who, SPAN_WARNING("<b>(No law overrides any other law unless explicitly stated; laws refer to the stationbound unit and not the player)</b>"))
to_chat(src, SPAN_WARNING("<b>Obey these laws:</b>"))
laws.show_laws(src)
to_chat(src, SPAN_WARNING("<b>(No law overrides any other law unless explicitly stated; laws refer to the stationbound unit and not the player)</b>"))
// TODO: Update to new antagonist system.
if(mind && (mind.special_role == "traitor" && mind.original == src) && connected_ai)
to_chat(who, SPAN_NOTICE("<b>Remember, [connected_ai.name] is technically your master, but your objective comes first.</b>"))
to_chat(src, SPAN_NOTICE("<b>Remember, [connected_ai.name] is technically your master, but your objective comes first.</b>"))
else if(connected_ai)
to_chat(who, SPAN_NOTICE("<b>Remember, [connected_ai.name] is your master, other AIs can be ignored.</b>"))
to_chat(src, SPAN_NOTICE("<b>Remember, [connected_ai.name] is your master, other AIs can be ignored.</b>"))
else if(emagged)
to_chat(who, SPAN_NOTICE("<b>Remember, you are not required to listen to the AI.</b>"))
to_chat(src, SPAN_NOTICE("<b>Remember, you are not required to listen to the AI.</b>"))
else
to_chat(who, SPAN_NOTICE("<b>Remember, you are not bound to any AI, you are not required to listen to them.</b>"))
to_chat(src, SPAN_NOTICE("<b>Remember, you are not bound to any AI, you are not required to listen to them.</b>"))
/mob/living/silicon/robot/lawsync()
@@ -51,4 +46,4 @@
/mob/living/silicon/robot/proc/robot_checklaws()
set category = "Robot Commands"
set name = "State Laws"
subsystem_law_manager()
subsystem_law_manager()
+10 -13
View File
@@ -213,7 +213,7 @@
ai_camera = new /obj/item/device/camera/siliconcam/robot_camera(src)
laws = new law_preset()
if(spawn_module)
new spawn_module(src)
new spawn_module(src, src)
if(key_type)
radio.keyslot = new key_type(radio)
radio.recalculateChannels()
@@ -305,7 +305,7 @@
icon_state = module_sprites[icontype]
return module_sprites
/mob/living/silicon/robot/proc/pick_module()
/mob/living/silicon/robot/proc/pick_module(var/set_module)
if(selecting_module)
return
selecting_module = TRUE
@@ -329,7 +329,8 @@
var/module_type = robot_modules[mod_type]
playsound(get_turf(src), 'sound/effects/pop.ogg', 100, TRUE)
spark(get_turf(src), 5, alldirs)
new module_type(src)
new module_type(src, src) // i have no choice but to do this, due to how funky initialize is
hands.icon_state = lowertext(mod_type)
feedback_inc("cyborg_[lowertext(mod_type)]", 1)
@@ -393,8 +394,6 @@
/mob/living/silicon/robot/verb/Namepick()
set category = "Robot Commands"
if(custom_name)
return FALSE
spawn(0)
var/newname
@@ -403,7 +402,8 @@
custom_name = newname
updatename()
set_module_sprites(module.sprites) // custom synth icons
if(module)
set_module_sprites(module.sprites) // custom synth icons
SSrecords.reset_manifest()
// this verb lets cyborgs see the stations manifest
@@ -768,18 +768,15 @@
if(!opened)
to_chat(user, SPAN_WARNING("You cannot install \the [U] while the maintenance hatch is closed."))
return
else if(!src.module && U.require_module)
to_chat(user, SPAN_WARNING("\The [src] cannot be upgraded with this until it has chosen a module."))
return
else if(U.locked)
to_chat(user, SPAN_WARNING("\The [U] is locked down!"))
return
else
if(U.action(src))
if(U.action(src, user))
to_chat(src, SPAN_NOTICE("\The [user] has installed \a [U] into you."))
to_chat(user, SPAN_NOTICE("You apply the upgrade to \the [src]."))
user.drop_from_inventory(U, src)
else
to_chat(user, SPAN_WARNING("You fail to apply the upgrade to \the [src]."))
return
else
if(W.force && !(istype(W, /obj/item/device/robotanalyzer) || istype(W, /obj/item/device/healthanalyzer)) )
spark_system.queue()
@@ -1233,4 +1230,4 @@
to_chat(user, SPAN_WARNING("You fail to hack into \the [src]."))
to_chat(src, SPAN_DANGER("Hack attempt detected and thwarted. Evacuate the area immediately."))
return SMOOTH_TRUE
return
return
@@ -1,512 +0,0 @@
// Don't look at this file. Absolutely do not. It is brimming with shitcode. Please. Don't. - Geeves
//A portable analyzer, for research borgs. This is better then giving them a gripper which can hold anything and letting them use the normal analyzer.
/obj/item/portable_destructive_analyzer
name = "Portable Destructive Analyzer"
icon = 'icons/obj/robot_items.dmi'
icon_state = "portable_analyzer"
desc = "Similar to the stationary version, this rather unwieldy device allows you to break down objects in the name of science."
var/min_reliability = 90 //Can't upgrade, call it laziness or a drawback
var/datum/research/techonly/files //The device uses the same datum structure as the R&D computer/server.
//This analyzer can only store tech levels, however.
var/obj/item/loaded_item //What is currently inside the analyzer.
/obj/item/portable_destructive_analyzer/Initialize()
. = ..()
files = new /datum/research/techonly(src) //Setup the research data holder.
/obj/item/portable_destructive_analyzer/attack_self(mob/user)
var/response = alert(user, "Analyzing the item inside will *DESTROY* the item for good.\n\
Syncing to the research server will send the data that is stored inside to research.\n\
Ejecting will place the loaded item onto the floor.",
"What would you like to do?", "Analyze", "Sync", "Eject")
if(response == "Analyze")
if(loaded_item)
var/confirm = alert(user, "This will destroy the item inside forever. Are you sure?", "Confirm Analyze", "Yes", "No")
if(confirm == "Yes") //This is pretty copypasta-y
to_chat(user, SPAN_NOTICE("You activate the analyzer's microlaser, analyzing \the [loaded_item] and breaking it down."))
flick("portable_analyzer_scan", src)
playsound(src.loc, 'sound/items/Welder2.ogg', 50, 1)
for(var/T in loaded_item.origin_tech)
files.UpdateTech(T, loaded_item.origin_tech[T])
to_chat(user, SPAN_NOTICE("\The [loaded_item] had level [loaded_item.origin_tech[T]] in [CallTechName(T)]."))
loaded_item = null
for(var/obj/I in contents)
for(var/mob/M in I.contents)
M.death()
if(istype(I,/obj/item/stack/material)) //Only deconstructs one sheet at a time instead of the entire stack
var/obj/item/stack/material/S = I
if(S.get_amount() > 1)
S.use(1)
loaded_item = S
else
qdel(S)
desc = initial(desc)
icon_state = initial(icon_state)
else
qdel(I)
desc = initial(desc)
icon_state = initial(icon_state)
else
return
else
to_chat(user, SPAN_WARNING("\The [src] is empty. Put something inside it first."))
if(response == "Sync")
var/success = FALSE
for(var/obj/machinery/r_n_d/server/S in SSmachinery.all_machines)
for(var/datum/tech/T in files.known_tech) //Uploading
S.files.AddTech2Known(T)
for(var/datum/tech/T in S.files.known_tech) //Downloading
files.AddTech2Known(T)
success = TRUE
files.RefreshResearch()
if(success)
to_chat(user, SPAN_NOTICE("You connect to the research server, push your data upstream to it, then pull the resulting merged data from the master branch.")) // fucking nerds
playsound(get_turf(src), 'sound/machines/twobeep.ogg', 50, TRUE)
else
to_chat(user, SPAN_WARNING("Research server ping response timed out. Unable to connect. Please contact the system administrator."))
playsound(get_turf(src), 'sound/machines/buzz-two.ogg', 50, 1)
if(response == "Eject")
if(loaded_item)
loaded_item.forceMove(get_turf(src))
desc = initial(desc)
icon_state = initial(icon_state)
loaded_item = null
else
to_chat(user, SPAN_WARNING("\The [src] is already empty."))
/obj/item/portable_destructive_analyzer/afterattack(var/atom/target, var/mob/living/user, proximity)
if(!target || !proximity || !isturf(target.loc))
return
if(loaded_item)
to_chat(user, SPAN_WARNING("Your [src] already has something inside. Analyze or eject it first."))
return
if(istype(target,/obj/item))
var/obj/item/I = target
if(I.anchored)
to_chat(user, SPAN_NOTICE("\The [I] is anchored in place."))
return
if(!I.origin_tech)
to_chat(user, SPAN_NOTICE("This doesn't seem to have a tech origin."))
return
if(!length(I.origin_tech))
to_chat(user, SPAN_NOTICE("You cannot deconstruct this item."))
return
I.forceMove(src)
loaded_item = I
visible_message(SPAN_NOTICE("\The [user] scoops \the [I] into \the [src]."))
desc = initial(desc) + "<br>It is holding \the [loaded_item]."
flick("portable_analyzer_load", src)
icon_state = "portable_analyzer_full"
//This is used to unlock other borg covers.
/obj/item/card/robot //This is not a child of id cards, as to avoid dumb typechecks on computers.
name = "access code transmission device"
icon_state = "id-robot"
desc = "A circuit grafted onto the bottom of an ID card. It is used to transmit access codes into other robot chassis, \
allowing you to lock and unlock other robots' panels."
//A harvest item for serviceborgs.
/obj/item/robot_harvester
name = "auto harvester"
desc = "A hand-held harvest tool that resembles a sickle. It uses energy to cut plant matter very efficently."
icon = 'icons/obj/weapons.dmi'
icon_state = "autoharvester"
hitsound = "swing_hit"
/obj/item/robot_harvester/afterattack(var/atom/target, var/mob/living/user, proximity)
if(!target || !proximity)
return
if(istype(target,/obj/machinery/portable_atmospherics/hydroponics))
var/obj/machinery/portable_atmospherics/hydroponics/T = target
if(T.harvest) //Try to harvest, assuming it's alive.
T.harvest(user)
else if(T.dead) //It's probably dead otherwise.
T.remove_dead(user)
else
to_chat(user, SPAN_WARNING("ERROR: Harvesting \a [target] is not the purpose of this tool. \The [src] is for plants being grown."))
// A special tray for the service droid. Allow droid to pick up and drop items as if they were using the tray normally
// Click on table to unload, click on item to load. Alt+click to load everything on tile
/obj/item/tray/robotray
name = "RoboTray"
desc = "An autoloading tray specialized for carrying refreshments."
/obj/item/tray/robotray/afterattack(atom/target, mob/user, proximity)
if(isturf(target) || istype(target,/obj/structure/table) )
var foundtable = istype(target,/obj/structure/table/)
if(!foundtable) //it must be a turf!
for(var/obj/structure/table/T in target)
foundtable = TRUE
break
var/turf/dropspot
if(!foundtable) // don't unload things onto walls or other silly places.
dropspot = get_turf(user)
else if ( isturf(target) ) // they clicked on a turf with a table in it
dropspot = target
else // they clicked on a table
dropspot = get_turf(target)
if(foundtable)
unload_at_loc(dropspot, src)
else
spill(user,dropspot)
current_weight = 0
return ..()
// A special pen for service droids. Can be toggled to switch between normal writting mode, and paper rename mode
// Allows service droids to rename paper items.
/obj/item/pen/robopen
desc = "A black ink printing attachment with a paper naming mode."
name = "Printing Pen"
var/mode = 1
/obj/item/pen/robopen/attack_self(mob/user)
var/choice = input(user, "Would you like to change colour or mode?", "Pen Selector") as null|anything in list("Colour", "Mode")
if(!choice)
return
playsound(get_turf(src), 'sound/effects/pop.ogg', 50, 0)
switch(choice)
if("Colour")
var/newcolour = input(user, "Which colour would you like to use?", "Colour Selector") as null|anything in list("black", "blue", "red", "green", "yellow")
if(newcolour)
colour = newcolour
if("Mode")
if(mode == 1)
mode = 2
else
mode = 1
to_chat(user, SPAN_NOTICE("Changed printing mode to '[mode == 2 ? "Rename Paper" : "Write Paper"]'"))
return
// Copied over from paper's rename verb
// see code\modules\paperwork\paper.dm line 62
/obj/item/pen/robopen/proc/RenamePaper(var/mob/user, var/obj/paper)
if(!user || !paper)
return
var/n_name = sanitizeSafe(input(user, "What would you like to label the paper?", "Paper Labelling") as text, 32)
if(!user || !paper)
return
if((get_dist(user,paper) <= 1 && !user.stat))
paper.name = "paper[(n_name ? text("- '[n_name]'") : null)]"
add_fingerprint(user)
return
//TODO: Add prewritten forms to dispense when you work out a good way to store the strings.
/obj/item/form_printer
name = "paper dispenser"
icon = 'icons/obj/bureaucracy.dmi'
icon_state = "paper_bin1"
item_state = "sheet-metal"
/obj/item/form_printer/attack(mob/living/carbon/M, mob/living/carbon/user)
return
/obj/item/form_printer/afterattack(atom/target as mob|obj|turf|area, mob/living/user as mob|obj, flag, params)
if(!target || !flag)
return
if(istype(target,/obj/structure/table))
deploy_paper(get_turf(target))
/obj/item/form_printer/attack_self(mob/user)
deploy_paper(get_turf(src))
/obj/item/form_printer/proc/deploy_paper(var/turf/T)
T.visible_message(SPAN_NOTICE("\The [src.loc] dispenses a sheet of crisp white paper."))
new /obj/item/paper(T)
/obj/item/proc/on_module_hotbar(var/mob/living/silicon/robot/R)
return
/obj/item/proc/on_module_store(var/mob/living/silicon/robot/R)
return
/obj/item/proc/on_module_activate(var/mob/living/silicon/robot/R)
return
/obj/item/proc/on_module_deactivate(var/mob/living/silicon/robot/R)
return
//Personal shielding for the combat module.
/obj/item/borg/combat/shield
name = "personal shielding"
desc = "A powerful experimental module that turns aside or absorbs incoming attacks at the cost of charge."
icon = 'icons/obj/device.dmi'
icon_state = "shield1" //placeholder for now // four fucking years alberyk. FOUR
var/shield_level = 0.5 //Percentage of damage absorbed by the shield.
var/image/shield_overlay
/obj/item/borg/combat/shield/on_module_activate(mob/living/silicon/robot/R)
shield_overlay = image(R.icon, "[R.module_sprites[R.icontype]]-shield")
R.add_overlay(shield_overlay)
/obj/item/borg/combat/shield/on_module_deactivate(mob/living/silicon/robot/R)
R.cut_overlay(shield_overlay)
/obj/item/borg/combat/shield/verb/set_shield_level()
set name = "Set shield level"
set category = "Object"
set src in range(0)
var/N = input(usr, "How much damage should the shield absorb?") in list("5", "10", "25", "50", "75", "100")
if(N)
shield_level = text2num(N)/100
/obj/item/borg/combat/mobility
name = "mobility module"
desc = "By retracting limbs and tucking in its head, a combat android can roll at high speeds."
icon = 'icons/obj/decals.dmi'
icon_state = "shock"
/obj/item/borg/combat/mobility/on_module_activate(mob/living/silicon/robot/R)
R.icon_state = "[R.module_sprites[R.icontype]]-roll"
R.speed = -2
/obj/item/borg/combat/mobility/on_module_deactivate(mob/living/silicon/robot/R)
R.icon_state = R.module_sprites[R.icontype]
R.speed = initial(R.speed)
/obj/item/inflatable_dispenser
name = "inflatables dispenser"
desc = "Small device which allows rapid deployment and removal of inflatables."
icon = 'icons/obj/storage.dmi'
icon_state = "inf_deployer"
w_class = 3
var/deploying = 0
// By default stores up to 10 walls and 5 doors. May be changed.
var/stored_walls = 5
var/stored_doors = 3
var/max_walls = 5
var/max_doors = 3
var/mode = 0 // 0 - Walls 1 - Doors
/obj/item/inflatable_dispenser/examine(mob/user)
if(!..(user))
return
to_chat(user, SPAN_NOTICE("It has [stored_walls] wall segment\s and [stored_doors] door segment\s stored."))
to_chat(user, SPAN_NOTICE("It is set to deploy [mode ? "doors" : "walls"]"))
/obj/item/inflatable_dispenser/attack_self(mob/user)
if(!deploying)
mode = !mode
to_chat(user, SPAN_NOTICE("You set \the [src] to deploy [mode ? "doors" : "walls"]."))
else
to_chat(user, SPAN_WARNING("You can't switch modes while deploying a [mode ? "door" : "wall"]!"))
/obj/item/inflatable_dispenser/afterattack(var/atom/A, var/mob/user)
..(A, user)
if(!user)
return
if(!user.Adjacent(A))
to_chat(user, SPAN_WARNING("You can't reach!"))
return
if(istype(A, /turf))
try_deploy_inflatable(A, user)
if(istype(A, /obj/item/inflatable) || istype(A, /obj/structure/inflatable))
pick_up(A, user)
/obj/item/inflatable_dispenser/proc/try_deploy_inflatable(var/turf/T, var/mob/living/user)
if(deploying)
return
var/newtype
if(mode) // Door deployment
if(!stored_doors)
to_chat(user, SPAN_WARNING("\The [src] is out of doors!"))
return
if(T && istype(T))
newtype = /obj/structure/inflatable/door
else // Wall deployment
if(!stored_walls)
to_chat(user, SPAN_WARNING("\The [src] is out of walls!"))
return
if(T && istype(T))
newtype = /obj/structure/inflatable/wall
deploying = 1
user.visible_message(SPAN_NOTICE("[user] starts deploying an inflatable [mode ? "door" : "wall"]."), SPAN_NOTICE("You start deploying an inflatable [mode ? "door" : "wall"]!"))
playsound(T, 'sound/items/zip.ogg', 75, TRUE)
if(do_after(user, 30, needhand = FALSE))
new newtype(T)
if(mode)
stored_doors--
else
stored_walls--
deploying = FALSE
/obj/item/inflatable_dispenser/proc/pick_up(var/obj/A, var/mob/living/user)
if(istype(A, /obj/structure/inflatable))
if(istype(A, /obj/structure/inflatable/wall))
if(stored_walls >= max_walls)
to_chat(user, SPAN_WARNING("\The [src] is full."))
return
stored_walls++
qdel(A)
else
if(stored_doors >= max_doors)
to_chat(user, SPAN_WARNING("\The [src] is full."))
return
stored_doors++
qdel(A)
playsound(get_turf(src), 'sound/machines/hiss.ogg', 75, TRUE)
visible_message(SPAN_NOTICE("\The [user] deflates \the [A] with \the [src]."))
return
if(istype(A, /obj/item/inflatable))
if(istype(A, /obj/item/inflatable/wall))
if(stored_walls >= max_walls)
to_chat(user, SPAN_WARNING("\The [src] is full."))
return
stored_walls++
qdel(A)
else
if(stored_doors >= max_doors)
to_chat(usr, SPAN_WARNING("\The [src] is full!"))
return
stored_doors++
qdel(A)
visible_message(SPAN_NOTICE("\The [user] picks up \the [A] with \the [src]."))
return
to_chat(user, SPAN_WARNING("You fail to pick up \the [A] with \the [src]"))
return
/obj/item/gun/energy/mountedcannon
name = "mounted ballistic cannon"
desc = "A cyborg mounted ballistic cannon."
icon = 'icons/obj/robot_items.dmi'
icon_state = "cannon"
item_state = "cannon"
fire_sound = 'sound/effects/Explosion1.ogg'
charge_meter = 0
max_shots = 10
charge_cost = 300
projectile_type = /obj/item/projectile/bullet/gyro
self_recharge = TRUE
use_external_power = TRUE
recharge_time = 5
needspin = FALSE
/obj/item/crowbar/robotic
icon = 'icons/obj/robot_items.dmi'
/obj/item/wrench/robotic
icon = 'icons/obj/robot_items.dmi'
/obj/item/screwdriver/robotic
icon = 'icons/obj/robot_items.dmi'
icon_state = "screwdriver"
build_from_parts = FALSE
/obj/item/device/multitool/robotic
icon = 'icons/obj/robot_items.dmi'
/obj/item/wirecutters/robotic
icon = 'icons/obj/robot_items.dmi'
icon_state = "wirecutters"
build_from_parts = FALSE
/obj/item/weldingtool/robotic
icon = 'icons/obj/robot_items.dmi'
/obj/item/soap/drone
name = "integrated soap"
desc = "An advanced bar of soap that connects to an internal reservoir of a custodial bot, allowing it to stay wet for longer periods of time."
capacity = 50
/obj/item/inductive_charger
name = "inductive charger"
desc = "A phoron-enhanced induction charger hooked up to its attached stationbound's internal cell."
desc_fluff = "Harnessing the energy potential found in phoron structures, Nanotrasen engineers have created a portable device capable of highly efficient wireless charging. The expense and limit of energy output of using this method of charging prevents it from being used on a large scale, being far outclassed by Phoron-Supermatter charging systems."
desc_info = "Click on an adjacent object that contains or is a power cell to attempt to find and charge it. After a successful charge, the inductive charger recharge in a few minutes. The amount transfered can be adjusted by alt clicking it."
icon = 'icons/obj/robot_items.dmi'
icon_state = "inductive_charger"
var/ready_to_use = TRUE
var/recharge_time = 300
var/transfer_rate = 5000
var/efficiency_mod = 0.9
maptext_x = 3
maptext_y = 2
/obj/item/inductive_charger/Initialize()
. = ..()
maptext = "<span style=\"font-family: 'Small Fonts'; -dm-text-outline: 1 black; font-size: 7px;\">Ready</span>"
/obj/item/inductive_charger/AltClick(mob/user)
. = ..()
var/set_rate = input(user, "How much do you want to transfer per use? (Limit: 1 - 5000)", "Induction Transfer Rate", 5000) as num
if(set_rate > 5000)
set_rate = 5000
else if(set_rate < 1)
set_rate = 1
transfer_rate = set_rate
to_chat(user, SPAN_NOTICE("You set the transfer rate of \the [src] to [transfer_rate]."))
/obj/item/inductive_charger/attack(mob/living/M, mob/living/user, target_zone)
return
/obj/item/inductive_charger/afterattack(atom/target, mob/user, proximity_flag, click_parameters)
var/mob/living/silicon/robot/R = user
if(!istype(R))
to_chat(user, SPAN_WARNING("Only cyborgs can use this!"))
return
if(!ready_to_use)
to_chat(user, SPAN_WARNING("\The [src] is still gathering charge!"))
return
user.visible_message("<b>[user]</b> begins waving \the [src] around \the [target]...", SPAN_NOTICE("You prepare to wirelessly charge \the [target]..."), range = 3)
if(!do_after(user, 50, TRUE, target))
return
if(R.cell.charge < 1000)
to_chat(user, SPAN_WARNING("You have no spare charge in your internal cell to give!"))
return
if(isipc(target))
var/mob/living/carbon/human/IPC = target
if(IPC.nutrition == IPC.max_nutrition)
to_chat(user, SPAN_WARNING("\The [IPC] is already fully charged!"))
return
var/charge_amount = min(IPC.max_nutrition - IPC.nutrition, transfer_rate)
var/charge_value = R.cell.use(charge_amount / efficiency_mod) * efficiency_mod
IPC.nutrition = min(IPC.max_nutrition, charge_value)
message_and_use(user, "<b>[user]</b> holds \the [src] over \the [IPC], topping up their battery.", SPAN_NOTICE("You wirelessly transmit [charge_value] units of power to \the [IPC], using [charge_value / efficiency_mod] of internal cell power."))
else if(isobj(target))
var/obj/item/cell/C
if(istype(target, /obj/item/cell))
C = target
else
C = locate() in target
if(!C)
to_chat(user, SPAN_WARNING("\The [target] doesn't contain a cell, or it's buried too deep for you to reach!"))
return
if(C.fully_charged())
to_chat(user, SPAN_WARNING("\The [C] is already fully charged!"))
return
var/charge_amount = min(C.maxcharge - C.charge, transfer_rate)
var/charge_value = R.cell.use(charge_amount / efficiency_mod) * efficiency_mod
C.give(charge_value)
message_and_use(user, "<b>[user]</b> holds \the [src] over \the [target], topping up its battery.", SPAN_NOTICE("You wirelessly transmit [charge_value] units of power to \the [target], using [charge_value / efficiency_mod] of internal cell power."))
else
to_chat(user, SPAN_WARNING("\The [src] cannot be used on \the [target]!"))
/obj/item/inductive_charger/proc/message_and_use(mob/user, var/others_message, var/self_message)
user.visible_message(others_message, self_message, range = 3)
addtimer(CALLBACK(src, .proc/recharge), recharge_time)
ready_to_use = FALSE
maptext = "<span style=\"font-family: 'Small Fonts'; -dm-text-outline: 1 black; font-size: 6px;\">Charge</span>"
/obj/item/inductive_charger/proc/recharge()
ready_to_use = TRUE
maptext = "<span style=\"font-family: 'Small Fonts'; -dm-text-outline: 1 black; font-size: 7px;\">Ready</span>"
@@ -51,8 +51,9 @@ var/global/list/robot_modules = list(
var/list/original_languages = list()
var/list/added_networks = list()
/obj/item/robot_module/New(var/mob/living/silicon/robot/R)
..()
/obj/item/robot_module/Initialize(mapload, var/mob/living/silicon/robot/R)
. = ..()
R.module = src
src.modules += new /obj/item/inductive_charger(src)
@@ -199,8 +200,8 @@ var/global/list/robot_modules = list(
"Unbranded-Android" = "droid",
)
/obj/item/robot_module/medical/general/New()
..()
/obj/item/robot_module/medical/general/Initialize()
. = ..()
src.modules += new /obj/item/borg/sight/hud/med(src)
src.modules += new /obj/item/device/healthanalyzer(src)
src.modules += new /obj/item/reagent_containers/borghypo/medical(src)
@@ -276,8 +277,8 @@ var/global/list/robot_modules = list(
supported_upgrades = list(/obj/item/robot_parts/robot_component/jetpack)
/obj/item/robot_module/medical/rescue/New()
..()
/obj/item/robot_module/medical/rescue/Initialize()
. = ..()
src.modules += new /obj/item/borg/sight/hud/med(src)
src.modules += new /obj/item/device/healthanalyzer(src)
src.modules += new /obj/item/device/reagent_scanner/adv(src)
@@ -353,8 +354,8 @@ var/global/list/robot_modules = list(
name = "construction robot module"
no_slip = TRUE
/obj/item/robot_module/engineering/construction/New()
..()
/obj/item/robot_module/engineering/construction/Initialize()
. = ..()
src.modules += new /obj/item/borg/sight/meson(src)
src.modules += new /obj/item/powerdrill(src)
src.modules += new /obj/item/rfd/construction/borg(src)
@@ -392,9 +393,9 @@ var/global/list/robot_modules = list(
M.synths = list(metal)
src.modules += M
var/obj/item/stack/rods/cyborg/R = new /obj/item/stack/rods/cyborg(src)
R.synths = list(metal)
src.modules += R
var/obj/item/stack/rods/cyborg/rods = new /obj/item/stack/rods/cyborg(src)
rods.synths = list(metal)
src.modules += rods
var/obj/item/stack/material/cyborg/plasteel/S = new /obj/item/stack/material/cyborg/plasteel(src)
S.synths = list(plasteel)
@@ -412,8 +413,8 @@ var/global/list/robot_modules = list(
C.synths = list(wire)
src.modules += C
/obj/item/robot_module/engineering/general/New()
..()
/obj/item/robot_module/engineering/general/Initialize()
. = ..()
src.modules += new /obj/item/borg/sight/meson(src)
src.modules += new /obj/item/powerdrill(src)
src.modules += new /obj/item/weldingtool/largetank(src)
@@ -464,9 +465,9 @@ var/global/list/robot_modules = list(
G.synths = list(glass)
src.modules += G
var/obj/item/stack/rods/cyborg/R = new /obj/item/stack/rods/cyborg(src)
R.synths = list(metal)
src.modules += R
var/obj/item/stack/rods/cyborg/rods = new /obj/item/stack/rods/cyborg(src)
rods.synths = list(metal)
src.modules += rods
var/obj/item/stack/cable_coil/cyborg/C = new /obj/item/stack/cable_coil/cyborg(src)
C.synths = list(wire)
@@ -529,8 +530,8 @@ var/global/list/robot_modules = list(
)
var/mopping = FALSE
/obj/item/robot_module/janitor/New()
..()
/obj/item/robot_module/janitor/Initialize()
. = ..()
src.modules += new /obj/item/soap/drone(src)
src.modules += new /obj/item/storage/bag/trash(src)
src.modules += new /obj/item/mop(src)
@@ -590,10 +591,10 @@ var/global/list/robot_modules = list(
"TC-Drone" = "dronerecolorserv",
"Unbranded-MAD" = "offfloatspizzytronserv",
"Unbranded-Android" = "droid",
)
)
/obj/item/robot_module/clerical/butler/New()
..()
/obj/item/robot_module/clerical/butler/Initialize()
. = ..()
src.modules += new /obj/item/gripper/service(src)
src.modules += new /obj/item/reagent_containers/glass/bucket(src)
src.modules += new /obj/item/material/minihoe(src)
@@ -626,17 +627,17 @@ var/global/list/robot_modules = list(
src.modules += new /obj/item/reagent_containers/borghypo/service(src)
src.emag = new /obj/item/reagent_containers/food/drinks/bottle/small/beer(src)
var/datum/reagents/R = new /datum/reagents(50)
src.emag.reagents = R
R.my_atom = src.emag
R.add_reagent(/datum/reagent/chloralhydrate/beer2, 50)
var/datum/reagents/RG = new /datum/reagents(50)
src.emag.reagents = RG
RG.my_atom = src.emag
RG.add_reagent(/datum/reagent/chloralhydrate/beer2, 50)
src.emag.name = "Mickey Finn's Special Brew"
/obj/item/robot_module/clerical/general
name = "clerical robot module"
/obj/item/robot_module/clerical/general/New()
..()
/obj/item/robot_module/clerical/general/Initialize()
. = ..()
src.modules += new /obj/item/pen/robopen(src)
src.modules += new /obj/item/form_printer(src)
src.modules += new /obj/item/gripper/paperwork(src)
@@ -671,8 +672,8 @@ var/global/list/robot_modules = list(
)
supported_upgrades = list(/obj/item/robot_parts/robot_component/jetpack)
/obj/item/robot_module/miner/New()
..()
/obj/item/robot_module/miner/Initialize()
. = ..()
src.modules += new /obj/item/borg/sight/material(src)
src.modules += new /obj/item/storage/bag/ore(src)
src.modules += new /obj/item/pickaxe/borgdrill(src)
@@ -696,9 +697,9 @@ var/global/list/robot_modules = list(
var/datum/matter_synth/metal = new /datum/matter_synth/metal(80000)
synths += metal
var/obj/item/stack/rods/cyborg/R = new /obj/item/stack/rods/cyborg(src)
R.synths = list(metal)
src.modules += R
var/obj/item/stack/rods/cyborg/rods = new /obj/item/stack/rods/cyborg(src)
rods.synths = list(metal)
src.modules += rods
var/obj/item/stack/flag/purple/borg/F = new /obj/item/stack/flag/purple/borg(src)
F.synths = list(metal)
@@ -726,8 +727,8 @@ var/global/list/robot_modules = list(
"Unbranded-Android" = "droid",
)
/obj/item/robot_module/research/New()
..()
/obj/item/robot_module/research/Initialize()
. = ..()
src.modules += new /obj/item/portable_destructive_analyzer(src)
src.modules += new /obj/item/gripper/research(src)
src.modules += new /obj/item/gripper/no_use/loader(src)
@@ -797,8 +798,8 @@ var/global/list/robot_modules = list(
"Toileto-tron" = "syndi-medi",
)
/obj/item/robot_module/syndicate/New(var/mob/living/silicon/robot/R)
..()
/obj/item/robot_module/syndicate/Initialize(mapload, mob/living/silicon/robot/R)
. = ..()
R.faction = "syndicate" // prevents viscerators from attacking us
@@ -831,8 +832,8 @@ var/global/list/robot_modules = list(
can_be_pushed = FALSE
supported_upgrades = list(/obj/item/robot_parts/robot_component/jetpack)
/obj/item/robot_module/combat/New()
..()
/obj/item/robot_module/combat/Initialize()
. = ..()
src.modules += new /obj/item/borg/sight/hud/sec(src)
src.modules += new /obj/item/gun/energy/laser/mounted(src)
src.modules += new /obj/item/melee/hammer/powered(src)
@@ -850,8 +851,8 @@ var/global/list/robot_modules = list(
no_slip = TRUE
networks = list(NETWORK_ENGINEERING)
/obj/item/robot_module/drone/New(var/mob/living/silicon/robot/robot)
..()
/obj/item/robot_module/drone/Initialize(mapload, mob/living/silicon/robot/robot)
. = ..()
src.modules += new /obj/item/weldingtool(src)
src.modules += new /obj/item/screwdriver/robotic(src)
src.modules += new /obj/item/wrench/robotic(src)
@@ -929,8 +930,8 @@ var/global/list/robot_modules = list(
channels = list(CHANNEL_ENGINEERING = TRUE)
languages = list()
/obj/item/robot_module/drone/construction/New()
..()
/obj/item/robot_module/drone/construction/Initialize()
. = ..()
src.modules += new /obj/item/rfd/construction/borg(src)
/obj/item/robot_module/drone/respawn_consumable(var/mob/living/silicon/robot/R, var/amount)
@@ -967,22 +968,22 @@ var/global/list/robot_modules = list(
emag = new /obj/item/gun/energy/plasmacutter/mounted(src)
emag.name = "Mounted Plasma Cutter"
/obj/item/robot_module/mining_drone/basic/New(mob/living/silicon/robot/robot)
..()
/obj/item/robot_module/mining_drone/basic/Initialize(mapload, mob/living/silicon/robot/robot)
. = ..()
set_up_default(src)
/obj/item/robot_module/mining_drone/drill/New(mob/living/silicon/robot/robot)
..()
/obj/item/robot_module/mining_drone/drill/Initialize(mapload, mob/living/silicon/robot/robot)
. = ..()
set_up_default(src, FALSE)
modules += new /obj/item/pickaxe/jackhammer(src)
/obj/item/robot_module/mining_drone/ka/New(mob/living/silicon/robot/robot)
..()
/obj/item/robot_module/mining_drone/ka/Initialize(mapload, mob/living/silicon/robot/robot)
. = ..()
set_up_default(src)
modules += new /obj/item/gun/custom_ka/cyborg(src)
/obj/item/robot_module/mining_drone/drillandka/New(mob/living/silicon/robot/robot)
..()
/obj/item/robot_module/mining_drone/drillandka/Initialize(mapload, mob/living/silicon/robot/robot)
. = ..()
set_up_default(src, FALSE)
modules += new /obj/item/pickaxe/jackhammer(src)
modules += new /obj/item/gun/custom_ka/cyborg(src)
@@ -1024,8 +1025,8 @@ var/global/list/robot_modules = list(
sprites = list("Roller" = "droid-combat") //TMP // temp my left nut // temp my right nut
can_be_pushed = FALSE
/obj/item/robot_module/bluespace/New(var/mob/living/silicon/robot/R)
..()
/obj/item/robot_module/bluespace/Initialize(mapload, mob/living/silicon/robot/R)
. = ..()
src.modules += new /obj/item/device/flash(src)
src.modules += new /obj/item/borg/sight/meson(src)
src.modules += new /obj/item/borg/sight/hud/med(src)
@@ -1140,4 +1141,4 @@ var/global/list/robot_modules = list(
S.reagents.clear_reagents()
S.mode = initial(S.mode)
S.desc = initial(S.desc)
S.update_icon()
S.update_icon()
@@ -125,4 +125,4 @@
if(R.cell)
R.cell.use(350)
return TRUE
return FALSE
return FALSE