The NGCR: Nuclear Fission Reactor (#30493)

* coefficient balancing

* damage and meltdowns

* meltdown stuff

* alert stuff

* lots of work - whew

* some enrichment code

* rod encrichmnt

* working on enrichment

* more fabrication

* rod fab

* start to the nuke

* overload sprites

* overload code work

* some overload tweaking

* small tweak

* coolant ejections and QOL things

* overheat events + ripley gripper

* rebase + venting code

* save before rebase

* some pre-work for rods

* finishing the base rods

* fixed my dme

* de linting

* tiny lint fix

* more lint fixes

* linting

* linting

* linting

* linting

* linting

* temp delint

* temp delint

* undo TM stuff + minor fix

* didnt save

* some fixes

* fixes

* fixes and engine repair

* fixed broken durability decay

* LOTS of things

* tgui

* lint

* linter

* linter

* minor shit

* Update boxstation.dmm

* major refactors and fixes

* saved this

* critical testing tweaks and fixes

* fixes and tweaks

* smithing start

* forgot to save

* craftables + grill start

* saved

* fix

* more grill work

* Update tgui.bundle.js

* linter

* linter

* fixes

* rod fabricator initial

* cooking work

* push

* soundwork

* sound work tweak

* comments + sounds + toxins gen rework

* lots of work

* sprite stuff

* deconflicting

* delinting

* bundle rebuild

* prettier

* feex

* fuck you OD

* who asked?

* update to tgui

* another edit to tgui

* finish tgui

* remove debug metadata button

* rod tweaks for tgui

* Update code/datums/uplink_items/uplink_traitor.dm

Co-authored-by: Pooble <90473506+poobsie@users.noreply.github.com>
Signed-off-by: Kyani <65205627+EmeraldCandy@users.noreply.github.com>

* Update code/game/mecha/equipment/tools/work_tools.dm

Co-authored-by: Pooble <90473506+poobsie@users.noreply.github.com>
Signed-off-by: Kyani <65205627+EmeraldCandy@users.noreply.github.com>

* Update code/game/mecha/equipment/tools/work_tools.dm

Co-authored-by: Pooble <90473506+poobsie@users.noreply.github.com>
Signed-off-by: Kyani <65205627+EmeraldCandy@users.noreply.github.com>

* Update code/game/objects/items/robot/cyborg_gripper.dm

Co-authored-by: Pooble <90473506+poobsie@users.noreply.github.com>
Signed-off-by: Kyani <65205627+EmeraldCandy@users.noreply.github.com>

* Update code/modules/mob/living/simple_animal/parrot.dm

Co-authored-by: Pooble <90473506+poobsie@users.noreply.github.com>
Signed-off-by: Kyani <65205627+EmeraldCandy@users.noreply.github.com>

* Update code/modules/mob/living/simple_animal/parrot.dm

Co-authored-by: Pooble <90473506+poobsie@users.noreply.github.com>
Signed-off-by: Kyani <65205627+EmeraldCandy@users.noreply.github.com>

* Update code/modules/mob/living/simple_animal/parrot.dm

Co-authored-by: Pooble <90473506+poobsie@users.noreply.github.com>
Signed-off-by: Kyani <65205627+EmeraldCandy@users.noreply.github.com>

* Update code/modules/mob/living/simple_animal/parrot.dm

Co-authored-by: Pooble <90473506+poobsie@users.noreply.github.com>
Signed-off-by: Kyani <65205627+EmeraldCandy@users.noreply.github.com>

* Update code/modules/power/engines/fission/nuclear_misc.dm

Co-authored-by: Pooble <90473506+poobsie@users.noreply.github.com>
Signed-off-by: Kyani <65205627+EmeraldCandy@users.noreply.github.com>

* Update code/modules/power/engines/fission/nuclear_misc.dm

Co-authored-by: Pooble <90473506+poobsie@users.noreply.github.com>
Signed-off-by: Kyani <65205627+EmeraldCandy@users.noreply.github.com>

* Update code/modules/power/engines/fission/nuclear_misc.dm

Co-authored-by: Pooble <90473506+poobsie@users.noreply.github.com>
Signed-off-by: Kyani <65205627+EmeraldCandy@users.noreply.github.com>

* Update code/modules/power/engines/fission/nuclear_rods.dm

Co-authored-by: Pooble <90473506+poobsie@users.noreply.github.com>
Signed-off-by: Kyani <65205627+EmeraldCandy@users.noreply.github.com>

* Update code/modules/power/engines/fission/nuclear_rods.dm

Co-authored-by: Pooble <90473506+poobsie@users.noreply.github.com>
Signed-off-by: Kyani <65205627+EmeraldCandy@users.noreply.github.com>

* Update code/modules/power/engines/fission/reactor.dm

Co-authored-by: Pooble <90473506+poobsie@users.noreply.github.com>
Signed-off-by: Kyani <65205627+EmeraldCandy@users.noreply.github.com>

* Update code/modules/power/engines/fission/reactor.dm

Co-authored-by: Pooble <90473506+poobsie@users.noreply.github.com>
Signed-off-by: Kyani <65205627+EmeraldCandy@users.noreply.github.com>

* Update code/modules/power/engines/fission/nuclear_rods.dm

Co-authored-by: Pooble <90473506+poobsie@users.noreply.github.com>
Signed-off-by: Kyani <65205627+EmeraldCandy@users.noreply.github.com>

* Update code/modules/power/engines/fission/nuclear_rods.dm

Co-authored-by: Pooble <90473506+poobsie@users.noreply.github.com>
Signed-off-by: Kyani <65205627+EmeraldCandy@users.noreply.github.com>

* Update code/modules/power/engines/fission/nuclear_rods.dm

Co-authored-by: Pooble <90473506+poobsie@users.noreply.github.com>
Signed-off-by: Kyani <65205627+EmeraldCandy@users.noreply.github.com>

* Update code/modules/power/engines/fission/reactor.dm

Co-authored-by: Pooble <90473506+poobsie@users.noreply.github.com>
Signed-off-by: Kyani <65205627+EmeraldCandy@users.noreply.github.com>

* Update code/modules/smithing/components/misc_components.dm

Co-authored-by: Pooble <90473506+poobsie@users.noreply.github.com>
Signed-off-by: Kyani <65205627+EmeraldCandy@users.noreply.github.com>

* Update code/modules/power/engines/fission/nuclear_rods.dm

Co-authored-by: Pooble <90473506+poobsie@users.noreply.github.com>
Signed-off-by: Kyani <65205627+EmeraldCandy@users.noreply.github.com>

* Update tgui/packages/tgui/interfaces/NuclearRodFabricator.jsx

Co-authored-by: Pooble <90473506+poobsie@users.noreply.github.com>
Signed-off-by: Kyani <65205627+EmeraldCandy@users.noreply.github.com>

* Spans

* tgui build

* rod redo

* improve tgui for fabricator

* sprites and centrifuge/fab work

* tgui update

* spritework

* cyberiad + hydrogen conversion

* kerberos + counter

* Update code/modules/power/engines/fission/nuclear_rods.dm

Co-authored-by: Pooble <90473506+poobsie@users.noreply.github.com>
Signed-off-by: Kyani <65205627+EmeraldCandy@users.noreply.github.com>

* sprite + fab tweak

* tgui bundle

* lintering

* bugfixing

* linting

* linting

* event tweak

* add missing gases to fission monitor

* issue fixing

* sprite/overlay fixes

* mapping

* stations again

* space lattice

* tine tweak

* linter

* no rod alerts

* buttons

* loose wire

* make it so you can interact through rod casings and the uhh big thing in the center, what's that called again

* fixes

* door fix

* many bug fixes + crates

* fab ghost touch

* water convert + maint sprite + fixes

* pack changes + neighbor fix

* doors rename

* didnt save

* hydrogen fix

* map tweaks

* repair fixes + corium LETHALITY

* upped broken rad damage

* pipe rename + overload icons

* more roundstart moderators

* rod tree tweaks

* tweaks

* pack and enrichment fixes

* misc tweaks and fixes

* fixes: Density, circuits, coolant offline negation

* Apply suggestions from code review

Co-authored-by: warriorstar-orion <orion@snowfrost.garden>
Co-authored-by: DGamerL <108773801+DGamerL@users.noreply.github.com>
Signed-off-by: Kyani <65205627+EmeraldCandy@users.noreply.github.com>

* review changes

* linter + fix

* reviews and fixes

* LOTS of tweaks and changes

* supermatter kit

* spacematter balance

* tgui

* fixes and tweaks

* didnt save this

* mapping + smith fix

* cargo rods arnt radioactive til opened

* Apply suggestions from code review

Co-authored-by: Pooble <90473506+poobsie@users.noreply.github.com>
Signed-off-by: Kyani <65205627+EmeraldCandy@users.noreply.github.com>

* review items

* fixes

* linters

* moving components out of nullspace

* examine fix

* Update tgui.bundle.js

* explosion nerf and minor fix

* Apply suggestions from code review

Co-authored-by: Pooble <90473506+poobsie@users.noreply.github.com>
Signed-off-by: Kyani <65205627+EmeraldCandy@users.noreply.github.com>

* reviews

* map fix + ripley rad immune

* Apply suggestions from code review

Co-authored-by: Burzah <116982774+Burzah@users.noreply.github.com>
Signed-off-by: Kyani <65205627+EmeraldCandy@users.noreply.github.com>

* review

* fix chamber examine

* tweaks + rod fab disk drop

* Apply suggestions from code review

Co-authored-by: DGamerL <108773801+DGamerL@users.noreply.github.com>
Signed-off-by: Kyani <65205627+EmeraldCandy@users.noreply.github.com>

* review changes

* Update code/modules/power/engines/fission/nuclear_rods.dm

Co-authored-by: DGamerL <108773801+DGamerL@users.noreply.github.com>
Signed-off-by: Kyani <65205627+EmeraldCandy@users.noreply.github.com>

* fixes

* tgui bundle

* small rod tweaks

* Update code/game/machinery/computer/buildandrepair.dm

Co-authored-by: DGamerL <108773801+DGamerL@users.noreply.github.com>
Signed-off-by: Kyani <65205627+EmeraldCandy@users.noreply.github.com>

* Update code/modules/smithing/components/reactor_components.dm

Co-authored-by: DGamerL <108773801+DGamerL@users.noreply.github.com>
Signed-off-by: Kyani <65205627+EmeraldCandy@users.noreply.github.com>

* Update code/modules/power/engines/fission/reactor_machines.dm

Co-authored-by: DGamerL <108773801+DGamerL@users.noreply.github.com>
Signed-off-by: Kyani <65205627+EmeraldCandy@users.noreply.github.com>

* Update code/modules/power/engines/fission/reactor_machines.dm

Co-authored-by: DGamerL <108773801+DGamerL@users.noreply.github.com>
Signed-off-by: Kyani <65205627+EmeraldCandy@users.noreply.github.com>

* reviews

* Update code/modules/power/engines/fission/reactor_machines.dm

Signed-off-by: DGamerL <108773801+DGamerL@users.noreply.github.com>

---------

Signed-off-by: Kyani <65205627+EmeraldCandy@users.noreply.github.com>
Signed-off-by: DGamerL <108773801+DGamerL@users.noreply.github.com>
Co-authored-by: Burzah <116982774+Burzah@users.noreply.github.com>
Co-authored-by: Paul <pmerkamp@gmail.com>
Co-authored-by: Pooble <90473506+poobsie@users.noreply.github.com>
Co-authored-by: warriorstar-orion <orion@snowfrost.garden>
Co-authored-by: DGamerL <108773801+DGamerL@users.noreply.github.com>
This commit is contained in:
Kyani
2026-01-07 04:19:43 -05:00
committed by GitHub
parent 6611476bdb
commit f81ef075f1
59 changed files with 13266 additions and 8242 deletions

View File

@@ -79,6 +79,7 @@
<BR>
<b>Reinforce Station</b><BR>
<A href='byond://?src=[UID()];secretsfun=gammashuttle'>Move the Gamma Armory</A>&nbsp;&nbsp;
<A href='byond://?src=[UID()];secretsfun=nuclear_overload'>Disable Fission Reactor Safeties</A>&nbsp;&nbsp;
<BR>
</center>"}

View File

@@ -3341,6 +3341,15 @@
log_admin("[key_name(usr)] moved the gamma armory")
move_gamma_ship()
if("nuclear_overload")
SSblackbox.record_feedback("tally", "admin_secrets_fun_used", 1, "Disable Fission Reactor Safeties")
message_admins("[key_name_admin(usr)] disabled reactor safeties")
log_admin("[key_name(usr)] disabled reactor safeties")
if(GLOB.main_fission_reactor)
INVOKE_ASYNC(GLOB.main_fission_reactor, TYPE_PROC_REF(/obj/machinery/atmospherics/fission_reactor/, overload_reactor))
else
log_admin("An admin attempted to override fission reactor safeties, but no reactor was found!")
if(usr)
log_admin("[key_name(usr)] used secret [href_list["secretsfun"]]")
if(ok)

View File

@@ -105,3 +105,19 @@ USER_CONTEXT_MENU(admin_freeze, R_ADMIN, "\[Admin\] Freeze", atom/movable/M)
cut_overlay(freeze_overlay)
message_admins(SPAN_NOTICE("[key_name_admin(admin)] [processes ? "unfroze" : "froze"] a supermatter crystal"))
log_admin("[key_name(admin)] [processes ? "unfroze" : "froze"] a supermatter crystal")
/obj/machinery/atmospherics/fission_reactor/admin_Freeze(client/admin)
var/obj/effect/overlay/adminoverlay/freeze_overlay = new
freeze_overlay.pixel_x = 16
if(!admin_intervention)
radio.autosay("Alert: Unknown intervention is interfering in reactor core operations. It is not progressing in local timespace.", name, "Engineering")
GLOB.frozen_atom_list += src
admin_intervention = TRUE
add_overlay(freeze_overlay)
else
radio.autosay("Alert: Unknown intervention has ceased within the reactor core. It has returned to the regular flow of time.", name, "Engineering")
GLOB.frozen_atom_list -= src
admin_intervention = FALSE
cut_overlay(freeze_overlay)
message_admins(SPAN_NOTICE("[key_name_admin(admin)] [!admin_intervention ? "unfroze" : "froze"] the NGCR Reactor"))
log_admin("[key_name(admin)] [!admin_intervention ? "unfroze" : "froze"] the NGCR Reactor")

View File

@@ -110,10 +110,9 @@ RESTRICT_TYPE(/obj/machinery/cooking)
return
var/datum/cooking_surface/surface = surfaces[surface_idx]
var/list/surface_options = list(
RADIAL_ACTION_SET_ALARM = image(icon = 'icons/hud/radial.dmi', icon_state = "radial_setalarm"),
RADIAL_ACTION_ON_OFF = image(icon = 'icons/hud/radial.dmi', icon_state = "radial_onoff"),
)
var/list/surface_options = list(RADIAL_ACTION_SET_ALARM = image(icon = 'icons/hud/radial.dmi', icon_state = "radial_setalarm"))
if(surface.allow_toggling)
surface_options[RADIAL_ACTION_ON_OFF] = image(icon = 'icons/hud/radial.dmi', icon_state = "radial_onoff")
if(surface.allow_temp_change)
surface_options[RADIAL_ACTION_SET_TEMPERATURE] = image(icon = 'icons/hud/radial.dmi', icon_state = "radial_settemp")
var/option_choice = show_radial_menu(user, src, surface_options, require_near = TRUE)

View File

@@ -15,6 +15,7 @@ RESTRICT_TYPE(/datum/cooking_surface)
var/on = FALSE
var/prob_quality_decrease = 0
var/allow_temp_change = TRUE
var/allow_toggling = TRUE
VAR_PRIVATE/burn_callback
VAR_PRIVATE/fire_callback
VAR_PRIVATE/alarm_callback

View File

@@ -60,7 +60,8 @@
/obj/machinery/cooking/grill/examine(mob/user)
. = ..()
. += SPAN_NOTICE("It contains [round(stored_wood, 0.01)]/[wood_maximum] units of charcoal.")
if(wood_maximum != INFINITY)
. += SPAN_NOTICE("It contains [round(stored_wood, 0.01)]/[wood_maximum] units of charcoal.")
. += SPAN_NOTICE("<b>Ctrl-Click</b> on a surface to set its timer, temperature, and toggle it on or off.")
/obj/machinery/cooking/grill/process()
@@ -207,3 +208,65 @@
surface.container = new /obj/item/reagent_containers/cooking/grill_grate(src)
stored_wood = 30
update_appearance()
/obj/machinery/cooking/grill/loaded/reactor
icon_state = "blank"
wood_maximum = INFINITY
active_power_consumption = 0
idle_power_consumption = 0
flags = INDESTRUCTIBLE
/// The reactor that the grill is attached to
var/obj/machinery/atmospherics/fission_reactor/linked_reactor
/obj/machinery/cooking/grill/loaded/reactor/Initialize(mapload)
. = ..()
stored_wood = INFINITY
var/datum/cooking_surface/surface = surfaces[1]
surface.container.pixel_x = -16
surface.container.pixel_y = 0
surface.container.transform = matrix().Scale(1.35, 1.35)
surface.allow_toggling = FALSE
surface = surfaces[2]
surface.container.pixel_x = 16
surface.container.pixel_y = 0
surface.container.transform = matrix().Scale(1.35, 1.35)
surface.allow_toggling = FALSE
/obj/machinery/cooking/grill/loaded/reactor/attack_hand(mob/user, params)
var/mob/living/carbon/human/burn_victim = user
if(istype(burn_victim) && !burn_victim.gloves)
var/which_hand = "l_hand"
if(!burn_victim.hand)
which_hand = "r_hand"
burn_victim.adjustFireLossByPart(5, which_hand)
to_chat(burn_victim, SPAN_WARNING("Your hand is burned as you try to remove the grill grate, but its stuck firmly!"))
else if(istype(burn_victim))
to_chat(burn_victim, SPAN_WARNING("You try to remove the grill grate, but its stuck firmly!"))
// We dont want most of the normal proc for shutting off.
/obj/machinery/cooking/grill/loaded/reactor/ignite()
new /obj/effect/fire(loc, T0C + 300, (roll("2d10+15") SECONDS), 1)
// Chance of spreading
var/spread_count = rand(1, 3)
if(prob(30))
var/list/dirs = GLOB.alldirs.Copy()
while(spread_count && length(dirs))
var/direction = pick_n_take(dirs)
var/turf/T = get_step(src, direction)
if(T.density)
continue
new /obj/effect/fire(T, T0C + 300, (roll("2d10+15") SECONDS), 1)
spread_count--
// we want our icons in a specific spot
/obj/machinery/cooking/grill/loaded/reactor/update_surface_icon(surface_idx)
var/datum/cooking_surface/surface = surfaces[surface_idx]
if(!surface.container)
return
add_to_visible(surface.container, surface_idx)
/obj/machinery/cooking/grill/loaded/reactor/update_overlays()
return

View File

@@ -733,9 +733,28 @@
"TOXINS!",
"ONI SOMA!",
"GOLDEN BLAST",
"Is there supposed to be this much plasma in the chamber??",,
"Is there supposed to be this much plasma in the chamber??",
"Why are there so many borgs?",
"Why're your eyes glowing red?"
"Why're your eyes glowing red?",
"Opening the reactor vent is how it gets gas, right?",
"Let's fill the reactor with supermatter rods!",
"Think we could weaponize ejected coolant rods?",
"WHO KEEPS LEAVING THE FUEL RODS OUT",
"Why do we need coolant rods if we use gas?",
"Wait, why isn't the reactor integrity going up?",
"When did engineering get a pool!?",
"Does anyone else taste copper?",
"10 sieverts isn't a harmful amount of radiation, is it?",
"HELP! THE CHEF IS GRILLING ME ON THE NGCR!",
"Replace the spent fuel rods you lazy bums!",
"There is a xenomorph nesting on the reactor!",
"Why is there a Ripley pulling out the coolant rods?",
"Atmospheric Technicians are the NGCR's favorite moderators",
"Who let the clown touch the control rods?",
"Which of you chucklefucks brought a fuel rod to medbay?",
"A coolant rod just flew into the captain!",
"The reactor is going supercritical!",
"Danger! Reactor core chamber meltdown in progress! Integrity: 79.47%"
)
unique_pet = TRUE
gold_core_spawnable = NO_SPAWN

View File

@@ -0,0 +1,103 @@
/datum/nuclear_rod_design
var/type_path
var/category = "Unknown"
var/list/metadata
/datum/nuclear_rod_design/proc/build_metadata_list(path)
metadata = list()
type_path = path
var/obj/item/nuclear_rod/T = path
metadata["name"] = initial(T.name)
metadata["desc"] = initial(T.desc)
metadata["icon"] = initial(T.icon)
metadata["icon_state"] = initial(T.icon_state)
metadata["type_path"] = path
metadata["max_durability"] = initial(T.max_durability)
metadata["degradation_speed"] = initial(T.degradation_speed)
metadata["heat_amount"] = initial(T.heat_amount)
metadata["heat_amp_mod"] = initial(T.heat_amp_mod)
metadata["power_amount"] = initial(T.power_amount)
metadata["power_amp_mod"] = initial(T.power_amp_mod)
metadata["alpha_rad"] = initial(T.alpha_rad)
metadata["beta_rad"] = initial(T.beta_rad)
metadata["gamma_rad"] = initial(T.gamma_rad)
metadata["minimum_temp_modifier"] = initial(T.minimum_temp_modifier)
metadata["upgrade_required"] = initial(T.upgrade_required)
metadata["required_object"] = initial(T.required_object)
// Temp object lets us read in materials and adjacent requirements because you can't initial() a list
var/obj/item/nuclear_rod/temp_rod = new path()
var/list/raw_materials = temp_rod.materials
var/list/requirements = temp_rod.adjacent_requirements
qdel(temp_rod)
if(raw_materials && length(raw_materials))
var/list/formatted_materials = list()
for(var/mat_id in raw_materials)
var/display_name = CallMaterialName(mat_id)
formatted_materials[display_name] = raw_materials[mat_id]
metadata["materials"] = formatted_materials
else
metadata["materials"] = list()
if(ispath(path, /obj/item/nuclear_rod/fuel))
var/obj/item/nuclear_rod/fuel/F = path
metadata["craftable"] = initial(F.craftable)
metadata["enrichment_cycles"] = initial(F.enrichment_cycles)
metadata["power_enrich_threshold"] = initial(F.power_enrich_threshold)
metadata["heat_enrich_threshold"] = initial(F.heat_enrich_threshold)
// Get enrichment result names
if(initial(F.power_enrich_result))
var/obj/item/nuclear_rod/power_result = initial(F.power_enrich_result)
metadata["power_enrichment"] = initial(power_result.name)
metadata["power_enrichment_requirement"] = initial(F.power_enrich_threshold)
else
metadata["power_enrichment"] = null
metadata["power_enrichment_requirement"] = null
if(initial(F.heat_enrich_result))
var/obj/item/nuclear_rod/heat_result = initial(F.heat_enrich_result)
metadata["heat_enrichment"] = initial(heat_result.name)
metadata["heat_enrichment_requirement"] = initial(F.heat_enrich_threshold)
else
metadata["heat_enrichment"] = null
metadata["heat_enrichment_requirement"] = null
else if(ispath(path, /obj/item/nuclear_rod/moderator))
var/obj/item/nuclear_rod/moderator/M = path
metadata["craftable"] = initial(M.craftable)
else if(ispath(path, /obj/item/nuclear_rod/coolant))
var/obj/item/nuclear_rod/coolant/C = path
metadata["craftable"] = initial(C.craftable)
else
metadata["craftable"] = FALSE
if(requirements && length(requirements))
var/list/temp_reqs = list()
var/list/req_counts = list()
// Count occurrences of each requirement type
for(var/req_path in requirements)
var/obj/item/nuclear_rod/req = req_path
var/req_name = initial(req.name)
if(req_counts[req_name])
req_counts[req_name]++
else
req_counts[req_name] = 1
// Format the requirements with counts
for(var/req_name in req_counts)
var/count = req_counts[req_name]
temp_reqs += "[count]x [req_name]"
metadata["neighbor_requirements"] = temp_reqs
metadata["adjacent_requirements_display"] = english_list(temp_reqs, and_text = ", ")
else
metadata["neighbor_requirements"] = list()
metadata["adjacent_requirements_display"] = "None"
return TRUE

View File

@@ -0,0 +1,140 @@
#define MINIMUM_MOLES 3 //! the minimum amount of moles we transfer, regardless of pressure on the other side.
/obj/machinery/atmospherics/unary/reactor_gas_node
name = "reactor gas intake"
desc = "A sturdy-looking gas inlet that injects gas into the reactor."
icon = 'icons/obj/fission/reactor_machines.dmi'
icon_state = "gas_node"
layer = GAS_PIPE_VISIBLE_LAYER
max_integrity = 2000
target_pressure = 100000 // Maximum pressure in KPA
flags_2 = NO_MALF_EFFECT_2
/// Hold which reactor the intake is connected to.
var/obj/machinery/atmospherics/fission_reactor/linked_reactor
/// Is this vent taking air in or out. TRUE by default.
var/intake_vent = TRUE
/obj/machinery/atmospherics/unary/reactor_gas_node/output
name = "Reactor Gas Extractor"
intake_vent = FALSE
/obj/machinery/atmospherics/unary/reactor_gas_node/Initialize(mapload)
. = ..()
component_parts = list()
component_parts += new /obj/item/circuitboard/machine/reactor_gas_node(src)
component_parts += new /obj/item/stack/sheet/metal(src, 2)
component_parts += new /obj/item/stack/cable_coil(src, 2)
initialize_directions = dir
RefreshParts()
update_icon()
return INITIALIZE_HINT_LATELOAD
// Needs lateload to prevent reactor not being initialized yet and thus not able to set the link.
/obj/machinery/atmospherics/unary/reactor_gas_node/LateInitialize()
. = ..()
form_link(TRUE)
/obj/machinery/atmospherics/unary/reactor_gas_node/examine(mob/user)
. = ..()
. += SPAN_NOTICE("A wrench can be used to alter the direction of the node.")
. += SPAN_NOTICE("Gas nodes will only link with reactors when facing a reactor from the side opposite of the inlet pipe.")
/obj/machinery/atmospherics/unary/reactor_gas_node/process_atmos()
if(stat & (NOPOWER|BROKEN))
return FALSE
if(!linked_reactor)
return FALSE
if(linked_reactor.admin_intervention)
return FALSE
if(linked_reactor.safety_override) // We dont want to cool down an intentional runaway reactor
return FALSE
var/datum/gas_mixture/network1
var/datum/gas_mixture/network2
if(intake_vent)
network1 = linked_reactor.air_contents
network2 = air_contents
else
network1 = air_contents
network2 = linked_reactor.air_contents
if(!network1 || !network2)
return FALSE
// This is basically passive gate code
var/output_starting_pressure = network1.return_pressure()
var/input_starting_pressure = network2.return_pressure()
// Calculate necessary moles to transfer using PV = nRT
if((network2.total_moles() > 0) && (network2.temperature() > 0))
var/pressure_delta = min(target_pressure - output_starting_pressure, (input_starting_pressure - output_starting_pressure) / 2)
if(intake_vent)
pressure_delta = max(pressure_delta, MINIMUM_MOLES) // Always work at least a little bit when inputting gas
var/transfer_moles = pressure_delta * network1.volume / (network2.temperature() * R_IDEAL_GAS_EQUATION)
// Actually transfer the gas
var/datum/gas_mixture/removed = network2.remove(transfer_moles)
network1.merge(removed)
parent.update = TRUE
return TRUE
/obj/machinery/atmospherics/unary/reactor_gas_node/screwdriver_act(mob/living/user, obj/item/I)
default_deconstruction_screwdriver(user, icon_state, icon_state, I)
/obj/machinery/atmospherics/unary/reactor_gas_node/crowbar_act(mob/living/user, obj/item/I)
to_chat(user, SPAN_INFORMATION("You begin to pry out the internal piping..."))
if(I.use_tool(src, user, 3 SECONDS, volume = I.tool_volume))
default_deconstruction_crowbar(user, I)
/obj/machinery/atmospherics/unary/reactor_gas_node/wrench_act(mob/user, obj/item/I)
var/list/choices = list("West" = WEST, "East" = EAST, "South" = SOUTH, "North" = NORTH)
var/selected = tgui_input_list(user, "Select a direction for the connector.", "Connector Direction", choices)
if(!selected)
return ITEM_INTERACT_COMPLETE
if(!I.use_tool(src, user, 3 SECONDS, volume = I.tool_volume))
return ITEM_INTERACT_COMPLETE
if(!Adjacent(user))
to_chat(user, SPAN_WARNING("You moved away before construction was finished!"))
return ITEM_INTERACT_COMPLETE
dir = choices[selected]
initialize_directions = dir
for(var/obj/machinery/atmospherics/target in get_step(src, dir))
if(target.initialize_directions & get_dir(target,src))
node = target
break
form_link(FALSE)
initialize_atmos_network()
update_icon()
return ITEM_INTERACT_COMPLETE
/obj/machinery/atmospherics/unary/reactor_gas_node/proc/form_link(silent = FALSE)
linked_reactor = null
var/turf/T = get_step(src, REVERSE_DIR(dir))
for(var/obj/machinery/atmospherics/fission_reactor/reactor in T)
linked_reactor = reactor
for(var/obj/structure/filler/filler in T)
if(istype(filler.parent, /obj/machinery/atmospherics/fission_reactor))
linked_reactor = filler.parent
if(silent)
return
if(!linked_reactor)
playsound(src, 'sound/machines/buzz-sigh.ogg', 30, TRUE)
audible_message(SPAN_INFO("The gas node buzzes as it fails to connect to a reactor."))
else
playsound(src, 'sound/machines/ping.ogg', 30, TRUE)
audible_message(SPAN_INFO("The gas node pings as it connects to the reactor."))
/obj/machinery/atmospherics/unary/reactor_gas_node/multitool_act(mob/living/user, obj/item/I)
to_chat(user, SPAN_INFORMATION("You begin to reverse the gas flow direction..."))
if(do_after_once(user, 1 SECONDS, TRUE, src, allow_moving = FALSE))
intake_vent = !intake_vent
if(intake_vent)
name = "Reactor Gas Intake"
else
name = "Reactor Gas Extractor"
return ..()
#undef MINIMUM_MOLES

View File

@@ -0,0 +1,398 @@
// MARK: Reactor Power Output
/obj/machinery/power/reactor_power
name = "reactor output terminal"
desc = "A bundle of heavy watt power cables for managing power output from the reactor."
icon_state = "term"
plane = FLOOR_PLANE
layer = WIRE_TERMINAL_LAYER // A bit above wires
resistance_flags = INDESTRUCTIBLE
var/obj/machinery/atmospherics/fission_reactor/linked_reactor
/obj/machinery/power/reactor_power/Initialize(mapload)
. = ..()
return INITIALIZE_HINT_LATELOAD
// Needs lateload to prevent reactor not being initialized yet and thus not able to set the link.
/obj/machinery/power/reactor_power/LateInitialize()
. = ..()
linked_reactor = GLOB.main_fission_reactor
/obj/machinery/power/reactor_power/process()
if(linked_reactor && linked_reactor.can_create_power)
produce_direct_power(linked_reactor.final_power)
// MARK: Monitor
/obj/machinery/computer/fission_monitor
name = "NGCR monitoring console"
desc = "Used to monitor the Nanotrasen Gas Cooled Fission Reactor."
icon_keyboard = "power_key"
icon_screen = "smmon_0"
circuit = /obj/item/circuitboard/fission_monitor
light_color = LIGHT_COLOR_YELLOW
/// Last status of the active reactor for caching purposes
var/last_status
/// Reference to the active reactor
var/obj/machinery/atmospherics/fission_reactor/active
/// Is this monitor a controller? Affected by visibility from the reactor
var/controller = TRUE
/obj/machinery/computer/fission_monitor/Initialize(mapload)
. = ..()
return INITIALIZE_HINT_LATELOAD
/obj/machinery/computer/fission_monitor/LateInitialize()
. = ..()
active = GLOB.main_fission_reactor
determine_control()
/obj/machinery/computer/fission_monitor/Destroy()
active = null
return ..()
// This can normally never happen, but just in case.
/obj/machinery/computer/fission_monitor/Moved(atom/old_loc, movement_dir, forced, list/old_locs, momentum_change)
. = ..()
determine_control()
/obj/machinery/computer/fission_monitor/proc/determine_control()
if(!active)
return
if(active in oview(12, src))
controller = TRUE
else
controller = FALSE
/obj/machinery/computer/fission_monitor/attack_ai(mob/user)
attack_hand(user)
/obj/machinery/computer/fission_monitor/attack_hand(mob/user)
add_fingerprint(user)
if(stat & (BROKEN|NOPOWER))
return
ui_interact(user)
/obj/machinery/computer/fission_monitor/ui_state(mob/user)
return GLOB.default_state
/obj/machinery/computer/fission_monitor/process()
if(stat & (NOPOWER|BROKEN))
return FALSE
if(active)
var/new_status = active.get_status()
if(last_status != new_status)
last_status = new_status
icon_screen = "smmon_[last_status]"
update_icon()
return TRUE
/obj/machinery/computer/fission_monitor/multitool_act(mob/living/user, obj/item/I)
if(!I.multitool_check_buffer(user))
return
var/obj/item/multitool/multitool = I
if(istype(multitool.buffer, /obj/machinery/atmospherics/fission_reactor))
active = multitool.buffer
to_chat(user, SPAN_NOTICE("You load the buffer's linking data to [src]."))
/obj/machinery/computer/fission_monitor/ui_interact(mob/user, datum/tgui/ui = null)
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
ui = new(user, src, "ReactorMonitor", name)
ui.open()
return TRUE
/obj/machinery/computer/fission_monitor/ui_data(mob/user)
var/list/data = list()
// If we somehow dont have an engine anymore, handle it here.
if(!active)
return
if(active.stat & BROKEN)
active = null
return
var/datum/gas_mixture/air = active.air_contents
var/power_kilowatts = round((active.final_power / 1000), 1)
data["venting"] = active.venting
data["NGCR_integrity"] = active.get_integrity()
data["NGCR_power"] = power_kilowatts
data["NGCR_ambienttemp"] = air.temperature()
data["NGCR_ambientpressure"] = air.return_pressure()
data["NGCR_coefficient"] = active.reactivity_multiplier
if(active.control_lockout)
data["NGCR_throttle"] = 0
else
data["NGCR_throttle"] = 100 - active.desired_power
data["NGCR_operatingpower"] = 100 - active.operating_power
var/list/gasdata = list()
var/TM = air.total_moles()
if(TM)
gasdata.Add(list(list("name" = "Oxygen", "amount" = air.oxygen(), "portion" = round(100 * air.oxygen() / TM, 0.01))))
gasdata.Add(list(list("name" = "Carbon Dioxide", "amount" = air.carbon_dioxide(), "portion" = round(100 * air.carbon_dioxide() / TM, 0.01))))
gasdata.Add(list(list("name" = "Nitrogen", "amount" = air.nitrogen(), "portion" = round(100 * air.nitrogen() / TM, 0.01))))
gasdata.Add(list(list("name" = "Plasma", "amount" = air.toxins(), "portion" = round(100 * air.toxins() / TM, 0.01))))
gasdata.Add(list(list("name" = "Nitrous Oxide", "amount" = air.sleeping_agent(), "portion" = round(100 * air.sleeping_agent() / TM, 0.01))))
gasdata.Add(list(list("name" = "Agent B", "amount" = air.agent_b(), "portion" = round(100 * air.agent_b() / TM, 0.01))))
gasdata.Add(list(list("name" = "Hydrogen", "amount" = air.hydrogen(), "portion" = round(100 * air.hydrogen() / TM, 0.01))))
gasdata.Add(list(list("name" = "Water Vapor", "amount" = air.water_vapor(), "portion" = round(100 * air.water_vapor() / TM, 0.01))))
else
gasdata.Add(list(list("name" = "Oxygen", "amount" = 0, "portion" = 0)))
gasdata.Add(list(list("name" = "Carbon Dioxide", "amount" = 0,"portion" = 0)))
gasdata.Add(list(list("name" = "Nitrogen", "amount" = 0,"portion" = 0)))
gasdata.Add(list(list("name" = "Plasma", "amount" = 0,"portion" = 0)))
gasdata.Add(list(list("name" = "Nitrous Oxide", "amount" = 0,"portion" = 0)))
gasdata.Add(list(list("name" = "Agent B", "amount" = 0,"portion" = 0)))
gasdata.Add(list(list("name" = "Hydrogen", "amount" = 0,"portion" = 0)))
gasdata.Add(list(list("name" = "Water Vapor", "amount" = 0,"portion" = 0)))
data["gases"] = gasdata
data["controlling"] = controller
return data
/obj/machinery/computer/fission_monitor/ui_act(action, list/params, datum/tgui/ui, datum/ui_state/state)
if(..())
return
if(stat & (BROKEN|NOPOWER))
return
if(action == "set_throttle")
if(!controller)
visible_message(SPAN_WARNING("Error: Reactor is out of sight from laser guidance control."))
playsound(src, 'sound/machines/buzz-sigh.ogg', 50, TRUE)
return
var/temp_number = text2num(params["NGCR_throttle"])
active.desired_power = 100 - temp_number
if(action == "toggle_vent")
if(!controller)
visible_message(SPAN_WARNING("Error: Reactor is out of sight from laser guidance control."))
playsound(src, 'sound/machines/buzz-sigh.ogg', 50, TRUE)
return
if(active.vent_lockout)
playsound(src, 'sound/machines/buzz-sigh.ogg', 50, TRUE)
visible_message(SPAN_WARNING("ERROR: Vent servos unresponsive. Manual closure required."))
else
active.venting = !active.venting
// MARK: Slag
/obj/item/slag
name = "corium slag"
desc = "A large clump of active nuclear fuel fused with structural reactor metals."
icon = 'icons/effects/effects.dmi'
icon_state = "big_molten"
move_resist = MOVE_FORCE_STRONG // Massive chunk of metal slag, shouldnt be moving it without carrying.
w_class = WEIGHT_CLASS_HUGE
force = 15
throwforce = 10
/obj/item/slag/Initialize(mapload)
. = ..()
scatter_atom()
var/datum/component/inherent_radioactivity/rad_component = AddComponent(/datum/component/inherent_radioactivity, 5000, 5000, 5000, 2)
START_PROCESSING(SSradiation, rad_component)
START_PROCESSING(SSprocessing, src)
/obj/item/slag/process()
. = ..()
radiation_pulse(src, 500, ALPHA_RAD)
radiation_pulse(src, 500, BETA_RAD)
radiation_pulse(src, 500, GAMMA_RAD)
// MARK: Starter Grenade
/obj/item/grenade/nuclear_starter
name = "Neutronic Agitator"
desc = "A throwable device capable of inducing an artificial startup in rod chambers. Won't do anything for chambers not positioned correctly, or chambers without any rods inserted."
/obj/item/grenade/nuclear_starter/deconstruct(disassembled)
qdel(src)
/obj/item/grenade/nuclear_starter/prime()
playsound(src.loc, 'sound/weapons/bsg_explode.ogg', 50, TRUE, -3)
var/obj/effect/temp_visual/neutronic/warp = new(loc)
warp.pixel_x += 16
warp.pixel_y += 16
warp.transform = matrix().Scale(0.01, 0.01)
animate(warp, time = 0.5 SECONDS, transform = matrix().Scale(1, 1))
var/list/chamber_list = list()
for(var/obj/machinery/atmospherics/reactor_chamber/chamber in range(3, loc))
chamber_list += chamber
for(var/obj/machinery/atmospherics/reactor_chamber/chamber in chamber_list)
if(chamber.chamber_state == CHAMBER_DOWN && chamber.held_rod)
chamber.operational = TRUE
chamber.update_icon(UPDATE_OVERLAYS)
for(var/obj/machinery/atmospherics/reactor_chamber/chamber in chamber_list)
if(chamber.check_status())
chamber.requirements_met = TRUE
else
chamber.requirements_met = FALSE
chamber.update_icon(UPDATE_OVERLAYS)
qdel(src)
/obj/effect/temp_visual/neutronic
icon = 'icons/effects/light_352.dmi'
icon_state = "light"
plane = GRAVITY_PULSE_PLANE
appearance_flags = PIXEL_SCALE|LONG_GLIDE
duration = 0.5 SECONDS
pixel_x = -176
pixel_y = -176
// MARK: Rad Proof Pool
/turf/simulated/floor/plasteel/reactor_pool
name = "holding pool"
icon = 'icons/obj/fission/pool.dmi'
icon_state = "pool_round"
footstep = FOOTSTEP_WATER
barefootstep = FOOTSTEP_WATER
clawfootstep = FOOTSTEP_WATER
heavyfootstep = FOOTSTEP_WATER
/// Holds our pool controller
var/obj/machinery/poolcontroller/linkedcontroller
/// Holds our effect overlay
var/obj/item/effect/pool_overlay/effect
/turf/simulated/floor/plasteel/reactor_pool/Initialize(mapload)
. = ..()
RegisterSignal(src, COMSIG_ATOM_INITIALIZED_ON, PROC_REF(initialized_on))
return INITIALIZE_HINT_LATELOAD
/turf/simulated/floor/plasteel/reactor_pool/LateInitialize()
. = ..()
effect = new(src)
/turf/simulated/floor/plasteel/reactor_pool/crowbar_act(mob/user, obj/item/I)
return
/turf/simulated/floor/plasteel/reactor_pool/proc/initialized_on(atom/A)
SIGNAL_HANDLER // COMSIG_ATOM_INITIALIZED_ON
if(!linkedcontroller)
return
if(istype(A, /obj/effect/decal/cleanable)) // Better a typecheck than looping through thousands of turfs everyday
linkedcontroller.decalinpool += A
/turf/simulated/floor/plasteel/reactor_pool/Entered(atom/movable/AM, atom/OldLoc)
. = ..()
if(!linkedcontroller)
return
if(ismob(AM))
linkedcontroller.mobinpool += AM
/turf/simulated/floor/plasteel/reactor_pool/Exited(atom/movable/AM, direction)
. = ..()
if(!linkedcontroller)
return
if(ismob(AM))
linkedcontroller.mobinpool -= AM
/turf/simulated/floor/plasteel/reactor_pool/ChangeTurf(turf/simulated/floor/T, defer_change, keep_icon, ignore_air, copy_existing_baseturf)
QDEL_NULL(effect)
. = ..()
/turf/simulated/floor/plasteel/reactor_pool/Destroy()
QDEL_NULL(effect)
. = ..()
/turf/simulated/floor/plasteel/reactor_pool/wall
icon_state = "pool_wall_round"
/turf/simulated/floor/plasteel/reactor_pool/wall/ladder
icon_state = "ladder_wall_round"
/turf/simulated/floor/plasteel/reactor_pool/wall/filter
icon_state = "filter_wall_round"
/turf/simulated/floor/plasteel/reactor_pool/square
icon_state = "pool_sharp_square"
/obj/structure/railing/pool_lining
name = "pool lining"
icon = 'icons/obj/fission/pool.dmi'
icon_state = "poolborder"
flags = ON_BORDER | NODECONSTRUCT | INDESTRUCTIBLE
max_integrity = 200
/obj/structure/railing/pool_lining/ex_act(severity)
if(severity == EXPLODE_HEAVY || severity == EXPLODE_DEVASTATE)
qdel(src)
/obj/item/effect/pool_overlay
name = "holding pool"
desc = "water"
icon = 'icons/misc/beach.dmi'
icon_state = "seadeep"
alpha = 75
layer = ABOVE_ALL_MOB_LAYER
mouse_opacity = MOUSE_OPACITY_TRANSPARENT
anchored = TRUE
/obj/structure/railing/corner/pool_corner
name = "pool lining"
icon = 'icons/obj/fission/pool.dmi'
icon_state = "bordercorner"
/obj/structure/railing/corner/pool_corner/inner
icon_state = "innercorner"
/obj/machinery/poolcontroller/invisible/nuclear
srange = 6
deep_water = TRUE
/obj/machinery/poolcontroller/invisible/nuclear/Initialize(mapload)
var/contents_loop = linked_area
if(!linked_area)
contents_loop = range(srange, src)
for(var/turf/simulated/floor/plasteel/reactor_pool/T in contents_loop)
T.linkedcontroller = src
linkedturfs += T
return ..()
/obj/machinery/poolcontroller/invisible/nuclear/Destroy()
for(var/turf/simulated/floor/plasteel/reactor_pool/W in linkedturfs)
if(W.linkedcontroller == src)
W.linkedcontroller = null
return ..()
/obj/machinery/poolcontroller/invisible/nuclear/processMob()
for(var/mob/M in mobinpool)
if(!istype(get_turf(M), /turf/simulated/floor/plasteel/reactor_pool))
mobinpool -= M
continue
M.clean_blood(radiation_clean = TRUE)
if(isliving(M))
var/mob/living/L = M
L.ExtinguishMob()
L.adjust_fire_stacks(-20) //Douse ourselves with water to avoid fire more easily
if(ishuman(M))
handleDrowning(M)
// MARK: Fab upgrade
/obj/item/rod_fabricator_upgrade
name = "Nuclear Fabricator Upgrade"
desc = "A design disk containing a dizzying amount of designs and improvements for nuclear rod fabrication."
icon = 'icons/obj/module.dmi'
icon_state = "datadisk5"
drop_sound = 'sound/items/handling/disk_drop.ogg'
pickup_sound = 'sound/items/handling/disk_pickup.ogg'
new_attack_chain = TRUE
// MARK: Chamber Doors
/obj/effect/temp_visual/chamber_closing
icon = 'icons/obj/fission/reactor_chamber.dmi'
icon_state = "doors_closing"
duration = 0.7 SECONDS
layer = ABOVE_ALL_MOB_LAYER + 0.03

View File

@@ -0,0 +1,546 @@
/obj/item/nuclear_rod
name = "Nuclear Control Rod"
desc = ABSTRACT_TYPE_DESC
icon = 'icons/obj/fission/reactor_rods.dmi'
icon_state = "fuel_238"
resistance_flags = LAVA_PROOF | FIRE_PROOF | UNACIDABLE
w_class = WEIGHT_CLASS_HUGE
force = 15
throwforce = 10
/// The path of the object required to fabricate this rod. leave null for nothing
var/required_object
/// How much durability is left before the rod is useless
var/durability
/// The maximum amount of durability for this rod. Used for percentage calculations
var/max_durability = 3000
/// How fast does this rod degrade? higher = faster
var/degradation_speed = 1
/// How much heat does this rod add by default
var/heat_amount = 0
/// How does this rod affect its neighbors heating
var/heat_amp_mod = 1
/// Holds the current heat mod after durability loss
var/current_heat_mod
/// How much power does this rod add by default in watts
var/power_amount = 0
/// How does this rod affect its neighbors power production
var/power_amp_mod = 1
/// Holds the current power mod after durability loss
var/current_power_mod
/// How much Alpha Rad is emitted by this rod
var/alpha_rad = 0
/// How much Beta Rad is emitted by this rod
var/beta_rad = 0
/// How much Gamma Rad is emitted by this rod
var/gamma_rad = 0
/// What items need to be adjacent to this rod for it to function properly
var/list/adjacent_requirements = list()
/// Modifies the reactor's minimum operating temperature.
var/minimum_temp_modifier = 0
/// Modified the reactor's overheat threshold
var/reactor_overheat_modifier = 0
/// holds our component to modify
var/datum/component/inherent_radioactivity/rad_component
/// Is this rod craftable at all via fabricators, or do they require other means?
var/craftable = FALSE
/// Does this rod require a science-upgraded fabricator?
var/upgrade_required = FALSE
/obj/item/nuclear_rod/Initialize(mapload)
. = ..()
durability = max_durability
/obj/item/nuclear_rod/examine(mob/user)
. = ..()
if(length(adjacent_requirements))
var/list/templist = list()
for(var/obj/item/nuclear_rod/requirement as anything in adjacent_requirements)
templist += initial(requirement.name)
var/requirement_list = english_list(templist, and_text = ", ")
. += "This rod has the following neighbor requirements: [requirement_list]"
else
. += "This rod has no neighbor requirements."
/obj/item/nuclear_rod/proc/get_durability_mod()
var/temp_mod
temp_mod = clamp(1.5 * (durability / max_durability) - 0.25, 0.25, 1)
return temp_mod
/obj/item/nuclear_rod/proc/calc_stat_decrease()
// Formula: y = (x * A) + (1 - A)
var/durability_stat = get_durability_mod()
current_power_mod = (power_amp_mod * durability_stat) + (1 - durability_stat)
current_heat_mod = (heat_amp_mod * durability_stat) + (1 - durability_stat)
/obj/item/nuclear_rod/proc/start_rads(power_modifier = 1)
var/new_alpha_rad = alpha_rad * power_modifier
var/new_beta_rad = beta_rad * power_modifier
var/new_gamma_rad = gamma_rad * power_modifier
rad_component = AddComponent(/datum/component/inherent_radioactivity, new_alpha_rad, new_beta_rad, new_gamma_rad, 1)
START_PROCESSING(SSradiation, rad_component)
/obj/item/nuclear_rod/proc/stop_rads()
if(!rad_component)
return
rad_component.RemoveComponent()
QDEL_NULL(rad_component)
/obj/item/nuclear_rod/proc/change_rad_intensity(power_modifier = 1)
rad_component.radioactivity_alpha = alpha_rad * power_modifier
rad_component.radioactivity_beta = beta_rad * power_modifier
rad_component.radioactivity_gamma = gamma_rad * power_modifier
/obj/item/nuclear_rod/proc/check_rad_shield()
var/turf/T = get_turf(src)
if(!T || !loc)
stop_rads()
return
if(istype(T, /turf/simulated/floor/plasteel/reactor_pool))
if(!rad_component)
return
else
stop_rads()
else if(istype(loc, /obj/machinery/atmospherics/reactor_chamber))
stop_rads()
else if(!rad_component)
start_rads()
/obj/item/nuclear_rod/Moved(atom/old_loc, movement_dir, forced, list/old_locs, momentum_change)
. = ..()
check_rad_shield()
/obj/item/nuclear_rod/fuel
name = "any fuel rod"
alpha_rad = 50
/// the amount of cycles needed to complete enrichment. 30 = ~1 minute
var/enrichment_cycles = 25
/// the total power amp mod needed to enrich
var/power_enrich_threshold = 0
/// How far we have progressed from to power enrichment
var/power_enrich_progress = 0
/// What power enrichment results in
var/power_enrich_result
/// the total heat amp mod needed to enrich
var/heat_enrich_threshold = 0
/// How far we have progressed from to power enrichment
var/heat_enrich_progress = 0
/// What heat enrichment results in
var/heat_enrich_result
/obj/item/nuclear_rod/fuel/Initialize(mapload)
. = ..()
if(!istype(loc, /obj/structure/closet/crate))
check_rad_shield()
/obj/item/nuclear_rod/fuel/proc/enrich(power_mod, heat_mod)
var/successful_enrichment = FALSE
if(power_enrich_result)
if(power_mod > power_enrich_threshold && power_enrich_progress < enrichment_cycles)
power_enrich_progress++
successful_enrichment = TRUE
if(heat_enrich_result)
if(heat_mod > heat_enrich_threshold && heat_enrich_progress < enrichment_cycles)
heat_enrich_progress++
successful_enrichment = TRUE
return successful_enrichment
// MARK: Fuel Rods
/obj/item/nuclear_rod/fuel/uranium_238
name = "uranium 238 fuel rod"
desc = "A standard fuel rod for most NGCR reactors. Has just barely enough Uranium 235 to be useful."
heat_amount = 5
power_amount = 20 KW
heat_amp_mod = 1.8
power_amp_mod = 1.1
alpha_rad = 200
beta_rad = 100
heat_enrich_threshold = 10 // all uranium rods surrounding: 1.8 x 1.8 x 1.8 x 1.8
power_enrich_threshold = 6.4 // all graphite rods surrounding: 1.6 x 1.6 x 1.6 x 1.6
heat_enrich_result = /obj/item/nuclear_rod/fuel/weak_thorium
power_enrich_result = /obj/item/nuclear_rod/fuel/weak_plutonium
adjacent_requirements = list(/obj/item/nuclear_rod/moderator)
craftable = TRUE
materials = list(MAT_METAL = 2000, MAT_URANIUM = 1000)
/obj/item/nuclear_rod/fuel/weak_thorium
name = "weak thorium fuel rod"
desc = "A specialized fuel rod refined from uranium 238. This rod will last longer than normal, and won't generate as much heat."
icon_state = "fuel_weakthor"
heat_amount = 5
power_amount = 20 KW
heat_amp_mod = 1.6
power_amp_mod = 1.1
max_durability = 5000
beta_rad = 100
gamma_rad = 100
power_enrich_threshold = 8
power_enrich_result = /obj/item/nuclear_rod/fuel/uranium_235
adjacent_requirements = list(
/obj/item/nuclear_rod/moderator,
/obj/item/nuclear_rod/coolant,
)
/obj/item/nuclear_rod/fuel/weak_plutonium
name = "weak plutonium fuel rod"
desc = "A specialized fuel rod refined from uranium 238. This rod produces twice as much power as standard uranium 238 fuel, but has higher operating requirements."
icon_state = "fuel_weakplut"
heat_amount = 10
power_amount = 40 KW
heat_amp_mod = 1.6
power_amp_mod = 1.1
max_durability = 3500
gamma_rad = 100
heat_enrich_threshold = 14
heat_enrich_result = /obj/item/nuclear_rod/fuel/uranium_235
adjacent_requirements = list(
/obj/item/nuclear_rod/fuel,
/obj/item/nuclear_rod/moderator,
/obj/item/nuclear_rod/coolant,
)
/obj/item/nuclear_rod/fuel/uranium_235
name = "uranium 235 fuel rod"
desc = "An advanced fuel rod for most NGCR reactors, formed from high-density uranium 235 isotopes."
icon_state = "fuel_235"
heat_amount = 20
power_amount = 50 KW
heat_amp_mod = 2.2
power_amp_mod = 1.3
max_durability = 5000
alpha_rad = 150
beta_rad = 100
heat_enrich_threshold = 25
power_enrich_threshold = 18
heat_enrich_result = /obj/item/nuclear_rod/fuel/thorium_salts
power_enrich_result = /obj/item/nuclear_rod/fuel/enriched_plutonium
origin_tech = "toxins=2"
craftable = TRUE
upgrade_required = TRUE
adjacent_requirements = list(
/obj/item/nuclear_rod/coolant/plasma_injector,
/obj/item/nuclear_rod/moderator,
/obj/item/nuclear_rod/moderator,
)
materials = list(MAT_METAL = 4000, MAT_URANIUM = 4000)
/obj/item/nuclear_rod/fuel/thorium_salts
name = "thorium salts fuel rod"
desc = "A specialized fuel rod refined from uranium 235. While this rod doesn't have any notable power boosts, its amazingly large integrity makes it virtually impossible to deplete in a single shift, if one can manage its heat."
icon_state = "fuel_richthor"
heat_amount = 40
power_amount = 35 KW
heat_amp_mod = 2.2
power_amp_mod = 1.3
max_durability = 15000
beta_rad = 250
adjacent_requirements = list(
/obj/item/nuclear_rod/moderator,
/obj/item/nuclear_rod/fuel/uranium_235,
/obj/item/nuclear_rod/fuel,
)
/obj/item/nuclear_rod/fuel/enriched_plutonium
name = "enriched plutonium fuel rod"
desc = "A specialized fuel rod refined from uranium 235. This rod is extremely powerful, boasting high power outputs and moderate durability. However, its heat presents an exceptional danger."
icon_state = "fuel_richplut"
heat_amount = 60
power_amount = 75 KW
heat_amp_mod = 4
power_amp_mod = 1.6
max_durability = 5000
beta_rad = 250
power_enrich_threshold = 25
power_enrich_result = /obj/item/nuclear_rod/fuel/americium
adjacent_requirements = list(
/obj/item/nuclear_rod/moderator/plasma_agitator,
/obj/item/nuclear_rod/fuel/thorium_salts,
)
/obj/item/nuclear_rod/fuel/supermatter
name = "supermatter fuel rod"
desc = "A dangerous fuel rod made entirely of supermatter, contained safely in a specialized housing case. Due to its unusual properties, it completely neutralizes any potential power from nearby rods."
icon_state = "fuel_sm"
heat_amount = 1200
power_amount = 800 KW
heat_amp_mod = 8
power_amp_mod = 0.1
max_durability = INFINITY
gamma_rad = 300
adjacent_requirements = list(
/obj/item/nuclear_rod/coolant/steam_hammerjet,
/obj/item/nuclear_rod/fuel,
/obj/item/nuclear_rod/moderator,
)
/obj/item/nuclear_rod/fuel/americium
name = "americium fuel rod"
desc = "A specialized fuel rod refined from enriched plutonium. A pinnacle of power generation, this rod's power generation is nearly unmatched if one can tame its vicious heat output."
icon_state = "fuel_americium"
heat_amount = 100
power_amount = 200 KW
heat_amp_mod = 6
power_amp_mod = 1.6
max_durability = 4000
gamma_rad = 300
adjacent_requirements = list(
/obj/item/nuclear_rod/fuel,
/obj/item/nuclear_rod/fuel,
)
/obj/item/nuclear_rod/fuel/bananium
name = "bananium fuel rod"
desc = "The funniest of all fuel rods with no solidified properties. Who knows what you might get out of it!"
icon_state = "fuel_clown"
gamma_rad = 300
craftable = TRUE
upgrade_required = TRUE
materials = list(MAT_TITANIUM = 2000, MAT_BANANIUM = 2000)
/obj/item/nuclear_rod/fuel/bananium/Initialize(mapload)
max_durability = rand(1000, 10000)
power_amp_mod = rand(1, 40) / 10
heat_amp_mod = rand(5, 80) / 10
power_amount = rand(10 KW, 200 KW)
heat_amount = rand(10, 500)
return ..()
/obj/item/nuclear_rod/fuel/meltdown
name = "meltdown rod"
desc = "A Syndicate-crafted rod capable of generating massive amounts of heat, leading to an eventual meltdown."
icon_state = "fuel_syndie"
heat_amount = 2000
max_durability = INFINITY
minimum_temp_modifier = 4000 // BIG hot
reactor_overheat_modifier = -400
alpha_rad = 250
beta_rad = 250
gamma_rad = 250
// MARK: Moderator Rods
/obj/item/nuclear_rod/moderator
name = "any moderator rod"
icon_state = "mod_water"
/obj/item/nuclear_rod/moderator/heavy_water
name = "heavy water moderator"
desc = "A basic moderation rod filled with a variant of water comprised of deuterium instead of hydrogen atoms."
heat_amp_mod = 1.1
power_amp_mod = 1.4
craftable = TRUE
materials = list(MAT_METAL = 2000, MAT_GLASS = 1000)
/obj/item/nuclear_rod/moderator/graphite
name = "graphite moderator"
desc = "A nuclear moderation rod comprised primarily of layered graphite. A staple of fission reactor operation through the ages."
icon_state = "mod_graphite"
heat_amp_mod = 1.3
power_amp_mod = 1.6
craftable = TRUE
materials = list(MAT_METAL = 4000, MAT_PLASMA = 2000)
adjacent_requirements = list(/obj/item/nuclear_rod/coolant)
/obj/item/nuclear_rod/moderator/titanium
name = "titanium moderator"
desc = "A nuclear moderation rod comprised primarily of cast titanium. For what it lacks in power amplification, it makes up for in versatility and durability."
icon_state = "mod_titanium"
max_durability = 5000
heat_amp_mod = 1.1
power_amp_mod = 1.3
craftable = TRUE
materials = list(MAT_METAL = 2000, MAT_TITANIUM = 2000)
/obj/item/nuclear_rod/moderator/plasma_agitator
name = "plasma agitator"
desc = "A specialized moderator rod capable of inducing higher fission rates in fuel rods through a series of micro-burns. It doesn't last long."
icon_state = "mod_plasma"
max_durability = 2250
heat_amount = 20
heat_amp_mod = 5
power_amp_mod = 3
adjacent_requirements = list(
/obj/item/nuclear_rod/fuel,
/obj/item/nuclear_rod/fuel,
/obj/item/nuclear_rod/moderator,
)
/obj/item/nuclear_rod/moderator/aluminum_reflector
name = "liquid aluminum plate reflector"
desc = "A specialized moderator rod for amplifying the power output of nearby fuel rods. However, the temperature of the liquid aluminum will force the reactor to run hot."
icon_state = "mod_aluminium"
max_durability = 6000
power_amount = -15 KW
heat_amp_mod = 5
power_amp_mod = 3
minimum_temp_modifier = 400
reactor_overheat_modifier = 100
adjacent_requirements = list(
/obj/item/nuclear_rod/coolant/nitrogen_circulator,
/obj/item/nuclear_rod/moderator,
)
/obj/item/nuclear_rod/moderator/bluespace_agitator
name = "bluespace crystal agitator"
desc = "An advanced moderator rod that will pull extra neutrons out of bluespace to bombard local fuel rods. The result is a massive increase of power and heat generation. It is exceptionally versatile; however, its power requirements limit its uses."
icon_state = "mod_bluespace"
max_durability = 4000
power_amount = -30 KW
heat_amp_mod = 12
power_amp_mod = 5
upgrade_required = TRUE
craftable = TRUE
materials = list(MAT_METAL = 2000, MAT_TITANIUM = 1000, MAT_BLUESPACE = 1000)
/obj/item/nuclear_rod/moderator/diamond_plate
name = "diamond reflector plates"
desc = "An advanced moderator rod that can reflect nearly all neutrons back to their point of origin. Simple, stable, reliable."
icon_state = "mod_diamond"
max_durability = 6000
heat_amp_mod = 6.5
power_amp_mod = 3.3
reactor_overheat_modifier = 100
craftable = TRUE
upgrade_required = TRUE
materials = list(MAT_METAL = 2000, MAT_TITANIUM = 1000, MAT_DIAMOND = 1000)
adjacent_requirements = list(
/obj/item/nuclear_rod/fuel,
/obj/item/nuclear_rod/fuel,
/obj/item/nuclear_rod/fuel,
)
/obj/item/nuclear_rod/moderator/platinum_plating
name = "platinum reflector plating"
desc = "An advanced moderator similar to diamond plates, but improved with precious space metals."
icon_state = "mod_platinum"
max_durability = 8000
heat_amp_mod = 8
power_amp_mod = 3.9
reactor_overheat_modifier = 300
adjacent_requirements = list(/obj/item/nuclear_rod/fuel/americium)
/// MARK: Coolant Rods
/obj/item/nuclear_rod/coolant
name = "any coolant rod"
icon_state = "coolant_water"
/obj/item/nuclear_rod/coolant/light_water
name = "light water circulator"
desc = "A basic coolant rod that circulates distilled water through critical reactor components."
heat_amount = -10
power_amount = -10 KW
reactor_overheat_modifier = 25
craftable = TRUE
adjacent_requirements = list(/obj/item/nuclear_rod/moderator)
materials = list(MAT_METAL = 2000, MAT_GLASS = 1000)
/obj/item/nuclear_rod/coolant/co2_regulator
name = "carbon dioxide regulator"
desc = "A specialized coolant rod filled with carbon dioxide gas, capable of regulating temperature spikes in fuel rods. However, it's very energy inefficient."
icon_state = "coolant_carbon"
heat_amount = -4
heat_amp_mod = 0.6
power_amount = -15 KW
craftable = TRUE
adjacent_requirements = list(/obj/item/nuclear_rod/moderator)
materials = list(MAT_METAL = 2000, MAT_PLASMA = 2000, MAT_GLASS = 1000)
/obj/item/nuclear_rod/coolant/plasma_injector
name = "plasma injector"
desc = "A specialized coolant rod filled with gaseous plasma. By taking advantage of plasma's unique heat-absorbent properties, small amounts injected around fuel rods neutralize excess heat. However, the tank runs out quickly this way."
icon_state = "coolant_plasma"
max_durability = 1900
heat_amp_mod = 0.5
power_amp_mod = 1.5
craftable = TRUE
adjacent_requirements = list(/obj/item/nuclear_rod/coolant)
materials = list(MAT_METAL = 2000, MAT_PLASMA = 2000, MAT_GLASS = 1000)
/obj/item/nuclear_rod/coolant/nitrogen_circulator
name = "nitrogen circulator"
desc = "A specialized coolant rod filled with nitrogen gas. While not as powerful as similar alternatives, this rod is exceptionally stable and will last longer."
icon_state = "coolant_nitrogen"
max_durability = 3500
heat_amount = -10
power_amp_mod = 0.9
heat_amp_mod = 0.7
craftable = TRUE
reactor_overheat_modifier = 50
power_amount = -5 KW
materials = list(MAT_METAL = 2000, MAT_PLASMA = 2000, MAT_GLASS = 1000)
/obj/item/nuclear_rod/coolant/molten_salt
name = "molten salt circulator"
desc = "A specialized coolant rod that circulates molten salts through the core of the reactor. Despite forcing the reactor to run exceptionally hot, this rod provides top-notch cooling potential above its resting temperature."
icon_state = "coolant_salt"
power_amount = -20 KW
heat_amount = -60
heat_amp_mod = 0.8
max_durability = 8000
minimum_temp_modifier = 750
reactor_overheat_modifier = 100
materials = list(MAT_METAL = 2000, MAT_PLASMA = 2000, MAT_GLASS = 1000)
adjacent_requirements = list(
/obj/item/nuclear_rod/coolant/nitrogen_circulator,
/obj/item/nuclear_rod/moderator,
/obj/item/nuclear_rod/fuel,
/obj/item/nuclear_rod/fuel,
)
/obj/item/nuclear_rod/coolant/steam_hammerjet
name = "steam hammerjet"
desc = "A specialized coolant rod that injects distilled steam throughout the reactor's critical components. Although it makes the reactor run warm, it's very good at suppressing heat buildup."
icon_state = "coolant_steam"
power_amount = -10 KW
heat_amount = -40
heat_amp_mod = 0.4
max_durability = 6000
minimum_temp_modifier = 450
reactor_overheat_modifier = 100
adjacent_requirements = list(
/obj/item/nuclear_rod/coolant/light_water,
/obj/item/nuclear_rod/coolant/light_water,
)
/obj/item/nuclear_rod/coolant/bluespace_displacer
name = "bluespace heat displacer"
desc = "An advanced coolant rod capable of pulling heat directly out of neighboring rods and sending it... somewhere."
icon_state = "coolant_bluespace"
power_amount = -40 KW
heat_amount = -100
heat_amp_mod = 0.8
power_amp_mod = 1.3
max_durability = INFINITY
reactor_overheat_modifier = 200
craftable = TRUE
upgrade_required = TRUE
materials = list(MAT_METAL = 2000, MAT_PLASMA = 2000, MAT_BLUESPACE = 1000)
adjacent_requirements = list(/obj/item/nuclear_rod/moderator/bluespace_agitator)
/obj/item/nuclear_rod/coolant/iridium_conductor
name = "iridium conductor coolant rod"
desc = "A dazzlingly beautiful rod with exceptionally powerful thermal conductivity. A highly sought after piece of equipment for its simplicity and potency."
icon_state = "coolant_iridium"
heat_amp_mod = 0.1
max_durability = 10000
reactor_overheat_modifier = 300
adjacent_requirements = list(
/obj/item/nuclear_rod/moderator/aluminum_reflector,
/obj/item/nuclear_rod/fuel/uranium_235,
)
/obj/item/nuclear_rod/coolant/condensed_spacematter
name = "condensed spacematter coolant rod"
desc = "While it's unknown quite what the rod is filled with, there's no questioning its heat-suppressing efficiency. However, it violently disintegrates in contact with anything that isn't its housing."
icon_state = "coolant_spacematter"
heat_amount = -1500
heat_amp_mod = 0.2
materials = list(MAT_METAL = 6000, MAT_PLASMA = 4000, MAT_TITANIUM = 2000)
craftable = TRUE
upgrade_required = TRUE
adjacent_requirements = list(
/obj/item/nuclear_rod/fuel/enriched_plutonium,
/obj/item/nuclear_rod/fuel/thorium_salts,
)

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,470 @@
#define DEFAULT_OPERATION_TIME 10 SECONDS //! The base amount of time needed to craft an item
/// MARK: Centrifuge
/obj/machinery/nuclear_centrifuge
name = "Fuel Enrichment Centrifuge"
desc = "An advanced device capable of separating and collecting fissile materials from enriched fuel rods."
icon = 'icons/obj/fission/reactor_machines.dmi'
icon_state = "centrifuge_empty"
idle_power_consumption = 200
active_power_consumption = 3000
anchored = TRUE
density = TRUE
resistance_flags = FIRE_PROOF | FREEZE_PROOF
armor = list(melee = 25, bullet = 10, laser = 30, energy = 0, bomb = 0, rad = INFINITY, fire = INFINITY, acid = 70)
/// The time it takes for the machine to process a rod
var/work_time
/// The averaged amount of all stock parts
var/average_component_rating
/// The result when we are done operating
var/rod_result
/// Holds the rod object inserted into the machine
var/obj/item/nuclear_rod/held_rod
/// the soundloop we will be using while operating
var/datum/looping_sound/centrifuge/soundloop
COOLDOWN_DECLARE(enrichment_timer)
/obj/machinery/nuclear_centrifuge/Initialize(mapload)
. = ..()
soundloop = new(list(src), FALSE)
component_parts = list()
component_parts += new /obj/item/circuitboard/nuclear_centrifuge(src)
component_parts += new /obj/item/stock_parts/manipulator(src)
component_parts += new /obj/item/stock_parts/manipulator(src)
component_parts += new /obj/item/stock_parts/manipulator(src)
component_parts += new /obj/item/stock_parts/manipulator(src)
RefreshParts()
update_icon(UPDATE_OVERLAYS)
/obj/machinery/nuclear_centrifuge/examine(mob/user)
. = ..()
if(held_rod)
. += SPAN_NOTICE("The current fuel rod may be removed with <b>Alt-Click</b>.")
/obj/machinery/nuclear_centrifuge/Destroy()
QDEL_NULL(soundloop)
return ..()
/obj/machinery/nuclear_centrifuge/RefreshParts()
average_component_rating = 0
for(var/obj/item/stock_parts/manipulator/part in component_parts)
average_component_rating += part.rating
average_component_rating /= 4 // average all 4 components
work_time = DEFAULT_OPERATION_TIME / average_component_rating
/obj/machinery/nuclear_centrifuge/item_interaction(mob/living/user, obj/item/used, list/modifiers)
. = ..()
if(!istype(used, /obj/item/nuclear_rod/fuel))
return CONTINUE_ATTACK
if(stat & NOPOWER)
return ITEM_INTERACT_COMPLETE
if(panel_open)
to_chat(user, SPAN_WARNING("You must close the access panel first!"))
return ITEM_INTERACT_COMPLETE
if(power_state == ACTIVE_POWER_USE) // dont start a new cycle when on
to_chat(user, SPAN_WARNING("There is already a fuel rod being processed!"))
return ITEM_INTERACT_COMPLETE
var/obj/item/nuclear_rod/fuel/rod = used
var/list/enrichment_to_name = list()
var/list/radial_list = list()
var/obj/item/nuclear_rod/fuel/rod_enrichment
if(rod.power_enrich_progress >= rod.enrichment_cycles && rod.power_enrich_result)
rod_enrichment = rod.power_enrich_result
enrichment_to_name["[rod_enrichment::name]"] = rod_enrichment
radial_list["[rod_enrichment::name]"] = image(icon = rod_enrichment::icon, icon_state = rod_enrichment::icon_state)
if(rod.heat_enrich_progress >= rod.enrichment_cycles && rod.heat_enrich_result)
rod_enrichment = rod.heat_enrich_result
enrichment_to_name["[rod_enrichment::name]"] = rod_enrichment
radial_list["[rod_enrichment::name]"] = image(icon = rod_enrichment::icon, icon_state = rod_enrichment::icon_state)
if(!length(radial_list))
to_chat(user, SPAN_WARNING("This rod has no potential for enrichment!"))
return ITEM_INTERACT_COMPLETE
var/enrichment_choice = show_radial_menu(user, src, radial_list, src, radius = 30, require_near = TRUE)
if(!enrichment_choice)
return ITEM_INTERACT_COMPLETE
rod_result = enrichment_to_name[enrichment_choice]
held_rod = rod
user.transfer_item_to(rod, src)
begin_enrichment()
return ITEM_INTERACT_COMPLETE
/obj/machinery/nuclear_centrifuge/AltClick(mob/user, modifiers)
if(!held_rod)
return
if(power_state == ACTIVE_POWER_USE)
to_chat(user, SPAN_WARNING("You cannot remove the fuel rod while the machine is running!"))
return
held_rod.forceMove(get_turf(src))
held_rod = null
icon_state = "centrifuge_empty"
playsound(loc, 'sound/items/deconstruct.ogg', 50, TRUE)
/obj/machinery/nuclear_centrifuge/process()
if(stat & NOPOWER)
if(power_state == ACTIVE_POWER_USE)
abort_enrichment()
return
if(power_state == IDLE_POWER_USE)
return
if(!COOLDOWN_FINISHED(src, enrichment_timer))
return
finish_enrichment()
/obj/machinery/nuclear_centrifuge/screwdriver_act(mob/user, obj/item/I)
. = TRUE
if(held_rod)
to_chat(user, SPAN_WARNING("The machine cannot be opened while it contains a fuel rod!"))
return ITEM_INTERACT_COMPLETE
default_deconstruction_screwdriver(user, "centrifuge_maint", "centrifuge_empty", I)
/obj/machinery/nuclear_centrifuge/proc/begin_enrichment()
power_state = ACTIVE_POWER_USE
icon_state = "centrifuge_on"
COOLDOWN_START(src, enrichment_timer, work_time)
soundloop.start()
/obj/machinery/nuclear_centrifuge/proc/abort_enrichment()
power_state = IDLE_POWER_USE
icon_state = "centrifuge_full"
playsound(src, 'sound/machines/buzz-sigh.ogg', 30, TRUE)
soundloop.stop()
/obj/machinery/nuclear_centrifuge/proc/finish_enrichment()
icon_state = "centrifuge_full"
playsound(src, 'sound/machines/ping.ogg', 30, TRUE)
power_state = IDLE_POWER_USE
var/new_rod = new rod_result(contents)
rod_result = null
QDEL_NULL(held_rod)
held_rod = new_rod
soundloop.stop()
// MARK: Rod Fabricator
/obj/machinery/nuclear_rod_fabricator
name = "Nuclear Fuel Rod Fabricator"
desc = "A highly specialized fabricator for crafting nuclear rods."
icon = 'icons/obj/fission/reactor_machines.dmi'
icon_state = "rod_fab"
idle_power_consumption = 50
active_power_consumption = 3000
density = TRUE
resistance_flags = FIRE_PROOF | FREEZE_PROOF
armor = list(melee = 25, bullet = 10, laser = 30, energy = 0, bomb = 0, rad = INFINITY, fire = INFINITY, acid = 70)
/// Our holder for materials
var/datum/component/material_container/materials
/// How fast do we operate and/or do we get extra rods
var/efficiency_coeff = 1
/// The list for carrying fuel rods
var/list/category_fuel = list()
/// The list for carrying moderator rods
var/list/category_moderator = list()
/// The list for carrying coolant rods
var/list/category_coolant = list()
/// Is the rod fabricator currently upgraded from science
var/upgraded = FALSE
/// What is the current item being produced
var/schematic
/// The time it takes for the machine to process a rod
var/work_time
COOLDOWN_DECLARE(fabrication_timer)
/obj/machinery/nuclear_rod_fabricator/upgraded
upgraded = TRUE
/obj/machinery/nuclear_rod_fabricator/Initialize(mapload)
. = ..()
materials = AddComponent(/datum/component/material_container, list(MAT_METAL, MAT_GLASS, MAT_SILVER, MAT_GOLD, MAT_DIAMOND, MAT_PLASMA, MAT_URANIUM, MAT_BANANIUM, MAT_TRANQUILLITE, MAT_TITANIUM, MAT_BLUESPACE, MAT_PLASTIC), 0, TRUE, /obj/item/stack, CALLBACK(src, PROC_REF(is_insertion_ready)), CALLBACK(src, PROC_REF(AfterMaterialInsert)))
materials.precise_insertion = TRUE
component_parts = list()
component_parts += new /obj/item/circuitboard/nuclear_rod_fabricator(src)
component_parts += new /obj/item/stock_parts/matter_bin(src)
component_parts += new /obj/item/stock_parts/matter_bin(src)
component_parts += new /obj/item/stock_parts/manipulator(src)
component_parts += new /obj/item/stock_parts/manipulator(src)
RefreshParts()
create_designs()
/obj/machinery/nuclear_rod_fabricator/RefreshParts()
var/temp_coeff = 12
var/average_component_rating = 0
for(var/obj/item/stock_parts/manipulator/M in component_parts)
temp_coeff -= M.rating
average_component_rating += M.rating
work_time = DEFAULT_OPERATION_TIME / average_component_rating
efficiency_coeff = clamp(temp_coeff / 10, 0.05, 1)
temp_coeff = 0
for(var/obj/item/stock_parts/matter_bin/M in component_parts)
temp_coeff += M.rating
materials.max_amount = temp_coeff * 75000
/obj/machinery/nuclear_rod_fabricator/attack_ghost(mob/user)
return attack_hand(user)
/obj/machinery/nuclear_rod_fabricator/proc/is_insertion_ready(mob/user)
if(panel_open)
to_chat(user, SPAN_WARNING("You can't load [src] while it's opened!"))
return FALSE
if(stat & BROKEN)
to_chat(user, SPAN_WARNING("[src] is broken."))
return FALSE
if(stat & NOPOWER)
to_chat(user, SPAN_WARNING("[src] has no power."))
return FALSE
return TRUE
/obj/machinery/nuclear_rod_fabricator/proc/AfterMaterialInsert(type_inserted, id_inserted, amount_inserted)
var/stack_name
if(ispath(type_inserted, /obj/item/stack/ore/bluespace_crystal))
stack_name = "bluespace"
use_power(MINERAL_MATERIAL_AMOUNT / 10)
else
var/obj/item/stack/S = type_inserted
stack_name = initial(S.name)
use_power(min(1000, (amount_inserted / 100)))
add_overlay("protolathe_[stack_name]")
addtimer(CALLBACK(src, TYPE_PROC_REF(/atom, cut_overlay), "protolathe_[stack_name]"), 10)
/obj/machinery/nuclear_rod_fabricator/proc/check_mat(obj/item/nuclear_rod/being_built, M)
var/A = materials.amount(M)
if(!A)
visible_message(SPAN_WARNING("Something has gone very wrong. Alert a developer."))
return
else
A /= max(1, (being_built.materials[M] * efficiency_coeff))
return A
/obj/machinery/nuclear_rod_fabricator/item_interaction(mob/living/user, obj/item/used, list/modifiers)
if(istype(used, /obj/item/storage/part_replacer))
return ..()
if(panel_open)
to_chat(user, SPAN_WARNING("You can't load [src] while the maintenance panel is opened."))
return ITEM_INTERACT_COMPLETE
if(istype(used, /obj/item/rod_fabricator_upgrade))
upgraded = TRUE
create_designs()
user.drop_item(used)
qdel(used)
return ITEM_INTERACT_COMPLETE
return ..()
/obj/machinery/nuclear_rod_fabricator/crowbar_act(mob/living/user, obj/item/I)
if(!panel_open)
return
. = TRUE
materials.retrieve_all()
default_deconstruction_crowbar(user, I)
/obj/machinery/nuclear_rod_fabricator/on_deconstruction()
if(upgraded)
new /obj/item/rod_fabricator_upgrade(loc)
return ..()
/obj/machinery/nuclear_rod_fabricator/proc/create_designs()
category_fuel = list()
category_moderator = list()
category_coolant = list()
for(var/obj/rod_path as anything in subtypesof(/obj/item/nuclear_rod))
if(initial(rod_path.desc) == ABSTRACT_TYPE_DESC)
continue
var/datum/nuclear_rod_design/D = new /datum/nuclear_rod_design()
D.build_metadata_list(rod_path)
if(!D.metadata["craftable"])
continue
if(D.metadata["upgrade_required"] && !upgraded)
continue
if(ispath(rod_path, /obj/item/nuclear_rod/fuel))
category_fuel += D
else if(ispath(rod_path, /obj/item/nuclear_rod/moderator))
category_moderator += D
else if(ispath(rod_path, /obj/item/nuclear_rod/coolant))
category_coolant += D
/obj/machinery/nuclear_rod_fabricator/ui_data(mob/user)
var/list/data = list()
data["fuel_rods"] = list()
for(var/datum/nuclear_rod_design/D in category_fuel)
data["fuel_rods"] += list(D.metadata)
data["moderator_rods"] = list()
for(var/datum/nuclear_rod_design/D in category_moderator)
data["moderator_rods"] += list(D.metadata)
data["coolant_rods"] = list()
for(var/datum/nuclear_rod_design/D in category_coolant)
data["coolant_rods"] += list(D.metadata)
// Add available resources from the material container
data["resources"] = list()
if(materials)
// Get all material types that the fabricator supports
var/list/supported_materials = list(
MAT_METAL, MAT_GLASS, MAT_SILVER, MAT_GOLD, MAT_DIAMOND, MAT_PLASMA,
MAT_URANIUM, MAT_TITANIUM, MAT_BLUESPACE, MAT_PLASTIC, MAT_BANANIUM, MAT_TRANQUILLITE
)
for(var/mat_id in supported_materials)
var/amount = materials.amount(mat_id)
if(amount > 0)
var/sheets = round(amount / MINERAL_MATERIAL_AMOUNT)
var/display_name = CallMaterialName(mat_id)
data["resources"][display_name] = list(
"amount" = amount,
"sheets" = sheets,
"id" = mat_id
)
return data
/obj/machinery/nuclear_rod_fabricator/attack_hand(mob/user)
ui_interact(user)
/obj/machinery/nuclear_rod_fabricator/interact(mob/user)
. = ..()
if(panel_open)
to_chat(user, SPAN_WARNING("You can't access [src] while it's opened!"))
return
/obj/machinery/nuclear_rod_fabricator/ui_state(mob/user)
return GLOB.default_state
/obj/machinery/nuclear_rod_fabricator/ui_interact(mob/user, datum/tgui/ui = null)
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
ui = new(user, src, "NuclearRodFabricator", name)
ui.open()
/obj/machinery/nuclear_rod_fabricator/ui_act(action, list/params, datum/tgui/ui, datum/ui_state/state)
if(..())
return
switch(action)
if("fabricate_rod")
var/rod_type_path = text2path(params["type_path"])
if(!rod_type_path)
return FALSE
var/datum/nuclear_rod_design/selected_design
for(var/datum/nuclear_rod_design/D in category_fuel + category_moderator + category_coolant)
if(D.type_path == rod_type_path)
selected_design = D
break
if(!selected_design)
return FALSE
if(power_state == ACTIVE_POWER_USE)
to_chat(usr, SPAN_WARNING("A rod is already being fabricated!"))
return FALSE
// Check if we have enough materials
var/obj/item/nuclear_rod/temp_rod = new rod_type_path()
var/list/required_materials = temp_rod.materials
qdel(temp_rod)
if(!required_materials || !length(required_materials))
to_chat(usr, SPAN_WARNING("This rod design has no material requirements defined - please create an issue report!"))
return FALSE
for(var/mat_id in required_materials)
var/required_amount = required_materials[mat_id] * efficiency_coeff
if(materials.amount(mat_id) < required_amount)
to_chat(usr, SPAN_WARNING("Not enough materials! Need [required_amount] units of [mat_id]!"))
return FALSE
// Spend materials
var/list/materials_to_use = list()
for(var/mat_id in required_materials)
materials_to_use[mat_id] = required_materials[mat_id] * efficiency_coeff
if(!materials.use_amount(materials_to_use))
to_chat(usr, SPAN_WARNING("Failed to deduct materials!"))
return FALSE
// Begin Process
begin_fabrication(rod_type_path)
return TRUE
if("eject_material")
var/material_id = params["id"]
var/amount = params["amount"]
if(!material_id || !materials.materials[material_id])
return FALSE
var/desired_sheets = 0
if(amount == "custom")
var/datum/material/M = materials.materials[material_id]
var/max_sheets = round(M.amount / MINERAL_MATERIAL_AMOUNT)
if(max_sheets <= 0)
to_chat(usr, SPAN_WARNING("Not enough [M.name] to eject!"))
return FALSE
desired_sheets = tgui_input_number(usr, "How many sheets do you want to eject?", "Ejecting [M.name]", 1, max_sheets, 1)
if(isnull(desired_sheets))
return FALSE
else
desired_sheets = text2num(amount)
desired_sheets = max(0, round(desired_sheets))
if(desired_sheets > 0)
materials.retrieve_sheets(desired_sheets, material_id, get_turf(src))
to_chat(usr, SPAN_NOTICE("[src] ejects [desired_sheets] sheets."))
return TRUE
return FALSE
/obj/machinery/nuclear_rod_fabricator/screwdriver_act(mob/user, obj/item/I)
. = TRUE
if(power_state == ACTIVE_POWER_USE)
to_chat(user, SPAN_WARNING("The machine cannot be opened while it is operating!"))
return ITEM_INTERACT_COMPLETE
default_deconstruction_screwdriver(user, "rod_fab_maint", "rod_fab", I)
/obj/machinery/nuclear_rod_fabricator/proc/begin_fabrication(rod_type_path)
power_state = ACTIVE_POWER_USE
icon_state = "rod_fab_on"
COOLDOWN_START(src, fabrication_timer, work_time)
schematic = rod_type_path
/obj/machinery/nuclear_rod_fabricator/proc/finish_fabrication()
power_state = IDLE_POWER_USE
icon_state = "rod_fab"
var/obj/item/nuclear_rod/new_rod = new schematic(get_turf(src))
src.visible_message(SPAN_NOTICE("[src] fabricates \a [new_rod.name]."))
playsound(src, 'sound/machines/ping.ogg', 50, TRUE)
/obj/machinery/nuclear_rod_fabricator/proc/abort_fabrication()
power_state = IDLE_POWER_USE
icon_state = "rod_fab"
playsound(src, 'sound/machines/buzz-sigh.ogg', 30, TRUE)
/obj/machinery/nuclear_rod_fabricator/process()
if(stat & NOPOWER)
if(power_state == ACTIVE_POWER_USE)
abort_fabrication()
return
if(power_state == IDLE_POWER_USE)
return
if(!COOLDOWN_FINISHED(src, fabrication_timer))
return
finish_fabrication()
#undef DEFAULT_OPERATION_TIME

View File

@@ -0,0 +1,810 @@
#define CHAMBER_HEAT_DAMAGE 15 //! How much damage reactor chambers do when on.
/obj/machinery/atmospherics/reactor_chamber
name = "rod housing chamber"
desc = "A chamber used to house nuclear rods of various types to facilitate a fission reaction."
icon = 'icons/obj/fission/reactor_chamber.dmi'
icon_state = "chamber_down"
layer = BELOW_OBJ_LAYER
pass_flags_self = PASSTAKE
resistance_flags = LAVA_PROOF | FIRE_PROOF | ACID_PROOF | FREEZE_PROOF
max_integrity = 400
armor = list(melee = 80, bullet = 30, laser = 30, energy = 10, bomb = 40, rad = INFINITY, fire = INFINITY, acid = INFINITY) // Fairly robust
idle_power_consumption = 100
flags_2 = NO_MALF_EFFECT_2
/// Each reactor chamber can only be linked to a single reactor, if somehow theres two.
var/obj/machinery/atmospherics/fission_reactor/linked_reactor
/// Holds the specific rod inserted into the chamber
var/obj/item/nuclear_rod/held_rod
/// Is the chamber up, down, or open
var/chamber_state = 1
/// Has the requirements for the rod inside this chamber been met?
var/requirements_met = FALSE
/// Is the rod chamber actively running and providing its effects
var/operational = FALSE
/// Holds the list of linked neighbors
var/list/neighbors = list()
/// Skip this chamber when building links
var/skip_link = FALSE
/// The total amount of heat produced by this chamber
var/heat_total
/// The total amount of power produced by this rod
var/power_total
/// Is the chamber currently in an enrichment process
var/enriching = FALSE
/// Has the chamber been welded shut. Uh oh!
var/welded = FALSE
/// Holds the current accumulated power mod value from its neighbors
var/power_mod_total = 1
/// Holds the current accumulated heat mod value from its neighbors
var/heat_mod_total = 1
/// A simple binary to prevent open/close spam mucking up the anims
var/lockout = FALSE
/// Holds our durability bar overlay level. Updates overlays if it changes
var/durability_level = 0
/// Holds our previous overlay.
var/previous_durability_level
/obj/machinery/atmospherics/reactor_chamber/Initialize(mapload)
. = ..()
dupe_check()
component_parts = list()
component_parts += new /obj/item/circuitboard/machine/reactor_chamber(src)
component_parts += new /obj/item/stock_parts/manipulator(src)
component_parts += new /obj/item/stack/sheet/mineral/plastitanium(src, 2)
component_parts += new /obj/item/stack/sheet/metal(src, 2)
component_parts += new /obj/item/stack/cable_coil(src, 5)
RefreshParts()
update_icon(UPDATE_OVERLAYS)
RegisterSignal(src, COMSIG_PARENT_EXAMINE, PROC_REF(deep_examine))
return INITIALIZE_HINT_LATELOAD
// Needs to be late so it does not initialize before the reactor or the other neighbors are ready
/obj/machinery/atmospherics/reactor_chamber/LateInitialize()
. = ..()
find_link()
update_icon(UPDATE_OVERLAYS)
/obj/machinery/atmospherics/reactor_chamber/uranium
/obj/machinery/atmospherics/reactor_chamber/uranium/Initialize(mapload)
. = ..()
held_rod = new /obj/item/nuclear_rod/fuel/uranium_238(src)
/obj/machinery/atmospherics/reactor_chamber/heavy_water
/obj/machinery/atmospherics/reactor_chamber/heavy_water/Initialize(mapload)
. = ..()
held_rod = new /obj/item/nuclear_rod/moderator/heavy_water(src)
/obj/machinery/atmospherics/reactor_chamber/examine(mob/user)
. = ..()
. += SPAN_NOTICE("[src] can be sealed/unsealed from its base with a lit welder using harm intent, but only while the chamber is lowered.")
. += SPAN_NOTICE("Alt+click to open and close the shielding while the chamber is raised.")
. += SPAN_NOTICE("Click on the chamber while it is closed to raise and lower it.")
if(isobserver(user))
// observers get regular examine + nested multitool info
var/list/deep_info = get_deep_examine_info()
if(length(deep_info))
. += chat_box_examine(deep_info.Join("<br>"))
/obj/machinery/atmospherics/reactor_chamber/on_deconstruction()
desync()
if(held_rod) // We shouldnt be able to decon with this in, but just in case
if(held_rod.reactor_overheat_modifier)
linked_reactor.update_overheat_threshold(-held_rod.reactor_overheat_modifier)
held_rod.forceMove(loc)
held_rod = null
return ..()
/obj/machinery/atmospherics/reactor_chamber/Destroy()
if(held_rod && held_rod.reactor_overheat_modifier)
linked_reactor.update_overheat_threshold(-held_rod.reactor_overheat_modifier)
QDEL_NULL(held_rod)
if(linked_reactor)
desync()
UnregisterSignal(src, COMSIG_PARENT_EXAMINE)
return ..()
/obj/machinery/atmospherics/reactor_chamber/update_icon_state()
return
/obj/machinery/atmospherics/reactor_chamber/update_overlays()
. = ..()
overlays.Cut()
if(welded)
var/mutable_appearance/weld_overlay = mutable_appearance(layer = BELOW_OBJ_LAYER + 0.03)
weld_overlay.icon_state = "welded"
. += weld_overlay
if(chamber_state == CHAMBER_OPEN)
var/mutable_appearance/cover_icon = mutable_appearance(layer = ABOVE_ALL_MOB_LAYER + 0.02)
cover_icon.icon = icon
cover_icon.icon_state = "door_open"
. += cover_icon
if(!held_rod)
return
if(chamber_state == CHAMBER_OPEN)
var/mutable_appearance/rod_overlay = mutable_appearance(layer = ABOVE_ALL_MOB_LAYER + 0.01)
rod_overlay.icon = icon
if(istype(held_rod, /obj/item/nuclear_rod/fuel))
rod_overlay.icon_state = "fuel_overlay"
if(istype(held_rod, /obj/item/nuclear_rod/coolant))
rod_overlay.icon_state = "coolant_overlay"
if(istype(held_rod, /obj/item/nuclear_rod/moderator))
rod_overlay.icon_state = "moderator_overlay"
. += rod_overlay
var/mutable_appearance/state_overlay = mutable_appearance(layer = BELOW_OBJ_LAYER + 0.01)
state_overlay.icon = icon
if(chamber_state == CHAMBER_DOWN)
if(enriching)
state_overlay.icon_state = "blue"
else if(requirements_met)
if(operational)
state_overlay.icon_state = "green"
else
state_overlay.icon_state = "orange"
else
if(operational)
state_overlay.icon_state = "orange"
else
state_overlay.icon_state = "red"
var/mutable_appearance/display_overlay = mutable_appearance(layer = BELOW_OBJ_LAYER + 0.01)
if(istype(held_rod, /obj/item/nuclear_rod/fuel))
display_overlay.icon_state = "display_fuel"
if(istype(held_rod, /obj/item/nuclear_rod/moderator))
display_overlay.icon_state = "display_moderator"
if(istype(held_rod, /obj/item/nuclear_rod/coolant))
display_overlay.icon_state = "display_coolant"
. += display_overlay
if(chamber_state == CHAMBER_OVERLOAD_IDLE)
if(held_rod && istype(held_rod, /obj/item/nuclear_rod/fuel))
state_overlay.icon_state = "orange"
else
state_overlay.icon_state = "red"
if(chamber_state == CHAMBER_OVERLOAD_ACTIVE)
state_overlay.icon_state = "overload"
. += state_overlay
var/mutable_appearance/durability_overlay = mutable_appearance(icon, layer = BELOW_OBJ_LAYER + 0.01)
durability_overlay.icon_state = "dur_[previous_durability_level]"
. += durability_overlay
/// Check for multiple on a tile and nuke it
/obj/machinery/atmospherics/reactor_chamber/proc/dupe_check()
var/obj/machinery/atmospherics/reactor_chamber/chamber = locate() in range(0, src)
if(chamber && chamber != src)
visible_message(SPAN_WARNING("[src] has no room to deploy and breaks apart!"))
chamber.deconstruct()
/obj/machinery/atmospherics/reactor_chamber/attack_hand(mob/user)
if(!user)
return
if(linked_reactor && linked_reactor.admin_intervention)
to_chat(user, SPAN_WARNING("An unusual force prevents you from moving the chamber!"))
return
if(stat & NOPOWER)
to_chat(user, SPAN_WARNING("The chamber's locks wont disengage without power!"))
return
if(!is_mecha_occupant(user))
add_fingerprint(user)
switch(chamber_state)
if(CHAMBER_DOWN, CHAMBER_OVERLOAD_IDLE)
if(!Adjacent(user))
return
if(welded)
to_chat(user, SPAN_WARNING("[src] is welded shut. It wont budge!"))
return
if(!density_check(user))
return
var/delay = 1 SECONDS
if(linked_reactor && !linked_reactor.offline)
delay = 8 SECONDS
if(!is_mecha_occupant(user)) // Mech users are unaffected
burn_handler(user)
if(do_after_once(user, delay, target = src, allow_moving = FALSE))
if(!Adjacent(user)) // For mecha users
return
if(density_check(user))
raise()
return
if(CHAMBER_UP)
if(!density_check(user))
return
if(do_after_once(user, 2 SECONDS, target = src, allow_moving = FALSE))
if(chamber_state != CHAMBER_UP) // So that we cant lower while in the open state
return
if(density_check(user))
lower()
return
if(CHAMBER_OPEN)
if(issilicon(user)) // Handled seperately. Dont pull out this way
return
if(!held_rod)
to_chat(user, SPAN_WARNING("There is no rod inside of the chamber to remove!"))
return
if(user.put_in_hands(held_rod))
held_rod.add_fingerprint(user)
held_rod = null
playsound(loc, 'sound/machines/podopen.ogg', 50, TRUE)
update_icon(UPDATE_OVERLAYS)
return
to_chat(user, SPAN_WARNING("Your hands are currently full!"))
return
if(CHAMBER_OVERLOAD_ACTIVE)
to_chat(user, SPAN_ALERT("The chamber lockdowns have been engaged, preventing it from being raised!"))
return
update_icon(UPDATE_OVERLAYS)
/obj/machinery/atmospherics/reactor_chamber/AltClick(mob/user, modifiers)
if(!Adjacent(user) || lockout)
return
if(linked_reactor && linked_reactor.admin_intervention)
to_chat(user, SPAN_WARNING("An unusual force prevents you from manipulating the chamber!"))
return
if(chamber_state == CHAMBER_UP)
if(!lockout)
open()
return
if(chamber_state == CHAMBER_OPEN)
if(panel_open == TRUE)
to_chat(user, SPAN_WARNING("You must close the maintenance panel before the chamber can be sealed!"))
return
if(!lockout)
close()
return
/obj/machinery/atmospherics/reactor_chamber/proc/density_check(mob/user)
for(var/atom/thing in get_turf(src))
if(thing == src)
continue
if(thing.density)
to_chat(user, SPAN_WARNING("The chamber is being blocked from opening!"))
return FALSE
return TRUE
/obj/machinery/atmospherics/reactor_chamber/item_interaction(mob/living/user, obj/item/used, list/modifiers)
if(issilicon(user) && get_dist(src, user) > 1)
attack_hand(user)
return ITEM_INTERACT_COMPLETE
if(istype(used, /obj/item/nuclear_rod))
if(chamber_state == CHAMBER_OPEN)
if(held_rod)
to_chat(user, SPAN_WARNING("There is already a rod inside of the chamber!"))
return ITEM_INTERACT_COMPLETE
if(panel_open)
to_chat(user, SPAN_WARNING("The open maintenance panel prevents the rod from slotting inside!"))
return ITEM_INTERACT_COMPLETE
if(user.transfer_item_to(used, src, force = TRUE))
held_rod = used
playsound(loc, 'sound/machines/podclose.ogg', 50, TRUE)
update_icon(UPDATE_OVERLAYS)
return ITEM_INTERACT_COMPLETE
/obj/machinery/atmospherics/reactor_chamber/screwdriver_act(mob/living/user, obj/item/I)
if(!I.use_tool(src, user, 0, volume = 0))
return
. = TRUE
if(chamber_state != CHAMBER_OPEN)
to_chat(user, SPAN_ALERT("[src] must be raised and opened first!"))
return
if(linked_reactor && !linked_reactor.offline)
to_chat(user, SPAN_ALERT("The safety locks prevent maintenance while the reactor is on!"))
return
if(held_rod)
to_chat(user, SPAN_ALERT("You cannot reach the maintenance panel if there is a rod inside!"))
return
default_deconstruction_screwdriver(user, "chamber_maint", "chamber_open", I)
/obj/machinery/atmospherics/reactor_chamber/crowbar_act(mob/living/user, obj/item/I)
. = TRUE
default_deconstruction_crowbar(user, I)
/obj/machinery/atmospherics/reactor_chamber/welder_act(mob/living/user, obj/item/I)
if(user.a_intent == INTENT_HARM)
if(chamber_state == CHAMBER_OVERLOAD_IDLE || chamber_state == CHAMBER_OVERLOAD_ACTIVE)
to_chat(user, SPAN_WARNING("You probably shouldn't try to weld it right now."))
return ITEM_INTERACT_COMPLETE
if(chamber_state != CHAMBER_DOWN)
return ITEM_INTERACT_COMPLETE
to_chat(user, SPAN_WARNING("You begin [welded ? "unwelding" : "welding"] [src]"))
if(!I.use_tool(src, user, (6 SECONDS) * I.toolspeed, volume = I.tool_volume))
return ITEM_INTERACT_COMPLETE
if(welded)
unweld()
else
weld_shut()
update_icon(UPDATE_OVERLAYS)
return ITEM_INTERACT_COMPLETE
if(obj_integrity < max_integrity)
to_chat(user, SPAN_WARNING("You begin repairing [src]."))
if(!I.use_tool(src, user, (3 SECONDS) * I.toolspeed, volume = I.tool_volume))
return ITEM_INTERACT_COMPLETE
obj_integrity = max_integrity // Lets make sure we can keep these healthy if need be
else
to_chat(user, SPAN_WARNING("[src] is not in need of repair."))
return ITEM_INTERACT_COMPLETE
/obj/machinery/atmospherics/reactor_chamber/multitool_act(mob/living/user, obj/item/I)
. = TRUE
show_deep_examine(user)
/obj/machinery/atmospherics/reactor_chamber/proc/get_deep_examine_info()
if(chamber_state != CHAMBER_DOWN)
return null
if(!held_rod)
return list(SPAN_WARNING("There is no nuclear rod inside this housing chamber."))
if(!linked_reactor)
return list(SPAN_WARNING("This chamber is not connected to a reactor."))
var/operating_rate = linked_reactor.operating_rate()
var/durability_mod = held_rod.get_durability_mod()
var/list/message = list()
message += SPAN_NOTICE("[held_rod] is currently contained within this chamber.")
message += ""
if(held_rod.durability == 0)
message += SPAN_NOTICE("The rod has been fully depleted and rendered inert.")
return message
else
message += SPAN_NOTICE("Rod integrity is at [(held_rod.durability / held_rod.max_durability) * 100]%.")
message += ""
if(power_total && operational)
message += SPAN_NOTICE("The chamber is currently producing [(power_total * operating_rate * durability_mod) / 1000] KiloWatts of energy.")
message += SPAN_NOTICE("The chamber has a power modifier of [power_mod_total].")
else
message += SPAN_NOTICE("The chamber is producing no power.")
if(istype(held_rod, /obj/item/nuclear_rod/fuel))
var/obj/item/nuclear_rod/fuel/rod = held_rod
if(rod.power_enrich_progress >= rod.enrichment_cycles && rod.power_enrich_result)
message += SPAN_NOTICE("[held_rod] has been power enriched")
else
message += SPAN_NOTICE("[held_rod] has not yet finished a power enrichment process.")
message += ""
if(heat_total)
message += SPAN_NOTICE("The chamber is currently producing [heat_total * HEAT_MODIFIER * operating_rate * durability_mod] joules of heat.")
message += SPAN_NOTICE("The chamber has a heat modifier of [heat_mod_total].")
else
message += SPAN_NOTICE("The chamber is producing no heat.")
if(istype(held_rod, /obj/item/nuclear_rod/fuel))
var/obj/item/nuclear_rod/fuel/rod = held_rod
if(rod.heat_enrich_progress >= rod.enrichment_cycles && rod.heat_enrich_result)
message += SPAN_NOTICE("[held_rod] has been heat enriched")
else
message += SPAN_NOTICE("[held_rod] has not yet finished a heat enrichment process.")
return message
/obj/machinery/atmospherics/reactor_chamber/proc/show_deep_examine(mob/user)
var/list/info = get_deep_examine_info()
if(!info)
return ITEM_INTERACT_COMPLETE
to_chat(user, chat_box_examine(info.Join("<br>")))
return ITEM_INTERACT_COMPLETE
/obj/machinery/atmospherics/reactor_chamber/proc/deep_examine(datum/source, mob/user, list/examine_list)
SIGNAL_HANDLER // COMSIG_PARENT_EXAMINE
show_deep_examine(user)
/obj/machinery/atmospherics/reactor_chamber/proc/raise(playsound = TRUE)
chamber_state = CHAMBER_UP
icon_state = "chamber_up_anim"
lockout = TRUE
addtimer(CALLBACK(src, PROC_REF(finish_raise_anim)), 0.7 SECONDS)
density = TRUE
operational = FALSE
enriching = FALSE
requirements_met = FALSE
layer = ABOVE_MOB_LAYER
power_total = 0
check_minimum_modifier()
if(held_rod && held_rod.reactor_overheat_modifier)
linked_reactor.update_overheat_threshold(-held_rod.reactor_overheat_modifier)
if(playsound)
playsound(loc, 'sound/items/deconstruct.ogg', 50, TRUE)
if(istype(held_rod, /obj/item/nuclear_rod/fuel))
if(linked_reactor.offline)
held_rod.start_rads()
else
held_rod.start_rads(linked_reactor.reactivity_multiplier)
update_icon()
for(var/obj/machinery/atmospherics/reactor_chamber/chamber in neighbors)
if(!chamber.held_rod)
continue
if(chamber.check_status())
chamber.requirements_met = TRUE
else
chamber.requirements_met = FALSE
/obj/machinery/atmospherics/reactor_chamber/proc/finish_raise_anim()
lockout = FALSE
icon_state = "chamber_up"
/obj/machinery/atmospherics/reactor_chamber/proc/lower(playsound = TRUE)
density = FALSE
layer = BELOW_OBJ_LAYER
if(playsound)
playsound(loc, 'sound/items/deconstruct.ogg', 50, TRUE)
if(linked_reactor && linked_reactor.safety_override)
chamber_state = CHAMBER_OVERLOAD_IDLE
icon_state = "chamber_overload"
if(linked_reactor.check_overload_ready())
linked_reactor.set_overload()
update_icon()
return
chamber_state = CHAMBER_DOWN
icon_state = "chamber_down_anim"
addtimer(CALLBACK(src, PROC_REF(finish_down_anim)), 1.3 SECONDS)
if(!held_rod)
update_icon()
return
held_rod.stop_rads()
if(held_rod.reactor_overheat_modifier)
linked_reactor.update_overheat_threshold(held_rod.reactor_overheat_modifier)
previous_durability_level = clamp(ROUND_UP(((held_rod.durability / held_rod.max_durability) * 5) - 0.8), 0, 5)
if(check_status())
requirements_met = TRUE
else
requirements_met = FALSE
check_minimum_modifier()
update_icon()
/obj/machinery/atmospherics/reactor_chamber/proc/finish_down_anim()
icon_state = "chamber_down"
/obj/machinery/atmospherics/reactor_chamber/proc/close(playsound = TRUE)
chamber_state = CHAMBER_UP
new /obj/effect/temp_visual/chamber_closing(loc)
addtimer(CALLBACK(src, PROC_REF(finish_closing)), 0.5 SECONDS)
lockout = TRUE
if(playsound)
playsound(loc, 'sound/machines/switch.ogg', 50, TRUE)
/obj/machinery/atmospherics/reactor_chamber/proc/finish_closing()
lockout = FALSE
icon_state = "chamber_up"
update_icon(UPDATE_OVERLAYS)
/obj/machinery/atmospherics/reactor_chamber/proc/open(playsound = TRUE)
chamber_state = CHAMBER_OPEN
icon_state = "chamber_open"
var/cover_icon = mutable_appearance(icon, icon_state = "doors_opening", layer = ABOVE_ALL_MOB_LAYER + 0.02)
add_overlay(cover_icon)
lockout = TRUE
addtimer(CALLBACK(src, PROC_REF(finish_opening)), 0.5 SECONDS)
if(playsound)
playsound(loc, 'sound/machines/switch.ogg', 50, TRUE)
update_icon(UPDATE_OVERLAYS)
/obj/machinery/atmospherics/reactor_chamber/proc/finish_opening()
lockout = FALSE
/obj/machinery/atmospherics/reactor_chamber/proc/set_idle_overload()
if(chamber_state == CHAMBER_DOWN)
chamber_state = CHAMBER_OVERLOAD_IDLE
icon_state = "chamber_overload"
if(welded)
welded = FALSE
operational = FALSE
enriching = FALSE
requirements_met = FALSE
update_icon(UPDATE_OVERLAYS)
/obj/machinery/atmospherics/reactor_chamber/proc/set_active_overload()
chamber_state = CHAMBER_OVERLOAD_ACTIVE
icon_state = "chamber_down"
update_icon(UPDATE_OVERLAYS)
/// Gets the neighbors of the current chamber, and adds itself to its neighbors. can prompt a cascade of linking
/obj/machinery/atmospherics/reactor_chamber/proc/get_neighbors()
for(var/direction in GLOB.cardinal)
var/obj/machinery/atmospherics/reactor_chamber/chamber = locate() in get_step(src, direction)
if(!chamber)
continue
if(chamber.linked_reactor && chamber.linked_reactor != linked_reactor) // If for some god forsaken reason we have two
continue
if((chamber in neighbors) || (src in chamber.neighbors))
continue
neighbors += chamber
chamber.neighbors += src
if(!chamber.linked_reactor)
chamber.linked_reactor = linked_reactor
linked_reactor.connected_chambers += chamber
chamber.get_neighbors()
/// Removes the chamber from neighbor from its neighbors, and forces them to run status checks
/obj/machinery/atmospherics/reactor_chamber/proc/desync()
if(length(neighbors))
for(var/obj/machinery/atmospherics/reactor_chamber/chamber in neighbors)
chamber.neighbors -= src
neighbors.Cut()
if(linked_reactor)
linked_reactor.connected_chambers -= src
linked_reactor.clear_reactor_network(restart = TRUE)
/// Forms the two-way link between the reactor and the chamber, then searches for valid neighbors.
/obj/machinery/atmospherics/reactor_chamber/proc/form_link(obj/machinery/atmospherics/fission_reactor/reactor)
if(linked_reactor || skip_link) // Prevent duplicate linking or unwanted chambers
return
linked_reactor = reactor
linked_reactor.connected_chambers |= src
get_neighbors()
/// Searches for a valid reactor or linked chamber nearby
/obj/machinery/atmospherics/reactor_chamber/proc/find_link()
if(linked_reactor) // We already have a linked reactor
return
var/turf/nearby_turf
for(var/direction in GLOB.cardinal)
nearby_turf = get_step(src, direction)
var/obj/machinery/atmospherics/fission_reactor/reactor = locate() in nearby_turf
if(reactor)
form_link(reactor)
return TRUE
var/obj/structure/filler/filler = locate() in nearby_turf
if(filler &&istype(filler.parent, /obj/machinery/atmospherics/fission_reactor))
form_link(filler.parent)
return TRUE
var/obj/machinery/atmospherics/reactor_chamber/chamber = locate() in nearby_turf
if(chamber &&chamber.linked_reactor)
form_link(chamber.linked_reactor)
return TRUE
return FALSE
/// Validates that all rod requirements are being met
/obj/machinery/atmospherics/reactor_chamber/proc/check_status()
if(!held_rod)
return FALSE
var/list/temp_requirements = list()
temp_requirements += held_rod.adjacent_requirements // A temporary modable holder
if(!temp_requirements)
return TRUE
for(var/obj/machinery/atmospherics/reactor_chamber/chamber in neighbors)
if(!chamber.operational)
continue
if(chamber.held_rod.type in temp_requirements)
temp_requirements -= chamber.held_rod.type
continue
for(var/requirement in temp_requirements)
if(chamber.held_rod.type in typesof(requirement))
temp_requirements -= requirement
break
if(!length(temp_requirements))
return TRUE
return FALSE
/obj/machinery/atmospherics/reactor_chamber/process()
if(!linked_reactor)
if(find_link())
get_neighbors()
return
if(linked_reactor.admin_intervention)
return
if(!held_rod)
return
if(chamber_state != CHAMBER_DOWN) // We should only process reactor info when down
return
durability_level = clamp(ROUND_UP(((held_rod.durability / held_rod.max_durability) * 5) - 0.8), 0, 5)
if(durability_level != previous_durability_level)
previous_durability_level = durability_level
update_icon(UPDATE_OVERLAYS)
if(!linked_reactor.offline)
held_rod.calc_stat_decrease() // Only need to re-calc durability loss when the chamber is down and reactor is online
if(linked_reactor && linked_reactor.safety_override && !linked_reactor.control_lockout) // we only remove control lockout when the others are ready
if(chamber_state == CHAMBER_OVERLOAD_IDLE && istype(held_rod, /obj/item/nuclear_rod/fuel))
set_active_overload() // For latejoiners
if(operational && held_rod.durability <= 0)
requirements_met = FALSE
update_icon(UPDATE_OVERLAYS)
return
if(!requirements_met && !operational)
if(check_status())
requirements_met = TRUE
update_icon(UPDATE_OVERLAYS)
return
if(requirements_met && !operational)
if(prob(20))
operational = TRUE
update_icon(UPDATE_OVERLAYS)
return
if(!requirements_met && operational) // If it loses requirements, it wont immediately turn off
if(istype(held_rod, /obj/item/nuclear_rod/coolant))
if(prob(15)) // Higher rates of coolant rod failures once they're already on. Good luck.
operational = FALSE
update_icon(UPDATE_OVERLAYS)
else if(prob(1))
enriching = FALSE
operational = FALSE
update_icon(UPDATE_OVERLAYS)
return
/obj/machinery/atmospherics/reactor_chamber/process_atmos()
if(!held_rod || !linked_reactor || linked_reactor.offline)
return
if(chamber_state != CHAMBER_OPEN && chamber_state != CHAMBER_UP)
return
if(linked_reactor.admin_intervention)
return
var/datum/milla_safe/chamber_process/milla = new()
milla.invoke_async(src)
/datum/milla_safe/chamber_process
/datum/milla_safe/chamber_process/on_run(obj/machinery/atmospherics/reactor_chamber/chamber)
var/turf/T = get_turf(chamber)
var/datum/gas_mixture/environment = get_turf_air(T)
if(isnull(T)) // We have a null turf...something is wrong, stop processing this entity.
return PROCESS_KILL
if(!istype(chamber.loc, /turf)) // How in the FUCK did we manage this
return // Yeah just stop.
if(T.density)
var/turf/did_it_melt = T.ChangeTurf(T.baseturf)
if(!did_it_melt.density) // In case some joker finds way to place these on indestructible walls
chamber.visible_message(SPAN_WARNING("[chamber] melts through [T]!"))
return
var/heat_capacity = environment.heat_capacity()
var/heat_change = max(chamber.heat_total / heat_capacity) * HEAT_MODIFIER // the hotter the rod, the hotter the air
var/temp = environment.temperature()
if(chamber.chamber_state == CHAMBER_UP) // Its not fully exposed yet, and heating the reactor
heat_change *= 0.25
heat_change = max(heat_change, 1) // Always heat up at least a little
environment.set_temperature(temp + heat_change)
/// Calculate how much heat and energy we should be making
/obj/machinery/atmospherics/reactor_chamber/proc/calculate_stats(operating_rate = 0)
power_total = (held_rod.power_amount * operating_rate)
heat_total = (held_rod.heat_amount * operating_rate)
power_mod_total = 1
heat_mod_total = 1
for(var/obj/machinery/atmospherics/reactor_chamber/chamber in neighbors)
if(!chamber.held_rod || chamber.chamber_state == CHAMBER_OPEN)
continue
if(istype(chamber.held_rod, /obj/item/nuclear_rod/coolant) && !chamber.operational) // Do not apply negative heat gen on coolant when not on.
heat_mod_total *= 1
else if(held_rod.heat_amount > 0) // Do not multiply negative heat.
heat_mod_total *= chamber.held_rod.current_heat_mod // We generate heat even when its not operational
if(operational && chamber.chamber_state == CHAMBER_DOWN)
if(held_rod.power_amount > 0) // Do not multiply negative power.
power_mod_total *= chamber.held_rod.current_power_mod
power_total *= power_mod_total
heat_total *= heat_mod_total
/obj/machinery/atmospherics/reactor_chamber/proc/eject_rod()
raise(FALSE)
open(FALSE)
var/datum/effect_system/smoke_spread/bad/smoke = new()
smoke.set_up(5, FALSE, loc)
smoke.start()
var/rad_type = pick(ALPHA_RAD, BETA_RAD, GAMMA_RAD)
for(var/turf/T in view(2, loc))
T.contaminate_atom(src, 300, rad_type)
var/distance_traveled = rand(10, 60)
var/angle = rand(0, 360)
var/turf/end = get_turf_in_angle(angle, loc, distance_traveled)
var/obj/effect/immovablerod/nuclear_rod/nuclear_rod = new(loc, end)
var/matrix/M = new
M.Turn(angle)
nuclear_rod.transform = M
nuclear_rod.icon = held_rod.icon
nuclear_rod.icon_state = held_rod.icon_state
nuclear_rod.held_rod = held_rod
held_rod.forceMove(src)
held_rod = null
update_icon(UPDATE_OVERLAYS)
playsound(src, 'sound/effects/bang.ogg', 70, TRUE)
audible_message(SPAN_USERDANGER("POW!"))
/obj/machinery/atmospherics/reactor_chamber/proc/weld_shut()
welded = TRUE
playsound(loc, 'sound/items/welder2.ogg', 60, TRUE)
update_icon(UPDATE_OVERLAYS)
/obj/machinery/atmospherics/reactor_chamber/proc/unweld()
welded = FALSE
playsound(loc, 'sound/items/welder2.ogg', 60, TRUE)
update_icon(UPDATE_OVERLAYS)
/obj/machinery/atmospherics/reactor_chamber/proc/burn_handler(mob/user)
var/burn_damage = CHAMBER_HEAT_DAMAGE
if(linked_reactor.check_overheating()) // Ouch, even hotter!
burn_damage *= 2
if(istype(user, /mob/living/carbon/human))
var/mob/living/carbon/human/H = user
if(H.gloves)
var/obj/item/clothing/gloves/G = H.gloves
if(G.max_heat_protection_temperature)
burn_damage *= 0.5
else if(HAS_TRAIT(H, TRAIT_RESISTHEAT) || HAS_TRAIT(H, TRAIT_RESISTHEATHANDS))
burn_damage *= 0.5
var/obj/item/organ/external/affecting = H.get_organ("[user.hand ? "l" : "r" ]_hand")
if(affecting.receive_damage(0, burn_damage)) // Burn damage to them fingers
H.UpdateDamageIcon()
H.updatehealth()
else if(isliving(user))
var/mob/living/L = user
if(issilicon(L)) // More resistant by default
burn_damage *= 0.5
L.adjustFireLoss(burn_damage)
/obj/machinery/atmospherics/reactor_chamber/proc/check_minimum_modifier()
if(!linked_reactor)
return
if(!held_rod)
return
if(!held_rod.minimum_temp_modifier)
return
if(held_rod.minimum_temp_modifier >= linked_reactor.minimum_operating_temp)
linked_reactor.update_minimum_temp()
/obj/effect/immovablerod/nuclear_rod
name = "\improper Nuclear Coolant Rod"
desc = "Getting hit by this might make you wish you got radiation sickness instead."
notify = FALSE
var/obj/held_rod
/// Lets not break the reactor with this.
/obj/effect/immovablerod/nuclear_rod/clong_thing(atom/victim)
if(istype(victim, /obj/machinery/atmospherics/fission_reactor))
return
if(istype(victim, /obj/structure/filler))
var/obj/structure/filler/filler = victim
if(istype(filler.parent, /obj/machinery/atmospherics/fission_reactor))
return
if(istype(victim, /obj/machinery/atmospherics/reactor_chamber))
return
if(isobj(victim) && victim.density)
victim.ex_act(EXPLODE_HEAVY)
else if(ismob(victim))
if(ishuman(victim))
var/mob/living/carbon/human/H = victim
H.visible_message(SPAN_DANGER("[H.name] is penetrated by an ejected coolant rod!"),
SPAN_USERDANGER("The rod penetrates you!"),
SPAN_DANGER("You hear a CLANG!"))
H.adjustBruteLoss(100) // Not as strong as a normal rod
if(victim.density || prob(20)) // We want to hit more things than a normal rod though
victim.ex_act(EXPLODE_HEAVY)
/obj/effect/immovablerod/nuclear_rod/Move()
. = ..()
if(loc == end)
qdel(src)
/obj/effect/immovablerod/nuclear_rod/Destroy()
held_rod.forceMove(get_turf(src))
return ..()
#undef CHAMBER_HEAT_DAMAGE

View File

@@ -312,6 +312,16 @@
build_path = /obj/item/circuitboard/singulo_monitor
category = list("Computer Boards")
/datum/design/nuclear_monitor
name = "Console Board (Nuclear Reactor Monitoring)"
desc = "Allows for the construction of circuit boards used to build a nuclear reactor monitoring console."
id = "nuclear_monitor"
req_tech = list("programming" = 2, "powerstorage" = 2)
build_type = IMPRINTER
materials = list(MAT_GLASS = 1000)
build_path = /obj/item/circuitboard/fission_monitor
category = list("Computer Boards")
/datum/design/ordercomp
name = "Console Board (Supply Ordering Console)"
desc = "Allows for the construction of circuit boards used to build a supply ordering console."

View File

@@ -106,3 +106,64 @@
materials = list(MAT_GLASS = 1000)
build_path = /obj/item/circuitboard/grounding_rod
category = list("Engineering Machinery")
/datum/design/centrifuge
name = "Machine Design (Nuclear Centrifuge Board)"
desc = "The circuit board for a nuclear centrifuge."
id = "nuclear_centrifuge"
req_tech = list("programming" = 3, "materials" = 5, "magnets" = 5, "plasmatech" = 3)
build_type = IMPRINTER
materials = list(MAT_GOLD = 1000, MAT_GLASS = 1000)
build_path = /obj/item/circuitboard/nuclear_centrifuge
category = list("Power", "Engineering Machinery")
/datum/design/rod_fabricator
name = "Machine Design (Nuclear Rod Fabricator Board)"
desc = "The circuit board for a nuclear rod fabricator."
id = "nuclear_fabricator"
req_tech = list("programming" = 5, "materials" = 5, "magnets" = 4, "plasmatech" = 3)
build_type = IMPRINTER
materials = list(MAT_GOLD = 1000, MAT_GLASS = 1000)
build_path = /obj/item/circuitboard/nuclear_rod_fabricator
category = list("Power", "Engineering Machinery")
/datum/design/nuclear_gas_node
name = "Machine Design (Nuclear Gas Node Board)"
desc = "The circuit board for a nuclear gas node."
id = "nuclear_gas_node"
req_tech = list("programming" = 4, "materials" = 4, "magnets" = 4, "plasmatech" = 3)
build_type = IMPRINTER
materials = list(MAT_GOLD = 1000, MAT_GLASS = 1000)
build_path = /obj/item/circuitboard/machine/reactor_gas_node
category = list("Power", "Engineering Machinery")
/datum/design/rod_fabricator_upgrade
name = "Nuclear Rod Fabricator Upgrade"
desc = "A design disk containing a dizzying amount of designs and improvements for nuclear rod fabrication."
id = "nuclear_fab_upgrade"
req_tech = list("programming" = 5, "materials" = 5, "magnets" = 4, "plasmatech" = 3, "toxins" = 3)
build_type = PROTOLATHE
materials = list(MAT_METAL = 2000, MAT_GLASS = 2000, MAT_URANIUM = 500, MAT_GOLD = 400)
build_path = /obj/item/rod_fabricator_upgrade
category = list("Power", "Engineering Machinery", "Misc")
/datum/design/reactor_chamber
name = "Machine Design (Reactor Chamber Board)"
desc = "A chamber used to house nuclear rods of various types to facilitate a fission reaction."
id = "reactor_chamber"
req_tech = list("programming" = 4, "materials" = 4, "magnets" = 4, "plasmatech" = 3)
build_type = IMPRINTER
materials = list(MAT_GLASS = 2000)
build_path = /obj/item/circuitboard/machine/reactor_chamber
category = list("Power", "Engineering Machinery", "Misc")
/datum/design/neutron_grenade
name = "Neutron Agitator Grenade"
desc = "A throwable device capable of inducing an artificial startup in rod chambers."
id = "neutron_grenade"
req_tech = list("materials" = 6, "magnets" = 5, "plasmatech" = 5, "toxins" = 5)
build_type = PROTOLATHE
materials = list(MAT_METAL = 2000, MAT_PLASMA = 2000, MAT_GOLD = 2000)
build_path = /obj/item/grenade/nuclear_starter
category = list("Power", "Misc")

View File

@@ -143,3 +143,8 @@
status_display_data = "deltaalert"
elevating_to_announcement_title = "Attention! Delta security level reached!"
elevating_to_announcement_text = "The station's self-destruct mechanism has been engaged. All crew are instructed to abandon the station immediately. This is not a drill."
/datum/security_level/delta/overload
number_level = SEC_LEVEL_DELTA_REACTOR
elevating_to_announcement_title = "Attention! Delta-AZ5 security level reached!"
elevating_to_announcement_text = "Central Command has disabled all nuclear fission reactor failsafes. Crew are instructed to ensure detonation of the station fission reactor at all costs."

View File

@@ -0,0 +1,83 @@
/obj/item/smithed_item/component/rod_housing
name = "Debug rod housing"
desc = ABSTRACT_TYPE_DESC
icon_state = "rod_housing"
part_type = PART_PRIMARY
/obj/item/smithed_item/component/rod_housing/plasma_agitator
name = "plasma agitator cladding"
desc = "The primary structural housing of a plasma agitator."
materials = list(MAT_METAL = 6000, MAT_GOLD = 2000)
finished_product = /obj/item/nuclear_rod/moderator/plasma_agitator
/obj/item/smithed_item/component/rod_housing/aluminum_reflector
name = "aluminum reflector cladding"
desc = "The primary structural housing of an aluminum reflector."
materials = list(MAT_METAL = 6000, MAT_GOLD = 2000)
finished_product = /obj/item/nuclear_rod/moderator/aluminum_reflector
/obj/item/smithed_item/component/rod_housing/molten_salt
name = "molten salt circulator cladding"
desc = "The primary structural housing of a molten salt circultor."
materials = list(MAT_METAL = 6000, MAT_GLASS = 4000)
finished_product = /obj/item/nuclear_rod/coolant/molten_salt
/obj/item/smithed_item/component/rod_housing/steam_hammerjet
name = "steam hammerjet cladding"
desc = "The primary structural housing of a steam hammerjet."
materials = list(MAT_METAL = 6000, MAT_GLASS = 4000)
finished_product = /obj/item/nuclear_rod/coolant/steam_hammerjet
/obj/item/smithed_item/component/rod_housing/platinum_refelctor
name = "platinum plate cladding"
desc = "The primary structural housing of a platinum reflector plate."
materials = list(MAT_METAL = 6000, MAT_TITANIUM = 2000)
finished_product = /obj/item/nuclear_rod/moderator/platinum_plating
/obj/item/smithed_item/component/rod_housing/iridium_conductor
name = "iridium conductor cladding"
desc = "The primary structural housing of an iridium conductor."
materials = list(MAT_METAL = 6000, MAT_TITANIUM = 2000)
finished_product = /obj/item/nuclear_rod/coolant/iridium_conductor
/obj/item/smithed_item/component/rod_core
name = "Debug rod core"
desc = ABSTRACT_TYPE_DESC
icon_state = "rod_core"
part_type = PART_SECONDARY
/obj/item/smithed_item/component/rod_core/plasma_agitator
name = "plasma agitator core"
desc = "This is the primary core structure of a plasma agitator."
materials = list(MAT_TITANIUM = 2000, MAT_PLASMA = 6000)
finished_product = /obj/item/nuclear_rod/moderator/plasma_agitator
/obj/item/smithed_item/component/rod_core/aluminum_reflector
name = "aluminum reflector core"
desc = "This is the primary core structure of an aluminum reflector."
materials = list(MAT_TITANIUM = 2000, MAT_SILVER = 4000)
finished_product = /obj/item/nuclear_rod/moderator/aluminum_reflector
/obj/item/smithed_item/component/rod_core/molten_salt
name = "molten salt circulator core"
desc = "This is the primary core structure of a molten salt circulator."
materials = list(MAT_TITANIUM = 4000)
finished_product = /obj/item/nuclear_rod/coolant/molten_salt
/obj/item/smithed_item/component/rod_core/steam_hammerjet
name = "steam hammerjet core"
desc = "This is the primary core structure of a steam hammerjet."
materials = list(MAT_TITANIUM = 2000, MAT_GOLD = 2000)
finished_product = /obj/item/nuclear_rod/coolant/steam_hammerjet
/obj/item/smithed_item/component/rod_core/platinum_refelctor
name = "platinum reflector core"
desc = "This is the primary core structure of a platinum reflector."
materials = list(MAT_TITANIUM = 2000, MAT_PLATINUM = 2000)
finished_product = /obj/item/nuclear_rod/moderator/platinum_plating
/obj/item/smithed_item/component/rod_core/iridium_conductor
name = "iridium conductor core"
desc = "This is the primary core structure of an iridium conductor."
materials = list(MAT_TITANIUM = 2000, MAT_IRIDIUM = 2000)
finished_product = /obj/item/nuclear_rod/coolant/iridium_conductor

View File

@@ -289,6 +289,8 @@
extra_product.material = current_product.material
extra_product.set_stats()
product = extra_product
else if(istype(finished_product, /obj/item/nuclear_rod))
product = new finished_product.type(get_turf(src))
product.update_appearance(UPDATE_NAME)
product.scatter_atom()

View File

@@ -180,6 +180,26 @@
product_type = /obj/item/smithed_item/component/knife_handle
basin_state = "cast_knife_handle"
/obj/item/smithing_cast/component/rod_housing
name = "rod housing cast"
icon_state = "rod_housing_cast"
desc = "A cast for creating a nuclear rod housing frame."
product_type = /obj/item/smithed_item/component/rod_housing
basin_state = "cast_rod_housing"
/obj/item/smithing_cast/component/rod_housing/AltClick(mob/user)
return
/obj/item/smithing_cast/component/rod_core
name = "rod core cast"
icon_state = "rod_core_cast"
desc = "A cast for creating a nuclear rod core."
product_type = /obj/item/smithed_item/component/rod_core
basin_state = "cast_rod_core"
/obj/item/smithing_cast/component/rod_core/AltClick(mob/user)
return
/obj/item/smithing_cast/component/trim
name = "trim cast"
icon_state = "trim_cast"

View File

@@ -134,6 +134,12 @@ GLOBAL_LIST_INIT(non_simple_animals, typecacheof(list(/mob/living/carbon/human/m
density = TRUE
anchored = TRUE
invisibility = 101
/// Keeps track of what the multitile is connected to
var/parent
/obj/structure/filler/Destroy()
parent = null
. = ..()
/obj/structure/filler/ex_act()
return

View File

@@ -216,6 +216,54 @@
cost = 750 //So cargo thinks twice before killing themselves with it
containername = "supermatter shard crate"
/datum/supply_packs/engineering/nuclear_supermatter_rod
name = "Nuclear Supermatter Rod Crate"
contains = list(
/obj/item/nuclear_rod/fuel/supermatter,
/obj/item/nuclear_rod/fuel/supermatter,
)
cost = 400
containertype = /obj/structure/closet/crate/secure/engineering
containername = "nuclear supermatter rod crate"
/datum/supply_packs/engineering/nuclear_supermatter_kit
name = "Nuclear Supermatter Rods Starter Crate"
contains = list(
/obj/item/nuclear_rod/fuel/supermatter,
/obj/item/nuclear_rod/fuel/supermatter,
/obj/item/nuclear_rod/coolant/steam_hammerjet,
/obj/item/nuclear_rod/coolant/steam_hammerjet,
/obj/item/nuclear_rod/moderator/plasma_agitator,
/obj/item/nuclear_rod/moderator/plasma_agitator
)
cost = 800
containertype = /obj/structure/closet/crate/secure/engineering
containername = "nuclear supermatter starter crate"
/datum/supply_packs/engineering/nuclear_moderator_rods
name = "Forged Nuclear Moderator crate"
contains = list(
/obj/item/nuclear_rod/moderator/plasma_agitator,
/obj/item/nuclear_rod/moderator/plasma_agitator,
/obj/item/nuclear_rod/moderator/aluminum_reflector,
/obj/item/nuclear_rod/moderator/aluminum_reflector
)
cost = 600
containertype = /obj/structure/closet/crate/secure/engineering
containername = "Forged Nuclear Moderator crate"
/datum/supply_packs/engineering/nuclear_coolant_rods
name = "Forged Nuclear Coolant crate"
contains = list(
/obj/item/nuclear_rod/coolant/steam_hammerjet,
/obj/item/nuclear_rod/coolant/steam_hammerjet,
/obj/item/nuclear_rod/coolant/molten_salt,
/obj/item/nuclear_rod/coolant/molten_salt
)
cost = 600
containertype = /obj/structure/closet/crate/secure/engineering
containername = "Forged Nuclear Coolant crate"
/* Commented out as the TEG is fully problematic. If the syndie base is changed to be dependant on another powersource, we can look at a rework.
/datum/supply_packs/engineering/engine/teg
name = "Thermo-Electric Generator Crate"