Merge branch 'master' into a-few-speech-verbs

This commit is contained in:
shellspeed1
2022-09-19 14:06:50 -07:00
committed by GitHub
66 changed files with 4439 additions and 38 deletions

File diff suppressed because it is too large Load Diff

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 = 8
},
/turf/open/floor/engine,
/area/engineering/main/reactor_core)
"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/engineering/main/reactor_core)
"c" = (
/obj/effect/turf_decal/stripes/red/line{
dir = 4
},
/turf/open/floor/engine,
/area/engineering/main/reactor_core)
"d" = (
/obj/structure/cable/yellow,
/obj/machinery/atmospherics/components/trinary/nuclear_reactor/cargo,
/turf/open/floor/engine,
/area/engineering/main/reactor_core)
"e" = (
/obj/effect/turf_decal/stripes/red/corner{
dir = 4
},
/turf/open/floor/engine,
/area/engineering/main/reactor_core)
"f" = (
/obj/machinery/atmospherics/pipe/simple/cyan{
dir = 4
},
/turf/open/floor/engine,
/area/engineering/main/reactor_core)
"g" = (
/obj/structure/cable/yellow{
icon_state = "1-2"
},
/obj/machinery/atmospherics/pipe/simple/purple,
/turf/open/floor/engine,
/area/engineering/main/reactor_core)
"h" = (
/turf/open/floor/engine,
/area/engineering/main/reactor_core)
"s" = (
/obj/effect/turf_decal/stripes/red/corner,
/turf/open/floor/engine,
/area/engineering/main/reactor_core)
"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/engineering/main/reactor_core)
"B" = (
/obj/effect/turf_decal/stripes/red/corner{
dir = 1
},
/turf/open/floor/engine,
/area/engineering/main/reactor_core)
"G" = (
/obj/machinery/atmospherics/pipe/simple/cyan{
dir = 4
},
/turf/open/floor/plating,
/area/engineering/main/reactor_core)
"M" = (
/obj/effect/turf_decal/stripes/red/line,
/turf/open/floor/engine,
/area/engineering/main/reactor_core)
"O" = (
/obj/machinery/atmospherics/pipe/simple/scrubbers{
dir = 4
},
/turf/open/floor/plating,
/area/engineering/main/reactor_core)
"P" = (
/obj/effect/turf_decal/stripes/red/line{
dir = 8
},
/turf/open/floor/engine,
/area/engineering/main/reactor_core)
"V" = (
/obj/effect/turf_decal/stripes/red/line{
dir = 1
},
/turf/open/floor/engine,
/area/engineering/main/reactor_core)
"Y" = (
/obj/structure/cable/yellow{
icon_state = "0-2"
},
/obj/machinery/atmospherics/pipe/simple/purple,
/turf/open/floor/plating,
/area/engineering/main/reactor_core)
"Z" = (
/obj/machinery/atmospherics/pipe/simple/scrubbers{
dir = 4
},
/turf/open/floor/engine,
/area/engineering/main/reactor_core)
(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
"}

View File

@@ -24,8 +24,9 @@
#define NANITE_HUD "20"
#define DIAG_NANITE_FULL_HUD "21"
#define RAD_HUD "22" //radation alerts for medical huds
#define DIAG_LAUNCHPAD_HUD "23" //Displays launchpads' targeting reticle
//for antag huds. these are used at the /mob level
#define ANTAG_HUD "23"
#define ANTAG_HUD "24"
//by default everything in the hud_list of an atom is an image
//a value in hud_list with one of these will change that behavior

View File

@@ -16,6 +16,10 @@
#define CHANNEL_DIGEST 1009
#define CHANNEL_PREYLOOP 1008
//Reactor Channel
#define CHANNEL_REACTOR_ALERT 1007 // Is that radiation I hear? (ported from hyper)
///Default range of a sound.
#define SOUND_RANGE 17
///default extra range for sounds considered to be quieter
@@ -34,7 +38,7 @@
//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 1007 //CIT CHANGE - COMPENSATES FOR VORESOUND CHANNELS
#define MAX_INSTRUMENT_CHANNELS (128 * 6)

View File

@@ -0,0 +1,43 @@
/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

View File

@@ -27,6 +27,10 @@
/proc/radiation_pulse(atom/source, intensity, range_modifier, log=FALSE, can_contaminate=TRUE)
if(!SSradiation.can_fire)
return
var/turf/open/pool/PL = get_turf(source)
if(istype(PL))
if(PL.filled == TRUE)
intensity *= 0.15
var/area/A = get_area(source)
var/atom/nested_loc = source.loc
var/spawn_waves = TRUE
@@ -52,6 +56,5 @@
thing.rad_act(intensity)
if(log)
var/turf/_source_T = get_turf(source)
log_game("Radiation pulse with intensity: [intensity] and range modifier: [range_modifier] in [loc_name(_source_T)][spawn_waves ? "" : " (contained by [nested_loc.name])"]")
log_game("Radiation pulse with intensity: [intensity] and range modifier: [range_modifier] in [loc_name(PL)][spawn_waves ? "" : " (contained by [nested_loc.name])"]")
return TRUE

View File

@@ -47,6 +47,7 @@
#define ui_back "CENTER-2:14,SOUTH:5"
#define ui_storage1 "CENTER+1:18,SOUTH:5"
#define ui_storage2 "CENTER+2:20,SOUTH:5"
#define ui_combo "CENTER+4:24,SOUTH+1:7" // combo meter for martial arts
//Lower right, persistent menu
#define ui_drop_throw "EAST-1:28,SOUTH+1:7"

View File

@@ -33,6 +33,8 @@ GLOBAL_LIST_INIT(available_ui_styles, list(
var/atom/movable/screen/alien_plasma_display
var/atom/movable/screen/alien_queen_finder
var/atom/movable/screen/combo/combo_display
var/atom/movable/screen/devil/soul_counter/devilsouldisplay
var/atom/movable/screen/synth/coolant_counter/coolant_display
@@ -130,6 +132,7 @@ GLOBAL_LIST_INIT(available_ui_styles, list(
blobpwrdisplay = null
alien_plasma_display = null
alien_queen_finder = null
combo_display = null
QDEL_LIST_ASSOC_VAL(plane_masters)
QDEL_LIST(screenoverlays)

View File

@@ -461,6 +461,9 @@
zone_select.update_icon()
static_inventory += zone_select
combo_display = new /atom/movable/screen/combo()
infodisplay += combo_display
for(var/atom/movable/screen/inventory/inv in (static_inventory + toggleable_inventory))
if(inv.slot_id)
inv.hud = src

View File

@@ -720,3 +720,28 @@
/atom/movable/screen/component_button/Click(params)
if(parent)
parent.component_click(src, params)
/atom/movable/screen/combo
icon_state = ""
mouse_opacity = MOUSE_OPACITY_TRANSPARENT
screen_loc = ui_combo
layer = ABOVE_HUD_LAYER
var/timerid
/atom/movable/screen/combo/proc/clear_streak()
cut_overlays()
icon_state = ""
/atom/movable/screen/combo/update_icon_state(streak = "")
clear_streak()
if (timerid)
deltimer(timerid)
if (!streak)
return
timerid = addtimer(CALLBACK(src, .proc/clear_streak), 20, TIMER_UNIQUE | TIMER_STOPPABLE)
icon_state = "combo"
for (var/i = 1; i <= length(streak); ++i)
var/intent_text = copytext(streak, i, i + 1)
var/image/intent_icon = image(icon,src,"combo_[intent_text]")
intent_icon.pixel_x = 16 * (i - 1) - 8 * length(streak)
add_overlay(intent_icon)

View File

@@ -52,10 +52,10 @@
/datum/atom_hud/data/diagnostic
/datum/atom_hud/data/diagnostic/basic
hud_icons = list(DIAG_HUD, DIAG_STAT_HUD, DIAG_BATT_HUD, DIAG_MECH_HUD, DIAG_BOT_HUD, DIAG_CIRCUIT_HUD, DIAG_TRACK_HUD, DIAG_AIRLOCK_HUD, DIAG_NANITE_FULL_HUD)
hud_icons = list(DIAG_HUD, DIAG_STAT_HUD, DIAG_BATT_HUD, DIAG_MECH_HUD, DIAG_BOT_HUD, DIAG_CIRCUIT_HUD, DIAG_TRACK_HUD, DIAG_AIRLOCK_HUD, DIAG_NANITE_FULL_HUD, DIAG_LAUNCHPAD_HUD)
/datum/atom_hud/data/diagnostic/advanced
hud_icons = list(DIAG_HUD, DIAG_STAT_HUD, DIAG_BATT_HUD, DIAG_MECH_HUD, DIAG_BOT_HUD, DIAG_CIRCUIT_HUD, DIAG_TRACK_HUD, DIAG_AIRLOCK_HUD, DIAG_NANITE_FULL_HUD, DIAG_PATH_HUD)
hud_icons = list(DIAG_HUD, DIAG_STAT_HUD, DIAG_BATT_HUD, DIAG_MECH_HUD, DIAG_BOT_HUD, DIAG_CIRCUIT_HUD, DIAG_TRACK_HUD, DIAG_AIRLOCK_HUD, DIAG_NANITE_FULL_HUD, DIAG_PATH_HUD,DIAG_LAUNCHPAD_HUD)
/datum/atom_hud/data/bot_path
hud_icons = list(DIAG_PATH_HUD)

View File

@@ -119,3 +119,8 @@
// volume = 70
// falloff_distance = 5
// falloff_exponent = 20
/datum/looping_sound/rbmk_reactor
mid_length = 16
mid_sounds = list('sound/effects/rbmk/reactor_hum.ogg' = 10)
volume = 10

View File

@@ -15,6 +15,8 @@
/// Set this variable to something not null, this'll be the preferred unarmed parry in most cases if [can_martial_parry] is TRUE. YOU MUST RUN [get_block_parry_data(this)] INSTEAD OF DIRECTLY ACCESSING!
var/datum/block_parry_data/block_parry_data
var/pugilist = FALSE
var/datum/weakref/holder //owner of the martial art
var/display_combos = FALSE //shows combo meter if true
/datum/martial_art/proc/disarm_act(mob/living/carbon/human/A, mob/living/carbon/human/D)
return FALSE
@@ -25,7 +27,7 @@
/datum/martial_art/proc/grab_act(mob/living/carbon/human/A, mob/living/carbon/human/D)
return FALSE
/datum/martial_art/proc/can_use(mob/living/carbon/human/H)
/datum/martial_art/proc/can_use(mob/living/carbon/human/owner_human)
return TRUE
/datum/martial_art/proc/add_to_streak(element,mob/living/carbon/human/D)
@@ -34,11 +36,16 @@
streak = streak+element
if(length(streak) > max_streak_length)
streak = copytext(streak, 1 + length(streak[1]))
if(display_combos)
var/mob/living/holder_living = holder.resolve()
holder_living?.hud_used?.combo_display.update_icon_state(streak)
return
/datum/martial_art/proc/reset_streak(mob/living/carbon/human/new_target)
current_target = new_target
streak = ""
var/mob/living/holder_living = holder.resolve()
holder_living?.hud_used?.combo_display.update_icon_state(streak)
/datum/martial_art/proc/damage_roll(mob/living/carbon/human/A, mob/living/carbon/human/D)
//Here we roll for our damage to be added into the damage var in the various attack procs. This is changed depending on whether we are in combat mode, lying down, or if our target is in combat mode.
@@ -47,46 +54,48 @@
damage *= 0.7
return damage
/datum/martial_art/proc/teach(mob/living/carbon/human/H, make_temporary = FALSE)
if(!istype(H) || !H.mind)
/datum/martial_art/proc/teach(mob/living/carbon/human/owner_human, make_temporary = FALSE)
if(!istype(owner_human) || !owner_human.mind)
return FALSE
if(H.mind.martial_art)
if(owner_human.mind.martial_art)
if(make_temporary)
if(!H.mind.martial_art.allow_temp_override)
if(!owner_human.mind.martial_art.allow_temp_override)
return FALSE
store(H.mind.martial_art,H)
store(owner_human.mind.martial_art,owner_human)
else
H.mind.martial_art.on_remove(H)
owner_human.mind.martial_art.on_remove(owner_human)
else if(make_temporary)
base = H.mind.default_martial_art
base = owner_human.mind.default_martial_art
if(help_verb)
add_verb(H, help_verb)
H.mind.martial_art = src
add_verb(owner_human, help_verb)
owner_human.mind.martial_art = src
holder = WEAKREF(owner_human)
if(pugilist)
ADD_TRAIT(H, TRAIT_PUGILIST, MARTIAL_ARTIST_TRAIT)
ADD_TRAIT(owner_human, TRAIT_PUGILIST, MARTIAL_ARTIST_TRAIT)
return TRUE
/datum/martial_art/proc/store(datum/martial_art/M,mob/living/carbon/human/H)
M.on_remove(H)
/datum/martial_art/proc/store(datum/martial_art/M,mob/living/carbon/human/owner_human)
M.on_remove(owner_human)
if(M.base) //Checks if M is temporary, if so it will not be stored.
base = M.base
else //Otherwise, M is stored.
base = M
/datum/martial_art/proc/remove(mob/living/carbon/human/H)
if(!istype(H) || !H.mind || H.mind.martial_art != src)
/datum/martial_art/proc/remove(mob/living/carbon/human/owner_human)
if(!istype(owner_human) || !owner_human.mind || owner_human.mind.martial_art != src)
return
on_remove(H)
on_remove(owner_human)
if(base)
base.teach(H)
base.teach(owner_human)
else
var/datum/martial_art/X = H.mind.default_martial_art
X.teach(H)
REMOVE_TRAIT(H, TRAIT_PUGILIST, MARTIAL_ARTIST_TRAIT)
var/datum/martial_art/X = owner_human.mind.default_martial_art
X.teach(owner_human)
REMOVE_TRAIT(owner_human, TRAIT_PUGILIST, MARTIAL_ARTIST_TRAIT)
holder = null
/datum/martial_art/proc/on_remove(mob/living/carbon/human/H)
/datum/martial_art/proc/on_remove(mob/living/carbon/human/owner_human)
if(help_verb)
remove_verb(H, help_verb)
remove_verb(owner_human, help_verb)
return
///Gets called when a projectile hits the owner. Returning anything other than BULLET_ACT_HIT will stop the projectile from hitting the mob.

View File

@@ -11,6 +11,7 @@
block_chance = 75
pugilist = TRUE
var/old_grab_state = null
display_combos = TRUE
/datum/martial_art/cqc/reset_streak(mob/living/carbon/human/new_target)
. = ..()

View File

@@ -7,6 +7,7 @@
id = MARTIALART_PLASMAFIST
help_verb = /mob/living/carbon/human/proc/plasma_fist_help
pugilist = TRUE
display_combos = TRUE
/datum/martial_art/plasma_fist/proc/check_streak(mob/living/carbon/human/A, mob/living/carbon/human/D)

View File

@@ -13,6 +13,7 @@
var/datum/action/risingbassmove/sidekick = new/datum/action/risingbassmove/sidekick()
var/datum/action/risingbassmove/deftswitch = new/datum/action/risingbassmove/deftswitch()
var/repulsecool = 0
display_combos = TRUE
/datum/martial_art/the_rising_bass/proc/check_streak(mob/living/carbon/human/A, mob/living/carbon/human/D)
if(findtext(streak,SIDE_KICK_COMBO))

View File

@@ -9,6 +9,7 @@
help_verb = /mob/living/carbon/human/proc/sleeping_carp_help
block_parry_data = /datum/block_parry_data/sleeping_carp
pugilist = TRUE
display_combos = TRUE
/datum/martial_art/the_sleeping_carp/proc/check_streak(mob/living/carbon/human/A, mob/living/carbon/human/D)
if(findtext(streak,STRONG_PUNCH_COMBO))

View File

@@ -55,6 +55,11 @@
suffix = "Box/Engine/budget.dmm"
name = "Box P.A.C.M.A.N"
/datum/map_template/ruin/station/box/engine/rbmk
id = "engine_rbmk"
suffix = "Box/Engine/engine_rbmk.dmm"
name = "Box RBMK"
// Lavaland
// Mining Base
/datum/map_template/ruin/station/lavaland/mining_base

View File

@@ -864,6 +864,10 @@
return SEND_SIGNAL(src, COMSIG_ATOM_EMAG_ACT)
/atom/proc/rad_act(strength)
var/turf/open/pool/PL = get_turf(src)
if(istype(PL))
if(PL.filled == TRUE)
strength *= 0.15
SEND_SIGNAL(src, COMSIG_ATOM_RAD_ACT, strength)
/atom/proc/narsie_act()

View File

@@ -100,6 +100,7 @@
var/new_x = text2num(params["x"])
var/new_y = text2num(params["y"])
current_pad.set_offset(new_x, new_y)
current_pad.update_indicator()
. = TRUE
if("move_pos")
var/plus_x = text2num(params["x"])
@@ -108,6 +109,7 @@
x = current_pad.x_offset + plus_x,
y = current_pad.y_offset + plus_y
)
current_pad.update_indicator()
. = TRUE
if("rename")
. = TRUE
@@ -119,12 +121,15 @@
if(usr && alert(usr, "Are you sure?", "Unlink Launchpad", "I'm Sure", "Abort") != "Abort")
launchpads -= current_pad
selected_id = null
current_pad.update_indicator()
. = TRUE
if("launch")
teleport(usr, current_pad, TRUE)
current_pad.update_indicator()
. = TRUE
if("pull")
teleport(usr, current_pad, FALSE)
current_pad.update_indicator()
. = TRUE
. = TRUE

View File

@@ -6,6 +6,7 @@
use_power = TRUE
idle_power_usage = 200
active_power_usage = 2500
hud_possible = list(DIAG_LAUNCHPAD_HUD)
circuit = /obj/item/circuitboard/machine/launchpad
var/icon_teleport = "lpad-beam"
var/stationary = TRUE //to prevent briefcase pad deconstruction and such
@@ -24,6 +25,25 @@
E += M.rating*15
range = E
/obj/machinery/launchpad/Initialize()
. = ..()
prepare_huds()
for(var/datum/atom_hud/data/diagnostic/diag_hud in GLOB.huds)
diag_hud.add_to_hud(src)
var/image/holder = hud_list[DIAG_LAUNCHPAD_HUD]
var/mutable_appearance/MA = new /mutable_appearance()
MA.icon = 'icons/effects/effects.dmi'
MA.icon_state = "launchpad_target"
MA.layer = ABOVE_OPEN_TURF_LAYER
MA.plane = 0
holder.appearance = MA
update_indicator()
/obj/machinery/launchpad/Destroy()
qdel(hud_list[DIAG_LAUNCHPAD_HUD])
return ..()
/obj/machinery/launchpad/examine(mob/user)
. = ..()
if(in_range(user, src) || isobserver(user))
@@ -32,6 +52,7 @@
/obj/machinery/launchpad/attackby(obj/item/I, mob/user, params)
if(stationary)
if(default_deconstruction_screwdriver(user, "lpad-idle-o", "lpad-idle", I))
update_indicator()
return
if(panel_open)
@@ -63,6 +84,17 @@
return FALSE
return TRUE
/obj/machinery/launchpad/proc/update_indicator()
var/image/holder = hud_list[DIAG_LAUNCHPAD_HUD]
var/turf/target_turf
if(isAvailable())
target_turf = locate(x + x_offset, y + y_offset, z)
if(target_turf)
holder.icon_state = indicator_icon
holder.loc = target_turf
else
holder.icon_state = null
/obj/machinery/launchpad/proc/set_offset(x, y)
if(teleporting)
return
@@ -89,11 +121,13 @@
flick(icon_teleport, src)
//Change the indicator's icon to show that we're teleporting
if(sending)
indicator_icon = "launchpad_launch"
else
indicator_icon = "launchpad_pull"
update_indicator()
playsound(get_turf(src), 'sound/weapons/flash.ogg', 25, TRUE)
teleporting = TRUE
@@ -103,6 +137,7 @@
//Set the indicator icon back to normal
indicator_icon = "launchpad_target"
update_indicator()
if(QDELETED(src) || !isAvailable())
return
@@ -213,6 +248,7 @@
if(do_after(usr, 30, target = usr))
usr.put_in_hands(briefcase)
moveToNullspace() //hides it from suitcase contents
update_indicator()
closed = TRUE
/obj/machinery/launchpad/briefcase/attackby(obj/item/I, mob/user, params)
@@ -249,6 +285,7 @@
user.visible_message("<span class='notice'>[user] starts setting down [src]...", "You start setting up [pad]...</span>")
if(do_after(user, 30, target = user))
pad.forceMove(get_turf(src))
pad.update_indicator()
pad.closed = FALSE
user.transferItemToLoc(src, pad, TRUE)
SEND_SIGNAL(src, COMSIG_TRY_STORAGE_HIDE_ALL)
@@ -322,6 +359,7 @@
var/new_x = text2num(params["x"])
var/new_y = text2num(params["y"])
pad.set_offset(new_x, new_y)
pad.update_indicator()
. = TRUE
if("move_pos")
var/plus_x = text2num(params["x"])
@@ -330,6 +368,7 @@
x = pad.x_offset + plus_x,
y = pad.y_offset + plus_y
)
pad.update_indicator()
. = TRUE
if("rename")
. = TRUE
@@ -340,12 +379,15 @@
if("remove")
. = TRUE
if(usr && alert(usr, "Are you sure?", "Unlink Launchpad", "I'm Sure", "Abort") != "Abort")
pad.update_indicator()
pad = null
if("launch")
sending = TRUE
teleport(usr, pad)
pad.update_indicator()
. = TRUE
if("pull")
sending = FALSE
teleport(usr, pad)
pad.update_indicator()
. = TRUE

View File

@@ -0,0 +1,112 @@
//ported from TG, credit to XDTM
/obj/item/swapper
name = "quantum spin inverter"
desc = "An experimental device that is able to swap the locations of two entities by switching their particles' spin values. Must be linked to another device to function."
icon = 'icons/obj/device.dmi'
icon_state = "swapper"
item_state = "electronic"
w_class = WEIGHT_CLASS_SMALL
item_flags = NOBLUDGEON
lefthand_file = 'icons/mob/inhands/misc/devices_lefthand.dmi'
righthand_file = 'icons/mob/inhands/misc/devices_righthand.dmi'
var/cooldown = 300
var/next_use = 0
var/obj/item/swapper/linked_swapper
/obj/item/swapper/Destroy()
if(linked_swapper)
linked_swapper.linked_swapper = null //*inception music*
linked_swapper.update_appearance()
linked_swapper = null
return ..()
/obj/item/swapper/update_icon_state()
icon_state = "swapper[linked_swapper ? "-linked" : null]"
return ..()
/obj/item/swapper/attackby(obj/item/I, mob/user, params)
if(istype(I, /obj/item/swapper))
var/obj/item/swapper/other_swapper = I
if(other_swapper.linked_swapper)
to_chat(user, span_warning("[other_swapper] is already linked. Break the current link to establish a new one."))
return
if(linked_swapper)
to_chat(user, span_warning("[src] is already linked. Break the current link to establish a new one."))
return
to_chat(user, span_notice("You establish a quantum link between the two devices."))
linked_swapper = other_swapper
other_swapper.linked_swapper = src
update_appearance()
linked_swapper.update_appearance()
else
return ..()
/obj/item/swapper/attack_self(mob/living/user)
if(world.time < next_use)
to_chat(user, span_warning("[src] is still recharging."))
return
if(QDELETED(linked_swapper))
to_chat(user, span_warning("[src] is not linked with another swapper."))
return
playsound(src, 'sound/weapons/flash.ogg', 25, TRUE)
to_chat(user, span_notice("You activate [src]."))
playsound(linked_swapper, 'sound/weapons/flash.ogg', 25, TRUE)
if(ismob(linked_swapper.loc))
var/mob/holder = linked_swapper.loc
to_chat(holder, span_notice("[linked_swapper] starts buzzing."))
next_use = world.time + cooldown //only the one used goes on cooldown
addtimer(CALLBACK(src, .proc/swap, user), 25)
/obj/item/swapper/examine(mob/user)
. = ..()
if(world.time < next_use)
. += span_warning("Time left to recharge: [DisplayTimeText(next_use - world.time)].")
if(linked_swapper)
. += span_notice("<b>Linked.</b> Alt-Click to break the quantum link.")
else
. += span_notice("<b>Not Linked.</b> Use on another quantum spin inverter to establish a quantum link.")
/obj/item/swapper/AltClick(mob/living/user)
if(!user.canUseTopic(src, BE_CLOSE, NO_DEXTERY,, FALSE, !iscyborg(user))) //someone mispelled dexterity
return
to_chat(user, span_notice("You break the current quantum link."))
if(!QDELETED(linked_swapper))
linked_swapper.linked_swapper = null
linked_swapper.update_appearance()
linked_swapper = null
update_appearance()
//Gets the topmost teleportable container
/obj/item/swapper/proc/get_teleportable_container()
var/atom/movable/teleportable = src
while(ismovable(teleportable.loc))
var/atom/movable/AM = teleportable.loc
if(AM.anchored)
break
if(isliving(AM))
var/mob/living/L = AM
if(L.buckled)
if(L.buckled.anchored)
break
else
var/obj/buckled_obj = L.buckled
buckled_obj.unbuckle_mob(L)
teleportable = AM
return teleportable
/obj/item/swapper/proc/swap(mob/user)
if(QDELETED(linked_swapper) || world.time < linked_swapper.cooldown)
return
var/atom/movable/A = get_teleportable_container()
var/atom/movable/B = linked_swapper.get_teleportable_container()
var/target_A = A.drop_location()
var/target_B = B.drop_location()
//TODO: add a sound effect or visual effect
if(do_teleport(A, target_B, channel = TELEPORT_CHANNEL_QUANTUM))
do_teleport(B, target_A, channel = TELEPORT_CHANNEL_QUANTUM)
if(ismob(B))
var/mob/M = B
to_chat(M, span_warning("[linked_swapper] activates, and you find yourself somewhere else."))

View File

@@ -494,6 +494,38 @@
title = "Toxins or: How I Learned to Stop Worrying and Love the Maxcap"
page_link = "Guide_to_toxins"
/obj/item/book/manual/wiki/rbmk
name = "\improper Haynes nuclear reactor owner's manual"
icon_state = "bookEngineering2"
author = "CogWerk Engineering Reactor Design Department"
title = "Haynes nuclear reactor owner's manual"
page_link = "Guide_to_the_Nuclear_Reactor"
/obj/item/book/manual/wiki/rbmk/initialize_wikibook()
var/wikiurl = "https://nsv.beestation13.com/wiki"
if(wikiurl)
dat = {"
<html><head>
<meta http-equiv='Content-Type' content='text/html; charset=UTF-8'>
<style>
iframe {
display: none;
}
</style>
</head>
<body>
<script type="text/javascript">
function pageloaded(myframe) {
document.getElementById("loading").style.display = "none";
myframe.style.display = "inline";
}
</script>
<p id='loading'>You start skimming through the manual...</p>
<iframe width='100%' height='97%' onload="pageloaded(this)" src="[wikiurl]/[page_link]?printable=yes&remove_links=1" frameborder="0" id="main_frame"></iframe>
</body>
</html>
"}
/obj/item/book/manual/wiki/toxins/suicide_act(mob/user)
var/mob/living/carbon/human/H = user
user.visible_message("<span class='suicide'>[user] starts dancing to the Rhumba Beat! It looks like [user.p_theyre()] trying to commit suicide!</span>")

View File

@@ -0,0 +1,4 @@
/datum/export/plutonium_rod
cost = 20000
unit_name = "Plutonium Rod"
export_types = list(/obj/item/fuel_rod/plutonium)

View File

@@ -158,6 +158,14 @@
/obj/item/clothing/head/hardhat/red)
crate_name = "firefighting crate"
/datum/supply_pack/emergency/Flexiseal
name = "Flexi Seal Crate"
desc = "Flexi Seal, the perfect stuff for fixing a nuclear reactor safely!"
cost = 1000
contains = list(/obj/item/sealant)
crate_name = "Flexi Seal Crate"
crate_type = /obj/structure/closet/crate/radiation
/datum/supply_pack/emergency/atmostank
name = "Firefighting Tank Backpack"
desc = "Mow down fires with this high-capacity fire fighting tank backpack. Requires Atmospherics access to open."

View File

@@ -166,3 +166,40 @@
cost = 7000
contains = list(/obj/machinery/the_singularitygen/tesla)
crate_name = "tesla generator crate"
/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/fuel_rod,
/obj/item/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/fuel_rod/material/bananium,
/obj/item/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,
/obj/item/paper/fluff/rbmkcargo,
/obj/item/book/manual/wiki/rbmk)
crate_name = "Build Your Own Reactor Kit"
crate_type = /obj/structure/closet/crate/secure/engineering
dangerous = TRUE

View File

@@ -98,6 +98,16 @@
name = "garden & kitchen bluespace shelter capsule"
desc = "Everything someone needs to make a home cooked meal while surviving the depths of hell... or space."
template_id = "shelter_zeta"
// RBMK reactor beacon so people can create the engine
/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"
//Pod objects
//Window

View File

@@ -107,3 +107,11 @@
. = ..()
whitelisted_turfs = typecacheof(/turf/closed/mineral)
banned_objects = typecacheof(/obj/structure/stone_tile)
// 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"

View File

@@ -14,7 +14,7 @@
skinned_type = /obj/item/stack/sheet/animalhide/xeno
exotic_bloodtype = "X*"
damage_overlay_type = "xeno"
disliked_food = JUNKFOOD
disliked_food = null
liked_food = GROSS | MEAT
species_category = SPECIES_CATEGORY_ALIEN
wings_icons = SPECIES_WINGS_DRAGON //most depictions of xenomorphs with wings are closest to this.

View File

@@ -37,6 +37,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

View File

@@ -0,0 +1,251 @@
/obj/item/fuel_rod
name = "Uranium-235 Fuel Rod"
desc = "A titanium sheathed rod containing a measure of enriched uranium-dioxide powder inside, and a breeding blanket of uranium-238 around it, used to kick off a fission reaction and breed plutonium fuel respectivly."
icon = 'icons/obj/control_rod.dmi'
icon_state = "irradiated"
w_class = WEIGHT_CLASS_BULKY
var/depletion = 0 //Each fuel rod will deplete in around 30 minutes.
var/fuel_power = 0.10
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/fuel_rod/ComponentInitialize()
. = ..()
AddComponent(/datum/component/two_handed, require_twohands = TRUE)
/obj/item/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/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/fuel_rod/proc/depletion_final(result_rod)
if(!result_rod)
return
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/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/fuel_rod/plutonium(loc)
R.depletion = depletion
if(prob(1))
R.name = "Plush-239 Fuel Rod"
R.desc = "NanoTrasen would like to remind you that it is not liable for any permanent radioactive damage done to its employees."
R.icon = 'icons/obj/plushes.dmi'
R.icon_state = "romanian"
R.fuel_power = 0.25 //Funny easter egg, slightly more powerful too.
if("depleted")
if(fuel_power < 10)
fuel_power = 0
playsound(loc, 'sound/effects/supermatter.ogg', 100, TRUE)
R = new /obj/item/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/fuel_rod/proc/deplete(amount=0.035)
depletion += amount * depletion_speed_modifier
if(depletion >= depletion_threshold && !depleted_final)
depleted_final = TRUE
depletion_final(depletion_conversion_type)
/obj/item/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/fuel_rod/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/fuel_rod/depleted
fuel_power = 0.05
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 = null // It means that it won't turn into anything
process = TRUE
// Master type for material optional (or requiring, wyci) and/or producing rods
/obj/item/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 = null
// Called when the rod is fully harvested
/obj/item/fuel_rod/material/proc/expend()
expended = TRUE
// Basic checks for material rods
/obj/item/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/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/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/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>")
playsound(loc, 'sound/effects/stonedoor_openclose.ogg', 50, 1)
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>")
playsound(src, 'sound/machines/buzz-sigh.ogg', 50, 0)
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>")
playsound(loc, 'sound/effects/stonedoor_openclose.ogg', 50, 1)
initial_amount = 0
/obj/item/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)
. += "<span class='warning'>This fuel rod's [material_name] are now fully grown, and it currently bears [grown_amount] harvestable [material_name_singular]\s.</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/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/fuel_rod/material/telecrystal/depletion_final(result_rod)
..()
if(result_rod)
return
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/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/fuel_rod/material/bananium/deplete(amount=0.035)
..()
if(initial_amount == max_initial_amount && prob(10))
playsound(src, pick('sound/items/bikehorn.ogg', 'sound/misc/bikehorn_creepy.ogg'), 50) // HONK
/obj/item/fuel_rod/material/bananium/depletion_final(result_rod)
..()
if(result_rod)
return
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

View File

@@ -0,0 +1,37 @@
// 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
link_to_reactor()
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, 9999999) // cmon, what are the chances? The chances are... Very low friend... But maybe we can make this a bit better.
// Cargo variants 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
/obj/item/paper/fluff/rbmkcargo
name = "Nuclear Reactor Instructions"
info = "Make sure a 5x5 area is completely clear of pipes, cables and machinery when using the beacon. Those will be provided automatically with the beacon's bluespace decompression. Use a multitool on the reactor then on the computers provided to link them together. Also make sure the reactor has a proper pipeline filled with cooling gas before inserting fuel rods. Good luck!"

View File

@@ -1686,14 +1686,14 @@ All effects don't start immediately, but rather get worse over time; the rate is
var/heal_points = 10
if(L.health <= 0)
heal_points = 20 //heal more if we're in softcrit
for(var/i in 1 to min(volume, heal_points)) //only heals 1 point of damage per unit on add, for balance reasons
L.adjustBruteLoss(-1)
L.adjustFireLoss(-1)
L.adjustToxLoss(-1)
L.adjustOxyLoss(-1)
L.adjustStaminaLoss(-1)
heal_points = min(volume, heal_points)
L.adjustBruteLoss(-heal_points)
L.adjustFireLoss(-heal_points)
L.adjustToxLoss(-heal_points)
L.adjustOxyLoss(-heal_points)
L.adjustStaminaLoss(-heal_points)
L.visible_message("<span class='warning'>[L] shivers with renewed vigor!</span>", "<span class='notice'>One taste of [lowertext(name)] fills you with energy!</span>")
if(!L.stat && heal_points == 20) //brought us out of softcrit
if(!L.stat && L.health > 0) //brought us out of softcrit
L.visible_message("<span class='danger'>[L] lurches to [L.p_their()] feet!</span>", "<span class='boldnotice'>Up and at 'em, kid.</span>")
/datum/reagent/consumable/ethanol/bastion_bourbon/on_mob_life(mob/living/L)

View File

@@ -115,3 +115,13 @@
build_path = /obj/item/pipe/bluespace
category = list("Bluespace Designs")
departmental_flags = DEPARTMENTAL_FLAG_SCIENCE | DEPARTMENTAL_FLAG_ENGINEERING
/datum/design/swapper //ported from TG, credit to XDTM
name = "Quantum Spin Inverter"
desc = "An experimental device that is able to swap the locations of two entities by switching their particles' spin values. Must be linked to another device to function."
id = "swapper"
build_type = PROTOLATHE
materials = list(/datum/material/iron = 500, /datum/material/diamond = 1500, /datum/material/glass = 1000, /datum/material/bluespace = 2000, /datum/material/silver=1000)
build_path = /obj/item/swapper
category = list("Bluespace Designs")
departmental_flags = DEPARTMENTAL_FLAG_SCIENCE

View File

@@ -61,7 +61,7 @@
display_name = "Bluespace Travel"
description = "Application of Bluespace for static teleportation technology."
prereq_ids = list("adv_power", "adv_bluespace")
design_ids = list("tele_station", "tele_hub", "quantumpad", "quantum_keycard", "launchpad", "launchpad_console", "teleconsole", "roastingstick", "bluespace_pipe")
design_ids = list("tele_station", "tele_hub", "quantumpad", "quantum_keycard", "launchpad", "launchpad_console", "teleconsole", "roastingstick", "bluespace_pipe","swapper")
research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500)
/datum/techweb_node/unregulated_bluespace

View File

@@ -15,6 +15,7 @@
var/list/accents = list() //done in order of priority (please always apply abductor accent and stuttering last)
var/static/list/languages_possible_base = typecacheof(list(
/datum/language/common,
/datum/language/machine,
/datum/language/draconic,
/datum/language/codespeak,
/datum/language/monkey,
@@ -142,7 +143,7 @@
icon_state = "tonguexeno"
say_mod = "hisses"
taste_sensitivity = 10 // LIZARDS ARE ALIENS CONFIRMED
maxHealth = 500 //They've a little mouth for a tongue, so it's pretty rhobust
maxHealth = 500 //They've a little mouth for a tongue, so it's pretty robust
initial_accents = list(/datum/accent/alien)
var/static/list/languages_possible_alien = typecacheof(list(
/datum/language/xenocommon,
@@ -155,6 +156,13 @@
. = ..()
languages_possible = languages_possible_alien
/obj/item/organ/tongue/alien/hybrid
name = "xenohybrid tongue"
/obj/item/organ/tongue/alien/hybrid/Initialize(mapload)
. = ..()
languages_possible = languages_possible_base
/obj/item/organ/tongue/bone
name = "bone \"tongue\""
desc = "Apparently skeletons alter the sounds they produce through oscillation of their teeth, hence their characteristic rattling."
@@ -248,6 +256,7 @@
taste_sensitivity = 101 // Not a tongue, they can't taste shit
var/static/list/languages_possible_ethereal = typecacheof(list(
/datum/language/common,
/datum/language/machine,
/datum/language/draconic,
/datum/language/codespeak,
/datum/language/monkey,
@@ -269,6 +278,7 @@
say_mod = "chitters"
var/static/list/languages_possible_arachnid = typecacheof(list(
/datum/language/common,
/datum/language/machine,
/datum/language/draconic,
/datum/language/codespeak,
/datum/language/monkey,

View File

@@ -275,6 +275,18 @@
purchasable_from = UPLINK_NUKE_OPS | UPLINK_CLOWN_OPS
restricted = TRUE
//this seems like a terrible idea to me, so commenting it out for now. -Shell
/*
/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
*/
/* for now
/datum/uplink_item/device_tools/suspiciousphone
name = "Protocol CRAB-17 Phone"

View File

@@ -470,6 +470,7 @@ BOX_RANDOM_ENGINE Box TEG,3
BOX_RANDOM_ENGINE Box Empty,0
BOX_RANDOM_ENGINE Box Antimatter,1
BOX_RANDOM_ENGINE Box P.A.C.M.A.N,1
BOX_RANDOM_ENGINE Box RBMK,3
## Whether the suicide verb is allowed.

View File

@@ -26,3 +26,23 @@
2022-09-14:
timothyteakettle:
- rscadd: lets ghosts click a pAI device to download into it without a master
2022-09-18:
Putnam3145:
- code_imp: Spurious for loop squashed
That REALLY Good Soda Flavor, jacklecroy on GitHub, ported by Hatterhat:
- rscadd: Using certain martial arts will create a combo meter when you attack.
- imageadd: Added combo meter icons.
shellspeed1:
- rscadd: The Quantum Spin design has been brought over from TG for testing in the
Citadel Station facilities.
- balance: Launchpads now have a targeting icon.
- balance: Massive gamebreaking balance. Xenohybrids can now eat DOUGHNUTS. Security
officers everywhere are afraid.
- bugfix: makes it some people can speak the encoded langauge.
- bugfix: makes the xenotongue a xenohybrid tongue so that people with it can speak
other langauges.
- rscadd: Adds the RBMK reactor from NSV. Credit to Kmc2000 for originally making
it. https://github.com/BeeStation/NSV13/pull/828
2022-09-19:
Putnam3145:
- code_imp: Auxmos updated to 2.0.0

Binary file not shown.

Before

Width:  |  Height:  |  Size: 888 KiB

After

Width:  |  Height:  |  Size: 890 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 117 KiB

After

Width:  |  Height:  |  Size: 119 KiB

BIN
icons/obj/control_rod.dmi Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 59 KiB

After

Width:  |  Height:  |  Size: 59 KiB

BIN
icons/obj/inflatable.dmi Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

BIN
icons/obj/machines/rbmk.dmi Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

BIN
icons/obj/rbmk_computer.dmi Normal file

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.

View File

@@ -196,6 +196,7 @@
#include "code\__HELPERS\level_traits.dm"
#include "code\__HELPERS\lighting.dm"
#include "code\__HELPERS\markov.dm"
#include "code\__HELPERS\matrices.dm"
#include "code\__HELPERS\mobs.dm"
#include "code\__HELPERS\mouse_control.dm"
#include "code\__HELPERS\names.dm"
@@ -1203,6 +1204,7 @@
#include "code\game\objects\items\devices\reverse_bear_trap.dm"
#include "code\game\objects\items\devices\scanners.dm"
#include "code\game\objects\items\devices\sensor_device.dm"
#include "code\game\objects\items\devices\swapper.dm"
#include "code\game\objects\items\devices\taperecorder.dm"
#include "code\game\objects\items\devices\traitordevices.dm"
#include "code\game\objects\items\devices\transfer_valve.dm"
@@ -1970,6 +1972,7 @@
#include "code\modules\cargo\bounties\slime.dm"
#include "code\modules\cargo\bounties\special.dm"
#include "code\modules\cargo\bounties\virus.dm"
#include "code\modules\cargo\exports\engineering.dm"
#include "code\modules\cargo\exports\food_wine.dm"
#include "code\modules\cargo\exports\gear.dm"
#include "code\modules\cargo\exports\large_objects.dm"
@@ -3109,6 +3112,9 @@
#include "code\modules\power\antimatter\containment_jar.dm"
#include "code\modules\power\antimatter\control.dm"
#include "code\modules\power\antimatter\shielding.dm"
#include "code\modules\power\reactor\fuel_rods.dm"
#include "code\modules\power\reactor\rbmk.dm"
#include "code\modules\power\reactor\reactor_cargo.dm"
#include "code\modules\power\singularity\collector.dm"
#include "code\modules\power\singularity\containment_field.dm"
#include "code\modules\power\singularity\emitter.dm"

View File

@@ -0,0 +1,94 @@
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 { NtosWindow } from '../layouts';
import { useBackend, useLocalState } from '../backend';
export const NtosRbmkStats = (props, context) => {
const { act, data } = useBackend(context);
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 (
<NtosWindow
resizable
width={440}
height={650}>
<NtosWindow.Content>
<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 fill 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>
</NtosWindow.Content>
</NtosWindow>
);
};

View File

@@ -0,0 +1,56 @@
import { Fragment } from 'inferno';
import { useBackend, useLocalState } from '../backend';
import { Section, ProgressBar, Slider } from '../components';
import { Window } from '../layouts';
export const RbmkControlRods = (props, context) => {
const { act, data } = useBackend(context);
const control_rods = data.control_rods;
const k = data.k;
const desiredK = data.desiredK;
return (
<Window
resizable
theme="ntos"
width={300}
height={300}>
<Window.Content>
<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 />
<Slider
value={desiredK}
fillValue={k}
minValue={0}
maxValue={3}
step={0.1}
stepPixelSize={5}
onDrag={(e, value) => act('input', {
target: value,
})} />
</Section>
</Window.Content>
</Window>
);
};

View File

@@ -0,0 +1,89 @@
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 { Window } from '../layouts';
import { useBackend, useLocalState } from '../backend';
export const RbmkStats = (props, context) => {
const { act, data } = useBackend(context);
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 (
<Window
resizable
theme="ntos"
width={350}
height={500}>
<Window.Content>
<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 fill 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>
</Window.Content>
</Window>
);
};