diff --git a/code/game/mecha/mech_fabricator.dm b/code/game/mecha/mech_fabricator.dm index 56c9f74f49f..973b8de1d61 100644 --- a/code/game/mecha/mech_fabricator.dm +++ b/code/game/mecha/mech_fabricator.dm @@ -44,7 +44,12 @@ /obj/item/robot_parts/l_arm, /obj/item/robot_parts/r_arm, /obj/item/robot_parts/l_leg, - /obj/item/robot_parts/r_leg + /obj/item/robot_parts/r_leg, + /obj/item/robot_parts/robot_component/binary_communication_device, + /obj/item/robot_parts/robot_component/radio, + /obj/item/robot_parts/robot_component/actuator, + /obj/item/robot_parts/robot_component/diagnosis_unit, + /obj/item/robot_parts/robot_component/camera ), "Ripley"=list( /obj/item/mecha_parts/chassis/ripley, diff --git a/code/game/objects/items/robot/robot_parts.dm b/code/game/objects/items/robot/robot_parts.dm index d15e17033f7..aa938a13e55 100644 --- a/code/game/objects/items/robot/robot_parts.dm +++ b/code/game/objects/items/robot/robot_parts.dm @@ -162,7 +162,7 @@ else user << "\blue You need to attach a flash to it first!" - if(istype(W, /obj/item/device/mmi) || istype(W, /obj/item/device/mmi/posibrain)) + if(istype(W, /obj/item/device/mmi)) var/obj/item/device/mmi/M = W if(check_completion()) if(!istype(loc,/turf)) @@ -194,7 +194,7 @@ user << "\red This [W] does not seem to fit." return - var/mob/living/silicon/robot/O = new /mob/living/silicon/robot(get_turf(loc)) + var/mob/living/silicon/robot/O = new /mob/living/silicon/robot(get_turf(loc), unfinished = 1) if(!O) return user.drop_item() diff --git a/code/modules/mob/living/silicon/robot/component.dm b/code/modules/mob/living/silicon/robot/component.dm new file mode 100644 index 00000000000..b45ea8b0ae3 --- /dev/null +++ b/code/modules/mob/living/silicon/robot/component.dm @@ -0,0 +1,149 @@ +// 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/energy_consumption = 0 +/datum/robot_component/var/max_damage = 30 +/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/proc/is_functioning() + return brute_damage + electronics_damage < 30 + +/datum/robot_component/New(mob/living/silicon/robot/R) + src.owner = R + +/datum/robot_component/proc/install() +/datum/robot_component/proc/uninstall() + +/datum/robot_component/proc/destroy() + if(wrapped) + del wrapped + + + wrapped = new/obj/item/broken_device + + // The thing itself isn't there anymore, but some fried remains are. + installed = -1 + uninstall() + +/datum/robot_component/proc/take_damage(brute, electronics, sharp) + if(installed != 1) return + + brute_damage += brute + electronics_damage += electronics + + if(brute_damage + electronics_damage > max_damage) destroy() + +/datum/robot_component/proc/heal_damage(brute, electronics) + if(!is_functioning()) + // If it's not functioning, it's beyond repairing without taking it out. + return 0 + + brute_damage = max(0, brute_damage - brute) + electronics_damage = max(0, electronics_damage - electronics) + +/datum/robot_component/proc/is_powered() + return installed == 1 && (!energy_consumption || powered) + + +/datum/robot_component/proc/consume_power() + if(toggled == 0) + powered = 0 + return + if(owner.cell.charge >= energy_consumption) + owner.cell.use(energy_consumption) + powered = 1 + else + powered = 0 + + +/datum/robot_component/actuator + name = "actuator" + energy_consumption = 2 + external_type = /obj/item/robot_parts/robot_component/actuator + max_damage = 60 + +/datum/robot_component/cell + name = "power cell" + max_damage = 60 + +/datum/robot_component/cell/destroy() + ..() + owner.cell = null + +/datum/robot_component/radio + name = "radio" + external_type = /obj/item/robot_parts/robot_component/radio + energy_consumption = 3 + max_damage = 10 + +/datum/robot_component/binary_communication + name = "binary communication device" + external_type = /obj/item/robot_parts/robot_component/binary_communication_device + energy_consumption = 0 + max_damage = 30 + +/datum/robot_component/camera + name = "camera" + external_type = /obj/item/robot_parts/robot_component/camera + energy_consumption = 2 + max_damage = 20 + +/datum/robot_component/diagnosis_unit + name = "self-diagnosis unit" + energy_consumption = 1 + external_type = /obj/item/robot_parts/robot_component/diagnosis_unit + max_damage = 30 + +/mob/living/silicon/robot/proc/initialize_components() + // This only initializes the components, it doesn't set them to installed. + + components["actuator"] = new/datum/robot_component/actuator(src) + components["radio"] = new/datum/robot_component/radio(src) + components["power cell"] = new/datum/robot_component/cell(src) + components["diagnosis unit"] = new/datum/robot_component/diagnosis_unit(src) + components["camera"] = new/datum/robot_component/camera(src) + components["comms"] = new/datum/robot_component/binary_communication(src) + +/mob/living/silicon/robot/proc/is_component_functioning(module_name) + var/datum/robot_component/C = components[module_name] + return C && C.installed == 1 && C.toggled && C.is_powered() + +/obj/item/broken_device + name = "broken component" + icon = 'robot_component.dmi' + icon_state = "broken" + +/obj/item/robot_parts/robot_component + icon = 'robot_component.dmi' + icon_state = "working" + construction_time = 200 + construction_cost = list("metal"=5000) + + +// TODO: actual icons ;) +/obj/item/robot_parts/robot_component/binary_communication_device + name = "binary communication device" + +/obj/item/robot_parts/robot_component/actuator + name = "actuator" + +/obj/item/robot_parts/robot_component/camera + name = "camera" + +/obj/item/robot_parts/robot_component/diagnosis_unit + name = "diagnosis unit" + +/obj/item/robot_parts/robot_component/radio + name = "radio" \ No newline at end of file diff --git a/code/modules/mob/living/silicon/robot/life.dm b/code/modules/mob/living/silicon/robot/life.dm index a4d6cdc7481..11d6bea91b4 100644 --- a/code/modules/mob/living/silicon/robot/life.dm +++ b/code/modules/mob/living/silicon/robot/life.dm @@ -37,23 +37,25 @@ /mob/living/silicon/robot/proc/use_power() - if (src.cell) + if (is_component_functioning("power cell")) if(src.cell.charge <= 0) uneq_all() src.stat = 1 - else if (src.cell.charge <= 100) - uneq_all() - src.sight_mode = 0 - src.cell.use(1) else if(src.module_state_1) - src.cell.use(5) + src.cell.use(3) if(src.module_state_2) - src.cell.use(5) + src.cell.use(3) if(src.module_state_3) - src.cell.use(5) - src.cell.use(1) - src.blinded = 0 + src.cell.use(3) + + for(var/V in components) + var/datum/robot_component/C = components[V] + C.consume_power() + + if(!is_component_functioning("actuator")) + Paralyse(3) + src.stat = 0 else uneq_all() @@ -128,6 +130,17 @@ src.druggy-- src.druggy = max(0, src.druggy) + if(!is_component_functioning("radio")) + radio.on = 0 + else + radio.on = 1 + + if(is_component_functioning("camera")) + src.blinded = 0 + else + src.blinded = 1 + + return 1 /mob/living/silicon/robot/proc/handle_regular_hud_updates() diff --git a/code/modules/mob/living/silicon/robot/robot.dm b/code/modules/mob/living/silicon/robot/robot.dm index af99686b006..2386e899781 100644 --- a/code/modules/mob/living/silicon/robot/robot.dm +++ b/code/modules/mob/living/silicon/robot/robot.dm @@ -27,6 +27,9 @@ var/obj/item/weapon/cell/cell = null var/obj/machinery/camera/camera = null + // Components are basically robot organs. + var/list/components = list() + var/obj/item/device/mmi/mmi = null var/obj/item/device/pda/ai/rbPDA = null @@ -58,7 +61,7 @@ var/braintype = "Cyborg" var/pose -/mob/living/silicon/robot/New(loc,var/syndie = 0) +/mob/living/silicon/robot/New(loc,var/syndie = 0,var/unfinished = 0) spark_system = new /datum/effect/effect/system/spark_spread() spark_system.set_up(5, 0, src) spark_system.attach(src) @@ -67,12 +70,10 @@ updatename("Default") updateicon() - if(!cell) - cell = new /obj/item/weapon/cell(src) - cell.maxcharge = 7500 - cell.charge = 7500 - if(syndie) + if(!cell) + cell = new /obj/item/weapon/cell(src) + laws = new /datum/ai_laws/antimov() lawupdate = 0 scrambledcodes = 1 @@ -99,6 +100,25 @@ camera.network = list("SS13") if(isWireCut(5)) // 5 = BORG CAMERA camera.status = 0 + + initialize_components() + if(!unfinished) + // Create all the robot parts. + for(var/V in components) if(V != "power cell") + var/datum/robot_component/C = components[V] + C.installed = 1 + C.wrapped = new C.external_type + + if(!cell) + cell = new /obj/item/weapon/cell(src) + cell.maxcharge = 7500 + cell.charge = 7500 + + if(cell) + var/datum/robot_component/cell_component = components["power cell"] + cell_component.wrapped = cell + cell_component.installed = 1 + ..() playsound(loc, 'sound/voice/liveagain.ogg', 75, 1) @@ -381,6 +401,53 @@ viewalerts = 1 src << browse(dat, "window=robotalerts&can_close=0") +/mob/living/silicon/robot/proc/self_diagnosis() + if(!is_component_functioning("diagnosis unit")) + return null + + var/dat = "
| Power consumption | [C.energy_consumption] |
| Brute Damage: | [C.brute_damage] |
| Electronics Damage: | [C.electronics_damage] |
| Powered: | [(!C.energy_consumption || C.is_powered()) ? "Yes" : "No"] |
| Toggled: | [ C.toggled ? "Yes" : "No"] |