Merge remote-tracking branch 'upstream/master' into rmv

This commit is contained in:
Archie
2021-05-06 00:13:29 -03:00
56 changed files with 8469 additions and 69 deletions
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+149
View File
@@ -0,0 +1,149 @@
//MAP CONVERTED BY dmm2tgm.py THIS HEADER COMMENT PREVENTS RECONVERSION, DO NOT REMOVE
"a" = (
/obj/effect/turf_decal/stripes/red/corner{
dir = 4
},
/turf/open/floor/engine,
/area/space)
"b" = (
/obj/effect/turf_decal/stripes/red/line{
dir = 4
},
/obj/effect/turf_decal/arrows/white{
dir = 8;
pixel_x = 5;
pixel_y = 10
},
/turf/open/floor/engine,
/area/space)
"c" = (
/obj/effect/turf_decal/stripes/red/line{
dir = 4
},
/turf/open/floor/engine,
/area/space)
"d" = (
/obj/structure/cable/yellow,
/obj/machinery/atmospherics/components/trinary/nuclear_reactor/cargo,
/turf/open/floor/engine,
/area/space)
"e" = (
/obj/effect/turf_decal/stripes/red/corner{
dir = 1
},
/turf/open/floor/engine,
/area/space)
"f" = (
/obj/machinery/atmospherics/pipe/simple/cyan{
dir = 4
},
/turf/open/floor/engine,
/area/space)
"g" = (
/obj/structure/cable/yellow{
icon_state = "1-2"
},
/obj/machinery/atmospherics/pipe/simple/purple,
/turf/open/floor/engine,
/area/space)
"h" = (
/turf/open/floor/engine,
/area/space)
"s" = (
/obj/effect/turf_decal/stripes/red/corner,
/turf/open/floor/engine,
/area/space)
"t" = (
/obj/effect/turf_decal/stripes/red/line{
dir = 8
},
/obj/effect/turf_decal/arrows/white{
dir = 8;
pixel_x = 5;
pixel_y = 10
},
/turf/open/floor/engine,
/area/space)
"B" = (
/obj/effect/turf_decal/stripes/red/corner{
dir = 8
},
/turf/open/floor/engine,
/area/space)
"G" = (
/obj/machinery/atmospherics/pipe/simple/cyan{
dir = 4
},
/turf/open/floor/plating,
/area/space)
"M" = (
/obj/effect/turf_decal/stripes/red/line,
/turf/open/floor/engine,
/area/space)
"O" = (
/obj/machinery/atmospherics/pipe/simple/scrubbers{
dir = 4
},
/turf/open/floor/plating,
/area/space)
"P" = (
/obj/effect/turf_decal/stripes/red/line{
dir = 8
},
/turf/open/floor/engine,
/area/space)
"V" = (
/obj/effect/turf_decal/stripes/red/line{
dir = 1
},
/turf/open/floor/engine,
/area/space)
"Y" = (
/obj/structure/cable/yellow{
icon_state = "0-2"
},
/obj/machinery/atmospherics/pipe/simple/purple,
/turf/open/floor/plating,
/area/space)
"Z" = (
/obj/machinery/atmospherics/pipe/simple/scrubbers{
dir = 4
},
/turf/open/floor/engine,
/area/space)
(1,1,1) = {"
s
c
O
b
a
"}
(2,1,1) = {"
M
h
Z
h
V
"}
(3,1,1) = {"
Y
g
d
h
V
"}
(4,1,1) = {"
M
h
f
h
V
"}
(5,1,1) = {"
B
P
G
t
e
"}
+5 -1
View File
@@ -16,10 +16,14 @@
#define CHANNEL_DIGEST 1009
#define CHANNEL_PREYLOOP 1008
//Hyperstation Channels
#define CHANNEL_REACTOR_ALERT 1007 // reactor sounds
//THIS SHOULD ALWAYS BE THE LOWEST ONE!
//KEEP IT UPDATED
#define CHANNEL_HIGHEST_AVAILABLE 1008 //CIT CHANGE - COMPENSATES FOR VORESOUND CHANNELS
#define CHANNEL_HIGHEST_AVAILABLE 1006 //CIT CHANGE - COMPENSATES FOR VORESOUND CHANNELS
#define SOUND_MINIMUM_PRESSURE 10
+45 -1
View File
@@ -176,4 +176,48 @@ round(cos_inv_third+sqrt3_sin, 0.001), round(cos_inv_third-sqrt3_sin, 0.001), ro
offset = (y-1)*4
for(x in 1 to 4)
output[offset+x] = round(A[offset+1]*B[x] + A[offset+2]*B[x+4] + A[offset+3]*B[x+8] + A[offset+4]*B[x+12]+(y==5?B[x+16]:0), 0.001)
return output
return output
/atom/proc/shake_animation(var/intensity = 8) //Makes the object visibly shake
var/initial_transform = new/matrix(transform)
var/init_px = pixel_x
var/shake_dir = pick(-1, 1)
var/rotation = 2+soft_cap(intensity, 1, 1, 0.94)
var/offset = 1+soft_cap(intensity*0.3, 1, 1, 0.8)
var/time = 2+soft_cap(intensity*0.3, 2, 1, 0.92)
animate(src, transform=turn(transform, rotation*shake_dir), pixel_x=init_px + offset*shake_dir, time=1)
animate(transform=initial_transform, pixel_x=init_px, time=time, easing=ELASTIC_EASING)
/*
This proc makes the input taper off above cap. But there's no absolute cutoff.
Chunks of the input value above cap, are reduced more and more with each successive one and added to the output
A higher input value always makes a higher output value. but the rate of growth slows
*/
/proc/soft_cap(var/input, var/cap = 0, var/groupsize = 1, var/groupmult = 0.9)
//The cap is a ringfenced amount. If we're below that, just return the input
if (input <= cap)
return input
var/output = 0
var/buffer = 0
var/power = 1//We increment this after each group, then apply it to the groupmult as a power
//Ok its above, so the cap is a safe amount, we move that to the output
input -= cap
output += cap
//Now we start moving groups from input to buffer
while (input > 0)
buffer = min(input, groupsize) //We take the groupsize, or all the input has left if its less
input -= buffer
buffer *= groupmult**power //This reduces the group by the groupmult to the power of which index we're on.
//This ensures that each successive group is reduced more than the previous one
output += buffer
power++ //Transfer to output, increment power, repeat until the input pile is all used
return output
+4
View File
@@ -27,6 +27,10 @@
/proc/radiation_pulse(atom/source, intensity, range_modifier, log=FALSE, can_contaminate=TRUE)
if(!SSradiation.can_fire)
return
if(istype(get_turf(source), /turf/open/pool))
var/turf/open/pool/PL = get_turf(source)
if(PL.filled == TRUE)
intensity *= 0.15
var/area/A = get_area(source)
var/atom/nested_loc = source.loc
var/spawn_waves = TRUE
+5 -1
View File
@@ -537,6 +537,10 @@
SEND_SIGNAL(src, COMSIG_ATOM_EMAG_ACT)
/atom/proc/rad_act(strength)
if(istype(get_turf(src), /turf/open/pool))
var/turf/open/pool/PL = get_turf(src)
if(PL.filled == TRUE)
strength *= 0.15
SEND_SIGNAL(src, COMSIG_ATOM_RAD_ACT, strength)
/atom/proc/narsie_act()
@@ -894,4 +898,4 @@ Proc for attack log creation, because really why not
if(href_list["statpanel_item_click"])
// first of all make sure we valid
var/mouseparams = list2params(paramslist)
usr_client.Click(src, loc, null, mouseparams)
usr_client.Click(src, loc, null, mouseparams)
@@ -13,19 +13,16 @@
var/list/living_antags = list()
var/list/dead_players = list()
var/list/list_observers = list()
/datum/dynamic_ruleset/event/acceptable(population=0, threat=0)
if(istype(controller, /datum/round_event_control))
var/datum/round_event_control/R = controller
if(R.map_blacklist.len && (SSmapping.config.map_file in R.map_blacklist)) //Apparently dynamic doesn't call a controller's canSpawnEvent :>
return FALSE
if(R.map_whitelist.len && !(SSmapping.config.map_file in R.map_whitelist))
return FALSE
return ..()
var/list/map_blacklist = list() //Determines if a map, "BoxStation.dmm" for example, will spawn. Has to be case-sensitive
var/list/map_whitelist = list() //Blacklist/Whitelist does not check round event controllers, they are separate vars
/datum/dynamic_ruleset/event/ready(forced = 0)
if (!forced)
var/job_check = 0
if (map_blacklist.len && (SSmapping.config.map_file in map_blacklist))
return FALSE
if (map_whitelist.len && !(SSmapping.config.map_file in map_whitelist))
return FALSE
if (enemy_roles.len > 0)
for (var/mob/M in mode.current_players[CURRENT_LIVING_PLAYERS])
if (M.stat == DEAD)
@@ -232,6 +229,7 @@
//property_weights = list("extended" = -2)
occurances_max = 2
chaos_min = 1.5
map_blacklist = list("LayeniaStation.dmm")
/datum/dynamic_ruleset/event/meteor_wave/ready()
if(world.time-SSticker.round_start_time > 35 MINUTES && mode.threat_level > 40 && mode.threat >= 25 && prob(30))
@@ -408,6 +406,7 @@
//property_weights = list("extended" = 1)
occurances_max = 3
chaos_min = 0.5
map_blacklist = list("LayeniaStation.dmm")
/datum/dynamic_ruleset/event/communications_blackout
name = "Communications Blackout"
@@ -471,6 +470,7 @@
repeatable = TRUE
//property_weights = list("extended" = 1)
occurances_max = 3
/datum/dynamic_ruleset/event/electrical_storm
name = "Electrical Storm"
@@ -544,6 +544,7 @@
//property_weights = list("extended" = 1)
occurances_max = 2
chaos_min = 1.0
map_blacklist = list("LayeniaStation.dmm")
/datum/dynamic_ruleset/event/swarmers
name = "Swarmers"
@@ -604,6 +605,7 @@
repeatable_weight_decrease = 2
chaos_min = 1.5
var/atom/special_target
map_blacklist = list("LayeniaStation.dmm")
/*
/datum/dynamic_ruleset/event/immovable_rod/execute() //I do not know why this is necessary
@@ -629,6 +631,7 @@
cost = 10
repeatable = TRUE
occurances_max = 2
map_blacklist = list("LayeniaStation.dmm")
/datum/dynamic_ruleset/event/high_priority_bounty
name = "High Priority Bounty"
@@ -723,6 +726,7 @@
weight = 4
repeatable_weight_decrease = 3
occurances_max = 2
map_blacklist = list("LayeniaStation.dmm")
/datum/dynamic_ruleset/event/sentience
name = "Random Human-level Intelligence"
+1 -1
View File
@@ -9,7 +9,7 @@
S.update_icon()
S.power_change()
var/list/skipped_areas = list(/area/engine/engineering, /area/engine/supermatter, /area/engine/atmospherics_engine, /area/ai_monitored/turret_protected/ai)
var/list/skipped_areas = list(/area/engine/engineering, /area/engine/supermatter, /area/engine/atmospherics_engine, /area/engine/engineering/reactor_core, /area/engine/engineering/reactor_control, /area/ai_monitored/turret_protected/ai)
for(var/area/A in world)
if( !A.requires_power || A.always_unpowered )
@@ -208,7 +208,7 @@
/datum/pipeline/proc/return_air()
. = other_airs + air
if(null in .)
stack_trace("[src] has one or more null gas mixtures, which may cause bugs. Null mixtures will not be considered in reconcile_air().")
stack_trace("[src]([REF(src)]) has one or more null gas mixtures, which may cause bugs. Null mixtures will not be considered in reconcile_air().")
return removeNullsFromList(.)
/datum/pipeline/proc/reconcile_air()
+36
View File
@@ -193,3 +193,39 @@
contains = list(/obj/item/energy_harvester)
crate_name = "energy harvesting module crate"
crate_type = /obj/structure/closet/crate/secure/engineering
/datum/supply_pack/engine/fuel_rod
name = "Uranium Fuel Rod crate"
desc = "Two additional fuel rods for use in a reactor, requires CE access to open. Caution: Radioactive"
cost = 3000
access = ACCESS_CE
contains = list(/obj/item/twohanded/required/fuel_rod,
/obj/item/twohanded/required/fuel_rod)
crate_name = "Uranium-235 Fuel Rod crate"
crate_type = /obj/structure/closet/crate/secure/engineering
dangerous = TRUE
/datum/supply_pack/engine/bananium_fuel_rod
name = "Bananium Fuel Rod crate"
desc = "Two fuel rods designed to utilize and multiply bananium in a reactor, requires CE access to open. Caution: Radioactive"
cost = 4000
access = ACCESS_CE // Nag your local CE
contains = list(/obj/item/twohanded/required/fuel_rod/material/bananium,
/obj/item/twohanded/required/fuel_rod/material/bananium)
crate_name = "Bluespace Crystal Fuel Rod crate"
crate_type = /obj/structure/closet/crate/secure/engineering
dangerous = TRUE
contraband = TRUE
/datum/supply_pack/engine/reactor
name = "RMBK Nuclear Reactor Kit" // (not) a toy
desc = "Contains a reactor beacon and 3 reactor consoles. Uranium rods not included."
cost = 12000
access = ACCESS_CE
contains = list(/obj/item/survivalcapsule/reactor,
/obj/machinery/computer/reactor/control_rods/cargo,
/obj/machinery/computer/reactor/stats/cargo,
/obj/machinery/computer/reactor/fuel_rods/cargo)
crate_name = "Build Your Own Reactor Kit"
crate_type = /obj/structure/closet/crate/secure/engineering
dangerous = TRUE
@@ -38,6 +38,7 @@
hard_drive.store_file(new/datum/computer_file/program/power_monitor())
hard_drive.store_file(new/datum/computer_file/program/alarm_monitor())
hard_drive.store_file(new/datum/computer_file/program/supermatter_monitor())
hard_drive.store_file(new/datum/computer_file/program/nuclear_monitor())
// ===== RESEARCH CONSOLE =====
/obj/machinery/modular_computer/console/preset/research
@@ -0,0 +1,4 @@
/datum/export/plutonium_rod
cost = 20000
unit_name = "Plutonium Rod"
export_types = list(/obj/item/twohanded/required/fuel_rod/plutonium)
@@ -0,0 +1,8 @@
// yes, I COULD make it a seperate object from the surv capsule but the code needed is indeticle soo...
/obj/item/survivalcapsule/reactor // the not-so-survival capsule
name = "RMBK Reactor Beacon"
desc = "A special bluespace beacon designed to implement a reactor into the hull of the ship or station that it is activated on."
icon = 'icons/obj/device.dmi'
icon_state = "beacon"
template_id = "reactor"
@@ -0,0 +1,7 @@
// yes, I COULD make it a seperate object from the surv capsule but the code needed is indeticle soo...
/datum/map_template/shelter/reactor
name = "RBMK Reactor"
shelter_id = "reactor"
description = "A reactor core, coolant and moderator loop not included."
mappath = "_maps/templates/reactor_1.dmm"
@@ -0,0 +1,229 @@
/obj/item/twohanded/required/fuel_rod
var/rad_strength = 500
var/half_life = 2000 // how many depletion ticks are needed to half the fuel_power (1 tick = 1 second)
var/time_created = 0
var/og_fuel_power = 0.20 //the original fuel power value
var/process = FALSE
// The depletion where depletion_final() will be called (and does something)
var/depletion_threshold = 100
// How fast this rod will deplete
var/depletion_speed_modifier = 1
var/depleted_final = FALSE // depletion_final should run only once
var/depletion_conversion_type = "plutonium"
/obj/item/twohanded/required/fuel_rod/Initialize()
. = ..()
time_created = world.time
AddComponent(/datum/component/radioactive, rad_strength, src) // This should be temporary for it won't make rads go lower than 350
if(process)
START_PROCESSING(SSobj, src)
/obj/item/twohanded/required/fuel_rod/Destroy()
if(process)
STOP_PROCESSING(SSobj, src)
var/obj/machinery/atmospherics/components/trinary/nuclear_reactor/N = loc
if(istype(N))
N.fuel_rods -= src
. = ..()
// This proc will try to convert your fuel rod if you don't override this proc
// So, ideally, you should write an override of this for every fuel rod you want to create
/obj/item/twohanded/required/fuel_rod/proc/depletion_final(result_rod = "")
if(result_rod)
var/obj/machinery/atmospherics/components/trinary/nuclear_reactor/N = loc
// Rod conversion is moot when you can't find the reactor
if(istype(N))
var/obj/item/twohanded/required/fuel_rod/R
// You can add your own depletion scheme and not override this proc if you are going to convert a fuel rod into another type
switch(result_rod)
if("plutonium")
R = new /obj/item/twohanded/required/fuel_rod/plutonium(loc)
R.depletion = depletion
if("depleted")
if(fuel_power < 10)
fuel_power = 0
playsound(loc, 'sound/effects/supermatter.ogg', 100, TRUE)
R = new /obj/item/twohanded/required/fuel_rod/depleted(loc)
R.depletion = depletion
// Finalization of conversion
if(istype(R))
N.fuel_rods += R
qdel(src)
else
depleted_final = FALSE // Maybe try again later?
/obj/item/twohanded/required/fuel_rod/deplete(amount=0.035) // override for the one in rmbk.dm
depletion += amount * depletion_speed_modifier
if(depletion >= depletion_threshold && !depleted_final)
depleted_final = TRUE
depletion_final(depletion_conversion_type)
/obj/item/twohanded/required/fuel_rod/plutonium
fuel_power = 0.20
name = "Plutonium-239 Fuel Rod"
desc = "A highly energetic titanium sheathed rod containing a sizeable measure of weapons grade plutonium, it's highly efficient as nuclear fuel, but will cause the reaction to get out of control if not properly utilised."
icon_state = "inferior"
rad_strength = 1500
process = TRUE // for half life code
depletion_threshold = 300
depletion_conversion_type = "depleted"
/obj/item/twohanded/required/fuel_rod/plutonium/process()
fuel_power = og_fuel_power * 0.5**((world.time - time_created) / half_life SECONDS) // halves the fuel power every half life (33 minutes)
/obj/item/twohanded/required/fuel_rod/depleted
name = "Depleted Fuel Rod"
desc = "A highly radioactive fuel rod which has expended most of it's useful energy."
icon_state = "normal"
rad_strength = 6000 // smelly
depletion_conversion_type = "" // It means that it won't turn into anything
// Master type for material optional (or requiring, wyci) and/or producing rods
/obj/item/twohanded/required/fuel_rod/material
// Whether the rod has been harvested. Should be set in expend().
var/expended = FALSE
// The material that will be inserted and then multiplied (or not). Should be some sort of /obj/item/stack
var/material_type
// The name of material that'll be used for texts
var/material_name
var/material_name_singular
var/initial_amount = 0
// The maximum amount of material the rod can hold
var/max_initial_amount = 10
var/grown_amount = 0
// The multiplier for growth. 1 for the same 2 for double etc etc
var/multiplier = 2
// After this depletion, you won't be able to add new materials
var/material_input_deadline = 25
// Material fuel rods generally don't get converted into another fuel object
depletion_conversion_type = ""
// Called when the rod is fully harvested
/obj/item/twohanded/required/fuel_rod/material/proc/expend()
expended = TRUE
// Basic checks for material rods
/obj/item/twohanded/required/fuel_rod/material/proc/check_material_input(mob/user)
if(depletion >= material_input_deadline)
to_chat(user, "<span class='warning'>The sample slots have sealed themselves shut, it's too late to add [material_name] now!</span>") // no cheesing in crystals at 100%
return FALSE
if(expended)
to_chat(user, "<span class='warning'>\The [src]'s material slots have already been used.</span>")
return FALSE
return TRUE
// The actual growth
/obj/item/twohanded/required/fuel_rod/material/depletion_final(result_rod)
if(result_rod)
..() // So if you put anything into depletion_conversion_type then your fuel rod will be converted (or not) and *won't grow*
else
grown_amount = initial_amount * multiplier
/obj/item/twohanded/required/fuel_rod/material/attackby(obj/item/W, mob/user, params)
var/obj/item/stack/M = W
if(istype(M, material_type))
if(!check_material_input(user))
return
if(initial_amount < max_initial_amount)
var/adding = min((max_initial_amount - initial_amount), M.amount)
M.amount -= adding
initial_amount += adding
if (adding == 1)
to_chat(user, "<span class='notice'>You insert [adding] [material_name_singular] into \the [src].</span>")
else
to_chat(user, "<span class='notice'>You insert [adding] [material_name] into \the [src].</span>")
M.zero_amount()
else
to_chat(user, "<span class='warning'>\The [src]'s material slots are full!</span>")
return
else
return ..()
/obj/item/twohanded/required/fuel_rod/material/attack_self(mob/user)
if(expended)
to_chat(user, "<span class='notice'>You have already removed [material_name] from \the [src].</span>")
return
if(depleted_final)
new material_type(user.loc, grown_amount)
if (grown_amount == 1)
to_chat(user, "<span class='notice'>You harvest [grown_amount] [material_name_singular] from \the [src].</span>") // Unlikely
else
to_chat(user, "<span class='notice'>You harvest [grown_amount] [material_name] from \the [src].</span>")
grown_amount = 0
expend()
else if(depletion)
to_chat(user, "<span class='warning'>\The [src] has not fissiled enough to fully grow the sample. The progress bar shows it is [min(depletion/depletion_threshold*100,100)]% complete.</span>")
else if(initial_amount)
new material_type(user.loc, initial_amount)
if (initial_amount == 1)
to_chat(user, "<span class='notice'>You remove [initial_amount] [material_name_singular] from \the [src].</span>")
else
to_chat(user, "<span class='notice'>You remove [initial_amount] [material_name] from \the [src].</span>")
initial_amount = 0
/obj/item/twohanded/required/fuel_rod/material/examine(mob/user)
. = ..()
if(expended)
. += "<span class='warning'>The material slots have been slagged by the extreme heat, you can't grow [material_name] in this rod again...</span>"
return
else if(depleted_final)
if(grown_amount == 1)
. += "<span class='warning'>This fuel rod's [material_name] are now fully grown, and it currently bears [grown_amount] harvestable [material_name_singular].</span>"
else
. += "<span class='warning'>This fuel rod's [material_name] are now fully grown, and it currently bears [grown_amount] harvestable [material_name].</span>"
return
if(depletion)
. += "<span class='danger'>The sample is [min(depletion/depletion_threshold*100,100)]% fissiled.</span>"
. += "<span class='disarm'>[initial_amount]/[max_initial_amount] of the slots for [material_name] are full.</span>"
/obj/item/twohanded/required/fuel_rod/material/telecrystal
name = "Telecrystal Fuel Rod"
desc = "A disguised titanium sheathed rod containing several small slots infused with uranium dioxide. Permits the insertion of telecrystals to grow more. Fissiles much faster than its standard counterpart"
icon_state = "telecrystal"
fuel_power = 0.30 // twice as powerful as a normal rod, you're going to need some engineering autism if you plan to mass produce TC
depletion_speed_modifier = 3 // headstart, otherwise it takes two hours
rad_strength = 1500
max_initial_amount = 8
multiplier = 3
material_type = /obj/item/stack/telecrystal
material_name = "telecrystals"
material_name_singular = "telecrystal"
/obj/item/twohanded/required/fuel_rod/material/telecrystal/depletion_final(result_rod)
..()
if(!result_rod)
fuel_power = 0.60 // thrice as powerful as plutonium, you'll want to get this one out quick!
name = "Exhausted Telecrystal Fuel Rod"
desc = "A highly energetic, disguised titanium sheathed rod containing a number of slots filled with greatly expanded telecrystals which can be removed by hand. It's extremely efficient as nuclear fuel, but will cause the reaction to get out of control if not properly utilised."
icon_state = "telecrystal_used"
AddComponent(/datum/component/radioactive, 3000, src)
/obj/item/twohanded/required/fuel_rod/material/bananium
name = "Bananium Fuel Rod"
desc = "A hilarious heavy-duty fuel rod which fissiles a bit slower than its cowardly counterparts. However, its cutting-edge cosmic clown technology allows rooms for extraordinarily exhilarating extraterrestrial element called bananium to menacingly multiply."
icon_state = "bananium"
fuel_power = 0.15
depletion_speed_modifier = 3
rad_strength = 350
max_initial_amount = 10
multiplier = 3
material_type = /obj/item/stack/sheet/mineral/bananium
material_name = "sheets of bananium"
material_name_singular = "sheet of bananium"
/obj/item/twohanded/required/fuel_rod/material/bananium/deplete(amount=0.035)
..()
if(initial_amount == max_initial_amount && prob(10))
playsound(src, pick('sound/items/bikehorn.ogg', 'yogstation/sound/misc/bikehorn_creepy.ogg'), 50) // HONK
/obj/item/twohanded/required/fuel_rod/material/bananium/depletion_final(result_rod)
..()
if(!result_rod)
fuel_power = 0.3 // Be warned
name = "Fully Grown Bananium Fuel Rod"
desc = "A hilarious heavy-duty fuel rod which fissiles a bit slower than it cowardly counterparts. Its greatly grimacing grwoth stage is now over, and bananium outgrowth hums as if it's blatantly honking bike horns."
icon_state = "bananium_used"
AddComponent(/datum/component/radioactive, 1250, src)
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,31 @@
// modular shitcode but it works:tm:
/obj/machinery/atmospherics/components/trinary/nuclear_reactor/multitool_act(mob/living/user, obj/item/multitool/I)
if(istype(I))
to_chat(user, "<span class='notice'>You add \the [src]'s ID into the multitool's buffer.</span>")
I.buffer = src.id
return TRUE
/obj/machinery/computer/reactor/multitool_act(mob/living/user, obj/item/multitool/I)
if(istype(I))
to_chat(user, "<span class='notice'>You add the reactor's ID to \the [src]>")
src.id = I.buffer
return TRUE
/obj/machinery/atmospherics/components/trinary/nuclear_reactor/cargo // easier on the brain
/obj/machinery/atmospherics/components/trinary/nuclear_reactor/cargo/New()
id = rand(1, 1000000) // cmon, what are the chances?
// Cargo varients can be wrenched down and don't start linked to the default RMBK reactor
/obj/machinery/computer/reactor/control_rods/cargo
anchored = FALSE
id = null
/obj/machinery/computer/reactor/stats/cargo
anchored = FALSE
id = null
/obj/machinery/computer/reactor/fuel_rods/cargo
anchored = FALSE
id = null
@@ -0,0 +1,8 @@
/datum/uplink_item/device_tools/tc_rod
name = "Telecrystal Fuel Rod"
desc = "This special fuel rod has eight material slots that can be inserted with telecrystals, \
once the rod has been fully depleted, you will be able to harvest the extra telecrystals. \
Please note: This Rod fissiles much faster than it's regular counterpart, it doesn't take \
much to overload the reactor with these..."
item = /obj/item/twohanded/required/fuel_rod/material/telecrystal
cost = 7
+3 -3
View File
@@ -162,6 +162,9 @@
C.adjustArousalLoss(20)
M.adjustArousalLoss(20)
M.do_jitter_animation() //make your partner shake too!
if (C.getArousalLoss() >= 100 && ishuman(C) && C.has_dna())
var/mob/living/carbon/human/O = C
O.mob_climax_partner(P, M, FALSE, TRUE, FALSE, TRUE) //climax with their partner remotely, and impreg because people keep asking!
if(option == "Lick")
to_chat(M, "<span class='love'>You feel a tongue lick you through the portal against your vagina.</span>")
M.adjustArousalLoss(10)
@@ -169,9 +172,6 @@
to_chat(M, "<span class='love'>You feel someone touching your vagina through the portal.</span>")
M.adjustArousalLoss(5)
if (C.getArousalLoss() >= 100 && ishuman(C) && C.has_dna())
var/mob/living/carbon/human/O = C
O.mob_climax_partner(P, M, FALSE, TRUE, FALSE, TRUE) //climax with their partner remotely, and impreg because people keep asking!
return
..()
Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.

Before

Width:  |  Height:  |  Size: 28 KiB

After

Width:  |  Height:  |  Size: 28 KiB

@@ -390,9 +390,11 @@
if(G.can_climax)
setArousalLoss(min_arousal)
else //knots and other non-spilling orgasms
else //knots, portal fleshlights, and other non-spilling orgasms
if(!cover)
if(do_after(src, mb_time, target = src) && in_range(src, L))
if(!remote && !in_range(src, L))
return
if(do_after(src, mb_time, target = src))
var/obj/item/organ/genital/penis/P = G
if (P.condom)//condomed.
src.condomclimax()
+7
View File
@@ -3072,6 +3072,7 @@
#include "hyperstation\code\modules\antagonists\wendigo\mob\update_icons.dm"
#include "hyperstation\code\modules\antagonists\werewolf\werewolf.dm"
#include "hyperstation\code\modules\arousal\arousalhud.dm"
#include "hyperstation\code\modules\cargo\exports\engineering.dm"
#include "hyperstation\code\modules\cargo\exports\sweatshop.dm"
#include "hyperstation\code\modules\cargo\packs\misc.dm"
#include "hyperstation\code\modules\cargo\sweatshop\metal.dm"
@@ -3089,9 +3090,14 @@
#include "hyperstation\code\modules\crafting\recipes.dm"
#include "hyperstation\code\modules\economy\account.dm"
#include "hyperstation\code\modules\integrated_electronics\input.dm"
#include "hyperstation\code\modules\mining\shelters.dm"
#include "hyperstation\code\modules\mining\equipment\survival_pod.dm"
#include "hyperstation\code\modules\mob\mob_helpers.dm"
#include "hyperstation\code\modules\mob\living\status_indicators.dm"
#include "hyperstation\code\modules\patreon\patreon.dm"
#include "hyperstation\code\modules\power\reactor\fuel_rods.dm"
#include "hyperstation\code\modules\power\reactor\rbmk.dm"
#include "hyperstation\code\modules\power\reactor\reactor_cargo.dm"
#include "hyperstation\code\modules\reagents\chemistry\reagents\food_reagents.dm"
#include "hyperstation\code\modules\reagents\chemistry\reagents\hydroponics_reactions.dm"
#include "hyperstation\code\modules\resize\resize_action.dm"
@@ -3099,6 +3105,7 @@
#include "hyperstation\code\modules\resize\sizechems.dm"
#include "hyperstation\code\modules\resize\sizegun.dm"
#include "hyperstation\code\modules\surgery\organs\augments_arms.dm"
#include "hyperstation\code\modules\uplink\uplink_items.dm"
#include "hyperstation\code\obj\ashtray.dm"
#include "hyperstation\code\obj\bluespace sewing kit.dm"
#include "hyperstation\code\obj\condom.dm"
@@ -0,0 +1,90 @@
import { map, sortBy } from 'common/collections';
import { flow } from 'common/fp';
import { toFixed } from 'common/math';
import { pureComponentHooks } from 'common/react';
import { Component, Fragment } from 'inferno';
import { Box, Button, Chart, ColorBox, Flex, Icon, LabeledList, ProgressBar, Section, Table } from '../components';
import { useBackend, useLocalState } from '../backend';
export const NtosRbmkStats = props => {
const { state } = props;
const { act, data } = useBackend(props);
const powerData = data.powerData.map((value, i) => [i, value]);
const psiData = data.psiData.map((value, i) => [i, value]);
const tempInputData = data.tempInputData.map((value, i) => [i, value]);
const tempOutputdata = data.tempOutputdata.map((value, i) => [i, value]);
return (
<Section title="Reactor Management">
<Section title="Legend:" buttons={
<Button
icon="search"
onClick={() => act('swap_reactor')}
content="Change Reactor" />
}>
Reactor Power (%):
<ProgressBar
value={data.power}
minValue={0}
maxValue={100}
color="yellow" />
<br />
Reactor Pressure (PSI):
<ProgressBar
value={data.psi}
minValue={0}
maxValue={2000}
color="white" >
{data.psi} PSI
</ProgressBar>
Coolant temperature (°C):
<ProgressBar
value={data.coolantInput}
minValue={-273.15}
maxValue={1227}
color="blue">
{data.coolantInput} °C
</ProgressBar>
Outlet temperature (°C):
<ProgressBar
value={data.coolantOutput}
minValue={-273.15}
maxValue={1227}
color="bad">
{data.coolantOutput} °C
</ProgressBar>
</Section>
<Section title="Reactor Statistics:" height="200px">
<Chart.Line
fillPositionedParent
data={powerData}
rangeX={[0, powerData.length - 1]}
rangeY={[0, 1500]}
strokeColor="rgba(255, 215,0, 1)"
fillColor="rgba(255, 215, 0, 0.1)" />
<Chart.Line
fillPositionedParent
data={psiData}
rangeX={[0, psiData.length - 1]}
rangeY={[0, 1500]}
strokeColor="rgba(255,250,250, 1)"
fillColor="rgba(255,250,250, 0.1)" />
<Chart.Line
fillPositionedParent
data={tempInputData}
rangeX={[0, tempInputData.length - 1]}
rangeY={[-273.15, 1227]}
strokeColor="rgba(127, 179, 255 , 1)"
fillColor="rgba(127, 179, 255 , 0.1)" />
<Chart.Line
fillPositionedParent
data={tempOutputdata}
rangeX={[0, tempOutputdata.length - 1]}
rangeY={[-273.15, 1227]}
strokeColor="rgba(255, 0, 0 , 1)"
fillColor="rgba(255, 0, 0 , 0.1)" />
</Section>
</Section>
);
};
@@ -0,0 +1,53 @@
import { Fragment } from 'inferno';
import { useBackend, useLocalState } from '../backend';
import { Section, ProgressBar, LabeledList, NumberInput } from '../components';
export const RbmkControlRods = props => {
const { state } = props;
const { act, data } = useBackend(props);
const control_rods = data.control_rods;
const k = data.k;
const desiredK = data.desiredK;
return (
<Section title="Control Rod Management:">
Control Rod Insertion:
<ProgressBar
value={(control_rods / 100 * 100) * 0.01}
ranges={{
good: [0.7, Infinity],
average: [0.4, 0.7],
bad: [-Infinity, 0.4],
}} />
<br />
Neutrons per generation (K):
<br />
<ProgressBar
value={(k / 3 * 100) * 0.01}
ranges={{
good: [-Infinity, 0.4],
average: [0.4, 0.6],
bad: [0.6, Infinity],
}}>
{k}
</ProgressBar>
<br />
Target criticality:
<br />
<LabeledList>
<LabeledList.Item label="Target">
<NumberInput
animated
value={desiredK}
unit="k"
width="125px"
minValue={0}
maxValue={3}
step={0.1}
onChange={(e, value) => act('input', {
target: value,
})} />
</LabeledList.Item>
</LabeledList>
</Section>
);
};
@@ -0,0 +1,83 @@
import { map, sortBy } from 'common/collections';
import { flow } from 'common/fp';
import { toFixed } from 'common/math';
import { pureComponentHooks } from 'common/react';
import { Component, Fragment } from 'inferno';
import { Box, Button, Chart, ColorBox, Flex, Icon, LabeledList, ProgressBar, Section, Table } from '../components';
import { useBackend, useLocalState } from '../backend';
export const RbmkStats = props => {
const { state } = props;
const { act, data } = useBackend(props);
const powerData = data.powerData.map((value, i) => [i, value]);
const psiData = data.psiData.map((value, i) => [i, value]);
const tempInputData = data.tempInputData.map((value, i) => [i, value]);
const tempOutputdata = data.tempOutputdata.map((value, i) => [i, value]);
return (
<Section title="RBMK Stats:">
<Section title="Legend:">
Reactor Power (%):
<ProgressBar
value={data.power}
minValue={0}
maxValue={100}
color="yellow" />
<br />
Reactor Pressure (PSI):
<ProgressBar
value={data.psi}
minValue={0}
maxValue={2000}
color="white" >
{data.psi} PSI
</ProgressBar>
Coolant temperature (°C):
<ProgressBar
value={data.coolantInput}
minValue={-273.15}
maxValue={1227}
color="blue">
{data.coolantInput} °C
</ProgressBar>
Outlet temperature (°C):
<ProgressBar
value={data.coolantOutput}
minValue={-273.15}
maxValue={1227}
color="bad">
{data.coolantOutput} °C
</ProgressBar>
</Section>
<Section title="Reactor Statistics:" height="200px">
<Chart.Line
fillPositionedParent
data={powerData}
rangeX={[0, powerData.length - 1]}
rangeY={[0, 1500]}
strokeColor="rgba(255, 215,0, 1)"
fillColor="rgba(255, 215, 0, 0.1)" />
<Chart.Line
fillPositionedParent
data={psiData}
rangeX={[0, psiData.length - 1]}
rangeY={[0, 1500]}
strokeColor="rgba(255,250,250, 1)"
fillColor="rgba(255,250,250, 0.1)" />
<Chart.Line
fillPositionedParent
data={tempInputData}
rangeX={[0, tempInputData.length - 1]}
rangeY={[-273.15, 1227]}
strokeColor="rgba(127, 179, 255 , 1)"
fillColor="rgba(127, 179, 255 , 0.1)" />
<Chart.Line
fillPositionedParent
data={tempOutputdata}
rangeX={[0, tempOutputdata.length - 1]}
rangeY={[-273.15, 1227]}
strokeColor="rgba(255, 0, 0 , 1)"
fillColor="rgba(255, 0, 0 , 0.1)" />
</Section>
</Section>
);
};
+58
View File
@@ -0,0 +1,58 @@
import { classes } from 'common/react';
import { IS_IE8 } from '../byond';
/**
* Brings Layout__content DOM element back to focus.
*
* Commonly used to keep the content scrollable in IE.
*/
export const refocusLayout = () => {
// IE8: Focus method is seemingly fucked.
if (IS_IE8) {
return;
}
const element = document.getElementById('Layout__content');
if (element) {
element.focus();
}
};
export const Layout = props => {
const {
className,
theme = 'nanotrasen',
children,
} = props;
return (
<div className={'theme-' + theme}>
<div
className={classes([
'Layout',
className,
])}>
{children}
</div>
</div>
);
};
const LayoutContent = props => {
const {
className,
scrollable,
children,
} = props;
return (
<div
id="Layout__content"
className={classes([
'Layout__content',
scrollable && 'Layout__content--scrollable',
className,
])}>
{children}
</div>
);
};
Layout.Content = LayoutContent;
@@ -0,0 +1,126 @@
import { useBackend } from '../backend';
import { Box, Button } from '../components';
import { refocusLayout } from './Layout';
import { Window } from './Window';
export const NtosWindow = (props, context) => {
const {
resizable,
theme = 'ntos',
children,
} = props;
const { act, data } = useBackend(context);
const {
PC_batteryicon,
PC_showbatteryicon,
PC_batterypercent,
PC_ntneticon,
PC_apclinkicon,
PC_stationtime,
PC_programheaders = [],
PC_showexitprogram,
} = data;
return (
<Window
theme={theme}
resizable={resizable}>
<div className="NtosWindow">
<div
className="NtosWindow__header NtosHeader"
onMouseDown={() => {
refocusLayout();
}}>
<div className="NtosHeader__left">
<Box inline bold mr={2}>
{PC_stationtime}
</Box>
<Box inline italic mr={2} opacity={0.33}>
NtOS
</Box>
</div>
<div className="NtosHeader__right">
{PC_programheaders.map(header => (
<Box key={header.icon} inline mr={1}>
<img
className="NtosHeader__icon"
src={header.icon} />
</Box>
))}
<Box inline>
{PC_ntneticon && (
<img
className="NtosHeader__icon"
src={PC_ntneticon} />
)}
</Box>
{!!PC_showbatteryicon && PC_batteryicon && (
<Box inline mr={1}>
{PC_batteryicon && (
<img
className="NtosHeader__icon"
src={PC_batteryicon} />
)}
{PC_batterypercent && (
PC_batterypercent
)}
</Box>
)}
{PC_apclinkicon && (
<Box inline mr={1}>
<img
className="NtosHeader__icon"
src={PC_apclinkicon} />
</Box>
)}
{!!PC_showexitprogram && (
<Button
width="26px"
lineHeight="22px"
textAlign="center"
color="transparent"
icon="window-minimize-o"
tooltip="Minimize"
tooltipPosition="bottom"
onClick={() => act('PC_minimize')} />
)}
{!!PC_showexitprogram && (
<Button
mr="-3px"
width="26px"
lineHeight="22px"
textAlign="center"
color="transparent"
icon="window-close-o"
tooltip="Close"
tooltipPosition="bottom-left"
onClick={() => act('PC_exit')} />
)}
{!PC_showexitprogram && (
<Button
mr="-3px"
width="26px"
lineHeight="22px"
textAlign="center"
color="transparent"
icon="power-off"
tooltip="Power off"
tooltipPosition="bottom-left"
onClick={() => act('PC_shutdown')} />
)}
</div>
</div>
{children}
</div>
</Window>
);
};
const NtosWindowContent = props => {
return (
<div className="NtosWindow__content">
<Window.Content {...props} />
</div>
);
};
NtosWindow.Content = NtosWindowContent;
+142
View File
@@ -0,0 +1,142 @@
import { classes } from 'common/react';
import { decodeHtmlEntities, toTitleCase } from 'common/string';
import { Component, Fragment } from 'inferno';
import { useBackend } from '../backend';
import { IS_IE8, runCommand, winset } from '../byond';
import { Box, Icon } from '../components';
import { UI_DISABLED, UI_INTERACTIVE, UI_UPDATE } from '../constants';
import { dragStartHandler, resizeStartHandler } from '../drag';
import { releaseHeldKeys } from '../hotkeys';
import { createLogger } from '../logging';
import { Layout, refocusLayout } from './Layout';
const logger = createLogger('Window');
export class Window extends Component {
componentDidMount() {
refocusLayout();
}
render() {
const {
resizable,
theme,
children,
} = this.props;
const {
config,
debugLayout,
} = useBackend(this.context);
// Determine when to show dimmer
const showDimmer = config.observer
? config.status < UI_DISABLED
: config.status < UI_INTERACTIVE;
return (
<Layout
className="Window"
theme={theme}>
<TitleBar
className="Window__titleBar"
title={decodeHtmlEntities(config.title)}
status={config.status}
fancy={config.fancy}
onDragStart={dragStartHandler}
onClose={() => {
logger.log('pressed close');
releaseHeldKeys();
winset(config.window, 'is-visible', false);
runCommand(`uiclose ${config.ref}`);
}} />
<div
className={classes([
'Window__rest',
debugLayout && 'debug-layout',
])}>
{children}
{showDimmer && (
<div className="Window__dimmer" />
)}
</div>
{config.fancy && resizable && (
<Fragment>
<div className="Window__resizeHandle__e"
onMousedown={resizeStartHandler(1, 0)} />
<div className="Window__resizeHandle__s"
onMousedown={resizeStartHandler(0, 1)} />
<div className="Window__resizeHandle__se"
onMousedown={resizeStartHandler(1, 1)} />
</Fragment>
)}
</Layout>
);
}
}
const WindowContent = props => {
const { scrollable, children } = props;
// A bit lazy to actually write styles for it,
// so we simply include a Box with margins.
return (
<Layout.Content
scrollable={scrollable}>
<Box m={1}>
{children}
</Box>
</Layout.Content>
);
};
Window.Content = WindowContent;
const statusToColor = status => {
switch (status) {
case UI_INTERACTIVE:
return 'good';
case UI_UPDATE:
return 'average';
case UI_DISABLED:
default:
return 'bad';
}
};
const TitleBar = props => {
const {
className,
title,
status,
fancy,
onDragStart,
onClose,
} = props;
return (
<div
className={classes([
'TitleBar',
className,
])}>
<Icon
className="TitleBar__statusIcon"
color={statusToColor(status)}
name="eye" />
<div className="TitleBar__title">
{title === title.toLowerCase()
? toTitleCase(title)
: title}
</div>
<div
className="TitleBar__dragZone"
onMousedown={e => fancy && onDragStart(e)} />
{!!fancy && (
<div
className="TitleBar__close TitleBar__clickable"
// IE8: Synthetic onClick event doesn't work on IE8.
// IE8: Use a plain character instead of a unicode symbol.
// eslint-disable-next-line react/no-unknown-property
onclick={onClose}>
{IS_IE8 ? 'x' : '×'}
</div>
)}
</div>
);
};
+3
View File
@@ -0,0 +1,3 @@
export { Layout, refocusLayout } from './Layout';
export { NtosWindow } from './NtosWindow';
export { Window } from './Window';
File diff suppressed because one or more lines are too long
+21
View File
@@ -60,6 +60,9 @@ import { NtosNetChat } from './interfaces/NtosNetChat';
import { NtosNetDownloader } from './interfaces/NtosNetDownloader';
import { NtosSupermatterMonitor } from './interfaces/NtosSupermatterMonitor';
import { NtosWrapper } from './interfaces/NtosWrapper';
import { NtosRbmkStats } from './interfaces/NtosRbmkStats';
import { RbmkControlRods } from './interfaces/RbmkControlRods';
import { RbmkStats } from './interfaces/RbmkStats';
import { NuclearBomb } from './interfaces/NuclearBomb';
import { OperatingComputer } from './interfaces/OperatingComputer';
import { OreBox } from './interfaces/OreBox';
@@ -370,6 +373,24 @@ const ROUTES = {
scrollable: true,
theme: 'ntos',
},
ntosrbmkstats: {
component: () => NtosRbmkStats,
wrapper: () => NtosWrapper,
scrollable: true,
theme: 'ntos',
},
rbmkcontrolrods: {
component: () => RbmkControlRods,
wrapper: () => NtosWrapper,
scrollable: true,
theme: 'ntos',
},
rbmkstats: {
component: () => RbmkStats,
wrapper: () => NtosWrapper,
scrollable: true,
theme: 'ntos',
},
nuclear_bomb: {
component: () => NuclearBomb,
scrollable: false,