Files
Bubberstation/code/modules/research/anomaly/explosive_compressor.dm
EOBGames b08632353c [MDB IGNORE] Eliminates Toxins (#60619)
Repaths everything referring to "toxins" while actually meaning either the room in science or plasma gas. While this PR might be disrespectful to our forefathers, given this is (I believe) a holdover from as far back as the Exadv1 days, this has constantly irked me since I started working with the code. None of the player-facing stuff has referred to plasma as toxin since before 4407 hit, besides the Toxins Lab, and yet all of the type-paths are still pointing at toxins, making it a nightmare to search for in a map editor, and making the code needlessly easy to confuse with that of toxin damage. So this just fires it into the sun.

Anything relating to Toxins, the science subdepartment, now makes reference to Ordnance instead. This felt fitting enough given the focus of the subdepartment is around the creation of and testing of explosives.
Anything relating to plasma gas has, fittingly, been made to refer to plasma gas.

Edit: Ah yes, I feel I should probably apologise off the bat for the size of this PR- the code touched is mostly atmos machinery and simplemobs, a few sprites here and there, and of course the station maps + a few offstation maps.

Makes the code more legible and makes mapping less painful.

(The payment has been made)
2021-08-17 11:49:47 -07:00

222 lines
8.4 KiB
Plaintext

#define MAX_RADIUS_REQUIRED 20 //maxcap
#define MIN_RADIUS_REQUIRED 4 //1, 2, 4
/// How long the compression test can last before the machine just gives up and ejects the items.
#define COMPRESSION_TEST_TIME (SSOBJ_DT SECONDS * 5)
/**
* # Explosive compressor machines
*
* The explosive compressor machine used in anomaly core production.
*
* Uses the standard ordnance/tank explosion scaling to compress raw anomaly cores into completed ones. The required explosion radius increases as more cores of that type are created.
*/
/obj/machinery/research/explosive_compressor
name = "implosion compressor"
desc = "An advanced machine capable of implosion-compressing raw anomaly cores into finished artifacts."
icon = 'icons/obj/machines/research.dmi'
icon_state = "explosive_compressor"
density = TRUE
/// The raw core inserted in the machine.
var/obj/item/raw_anomaly_core/inserted_core
/// The TTV inserted in the machine.
var/obj/item/transfer_valve/inserted_bomb
/// The timer that lets us timeout the test.
var/datum/timedevent/timeout_timer
/// Whether we are currently testing a bomb and core.
var/testing = FALSE
/// The message produced by the explosive compressor at the end of the compression test.
var/test_status = null
/// The last time we did say_requirements(), because someone will inevitably click spam this.
var/last_requirements_say = 0
/obj/machinery/research/explosive_compressor/Initialize()
. = ..()
RegisterSignal(src, COMSIG_ATOM_INTERNAL_EXPLOSION, .proc/check_test)
/obj/machinery/research/explosive_compressor/Destroy()
UnregisterSignal(src, COMSIG_ATOM_INTERNAL_EXPLOSION)
return ..()
/obj/machinery/research/explosive_compressor/examine(mob/user)
. = ..()
. += span_notice("Ctrl-Click to remove an inserted core.")
. += span_notice("Click with an empty hand to gather information about the required radius of an inserted core. Insert a ready TTV to start the implosion process if a core is inserted.")
/obj/machinery/research/explosive_compressor/assume_air(datum/gas_mixture/giver)
qdel(giver)
return null // Required to make the TTV not vent directly into the air.
/obj/machinery/research/explosive_compressor/attack_hand(mob/living/user, list/modifiers)
. = ..()
if(.)
return
if(!inserted_core)
to_chat(user, span_warning("There is no core inserted."))
return
if(last_requirements_say + 3 SECONDS > world.time)
return
last_requirements_say = world.time
say_requirements(inserted_core)
/obj/machinery/research/explosive_compressor/CtrlClick(mob/living/user)
. = ..()
if(!istype(user) || !user.Adjacent(src) || !(user.mobility_flags & MOBILITY_USE))
return
if(!inserted_core)
to_chat(user, span_warning("There is no core inserted."))
return
if(testing)
to_chat(user, span_warning("You can't remove [inserted_core] from [src] while [p_theyre()] in testing mode."))
return
inserted_core.forceMove(get_turf(user))
to_chat(user, span_notice("You remove [inserted_core] from [src]."))
user.put_in_hands(inserted_core)
inserted_core = null
/**
* Says (no, literally) the data of required explosive power for a certain anomaly type.
*/
/obj/machinery/research/explosive_compressor/proc/say_requirements(obj/item/raw_anomaly_core/core)
var/required = get_required_radius(core.anomaly_type)
if(isnull(required))
say("Unfortunately, due to diminishing supplies of condensed anomalous matter, [core] and any cores of its type are no longer of a sufficient quality level to be compressed into a working core.")
else
say("[core] requires a minimum of a theoretical radius of [required] to successfully implode into a charged anomaly core.")
/**
* Determines how much explosive power (last value, so light impact theoretical radius) is required to make a certain anomaly type.
*
* Returns null if the max amount has already been reached.
*
* Arguments:
* * anomaly_type - anomaly type define
*/
/obj/machinery/research/explosive_compressor/proc/get_required_radius(anomaly_type)
var/already_made = SSresearch.created_anomaly_types[anomaly_type]
var/hard_limit = SSresearch.anomaly_hard_limit_by_type[anomaly_type]
if(already_made >= hard_limit)
return //return null
// my crappy autoscale formula
// linear scaling.
var/radius_span = MAX_RADIUS_REQUIRED - MIN_RADIUS_REQUIRED
var/radius_increase_per_core = radius_span / hard_limit
var/radius = clamp(round(MIN_RADIUS_REQUIRED + radius_increase_per_core * already_made, 1), MIN_RADIUS_REQUIRED, MAX_RADIUS_REQUIRED)
return radius
/obj/machinery/research/explosive_compressor/attackby(obj/item/tool, mob/living/user, params)
. = ..()
if(istype(tool, /obj/item/raw_anomaly_core))
if(inserted_core)
to_chat(user, span_warning("There is already a core in [src]."))
return
if(testing)
to_chat(user, span_warning("You can't insert [tool] into [src] while [p_theyre()] in testing mode."))
return
if(!user.transferItemToLoc(tool, src))
to_chat(user, span_warning("[tool] is stuck to your hand."))
return
inserted_core = tool
to_chat(user, span_notice("You insert [tool] into [src]."))
return
if(istype(tool, /obj/item/transfer_valve))
// If they don't have a bomb core inserted, don't let them insert this. If they do, insert and do implosion.
if(!inserted_core)
to_chat(user, span_warning("There is no core inserted in [src]. What would be the point of detonating an implosion without a core?"))
return
if(testing)
to_chat(user, span_warning("You can't insert [tool] into [src] while [p_theyre()] in testing mode."))
return
var/obj/item/transfer_valve/valve = tool
if(!valve.ready())
to_chat(user, span_warning("[valve] is incomplete."))
return
if(!user.transferItemToLoc(tool, src))
to_chat(user, span_warning("[tool] is stuck to your hand."))
return
inserted_bomb = tool
to_chat(user, span_notice("You insert [tool] and press the start button."))
start_test()
/**
* Starts a compression test.
*/
/obj/machinery/research/explosive_compressor/proc/start_test()
if(!istype(inserted_core) || !istype(inserted_bomb))
end_test("ERROR: Missing equpment. Items ejected.")
return
say("Beginning compression test. Opening transfer valve.")
testing = TRUE
test_status = null
inserted_bomb.toggle_valve()
timeout_timer = addtimer(CALLBACK(src, .proc/timeout_test), COMPRESSION_TEST_TIME, TIMER_STOPPABLE | TIMER_UNIQUE | TIMER_NO_HASH_WAIT)
return
/**
* Ends a compression test.
*
* Arguments:
* - message: A message for the compressor to say when the test ends.
*/
/obj/machinery/research/explosive_compressor/proc/end_test(message)
if(inserted_core)
inserted_core.forceMove(drop_location())
inserted_core = null
if(inserted_bomb)
inserted_bomb.forceMove(drop_location())
inserted_bomb = null
if(timeout_timer)
QDEL_NULL(timeout_timer)
if(message)
say(message)
testing = FALSE
return
/**
* Checks whether an internal explosion was sufficient to compress the core.
*/
/obj/machinery/research/explosive_compressor/proc/check_test(atom/source, list/arguments)
SIGNAL_HANDLER
. = COMSIG_CANCEL_EXPLOSION
if(!inserted_core)
test_status = "ERROR: No core present during detonation."
return
var/heavy = arguments[EXARG_KEY_DEV_RANGE]
var/medium = arguments[EXARG_KEY_HEAVY_RANGE]
var/light = arguments[EXARG_KEY_LIGHT_RANGE]
var/explosion_range = max(heavy, medium, light, 0)
var/required_range = get_required_radius(inserted_core.anomaly_type)
var/turf/location = get_turf(src)
var/cap_multiplier = SSmapping.level_trait(location.z, ZTRAIT_BOMBCAP_MULTIPLIER)
if(isnull(cap_multiplier))
cap_multiplier = 1
var/capped_heavy = min(GLOB.MAX_EX_DEVESTATION_RANGE * cap_multiplier, heavy)
var/capped_medium = min(GLOB.MAX_EX_HEAVY_RANGE * cap_multiplier, medium)
SSexplosions.shake_the_room(location, explosion_range, (capped_heavy * 15) + (capped_medium * 20), capped_heavy, capped_medium)
if(explosion_range < required_range)
test_status = "Resultant detonation failed to produce enough implosive power to compress [inserted_core]. Core ejected."
return
if(test_status)
return
inserted_core = inserted_core.create_core(src, TRUE, TRUE)
test_status = "Success. Resultant detonation has theoretical range of [explosion_range]. Required radius was [required_range]. Core production complete."
return
/**
* Handles timing out the test after a while.
*/
/obj/machinery/research/explosive_compressor/proc/timeout_test()
timeout_timer = null
if(!test_status)
test_status = "Transfer valve resulted in negligible explosive power. Items ejected."
end_test(test_status)
#undef MAX_RADIUS_REQUIRED
#undef MIN_RADIUS_REQUIRED