mirror of
https://github.com/CHOMPStation2/CHOMPStation2.git
synced 2025-12-11 02:34:00 +00:00
Ports R-UST from Baystation12 + small admin debug verb
This commit is contained in:
@@ -74,6 +74,7 @@
|
||||
#define XGM_GAS_FUEL 1
|
||||
#define XGM_GAS_OXIDIZER 2
|
||||
#define XGM_GAS_CONTAMINANT 4
|
||||
#define XGM_GAS_FUSION_FUEL 8
|
||||
|
||||
#define TANK_LEAK_PRESSURE (30.*ONE_ATMOSPHERE) // Tank starts leaking.
|
||||
#define TANK_RUPTURE_PRESSURE (40.*ONE_ATMOSPHERE) // Tank spills all contents into atmosphere.
|
||||
@@ -94,3 +95,6 @@
|
||||
#define ATMOSTANK_CO2 25000 // CO2 and PH are not critically important for station, only for toxins and alternative coolants, no need to store a lot of those.
|
||||
#define ATMOSTANK_PHORON 25000
|
||||
#define ATMOSTANK_NITROUSOXIDE 10000 // N2O doesn't have a real useful use, i guess it's on station just to allow refilling of sec's riot control canisters?
|
||||
|
||||
//R-UST port
|
||||
#define GAS_FUEL "fuel"
|
||||
@@ -198,3 +198,6 @@
|
||||
#define TSC_GIL "Gilthari"
|
||||
|
||||
#define MIDNIGHT_ROLLOVER 864000 //number of deciseconds in a day
|
||||
|
||||
#define WORLD_ICON_SIZE 32 //Needed for the R-UST port
|
||||
#define PIXEL_MULTIPLIER WORLD_ICON_SIZE/32 //Needed for the R-UST port
|
||||
|
||||
@@ -18,6 +18,24 @@
|
||||
specific_heat = 30 // J/(mol*K)
|
||||
molar_mass = 0.044 // kg/mol
|
||||
|
||||
//R-UST port
|
||||
/decl/xgm_gas/fuel
|
||||
id = GAS_FUEL
|
||||
name = "Fuel"
|
||||
|
||||
//Note that this has a significant impact on TTV yield.
|
||||
//Because it is so high, any leftover phoron soaks up a lot of heat and drops the yield pressure.
|
||||
specific_heat = 200 // J/(mol*K)
|
||||
|
||||
//Hypothetical group 14 (same as carbon), period 8 element.
|
||||
//Using multiplicity rule, it's atomic number is 162
|
||||
//and following a N/Z ratio of 1.5, the molar mass of a monatomic gas is:
|
||||
molar_mass = 0.405 // kg/mol
|
||||
|
||||
tile_overlay = "gas_dense"
|
||||
overlay_limit = 0.7
|
||||
flags = XGM_GAS_FUEL | XGM_GAS_CONTAMINANT | XGM_GAS_FUSION_FUEL
|
||||
|
||||
/decl/xgm_gas/phoron
|
||||
id = "phoron"
|
||||
name = "Phoron"
|
||||
|
||||
@@ -428,3 +428,23 @@ update_flag
|
||||
|
||||
src.update_icon()
|
||||
return 1
|
||||
|
||||
//R-UST port
|
||||
// Special types used for engine setup admin verb, they contain double amount of that of normal canister.
|
||||
/obj/machinery/portable_atmospherics/canister/nitrogen/engine_setup/New()
|
||||
..()
|
||||
src.air_contents.adjust_gas("nitrogen", MolesForPressure())
|
||||
src.update_icon()
|
||||
return 1
|
||||
|
||||
/obj/machinery/portable_atmospherics/canister/carbon_dioxide/engine_setup/New()
|
||||
..()
|
||||
src.air_contents.adjust_gas("carbon_dioxide", MolesForPressure())
|
||||
src.update_icon()
|
||||
return 1
|
||||
|
||||
/obj/machinery/portable_atmospherics/canister/phoron/engine_setup/New()
|
||||
..()
|
||||
src.air_contents.adjust_gas(GAS_FUEL, MolesForPressure())
|
||||
src.update_icon()
|
||||
return 1
|
||||
@@ -147,6 +147,48 @@
|
||||
</body>
|
||||
</html>"}
|
||||
|
||||
//R-UST port
|
||||
/obj/item/weapon/book/manual/rust_engine
|
||||
name = "R-UST Operating Manual"
|
||||
icon_state = "bookSupermatter"
|
||||
author = "Cindy Crawfish"
|
||||
title = "R-UST Operating Manual"
|
||||
|
||||
/obj/item/weapon/book/manual/rust_engine/New()
|
||||
..()
|
||||
dat = {"<html>
|
||||
<head>
|
||||
<style>
|
||||
h1 {font-size: 18px; margin: 15px 0px 5px;}
|
||||
h2 {font-size: 15px; margin: 15px 0px 5px;}
|
||||
li {margin: 2px 0px 2px 15px;}
|
||||
ul {margin: 5px; padding: 0px;}
|
||||
ol {margin: 5px; padding: 0px 15px;}
|
||||
body {font-size: 13px; font-family: Verdana;}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<i>This guide appears to have been scribbled in haste on the back of a WetSkrell magazine...</i>
|
||||
<br><br>
|
||||
<ol>
|
||||
<li>Put uranium in the portable generator near the gyrotron and turn it to full. This is to provide initial power to the core.</li>
|
||||
<li>Enable and max output on the SMES in the engine room. This is to power the gyrotron.</li>
|
||||
<li>Go into the control room, interact with the fusion core control console. Turn the field on and raise size to 501. Any bigger and it will start EMPing the doors. Any smaller and the fuel pellets might miss.</li>
|
||||
<li>Interact with the gyrotron control computer, set power as high as the SMES can support, usually around 4, and turn it on. This will start increasing the plasma temperature to the point where reactions can occur.</li>
|
||||
<li>Go into the engine room and insert a deuterium fuel assembly and a tritium fuel assembly into two of the fuel injectors. You can make deuterium rods in the fuel compressor if you want to play it safe.</li>
|
||||
<li>Go back to the control room and turn the fuel injectors on. This will start firing pellets into the field.</li>
|
||||
<li>Wait for reactions to start (plasma temperature will spike and fuel amounts will drop). Turn the gyrotron power down until it's keeping up with field instability. This will prevent cumulative instability from the deuterium-tritium reaction fucking up the field. If you're using straight deuterium instability isn't a problem and you can turn the gyrotron off.</li>
|
||||
<li>Configure the SMES, turn the PACMAN off before it explodes.</li>
|
||||
</ol>
|
||||
<br>
|
||||
<b>NOTES FOR NEWBIES</b>
|
||||
<br>
|
||||
Anything touching the field will mess with its stability and eventually cause it to rupture. Rupturing is bad. Use the gyrotron to keep instability down if you're running the engine on unstable fuel.
|
||||
<br><br>
|
||||
Likewise, no matter how sad the core seems, don't fucking hug it, you'll blow the field out and set the engine room on fire.
|
||||
</body>
|
||||
</html>"}
|
||||
|
||||
/obj/item/weapon/book/manual/engineering_hacking
|
||||
name = "Hacking"
|
||||
icon_state ="bookHacking"
|
||||
|
||||
@@ -158,6 +158,17 @@
|
||||
default_type = "osmium"
|
||||
apply_colour = 1
|
||||
|
||||
//R-UST port
|
||||
// Fusion fuel.
|
||||
/obj/item/stack/material/deuterium
|
||||
name = "deuterium"
|
||||
icon_state = "sheet-silver"
|
||||
default_type = "deuterium"
|
||||
apply_colour = 1
|
||||
|
||||
/obj/item/stack/material/deuterium/fifty
|
||||
amount = 50
|
||||
|
||||
/obj/item/stack/material/steel
|
||||
name = DEFAULT_WALL_MATERIAL
|
||||
icon_state = "sheet-metal"
|
||||
|
||||
@@ -69,6 +69,7 @@ var/list/name_to_material
|
||||
var/flags = 0 // Various status modifiers.
|
||||
var/sheet_singular_name = "sheet"
|
||||
var/sheet_plural_name = "sheets"
|
||||
var/is_fusion_fuel
|
||||
|
||||
// Shards/tables/structures
|
||||
var/shard_type = SHARD_SHRAPNEL // Path of debris object.
|
||||
@@ -97,6 +98,7 @@ var/list/name_to_material
|
||||
var/conductive = 1 // Objects with this var add CONDUCTS to flags on spawn.
|
||||
var/conductivity = null // How conductive the material is. Iron acts as the baseline, at 10.
|
||||
var/list/composite_material // If set, object matter var will be a list containing these values.
|
||||
var/luminescence
|
||||
|
||||
// Placeholder vars for the time being, todo properly integrate windows/light tiles/rods.
|
||||
var/created_window
|
||||
@@ -270,6 +272,22 @@ var/list/name_to_material
|
||||
sheet_singular_name = "ingot"
|
||||
sheet_plural_name = "ingots"
|
||||
|
||||
//R-UST port
|
||||
/material/supermatter
|
||||
name = "supermatter"
|
||||
icon_colour = "#FFFF00"
|
||||
radioactivity = 20
|
||||
stack_type = null
|
||||
luminescence = 3
|
||||
ignition_point = PHORON_MINIMUM_BURN_TEMPERATURE
|
||||
icon_base = "stone"
|
||||
shard_type = SHARD_SHARD
|
||||
hardness = 30
|
||||
door_icon_base = "stone"
|
||||
sheet_singular_name = "crystal"
|
||||
sheet_plural_name = "crystals"
|
||||
is_fusion_fuel = 1
|
||||
|
||||
/material/phoron
|
||||
name = "phoron"
|
||||
stack_type = /obj/item/stack/material/phoron
|
||||
@@ -567,6 +585,16 @@ var/list/name_to_material
|
||||
stack_origin_tech = list(TECH_MATERIAL = 5)
|
||||
sheet_singular_name = "ingot"
|
||||
sheet_plural_name = "ingots"
|
||||
is_fusion_fuel = 1
|
||||
|
||||
/material/deuterium
|
||||
name = "deuterium"
|
||||
stack_type = /obj/item/stack/material/deuterium
|
||||
icon_colour = "#999999"
|
||||
stack_origin_tech = list(TECH_MATERIAL = 3)
|
||||
sheet_singular_name = "ingot"
|
||||
sheet_plural_name = "ingots"
|
||||
is_fusion_fuel = 1
|
||||
|
||||
/material/mhydrogen
|
||||
name = "mhydrogen"
|
||||
@@ -574,6 +602,7 @@ var/list/name_to_material
|
||||
icon_colour = "#E6C5DE"
|
||||
stack_origin_tech = list(TECH_MATERIAL = 6, TECH_POWER = 6, TECH_MAGNET = 5)
|
||||
conductivity = 100
|
||||
is_fusion_fuel = 1
|
||||
|
||||
/material/platinum
|
||||
name = "platinum"
|
||||
|
||||
83
code/modules/power/fusion/_setup.dm
Normal file
83
code/modules/power/fusion/_setup.dm
Normal file
@@ -0,0 +1,83 @@
|
||||
// temperature of the core of the sun
|
||||
#define FUSION_HEAT_CAP 1.57e7
|
||||
|
||||
#define SETUP_OK 1 // All good
|
||||
#define SETUP_WARNING 2 // Something that shouldn't happen happened, but it's not critical so we will continue
|
||||
#define SETUP_ERROR 3 // Something bad happened, and it's important so we won't continue setup.
|
||||
#define SETUP_DELAYED 4 // Wait for other things first.
|
||||
|
||||
/datum/admins/proc/setup_fusion()
|
||||
set category = "Debug"
|
||||
set name = "Setup Fusion Core"
|
||||
set desc = "Allows you to start the R-UST engine."
|
||||
|
||||
if (!istype(src,/datum/admins))
|
||||
src = usr.client.holder
|
||||
if (!istype(src,/datum/admins))
|
||||
to_chat(usr, "Error: you are not an admin!")
|
||||
return
|
||||
|
||||
if(!(locate(/obj/machinery/power/fusion_core/mapped) in world))
|
||||
to_chat(usr, "This map is not appropriate for this verb.")
|
||||
return
|
||||
|
||||
var/response = input(usr, "Are you sure?", "Engine setup") as null|anything in list("No", "Yes")
|
||||
if(!response || response == "No")
|
||||
return
|
||||
|
||||
var/errors = 0
|
||||
var/warnings = 0
|
||||
var/success = 0
|
||||
|
||||
log_and_message_admins("## FUSION CORE SETUP - Setup initiated by [usr].")
|
||||
|
||||
for(var/obj/machinery/fusion_fuel_injector/mapped/injector in machines)
|
||||
injector.cur_assembly = new /obj/item/weapon/fuel_assembly/deuterium(injector)
|
||||
injector.BeginInjecting()
|
||||
|
||||
var/obj/machinery/power/fusion_core/mapped/core = locate() in machines
|
||||
if(core.jumpstart(15000))
|
||||
var/list/delayed_objects = list()
|
||||
|
||||
// SETUP PHASE
|
||||
for(var/obj/effect/engine_setup/S in world)
|
||||
var/result = S.activate(0)
|
||||
switch(result)
|
||||
if(SETUP_OK)
|
||||
success++
|
||||
continue
|
||||
if(SETUP_WARNING)
|
||||
warnings++
|
||||
continue
|
||||
if(SETUP_ERROR)
|
||||
errors++
|
||||
log_and_message_admins("## FUSION CORE SETUP - Error encountered! Aborting.")
|
||||
break
|
||||
if(SETUP_DELAYED)
|
||||
delayed_objects.Add(S)
|
||||
continue
|
||||
|
||||
if(!errors)
|
||||
for(var/obj/effect/engine_setup/S in delayed_objects)
|
||||
var/result = S.activate(1)
|
||||
switch(result)
|
||||
if(SETUP_OK)
|
||||
success++
|
||||
continue
|
||||
if(SETUP_WARNING)
|
||||
warnings++
|
||||
continue
|
||||
if(SETUP_ERROR)
|
||||
errors++
|
||||
log_and_message_admins("## FUSION CORE SETUP - Error encountered! Aborting.")
|
||||
break
|
||||
else
|
||||
log_and_message_admins("## FUSION CORE SETUP - Error encountered! Aborting.")
|
||||
errors++
|
||||
|
||||
log_and_message_admins("## FUSION CORE SETUP - Setup completed with [errors] errors, [warnings] warnings and [success] successful steps.")
|
||||
|
||||
#undef SETUP_OK
|
||||
#undef SETUP_WARNING
|
||||
#undef SETUP_ERROR
|
||||
#undef SETUP_DELAYED
|
||||
131
code/modules/power/fusion/core/_core.dm
Normal file
131
code/modules/power/fusion/core/_core.dm
Normal file
@@ -0,0 +1,131 @@
|
||||
/*
|
||||
TODO README
|
||||
*/
|
||||
|
||||
var/list/fusion_cores = list()
|
||||
|
||||
#define MAX_FIELD_STR 1000
|
||||
#define MIN_FIELD_STR 1
|
||||
|
||||
/obj/machinery/power/fusion_core
|
||||
name = "\improper R-UST Mk. 8 Tokamak core"
|
||||
desc = "An enormous solenoid for generating extremely high power electromagnetic fields. It includes a kinetic energy harvester."
|
||||
icon = 'icons/obj/machines/power/fusion.dmi'
|
||||
icon_state = "core0"
|
||||
density = 1
|
||||
use_power = 1
|
||||
idle_power_usage = 50
|
||||
active_power_usage = 500 //multiplied by field strength
|
||||
anchored = 0
|
||||
|
||||
var/obj/effect/fusion_em_field/owned_field
|
||||
var/field_strength = 1//0.01
|
||||
var/id_tag
|
||||
|
||||
/obj/machinery/power/fusion_core/mapped
|
||||
anchored = 1
|
||||
|
||||
/obj/machinery/power/fusion_core/initialize()
|
||||
. = ..()
|
||||
connect_to_network()
|
||||
fusion_cores += src
|
||||
|
||||
/obj/machinery/power/fusion_core/Destroy()
|
||||
for(var/obj/machinery/computer/fusion_core_control/FCC in machines)
|
||||
FCC.connected_devices -= src
|
||||
if(FCC.cur_viewed_device == src)
|
||||
FCC.cur_viewed_device = null
|
||||
fusion_cores -= src
|
||||
return ..()
|
||||
|
||||
/obj/machinery/power/fusion_core/process()
|
||||
if((stat & BROKEN) || !powernet || !owned_field)
|
||||
Shutdown()
|
||||
|
||||
/obj/machinery/power/fusion_core/Topic(href, href_list)
|
||||
if(..())
|
||||
return 1
|
||||
if(href_list["str"])
|
||||
var/dif = text2num(href_list["str"])
|
||||
field_strength = min(max(field_strength + dif, MIN_FIELD_STR), MAX_FIELD_STR)
|
||||
active_power_usage = 500 * field_strength
|
||||
if(owned_field)
|
||||
owned_field.ChangeFieldStrength(field_strength)
|
||||
|
||||
/obj/machinery/power/fusion_core/proc/Startup()
|
||||
if(owned_field)
|
||||
return
|
||||
owned_field = new(loc, src)
|
||||
owned_field.ChangeFieldStrength(field_strength)
|
||||
icon_state = "core1"
|
||||
use_power = 2
|
||||
. = 1
|
||||
|
||||
/obj/machinery/power/fusion_core/proc/Shutdown(var/force_rupture)
|
||||
if(owned_field)
|
||||
icon_state = "core0"
|
||||
if(force_rupture || owned_field.plasma_temperature > 1000)
|
||||
owned_field.Rupture()
|
||||
else
|
||||
owned_field.RadiateAll()
|
||||
qdel(owned_field)
|
||||
owned_field = null
|
||||
use_power = 1
|
||||
|
||||
/obj/machinery/power/fusion_core/proc/AddParticles(var/name, var/quantity = 1)
|
||||
if(owned_field)
|
||||
owned_field.AddParticles(name, quantity)
|
||||
. = 1
|
||||
|
||||
/obj/machinery/power/fusion_core/bullet_act(var/obj/item/projectile/Proj)
|
||||
if(owned_field)
|
||||
. = owned_field.bullet_act(Proj)
|
||||
|
||||
/obj/machinery/power/fusion_core/proc/set_strength(var/value)
|
||||
value = Clamp(value, MIN_FIELD_STR, MAX_FIELD_STR)
|
||||
field_strength = value
|
||||
active_power_usage = 5 * value
|
||||
if(owned_field)
|
||||
owned_field.ChangeFieldStrength(value)
|
||||
|
||||
/obj/machinery/power/fusion_core/attack_hand(var/mob/user)
|
||||
if(!Adjacent(user)) // As funny as it was for the AI to hug-kill the tokamak field from a distance...
|
||||
return
|
||||
visible_message("<span class='notice'>\The [user] hugs \the [src] to make it feel better!</span>")
|
||||
if(owned_field)
|
||||
Shutdown()
|
||||
|
||||
/obj/machinery/power/fusion_core/attackby(var/obj/item/W, var/mob/user)
|
||||
|
||||
if(owned_field)
|
||||
to_chat(user,"<span class='warning'>Shut \the [src] off first!</span>")
|
||||
return
|
||||
|
||||
if(ismultitool(W))
|
||||
var/new_ident = input("Enter a new ident tag.", "Fusion Core", id_tag) as null|text
|
||||
if(new_ident && user.Adjacent(src))
|
||||
id_tag = new_ident
|
||||
return
|
||||
|
||||
else if(iswrench(W))
|
||||
anchored = !anchored
|
||||
playsound(src.loc, 'sound/items/Ratchet.ogg', 75, 1)
|
||||
if(anchored)
|
||||
user.visible_message("[user.name] secures [src.name] to the floor.", \
|
||||
"You secure the [src.name] to the floor.", \
|
||||
"You hear a ratchet")
|
||||
else
|
||||
user.visible_message("[user.name] unsecures [src.name] from the floor.", \
|
||||
"You unsecure the [src.name] from the floor.", \
|
||||
"You hear a ratchet")
|
||||
return
|
||||
|
||||
return ..()
|
||||
|
||||
/obj/machinery/power/fusion_core/proc/jumpstart(var/field_temperature)
|
||||
field_strength = 501 // Generally a good size.
|
||||
Startup()
|
||||
if(!owned_field)
|
||||
return FALSE
|
||||
owned_field.plasma_temperature = field_temperature
|
||||
return TRUE
|
||||
176
code/modules/power/fusion/core/core_control.dm
Normal file
176
code/modules/power/fusion/core/core_control.dm
Normal file
@@ -0,0 +1,176 @@
|
||||
/obj/machinery/computer/fusion_core_control
|
||||
name = "\improper R-UST Mk. 8 core control"
|
||||
icon = 'icons/obj/machines/power/fusion.dmi'
|
||||
icon_state = "core_control"
|
||||
light_color = COLOR_ORANGE
|
||||
|
||||
var/id_tag
|
||||
var/scan_range = 25
|
||||
var/list/connected_devices = list()
|
||||
var/obj/machinery/power/fusion_core/cur_viewed_device
|
||||
|
||||
/obj/machinery/computer/fusion_core_control/attackby(var/obj/item/thing, var/mob/user)
|
||||
if(ismultitool(thing))
|
||||
var/new_ident = input("Enter a new ident tag.", "Core Control", id_tag) as null|text
|
||||
if(new_ident && user.Adjacent(src))
|
||||
id_tag = new_ident
|
||||
cur_viewed_device = null
|
||||
return
|
||||
else
|
||||
return ..()
|
||||
|
||||
/obj/machinery/computer/fusion_core_control/attack_ai(mob/user)
|
||||
attack_hand(user)
|
||||
|
||||
/obj/machinery/computer/fusion_core_control/attack_hand(mob/user)
|
||||
add_fingerprint(user)
|
||||
interact(user)
|
||||
|
||||
/obj/machinery/computer/fusion_core_control/interact(mob/user)
|
||||
|
||||
if(!cur_viewed_device || !check_core_status(cur_viewed_device))
|
||||
cur_viewed_device = null
|
||||
|
||||
if(!id_tag)
|
||||
to_chat(user, "<span class='warning'>This console has not been assigned an ident tag. Please contact your system administrator or conduct a manual update with a standard multitool.</span>")
|
||||
return
|
||||
|
||||
if(cur_viewed_device && (cur_viewed_device.id_tag != id_tag || get_dist(src, cur_viewed_device) > scan_range))
|
||||
cur_viewed_device = null
|
||||
|
||||
var/dat = "<B>Core Control #[id_tag]</B><BR>"
|
||||
|
||||
if(cur_viewed_device)
|
||||
dat += {"
|
||||
<a href='?src=\ref[src];goto_scanlist=1'>Back to overview</a><hr>
|
||||
Device ident '[cur_viewed_device.id_tag]' <span style='color: [cur_viewed_device.owned_field ? "green" : "red"]'>[cur_viewed_device.owned_field ? "active" : "inactive"].</span><br>
|
||||
<b>Power status:</b> [cur_viewed_device.avail()]/[cur_viewed_device.active_power_usage] W<br>
|
||||
<hr>
|
||||
<a href='?src=\ref[src];toggle_active=1'>Bring field [cur_viewed_device.owned_field ? "offline" : "online"].</a><br>
|
||||
<hr>
|
||||
<b>Field power density (W.m<sup>-3</sup>):</b><br>
|
||||
<a href='?src=\ref[src];str=-1000'>----</a>
|
||||
<a href='?src=\ref[src];str=-100'>--- </a>
|
||||
<a href='?src=\ref[src];str=-10'>-- </a>
|
||||
<a href='?src=\ref[src];str=-1'>- </a>
|
||||
<a href='?src=\ref[src];str=0'>[cur_viewed_device.field_strength]</a>
|
||||
<a href='?src=\ref[src];str=1'>+ </a>
|
||||
<a href='?src=\ref[src];str=10'>++ </a>
|
||||
<a href='?src=\ref[src];str=100'>+++ </a>
|
||||
<a href='?src=\ref[src];str=1000'>++++</a><hr>
|
||||
"}
|
||||
|
||||
if(cur_viewed_device.owned_field)
|
||||
dat += {"
|
||||
<b>Approximate field diameter (m):</b> [cur_viewed_device.owned_field.size]<br>
|
||||
<b>Field instability:</b> [cur_viewed_device.owned_field.percent_unstable * 100]%<br>
|
||||
<b>Plasma temperature:</b> [cur_viewed_device.owned_field.plasma_temperature + 295]K<hr>
|
||||
<b>Fuel:</b><br>
|
||||
<table><tr><th><b>Name</b></th><th><b>Amount</b></th></tr>
|
||||
"}
|
||||
for(var/reagent in cur_viewed_device.owned_field.dormant_reactant_quantities)
|
||||
dat += "<tr><td>[reagent]</td><td>[cur_viewed_device.owned_field.dormant_reactant_quantities[reagent]]</td></tr>"
|
||||
dat += "</table><hr>"
|
||||
|
||||
else
|
||||
|
||||
connected_devices.Cut()
|
||||
for(var/obj/machinery/power/fusion_core/C in fusion_cores)
|
||||
if(C.id_tag == id_tag && get_dist(src, C) <= scan_range)
|
||||
connected_devices += C
|
||||
for(var/obj/machinery/power/fusion_core/C in gyrotrons)
|
||||
if(C.id_tag == id_tag && get_dist(src, C) <= scan_range)
|
||||
connected_devices += C
|
||||
|
||||
if(connected_devices.len)
|
||||
dat += {"
|
||||
<b>Connected EM field generators:</b><hr>
|
||||
<table>
|
||||
<tr>
|
||||
<th><b>Device tag</b></th>
|
||||
<th><b>Status</b></th>
|
||||
<th><b>Controls</b></th>
|
||||
</tr>
|
||||
"}
|
||||
|
||||
for(var/obj/machinery/power/fusion_core/C in connected_devices)
|
||||
var/status
|
||||
var/can_access = 1
|
||||
if(!check_core_status(C))
|
||||
status = "<span style='color: red'>Unresponsive</span>"
|
||||
can_access = 0
|
||||
else if(C.avail() < C.active_power_usage)
|
||||
status = "<span style='color: orange'>Underpowered</span>"
|
||||
else
|
||||
status = "<span style='color: green'>Good</span>"
|
||||
|
||||
dat += {"
|
||||
<tr>
|
||||
<td>[C.id_tag]</td>
|
||||
<td>[status]</td>
|
||||
"}
|
||||
|
||||
if(!can_access)
|
||||
dat += {"
|
||||
<td><span style='color: red'>ERROR</span></td>
|
||||
"}
|
||||
else
|
||||
dat += {"
|
||||
<td><a href=?src=\ref[src];access_device=[connected_devices.Find(C)]'>ACCESS</a></td>
|
||||
"}
|
||||
dat += {"
|
||||
</tr>
|
||||
"}
|
||||
|
||||
else
|
||||
dat += "<span style='color: red'>No electromagnetic field generators connected.</span>"
|
||||
|
||||
var/datum/browser/popup = new(user, "fusion_control", name, 500, 400, src)
|
||||
popup.set_content(dat)
|
||||
popup.open()
|
||||
user.set_machine(src)
|
||||
|
||||
/obj/machinery/computer/fusion_core_control/Topic(href, href_list)
|
||||
. = ..()
|
||||
if(.)
|
||||
return
|
||||
|
||||
if(href_list["access_device"])
|
||||
var/idx = Clamp(text2num(href_list["toggle_active"]), 1, connected_devices.len)
|
||||
cur_viewed_device = connected_devices[idx]
|
||||
updateUsrDialog()
|
||||
return 1
|
||||
|
||||
//All HREFs from this point on require a device anyways.
|
||||
if(!cur_viewed_device || !check_core_status(cur_viewed_device) || cur_viewed_device.id_tag != id_tag || get_dist(src, cur_viewed_device) > scan_range)
|
||||
return
|
||||
|
||||
if(href_list["goto_scanlist"])
|
||||
cur_viewed_device = null
|
||||
updateUsrDialog()
|
||||
return 1
|
||||
|
||||
if(href_list["toggle_active"])
|
||||
if(!cur_viewed_device.Startup()) //Startup() whilst the device is active will return null.
|
||||
cur_viewed_device.Shutdown()
|
||||
updateUsrDialog()
|
||||
return 1
|
||||
|
||||
if(href_list["str"])
|
||||
var/val = text2num(href_list["str"])
|
||||
if(!val) //Value is 0, which is manual entering.
|
||||
cur_viewed_device.set_strength(input("Enter the new field power density (W.m^-3)", "Fusion Control", cur_viewed_device.field_strength) as num)
|
||||
else
|
||||
cur_viewed_device.set_strength(cur_viewed_device.field_strength + val)
|
||||
updateUsrDialog()
|
||||
return 1
|
||||
|
||||
//Returns 1 if the machine can be interacted with via this console.
|
||||
/obj/machinery/computer/fusion_core_control/proc/check_core_status(var/obj/machinery/power/fusion_core/C)
|
||||
if(isnull(C))
|
||||
return
|
||||
if(C.stat & BROKEN)
|
||||
return
|
||||
if(C.idle_power_usage > C.avail())
|
||||
return
|
||||
. = 1
|
||||
494
code/modules/power/fusion/core/core_field.dm
Normal file
494
code/modules/power/fusion/core/core_field.dm
Normal file
@@ -0,0 +1,494 @@
|
||||
#define FUSION_ENERGY_PER_K 20
|
||||
|
||||
/obj/effect/fusion_em_field
|
||||
name = "electromagnetic field"
|
||||
desc = "A coruscating, barely visible field of energy. It is shaped like a slightly flattened torus."
|
||||
icon = 'icons/obj/machines/power/fusion.dmi'
|
||||
icon_state = "emfield_s1"
|
||||
alpha = 50
|
||||
layer = 4
|
||||
light_color = COLOR_BLUE
|
||||
|
||||
var/size = 1
|
||||
var/energy = 0
|
||||
var/plasma_temperature = 0
|
||||
var/radiation = 0
|
||||
var/field_strength = 0.01
|
||||
var/tick_instability = 0
|
||||
var/percent_unstable = 0
|
||||
|
||||
var/obj/machinery/power/fusion_core/owned_core
|
||||
var/list/dormant_reactant_quantities = list()
|
||||
var/list/particle_catchers = list()
|
||||
|
||||
var/list/ignore_types = list(
|
||||
/obj/item/projectile,
|
||||
/obj/effect,
|
||||
/obj/fire,
|
||||
/obj/structure/cable,
|
||||
/obj/machinery/atmospherics,
|
||||
/obj/machinery/air_sensor,
|
||||
/mob/observer/dead
|
||||
)
|
||||
|
||||
var/light_min_range = 2
|
||||
var/light_min_power = 3
|
||||
var/light_max_range = 10
|
||||
var/light_max_power = 10
|
||||
|
||||
var/last_range
|
||||
var/last_power
|
||||
|
||||
/obj/effect/fusion_em_field/New(loc, var/obj/machinery/power/fusion_core/new_owned_core)
|
||||
..()
|
||||
|
||||
set_light(light_min_range,light_min_power)
|
||||
last_range = light_min_range
|
||||
last_power = light_min_power
|
||||
|
||||
owned_core = new_owned_core
|
||||
if(!owned_core)
|
||||
qdel(src)
|
||||
|
||||
//create the gimmicky things to handle field collisions
|
||||
var/obj/effect/fusion_particle_catcher/catcher
|
||||
|
||||
catcher = new (locate(src.x,src.y,src.z))
|
||||
catcher.parent = src
|
||||
catcher.SetSize(1)
|
||||
particle_catchers.Add(catcher)
|
||||
|
||||
catcher = new (locate(src.x-1,src.y,src.z))
|
||||
catcher.parent = src
|
||||
catcher.SetSize(3)
|
||||
particle_catchers.Add(catcher)
|
||||
catcher = new (locate(src.x+1,src.y,src.z))
|
||||
catcher.parent = src
|
||||
catcher.SetSize(3)
|
||||
particle_catchers.Add(catcher)
|
||||
catcher = new (locate(src.x,src.y+1,src.z))
|
||||
catcher.parent = src
|
||||
catcher.SetSize(3)
|
||||
particle_catchers.Add(catcher)
|
||||
catcher = new (locate(src.x,src.y-1,src.z))
|
||||
catcher.parent = src
|
||||
catcher.SetSize(3)
|
||||
particle_catchers.Add(catcher)
|
||||
|
||||
catcher = new (locate(src.x-2,src.y,src.z))
|
||||
catcher.parent = src
|
||||
catcher.SetSize(5)
|
||||
particle_catchers.Add(catcher)
|
||||
catcher = new (locate(src.x+2,src.y,src.z))
|
||||
catcher.parent = src
|
||||
catcher.SetSize(5)
|
||||
particle_catchers.Add(catcher)
|
||||
catcher = new (locate(src.x,src.y+2,src.z))
|
||||
catcher.parent = src
|
||||
catcher.SetSize(5)
|
||||
particle_catchers.Add(catcher)
|
||||
catcher = new (locate(src.x,src.y-2,src.z))
|
||||
catcher.parent = src
|
||||
catcher.SetSize(5)
|
||||
particle_catchers.Add(catcher)
|
||||
|
||||
catcher = new (locate(src.x-3,src.y,src.z))
|
||||
catcher.parent = src
|
||||
catcher.SetSize(7)
|
||||
particle_catchers.Add(catcher)
|
||||
catcher = new (locate(src.x+3,src.y,src.z))
|
||||
catcher.parent = src
|
||||
catcher.SetSize(7)
|
||||
particle_catchers.Add(catcher)
|
||||
catcher = new (locate(src.x,src.y+3,src.z))
|
||||
catcher.parent = src
|
||||
catcher.SetSize(7)
|
||||
particle_catchers.Add(catcher)
|
||||
catcher = new (locate(src.x,src.y-3,src.z))
|
||||
catcher.parent = src
|
||||
catcher.SetSize(7)
|
||||
particle_catchers.Add(catcher)
|
||||
|
||||
processing_objects.Add(src)
|
||||
|
||||
/obj/effect/fusion_em_field/process()
|
||||
//make sure the field generator is still intact
|
||||
if(!owned_core || QDELETED(owned_core))
|
||||
qdel(src)
|
||||
return
|
||||
|
||||
// Take some gas up from our environment.
|
||||
var/added_particles = FALSE
|
||||
var/datum/gas_mixture/uptake_gas = owned_core.loc.return_air()
|
||||
if(uptake_gas)
|
||||
uptake_gas = uptake_gas.remove_by_flag(XGM_GAS_FUSION_FUEL, rand(50,100))
|
||||
if(uptake_gas && uptake_gas.total_moles)
|
||||
for(var/gasname in uptake_gas.gas)
|
||||
if(uptake_gas.gas[gasname]*10 > dormant_reactant_quantities[gasname])
|
||||
AddParticles(gasname, uptake_gas.gas[gasname]*10)
|
||||
uptake_gas.adjust_gas(gasname, -(uptake_gas.gas[gasname]), update=FALSE)
|
||||
added_particles = TRUE
|
||||
if(added_particles)
|
||||
uptake_gas.update_values()
|
||||
|
||||
//let the particles inside the field react
|
||||
React()
|
||||
|
||||
// Dump power to our powernet.
|
||||
owned_core.add_avail(FUSION_ENERGY_PER_K * plasma_temperature)
|
||||
|
||||
// Energy decay.
|
||||
if(plasma_temperature >= 1)
|
||||
var/lost = plasma_temperature*0.01
|
||||
radiation += lost
|
||||
plasma_temperature -= lost
|
||||
|
||||
//handle some reactants formatting
|
||||
for(var/reactant in dormant_reactant_quantities)
|
||||
var/amount = dormant_reactant_quantities[reactant]
|
||||
if(amount < 1)
|
||||
dormant_reactant_quantities.Remove(reactant)
|
||||
else if(amount >= 1000000)
|
||||
var/radiate = rand(3 * amount / 4, amount / 4)
|
||||
dormant_reactant_quantities[reactant] -= radiate
|
||||
radiation += radiate
|
||||
|
||||
var/use_range
|
||||
var/use_power
|
||||
if(plasma_temperature <= 6000)
|
||||
use_range = light_min_range
|
||||
use_power = light_min_power
|
||||
else if(plasma_temperature >= 25000)
|
||||
use_range = light_max_range
|
||||
use_power = light_max_power
|
||||
else
|
||||
var/temp_mod = ((plasma_temperature-5000)/20000)
|
||||
use_range = light_min_range + ceil((light_max_range-light_min_range)*temp_mod)
|
||||
use_power = light_min_power + ceil((light_max_power-light_min_power)*temp_mod)
|
||||
|
||||
if(last_range != use_range || last_power != use_power)
|
||||
set_light(use_range,use_power)
|
||||
last_range = use_range
|
||||
last_power = use_power
|
||||
|
||||
check_instability()
|
||||
Radiate()
|
||||
if(radiation)
|
||||
radiation_repository.radiate(src, radiation)
|
||||
return 1
|
||||
|
||||
/obj/effect/fusion_em_field/proc/check_instability()
|
||||
if(tick_instability > 0)
|
||||
percent_unstable += (tick_instability*size)/10000
|
||||
tick_instability = 0
|
||||
else
|
||||
if(percent_unstable < 0)
|
||||
percent_unstable = 0
|
||||
else
|
||||
if(percent_unstable > 100)
|
||||
percent_unstable = 100
|
||||
if(percent_unstable > 0)
|
||||
percent_unstable = max(0, percent_unstable-rand(0.01,0.03))
|
||||
|
||||
if(percent_unstable >= 1)
|
||||
owned_core.Shutdown(force_rupture=1)
|
||||
else
|
||||
if(percent_unstable > 0.5 && prob(percent_unstable*100))
|
||||
if(plasma_temperature < 2000)
|
||||
visible_message("<span class='danger'>\The [src] ripples uneasily, like a disturbed pond.</span>")
|
||||
else
|
||||
var/flare
|
||||
var/fuel_loss
|
||||
var/rupture
|
||||
if(percent_unstable < 0.7)
|
||||
visible_message("<span class='danger'>\The [src] ripples uneasily, like a disturbed pond.</span>")
|
||||
fuel_loss = prob(5)
|
||||
else if(percent_unstable < 0.9)
|
||||
visible_message("<span class='danger'>\The [src] undulates violently, shedding plumes of plasma!</span>")
|
||||
flare = prob(50)
|
||||
fuel_loss = prob(20)
|
||||
rupture = prob(5)
|
||||
else
|
||||
visible_message("<span class='danger'>\The [src] is wracked by a series of horrendous distortions, buckling and twisting like a living thing!</span>")
|
||||
flare = 1
|
||||
fuel_loss = prob(50)
|
||||
rupture = prob(25)
|
||||
|
||||
if(rupture)
|
||||
owned_core.Shutdown(force_rupture=1)
|
||||
else
|
||||
var/lost_plasma = (plasma_temperature*percent_unstable)
|
||||
radiation += lost_plasma
|
||||
if(flare)
|
||||
radiation += plasma_temperature/2
|
||||
plasma_temperature -= lost_plasma
|
||||
|
||||
if(fuel_loss)
|
||||
for(var/particle in dormant_reactant_quantities)
|
||||
var/lost_fuel = dormant_reactant_quantities[particle]*percent_unstable
|
||||
radiation += lost_fuel
|
||||
dormant_reactant_quantities[particle] -= lost_fuel
|
||||
if(dormant_reactant_quantities[particle] <= 0)
|
||||
dormant_reactant_quantities.Remove(particle)
|
||||
Radiate()
|
||||
return
|
||||
|
||||
/obj/effect/fusion_em_field/proc/Rupture()
|
||||
visible_message("<span class='danger'>\The [src] shudders like a dying animal before flaring to eye-searing brightness and rupturing!</span>")
|
||||
set_light(15, 15, "#CCCCFF")
|
||||
empulse(get_turf(src), ceil(plasma_temperature/1000), ceil(plasma_temperature/300))
|
||||
sleep(5)
|
||||
RadiateAll()
|
||||
explosion(get_turf(owned_core),-1,-1,8,10) // Blow out all the windows.
|
||||
return
|
||||
|
||||
/obj/effect/fusion_em_field/proc/ChangeFieldStrength(var/new_strength)
|
||||
var/calc_size = 1
|
||||
if(new_strength <= 50)
|
||||
calc_size = 1
|
||||
else if(new_strength <= 200)
|
||||
calc_size = 3
|
||||
else if(new_strength <= 500)
|
||||
calc_size = 5
|
||||
else
|
||||
calc_size = 7
|
||||
field_strength = new_strength
|
||||
change_size(calc_size)
|
||||
|
||||
/obj/effect/fusion_em_field/proc/AddEnergy(var/a_energy, var/a_plasma_temperature)
|
||||
energy += a_energy
|
||||
plasma_temperature += a_plasma_temperature
|
||||
if(a_energy && percent_unstable > 0)
|
||||
percent_unstable -= a_energy/10000
|
||||
if(percent_unstable < 0)
|
||||
percent_unstable = 0
|
||||
while(energy >= 100)
|
||||
energy -= 100
|
||||
plasma_temperature += 1
|
||||
|
||||
/obj/effect/fusion_em_field/proc/AddParticles(var/name, var/quantity = 1)
|
||||
if(name in dormant_reactant_quantities)
|
||||
dormant_reactant_quantities[name] += quantity
|
||||
else if(name != "proton" && name != "electron" && name != "neutron")
|
||||
dormant_reactant_quantities.Add(name)
|
||||
dormant_reactant_quantities[name] = quantity
|
||||
|
||||
/obj/effect/fusion_em_field/proc/RadiateAll(var/ratio_lost = 1)
|
||||
|
||||
// Create our plasma field and dump it into our environment.
|
||||
var/turf/T = get_turf(src)
|
||||
if(istype(T))
|
||||
var/datum/gas_mixture/plasma = new
|
||||
plasma.adjust_gas("oxygen", (size*100), 0)
|
||||
plasma.adjust_gas("phoron", (size*100), 0)
|
||||
plasma.temperature = (plasma_temperature/2)
|
||||
plasma.update_values()
|
||||
T.assume_air(plasma)
|
||||
T.hotspot_expose(plasma_temperature)
|
||||
plasma = null
|
||||
|
||||
// Radiate all our unspent fuel and energy.
|
||||
for(var/particle in dormant_reactant_quantities)
|
||||
radiation += dormant_reactant_quantities[particle]
|
||||
dormant_reactant_quantities.Remove(particle)
|
||||
radiation += plasma_temperature/2
|
||||
plasma_temperature = 0
|
||||
|
||||
radiation_repository.radiate(src, radiation)
|
||||
Radiate()
|
||||
|
||||
/obj/effect/fusion_em_field/proc/Radiate()
|
||||
if(istype(loc, /turf))
|
||||
var/empsev = max(1, min(3, ceil(size/2)))
|
||||
for(var/atom/movable/AM in range(max(1,Floor(size/2)), loc))
|
||||
|
||||
if(AM == src || AM == owned_core || !AM.simulated)
|
||||
continue
|
||||
|
||||
var/skip_obstacle
|
||||
for(var/ignore_path in ignore_types)
|
||||
if(istype(AM, ignore_path))
|
||||
skip_obstacle = TRUE
|
||||
break
|
||||
if(skip_obstacle)
|
||||
continue
|
||||
|
||||
log_debug("R-UST DEBUG: [AM] is [AM.type]")
|
||||
AM.visible_message("<span class='danger'>The field buckles visibly around \the [AM]!</span>")
|
||||
tick_instability += rand(15,30)
|
||||
AM.emp_act(empsev)
|
||||
|
||||
if(owned_core && owned_core.loc)
|
||||
var/datum/gas_mixture/environment = owned_core.loc.return_air()
|
||||
if(environment && environment.temperature < (T0C+1000)) // Putting an upper bound on it to stop it being used in a TEG.
|
||||
environment.add_thermal_energy(plasma_temperature*20000)
|
||||
radiation = 0
|
||||
|
||||
/obj/effect/fusion_em_field/proc/change_size(var/newsize = 1)
|
||||
var/changed = 0
|
||||
switch(newsize)
|
||||
if(1)
|
||||
size = 1
|
||||
icon = 'icons/obj/machines/power/fusion.dmi'
|
||||
icon_state = "emfield_s1"
|
||||
pixel_x = 0
|
||||
pixel_y = 0
|
||||
//
|
||||
changed = 1
|
||||
if(3)
|
||||
size = 3
|
||||
icon = 'icons/effects/96x96.dmi'
|
||||
icon_state = "emfield_s3"
|
||||
pixel_x = -32 * PIXEL_MULTIPLIER
|
||||
pixel_y = -32 * PIXEL_MULTIPLIER
|
||||
//
|
||||
changed = 3
|
||||
if(5)
|
||||
size = 5
|
||||
icon = 'icons/effects/160x160.dmi'
|
||||
icon_state = "emfield_s5"
|
||||
pixel_x = -64 * PIXEL_MULTIPLIER
|
||||
pixel_y = -64 * PIXEL_MULTIPLIER
|
||||
//
|
||||
changed = 5
|
||||
if(7)
|
||||
size = 7
|
||||
icon = 'icons/effects/224x224.dmi'
|
||||
icon_state = "emfield_s7"
|
||||
pixel_x = -96 * PIXEL_MULTIPLIER
|
||||
pixel_y = -96 * PIXEL_MULTIPLIER
|
||||
//
|
||||
changed = 7
|
||||
for(var/obj/effect/fusion_particle_catcher/catcher in particle_catchers)
|
||||
catcher.UpdateSize()
|
||||
return changed
|
||||
|
||||
//the !!fun!! part
|
||||
/obj/effect/fusion_em_field/proc/React()
|
||||
//loop through the reactants in random order
|
||||
var/list/react_pool = dormant_reactant_quantities.Copy()
|
||||
|
||||
//cant have any reactions if there aren't any reactants present
|
||||
if(react_pool.len)
|
||||
//determine a random amount to actually react this cycle, and remove it from the standard pool
|
||||
//this is a hack, and quite nonrealistic :(
|
||||
for(var/reactant in react_pool)
|
||||
react_pool[reactant] = rand(Floor(react_pool[reactant]/2),react_pool[reactant])
|
||||
dormant_reactant_quantities[reactant] -= react_pool[reactant]
|
||||
if(!react_pool[reactant])
|
||||
react_pool -= reactant
|
||||
|
||||
//loop through all the reacting reagents, picking out random reactions for them
|
||||
var/list/produced_reactants = new/list
|
||||
var/list/p_react_pool = react_pool.Copy()
|
||||
while(p_react_pool.len)
|
||||
//pick one of the unprocessed reacting reagents randomly
|
||||
var/cur_p_react = pick(p_react_pool)
|
||||
p_react_pool.Remove(cur_p_react)
|
||||
|
||||
//grab all the possible reactants to have a reaction with
|
||||
var/list/possible_s_reacts = react_pool.Copy()
|
||||
//if there is only one of a particular reactant, then it can not react with itself so remove it
|
||||
possible_s_reacts[cur_p_react] -= 1
|
||||
if(possible_s_reacts[cur_p_react] < 1)
|
||||
possible_s_reacts.Remove(cur_p_react)
|
||||
|
||||
//loop through and work out all the possible reactions
|
||||
var/list/possible_reactions = new/list
|
||||
for(var/cur_s_react in possible_s_reacts)
|
||||
if(possible_s_reacts[cur_s_react] < 1)
|
||||
continue
|
||||
var/decl/fusion_reaction/cur_reaction = get_fusion_reaction(cur_p_react, cur_s_react)
|
||||
if(cur_reaction && plasma_temperature >= cur_reaction.minimum_energy_level)
|
||||
possible_reactions.Add(cur_reaction)
|
||||
|
||||
//if there are no possible reactions here, abandon this primary reactant and move on
|
||||
if(!possible_reactions.len)
|
||||
continue
|
||||
|
||||
//split up the reacting atoms between the possible reactions
|
||||
while(possible_reactions.len)
|
||||
var/decl/fusion_reaction/cur_reaction = pick(possible_reactions)
|
||||
possible_reactions.Remove(cur_reaction)
|
||||
|
||||
//set the randmax to be the lower of the two involved reactants
|
||||
var/max_num_reactants = react_pool[cur_reaction.p_react] > react_pool[cur_reaction.s_react] ? \
|
||||
react_pool[cur_reaction.s_react] : react_pool[cur_reaction.p_react]
|
||||
if(max_num_reactants < 1)
|
||||
continue
|
||||
|
||||
//make sure we have enough energy
|
||||
if(plasma_temperature < cur_reaction.minimum_reaction_temperature)
|
||||
continue
|
||||
|
||||
if(plasma_temperature < max_num_reactants * cur_reaction.energy_consumption)
|
||||
max_num_reactants = round(plasma_temperature / cur_reaction.energy_consumption)
|
||||
if(max_num_reactants < 1)
|
||||
continue
|
||||
|
||||
//randomly determined amount to react
|
||||
var/amount_reacting = rand(1, max_num_reactants)
|
||||
|
||||
//removing the reacting substances from the list of substances that are primed to react this cycle
|
||||
//if there aren't enough of that substance (there should be) then modify the reactant amounts accordingly
|
||||
if( react_pool[cur_reaction.p_react] - amount_reacting >= 0 )
|
||||
react_pool[cur_reaction.p_react] -= amount_reacting
|
||||
else
|
||||
amount_reacting = react_pool[cur_reaction.p_react]
|
||||
react_pool[cur_reaction.p_react] = 0
|
||||
//same again for secondary reactant
|
||||
if(react_pool[cur_reaction.s_react] - amount_reacting >= 0 )
|
||||
react_pool[cur_reaction.s_react] -= amount_reacting
|
||||
else
|
||||
react_pool[cur_reaction.p_react] += amount_reacting - react_pool[cur_reaction.p_react]
|
||||
amount_reacting = react_pool[cur_reaction.s_react]
|
||||
react_pool[cur_reaction.s_react] = 0
|
||||
|
||||
plasma_temperature -= max_num_reactants * cur_reaction.energy_consumption // Remove the consumed energy.
|
||||
plasma_temperature += max_num_reactants * cur_reaction.energy_production // Add any produced energy.
|
||||
radiation += max_num_reactants * cur_reaction.radiation // Add any produced radiation.
|
||||
tick_instability += max_num_reactants * cur_reaction.instability
|
||||
|
||||
// Create the reaction products.
|
||||
for(var/reactant in cur_reaction.products)
|
||||
var/success = 0
|
||||
for(var/check_reactant in produced_reactants)
|
||||
if(check_reactant == reactant)
|
||||
produced_reactants[reactant] += cur_reaction.products[reactant] * amount_reacting
|
||||
success = 1
|
||||
break
|
||||
if(!success)
|
||||
produced_reactants[reactant] = cur_reaction.products[reactant] * amount_reacting
|
||||
|
||||
// Handle anything special. If this proc returns true, abort the current reaction.
|
||||
if(cur_reaction.handle_reaction_special(src))
|
||||
return
|
||||
|
||||
// This reaction is done, and can't be repeated this sub-cycle.
|
||||
possible_reactions.Remove(cur_reaction.s_react)
|
||||
|
||||
// Loop through the newly produced reactants and add them to the pool.
|
||||
for(var/reactant in produced_reactants)
|
||||
AddParticles(reactant, produced_reactants[reactant])
|
||||
|
||||
// Check whether there are reactants left, and add them back to the pool.
|
||||
for(var/reactant in react_pool)
|
||||
AddParticles(reactant, react_pool[reactant])
|
||||
|
||||
/obj/effect/fusion_em_field/Destroy()
|
||||
set_light(0)
|
||||
RadiateAll()
|
||||
for(var/obj/effect/fusion_particle_catcher/catcher in particle_catchers)
|
||||
qdel(catcher)
|
||||
if(owned_core)
|
||||
owned_core.owned_field = null
|
||||
owned_core = null
|
||||
processing_objects.Remove(src)
|
||||
. = ..()
|
||||
|
||||
/obj/effect/fusion_em_field/bullet_act(var/obj/item/projectile/Proj)
|
||||
AddEnergy(Proj.damage)
|
||||
update_icon()
|
||||
return 0
|
||||
|
||||
#undef FUSION_HEAT_CAP
|
||||
67
code/modules/power/fusion/fuel_assembly/fuel_assembly.dm
Normal file
67
code/modules/power/fusion/fuel_assembly/fuel_assembly.dm
Normal file
@@ -0,0 +1,67 @@
|
||||
/obj/item/weapon/fuel_assembly
|
||||
name = "fuel rod assembly"
|
||||
icon = 'icons/obj/machines/power/fusion.dmi'
|
||||
icon_state = "fuel_assembly"
|
||||
layer = 4
|
||||
|
||||
var/material_name
|
||||
|
||||
var/percent_depleted = 1
|
||||
var/list/rod_quantities = list()
|
||||
var/fuel_type = "composite"
|
||||
var/fuel_colour
|
||||
var/radioactivity = 0
|
||||
var/const/initial_amount = 300
|
||||
|
||||
/obj/item/weapon/fuel_assembly/New(var/newloc, var/_material, var/_colour)
|
||||
fuel_type = _material
|
||||
fuel_colour = _colour
|
||||
..(newloc)
|
||||
|
||||
/obj/item/weapon/fuel_assembly/initialize()
|
||||
. = ..()
|
||||
var/material/material = get_material_by_name(fuel_type)
|
||||
if(istype(material))
|
||||
name = "[material.use_name] fuel rod assembly"
|
||||
desc = "A fuel rod for a fusion reactor. This one is made from [material.use_name]."
|
||||
fuel_colour = material.icon_colour
|
||||
fuel_type = material.use_name
|
||||
if(material.radioactivity)
|
||||
radioactivity = material.radioactivity
|
||||
desc += " It is warm to the touch."
|
||||
processing_objects += src
|
||||
if(material.luminescence)
|
||||
set_light(material.luminescence, material.luminescence, material.icon_colour)
|
||||
else
|
||||
name = "[fuel_type] fuel rod assembly"
|
||||
desc = "A fuel rod for a fusion reactor. This one is made from [fuel_type]."
|
||||
|
||||
icon_state = "blank"
|
||||
var/image/I = image(icon, "fuel_assembly")
|
||||
I.color = fuel_colour
|
||||
overlays += list(I, image(icon, "fuel_assembly_bracket"))
|
||||
rod_quantities[fuel_type] = initial_amount
|
||||
|
||||
/obj/item/weapon/fuel_assembly/process()
|
||||
if(!radioactivity)
|
||||
return PROCESS_KILL
|
||||
|
||||
if(istype(loc, /turf))
|
||||
radiation_repository.radiate(src, max(1,ceil(radioactivity/30)))
|
||||
|
||||
/obj/item/weapon/fuel_assembly/Destroy()
|
||||
processing_objects -= src
|
||||
return ..()
|
||||
|
||||
// Mapper shorthand.
|
||||
/obj/item/weapon/fuel_assembly/deuterium/New(var/newloc)
|
||||
..(newloc, "deuterium")
|
||||
|
||||
/obj/item/weapon/fuel_assembly/tritium/New(var/newloc)
|
||||
..(newloc, "tritium")
|
||||
|
||||
/obj/item/weapon/fuel_assembly/phoron/New(var/newloc)
|
||||
..(newloc, "phoron")
|
||||
|
||||
/obj/item/weapon/fuel_assembly/supermatter/New(var/newloc)
|
||||
..(newloc, "supermatter")
|
||||
54
code/modules/power/fusion/fuel_assembly/fuel_compressor.dm
Normal file
54
code/modules/power/fusion/fuel_assembly/fuel_compressor.dm
Normal file
@@ -0,0 +1,54 @@
|
||||
/obj/machinery/fusion_fuel_compressor
|
||||
name = "fuel compressor"
|
||||
icon = 'icons/obj/machines/power/fusion.dmi'
|
||||
icon_state = "fuel_compressor1"
|
||||
density = 1
|
||||
anchored = 1
|
||||
layer = 4
|
||||
|
||||
/obj/machinery/fusion_fuel_compressor/MouseDrop_T(var/atom/movable/target, var/mob/user)
|
||||
if(user.incapacitated() || !user.Adjacent(src))
|
||||
return
|
||||
return do_special_fuel_compression(target, user)
|
||||
|
||||
/obj/machinery/fusion_fuel_compressor/proc/do_special_fuel_compression(var/obj/item/thing, var/mob/user)
|
||||
if(istype(thing) && thing.reagents && thing.reagents.total_volume && thing.is_open_container())
|
||||
if(thing.reagents.reagent_list.len > 1)
|
||||
to_chat(user, "<span class='warning'>The contents of \the [thing] are impure and cannot be used as fuel.</span>")
|
||||
return 1
|
||||
if(thing.reagents.total_volume < 50)
|
||||
to_chat(user, "<span class='warning'>You need at least fifty units of material to form a fuel rod.</span>")
|
||||
return 1
|
||||
var/datum/reagent/R = thing.reagents.reagent_list[1]
|
||||
visible_message("<span class='notice'>\The [src] compresses the contents of \the [thing] into a new fuel assembly.</span>")
|
||||
var/obj/item/weapon/fuel_assembly/F = new(get_turf(src), R.id, R.color)
|
||||
thing.reagents.remove_reagent(R.id, R.volume)
|
||||
user.put_in_hands(F)
|
||||
|
||||
else if(istype(thing, /obj/machinery/power/supermatter/shard))
|
||||
var/obj/item/weapon/fuel_assembly/F = new(get_turf(src), "supermatter")
|
||||
visible_message("<span class='notice'>\The [src] compresses the \[thing] into a new fuel assembly.</span>")
|
||||
qdel(thing)
|
||||
user.put_in_hands(F)
|
||||
return 1
|
||||
return 0
|
||||
|
||||
/obj/machinery/fusion_fuel_compressor/attackby(var/obj/item/thing, var/mob/user)
|
||||
if(istype(thing, /obj/item/stack/material))
|
||||
var/obj/item/stack/material/M = thing
|
||||
var/material/mat = M.get_material()
|
||||
if(!mat.is_fusion_fuel)
|
||||
to_chat(user, "<span class='warning'>It would be pointless to make a fuel rod out of [mat.use_name].</span>")
|
||||
return
|
||||
if(M.get_amount() < 25)
|
||||
to_chat(user, "<span class='warning'>You need at least 25 [mat.sheet_plural_name] to make a fuel rod.</span>")
|
||||
return
|
||||
var/obj/item/weapon/fuel_assembly/F = new(get_turf(src), mat.name)
|
||||
visible_message("<span class='notice'>\The [src] compresses the [mat.use_name] into a new fuel assembly.</span>")
|
||||
M.use(25)
|
||||
user.put_in_hands(F)
|
||||
|
||||
else if(do_special_fuel_compression(thing, user))
|
||||
return
|
||||
|
||||
return ..()
|
||||
102
code/modules/power/fusion/fuel_assembly/fuel_control.dm
Normal file
102
code/modules/power/fusion/fuel_assembly/fuel_control.dm
Normal file
@@ -0,0 +1,102 @@
|
||||
/obj/machinery/computer/fusion_fuel_control
|
||||
name = "fuel injection control computer"
|
||||
icon = 'icons/obj/machines/power/fusion.dmi'
|
||||
icon_state = "fuel"
|
||||
|
||||
var/id_tag
|
||||
var/scan_range = 25
|
||||
|
||||
/obj/machinery/computer/fusion_fuel_control/attack_ai(mob/user)
|
||||
attack_hand(user)
|
||||
|
||||
/obj/machinery/computer/fusion_fuel_control/attack_hand(mob/user)
|
||||
add_fingerprint(user)
|
||||
interact(user)
|
||||
|
||||
/obj/machinery/computer/fusion_fuel_control/interact(var/mob/user)
|
||||
|
||||
if(stat & (BROKEN|NOPOWER))
|
||||
user.unset_machine()
|
||||
user << browse(null, "window=fuel_control")
|
||||
return
|
||||
|
||||
if (!istype(user, /mob/living/silicon) && get_dist(src, user) > 1)
|
||||
user.unset_machine()
|
||||
user << browse(null, "window=fuel_control")
|
||||
return
|
||||
|
||||
if(!id_tag)
|
||||
to_chat(user, "<span class='warning'>This console has not been assigned an ident tag. Please contact your system administrator or conduct a manual update with a standard multitool.</span>")
|
||||
return
|
||||
|
||||
var/dat = "<B>Reactor Core Fuel Control #[id_tag]</B><BR>"
|
||||
dat += {"
|
||||
<hr>
|
||||
<table border=1 width='100%'>
|
||||
<tr>
|
||||
<td><b>Contains</b></td>
|
||||
<td><b>Assembly</b></td>
|
||||
<td><b>Remaining</b></td>
|
||||
</tr>"}
|
||||
|
||||
for(var/obj/machinery/fusion_fuel_injector/I in fuel_injectors)
|
||||
if(!id_tag || !I.id_tag || I.id_tag != id_tag || get_dist(src, I) > scan_range)
|
||||
continue
|
||||
|
||||
dat += "<tr>"
|
||||
|
||||
if(I.stat & (BROKEN|NOPOWER))
|
||||
dat += "<td><span class='danger'>ERROR</span></td>"
|
||||
dat += "<td><span class='danger'>ERROR</span></td>"
|
||||
dat += "<td><span class='danger'>ERROR</span></td>"
|
||||
else
|
||||
dat += "<td>[I.cur_assembly ? I.cur_assembly.fuel_type : "NONE"]</td>"
|
||||
if(I.cur_assembly)
|
||||
dat += "<td><a href='?src=\ref[src];toggle_injecting=\ref[I]'>\[[I.injecting ? "Halt injecting" : "Begin injecting"]\]</a></td>"
|
||||
else
|
||||
dat += "<td>None</td>"
|
||||
if(I.cur_assembly)
|
||||
dat += "<td>[I.cur_assembly.percent_depleted * 100]%</td>"
|
||||
else
|
||||
dat += "<td>NA</td>"
|
||||
|
||||
dat += "</tr>"
|
||||
|
||||
dat += {"</table><hr>
|
||||
<A href='?src=\ref[src];refresh=1'>Refresh</A>
|
||||
<A href='?src=\ref[src];close=1'>Close</A><BR>"}
|
||||
|
||||
var/datum/browser/popup = new(user, "fuel_control", "Fusion Fuel Control Console", 800, 400, src)
|
||||
popup.set_content(dat)
|
||||
popup.open()
|
||||
user.set_machine(src)
|
||||
|
||||
/obj/machinery/computer/fusion_fuel_control/Topic(href, href_list)
|
||||
if(..())
|
||||
return 1
|
||||
|
||||
if(href_list["toggle_injecting"])
|
||||
var/obj/machinery/fusion_fuel_injector/I = locate(href_list["toggle_injecting"])
|
||||
if(I.id_tag != id_tag || get_dist(src, I) > scan_range)
|
||||
return
|
||||
|
||||
if(istype(I))
|
||||
if(I.injecting)
|
||||
I.StopInjecting()
|
||||
else
|
||||
I.BeginInjecting()
|
||||
|
||||
if( href_list["close"] )
|
||||
usr << browse(null, "window=fuel_control")
|
||||
usr.unset_machine()
|
||||
|
||||
updateDialog()
|
||||
|
||||
|
||||
/obj/machinery/computer/fusion_fuel_control/attackby(var/obj/item/W, var/mob/user)
|
||||
if(ismultitool(W))
|
||||
var/new_ident = input("Enter a new ident tag.", "Fuel Control", id_tag) as null|text
|
||||
if(new_ident && user.Adjacent(src))
|
||||
id_tag = new_ident
|
||||
return
|
||||
return ..()
|
||||
153
code/modules/power/fusion/fuel_assembly/fuel_injector.dm
Normal file
153
code/modules/power/fusion/fuel_assembly/fuel_injector.dm
Normal file
@@ -0,0 +1,153 @@
|
||||
var/list/fuel_injectors = list()
|
||||
|
||||
/obj/machinery/fusion_fuel_injector
|
||||
name = "fuel injector"
|
||||
icon = 'icons/obj/machines/power/fusion.dmi'
|
||||
icon_state = "injector0"
|
||||
density = 1
|
||||
anchored = 0
|
||||
req_access = list(access_engine)
|
||||
use_power = 1
|
||||
idle_power_usage = 10
|
||||
active_power_usage = 500
|
||||
|
||||
var/fuel_usage = 0.0001
|
||||
var/id_tag
|
||||
var/injecting = 0
|
||||
var/obj/item/weapon/fuel_assembly/cur_assembly
|
||||
|
||||
/obj/machinery/fusion_fuel_injector/New()
|
||||
..()
|
||||
fuel_injectors += src
|
||||
tag = null
|
||||
|
||||
/obj/machinery/fusion_fuel_injector/Destroy()
|
||||
if(cur_assembly)
|
||||
cur_assembly.forceMove(get_turf(src))
|
||||
cur_assembly = null
|
||||
fuel_injectors -= src
|
||||
return ..()
|
||||
|
||||
/obj/machinery/fusion_fuel_injector/mapped
|
||||
anchored = 1
|
||||
|
||||
/obj/machinery/fusion_fuel_injector/process()
|
||||
if(injecting)
|
||||
if(stat & (BROKEN|NOPOWER))
|
||||
StopInjecting()
|
||||
else
|
||||
Inject()
|
||||
|
||||
/obj/machinery/fusion_fuel_injector/attackby(obj/item/W, mob/user)
|
||||
|
||||
if(ismultitool(W))
|
||||
var/new_ident = input("Enter a new ident tag.", "Fuel Injector", id_tag) as null|text
|
||||
if(new_ident && user.Adjacent(src))
|
||||
id_tag = new_ident
|
||||
return
|
||||
|
||||
if(istype(W, /obj/item/weapon/fuel_assembly))
|
||||
|
||||
if(injecting)
|
||||
to_chat(user, "<span class='warning'>Shut \the [src] off before playing with the fuel rod!</span>")
|
||||
return
|
||||
|
||||
if(cur_assembly)
|
||||
cur_assembly.forceMove(get_turf(src))
|
||||
visible_message("<span class='notice'>\The [user] swaps \the [src]'s [cur_assembly] for \a [W].</span>")
|
||||
else
|
||||
visible_message("<span class='notice'>\The [user] inserts \a [W] into \the [src].</span>")
|
||||
|
||||
user.drop_from_inventory(W)
|
||||
W.forceMove(src)
|
||||
if(cur_assembly)
|
||||
cur_assembly.forceMove(get_turf(src))
|
||||
user.put_in_hands(cur_assembly)
|
||||
cur_assembly = W
|
||||
return
|
||||
|
||||
if(iswrench(W))
|
||||
if(injecting)
|
||||
to_chat(user, "<span class='warning'>Shut \the [src] off first!</span>")
|
||||
return
|
||||
anchored = !anchored
|
||||
playsound(src.loc, 'sound/items/Ratchet.ogg', 75, 1)
|
||||
if(anchored)
|
||||
user.visible_message("\The [user] secures \the [src] to the floor.")
|
||||
else
|
||||
user.visible_message("\The [user] unsecures \the [src] from the floor.")
|
||||
return
|
||||
|
||||
return ..()
|
||||
|
||||
/obj/machinery/fusion_fuel_injector/attack_hand(mob/user)
|
||||
|
||||
if(injecting)
|
||||
to_chat(user, "<span class='warning'>Shut \the [src] off before playing with the fuel rod!</span>")
|
||||
return
|
||||
|
||||
if(cur_assembly)
|
||||
cur_assembly.forceMove(get_turf(src))
|
||||
user.put_in_hands(cur_assembly)
|
||||
visible_message("<span class='notice'>\The [user] removes \the [cur_assembly] from \the [src].</span>")
|
||||
cur_assembly = null
|
||||
return
|
||||
else
|
||||
to_chat(user, "<span class='warning'>There is no fuel rod in \the [src].</span>")
|
||||
return
|
||||
|
||||
/obj/machinery/fusion_fuel_injector/proc/BeginInjecting()
|
||||
if(!injecting && cur_assembly)
|
||||
icon_state = "injector1"
|
||||
injecting = 1
|
||||
use_power = 1
|
||||
|
||||
/obj/machinery/fusion_fuel_injector/proc/StopInjecting()
|
||||
if(injecting)
|
||||
injecting = 0
|
||||
icon_state = "injector0"
|
||||
use_power = 0
|
||||
|
||||
/obj/machinery/fusion_fuel_injector/proc/Inject()
|
||||
if(!injecting)
|
||||
return
|
||||
if(cur_assembly)
|
||||
var/amount_left = 0
|
||||
for(var/reagent in cur_assembly.rod_quantities)
|
||||
if(cur_assembly.rod_quantities[reagent] > 0)
|
||||
var/amount = cur_assembly.rod_quantities[reagent] * fuel_usage
|
||||
var/numparticles = round(amount * 1000)
|
||||
if(numparticles < 1)
|
||||
numparticles = 1
|
||||
var/obj/effect/accelerated_particle/A = new/obj/effect/accelerated_particle(get_turf(src), dir)
|
||||
A.particle_type = reagent
|
||||
A.additional_particles = numparticles - 1
|
||||
A.move(1)
|
||||
if(cur_assembly)
|
||||
cur_assembly.rod_quantities[reagent] -= amount
|
||||
amount_left += cur_assembly.rod_quantities[reagent]
|
||||
if(cur_assembly)
|
||||
cur_assembly.percent_depleted = amount_left / cur_assembly.initial_amount
|
||||
flick("injector-emitting",src)
|
||||
else
|
||||
StopInjecting()
|
||||
|
||||
/obj/machinery/fusion_fuel_injector/verb/rotate_clock()
|
||||
set category = "Object"
|
||||
set name = "Rotate Generator (Clockwise)"
|
||||
set src in view(1)
|
||||
|
||||
if (usr.incapacitated() || usr.restrained() || anchored)
|
||||
return
|
||||
|
||||
src.dir = turn(src.dir, -90)
|
||||
|
||||
/obj/machinery/fusion_fuel_injector/verb/rotate_anticlock()
|
||||
set category = "Object"
|
||||
set name = "Rotate Generator (Counter-clockwise)"
|
||||
set src in view(1)
|
||||
|
||||
if (usr.incapacitated() || usr.restrained() || anchored)
|
||||
return
|
||||
|
||||
src.dir = turn(src.dir, 90)
|
||||
89
code/modules/power/fusion/fusion_circuits.dm
Normal file
89
code/modules/power/fusion/fusion_circuits.dm
Normal file
@@ -0,0 +1,89 @@
|
||||
/obj/item/weapon/circuitboard/fusion_core_control
|
||||
name = "circuit board (fusion core controller)"
|
||||
build_path = /obj/machinery/computer/fusion_core_control
|
||||
origin_tech = list(TECH_DATA = 4, TECH_ENGINEERING = 4)
|
||||
|
||||
/obj/item/weapon/circuitboard/fusion_fuel_compressor
|
||||
name = "circuit board (fusion fuel compressor)"
|
||||
build_path = /obj/machinery/fusion_fuel_compressor
|
||||
board_type = "machine"
|
||||
origin_tech = list(TECH_POWER = 3, TECH_ENGINEERING = 4, TECH_MATERIAL = 4)
|
||||
req_components = list(
|
||||
/obj/item/weapon/stock_parts/manipulator/pico = 2,
|
||||
/obj/item/weapon/stock_parts/matter_bin/super = 2,
|
||||
/obj/item/weapon/stock_parts/console_screen = 1,
|
||||
/obj/item/stack/cable_coil = 5
|
||||
)
|
||||
|
||||
/obj/item/weapon/circuitboard/fusion_fuel_control
|
||||
name = "circuit board (fusion fuel controller)"
|
||||
build_path = /obj/machinery/computer/fusion_fuel_control
|
||||
origin_tech = list(TECH_DATA = 4, TECH_ENGINEERING = 4)
|
||||
|
||||
/obj/item/weapon/circuitboard/gyrotron_control
|
||||
name = "circuit board (gyrotron controller)"
|
||||
build_path = /obj/machinery/computer/gyrotron_control
|
||||
origin_tech = list(TECH_DATA = 4, TECH_ENGINEERING = 4)
|
||||
|
||||
/obj/item/weapon/circuitboard/fusion_core
|
||||
name = "internal circuitry (fusion core)"
|
||||
build_path = /obj/machinery/power/fusion_core
|
||||
board_type = "machine"
|
||||
origin_tech = list(TECH_BLUESPACE = 2, TECH_MAGNET = 4, TECH_POWER = 4)
|
||||
req_components = list(
|
||||
/obj/item/weapon/stock_parts/manipulator/pico = 2,
|
||||
/obj/item/weapon/stock_parts/micro_laser/ultra = 1,
|
||||
/obj/item/weapon/stock_parts/subspace/crystal = 1,
|
||||
/obj/item/weapon/stock_parts/console_screen = 1,
|
||||
/obj/item/stack/cable_coil = 5
|
||||
)
|
||||
|
||||
/obj/item/weapon/circuitboard/fusion_injector
|
||||
name = "internal circuitry (fusion fuel injector)"
|
||||
build_path = /obj/machinery/fusion_fuel_injector
|
||||
board_type = "machine"
|
||||
origin_tech = list(TECH_POWER = 3, TECH_ENGINEERING = 4, TECH_MATERIAL = 4)
|
||||
req_components = list(
|
||||
/obj/item/weapon/stock_parts/manipulator/pico = 2,
|
||||
/obj/item/weapon/stock_parts/scanning_module/phasic = 1,
|
||||
/obj/item/weapon/stock_parts/matter_bin/super = 1,
|
||||
/obj/item/weapon/stock_parts/console_screen = 1,
|
||||
/obj/item/stack/cable_coil = 5
|
||||
)
|
||||
|
||||
/datum/design/circuit/fusion
|
||||
name = "fusion core control console"
|
||||
id = "fusion_core_control"
|
||||
build_path = /obj/item/weapon/circuitboard/fusion_core_control
|
||||
sort_string = "LAAAD"
|
||||
req_tech = list(TECH_POWER = 3, TECH_ENGINEERING = 3, TECH_MATERIAL = 3)
|
||||
|
||||
/datum/design/circuit/fusion/fuel_compressor
|
||||
name = "fusion fuel compressor"
|
||||
id = "fusion_fuel_compressor"
|
||||
build_path = /obj/item/weapon/circuitboard/fusion_fuel_compressor
|
||||
sort_string = "LAAAE"
|
||||
|
||||
/datum/design/circuit/fusion/fuel_control
|
||||
name = "fusion fuel control console"
|
||||
id = "fusion_fuel_control"
|
||||
build_path = /obj/item/weapon/circuitboard/fusion_fuel_control
|
||||
sort_string = "LAAAF"
|
||||
|
||||
/datum/design/circuit/fusion/gyrotron_control
|
||||
name = "gyrotron control console"
|
||||
id = "gyrotron_control"
|
||||
build_path = /obj/item/weapon/circuitboard/gyrotron_control
|
||||
sort_string = "LAAAG"
|
||||
|
||||
/datum/design/circuit/fusion/core
|
||||
name = "fusion core"
|
||||
id = "fusion_core"
|
||||
build_path = /obj/item/weapon/circuitboard/fusion_core
|
||||
sort_string = "LAAAH"
|
||||
|
||||
/datum/design/circuit/fusion/injector
|
||||
name = "fusion fuel injector"
|
||||
id = "fusion_injector"
|
||||
build_path = /obj/item/weapon/circuitboard/fusion_injector
|
||||
sort_string = "LAAAI"
|
||||
41
code/modules/power/fusion/fusion_particle_catcher.dm
Normal file
41
code/modules/power/fusion/fusion_particle_catcher.dm
Normal file
@@ -0,0 +1,41 @@
|
||||
/obj/effect/fusion_particle_catcher
|
||||
icon = 'icons/effects/effects.dmi'
|
||||
density = 1
|
||||
anchored = 1
|
||||
invisibility = 101
|
||||
var/obj/effect/fusion_em_field/parent
|
||||
var/mysize = 0
|
||||
|
||||
light_color = COLOR_BLUE
|
||||
|
||||
/obj/effect/fusion_particle_catcher/Destroy()
|
||||
. =..()
|
||||
parent.particle_catchers -= src
|
||||
parent = null
|
||||
|
||||
/obj/effect/fusion_particle_catcher/proc/SetSize(var/newsize)
|
||||
name = "collector [newsize]"
|
||||
mysize = newsize
|
||||
UpdateSize()
|
||||
|
||||
/obj/effect/fusion_particle_catcher/proc/AddParticles(var/name, var/quantity = 1)
|
||||
if(parent && parent.size >= mysize)
|
||||
parent.AddParticles(name, quantity)
|
||||
return 1
|
||||
return 0
|
||||
|
||||
/obj/effect/fusion_particle_catcher/proc/UpdateSize()
|
||||
if(parent.size >= mysize)
|
||||
density = 1
|
||||
name = "collector [mysize] ON"
|
||||
else
|
||||
density = 0
|
||||
name = "collector [mysize] OFF"
|
||||
|
||||
/obj/effect/fusion_particle_catcher/bullet_act(var/obj/item/projectile/Proj)
|
||||
parent.AddEnergy(Proj.damage)
|
||||
update_icon()
|
||||
return 0
|
||||
|
||||
/obj/effect/fusion_particle_catcher/CanPass(var/atom/movable/mover, var/turf/target, var/height=0, var/air_group=0)
|
||||
return ismob(mover)
|
||||
164
code/modules/power/fusion/fusion_reactions.dm
Normal file
164
code/modules/power/fusion/fusion_reactions.dm
Normal file
@@ -0,0 +1,164 @@
|
||||
var/list/fusion_reactions
|
||||
|
||||
/decl/fusion_reaction
|
||||
var/p_react = "" // Primary reactant.
|
||||
var/s_react = "" // Secondary reactant.
|
||||
var/minimum_energy_level = 1
|
||||
var/energy_consumption = 0
|
||||
var/energy_production = 0
|
||||
var/radiation = 0
|
||||
var/instability = 0
|
||||
var/list/products = list()
|
||||
var/minimum_reaction_temperature = 100
|
||||
|
||||
/decl/fusion_reaction/proc/handle_reaction_special(var/obj/effect/fusion_em_field/holder)
|
||||
return 0
|
||||
|
||||
proc/get_fusion_reaction(var/p_react, var/s_react, var/m_energy)
|
||||
if(!fusion_reactions)
|
||||
fusion_reactions = list()
|
||||
for(var/rtype in typesof(/decl/fusion_reaction) - /decl/fusion_reaction)
|
||||
var/decl/fusion_reaction/cur_reaction = new rtype()
|
||||
if(!fusion_reactions[cur_reaction.p_react])
|
||||
fusion_reactions[cur_reaction.p_react] = list()
|
||||
fusion_reactions[cur_reaction.p_react][cur_reaction.s_react] = cur_reaction
|
||||
if(!fusion_reactions[cur_reaction.s_react])
|
||||
fusion_reactions[cur_reaction.s_react] = list()
|
||||
fusion_reactions[cur_reaction.s_react][cur_reaction.p_react] = cur_reaction
|
||||
|
||||
if(fusion_reactions.Find(p_react))
|
||||
var/list/secondary_reactions = fusion_reactions[p_react]
|
||||
if(secondary_reactions.Find(s_react))
|
||||
return fusion_reactions[p_react][s_react]
|
||||
|
||||
// Material fuels
|
||||
// deuterium
|
||||
// tritium
|
||||
// phoron
|
||||
// supermatter
|
||||
|
||||
// Virtual fuels
|
||||
// helium-3
|
||||
// lithium-6
|
||||
// boron-11
|
||||
|
||||
// Basic power production reactions.
|
||||
/decl/fusion_reaction/deuterium_deuterium
|
||||
p_react = "deuterium"
|
||||
s_react = "deuterium"
|
||||
energy_consumption = 1
|
||||
energy_production = 2
|
||||
|
||||
// Advanced production reactions (todo)
|
||||
/decl/fusion_reaction/deuterium_helium
|
||||
p_react = "deuterium"
|
||||
s_react = "helium-3"
|
||||
energy_consumption = 1
|
||||
energy_production = 5
|
||||
radiation = 2
|
||||
|
||||
/decl/fusion_reaction/deuterium_tritium
|
||||
p_react = "deuterium"
|
||||
s_react = "tritium"
|
||||
energy_consumption = 1
|
||||
energy_production = 1
|
||||
products = list("helium-3" = 1)
|
||||
instability = 0.5
|
||||
radiation = 3
|
||||
|
||||
/decl/fusion_reaction/deuterium_lithium
|
||||
p_react = "deuterium"
|
||||
s_react = "lithium"
|
||||
energy_consumption = 2
|
||||
energy_production = 0
|
||||
radiation = 3
|
||||
products = list("tritium"= 1)
|
||||
instability = 1
|
||||
|
||||
// Unideal/material production reactions
|
||||
/decl/fusion_reaction/oxygen_oxygen
|
||||
p_react = "oxygen"
|
||||
s_react = "oxygen"
|
||||
energy_consumption = 10
|
||||
energy_production = 0
|
||||
instability = 5
|
||||
radiation = 5
|
||||
products = list("silicon"= 1)
|
||||
|
||||
/decl/fusion_reaction/iron_iron
|
||||
p_react = "iron"
|
||||
s_react = "iron"
|
||||
products = list("silver" = 1, "gold" = 1, "platinum" = 1) // Not realistic but w/e
|
||||
energy_consumption = 10
|
||||
energy_production = 0
|
||||
instability = 2
|
||||
minimum_reaction_temperature = 10000
|
||||
|
||||
/decl/fusion_reaction/phoron_hydrogen
|
||||
p_react = "hydrogen"
|
||||
s_react = "phoron"
|
||||
energy_consumption = 10
|
||||
energy_production = 0
|
||||
instability = 5
|
||||
products = list("mydrogen" = 1)
|
||||
minimum_reaction_temperature = 8000
|
||||
|
||||
// VERY UNIDEAL REACTIONS.
|
||||
/decl/fusion_reaction/phoron_supermatter
|
||||
p_react = "supermatter"
|
||||
s_react = "phoron"
|
||||
energy_consumption = 0
|
||||
energy_production = 5
|
||||
radiation = 20
|
||||
instability = 20
|
||||
|
||||
/decl/fusion_reaction/phoron_supermatter/handle_reaction_special(var/obj/effect/fusion_em_field/holder)
|
||||
|
||||
wormhole_event()
|
||||
|
||||
var/turf/origin = get_turf(holder)
|
||||
holder.Rupture()
|
||||
qdel(holder)
|
||||
var/radiation_level = rand(100, 200)
|
||||
|
||||
// Copied from the SM for proof of concept. //Not any more --Cirra //Use the whole z proc --Leshana
|
||||
radiation_repository.z_radiate(locate(1, 1, holder.z), radiation_level, 1)
|
||||
|
||||
for(var/mob/living/mob in living_mob_list)
|
||||
var/turf/T = get_turf(mob)
|
||||
if(T && (holder.z == T.z))
|
||||
if(istype(mob, /mob/living/carbon/human))
|
||||
var/mob/living/carbon/human/H = mob
|
||||
H.hallucination += rand(100,150)
|
||||
|
||||
for(var/obj/machinery/fusion_fuel_injector/I in range(world.view, origin))
|
||||
if(I.cur_assembly && I.cur_assembly.fuel_type == "supermatter")
|
||||
explosion(get_turf(I), 1, 2, 3)
|
||||
spawn(5)
|
||||
if(I && I.loc)
|
||||
qdel(I)
|
||||
|
||||
sleep(5)
|
||||
explosion(origin, 1, 2, 5)
|
||||
|
||||
return 1
|
||||
|
||||
|
||||
// High end reactions.
|
||||
/decl/fusion_reaction/boron_hydrogen
|
||||
p_react = "boron"
|
||||
s_react = "hydrogen"
|
||||
minimum_energy_level = FUSION_HEAT_CAP * 0.5
|
||||
energy_consumption = 3
|
||||
energy_production = 15
|
||||
radiation = 3
|
||||
instability = 3
|
||||
|
||||
/decl/fusion_reaction/hydrogen_hydrogen
|
||||
p_react = "hydrogen"
|
||||
s_react = "hydrogen"
|
||||
minimum_energy_level = FUSION_HEAT_CAP * 0.75
|
||||
energy_consumption = 0
|
||||
energy_production = 20
|
||||
radiation = 5
|
||||
instability = 5
|
||||
57
code/modules/power/fusion/gyrotron/gyrotron.dm
Normal file
57
code/modules/power/fusion/gyrotron/gyrotron.dm
Normal file
@@ -0,0 +1,57 @@
|
||||
var/list/gyrotrons = list()
|
||||
|
||||
/obj/machinery/power/emitter/gyrotron
|
||||
name = "gyrotron"
|
||||
icon = 'icons/obj/machines/power/fusion.dmi'
|
||||
desc = "It is a heavy duty industrial gyrotron suited for powering fusion reactors."
|
||||
icon_state = "emitter-off"
|
||||
req_access = list(access_engine)
|
||||
use_power = 1
|
||||
active_power_usage = 50000
|
||||
|
||||
var/id_tag
|
||||
var/rate = 3
|
||||
var/mega_energy = 1
|
||||
|
||||
|
||||
/obj/machinery/power/emitter/gyrotron/anchored
|
||||
anchored = 1
|
||||
state = 2
|
||||
|
||||
/obj/machinery/power/emitter/gyrotron/initialize()
|
||||
gyrotrons += src
|
||||
active_power_usage = mega_energy * 50000
|
||||
. = ..()
|
||||
|
||||
/obj/machinery/power/emitter/gyrotron/Destroy()
|
||||
gyrotrons -= src
|
||||
return ..()
|
||||
|
||||
/obj/machinery/power/emitter/gyrotron/process()
|
||||
active_power_usage = mega_energy * 50000
|
||||
. = ..()
|
||||
|
||||
/obj/machinery/power/emitter/gyrotron/get_rand_burst_delay()
|
||||
return rate * 10
|
||||
|
||||
/obj/machinery/power/emitter/gyrotron/get_burst_delay()
|
||||
return rate * 10
|
||||
|
||||
/obj/machinery/power/emitter/gyrotron/get_emitter_beam()
|
||||
var/obj/item/projectile/beam/emitter/E = ..()
|
||||
E.damage = mega_energy * 50
|
||||
return E
|
||||
|
||||
/obj/machinery/power/emitter/gyrotron/update_icon()
|
||||
if (active && powernet && avail(active_power_usage))
|
||||
icon_state = "emitter-on"
|
||||
else
|
||||
icon_state = "emitter-off"
|
||||
|
||||
/obj/machinery/power/emitter/gyrotron/attackby(var/obj/item/W, var/mob/user)
|
||||
if(ismultitool(W))
|
||||
var/new_ident = input("Enter a new ident tag.", "Gyrotron", id_tag) as null|text
|
||||
if(new_ident && user.Adjacent(src))
|
||||
id_tag = new_ident
|
||||
return
|
||||
return ..()
|
||||
97
code/modules/power/fusion/gyrotron/gyrotron_control.dm
Normal file
97
code/modules/power/fusion/gyrotron/gyrotron_control.dm
Normal file
@@ -0,0 +1,97 @@
|
||||
/obj/machinery/computer/gyrotron_control
|
||||
name = "gyrotron control console"
|
||||
icon = 'icons/obj/machines/power/fusion.dmi'
|
||||
icon_state = "engine"
|
||||
light_color = COLOR_BLUE
|
||||
|
||||
var/id_tag
|
||||
var/scan_range = 25
|
||||
|
||||
/obj/machinery/computer/gyrotron_control/attack_ai(var/mob/user)
|
||||
attack_hand(user)
|
||||
|
||||
/obj/machinery/computer/gyrotron_control/attack_hand(var/mob/user)
|
||||
add_fingerprint(user)
|
||||
interact(user)
|
||||
|
||||
/obj/machinery/computer/gyrotron_control/interact(var/mob/user)
|
||||
|
||||
if(!id_tag)
|
||||
to_chat(user, "<span class='warning'>This console has not been assigned an ident tag. Please contact your system administrator or conduct a manual update with a standard multitool.</span>")
|
||||
return
|
||||
|
||||
var/dat = "<td><b>Gyrotron controller #[id_tag]</b>"
|
||||
|
||||
dat = "<table><tr>"
|
||||
dat += "<td><b>Mode</b></td>"
|
||||
dat += "<td><b>Fire Delay</b></td>"
|
||||
dat += "<td><b>Power</b></td>"
|
||||
dat += "</tr>"
|
||||
|
||||
for(var/obj/machinery/power/emitter/gyrotron/G in gyrotrons)
|
||||
if(!G || G.id_tag != id_tag || get_dist(src, G) > scan_range)
|
||||
continue
|
||||
|
||||
dat += "<tr>"
|
||||
if(G.state != 2 || (G.stat & (NOPOWER | BROKEN))) //Error data not found.
|
||||
dat += "<td><span style='color: red'>ERROR</span></td>"
|
||||
dat += "<td><span style='color: red'>ERROR</span></td>"
|
||||
dat += "<td><span style='color: red'>ERROR</span></td>"
|
||||
else
|
||||
dat += "<td><a href='?src=\ref[src];machine=\ref[G];toggle=1'>[G.active ? "Emitting" : "Standing By"]</a></td>"
|
||||
dat += "<td><a href='?src=\ref[src];machine=\ref[G];modifyrate=1'>[G.rate]</a></td>"
|
||||
dat += "<td><a href='?src=\ref[src];machine=\ref[G];modifypower=1'>[G.mega_energy]</a></td>"
|
||||
|
||||
dat += "</tr></table>"
|
||||
|
||||
var/datum/browser/popup = new(user, "gyrotron_controller_[id_tag]", "Gyrotron Remote Control Console", 500, 400, src)
|
||||
popup.set_content(dat)
|
||||
popup.open()
|
||||
add_fingerprint(user)
|
||||
user.set_machine(src)
|
||||
|
||||
/obj/machinery/computer/gyrotron_control/Topic(var/href, var/list/href_list)
|
||||
. = ..()
|
||||
if(.)
|
||||
return
|
||||
|
||||
if(stat & (NOPOWER | BROKEN))
|
||||
return
|
||||
|
||||
var/obj/machinery/power/emitter/gyrotron/G = locate(href_list["machine"])
|
||||
if(!G || G.id_tag != id_tag || get_dist(src, G) > scan_range)
|
||||
return
|
||||
|
||||
if(href_list["modifypower"])
|
||||
var/new_val = input("Enter new emission power level (1 - 50)", "Modifying power level", G.mega_energy) as num
|
||||
if(!new_val)
|
||||
to_chat(usr, "<span class='warning'>That's not a valid number.</span>")
|
||||
return 1
|
||||
G.mega_energy = Clamp(new_val, 1, 50)
|
||||
G.active_power_usage = G.mega_energy * 1500
|
||||
updateUsrDialog()
|
||||
return 1
|
||||
|
||||
if(href_list["modifyrate"])
|
||||
var/new_val = input("Enter new emission delay between 1 and 10 seconds.", "Modifying emission rate", G.rate) as num
|
||||
if(!new_val)
|
||||
to_chat(usr, "<span class='warning'>That's not a valid number.</span>")
|
||||
return 1
|
||||
G.rate = Clamp(new_val, 1, 10)
|
||||
updateUsrDialog()
|
||||
return 1
|
||||
|
||||
if(href_list["toggle"])
|
||||
G.activate(usr)
|
||||
updateUsrDialog()
|
||||
return 1
|
||||
|
||||
return 0
|
||||
|
||||
/obj/machinery/computer/gyrotron_control/attackby(var/obj/item/W, var/mob/user)
|
||||
if(ismultitool(W))
|
||||
var/new_ident = input("Enter a new ident tag.", "Gyrotron Control", id_tag) as null|text
|
||||
if(new_ident && user.Adjacent(src))
|
||||
id_tag = new_ident
|
||||
return
|
||||
return ..()
|
||||
@@ -75,7 +75,7 @@
|
||||
src.active = 1
|
||||
user << "You turn on [src]."
|
||||
src.shot_number = 0
|
||||
src.fire_delay = 100
|
||||
src.fire_delay = get_initial_fire_delay()
|
||||
message_admins("Emitter turned on by [key_name(user, user.client)](<A HREF='?_src_=holder;adminmoreinfo=\ref[user]'>?</A>) in ([x],[y],[z] - <A HREF='?_src_=holder;adminplayerobservecoodjump=1;X=[x];Y=[y];Z=[z]'>JMP</a>)",0,1)
|
||||
log_game("Emitter turned on by [user.ckey]([user]) in ([x],[y],[z])")
|
||||
investigate_log("turned <font color='green'>on</font> by [user.key]","singulo")
|
||||
@@ -119,10 +119,10 @@
|
||||
|
||||
src.last_shot = world.time
|
||||
if(src.shot_number < burst_shots)
|
||||
src.fire_delay = 2
|
||||
src.fire_delay = get_burst_delay() //R-UST port
|
||||
src.shot_number ++
|
||||
else
|
||||
src.fire_delay = rand(min_burst_delay, max_burst_delay)
|
||||
src.fire_delay = get_rand_burst_delay() //R-UST port
|
||||
src.shot_number = 0
|
||||
|
||||
//need to calculate the power per shot as the emitter doesn't fire continuously.
|
||||
@@ -135,7 +135,7 @@
|
||||
s.set_up(5, 1, src)
|
||||
s.start()
|
||||
|
||||
var/obj/item/projectile/beam/emitter/A = new /obj/item/projectile/beam/emitter( src.loc )
|
||||
var/obj/item/projectile/beam/emitter/A = get_emitter_beam()
|
||||
A.damage = round(power_per_shot/EMITTER_DAMAGE_POWER_TRANSFER)
|
||||
A.launch( get_step(src.loc, src.dir) )
|
||||
|
||||
@@ -266,3 +266,16 @@
|
||||
user << "<span class='danger'>\The [src] is damaged.</span>"
|
||||
if(77 to 99)
|
||||
user << "<span class='warning'>\The [src] is slightly damaged.</span>"
|
||||
|
||||
//R-UST port
|
||||
/obj/machinery/power/emitter/proc/get_initial_fire_delay()
|
||||
return 100
|
||||
|
||||
/obj/machinery/power/emitter/proc/get_rand_burst_delay()
|
||||
return rand(min_burst_delay, max_burst_delay)
|
||||
|
||||
/obj/machinery/power/emitter/proc/get_burst_delay()
|
||||
return 2
|
||||
|
||||
/obj/machinery/power/emitter/proc/get_emitter_beam()
|
||||
return new /obj/item/projectile/beam/emitter(get_turf(src))
|
||||
@@ -43,6 +43,21 @@
|
||||
toxmob(A)
|
||||
if((istype(A,/obj/machinery/the_singularitygen))||(istype(A,/obj/singularity/)))
|
||||
A:energy += energy
|
||||
//R-UST port
|
||||
else if(istype(A,/obj/machinery/power/fusion_core))
|
||||
var/obj/machinery/power/fusion_core/collided_core = A
|
||||
if(particle_type && particle_type != "neutron")
|
||||
if(collided_core.AddParticles(particle_type, 1 + additional_particles))
|
||||
collided_core.owned_field.plasma_temperature += mega_energy
|
||||
collided_core.owned_field.energy += energy
|
||||
loc = null
|
||||
else if(istype(A, /obj/effect/fusion_particle_catcher))
|
||||
var/obj/effect/fusion_particle_catcher/PC = A
|
||||
if(particle_type && particle_type != "neutron")
|
||||
if(PC.parent.owned_core.AddParticles(particle_type, 1 + additional_particles))
|
||||
PC.parent.plasma_temperature += mega_energy
|
||||
PC.parent.energy += energy
|
||||
loc = null
|
||||
return
|
||||
|
||||
|
||||
|
||||
@@ -43,6 +43,31 @@
|
||||
color = "#003333"
|
||||
strength = 10
|
||||
|
||||
//R-UST port
|
||||
// Produced during deuterium synthesis. Super poisonous, SUPER flammable (doesn't need oxygen to burn).
|
||||
/datum/reagent/toxin/phoroxygen
|
||||
name = "Oxyphoron"
|
||||
id = "oxyphoron"
|
||||
description = "An exceptionally flammable molecule formed from deuterium synthesis."
|
||||
strength = 80
|
||||
var/fire_mult = 30
|
||||
|
||||
/datum/reagent/toxin/phoroxygen/touch_mob(var/mob/living/L, var/amount)
|
||||
if(istype(L))
|
||||
L.adjust_fire_stacks(amount / fire_mult)
|
||||
|
||||
/datum/reagent/toxin/phoroxygen/affect_touch(var/mob/living/carbon/M, var/alien, var/removed)
|
||||
M.take_organ_damage(0, removed * 0.1) //being splashed directly with oxyphoron causes minor chemical burns
|
||||
if(prob(10 * fire_mult))
|
||||
M.pl_effects()
|
||||
|
||||
/datum/reagent/toxin/phoroxygen/touch_turf(var/turf/simulated/T)
|
||||
if(!istype(T))
|
||||
return
|
||||
T.assume_gas("oxygen", ceil(volume/2), T20C)
|
||||
T.assume_gas("phoron", ceil(volume/2), T20C)
|
||||
remove_self(volume)
|
||||
|
||||
/datum/reagent/toxin/spidertoxin
|
||||
name = "Spidertoxin"
|
||||
id = "spidertoxin"
|
||||
|
||||
@@ -1842,7 +1842,6 @@
|
||||
required_reagents = list("tea" = 5, "berryjuice" = 1)
|
||||
result_amount = 6
|
||||
|
||||
/datum/chemical_reaction/drinks/sakebomb
|
||||
name = "Sake Bomb"
|
||||
id = "sakebomb"
|
||||
result = "sakebomb"
|
||||
@@ -1863,7 +1862,6 @@
|
||||
required_reagents = list("sake" = 2, "vodka" = 2, "tomatojuice" = 1)
|
||||
result_amount = 5
|
||||
|
||||
/datum/chemical_reaction/drinks/tokyorose
|
||||
name = "Tokyo Rose"
|
||||
id = "tokyorose"
|
||||
result = "tokyorose"
|
||||
@@ -1906,9 +1904,6 @@
|
||||
result_amount = 3
|
||||
|
||||
/datum/chemical_reaction/drinks/euphoria
|
||||
name = "Euphoria"
|
||||
id = "euphoria"
|
||||
result = "euphoria"
|
||||
required_reagents = list("specialwhiskey" = 1, "cognac" = 2)
|
||||
result_amount = 3
|
||||
|
||||
@@ -1916,7 +1911,6 @@
|
||||
name = "Xanadu Cannon"
|
||||
id = "xanaducannon"
|
||||
result = "xanaducannon"
|
||||
required_reagents = list("ale" = 1, "dr_gibb" = 1)
|
||||
result_amount = 2
|
||||
|
||||
/datum/chemical_reaction/drinks/debugger
|
||||
@@ -1946,3 +1940,16 @@
|
||||
result = "chrysanthemum"
|
||||
required_reagents = list("sake" = 1, "melonliquor" = 1)
|
||||
result_amount = 2
|
||||
|
||||
/datum/chemical_reaction/deuterium
|
||||
name = "Deuterium"
|
||||
id = "deuterium"
|
||||
result = null
|
||||
required_reagents = list("water" = 10)
|
||||
catalysts = list("oxyphoron" = 5)
|
||||
result_amount = 1
|
||||
|
||||
/datum/chemical_reaction/deuterium/on_reaction(var/datum/reagents/holder, var/created_volume)
|
||||
var/turf/T = get_turf(holder.my_atom)
|
||||
if(istype(T)) new /obj/item/stack/material/deuterium(T, created_volume)
|
||||
return
|
||||
251
code/modules/supermatter/setup_supermatter.dm
Normal file
251
code/modules/supermatter/setup_supermatter.dm
Normal file
@@ -0,0 +1,251 @@
|
||||
#define SETUP_OK 1 // All good
|
||||
#define SETUP_WARNING 2 // Something that shouldn't happen happened, but it's not critical so we will continue
|
||||
#define SETUP_ERROR 3 // Something bad happened, and it's important so we won't continue setup.
|
||||
#define SETUP_DELAYED 4 // Wait for other things first.
|
||||
|
||||
|
||||
#define ENERGY_NITROGEN 115 // Roughly 8 emitter shots.
|
||||
#define ENERGY_CARBONDIOXIDE 150 // Roughly 10 emitter shots.
|
||||
#define ENERGY_PHORON 300 // Roughly 20 emitter shots. Phoron can take more but this is enough to max out both SMESs anyway.
|
||||
|
||||
|
||||
/datum/admins/proc/setup_supermatter()
|
||||
set category = "Debug"
|
||||
set name = "Setup Supermatter"
|
||||
set desc = "Allows you to start the Supermatter engine."
|
||||
|
||||
if (!istype(src,/datum/admins))
|
||||
src = usr.client.holder
|
||||
if (!istype(src,/datum/admins))
|
||||
to_chat(usr, "Error: you are not an admin!")
|
||||
return
|
||||
|
||||
var/response = input(usr, "Are you sure? This will start up the engine with selected gas as coolant.", "Engine setup") as null|anything in list("N2", "CO2", "PH", "Abort")
|
||||
if(!response || response == "Abort")
|
||||
return
|
||||
|
||||
var/errors = 0
|
||||
var/warnings = 0
|
||||
var/success = 0
|
||||
|
||||
log_and_message_admins("## SUPERMATTER SETUP - Setup initiated by [usr] using coolant type [response].")
|
||||
|
||||
// CONFIGURATION PHASE
|
||||
// Coolant canisters, set types according to response.
|
||||
for(var/obj/effect/engine_setup/coolant_canister/C in world)
|
||||
switch(response)
|
||||
if("N2")
|
||||
C.canister_type = /obj/machinery/portable_atmospherics/canister/nitrogen/engine_setup/
|
||||
continue
|
||||
if("CO2")
|
||||
C.canister_type = /obj/machinery/portable_atmospherics/canister/carbon_dioxide/engine_setup/
|
||||
continue
|
||||
if("PH")
|
||||
C.canister_type = /obj/machinery/portable_atmospherics/canister/phoron/engine_setup/
|
||||
continue
|
||||
|
||||
for(var/obj/effect/engine_setup/core/C in world)
|
||||
switch(response)
|
||||
if("N2")
|
||||
C.energy_setting = ENERGY_NITROGEN
|
||||
continue
|
||||
if("CO2")
|
||||
C.energy_setting = ENERGY_CARBONDIOXIDE
|
||||
continue
|
||||
if("PH")
|
||||
C.energy_setting = ENERGY_PHORON
|
||||
continue
|
||||
|
||||
for(var/obj/effect/engine_setup/filter/F in world)
|
||||
F.coolant = response
|
||||
|
||||
var/list/delayed_objects = list()
|
||||
// SETUP PHASE
|
||||
for(var/obj/effect/engine_setup/S in world)
|
||||
var/result = S.activate(0)
|
||||
switch(result)
|
||||
if(SETUP_OK)
|
||||
success++
|
||||
continue
|
||||
if(SETUP_WARNING)
|
||||
warnings++
|
||||
continue
|
||||
if(SETUP_ERROR)
|
||||
errors++
|
||||
log_and_message_admins("## SUPERMATTER SETUP - Error encountered! Aborting.")
|
||||
break
|
||||
if(SETUP_DELAYED)
|
||||
delayed_objects.Add(S)
|
||||
continue
|
||||
|
||||
if(!errors)
|
||||
for(var/obj/effect/engine_setup/S in delayed_objects)
|
||||
var/result = S.activate(1)
|
||||
switch(result)
|
||||
if(SETUP_OK)
|
||||
success++
|
||||
continue
|
||||
if(SETUP_WARNING)
|
||||
warnings++
|
||||
continue
|
||||
if(SETUP_ERROR)
|
||||
errors++
|
||||
log_and_message_admins("## SUPERMATTER SETUP - Error encountered! Aborting.")
|
||||
break
|
||||
|
||||
log_and_message_admins("## SUPERMATTER SETUP - Setup completed with [errors] errors, [warnings] warnings and [success] successful steps.")
|
||||
|
||||
return
|
||||
|
||||
|
||||
|
||||
/obj/effect/engine_setup/
|
||||
name = "Engine Setup Marker"
|
||||
desc = "You shouldn't see this."
|
||||
invisibility = 101
|
||||
anchored = 1
|
||||
density = 0
|
||||
icon = 'icons/mob/screen1.dmi'
|
||||
icon_state = "x3"
|
||||
|
||||
/obj/effect/engine_setup/proc/activate(var/last = 0)
|
||||
return 1
|
||||
|
||||
|
||||
|
||||
// Tries to locate a pump, enables it, and sets it to MAX. Triggers warning if unable to locate a pump.
|
||||
/obj/effect/engine_setup/pump_max/
|
||||
name = "Pump Setup Marker"
|
||||
|
||||
/obj/effect/engine_setup/pump_max/activate()
|
||||
..()
|
||||
var/obj/machinery/atmospherics/binary/pump/P = locate() in get_turf(src)
|
||||
if(!P)
|
||||
log_and_message_admins("## WARNING: Unable to locate pump at [x] [y] [z]!")
|
||||
return SETUP_WARNING
|
||||
P.target_pressure = P.max_pressure_setting
|
||||
P.use_power = 1
|
||||
P.update_icon()
|
||||
return SETUP_OK
|
||||
|
||||
|
||||
|
||||
// Spawns an empty canister on this turf, if it has a connector port. Triggers warning if unable to find a connector port
|
||||
/obj/effect/engine_setup/empty_canister/
|
||||
name = "Empty Canister Marker"
|
||||
|
||||
/obj/effect/engine_setup/empty_canister/activate()
|
||||
..()
|
||||
var/obj/machinery/atmospherics/portables_connector/P = locate() in get_turf(src)
|
||||
if(!P)
|
||||
log_and_message_admins("## WARNING: Unable to locate connector port at [x] [y] [z]!")
|
||||
return SETUP_WARNING
|
||||
new/obj/machinery/portable_atmospherics/canister(get_turf(src)) // Canisters automatically connect to connectors in New()
|
||||
return SETUP_OK
|
||||
|
||||
|
||||
|
||||
|
||||
// Spawns a coolant canister on this turf, if it has a connector port.
|
||||
// Triggers error when unable to locate connector port or when coolant canister type is unset.
|
||||
/obj/effect/engine_setup/coolant_canister/
|
||||
name = "Coolant Canister Marker"
|
||||
var/canister_type = null
|
||||
|
||||
/obj/effect/engine_setup/coolant_canister/activate()
|
||||
..()
|
||||
var/obj/machinery/atmospherics/portables_connector/P = locate() in get_turf(src)
|
||||
if(!P)
|
||||
log_and_message_admins("## ERROR: Unable to locate coolant connector port at [x] [y] [z]!")
|
||||
return SETUP_ERROR
|
||||
if(!canister_type)
|
||||
log_and_message_admins("## ERROR: Canister type unset at [x] [y] [z]!")
|
||||
return SETUP_ERROR
|
||||
new canister_type(get_turf(src))
|
||||
return SETUP_OK
|
||||
|
||||
|
||||
|
||||
// Energises the supermatter. Errors when unable to locate supermatter.
|
||||
/obj/effect/engine_setup/core/
|
||||
name = "Supermatter Core Marker"
|
||||
var/energy_setting = 0
|
||||
|
||||
/obj/effect/engine_setup/core/activate(var/last = 0)
|
||||
if(!last)
|
||||
return SETUP_DELAYED
|
||||
..()
|
||||
var/obj/machinery/power/supermatter/SM = locate() in get_turf(src)
|
||||
if(!SM)
|
||||
log_and_message_admins("## ERROR: Unable to locate supermatter core at [x] [y] [z]!")
|
||||
return SETUP_ERROR
|
||||
if(!energy_setting)
|
||||
log_and_message_admins("## ERROR: Energy setting unset at [x] [y] [z]!")
|
||||
return SETUP_ERROR
|
||||
SM.power = energy_setting
|
||||
return SETUP_OK
|
||||
|
||||
|
||||
|
||||
// Tries to enable the SMES on max input/output settings. With load balancing it should be fine as long as engine outputs at least ~500kW
|
||||
/obj/effect/engine_setup/smes/
|
||||
name = "SMES Marker"
|
||||
|
||||
/obj/effect/engine_setup/smes/activate()
|
||||
..()
|
||||
var/obj/machinery/power/smes/S = locate() in get_turf(src)
|
||||
if(!S)
|
||||
log_and_message_admins("## WARNING: Unable to locate SMES unit at [x] [y] [z]!")
|
||||
return SETUP_WARNING
|
||||
S.input_attempt = 1
|
||||
S.output_attempt = 1
|
||||
S.input_level = S.input_level_max
|
||||
S.output_level = S.output_level_max
|
||||
S.update_icon()
|
||||
return SETUP_OK
|
||||
|
||||
|
||||
|
||||
// Sets up filters. This assumes filters are set to filter out N2 back to the core loop by default!
|
||||
/obj/effect/engine_setup/filter/
|
||||
name = "Omni Filter Marker"
|
||||
var/coolant = null
|
||||
|
||||
/obj/effect/engine_setup/filter/activate()
|
||||
..()
|
||||
var/obj/machinery/atmospherics/omni/filter/F = locate() in get_turf(src)
|
||||
if(!F)
|
||||
log_and_message_admins("## WARNING: Unable to locate omni filter at [x] [y] [z]!")
|
||||
return SETUP_WARNING
|
||||
if(!coolant)
|
||||
log_and_message_admins("## WARNING: No coolant type set at [x] [y] [z]!")
|
||||
return SETUP_WARNING
|
||||
|
||||
// Non-nitrogen coolant, adjust the filter's config first.
|
||||
if(coolant != "N2")
|
||||
for(var/datum/omni_port/P in F.ports)
|
||||
if(P.mode != ATM_N2)
|
||||
continue
|
||||
if(coolant == "PH")
|
||||
P.mode = ATM_P
|
||||
break
|
||||
else if(coolant == "CO2")
|
||||
P.mode = ATM_CO2
|
||||
break
|
||||
else
|
||||
log_and_message_admins("## WARNING: Inapropriate filter coolant type set at [x] [y] [z]!")
|
||||
return SETUP_WARNING
|
||||
F.rebuild_filtering_list()
|
||||
|
||||
F.use_power = 1
|
||||
F.update_icon()
|
||||
return SETUP_OK
|
||||
|
||||
|
||||
#undef SETUP_OK
|
||||
#undef SETUP_WARNING
|
||||
#undef SETUP_ERROR
|
||||
#undef SETUP_DELAYED
|
||||
#undef ENERGY_NITROGEN
|
||||
#undef ENERGY_CARBONDIOXIDE
|
||||
#undef ENERGY_PHORON
|
||||
BIN
icons/obj/machines/power/fusion.dmi
Normal file
BIN
icons/obj/machines/power/fusion.dmi
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 41 KiB |
14
polaris.dme
14
polaris.dme
@@ -1872,6 +1872,19 @@
|
||||
#include "code\modules\power\antimatter\containment_jar.dm"
|
||||
#include "code\modules\power\antimatter\control.dm"
|
||||
#include "code\modules\power\antimatter\shielding.dm"
|
||||
#include "code\modules\power\fusion\_setup.dm"
|
||||
#include "code\modules\power\fusion\fusion_circuits.dm"
|
||||
#include "code\modules\power\fusion\fusion_particle_catcher.dm"
|
||||
#include "code\modules\power\fusion\fusion_reactions.dm"
|
||||
#include "code\modules\power\fusion\core\_core.dm"
|
||||
#include "code\modules\power\fusion\core\core_control.dm"
|
||||
#include "code\modules\power\fusion\core\core_field.dm"
|
||||
#include "code\modules\power\fusion\fuel_assembly\fuel_assembly.dm"
|
||||
#include "code\modules\power\fusion\fuel_assembly\fuel_compressor.dm"
|
||||
#include "code\modules\power\fusion\fuel_assembly\fuel_control.dm"
|
||||
#include "code\modules\power\fusion\fuel_assembly\fuel_injector.dm"
|
||||
#include "code\modules\power\fusion\gyrotron\gyrotron.dm"
|
||||
#include "code\modules\power\fusion\gyrotron\gyrotron_control.dm"
|
||||
#include "code\modules\power\sensors\powernet_sensor.dm"
|
||||
#include "code\modules\power\sensors\sensor_monitoring.dm"
|
||||
#include "code\modules\power\singularity\act.dm"
|
||||
@@ -2087,6 +2100,7 @@
|
||||
#include "code\modules\spells\targeted\projectile\fireball.dm"
|
||||
#include "code\modules\spells\targeted\projectile\magic_missile.dm"
|
||||
#include "code\modules\spells\targeted\projectile\projectile.dm"
|
||||
#include "code\modules\supermatter\setup_supermatter.dm"
|
||||
#include "code\modules\supermatter\supermatter.dm"
|
||||
#include "code\modules\surgery\_defines.dm"
|
||||
#include "code\modules\surgery\bones.dm"
|
||||
|
||||
Reference in New Issue
Block a user