Ports R-UST from Baystation12 + small admin debug verb

This commit is contained in:
silveryferret
2017-07-19 01:39:12 -04:00
parent 60e945248a
commit 7567726c07
27 changed files with 2172 additions and 12 deletions

View File

@@ -74,6 +74,7 @@
#define XGM_GAS_FUEL 1 #define XGM_GAS_FUEL 1
#define XGM_GAS_OXIDIZER 2 #define XGM_GAS_OXIDIZER 2
#define XGM_GAS_CONTAMINANT 4 #define XGM_GAS_CONTAMINANT 4
#define XGM_GAS_FUSION_FUEL 8
#define TANK_LEAK_PRESSURE (30.*ONE_ATMOSPHERE) // Tank starts leaking. #define TANK_LEAK_PRESSURE (30.*ONE_ATMOSPHERE) // Tank starts leaking.
#define TANK_RUPTURE_PRESSURE (40.*ONE_ATMOSPHERE) // Tank spills all contents into atmosphere. #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_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_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? #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"

View File

@@ -198,3 +198,6 @@
#define TSC_GIL "Gilthari" #define TSC_GIL "Gilthari"
#define MIDNIGHT_ROLLOVER 864000 //number of deciseconds in a day #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

View File

@@ -18,6 +18,24 @@
specific_heat = 30 // J/(mol*K) specific_heat = 30 // J/(mol*K)
molar_mass = 0.044 // kg/mol 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 /decl/xgm_gas/phoron
id = "phoron" id = "phoron"
name = "Phoron" name = "Phoron"

View File

@@ -428,3 +428,23 @@ update_flag
src.update_icon() src.update_icon()
return 1 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

View File

@@ -147,6 +147,48 @@
</body> </body>
</html>"} </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 /obj/item/weapon/book/manual/engineering_hacking
name = "Hacking" name = "Hacking"
icon_state ="bookHacking" icon_state ="bookHacking"

View File

@@ -158,6 +158,17 @@
default_type = "osmium" default_type = "osmium"
apply_colour = 1 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 /obj/item/stack/material/steel
name = DEFAULT_WALL_MATERIAL name = DEFAULT_WALL_MATERIAL
icon_state = "sheet-metal" icon_state = "sheet-metal"

View File

@@ -69,6 +69,7 @@ var/list/name_to_material
var/flags = 0 // Various status modifiers. var/flags = 0 // Various status modifiers.
var/sheet_singular_name = "sheet" var/sheet_singular_name = "sheet"
var/sheet_plural_name = "sheets" var/sheet_plural_name = "sheets"
var/is_fusion_fuel
// Shards/tables/structures // Shards/tables/structures
var/shard_type = SHARD_SHRAPNEL // Path of debris object. 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/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/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/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. // Placeholder vars for the time being, todo properly integrate windows/light tiles/rods.
var/created_window var/created_window
@@ -270,6 +272,22 @@ var/list/name_to_material
sheet_singular_name = "ingot" sheet_singular_name = "ingot"
sheet_plural_name = "ingots" 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 /material/phoron
name = "phoron" name = "phoron"
stack_type = /obj/item/stack/material/phoron stack_type = /obj/item/stack/material/phoron
@@ -567,6 +585,16 @@ var/list/name_to_material
stack_origin_tech = list(TECH_MATERIAL = 5) stack_origin_tech = list(TECH_MATERIAL = 5)
sheet_singular_name = "ingot" sheet_singular_name = "ingot"
sheet_plural_name = "ingots" 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 /material/mhydrogen
name = "mhydrogen" name = "mhydrogen"
@@ -574,6 +602,7 @@ var/list/name_to_material
icon_colour = "#E6C5DE" icon_colour = "#E6C5DE"
stack_origin_tech = list(TECH_MATERIAL = 6, TECH_POWER = 6, TECH_MAGNET = 5) stack_origin_tech = list(TECH_MATERIAL = 6, TECH_POWER = 6, TECH_MAGNET = 5)
conductivity = 100 conductivity = 100
is_fusion_fuel = 1
/material/platinum /material/platinum
name = "platinum" name = "platinum"

View 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

View 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

View 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

View 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

View 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")

View 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 ..()

View 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 ..()

View 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)

View 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"

View 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)

View 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

View 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 ..()

View 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 ..()

View File

@@ -75,7 +75,7 @@
src.active = 1 src.active = 1
user << "You turn on [src]." user << "You turn on [src]."
src.shot_number = 0 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) 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])") 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") investigate_log("turned <font color='green'>on</font> by [user.key]","singulo")
@@ -119,10 +119,10 @@
src.last_shot = world.time src.last_shot = world.time
if(src.shot_number < burst_shots) if(src.shot_number < burst_shots)
src.fire_delay = 2 src.fire_delay = get_burst_delay() //R-UST port
src.shot_number ++ src.shot_number ++
else 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 src.shot_number = 0
//need to calculate the power per shot as the emitter doesn't fire continuously. //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.set_up(5, 1, src)
s.start() 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.damage = round(power_per_shot/EMITTER_DAMAGE_POWER_TRANSFER)
A.launch( get_step(src.loc, src.dir) ) A.launch( get_step(src.loc, src.dir) )
@@ -266,3 +266,16 @@
user << "<span class='danger'>\The [src] is damaged.</span>" user << "<span class='danger'>\The [src] is damaged.</span>"
if(77 to 99) if(77 to 99)
user << "<span class='warning'>\The [src] is slightly damaged.</span>" 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))

View File

@@ -43,6 +43,21 @@
toxmob(A) toxmob(A)
if((istype(A,/obj/machinery/the_singularitygen))||(istype(A,/obj/singularity/))) if((istype(A,/obj/machinery/the_singularitygen))||(istype(A,/obj/singularity/)))
A:energy += energy 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 return

View File

@@ -43,6 +43,31 @@
color = "#003333" color = "#003333"
strength = 10 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 /datum/reagent/toxin/spidertoxin
name = "Spidertoxin" name = "Spidertoxin"
id = "spidertoxin" id = "spidertoxin"

View File

@@ -1842,7 +1842,6 @@
required_reagents = list("tea" = 5, "berryjuice" = 1) required_reagents = list("tea" = 5, "berryjuice" = 1)
result_amount = 6 result_amount = 6
/datum/chemical_reaction/drinks/sakebomb
name = "Sake Bomb" name = "Sake Bomb"
id = "sakebomb" id = "sakebomb"
result = "sakebomb" result = "sakebomb"
@@ -1863,7 +1862,6 @@
required_reagents = list("sake" = 2, "vodka" = 2, "tomatojuice" = 1) required_reagents = list("sake" = 2, "vodka" = 2, "tomatojuice" = 1)
result_amount = 5 result_amount = 5
/datum/chemical_reaction/drinks/tokyorose
name = "Tokyo Rose" name = "Tokyo Rose"
id = "tokyorose" id = "tokyorose"
result = "tokyorose" result = "tokyorose"
@@ -1906,9 +1904,6 @@
result_amount = 3 result_amount = 3
/datum/chemical_reaction/drinks/euphoria /datum/chemical_reaction/drinks/euphoria
name = "Euphoria"
id = "euphoria"
result = "euphoria"
required_reagents = list("specialwhiskey" = 1, "cognac" = 2) required_reagents = list("specialwhiskey" = 1, "cognac" = 2)
result_amount = 3 result_amount = 3
@@ -1916,7 +1911,6 @@
name = "Xanadu Cannon" name = "Xanadu Cannon"
id = "xanaducannon" id = "xanaducannon"
result = "xanaducannon" result = "xanaducannon"
required_reagents = list("ale" = 1, "dr_gibb" = 1)
result_amount = 2 result_amount = 2
/datum/chemical_reaction/drinks/debugger /datum/chemical_reaction/drinks/debugger
@@ -1946,3 +1940,16 @@
result = "chrysanthemum" result = "chrysanthemum"
required_reagents = list("sake" = 1, "melonliquor" = 1) required_reagents = list("sake" = 1, "melonliquor" = 1)
result_amount = 2 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

View 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

Binary file not shown.

After

Width:  |  Height:  |  Size: 41 KiB

View File

@@ -1872,6 +1872,19 @@
#include "code\modules\power\antimatter\containment_jar.dm" #include "code\modules\power\antimatter\containment_jar.dm"
#include "code\modules\power\antimatter\control.dm" #include "code\modules\power\antimatter\control.dm"
#include "code\modules\power\antimatter\shielding.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\powernet_sensor.dm"
#include "code\modules\power\sensors\sensor_monitoring.dm" #include "code\modules\power\sensors\sensor_monitoring.dm"
#include "code\modules\power\singularity\act.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\fireball.dm"
#include "code\modules\spells\targeted\projectile\magic_missile.dm" #include "code\modules\spells\targeted\projectile\magic_missile.dm"
#include "code\modules\spells\targeted\projectile\projectile.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\supermatter\supermatter.dm"
#include "code\modules\surgery\_defines.dm" #include "code\modules\surgery\_defines.dm"
#include "code\modules\surgery\bones.dm" #include "code\modules\surgery\bones.dm"