Cyborg Power Usage Overhaul

- Adds new standardised proc for power usage as Cyborg
- Each component now uses different amount of power. Some components use "idle" power (camera), which means constant load. Other components use "active" power, which is single-time burst load.. Example: Actuator.
- Power usage is directly proportional to work done. Moving cyborg uses more power than still cyborg.
- Information in Status tab changed. Now it only shows percentage of remaining charge, as well as cell rating and cell load (W)
This commit is contained in:
Atlantiscze
2014-09-17 07:31:20 +02:00
parent f3acb6d8e1
commit ded8e21c0f
7 changed files with 131 additions and 24 deletions

View File

@@ -6,8 +6,9 @@
/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/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.
@@ -55,34 +56,47 @@
electronics_damage = max(0, electronics_damage - electronics)
/datum/robot_component/proc/is_powered()
return (installed == 1) && (brute_damage + electronics_damage < max_damage) && (!energy_consumption || powered)
return (installed == 1) && (brute_damage + electronics_damage < max_damage) && (!idle_usage || powered)
/datum/robot_component/proc/update_power_state()
if(toggled == 0)
powered = 0
return
if(owner.cell && owner.cell.charge >= energy_consumption)
owner.cell.use(energy_consumption)
if(owner.cell && owner.cell.charge >= idle_usage)
owner.cell_use_power(idle_usage)
powered = 1
else
powered = 0
// ARMOUR
// Protects the cyborg from damage. Usually first module to be hit
// No power usage
/datum/robot_component/armour
name = "armour plating"
energy_consumption = 0
external_type = /obj/item/robot_parts/robot_component/armour
max_damage = 60
// ACTUATOR
// Enables movement.
// Uses no power when idle. Uses 50J for each tile the cyborg moves.
/datum/robot_component/actuator
name = "actuator"
energy_consumption = 2
idle_usage = 0
active_usage = 50
external_type = /obj/item/robot_parts/robot_component/actuator
max_damage = 50
//A fixed and much cleaner implementation of /tg/'s special snowflake code.
/datum/robot_component/actuator/is_powered()
return (installed == 1) && (brute_damage + electronics_damage < max_damage)
// POWER CELL
// Stores power (how unexpected..)
// No power usage
/datum/robot_component/cell
name = "power cell"
max_damage = 50
@@ -91,33 +105,55 @@
..()
owner.cell = null
// RADIO
// Enables radio communications
// Uses no power when idle. Uses 10J for each received radio message, 50 for each transmitted message.
/datum/robot_component/radio
name = "radio"
external_type = /obj/item/robot_parts/robot_component/radio
energy_consumption = 1
active_usage = 10
max_damage = 40
// BINARY RADIO
// Enables binary communications with other cyborgs/AIs
// Uses no power when idle. Uses 10J for each received radio message, 50 for each transmitted message
/datum/robot_component/binary_communication
name = "binary communication device"
external_type = /obj/item/robot_parts/robot_component/binary_communication_device
energy_consumption = 0
active_usage = 10
max_damage = 30
// CAMERA
// Enables cyborg vision. Can also be remotely accessed via consoles.
// Uses 10J constantly
/datum/robot_component/camera
name = "camera"
external_type = /obj/item/robot_parts/robot_component/camera
energy_consumption = 1
idle_usage = 10
max_damage = 40
// SELF DIAGNOSIS MODULE
// Analyses cyborg's modules, providing damage readouts and basic information
// Uses 1kJ burst when analysis is done
/datum/robot_component/diagnosis_unit
name = "self-diagnosis unit"
energy_consumption = 1
active_usage = 1000
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.
// HELPER STUFF
// Initializes cyborg's components. Technically, adds default set of components to new borgs
/mob/living/silicon/robot/proc/initialize_components()
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)
@@ -126,10 +162,25 @@
components["comms"] = new/datum/robot_component/binary_communication(src)
components["armour"] = new/datum/robot_component/armour(src)
// Checks if component is functioning
/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()
// Returns component by it's string name
/mob/living/silicon/robot/proc/get_component(var/component_name)
var/datum/robot_component/C = components[component_name]
return C
// COMPONENT OBJECTS
// Component Objects
// These objects are visual representation of modules
/obj/item/broken_device
name = "broken component"
icon = 'icons/obj/robot_component.dmi'
@@ -144,7 +195,6 @@
var/burn = 0
var/icon_state_broken = "broken"
// TODO: actual icons ;)
/obj/item/robot_parts/robot_component/binary_communication_device
name = "binary communication device"
icon_state = "binradio"

View File

@@ -32,18 +32,20 @@
adjustFireLoss(0)
/mob/living/silicon/robot/proc/use_power()
// Debug only
// world << "DEBUG: life.dm line 35: cyborg use_power() called at tick [controller_iteration]"
used_power_this_tick = 0
for(var/V in components)
var/datum/robot_component/C = components[V]
C.update_power_state()
if ( cell && is_component_functioning("power cell") && src.cell.charge > 0 )
if(src.module_state_1)
src.cell.use(3)
cell_use_power(50) // 50W load for every enabled tool TODO: tool-specific loads
if(src.module_state_2)
src.cell.use(3)
cell_use_power(50)
if(src.module_state_3)
src.cell.use(3)
cell_use_power(50)
src.has_power = 1
else

View File

@@ -2,6 +2,8 @@ var/list/robot_verbs_default = list(
/mob/living/silicon/robot/proc/sensor_mode
)
#define CYBORG_POWER_USAGE_MULTIPLIER 2.5 // Multiplier for amount of power cyborgs use.
/mob/living/silicon/robot
name = "Cyborg"
real_name = "Cyborg"
@@ -10,6 +12,7 @@ var/list/robot_verbs_default = list(
maxHealth = 200
health = 200
var/used_power_this_tick = 0
var/sight_mode = 0
var/custom_name = ""
var/custom_sprite = 0 //Due to all the sprites involved, a var for our custom borgs may be best
@@ -383,7 +386,7 @@ var/list/robot_verbs_default = list(
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>"
dat += "<b>[C.name]</b><br><table><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.idle_usage || C.is_powered()) ? "Yes" : "No"]</td></tr><tr><td>Toggled:</td><td>[ C.toggled ? "Yes" : "No"]</td></table><br>"
return dat
@@ -395,6 +398,9 @@ var/list/robot_verbs_default = list(
if(!is_component_functioning("diagnosis unit"))
src << "\red Your self-diagnosis component isn't functioning."
var/datum/robot_component/CO = get_component("diagnosis unit")
if (!cell_use_power(CO.active_usage))
src << "\red Low Power."
var/dat = self_diagnosis()
src << browse(dat, "window=robotdiagnosis")
@@ -464,7 +470,9 @@ var/list/robot_verbs_default = list(
// this function displays the cyborgs current cell charge in the stat panel
/mob/living/silicon/robot/proc/show_cell_power()
if(cell)
stat(null, text("Charge Left: [cell.charge]/[cell.maxcharge]"))
stat(null, text("Charge Left: [round(cell.percent())]%"))
stat(null, text("Cell Rating: [round(cell.maxcharge)]")) // Round just in case we somehow get crazy values
stat(null, text("Power Cell Load: [round(used_power_this_tick)]W"))
else
stat(null, text("No Cell Inserted!"))
@@ -1327,3 +1335,20 @@ var/list/robot_verbs_default = list(
/mob/living/silicon/robot/proc/remove_robot_verbs()
src.verbs -= robot_verbs_default
// Uses power from cyborg's cell. Returns 1 on success or 0 on failure.
// Properly converts using CELLRATE now! Amount is in Joules.
/mob/living/silicon/robot/proc/cell_use_power(var/amount = 0)
// No cell inserted
if(!cell)
return 0
// Power cell is empty.
if(cell.charge == 0)
return 0
if(cell.use(amount * CELLRATE * CYBORG_POWER_USAGE_MULTIPLIER))
used_power_this_tick += amount * CYBORG_POWER_USAGE_MULTIPLIER
return 1
return 0

View File

@@ -22,5 +22,11 @@
return tally+config.robot_delay
// NEW: Use power while moving.
/mob/living/silicon/robot/Move()
..()
if (!is_component_functioning("actuator"))
return
var/datum/robot_component/actuator/A = get_component("actuator")
if (cell_use_power(A.active_usage))
..()

View File

@@ -72,7 +72,11 @@
if(message_mode && bot_type == IS_ROBOT && message_mode != "binary" && !R.is_component_functioning("radio"))
src << "\red Your radio isn't functional at this time."
return
if(bot_type == IS_ROBOT && message_mode != "binary")
var/datum/robot_component/radio/RA = R.get_component("radio")
if (!R.cell_use_power(RA.active_usage))
usr << "\red Not enough power to transmit message."
return
//parse language key and consume it
var/datum/language/speaking = parse_language(message)
@@ -100,6 +104,10 @@
if(!R.is_component_functioning("comms"))
src << "\red Your binary communications component isn't functional."
return
var/datum/robot_component/binary_communication/B = R.get_component("comms")
if(!R.cell_use_power(B.active_usage))
src << "\red Not enough power to transmit message."
return
if(IS_PAI)
src << "You do not appear to have that function"
return
@@ -197,6 +205,11 @@
var/renderedAI = "<i><span class='game say'>Robotic Talk, <a href='byond://?src=\ref[S];track2=\ref[S];track=\ref[src];trackname=[html_encode(src.name)]'><span class='name'>[name]</span></a> <span class='message'>[verb], \"[message]\"</span></span></i>"
S.show_message(renderedAI, 2)
else
var/mob/living/silicon/robot/borg = S
if(istype(borg) && borg.is_component_functioning("comms"))
var/datum/robot_component/RC = borg.get_component("comms")
if(!borg.use_power(RC.active_usage))
continue // No power.
S.show_message(rendered, 2)