mirror of
https://github.com/Aurorastation/Aurora.3.git
synced 2026-08-19 02:50:08 +01:00
https://www.youtube.com/watch?v=ZpUYjpKg9KY As per title. The goal is to add health to most objects in the game and thus allow them to be dynamically destructible, while also avoiding shitcode like each structure having its own snowflake health update proc. --------- Signed-off-by: Matt Atlas <mattiathebest2000@hotmail.it> Co-authored-by: Matt Atlas <liermattia@gmail.com> Co-authored-by: SleepyGemmy <99297919+SleepyGemmy@users.noreply.github.com>
584 lines
17 KiB
Plaintext
584 lines
17 KiB
Plaintext
/**
|
|
* BUILDABLE SMES (Superconducting Magnetic Energy Storage) UNIT
|
|
* AKA PSUs- both 'SMES unit' and 'PSU' will be used interchangeably in documentation and in-game.
|
|
*
|
|
* PSUs are linked by the RCON System, allowing for remote management of all linked
|
|
* It also supports RCON System which allows you to operate it remotely, if properly set.
|
|
*
|
|
* This file contains the main code and definition information for SMES units.
|
|
* For instantiation of buildable SMES units (the ones you'll see 99% of the time),
|
|
* please refer to 'code/modules/power/smes_construction.dm'
|
|
*/
|
|
|
|
#define SMESRATE 0.05
|
|
#define SMESMAXCHARGELEVEL 250000
|
|
#define SMESMAXOUTPUT 250000
|
|
|
|
//Cache defines
|
|
#define SMES_CLEVEL_1 1
|
|
#define SMES_CLEVEL_2 2
|
|
#define SMES_CLEVEL_3 3
|
|
#define SMES_CLEVEL_4 4
|
|
#define SMES_CLEVEL_5 5
|
|
#define SMES_OUTPUTTING 6
|
|
#define SMES_OUTPUT_ATTEMPT 7
|
|
#define SMES_NOT_OUTPUTTING 8
|
|
#define SMES_INPUTTING 9
|
|
#define SMES_INPUT_ATTEMPT 10
|
|
#define SMES_INPUT_MAX 11
|
|
|
|
/obj/machinery/power/smes
|
|
name = "power storage unit"
|
|
desc = "A high-capacity superconducting magnetic energy storage (SMES) unit."
|
|
icon_state = "smes"
|
|
density = 1
|
|
anchored = 1
|
|
use_power = POWER_USE_OFF
|
|
clicksound = SFX_SWITCH
|
|
|
|
maxhealth = OBJECT_HEALTH_MEDIUM
|
|
|
|
/// this it to prevent the damage text from playing repeatedly
|
|
var/busted = FALSE
|
|
/// maximum charge
|
|
var/capacity = 5e6
|
|
var/charge = 1e6 /// actual charge
|
|
var/max_coils = 0
|
|
|
|
/// 1 = attempting to charge, 0 = not attempting to charge
|
|
var/input_attempt = 0
|
|
/// 1 = actually inputting, 0 = not inputting
|
|
var/inputting = 0
|
|
/// amount of power the SMES attempts to charge by
|
|
var/input_level = 250000
|
|
/// cap on input_level
|
|
var/input_level_max = 2000000
|
|
/// amount that we received from powernet last tick
|
|
var/input_taken = 0
|
|
|
|
/// 1 = attempting to output, 0 = not attempting to output
|
|
var/output_attempt = 0
|
|
/// 1 = actually outputting, 0 = not outputting
|
|
var/outputting = 0
|
|
/// amount of power the SMES attempts to output
|
|
var/output_level = 250000
|
|
/// cap on output_level
|
|
var/output_level_max = 2000000
|
|
/// amount of power actually outputted. may be less than output_level if the powernet returns excess power
|
|
var/output_used = 0
|
|
|
|
///Holders for powerout event.
|
|
///var/last_output_attempt = 0
|
|
///var/last_input_attempt = 0
|
|
///var/last_charge = 0
|
|
|
|
///For icon overlay updates
|
|
var/last_disp
|
|
var/last_chrg
|
|
var/last_onln
|
|
|
|
var/input_cut = 0
|
|
var/input_pulsed = 0
|
|
var/output_cut = 0
|
|
var/output_pulsed = 0
|
|
/// Use by gridcheck event, if set to true we do not disable it
|
|
var/is_critical = FALSE
|
|
/// Set by gridcheck event, temporarily disables the SMES.
|
|
var/failure_timer = 0
|
|
var/target_load = 0
|
|
var/open_hatch = 0
|
|
var/name_tag = null
|
|
///Suggestions about how to avoid clickspam building several terminals accepted!
|
|
var/building_terminal = 0
|
|
var/obj/machinery/power/terminal/terminal = null
|
|
/// If this is set to 0 it will send out warning on New()
|
|
var/should_be_mapped = 0
|
|
var/datum/effect_system/sparks/big_spark
|
|
var/datum/effect_system/sparks/small_spark
|
|
|
|
var/time = 0
|
|
var/charge_mode = 0
|
|
var/last_time = 1
|
|
|
|
/obj/machinery/power/smes/assembly_hints(mob/user, distance, is_adjacent)
|
|
. += ..()
|
|
if(health < initial(health))
|
|
. += "It can be repaired with a <b>welding tool</b>."
|
|
|
|
/obj/machinery/power/smes/feedback_hints(mob/user, distance, is_adjacent)
|
|
. += ..()
|
|
if(is_badly_damaged())
|
|
. += SPAN_DANGER("\The [src] is damaged to the point of non-function!")
|
|
if(open_hatch)
|
|
. += "The maintenance hatch is open."
|
|
if (max_coils > 1 && Adjacent(user))
|
|
var/list/coils = list()
|
|
for(var/obj/item/smes_coil/C in component_parts)
|
|
coils += C
|
|
. += "The [max_coils] coil slots contain: [counting_english_list(coils)]."
|
|
|
|
/obj/machinery/power/smes/drain_power(var/drain_check, var/surge, var/amount = 0)
|
|
|
|
if(drain_check)
|
|
return 1
|
|
|
|
var/smes_amt = min((amount * SMESRATE), charge)
|
|
charge -= smes_amt
|
|
return smes_amt / SMESRATE
|
|
|
|
/obj/machinery/power/smes/proc/drain_power_simple(var/amount = 0)
|
|
var/power_drawn = between(0, amount, charge)
|
|
charge -= power_drawn
|
|
return power_drawn
|
|
|
|
/obj/machinery/power/smes/Destroy()
|
|
QDEL_NULL(big_spark)
|
|
QDEL_NULL(small_spark)
|
|
SSmachinery.smes_units -= src
|
|
QDEL_NULL(terminal)
|
|
return ..() // TODO: Properly clean up terminal.
|
|
|
|
/obj/machinery/power/smes/Initialize()
|
|
. = ..()
|
|
SSmachinery.smes_units += src
|
|
big_spark = bind_spark(src, 5, GLOB.alldirs)
|
|
small_spark = bind_spark(src, 3)
|
|
if(!powernet)
|
|
connect_to_network()
|
|
|
|
dir_loop:
|
|
for(var/d in GLOB.cardinals)
|
|
var/turf/T = get_step(src, d)
|
|
for(var/obj/machinery/power/terminal/term in T)
|
|
if(term && term.dir == turn(d, 180))
|
|
terminal = term
|
|
break dir_loop
|
|
if(!terminal)
|
|
stat |= BROKEN
|
|
return
|
|
terminal.master = src
|
|
if(!terminal.powernet)
|
|
terminal.connect_to_network()
|
|
update_icon()
|
|
|
|
if(!should_be_mapped)
|
|
warning("Non-buildable or Non-magical SMES at [src.x]X [src.y]Y [src.z]Z")
|
|
|
|
/obj/machinery/power/smes/proc/can_function()
|
|
if(is_badly_damaged())
|
|
return FALSE
|
|
if(stat & BROKEN)
|
|
return FALSE
|
|
return TRUE
|
|
|
|
/obj/machinery/power/smes/proc/is_badly_damaged()
|
|
if(health < initial(health) / 5)
|
|
return TRUE
|
|
return FALSE
|
|
|
|
/obj/machinery/power/smes/disconnect_terminal()
|
|
if(terminal)
|
|
terminal.master = null
|
|
terminal = null
|
|
return 1
|
|
return 0
|
|
|
|
/obj/machinery/power/smes/update_icon()
|
|
ClearOverlays()
|
|
var/mutable_appearance/oc
|
|
var/mutable_appearance/oc_emis
|
|
var/mutable_appearance/og
|
|
var/mutable_appearance/og_emis
|
|
var/mutable_appearance/op
|
|
var/mutable_appearance/op_emis
|
|
if(!can_function())
|
|
return
|
|
|
|
if(inputting == (1 || 2))
|
|
oc = overlay_image(icon, "[icon_state]-oc[inputting]")
|
|
oc_emis = emissive_appearance(icon, "[icon_state]-oc[inputting]")
|
|
else if (input_attempt)
|
|
oc = overlay_image(icon, "[icon_state]-oc0")
|
|
oc_emis = emissive_appearance(icon, "[icon_state]-oc0")
|
|
|
|
|
|
var/clevel = chargedisplay()
|
|
if(clevel)
|
|
og = overlay_image(icon, "[icon_state]-og[clevel]")
|
|
og_emis = emissive_appearance(icon, "[icon_state]-og[clevel]")
|
|
|
|
if(outputting == 2 || 1)
|
|
op = overlay_image(icon, "[icon_state]-op[outputting]")
|
|
op_emis = emissive_appearance(icon, "[icon_state]-op[outputting]")
|
|
else
|
|
op = overlay_image(icon, "[icon_state]-op0")
|
|
op_emis = emissive_appearance(icon, "[icon_state]-op0")
|
|
|
|
AddOverlays(list(
|
|
oc,
|
|
oc_emis,
|
|
og,
|
|
og_emis,
|
|
op,
|
|
op_emis
|
|
))
|
|
|
|
/obj/machinery/power/smes/proc/chargedisplay()
|
|
return round(5.5*charge/(capacity ? capacity : 5e6))
|
|
|
|
/obj/machinery/power/smes/proc/input_power(var/percentage)
|
|
var/inputted_power = target_load * (percentage/100)
|
|
inputted_power = between(0, inputted_power, target_load)
|
|
if(terminal && terminal.powernet)
|
|
inputted_power = TERMINAL_POWER_DRAW(inputted_power)
|
|
TERMINAL_DRAW_POWER(inputted_power)
|
|
charge += inputted_power * SMESRATE
|
|
input_taken = inputted_power
|
|
if(percentage == 100)
|
|
inputting = 2
|
|
else if(percentage)
|
|
inputting = 1
|
|
// else inputting = 0, as set in process()
|
|
|
|
/obj/machinery/power/smes/proc/update_time()
|
|
|
|
var/delta_power = input_taken - output_used
|
|
delta_power *= SMESRATE
|
|
|
|
var/goal = (delta_power < 0) ? (charge) : (capacity - charge)
|
|
time = world.time + (delta_power ? ((goal / abs(delta_power)) * (world.time - last_time)) : 0)
|
|
|
|
if(input_cut) // Cannot charge if input wire cut
|
|
charge_mode = 0
|
|
else if(delta_power < 0) // If we are negative - we are discharging
|
|
charge_mode = 0
|
|
else if(delta_power != 0)
|
|
charge_mode = 1
|
|
else
|
|
charge_mode = 2
|
|
last_time = world.time
|
|
|
|
/obj/machinery/power/smes/process()
|
|
if(!can_function())
|
|
return
|
|
if(failure_timer) // Disabled by gridcheck.
|
|
failure_timer--
|
|
return
|
|
|
|
// only update icon if state changed
|
|
if(last_disp != chargedisplay() || last_chrg != inputting || last_onln != outputting)
|
|
update_icon()
|
|
|
|
//store machine state to see if we need to update the icon overlays
|
|
last_disp = chargedisplay()
|
|
last_chrg = inputting
|
|
last_onln = outputting
|
|
|
|
update_time()
|
|
|
|
//inputting
|
|
if(input_attempt && (!input_pulsed && !input_cut))
|
|
target_load = min((capacity-charge)/SMESRATE, input_level) // Amount we will request from the powernet.
|
|
if(terminal && terminal.powernet)
|
|
terminal.powernet.smes_demand += target_load
|
|
terminal.powernet.inputting.Add(src)
|
|
else
|
|
target_load = 0 // We won't input any power without powernet connection.
|
|
inputting = 0
|
|
|
|
//outputting
|
|
if(output_attempt && (!output_pulsed && !output_cut) && powernet && charge)
|
|
output_used = min( charge/SMESRATE, output_level) //limit output to that stored
|
|
charge -= output_used*SMESRATE // reduce the storage (may be recovered in /restore() if excessive)
|
|
SMES_ADD_TO_POWERNET(src, output_used) // add output to powernet (smes side)
|
|
outputting = 2
|
|
else if(!powernet || !charge)
|
|
outputting = 1
|
|
else
|
|
outputting = 0
|
|
|
|
// called after all power processes are finished
|
|
// restores charge level to smes if there was excess this ptick
|
|
/obj/machinery/power/smes/proc/restore(var/percent_load)
|
|
if(!can_function())
|
|
return
|
|
|
|
if(!outputting)
|
|
output_used = 0
|
|
return
|
|
|
|
var/total_restore = output_used * (percent_load / 100) // First calculate amount of power used from our output
|
|
total_restore = between(0, total_restore, output_used) // Now clamp the value between 0 and actual output, just for clarity.
|
|
total_restore = output_used - total_restore // And, at last, subtract used power from outputted power, to get amount of power we will give back to the SMES.
|
|
|
|
// now recharge this amount
|
|
|
|
var/clev = chargedisplay()
|
|
|
|
charge += total_restore * SMESRATE // restore unused power
|
|
powernet.netexcess -= total_restore // remove the excess from the powernet, so later SMESes don't try to use it
|
|
|
|
output_used -= total_restore
|
|
|
|
if(clev != chargedisplay() ) //if needed updates the icons overlay
|
|
update_icon()
|
|
return
|
|
|
|
//Will return 1 on failure
|
|
/obj/machinery/power/smes/proc/make_terminal(const/mob/user)
|
|
if (user.loc == loc)
|
|
to_chat(user, SPAN_WARNING("You must not be on the same tile as the [src]."))
|
|
return 1
|
|
|
|
//Direction the terminal will face to
|
|
var/tempDir = get_dir(user, src)
|
|
switch(tempDir)
|
|
if (NORTHEAST, SOUTHEAST)
|
|
tempDir = EAST
|
|
if (NORTHWEST, SOUTHWEST)
|
|
tempDir = WEST
|
|
var/turf/tempLoc = get_step(src, REVERSE_DIR(tempDir))
|
|
if (istype(tempLoc, /turf/space))
|
|
to_chat(user, SPAN_WARNING("You can't build a terminal on space."))
|
|
return 1
|
|
else if (istype(tempLoc))
|
|
if(!tempLoc.is_plating())
|
|
to_chat(user, SPAN_WARNING("You must remove the floor plating first."))
|
|
return 1
|
|
to_chat(user, SPAN_NOTICE("You start adding cable to the [src]."))
|
|
if(do_after(user, 5 SECONDS, src, DO_REPAIR_CONSTRUCT))
|
|
terminal = new /obj/machinery/power/terminal(tempLoc)
|
|
terminal.set_dir(tempDir)
|
|
terminal.master = src
|
|
return 0
|
|
return 1
|
|
|
|
/obj/machinery/power/smes/attack_ai(mob/user)
|
|
if(!ai_can_interact(user))
|
|
return
|
|
add_hiddenprint(user)
|
|
ui_interact(user)
|
|
|
|
/obj/machinery/power/smes/attack_hand(mob/user)
|
|
add_fingerprint(user)
|
|
ui_interact(user)
|
|
|
|
/obj/machinery/power/smes/attackby(obj/item/attacking_item, mob/user)
|
|
if(attacking_item.tool_behaviour == TOOL_SCREWDRIVER)
|
|
if(!open_hatch)
|
|
if(is_badly_damaged())
|
|
to_chat(user, SPAN_WARNING("\The [src]'s maintenance panel is broken open!"))
|
|
return
|
|
open_hatch = 1
|
|
user.visible_message(\
|
|
SPAN_NOTICE("\The [user] opens the maintenance hatch of \the [src]."),\
|
|
SPAN_NOTICE("You open the maintenance hatch of \the [src]."),\
|
|
range = 4)
|
|
return 0
|
|
else
|
|
open_hatch = 0
|
|
user.visible_message(\
|
|
SPAN_NOTICE("\The [user] closes the maintenance hatch of \the [src]."),\
|
|
SPAN_NOTICE("You close the maintenance hatch of \the [src]."),\
|
|
range = 4)
|
|
return 0
|
|
|
|
if (!open_hatch)
|
|
to_chat(user, SPAN_WARNING("You need to open access hatch on [src] first!"))
|
|
return 0
|
|
|
|
if(attacking_item.tool_behaviour == TOOL_CABLECOIL && !terminal && !building_terminal)
|
|
building_terminal = 1
|
|
var/obj/item/stack/cable_coil/CC = attacking_item
|
|
if (CC.get_amount() <= 10)
|
|
to_chat(user, SPAN_WARNING("You need more cables."))
|
|
building_terminal = 0
|
|
return 0
|
|
if (make_terminal(user))
|
|
building_terminal = 0
|
|
return 0
|
|
building_terminal = 0
|
|
CC.use(10)
|
|
user.visible_message(\
|
|
SPAN_NOTICE("[user.name] has added cables to the [src]."),\
|
|
SPAN_NOTICE("You added cables to the [src]."))
|
|
terminal.connect_to_network()
|
|
stat = 0
|
|
return 0
|
|
|
|
else if(attacking_item.tool_behaviour == TOOL_WIRECUTTER && terminal && !building_terminal)
|
|
building_terminal = 1
|
|
var/turf/tempTDir = terminal.loc
|
|
if (istype(tempTDir))
|
|
if(!tempTDir.is_plating())
|
|
to_chat(user, SPAN_WARNING("You must remove the floor plating first."))
|
|
else
|
|
to_chat(user, SPAN_NOTICE("You begin to cut the cables..."))
|
|
if(attacking_item.use_tool(src, user, 50, volume = 50))
|
|
if (prob(50) && electrocute_mob(usr, terminal.powernet, terminal))
|
|
big_spark.queue()
|
|
building_terminal = 0
|
|
if(usr.stunned)
|
|
return 0
|
|
new /obj/item/stack/cable_coil(loc,10)
|
|
user.visible_message(\
|
|
SPAN_NOTICE("[user.name] cut the cables and dismantled the power terminal."),\
|
|
SPAN_NOTICE("You cut the cables and dismantle the power terminal."))
|
|
qdel(terminal)
|
|
building_terminal = 0
|
|
return 0
|
|
return 1
|
|
|
|
/obj/machinery/power/smes/ui_data(mob/user)
|
|
var/list/data = list()
|
|
data["name_tag"] = name_tag
|
|
data["charge_taken"] = round(input_taken)
|
|
data["charging"] = inputting
|
|
data["charge_attempt"] = input_attempt
|
|
data["charge_level"] = input_level
|
|
data["charge_max"] = input_level_max
|
|
data["output_load"] = round(output_used)
|
|
data["outputting"] = outputting
|
|
data["output_attempt"] = output_attempt
|
|
data["output_level"] = output_level
|
|
data["output_max"] = output_level_max
|
|
data["time"] = time
|
|
data["wtime"] = world.time
|
|
data["charge_mode"] = charge_mode
|
|
data["stored_capacity"] = 0
|
|
if(capacity)
|
|
data["stored_capacity"] = round(100.0*charge/capacity, 0.1)
|
|
data["fail_time"] = failure_timer * 2
|
|
return data
|
|
|
|
/obj/machinery/power/smes/ui_interact(mob/user, var/datum/tgui/ui)
|
|
if(!can_function())
|
|
if(!terminal)
|
|
to_chat(user, SPAN_WARNING("\The [src] is lacking a terminal!"))
|
|
return
|
|
if(is_badly_damaged())
|
|
to_chat(user, SPAN_WARNING("\The [src] is too damaged to function!"))
|
|
return
|
|
|
|
ui = SStgui.try_update_ui(user, src, ui)
|
|
if(!ui)
|
|
ui = new(user, src, "SMES", name, 540, 420)
|
|
ui.open()
|
|
|
|
/obj/machinery/power/smes/proc/Percentage()
|
|
return round(100.0*charge/capacity, 0.1)
|
|
|
|
/obj/machinery/power/smes/ui_act(action, list/params, datum/tgui/ui, datum/ui_state/state)
|
|
. = ..()
|
|
if(.)
|
|
return
|
|
|
|
switch(action)
|
|
if("cmode")
|
|
inputting(!input_attempt)
|
|
update_icon()
|
|
. = TRUE
|
|
if("online")
|
|
outputting(!output_attempt)
|
|
update_icon()
|
|
. = TRUE
|
|
if("reboot")
|
|
failure_timer = 0
|
|
update_icon()
|
|
. = TRUE
|
|
if("input")
|
|
input_level = clamp(params["input"], 0, input_level_max) // clamp to range
|
|
. = TRUE
|
|
if("output")
|
|
output_level = clamp(params["output"], 0, output_level_max) // clamp to range
|
|
. = TRUE
|
|
|
|
/obj/machinery/power/smes/proc/energy_fail(var/duration)
|
|
failure_timer = max(failure_timer, duration)
|
|
|
|
/obj/machinery/power/smes/proc/ion_act()
|
|
if(is_station_level(src.z))
|
|
if(prob(1)) //explosion
|
|
for(var/mob/M in viewers(src))
|
|
M.show_message(SPAN_WARNING("The [src.name] is making strange noises!"), 3, SPAN_WARNING("You hear sizzling electronics."), 2)
|
|
sleep(10*pick(4,5,6,7,10,14))
|
|
var/datum/effect/effect/system/smoke_spread/smoke = new /datum/effect/effect/system/smoke_spread()
|
|
smoke.set_up(3, 0, src.loc)
|
|
smoke.attach(src)
|
|
smoke.start()
|
|
explosion(src.loc, -1, 0, 1, 3, 1, 0)
|
|
qdel(src)
|
|
return
|
|
else if(prob(15)) //Power drain
|
|
small_spark.queue()
|
|
if(prob(50))
|
|
emp_act(EMP_HEAVY)
|
|
else
|
|
emp_act(EMP_LIGHT)
|
|
else if(prob(5)) //smoke only
|
|
var/datum/effect/effect/system/smoke_spread/smoke = new /datum/effect/effect/system/smoke_spread()
|
|
smoke.set_up(3, 0, src.loc)
|
|
smoke.attach(src)
|
|
smoke.start()
|
|
else
|
|
energy_fail(rand(0, 30))
|
|
|
|
/obj/machinery/power/smes/proc/inputting(var/do_input)
|
|
input_attempt = do_input
|
|
if(!input_attempt)
|
|
inputting = 0
|
|
|
|
/obj/machinery/power/smes/proc/outputting(var/do_output)
|
|
output_attempt = do_output
|
|
if(!output_attempt)
|
|
outputting = 0
|
|
|
|
/obj/machinery/power/smes/emp_act(severity)
|
|
. = ..()
|
|
|
|
if(prob(50))
|
|
inputting(rand(0,1))
|
|
outputting(rand(0,1))
|
|
if(prob(50))
|
|
output_level = rand(0, output_level_max)
|
|
input_level = rand(0, input_level_max)
|
|
if(prob(50))
|
|
charge -= 1e6/severity
|
|
if (charge < 0)
|
|
charge = 0
|
|
if(prob(50))
|
|
energy_fail(rand(0 + (severity * 30),30 + (severity * 30)))
|
|
update_icon()
|
|
|
|
|
|
/obj/machinery/power/smes/magical
|
|
name = "quantum power storage unit"
|
|
desc = "A high-capacity superconducting magnetic energy storage (SMES) unit. Gains energy from quantum entanglement link."
|
|
capacity = 5000000
|
|
output_level = 250000
|
|
should_be_mapped = 1
|
|
|
|
/obj/machinery/power/smes/magical/process()
|
|
charge = 5000000
|
|
..()
|
|
|
|
/obj/machinery/power/smes/buildable/superconducting
|
|
name = "superconducting cryogenic capacitor"
|
|
desc = "An experimental, extremely high-capacity type of SMES. It uses integrated cryogenic cooling and superconducting cables to break conventional limits on power transfer."
|
|
icon_state = "cannon_smes"
|
|
charge = 0
|
|
max_coils = 12
|
|
cur_coils = 12
|
|
|
|
#undef SMES_CLEVEL_1
|
|
#undef SMES_CLEVEL_2
|
|
#undef SMES_CLEVEL_3
|
|
#undef SMES_CLEVEL_4
|
|
#undef SMES_CLEVEL_5
|
|
#undef SMES_OUTPUTTING
|
|
#undef SMES_OUTPUT_ATTEMPT
|
|
#undef SMES_NOT_OUTPUTTING
|
|
#undef SMES_INPUTTING
|
|
#undef SMES_INPUT_ATTEMPT
|
|
#undef SMES_INPUT_MAX
|