Merge pull request #3126 from CIB/bleeding-edge-freeze

Implemented robot components(organs)
This commit is contained in:
Chinsky
2013-06-22 22:58:04 -07:00
8 changed files with 390 additions and 23 deletions

View File

@@ -0,0 +1,145 @@
// 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/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(installed != 1)
// If it's not installed, can't repair it.
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"

View File

@@ -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()

View File

@@ -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 = "<HEAD><TITLE>[src.name] Self-Diagnosis Report</TITLE></HEAD><BODY>\n"
for (var/V in components)
var/datum/robot_component/C = components[V]
dat += "<b>[C.name]</b><br><table><tr><td>Power consumption</td><td>[C.energy_consumption]</td></tr><tr><td>Brute Damage:</td><td>[C.brute_damage]</td></tr><tr><td>Electronics Damage:</td><td>[C.electronics_damage]</td></tr><tr><td>Powered:</td><td>[(!C.energy_consumption || C.is_powered()) ? "Yes" : "No"]</td></tr><tr><td>Toggled:</td><td>[ C.toggled ? "Yes" : "No"]</td></table><br>"
return dat
/mob/living/silicon/robot/verb/self_diagnosis_verb()
set category = "Robot Commands"
set name = "Self Diagnosis"
if(!is_component_functioning("diagnosis unit"))
src << "\red Your self-diagnosis component isn't functioning."
var/dat = self_diagnosis()
src << browse(dat, "window=robotdiagnosis")
/mob/living/silicon/robot/verb/toggle_component()
set category = "Robot Commands"
set name = "Toggle Component"
set desc = "Toggle a component, conserving power."
var/list/installed_components = list()
for(var/V in components)
if(V == "power cell") continue
var/datum/robot_component/C = components[V]
if(C.installed)
installed_components += V
var/toggle = input(src, "Which component do you want to toggle?", "Toggle Component") as null|anything in installed_components
if(!toggle)
return
var/datum/robot_component/C = components[toggle]
if(C.toggled)
C.toggled = 0
src << "\red You disable [C.name]."
else
C.toggled = 1
src << "\red You enable [C.name]."
/mob/living/silicon/robot/blob_act()
if (stat != 2)
adjustBruteLoss(60)
@@ -564,6 +631,20 @@
if (istype(W, /obj/item/weapon/handcuffs)) // fuck i don't even know why isrobot() in handcuff code isn't working so this will have to do
return
if(opened) // Are they trying to insert something?
for(var/V in components)
var/datum/robot_component/C = components[V]
if(!C.installed && istype(W, C.external_type))
C.installed = 1
C.wrapped = W
C.install()
user.drop_item()
W.loc = null
usr << "\blue You install the [W.name]."
return
if (istype(W, /obj/item/weapon/weldingtool))
if (!getBruteLoss())
user << "Nothing to fix here!"
@@ -609,6 +690,27 @@
C.updateicon()
new/obj/item/robot_parts/chest(loc)
src.Del()
else
// Okay we're not removing the cell or an MMI, but maybe something else?
var/list/removable_components = list()
for(var/V in components)
if(V == "power cell") continue
var/datum/robot_component/C = components[V]
if(C.installed == 1)
removable_components += V
var/remove = input(user, "Which component do you want to pry out?", "Remove Component") as null|anything in removable_components
if(!remove)
return
var/datum/robot_component/C = components[remove]
var/obj/item/I = C.wrapped
user << "You remove \the [I]."
I.loc = src.loc
if(C.installed == 1)
C.uninstall()
C.installed = 0
else
if(locked)
user << "The cover is locked and cannot be opened."
@@ -618,17 +720,20 @@
updateicon()
else if (istype(W, /obj/item/weapon/cell) && opened) // trying to put a cell inside
var/datum/robot_component/C = components["power cell"]
if(wiresexposed)
user << "Close the panel first."
else if(cell)
else if(cell || C.installed)
user << "There is a power cell already installed."
else
user.drop_item()
W.loc = src
cell = W
user << "You insert the power cell."
// chargecount = 0
updateicon()
C.installed = 1
C.wrapped = W
C.install()
else if (istype(W, /obj/item/weapon/wirecutters) || istype(W, /obj/item/device/multitool))
if (wiresexposed)
@@ -901,6 +1006,7 @@
add_fingerprint(user)
if(opened && !wiresexposed && (!istype(user, /mob/living/silicon)))
var/datum/robot_component/cell_component = components["power cell"]
if(cell)
cell.updateicon()
cell.add_fingerprint(user)
@@ -908,6 +1014,11 @@
user << "You remove \the [cell]."
cell = null
updateicon()
else if(cell_component.installed == -1)
cell_component.installed = 0
var/obj/item/broken_device = cell_component.wrapped
user << "You remove \the [broken_device]."
user.put_in_active_hand(broken_device)
if(ishuman(user))
if(istype(user:gloves, /obj/item/clothing/gloves/space_ninja)&&user:gloves:candrain&&!user:gloves:draining)

View File

@@ -0,0 +1,83 @@
/mob/living/silicon/robot/getBruteLoss()
var/amount = 0
for(var/V in components)
var/datum/robot_component/C = components[V]
if(C.installed == 1) amount += C.brute_damage
return amount
/mob/living/silicon/robot/getFireLoss()
var/amount = 0
for(var/V in components)
var/datum/robot_component/C = components[V]
if(C.installed == 1) amount += C.electronics_damage
return amount
/mob/living/silicon/robot/adjustBruteLoss(var/amount)
if(amount > 0)
take_overall_damage(amount, 0)
else
heal_overall_damage(-amount, 0)
/mob/living/silicon/robot/adjustFireLoss(var/amount)
if(amount > 0)
take_overall_damage(0, amount)
else
heal_overall_damage(0, -amount)
/mob/living/silicon/robot/proc/get_damaged_components(var/brute, var/burn)
var/list/datum/robot_component/parts = list()
for(var/V in components)
var/datum/robot_component/C = components[V]
if(C.installed == 1) if((brute && C.brute_damage) || (burn && C.electronics_damage))
parts += C
return parts
/mob/living/silicon/robot/proc/get_damageable_components()
var/list/rval = new
for(var/V in components)
var/datum/robot_component/C = components[V]
if(C.installed == 1) rval += C
return rval
/mob/living/silicon/robot/heal_organ_damage(var/brute, var/burn)
var/list/datum/robot_component/parts = get_damaged_components(brute,burn)
if(!parts.len) return
var/datum/robot_component/picked = pick(parts)
picked.heal_damage(brute,burn)
/mob/living/silicon/robot/take_organ_damage(var/brute, var/burn, var/sharp = 0)
var/datum/robot_component/C = pick(get_damageable_components())
C.take_damage(brute,burn,sharp)
/mob/living/silicon/robot/heal_overall_damage(var/brute, var/burn)
var/list/datum/robot_component/parts = get_damaged_components(brute,burn)
while(parts.len && (brute>0 || burn>0) )
var/datum/robot_component/picked = pick(parts)
var/brute_was = picked.brute_damage
var/burn_was = picked.electronics_damage
picked.heal_damage(brute,burn)
brute -= (brute_was-picked.brute_damage)
burn -= (burn_was-picked.electronics_damage)
parts -= picked
/mob/living/silicon/robot/take_overall_damage(var/brute, var/burn, var/sharp = 0, var/used_weapon = null)
if(status_flags & GODMODE) return //godmode
var/list/datum/robot_component/parts = get_damageable_components()
while(parts.len && (brute>0 || burn>0) )
var/datum/robot_component/picked = pick(parts)
var/brute_was = picked.brute_damage
var/burn_was = picked.electronics_damage
picked.take_damage(brute,burn)
brute -= (picked.brute_damage - brute_was)
burn -= (picked.electronics_damage - burn_was)
parts -= picked

View File

@@ -24,6 +24,14 @@
return ..(message)
message = copytext(message, 3)
message = trim(copytext(sanitize(message), 1, MAX_MESSAGE_LEN))
// TODO: move the component system up to silicon so we don't have to use this ugly hack..
if(istype(src, /mob/living/silicon/robot))
var/mob/living/silicon/robot/R = src
if(!R.is_component_functioning("comms"))
src << "\red Your binary communications component isn't functional."
return
robot_talk(message)
else if (department_radio_keys[prefix] == "department")
if(isAI(src)&&client)//For patching directly into AI holopads.