Recharger QoL Tweaks (#3826)

changes:

Rechargers now briefly show a progress bar showing the current charge level of the device currently charging.
Examining a recharger will now specify what is in the charger.
Atoms can now mark themselves as requiring an icon update on initialize instead of overriding Initialize() just to call update_icon().
Charger code is now slightly more modular, using proc/get_cell() to get a ref to the power cell instead of hard-coded if-else chains for each supported type.
This commit is contained in:
Lohikar
2017-11-18 18:46:14 +02:00
committed by Erki
parent def00ac176
commit 58519daeba
16 changed files with 133 additions and 85 deletions
-1
View File
@@ -57,7 +57,6 @@
#include "code\_helpers\global_lists.dm"
#include "code\_helpers\icon_smoothing.dm"
#include "code\_helpers\icons.dm"
#include "code\_helpers\items.dm"
#include "code\_helpers\lists.dm"
#include "code\_helpers\logging.dm"
#include "code\_helpers\maths.dm"
+2
View File
@@ -452,3 +452,5 @@ Define for getting a bitfield of adjacent turfs that meet a condition.
} \
} \
}
#define DEVICE_NO_CELL "no_cell"
-16
View File
@@ -1,16 +0,0 @@
//Prevents robots dropping their modules.
/proc/dropsafety(var/atom/movable/A)
if (istype(A.loc, /mob/living/silicon))
return 0
else if (istype(A.loc, /obj/item/rig_module))
return 0
return 1
/obj/proc/animate_shake()
var/init_px = pixel_x
var/shake_dir = pick(-1, 1)
animate(src, transform = turn(matrix(), 8*shake_dir), pixel_x = init_px + 2*shake_dir, time = 1)
animate(transform = null, pixel_x = init_px, time = 6, easing = ELASTIC_EASING)
+9
View File
@@ -1163,3 +1163,12 @@ var/list/wall_items = typecacheof(list(
#undef NOT_FLAG
#undef HAS_FLAG
//Prevents robots dropping their modules.
/proc/dropsafety(var/atom/movable/A)
if (istype(A.loc, /mob/living/silicon))
return 0
else if (istype(A.loc, /obj/item/rig_module))
return 0
return 1
+5 -1
View File
@@ -1,9 +1,10 @@
/atom
var/initialized = FALSE
var/update_icon_on_init // Default to 'no'.
/atom/New(loc, ...)
// For the DMM Suite.
if(use_preloader && (src.type == _preloader.target_path))//in case the instanciated atom is creating other atoms in New()
if(use_preloader && (type == _preloader.target_path))//in case the instanciated atom is creating other atoms in New()
_preloader.load(src)
//. = ..() //uncomment if you are dumb enough to add a /datum/New() proc
@@ -36,6 +37,9 @@
T.regenerate_ao()
#endif
if (update_icon_on_init)
queue_icon_update()
return INITIALIZE_HINT_NORMAL
//called if Initialize returns INITIALIZE_HINT_LATELOAD
+58 -39
View File
@@ -8,16 +8,39 @@
anchored = 1
use_power = 1
idle_power_usage = 4
active_power_usage = 30000 //15 kW
active_power_usage = 30 KILOWATTS
var/charging_efficiency = 0.85
//Entropy. The charge put into the cell is multiplied by this
var/obj/item/charging = null
var/obj/item/charging
var/list/allowed_devices = list(/obj/item/weapon/gun/energy, /obj/item/weapon/melee/baton, /obj/item/weapon/cell, /obj/item/modular_computer/, /obj/item/weapon/computer_hardware/battery_module)
var/list/allowed_devices = list(
/obj/item/weapon/gun/energy,
/obj/item/weapon/melee/baton,
/obj/item/weapon/cell,
/obj/item/modular_computer,
/obj/item/weapon/computer_hardware/battery_module
)
var/icon_state_charged = "recharger2"
var/icon_state_charging = "recharger1"
var/icon_state_idle = "recharger0" //also when unpowered
var/portable = 1
var/list/chargebars
/obj/machinery/recharger/examine(mob/user)
. = ..(user, 3)
user << "There is [charging ? "\a [charging]" : "nothing"] in [src]."
if (charging && .)
var/obj/item/weapon/cell/C = charging.get_cell()
if (istype(C) && user.client && (!user.progressbars || !user.progressbars[src]))
var/datum/progressbar/progbar = new(user, C.maxcharge, src)
progbar.update(C.charge)
LAZYADD(chargebars, progbar)
chargebars[progbar] = addtimer(CALLBACK(src, .proc/remove_bar, progbar, null), 3 SECONDS, TIMER_UNIQUE | TIMER_STOPPABLE)
/obj/machinery/recharger/proc/remove_bar(datum/progressbar/bar, timerid)
if (!timerid || deltimer(timerid))
LAZYREMOVE(chargebars, bar)
qdel(bar)
/obj/machinery/recharger/attackby(obj/item/weapon/G as obj, mob/user as mob)
if(portable && iswrench(G))
@@ -41,32 +64,21 @@
if(!dropsafety(G))
return
var/allowed = 0
for (var/allowed_type in allowed_devices)
if (istype(G, allowed_type)) allowed = 1
if(allowed)
if(is_type_in_list(G, allowed_devices))
if (G.get_cell() == DEVICE_NO_CELL)
if (G.charge_failure_message)
user << "<span class='warning'>\The [G][G.charge_failure_message]</span>"
return
if(charging)
user << "<span class='warning'>\A [charging] is already charging here.</span>"
return
// Checks to make sure he's not in space doing it, and that the area got proper power.
if(!powered())
user << "<span class='warning'>The [name] blinks red as you try to insert the item!</span>"
user << "<span class='warning'>\The [name] blinks red as you try to insert the item!</span>"
return
if (istype(G, /obj/item/weapon/gun/energy/gun/nuclear) || istype(G, /obj/item/weapon/gun/energy/crossbow))
user << "<span class='notice'>Your gun's recharge port was removed to make room for a miniaturized reactor.</span>"
return
if (istype(G, /obj/item/weapon/gun/energy/staff))
return
if (istype(G, /obj/item/weapon/gun/energy/wand))
return
if(istype(G, /obj/item/modular_computer))
var/obj/item/modular_computer/C = G
if(!C.battery_module)
user << "This device does not have a battery installed."
return
user.drop_item()
G.loc = src
G.forceMove(src)
charging = G
update_icon()
@@ -80,6 +92,9 @@
charging.update_icon()
user.put_in_hands(charging)
charging = null
if (chargebars)
for (var/thing in chargebars)
remove_bar(thing, chargebars[thing])
update_icon()
/obj/machinery/recharger/machinery_process()
@@ -92,20 +107,8 @@
update_use_power(1)
icon_state = icon_state_idle
else
var/cell = charging
if(istype(charging, /obj/item/weapon/melee/baton))
var/obj/item/weapon/melee/baton/B = charging
cell = B.bcell
else if(istype(charging, /obj/item/modular_computer))
var/obj/item/modular_computer/C = charging
cell = C.battery_module.battery
else if(istype(charging, /obj/item/weapon/gun/energy))
var/obj/item/weapon/gun/energy/E = charging
cell = E.power_supply
else if(istype(charging, /obj/item/weapon/computer_hardware/battery_module))
var/obj/item/weapon/computer_hardware/battery_module/BM = charging
cell = BM.battery
if(istype(cell, /obj/item/weapon/cell))
var/obj/item/weapon/cell/cell = charging.get_cell()
if(istype(cell))
var/obj/item/weapon/cell/C = cell
if(!C.fully_charged())
icon_state = icon_state_charging
@@ -114,7 +117,20 @@
else
icon_state = icon_state_charged
update_use_power(1)
return
if (chargebars)
for (var/thing in chargebars)
var/datum/progressbar/bar = thing
if (QDELETED(bar))
LAZYREMOVE(chargebars, bar)
else
bar.update(C.charge)
else if (cell == DEVICE_NO_CELL)
log_debug("recharger: Item [DEBUG_REF(charging)] was in charger, but claims to have no internal cell slot; booting item.")
charging.forceMove(loc)
charging.visible_message("\The [charging] falls out of [src].")
charging = null
/obj/machinery/recharger/emp_act(severity)
if(stat & (NOPOWER|BROKEN) || !anchored)
@@ -138,13 +154,16 @@
else
icon_state = icon_state_idle
obj/machinery/recharger/wallcharger
/obj/machinery/recharger/wallcharger
name = "wall recharger"
desc = "A heavy duty wall recharger specialized for energy weaponry."
icon = 'icons/obj/stationobjs.dmi'
icon_state = "wrecharger0"
active_power_usage = 50 KILOWATTS //50 kW , It's more specialized than the standalone recharger (guns and batons only) so make it more powerful
allowed_devices = list(/obj/item/weapon/gun/energy, /obj/item/weapon/melee/baton)
allowed_devices = list(
/obj/item/weapon/gun/energy,
/obj/item/weapon/melee/baton
)
icon_state_charged = "wrecharger2"
icon_state_charging = "wrecharger1"
icon_state_idle = "wrecharger0"
+6
View File
@@ -75,6 +75,8 @@
var/icon_override //Used to override hardcoded clothing dmis in human clothing pr
var/charge_failure_message = " cannot be recharged."
/obj/item/Destroy()
if(ismob(loc))
var/mob/m = loc
@@ -84,9 +86,13 @@
src.loc = null
return ..()
/obj/item/device
icon = 'icons/obj/device.dmi'
/obj/item/proc/get_cell()
return DEVICE_NO_CELL
//Checks if the item is being held by a mob, and if so, updates the held icons
/obj/item/proc/update_held_icon()
if(ismob(src.loc))
+14 -17
View File
@@ -15,20 +15,20 @@
var/stunforce = 0
var/agonyforce = 120
var/status = 0 //whether the thing is on or not
var/obj/item/weapon/cell/bcell = null
var/obj/item/weapon/cell/bcell
var/hitcost = 1000 //oh god why do power cells carry so much charge? We probably need to make a distinction between "industrial" sized power cells for APCs and power cells for everything else.
var/baton_color = "#FF6A00"
/obj/item/weapon/melee/baton/New()
..()
/obj/item/weapon/melee/baton/Initialize()
. = ..()
update_icon()
return
/obj/item/weapon/melee/baton/loaded/New() //this one starts with a cell pre-installed.
..()
/obj/item/weapon/melee/baton/loaded/Initialize() //this one starts with a cell pre-installed.
bcell = new/obj/item/weapon/cell/high(src)
update_icon()
return
. = ..()
/obj/item/weapon/melee/baton/get_cell()
return bcell
/obj/item/weapon/melee/baton/proc/deductcharge(var/chrgdeductamt)
if(bcell)
@@ -59,14 +59,14 @@
if(bcell)
user <<"<span class='notice'>The baton is [round(bcell.percent())]% charged.</span>"
if(!bcell)
else
user <<"<span class='warning'>The baton does not have a power source installed.</span>"
/obj/item/weapon/melee/baton/attackby(obj/item/weapon/W, mob/user)
if(istype(W, /obj/item/weapon/cell))
if(!bcell)
user.drop_item()
W.loc = src
W.forceMove(src)
bcell = W
user << "<span class='notice'>You install a cell in [src].</span>"
update_icon()
@@ -76,7 +76,7 @@
else if(isscrewdriver(W))
if(bcell)
bcell.update_icon()
bcell.loc = get_turf(src.loc)
bcell.forceMove(get_turf(src))
bcell = null
user << "<span class='notice'>You remove the cell from the [src].</span>"
status = 0
@@ -225,11 +225,9 @@
origin_tech = list(TECH_COMBAT = 4, TECH_ILLEGAL = 2)
contained_sprite = 1
/obj/item/weapon/melee/baton/stunrod/New()
..()
/obj/item/weapon/melee/baton/stunrod/Initialize()
bcell = new/obj/item/weapon/cell/high(src)
update_icon()
return
. = ..()
/obj/item/weapon/melee/baton/stunrod/update_icon() //this is needed due to how contained sprites work
if(status)
@@ -258,9 +256,8 @@
contained_sprite = 1
/obj/item/weapon/melee/baton/slime/Initialize()
. = ..()
bcell = new/obj/item/weapon/cell/high(src)
return
. = ..()
/obj/item/weapon/melee/baton/slime/attack(mob/M, mob/user, var/hit_zone)
if(isrobot(M) || ishuman(M))
+6
View File
@@ -216,3 +216,9 @@
//This is useful for setting special behaviour for built items that shouldn't apply to those spawned at roundstart
/obj/proc/Created()
return
/obj/proc/animate_shake()
var/init_px = pixel_x
var/shake_dir = pick(-1, 1)
animate(src, transform = turn(matrix(), 8*shake_dir), pixel_x = init_px + 2*shake_dir, time = 1)
animate(transform = null, pixel_x = init_px, time = 6, easing = ELASTIC_EASING)
@@ -276,3 +276,6 @@
return active_program.check_eye(user)
else
return ..()
/obj/item/modular_computer/get_cell()
return battery_module ? battery_module.get_cell() : DEVICE_NO_CELL
@@ -59,3 +59,5 @@
var/obj/item/weapon/computer_hardware/tesla_link/tesla_link // Tesla Link, Allows remote charging from nearest APC.
var/listener/listener //Listener needed for things
charge_failure_message = " does not have a battery installed."
@@ -8,7 +8,7 @@
malfunction_probability = 1
origin_tech = list(TECH_POWER = 1, TECH_ENGINEERING = 1)
var/battery_rating = 750
var/obj/item/weapon/cell/battery = null
var/obj/item/weapon/cell/battery
/obj/item/weapon/computer_hardware/battery_module/advanced
name = "advanced battery"
@@ -51,24 +51,27 @@
// This is not intended to be obtainable in-game. Intended for adminbus and debugging purposes.
/obj/item/weapon/computer_hardware/battery_module/lambda
name = "lambda coil"
desc = "A very complex device that creates it's own bluespace dimension. This dimension may be used to store massive amounts of energy."
desc = "A very complex device that creates its own bluespace dimension. This dimension may be used to store massive amounts of energy."
icon_state = "battery_lambda"
hardware_size = 1
battery_rating = 1000000
/obj/item/weapon/computer_hardware/battery_module/lambda/New()
..()
/obj/item/weapon/computer_hardware/battery_module/lambda/Initialize()
. = ..()
battery = new/obj/item/weapon/cell/infinite(src)
/obj/item/weapon/computer_hardware/battery_module/diagnostics(var/mob/user)
..()
user << "Internal battery charge: [battery.charge]/[battery.maxcharge] CU"
user << "Internal battery charge: [battery.charge]/[battery.maxcharge] mAh"
/obj/item/weapon/computer_hardware/battery_module/New()
battery = new/obj/item/weapon/cell(src)
battery.maxcharge = battery_rating
/obj/item/weapon/computer_hardware/battery_module/Initialize()
. = ..()
battery = new/obj/item/weapon/cell/device/variable(src, battery_rating)
battery.charge = 0
..()
/obj/item/weapon/computer_hardware/battery_module/proc/charge_to_full()
if(battery)
battery.charge = battery.maxcharge
/obj/item/weapon/computer_hardware/battery_module/get_cell()
return battery
+5 -2
View File
@@ -4,6 +4,7 @@
icon_state = "energy"
fire_sound = 'sound/weapons/Taser.ogg'
fire_sound_text = "laser blast"
update_icon_on_init = TRUE
var/obj/item/weapon/cell/power_supply //What type of power cell this uses
var/charge_cost = 200 //How much energy is needed to fire.
@@ -34,7 +35,10 @@
/obj/item/weapon/gun/energy/emp_act(severity)
..()
update_icon()
queue_icon_update()
/obj/item/weapon/gun/energy/get_cell()
return power_supply
/obj/item/weapon/gun/energy/Initialize()
. = ..()
@@ -42,7 +46,6 @@
power_supply = new cell_type(src)
else
power_supply = new /obj/item/weapon/cell/device/variable(src, max_shots*charge_cost)
update_icon()
/obj/item/weapon/gun/energy/Destroy()
QDEL_NULL(power_supply)
@@ -187,6 +187,10 @@ obj/item/weapon/gun/energy/staff/focus/attack_self(mob/living/user as mob)
projectile_type = /obj/item/projectile/magic
origin_tech = list(TECH_COMBAT = 6, TECH_MAGNET = 5, TECH_BLUESPACE = 6)
charge_meter = 0
charge_failure_message = null
/obj/item/weapon/gun/energy/wand/get_cell()
return DEVICE_NO_CELL
/obj/item/weapon/gun/energy/wand/handle_click_empty(mob/user = null)
if (user)
@@ -40,6 +40,7 @@
modifystate = null
var/reliability = 95
turret_sprite_set = "nuclear"
charge_failure_message = "'s charging socket was removed to make room for a minaturized reactor."
firemodes = list(
list(mode_name="stun", projectile_type=/obj/item/projectile/beam/stun, fire_sound='sound/weapons/Taser.ogg'),
@@ -48,6 +49,8 @@
var/lightfail = 0
/obj/item/weapon/gun/energy/gun/nuclear/get_cell()
return DEVICE_NO_CELL
/obj/item/weapon/gun/energy/gun/nuclear/proc/failcheck()
lightfail = 0
@@ -50,6 +50,10 @@
charge_meter = 0
can_turret = 1
turret_sprite_set = "crossbow"
charge_failure_message = "'s charging socket was removed to make room for a minaturized reactor."
/obj/item/weapon/gun/energy/crossbow/get_cell()
return DEVICE_NO_CELL
/obj/item/weapon/gun/energy/crossbow/ninja
name = "energy dart thrower"