mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2025-12-19 14:12:55 +00:00
## About The Pull Request <details> - renamed ai folder to announcer -- announcer -- - moved vox_fem to announcer - moved approachingTG to announcer - separated the ambience folder into ambience and instrumental -- ambience -- - created holy folder moved all related sounds there - created engineering folder and moved all related sounds there - created security folder and moved ambidet there - created general folder and moved ambigen there - created icemoon folder and moved all icebox-related ambience there - created medical folder and moved all medbay-related ambi there - created ruin folder and moves all ruins ambi there - created beach folder and moved seag and shore there - created lavaland folder and moved related ambi there - created aurora_caelus folder and placed its ambi there - created misc folder and moved the rest of the files that don't have a specific category into it -- instrumental -- - moved traitor folder here - created lobby_music folder and placed our songs there (title0 not used anywhere? - server-side modification?) -- items -- - moved secdeath to hailer - moved surgery to handling -- effects -- - moved chemistry into effects - moved hallucinations into effects - moved health into effects - moved magic into effects -- vehicles -- - moved mecha into vehicles created mobs folder -- mobs -- - moved creatures folder into mobs - moved voice into mobs renamed creatures to non-humanoids renamed voice to humanoids -- non-humanoids-- created cyborg folder created hiss folder moved harmalarm.ogg to cyborg -- humanoids -- -- misc -- moved ghostwhisper to misc moved insane_low_laugh to misc I give up trying to document this. </details> - [X] ambience - [x] announcer - [x] effects - [X] instrumental - [x] items - [x] machines - [x] misc - [X] mobs - [X] runtime - [X] vehicles - [ ] attributions ## Why It's Good For The Game This folder is so disorganized that it's vomit inducing, will make it easier to find and add new sounds, providng a minor structure to the sound folder. ## Changelog 🆑 grungussuss refactor: the sound folder in the source code has been reorganized, please report any oddities with sounds playing or not playing server: lobby music has been repathed to sound/music/lobby_music /🆑
362 lines
13 KiB
Plaintext
362 lines
13 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/anomaly_refinery
|
|
name = "anomaly refinery"
|
|
desc = "An advanced machine capable of implosion-compressing raw anomaly cores into finished artifacts. Also equipped with state of the art bomb prediction software."
|
|
circuit = /obj/item/circuitboard/machine/anomaly_refinery
|
|
icon = 'icons/obj/machines/research.dmi'
|
|
base_icon_state = "explosive_compressor"
|
|
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 active a bomb and core.
|
|
var/active = FALSE
|
|
/// The message produced by the explosive compressor at the end of the compression test.
|
|
var/test_status = null
|
|
/// Determines which tank will be the merge_gases target (destroyed upon testing).
|
|
var/obj/item/tank/tank_to_target
|
|
|
|
// These vars are used for the explosion simulation and doesn't affect the core detonation.
|
|
/// Combined result of the first two tanks. Exists only in our machine.
|
|
var/datum/gas_mixture/combined_gasmix
|
|
/// Here for the UI, tracks the amounts of reaction that has occured. 1 means valve opened but not reacted.
|
|
var/reaction_increment = 0
|
|
|
|
/obj/machinery/research/anomaly_refinery/Initialize(mapload)
|
|
. = ..()
|
|
RegisterSignal(src, COMSIG_ATOM_INTERNAL_EXPLOSION, PROC_REF(check_test))
|
|
|
|
/obj/machinery/research/anomaly_refinery/examine_more(mob/user)
|
|
. = ..()
|
|
if (obj_flags & EMAGGED)
|
|
. += span_notice("A small panel on [p_their()] side is dislaying a notice. Something about firmware?")
|
|
|
|
|
|
/obj/machinery/research/anomaly_refinery/assume_air(datum/gas_mixture/giver)
|
|
return null // Required to make the TTV not vent directly into the air.
|
|
|
|
/**
|
|
* 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/anomaly_refinery/proc/get_required_radius(anomaly_type)
|
|
if(!SSresearch.is_core_available(anomaly_type))
|
|
return //return null
|
|
|
|
var/already_made = SSresearch.created_anomaly_types[anomaly_type]
|
|
var/hard_limit = SSresearch.anomaly_hard_limit_by_type[anomaly_type]
|
|
|
|
// 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/anomaly_refinery/attackby(obj/item/tool, mob/living/user, params)
|
|
if(active)
|
|
to_chat(user, span_warning("You can't insert [tool] into [src] while [p_theyre()] currently active."))
|
|
return
|
|
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(!user.transferItemToLoc(tool, src))
|
|
to_chat(user, span_warning("[tool] is stuck to your hand."))
|
|
return
|
|
var/obj/item/raw_anomaly_core/raw_core = tool
|
|
if(!get_required_radius(raw_core.anomaly_type))
|
|
say("Unfortunately, due to diminishing supplies of condensed anomalous matter, [raw_core] and any cores of its type are no longer of a sufficient quality level to be compressed into a working core.")
|
|
return
|
|
inserted_core = raw_core
|
|
to_chat(user, span_notice("You insert [raw_core] into [src]."))
|
|
return
|
|
if(istype(tool, /obj/item/transfer_valve))
|
|
if(inserted_bomb)
|
|
to_chat(user, span_warning("There is already a bomb in [src]."))
|
|
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
|
|
tank_to_target = inserted_bomb.tank_two
|
|
to_chat(user, span_notice("You insert [tool] into [src]"))
|
|
return
|
|
update_appearance()
|
|
return ..()
|
|
|
|
/obj/machinery/research/anomaly_refinery/wrench_act(mob/living/user, obj/item/tool)
|
|
. = ..()
|
|
default_unfasten_wrench(user, tool)
|
|
return ITEM_INTERACT_SUCCESS
|
|
|
|
/obj/machinery/research/anomaly_refinery/screwdriver_act(mob/living/user, obj/item/tool)
|
|
if(!default_deconstruction_screwdriver(user, "[base_icon_state]-off", "[base_icon_state]", tool))
|
|
return FALSE
|
|
update_appearance()
|
|
return TRUE
|
|
|
|
/obj/machinery/research/anomaly_refinery/crowbar_act(mob/living/user, obj/item/tool)
|
|
if(!default_deconstruction_crowbar(tool))
|
|
return FALSE
|
|
return TRUE
|
|
|
|
/obj/machinery/research/anomaly_refinery/emag_act(mob/user, obj/item/card/emag/emag_card)
|
|
. = ..()
|
|
if (obj_flags & EMAGGED)
|
|
balloon_alert(user, "already hacked!")
|
|
return
|
|
|
|
obj_flags |= EMAGGED
|
|
playsound(src, 'sound/machines/buzz/buzz-sigh.ogg', 50, vary = FALSE)
|
|
say("ERROR: Unauthorized firmware access.")
|
|
return TRUE
|
|
|
|
/**
|
|
* Starts a compression test.
|
|
*/
|
|
/obj/machinery/research/anomaly_refinery/proc/start_test()
|
|
if (active)
|
|
say("ERROR: Already running a compression test.")
|
|
return
|
|
|
|
if(!istype(inserted_core) || !istype(inserted_bomb))
|
|
end_test("ERROR: Missing equpment. Items ejected.")
|
|
return
|
|
|
|
if(!inserted_bomb?.tank_one || !inserted_bomb?.tank_two || !(tank_to_target == inserted_bomb?.tank_one || tank_to_target == inserted_bomb?.tank_two))
|
|
end_test("ERROR: Transfer valve malfunctioning. Items ejected.")
|
|
return
|
|
|
|
say("Beginning compression test. Opening transfer valve.")
|
|
active = TRUE
|
|
test_status = null
|
|
|
|
if (obj_flags & EMAGGED)
|
|
say("ERROR: An firmware issue was detected while starting a process. Running autopatcher.")
|
|
playsound(src, 'sound/machines/ding.ogg', 50, vary = TRUE)
|
|
addtimer(CALLBACK(src, PROC_REF(error_test)), 2 SECONDS, TIMER_STOPPABLE | TIMER_UNIQUE | TIMER_NO_HASH_WAIT) // Synced with the sound.
|
|
return
|
|
|
|
inserted_bomb.toggle_valve(tank_to_target)
|
|
timeout_timer = addtimer(CALLBACK(src, PROC_REF(timeout_test)), COMPRESSION_TEST_TIME, TIMER_STOPPABLE | TIMER_UNIQUE | TIMER_NO_HASH_WAIT)
|
|
return
|
|
|
|
/**
|
|
* Ejects a live TTV.
|
|
* Triggered by attempting to operate an emagged anomaly refinery.
|
|
*/
|
|
/obj/machinery/research/anomaly_refinery/proc/error_test()
|
|
message_admins("[src] was emagged and ejected a TTV.")
|
|
investigate_log("was emagged and ejected a TTV.", INVESTIGATE_RESEARCH)
|
|
obj_flags &= ~EMAGGED
|
|
|
|
say("Issue resolved. Have a nice day!")
|
|
inserted_bomb.toggle_valve(tank_to_target)
|
|
eject_bomb(force = TRUE)
|
|
timeout_timer = addtimer(CALLBACK(src, PROC_REF(timeout_test)), COMPRESSION_TEST_TIME, TIMER_STOPPABLE | TIMER_UNIQUE | TIMER_NO_HASH_WAIT) // Actually start the test so they can't just put the bomb back in.
|
|
|
|
/**
|
|
* Ends a compression test.
|
|
*
|
|
* Arguments:
|
|
* - message: A message for the compressor to say when the test ends.
|
|
*/
|
|
/obj/machinery/research/anomaly_refinery/proc/end_test(message)
|
|
active = FALSE
|
|
tank_to_target = null
|
|
test_status = null
|
|
if(inserted_core)
|
|
eject_core()
|
|
if(inserted_bomb)
|
|
eject_bomb()
|
|
if(timeout_timer)
|
|
QDEL_NULL(timeout_timer)
|
|
if(message)
|
|
say(message)
|
|
return
|
|
|
|
/**
|
|
* Checks whether an internal explosion was sufficient to compress the core.
|
|
*/
|
|
/obj/machinery/research/anomaly_refinery/proc/check_test(atom/source, list/arguments)
|
|
SIGNAL_HANDLER
|
|
if(!inserted_core)
|
|
test_status = "ERROR: No core present during detonation."
|
|
return COMSIG_CANCEL_EXPLOSION
|
|
|
|
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]. Items ejected."
|
|
return COMSIG_CANCEL_EXPLOSION
|
|
|
|
if(test_status)
|
|
return COMSIG_CANCEL_EXPLOSION
|
|
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 COMSIG_CANCEL_EXPLOSION
|
|
|
|
/**
|
|
* Handles timing out the test after a while.
|
|
*/
|
|
/obj/machinery/research/anomaly_refinery/proc/timeout_test()
|
|
timeout_timer = null
|
|
if(!test_status)
|
|
test_status = "Transfer valve resulted in negligible explosive power. Items ejected."
|
|
end_test(test_status)
|
|
|
|
/// This is not the real valve opening process. This is the simulated one used for displaying reactions.
|
|
/obj/machinery/research/anomaly_refinery/proc/simulate_valve()
|
|
if(!inserted_bomb?.tank_one || !inserted_bomb?.tank_two)
|
|
eject_bomb()
|
|
return FALSE
|
|
|
|
if(reaction_increment == 0)
|
|
var/datum/gas_mixture/first_gasmix = inserted_bomb.tank_one.return_air()
|
|
var/datum/gas_mixture/second_gasmix = inserted_bomb.tank_two.return_air()
|
|
|
|
combined_gasmix = new(70)
|
|
combined_gasmix.volume = first_gasmix.volume + second_gasmix.volume
|
|
combined_gasmix.merge(first_gasmix.copy())
|
|
combined_gasmix.merge(second_gasmix.copy())
|
|
else
|
|
combined_gasmix.react()
|
|
|
|
reaction_increment += 1
|
|
|
|
/// We dont allow incomplete valves to go in but do code in checks for incomplete valves. Just in case.
|
|
/obj/machinery/research/anomaly_refinery/proc/eject_bomb(mob/user, force = FALSE)
|
|
if(!inserted_bomb || (active && !force))
|
|
return
|
|
if(user)
|
|
user.put_in_hands(inserted_bomb)
|
|
to_chat(user, span_notice("You remove [inserted_bomb] from [src]."))
|
|
else
|
|
inserted_bomb.forceMove(drop_location())
|
|
combined_gasmix = null
|
|
reaction_increment = 0
|
|
|
|
/obj/machinery/research/anomaly_refinery/proc/eject_core(mob/user)
|
|
if(!inserted_core || active)
|
|
return
|
|
if(user)
|
|
user.put_in_hands(inserted_core)
|
|
to_chat(user, span_notice("You remove [inserted_core] from [src]."))
|
|
else
|
|
inserted_core.forceMove(drop_location())
|
|
|
|
/// We rely on exited to clear references.
|
|
/obj/machinery/research/anomaly_refinery/Exited(atom/movable/gone, direction)
|
|
if(gone == inserted_bomb)
|
|
inserted_bomb = null
|
|
tank_to_target = null
|
|
if(gone == inserted_core)
|
|
inserted_core = null
|
|
. = ..()
|
|
|
|
/obj/machinery/research/anomaly_refinery/proc/swap_target()
|
|
if(!inserted_bomb?.tank_one || !inserted_bomb?.tank_two)
|
|
eject_bomb()
|
|
return FALSE
|
|
tank_to_target = (tank_to_target == inserted_bomb.tank_one) ? inserted_bomb.tank_two : inserted_bomb.tank_one
|
|
|
|
/obj/machinery/research/anomaly_refinery/on_deconstruction(disassembled)
|
|
eject_bomb()
|
|
eject_core()
|
|
return ..()
|
|
|
|
/obj/machinery/research/anomaly_refinery/Destroy()
|
|
inserted_bomb = null
|
|
inserted_core = null
|
|
combined_gasmix = null
|
|
return ..()
|
|
|
|
/obj/machinery/research/anomaly_refinery/ui_interact(mob/user, datum/tgui/ui)
|
|
. = ..()
|
|
ui = SStgui.try_update_ui(user, src, ui)
|
|
if(!ui)
|
|
ui = new(user, src, "AnomalyRefinery")
|
|
ui.open()
|
|
|
|
/obj/machinery/research/anomaly_refinery/ui_act(action, list/params, datum/tgui/ui, datum/ui_state/state)
|
|
. = ..()
|
|
if (.)
|
|
return
|
|
switch(action)
|
|
if("react")
|
|
simulate_valve()
|
|
if("eject_bomb")
|
|
eject_bomb(usr)
|
|
if("eject_core")
|
|
eject_core(usr)
|
|
if("start_implosion")
|
|
start_test()
|
|
if("swap")
|
|
swap_target()
|
|
|
|
/obj/machinery/research/anomaly_refinery/ui_data(mob/user)
|
|
var/list/data = list()
|
|
var/list/parsed_gasmixes = list()
|
|
var/obj/item/tank/other_tank
|
|
|
|
if(inserted_bomb?.tank_one && inserted_bomb?.tank_two)
|
|
other_tank = inserted_bomb.tank_one == tank_to_target ? inserted_bomb.tank_two : inserted_bomb.tank_one
|
|
|
|
parsed_gasmixes += list(gas_mixture_parser(tank_to_target?.return_air(), tank_to_target?.name))
|
|
parsed_gasmixes += list(gas_mixture_parser(other_tank?.return_air(), other_tank?.name))
|
|
parsed_gasmixes += list(gas_mixture_parser(combined_gasmix, "Combined Gasmix"))
|
|
|
|
data["gasList"] = parsed_gasmixes
|
|
|
|
data["valvePresent"] = inserted_bomb ? TRUE : FALSE
|
|
data["valveReady"] = (inserted_bomb?.tank_one && inserted_bomb?.tank_two) ? TRUE : FALSE
|
|
data["reactionIncrement"] = reaction_increment
|
|
|
|
data["core"] = inserted_core ? inserted_core.name : FALSE
|
|
data["requiredRadius"] = inserted_core ? get_required_radius(inserted_core.anomaly_type) : null
|
|
|
|
data["active"] = active
|
|
|
|
return data
|
|
|
|
#undef MAX_RADIUS_REQUIRED
|
|
#undef MIN_RADIUS_REQUIRED
|
|
#undef COMPRESSION_TEST_TIME
|