diff --git a/_maps/map_files/generic/CentCom.dmm b/_maps/map_files/generic/CentCom.dmm index 9f3dbc39c251..2409fd65a5d0 100644 --- a/_maps/map_files/generic/CentCom.dmm +++ b/_maps/map_files/generic/CentCom.dmm @@ -12624,7 +12624,7 @@ /obj/effect/portal/permanent/one_way/multi/entry{ alpha = 55; color = "7D7D7D"; - desc = "for when the clock hits one thirty and keeps ticking..."; + desc = "For when the clock hits one thirty and keeps ticking..."; id = "testchamber"; name = "Test Chamber Portal"; teleport_channel = "quantum" @@ -21648,7 +21648,7 @@ /obj/effect/portal/permanent/one_way/multi/entry{ alpha = 55; color = "7D7D7D"; - desc = "for when the clock hits one thirty and keeps ticking..."; + desc = "For when the clock hits one thirty and keeps ticking..."; id = "testchamber"; name = "Test Chamber Portal"; teleport_channel = "quantum" @@ -23483,7 +23483,7 @@ /obj/effect/portal/permanent/one_way/multi/entry{ alpha = 55; color = "7D7D7D"; - desc = "for when the clock hits one thirty and keeps ticking..."; + desc = "For when the clock hits one thirty and keeps ticking..."; id = "testchamber"; name = "Test Chamber Portal"; teleport_channel = "quantum" diff --git a/code/__DEFINES/construction/material.dm b/code/__DEFINES/construction/material.dm index 294fe6364cd5..10eeaf9ea6cf 100644 --- a/code/__DEFINES/construction/material.dm +++ b/code/__DEFINES/construction/material.dm @@ -12,7 +12,7 @@ /// The maximum size of a stack object. #define MAX_STACK_SIZE 50 /// Maximum amount of cable in a coil -#define MAXCOIL 30 +#define MAXCOIL 40 //Category of materials /// Is the material from an ore? currently unused but exists atm for categorizations sake diff --git a/code/__DEFINES/dcs/signals/signals_atom/signals_atom_main.dm b/code/__DEFINES/dcs/signals/signals_atom/signals_atom_main.dm index 4f56824b5e4a..188297594d37 100644 --- a/code/__DEFINES/dcs/signals/signals_atom/signals_atom_main.dm +++ b/code/__DEFINES/dcs/signals/signals_atom/signals_atom_main.dm @@ -100,6 +100,9 @@ /// from cosmetic items to restyle certain mobs, objects or organs: (atom/source, mob/living/trimmer, atom/movable/original_target, body_zone, restyle_type, style_speed) #define COMSIG_ATOM_RESTYLE "atom_restyle" +/// Called on [/atom/SpinAnimation()] : (speed, loops, segments, angle) +#define COMSIG_ATOM_SPIN_ANIMATION "atom_spin_animation" + ///! from proc/get_rad_contents(): () #define COMSIG_ATOM_RAD_PROBE "atom_rad_probe" #define COMPONENT_BLOCK_RADIATION 1 diff --git a/code/__DEFINES/dcs/signals/signals_atom/signals_atom_movable.dm b/code/__DEFINES/dcs/signals/signals_atom/signals_atom_movable.dm index 45be2ed4f984..44278be89e13 100644 --- a/code/__DEFINES/dcs/signals/signals_atom/signals_atom_movable.dm +++ b/code/__DEFINES/dcs/signals/signals_atom/signals_atom_movable.dm @@ -94,6 +94,7 @@ /// from base of atom/movable/Process_Spacemove(): (movement_dir, continuous_move) #define COMSIG_MOVABLE_SPACEMOVE "spacemove" #define COMSIG_MOVABLE_STOP_SPACEMOVE (1<<0) + #define COMSIG_MOVABLE_ALLOW_SPACEMOVE (1<<1) /// Sent from /obj/item/radio/talk_into(): (obj/item/radio/used_radio) #define COMSIG_MOVABLE_USING_RADIO "movable_radio" diff --git a/code/__DEFINES/layers.dm b/code/__DEFINES/layers.dm index 1ba6879005b8..211dc52c42d3 100644 --- a/code/__DEFINES/layers.dm +++ b/code/__DEFINES/layers.dm @@ -180,9 +180,9 @@ //#define OBJ_LAYER 3 //For easy recordkeeping; this is a byond define #define CLOSED_DOOR_LAYER 3.1 #define CLOSED_FIREDOOR_LAYER 3.11 +#define SHUTTER_LAYER 3.12 // HERE BE DRAGONS +#define CLOSED_BLASTDOOR_LAYER 3.13 // ABOVE DOORS #define ABOVE_OBJ_LAYER 3.2 -#define CLOSED_BLASTDOOR_LAYER 3.3 // ABOVE WINDOWS AND DOORS -#define SHUTTER_LAYER 3.3 // HERE BE DRAGONS #define ABOVE_WINDOW_LAYER 3.3 #define SIGN_LAYER 3.4 #define CORGI_ASS_PIN_LAYER 3.41 diff --git a/code/__DEFINES/mobs.dm b/code/__DEFINES/mobs.dm index 5817688c2ae3..e7f7f15cc4e2 100644 --- a/code/__DEFINES/mobs.dm +++ b/code/__DEFINES/mobs.dm @@ -314,6 +314,13 @@ #define REAGENTS_METABOLISM 0.4 //How many units of reagent are consumed per tick, by default. #define REAGENTS_EFFECT_MULTIPLIER (REAGENTS_METABOLISM / 0.4) // By defining the effect multiplier this way, it'll exactly adjust all effects according to how they originally were with the 0.4 metabolism +// Eye protection +#define FLASH_PROTECTION_HYPER_SENSITIVE -2 +#define FLASH_PROTECTION_SENSITIVE -1 +#define FLASH_PROTECTION_NONE 0 +#define FLASH_PROTECTION_FLASH 1 +#define FLASH_PROTECTION_WELDER 2 + // Roundstart trait system #define MAX_QUIRKS 6 //The maximum amount of quirks one character can have at roundstart @@ -392,3 +399,25 @@ /// Possible value of [/atom/movable/buckle_lying]. If set to a different (positive-or-zero) value than this, the buckling thing will force a lying angle on the buckled. #define NO_BUCKLE_LYING -1 + +/// Squashing will not occur if the mob is not lying down (bodyposition is LYING_DOWN) +#define SQUASHED_SHOULD_BE_DOWN (1<<0) +/// If present, outright gibs the squashed mob instead of just dealing damage +#define SQUASHED_SHOULD_BE_GIBBED (1<<1) +/// If squashing always passes if the mob is dead +#define SQUASHED_ALWAYS_IF_DEAD (1<<2) +/// Don't squash our mob if its not located in a turf +#define SQUASHED_DONT_SQUASH_IN_CONTENTS (1<<3) + +// Bitflags for mob dismemberment and gibbing +/// Mobs will drop a brain +#define DROP_BRAIN (1<<0) +/// Mobs will drop organs +#define DROP_ORGANS (1<<1) +/// Mobs will drop bodyparts (arms, legs, etc.) +#define DROP_BODYPARTS (1<<2) +/// Mobs will drop items +#define DROP_ITEMS (1<<3) + +/// Mobs will drop everything +#define DROP_ALL_REMAINS (DROP_BRAIN | DROP_ORGANS | DROP_BODYPARTS | DROP_ITEMS) diff --git a/code/__DEFINES/status_effects.dm b/code/__DEFINES/status_effects.dm index ab49290820fb..359711f46144 100644 --- a/code/__DEFINES/status_effects.dm +++ b/code/__DEFINES/status_effects.dm @@ -116,6 +116,8 @@ #define STATUS_EFFECT_EXPOSED /datum/status_effect/exposed //increases incoming damage +#define STATUS_EFFECT_EXPOSED_HARPOONED /datum/status_effect/exposed/harpooned //increases incoming damage when hit by a gasharpoon + #define STATUS_EFFECT_TAMING /datum/status_effect/taming //tames the target after enough tame stacks #define STATUS_EFFECT_NECROPOLIS_CURSE /datum/status_effect/necropolis_curse diff --git a/code/__DEFINES/subsystems.dm b/code/__DEFINES/subsystems.dm index e5357fbe10b0..696563feadb6 100644 --- a/code/__DEFINES/subsystems.dm +++ b/code/__DEFINES/subsystems.dm @@ -173,7 +173,8 @@ #define INIT_ORDER_PATH -50 #define INIT_ORDER_DISCORD -60 #define INIT_ORDER_EXPLOSIONS -69 -#define INIT_ORDER_STATPANELS -98 +#define INIT_ORDER_STATPANELS -97 +#define INIT_ORDER_INIT_PROFILER -98 //Near the end, logs the costs of initialize #define INIT_ORDER_DEMO -99 // To avoid a bunch of changes related to initialization being written, do this last #define INIT_ORDER_CHAT -100 //Should be last to ensure chat remains smooth during init. diff --git a/code/__HELPERS/animations.dm b/code/__HELPERS/animations.dm index cae8d3a8f52b..e80bfe319c0c 100644 --- a/code/__HELPERS/animations.dm +++ b/code/__HELPERS/animations.dm @@ -65,3 +65,53 @@ animate(transform = transforms[2], time = 0.1) animate(transform = transforms[3], time = 0.2) animate(transform = transforms[4], time = 0.3) + + +/** + * Proc called when you want the atom to spin around the center of its icon (or where it would be if its transform var is translated) + * By default, it makes the atom spin forever and ever at a speed of 60 rpm. + * + * Arguments: + * * speed: how much it takes for the atom to complete one 360° rotation + * * loops: how many times do we want the atom to rotate + * * clockwise: whether the atom ought to spin clockwise or counter-clockwise + * * segments: in how many animate calls the rotation is split. Probably unnecessary, but you shouldn't set it lower than 3 anyway. + * * parallel: whether the animation calls have the ANIMATION_PARALLEL flag, necessary for it to run alongside concurrent animations. + */ +/atom/proc/SpinAnimation(speed = 1 SECONDS, loops = -1, clockwise = TRUE, segments = 3, parallel = TRUE) + if(!segments) + return + var/segment = 360/segments + if(!clockwise) + segment = -segment + SEND_SIGNAL(src, COMSIG_ATOM_SPIN_ANIMATION, speed, loops, segments, segment) + do_spin_animation(speed, loops, segments, segment, parallel) + +/atom/proc/DabAnimation(speed = 1, loops = 1, direction = 1 , hold_seconds = 0 , angle = 1 , stay = FALSE) // Hopek 2019 + // By making this in atom/proc everything in the game can potentially dab. You have been warned. + if(hold_seconds > 9999) // if you need to hold a dab for more than 2 hours intentionally let me know. + return + if(hold_seconds > 0) + hold_seconds = hold_seconds * 10 // Converts seconds to deciseconds + if(angle == 1) //if angle is 1: random angle. Else take angle + angle = rand(25,50) + if(direction == 1) // direciton:: 1 for random pick, 2 for clockwise , 3 for anti-clockwise + direction = pick(2,3) + if(direction == 3) // if 3 then counter clockwise + angle = angle * -1 + if(speed == 1) // if speed is 1 choose random speed from list + speed = rand(3,5) + + // dab matrix here + var/matrix/DAB_COMMENCE = matrix(transform) + var/matrix/DAB_RETURN = matrix(transform) + DAB_COMMENCE.Turn(angle) // dab angle to matrix + + // Dab animation + animate(src, transform = DAB_COMMENCE, time = speed, loops ) // dab to hold angle + if(hold_seconds > 0) + sleep(hold_seconds) // time to hold the dab before going back + if(!stay) // if stay param is true dab doesn't return + animate(transform = DAB_RETURN, time = speed * 1.5, loops ) // reverse dab to starting position , slower + //doesn't have an object argument because this is "Stacking" with the animate call above + //3 billion% intentional diff --git a/code/__HELPERS/colors.dm b/code/__HELPERS/colors.dm index 134091a88f88..6c6f8064d9a2 100644 --- a/code/__HELPERS/colors.dm +++ b/code/__HELPERS/colors.dm @@ -40,6 +40,10 @@ /// But paired down and modified to work for our color range /// Accepts the color cutoffs as two 3 length list(0-100,...) arguments /proc/blend_cutoff_colors(list/first_color, list/second_color) + // These runtimes usually mean that either the eye or the glasses have an incorrect color_cutoffs + ASSERT(first_color?.len == 3, "First color must be a 3 length list, received [json_encode(first_color)]") + ASSERT(second_color?.len == 3, "Second color must be a 3 length list, received [json_encode(second_color)]") + var/list/output = new /list(3) // Invert the colors, multiply to "darken" (actually lights), then uninvert to get back to what we want diff --git a/code/__HELPERS/matrices.dm b/code/__HELPERS/matrices.dm index 636e4735bc02..2fca8792abe5 100644 --- a/code/__HELPERS/matrices.dm +++ b/code/__HELPERS/matrices.dm @@ -2,60 +2,6 @@ . = new_angle - old_angle Turn(.) //BYOND handles cases such as -270, 360, 540 etc. DOES NOT HANDLE 180 TURNS WELL, THEY TWEEN AND LOOK LIKE SHIT -/atom/proc/SpinAnimation(speed = 1 SECONDS, loops = -1, clockwise = 1, segments = 3, parallel = TRUE) - if(!segments) - return - var/segment = 360/segments - if(!clockwise) - segment = -segment - var/list/matrices = list() - for(var/i in 1 to segments-1) - var/matrix/M = matrix(transform) - M.Turn(segment*i) - matrices += M - var/matrix/last = matrix(transform) - matrices += last - - speed /= segments - - if(parallel) - animate(src, transform = matrices[1], time = speed, loops , flags = ANIMATION_PARALLEL) - else - animate(src, transform = matrices[1], time = speed, loops) - for(var/i in 2 to segments) //2 because 1 is covered above - animate(transform = matrices[i], time = speed) - //doesn't have an object argument because this is "Stacking" with the animate call above - //3 billion% intentional - -/atom/proc/DabAnimation(speed = 1, loops = 1, direction = 1 , hold_seconds = 0 , angle = 1 , stay = FALSE) // Hopek 2019 - // By making this in atom/proc everything in the game can potentially dab. You have been warned. - if(hold_seconds > 9999) // if you need to hold a dab for more than 2 hours intentionally let me know. - return - if(hold_seconds > 0) - hold_seconds = hold_seconds * 10 // Converts seconds to deciseconds - if(angle == 1) //if angle is 1: random angle. Else take angle - angle = rand(25,50) - if(direction == 1) // direciton:: 1 for random pick, 2 for clockwise , 3 for anti-clockwise - direction = pick(2,3) - if(direction == 3) // if 3 then counter clockwise - angle = angle * -1 - if(speed == 1) // if speed is 1 choose random speed from list - speed = rand(3,5) - - // dab matrix here - var/matrix/DAB_COMMENCE = matrix(transform) - var/matrix/DAB_RETURN = matrix(transform) - DAB_COMMENCE.Turn(angle) // dab angle to matrix - - // Dab animation - animate(src, transform = DAB_COMMENCE, time = speed, loops ) // dab to hold angle - if(hold_seconds > 0) - sleep(hold_seconds) // time to hold the dab before going back - if(!stay) // if stay param is true dab doesn't return - animate(transform = DAB_RETURN, time = speed * 1.5, loops ) // reverse dab to starting position , slower - //doesn't have an object argument because this is "Stacking" with the animate call above - //3 billion% intentional - //Dumps the matrix data in format a-f /matrix/proc/tolist() . = list() diff --git a/code/controllers/master.dm b/code/controllers/master.dm index 93b36ddf2b4d..2ad8972edec6 100644 --- a/code/controllers/master.dm +++ b/code/controllers/master.dm @@ -474,8 +474,8 @@ GLOBAL_REAL(Master, /datum/controller/master) = new var/newdrift = ((REALTIMEOFDAY - init_timeofday) - (world.time - init_time)) / world.tick_lag tickdrift = max(0, MC_AVERAGE_FAST(tickdrift, newdrift)) var/starting_tick_usage = TICK_USAGE - - if(newdrift - olddrift >= CONFIG_GET(number/drift_dump_threshold)) + //Yog: profile dumping was throttling lower performance computers, so we're going to have it disabled by default but you can enable it via config flags + if(newdrift - olddrift >= CONFIG_GET(number/drift_dump_threshold) && CONFIG_GET(flag/auto_profile)) AttemptProfileDump(CONFIG_GET(number/drift_profile_delay)) olddrift = newdrift diff --git a/code/controllers/subsystem/atoms.dm b/code/controllers/subsystem/atoms.dm index f2ce0c3522f2..8a3ca56432fa 100644 --- a/code/controllers/subsystem/atoms.dm +++ b/code/controllers/subsystem/atoms.dm @@ -1,4 +1,3 @@ -#define SUBSYSTEM_INIT_SOURCE "subsystem init" SUBSYSTEM_DEF(atoms) name = "Atoms" init_order = INIT_ORDER_ATOMS @@ -43,11 +42,16 @@ SUBSYSTEM_DEF(atoms) if(initialized == INITIALIZATION_INSSATOMS) return - set_tracked_initalized(INITIALIZATION_INNEW_MAPLOAD, SUBSYSTEM_INIT_SOURCE) + // Generate a unique mapload source for this run of InitializeAtoms + var/static/uid = 0 + uid = (uid + 1) % (SHORT_REAL_LIMIT - 1) + var/source = "subsystem init [uid]" + set_tracked_initalized(INITIALIZATION_INNEW_MAPLOAD, source) // This may look a bit odd, but if the actual atom creation runtimes for some reason, we absolutely need to set initialized BACK - CreateAtoms(atoms, atoms_to_return) - clear_tracked_initalize(SUBSYSTEM_INIT_SOURCE) + CreateAtoms(atoms, atoms_to_return, source) + clear_tracked_initalize(source) + SSicon_smooth.free_deferred(source) if(late_loaders.len) for(var/I in 1 to late_loaders.len) @@ -68,12 +72,13 @@ SUBSYSTEM_DEF(atoms) testing("[queued_deletions.len] atoms were queued for deletion.") queued_deletions.Cut() + // #ifdef PROFILE_MAPLOAD_INIT_ATOM // rustg_file_write(json_encode(mapload_init_times), "[GLOB.log_directory]/init_times.json") // #endif /// Actually creates the list of atoms. Exists soley so a runtime in the creation logic doesn't cause initalized to totally break -/datum/controller/subsystem/atoms/proc/CreateAtoms(list/atoms, list/atoms_to_return = null) +/datum/controller/subsystem/atoms/proc/CreateAtoms(list/atoms, list/atoms_to_return = null, mapload_source = null) if (atoms_to_return) LAZYINITLIST(created_atoms) @@ -91,7 +96,12 @@ SUBSYSTEM_DEF(atoms) for(var/I in 1 to atoms.len) var/atom/A = atoms[I] if(!(A.flags_1 & INITIALIZED_1)) - CHECK_TICK + // Unrolled CHECK_TICK setup to let us enable/disable mapload based off source + if(TICK_CHECK) + clear_tracked_initalize(mapload_source) + stoplag() + if(mapload_source) + set_tracked_initalized(INITIALIZATION_INNEW_MAPLOAD, mapload_source) PROFILE_INIT_ATOM_BEGIN() InitAtom(A, TRUE, mapload_arg) PROFILE_INIT_ATOM_END(A) @@ -108,7 +118,11 @@ SUBSYSTEM_DEF(atoms) #ifdef TESTING ++count #endif - CHECK_TICK + if(TICK_CHECK) + clear_tracked_initalize(mapload_source) + stoplag() + if(mapload_source) + set_tracked_initalized(INITIALIZATION_INNEW_MAPLOAD, mapload_source) testing("Initialized [count] atoms") @@ -118,12 +132,18 @@ SUBSYSTEM_DEF(atoms) /datum/controller/subsystem/atoms/proc/map_loader_stop(source) clear_tracked_initalize(source) +/// Returns the source currently modifying SSatom's init behavior +/datum/controller/subsystem/atoms/proc/get_initialized_source() + var/state_length = length(initialized_state) + if(!state_length) + return null + return initialized_state[state_length][1] + /// Use this to set initialized to prevent error states where the old initialized is overriden, and we end up losing all context /// Accepts a state and a source, the most recent state is used, sources exist to prevent overriding old values accidentially /datum/controller/subsystem/atoms/proc/set_tracked_initalized(state, source) if(!length(initialized_state)) base_initialized = initialized - initialized_state += list(list(source, state)) initialized = state @@ -141,9 +161,9 @@ SUBSYSTEM_DEF(atoms) return initialized = initialized_state[length(initialized_state)][2] -/// Returns TRUE if anything is currently being initialized or needing to be deleted +/// Returns TRUE if anything is currently being initialized /datum/controller/subsystem/atoms/proc/initializing_something() - return length(initialized_state) + return length(initialized_state) > 1 /datum/controller/subsystem/atoms/Recover() initialized = SSatoms.initialized @@ -201,5 +221,3 @@ SUBSYSTEM_DEF(atoms) var/initlog = InitLog() if(initlog) text2file(initlog, "[GLOB.log_directory]/initialize.log") - -#undef SUBSYSTEM_INIT_SOURCE diff --git a/code/controllers/subsystem/icon_smooth.dm b/code/controllers/subsystem/icon_smooth.dm index a0a33f0e17ac..9e5e9ffa99de 100644 --- a/code/controllers/subsystem/icon_smooth.dm +++ b/code/controllers/subsystem/icon_smooth.dm @@ -9,8 +9,7 @@ SUBSYSTEM_DEF(icon_smooth) var/list/blueprint_queue = list() var/list/smooth_queue = list() var/list/deferred = list() - - var/map_loading = FALSE + var/list/deferred_by_source = list() /datum/controller/subsystem/icon_smooth/fire() // We do not want to smooth icons of atoms whose neighbors are not initialized yet, @@ -63,16 +62,30 @@ SUBSYSTEM_DEF(icon_smooth) return SS_INIT_SUCCESS +/// Releases a pool of delayed smooth attempts from a particular source +/datum/controller/subsystem/icon_smooth/proc/free_deferred(source_to_free) + smooth_queue += deferred_by_source[source_to_free] + deferred_by_source -= source_to_free + if(!can_fire) + can_fire = TRUE /datum/controller/subsystem/icon_smooth/proc/add_to_queue(atom/thing) if(thing.smoothing_flags & SMOOTH_QUEUED) return thing.smoothing_flags |= SMOOTH_QUEUED + // If we're currently locked into mapload BY something + // Then put us in a deferred list that we release when this mapload run is finished + if(initialized && length(SSatoms.initialized_state) && SSatoms.initialized == INITIALIZATION_INNEW_MAPLOAD) + var/source = SSatoms.get_initialized_source() + LAZYADD(deferred_by_source[source], thing) + return smooth_queue += thing if(!can_fire) can_fire = TRUE /datum/controller/subsystem/icon_smooth/proc/remove_from_queues(atom/thing) + // Lack of removal from deferred_by_source is safe because the lack of SMOOTH_QUEUED will just free it anyway + // Hopefully this'll never cause a harddel (dies) thing.smoothing_flags &= ~SMOOTH_QUEUED smooth_queue -= thing if(blueprint_queue) diff --git a/code/controllers/subsystem/init_profiler.dm b/code/controllers/subsystem/init_profiler.dm new file mode 100644 index 000000000000..063898b6a098 --- /dev/null +++ b/code/controllers/subsystem/init_profiler.dm @@ -0,0 +1,28 @@ +#define INIT_PROFILE_NAME "init_profiler.json" + +///Subsystem exists so we can separately log init time costs from the costs of general operation +///Hopefully this makes sorting out what causes problems when easier +SUBSYSTEM_DEF(init_profiler) + name = "Init Profiler" + init_order = INIT_ORDER_INIT_PROFILER + init_stage = INITSTAGE_MAX + flags = SS_NO_FIRE + +/datum/controller/subsystem/init_profiler/Initialize() + if(CONFIG_GET(flag/auto_profile)) + write_init_profile() + return SS_INIT_SUCCESS + +/datum/controller/subsystem/init_profiler/proc/write_init_profile() + var/current_profile_data = world.Profile(PROFILE_REFRESH, format = "json") + CHECK_TICK + + if(!length(current_profile_data)) //Would be nice to have explicit proc to check this + stack_trace("Warning, profiling stopped manually before dump.") + var/prof_file = file("[GLOB.log_directory]/[INIT_PROFILE_NAME]") + if(fexists(prof_file)) + fdel(prof_file) + WRITE_FILE(prof_file, current_profile_data) + world.Profile(PROFILE_CLEAR) //Now that we're written this data out, dump it. We don't want it getting mixed up with our current round data + +#undef INIT_PROFILE_NAME diff --git a/code/controllers/subsystem/job.dm b/code/controllers/subsystem/job.dm index 8709e70f96eb..4fbc20fc21ae 100644 --- a/code/controllers/subsystem/job.dm +++ b/code/controllers/subsystem/job.dm @@ -617,9 +617,9 @@ SUBSYSTEM_DEF(job) /datum/controller/subsystem/job/proc/irish_override() var/datum/map_template/template = SSmapping.station_room_templates["Bar Irish"] - for(var/obj/effect/landmark/stationroom/box/bar/B in GLOB.bar_landmarks) + for(var/obj/effect/landmark/stationroom/box/bar/B in GLOB.landmarks_list) template.load(B.loc, centered = FALSE) - + qdel(B) /datum/controller/subsystem/job/proc/random_chapel_init() try @@ -664,9 +664,9 @@ SUBSYSTEM_DEF(job) log_game("WARNING: CHAPEL RECOVERY FAILED! THERE WILL BE NO CHAPEL FOR THIS ROUND!") return - for(var/obj/effect/landmark/stationroom/box/chapel/B in GLOB.chapel_landmarks) + for(var/obj/effect/landmark/stationroom/box/chapel/B in GLOB.landmarks_list) template.load(B.loc, centered = FALSE) - + qdel(B) catch(var/exception/e) message_admins("RUNTIME IN RANDOM_CHAPEL_INIT") spawn_chapel() @@ -681,9 +681,9 @@ SUBSYSTEM_DEF(job) if(isnull(template)) message_admins("UNABLE TO SPAWN CHAPEL") - for(var/obj/effect/landmark/stationroom/box/chapel/B in GLOB.chapel_landmarks) + for(var/obj/effect/landmark/stationroom/box/chapel/B in GLOB.landmarks_list) template.load(B.loc, centered = FALSE) - + qdel(B) /datum/controller/subsystem/job/proc/random_clerk_init() try @@ -728,9 +728,9 @@ SUBSYSTEM_DEF(job) log_game("WARNING: CLERK RECOVERY FAILED! THERE WILL BE NO CLERK SHOP FOR THIS ROUND!") return - for(var/obj/effect/landmark/stationroom/box/clerk/B in GLOB.clerk_office_landmarks) + for(var/obj/effect/landmark/stationroom/box/clerk/B in GLOB.landmarks_list) template.load(B.loc, centered = FALSE) - + qdel(B) catch(var/exception/e) message_admins("RUNTIME IN RANDOM_CLERK_INIT") spawn_clerk() @@ -745,8 +745,9 @@ SUBSYSTEM_DEF(job) if(isnull(template)) message_admins("UNABLE TO SPAWN CLERK") - for(var/obj/effect/landmark/stationroom/box/clerk/B in GLOB.clerk_office_landmarks) + for(var/obj/effect/landmark/stationroom/box/clerk/B in GLOB.landmarks_list) template.load(B.loc, centered = FALSE) + qdel(B) /datum/controller/subsystem/job/proc/handle_auto_deadmin_roles(client/C, rank) if(!C?.holder) diff --git a/code/controllers/subsystem/shuttle.dm b/code/controllers/subsystem/shuttle.dm index 667491c24048..156b929bae0b 100644 --- a/code/controllers/subsystem/shuttle.dm +++ b/code/controllers/subsystem/shuttle.dm @@ -1052,7 +1052,7 @@ SUBSYSTEM_DEF(shuttle) else if(S) . = TRUE // If successful, returns the mobile docking port - var/obj/docking_port/mobile/mdp = action_load(S) + var/obj/docking_port/mobile/mdp = action_load(S, replace = TRUE) if(mdp) user.forceMove(get_turf(mdp)) message_admins("[key_name_admin(usr)] loaded [mdp] with the shuttle manipulator.") diff --git a/code/controllers/subsystem/timer.dm b/code/controllers/subsystem/timer.dm index 95d590a0fded..d615bc28798b 100644 --- a/code/controllers/subsystem/timer.dm +++ b/code/controllers/subsystem/timer.dm @@ -4,8 +4,6 @@ #define BUCKET_POS(timer) (((ROUND_UP((timer.timeToRun - timer.timer_subsystem.head_offset) / world.tick_lag)+1) % BUCKET_LEN) || BUCKET_LEN) /// Gets the maximum time at which timers will be invoked from buckets, used for deferring to secondary queue #define TIMER_MAX(timer_ss) (timer_ss.head_offset + TICKS2DS(BUCKET_LEN + timer_ss.practical_offset - 1)) -/// Max float with integer precision -#define TIMER_ID_MAX (2**24) /** * # Timer Subsystem @@ -740,4 +738,3 @@ SUBSYSTEM_DEF(timer) #undef BUCKET_LEN #undef BUCKET_POS #undef TIMER_MAX -#undef TIMER_ID_MAX diff --git a/code/datums/components/bloodysoles.dm b/code/datums/components/bloodysoles.dm index 03afc96182dc..d05043312d7f 100644 --- a/code/datums/components/bloodysoles.dm +++ b/code/datums/components/bloodysoles.dm @@ -234,7 +234,7 @@ Like its parent but can be applied to carbon mobs instead of clothing items . = list() if(ishuman(wielder))// Monkeys get no bloody feet :( if(HAS_BLOOD_DNA(wielder)) - bloody_feet.color = bloody_feet.color = get_blood_dna_color(wielder.return_blood_DNA()) + bloody_feet.color = get_blood_dna_color(wielder.return_blood_DNA()) . += bloody_feet if(bloody_shoes[BLOOD_STATE_HUMAN] > 0 && !is_obscured()) wielder.remove_overlay(SHOES_LAYER) diff --git a/code/datums/components/squeak.dm b/code/datums/components/squeak.dm index 03f1e4f2d452..b996ab73d182 100644 --- a/code/datums/components/squeak.dm +++ b/code/datums/components/squeak.dm @@ -13,13 +13,18 @@ var/last_use = 0 var/use_delay = 20 + ///what we set connect_loc to if parent is an item + var/static/list/item_connections = list( + COMSIG_ATOM_ENTERED = PROC_REF(play_squeak_crossed), + ) + /datum/component/squeak/Initialize(custom_sounds, volume_override, chance_override, step_delay_override, use_delay_override) if(!isatom(parent)) return COMPONENT_INCOMPATIBLE RegisterSignals(parent, list(COMSIG_ATOM_ENTERED, COMSIG_ATOM_BLOB_ACT, COMSIG_ATOM_HULK_ATTACK, COMSIG_PARENT_ATTACKBY), PROC_REF(play_squeak)) if(ismovable(parent)) RegisterSignals(parent, list(COMSIG_MOVABLE_BUMP, COMSIG_MOVABLE_IMPACT, COMSIG_PROJECTILE_BEFORE_FIRE), PROC_REF(play_squeak)) - RegisterSignal(parent, COMSIG_MOVABLE_CROSSED, PROC_REF(play_squeak_crossed)) + AddComponent(/datum/component/connect_loc_behalf, parent, item_connections) RegisterSignal(parent, COMSIG_MOVABLE_DISPOSING, PROC_REF(disposing_react)) if(isitem(parent)) RegisterSignals(parent, list(COMSIG_ITEM_ATTACK, COMSIG_ITEM_ATTACK_OBJ, COMSIG_ITEM_HIT_REACT), PROC_REF(play_squeak)) @@ -41,6 +46,10 @@ if(isnum(use_delay_override)) use_delay = use_delay_override +/datum/component/squeak/UnregisterFromParent() + . = ..() + qdel(GetComponent(/datum/component/connect_loc_behalf)) + /datum/component/squeak/proc/play_squeak() if(prob(squeak_chance)) if(!override_squeak_sounds) diff --git a/code/datums/components/squishable.dm b/code/datums/components/squishable.dm new file mode 100644 index 000000000000..b3aba6d076ce --- /dev/null +++ b/code/datums/components/squishable.dm @@ -0,0 +1,81 @@ +///This component allows something to be when crossed, for example for cockroaches. +/datum/component/squashable + ///Chance on crossed to be squashed + var/squash_chance = 50 + ///How much brute is applied when mob is squashed + var/squash_damage = 1 + ///Squash flags, for extra checks etcetera. + var/squash_flags = NONE + ///Special callback to call on squash instead, for things like hauberoach + var/datum/callback/on_squash_callback + ///signal list given to connect_loc + var/static/list/loc_connections = list( + COMSIG_ATOM_ENTERED = PROC_REF(on_entered), + ) + + +/datum/component/squashable/Initialize(squash_chance, squash_damage, squash_flags, squash_callback) + . = ..() + if(!isliving(parent)) + return COMPONENT_INCOMPATIBLE + if(squash_chance) + src.squash_chance = squash_chance + if(squash_damage) + src.squash_damage = squash_damage + if(squash_flags) + src.squash_flags = squash_flags + if(!src.on_squash_callback && squash_callback) + on_squash_callback = CALLBACK(parent, squash_callback) + + AddComponent(/datum/component/connect_loc_behalf, parent, loc_connections) + +/datum/component/squashable/Destroy(force) + on_squash_callback = null + return ..() + +///Handles the squashing of the mob +/datum/component/squashable/proc/on_entered(turf/source_turf, atom/movable/crossing_movable) + // SIGNAL_HANDLER -- dont uncomment this + + if(parent == crossing_movable) + return + + var/mob/living/parent_as_living = parent + if((squash_flags & SQUASHED_DONT_SQUASH_IN_CONTENTS) && !isturf(parent_as_living.loc)) + return + + if((squash_flags & SQUASHED_SHOULD_BE_DOWN) && parent_as_living.body_position != LYING_DOWN) + return + + var/should_squash = ((squash_flags & SQUASHED_ALWAYS_IF_DEAD) && parent_as_living.stat == DEAD) || prob(squash_chance) + + if(should_squash && on_squash_callback) + if(on_squash_callback.Invoke(parent_as_living, crossing_movable)) + return //Everything worked, we're done! + if(isliving(crossing_movable)) + var/mob/living/crossing_mob = crossing_movable + if(crossing_mob.mob_size > MOB_SIZE_SMALL && !(crossing_mob.movement_type & MOVETYPES_NOT_TOUCHING_GROUND)) + if(HAS_TRAIT(crossing_mob, TRAIT_PACIFISM)) + crossing_mob.visible_message(span_notice("[crossing_mob] carefully steps over [parent_as_living]."), span_notice("You carefully step over [parent_as_living] to avoid hurting it.")) + return + if(should_squash) + crossing_mob.visible_message(span_notice("[crossing_mob] squashed [parent_as_living]."), span_notice("You squashed [parent_as_living].")) + Squish(parent_as_living) + else + parent_as_living.visible_message(span_notice("[parent_as_living] avoids getting crushed.")) + else if(isstructure(crossing_movable)) + if(should_squash) + crossing_movable.visible_message(span_notice("[parent_as_living] is crushed under [crossing_movable].")) + Squish(parent_as_living) + else + parent_as_living.visible_message(span_notice("[parent_as_living] avoids getting crushed.")) + +/datum/component/squashable/proc/Squish(mob/living/target) + if(squash_flags & SQUASHED_SHOULD_BE_GIBBED) + target.gib(DROP_ALL_REMAINS) + else + target.adjustBruteLoss(squash_damage) + +/datum/component/squashable/UnregisterFromParent() + . = ..() + qdel(GetComponent(/datum/component/connect_loc_behalf)) diff --git a/code/datums/elements/decals/blood.dm b/code/datums/elements/decals/blood.dm index cdaec2c089da..f496f76adf1e 100644 --- a/code/datums/elements/decals/blood.dm +++ b/code/datums/elements/decals/blood.dm @@ -13,10 +13,6 @@ /datum/element/decal/blood/generate_appearance(_icon, _icon_state, _dir, _plane, _layer, _color, _alpha, _smoothing, source) var/obj/item/I = source - if(!_icon) - _icon = 'icons/effects/blood.dmi' - if(!_icon_state) - _icon_state = "itemblood" if(!_color) _color = COLOR_BLOOD var/icon = I.icon @@ -25,19 +21,14 @@ // It's something which takes on the look of other items, probably icon = I.icon icon_state = I.icon_state - var/static/list/blood_splatter_appearances = list() - //try to find a pre-processed blood-splatter. otherwise, make a new one - var/index = "[REF(icon)]-[icon_state]" - pic = blood_splatter_appearances[index] - - if(!pic) - var/icon/blood_splatter_icon = icon(I.icon, I.icon_state, , 1) //icon of the item that will become splattered - var/icon/blood_icon = icon(_icon, _icon_state) //icon of the blood that we apply - blood_icon.Scale(blood_splatter_icon.Width(), blood_splatter_icon.Height()) - blood_splatter_icon.Blend(_color, ICON_ADD) //fills the icon_state with white (except where it's transparent) - blood_splatter_icon.Blend(blood_icon, ICON_MULTIPLY) //adds blood and the remaining white areas become transparant - pic = mutable_appearance(blood_splatter_icon, I.icon_state) - blood_splatter_appearances[index] = pic + var/icon/icon_for_size = icon(icon, icon_state) + var/scale_factor_x = icon_for_size.Width()/world.icon_size + var/scale_factor_y = icon_for_size.Height()/world.icon_size + var/mutable_appearance/blood_splatter = mutable_appearance('icons/effects/blood.dmi', "itemblood", appearance_flags = RESET_COLOR) //MA of the blood that we apply + blood_splatter.transform = blood_splatter.transform.Scale(scale_factor_x, scale_factor_y) + blood_splatter.blend_mode = BLEND_INSET_OVERLAY + blood_splatter.color = _color + pic = blood_splatter return TRUE /datum/element/decal/blood/proc/get_examine_name(datum/source, mob/user, list/override) diff --git a/code/datums/martial/reverbpalm.dm b/code/datums/martial/reverbpalm.dm index d92317aa06bf..36234dda2be8 100644 --- a/code/datums/martial/reverbpalm.dm +++ b/code/datums/martial/reverbpalm.dm @@ -48,9 +48,7 @@ //animation procs //knocking them down -/datum/martial_art/reverberating_palm/proc/footsies(mob/living/target, var/suplex = FALSE) - if(suplex) - animate(target, transform = matrix(180, MATRIX_ROTATE), time = 0 SECONDS, loop = 0) +/datum/martial_art/reverberating_palm/proc/footsies(mob/living/target) if(target.mobility_flags & MOBILITY_STAND) animate(target, transform = matrix(90, MATRIX_ROTATE), time = 0 SECONDS, loop = 0) return @@ -103,14 +101,14 @@ return COOLDOWN_START(src, next_palm, COOLDOWN_RPALM) var/obj/item/melee/overcharged_emitter/B = new() - user.visible_message(span_userdanger("[user]'s left arm begins crackling loudly!")) + user.visible_message(span_userdanger("[user]'s right arm begins crackling loudly!")) playsound(user,'sound/effects/beepskyspinsabre.ogg', 60, 1) if(do_after(user, 2 SECONDS, user, timed_action_flags = IGNORE_USER_LOC_CHANGE)) - if(!user.put_in_l_hand(B)) - to_chat(user, span_warning("You can't do this with your left hand full!")) + if(!user.put_in_r_hand(B)) + to_chat(user, span_warning("You can't do this with your right hand full!")) else user.visible_message(span_danger("[user]'s arm begins shaking violently!")) - if(user.active_hand_index % 2 == 0) + if(user.active_hand_index % 2 == 1) user.swap_hand(0) //do cooldown @@ -137,7 +135,7 @@ to_chat(user, span_warning("You can't do that yet!")) return COOLDOWN_START(src, next_suplex, COOLDOWN_SUPLEX) - footsies(target, TRUE) + footsies(target) var/turf/Q = get_step(get_turf(user), turn(user.dir,180)) user.visible_message(span_warning("[user] outstretches [user.p_their()] arm and goes for a grab!")) wakeup(target) @@ -150,7 +148,6 @@ if(target.stat == DEAD) target.visible_message(span_warning("[target] crashes and explodes!")) target.gib() - wakeup(target) to_chat(user, span_warning("[user] suplexes [target] against [Q]!")) to_chat(target, span_userdanger("[user] crushes you against [Q]!")) playsound(target, 'sound/effects/meteorimpact.ogg', 60, 1) diff --git a/code/datums/materials/_material.dm b/code/datums/materials/_material.dm index 906c17af66f9..29e700df8eb5 100644 --- a/code/datums/materials/_material.dm +++ b/code/datums/materials/_material.dm @@ -7,7 +7,7 @@ Simple datum which is instanced once per type and is used for every object of sa /datum/material var/name = "material" - var/desc = "its..stuff." + var/desc = "It's...stuff." // I'm stuff :stuff: ///Var that's mostly used by science machines to identify specific materials, should most likely be phased out at some point var/id = "mat" ///Base color of the material, is used for greyscale. Item isn't changed in color if this is null. diff --git a/code/datums/materials/basemats.dm b/code/datums/materials/basemats.dm index 3012fc6d533a..1cc3eb6763f8 100644 --- a/code/datums/materials/basemats.dm +++ b/code/datums/materials/basemats.dm @@ -2,7 +2,7 @@ /datum/material/iron name = "iron" id = "iron" - desc = "Common iron ore often found in sedimentary and igneous layers of the crust." + desc = "A common iron ore often found in sedimentary and igneous layers of the crust." color = "#878687" categories = list(MAT_CATEGORY_ORE = TRUE, MAT_CATEGORY_RIGID = TRUE) sheet_type = /obj/item/stack/sheet/metal @@ -24,7 +24,7 @@ /datum/material/silver name = "silver" id = "silver" - desc = "Silver" + desc = "Silver." color = "#bdbebf" categories = list(MAT_CATEGORY_ORE = TRUE, MAT_CATEGORY_RIGID = TRUE) sheet_type = /obj/item/stack/sheet/mineral/silver @@ -34,7 +34,7 @@ /datum/material/gold name = "gold" id = "gold" - desc = "Gold" + desc = "Gold. You're rich." color = "#f0972b" strength_modifier = 1.2 categories = list(MAT_CATEGORY_ORE = TRUE, MAT_CATEGORY_RIGID = TRUE) @@ -45,7 +45,7 @@ /datum/material/diamond name = "diamond" id = "diamond" - desc = "Highly pressurized carbon" + desc = "Highly pressurized carbon." color = "#22c2d4" categories = list(MAT_CATEGORY_ORE = TRUE, MAT_CATEGORY_RIGID = TRUE) sheet_type = /obj/item/stack/sheet/mineral/diamond @@ -55,7 +55,7 @@ /datum/material/uranium name = "uranium" id = "uranium" - desc = "Uranium" + desc = "Uranium, known for its radioactive properties." color = "#1fb83b" categories = list(MAT_CATEGORY_ORE = TRUE, MAT_CATEGORY_RIGID = TRUE) sheet_type = /obj/item/stack/sheet/mineral/uranium @@ -95,7 +95,7 @@ /datum/material/bluespace name = "bluespace crystal" id = "bluespace_crystal" - desc = "Crystals with bluespace properties" + desc = "Rare crystals with bluespace properties." color = "#506bc7" categories = list(MAT_CATEGORY_ORE = TRUE) sheet_type = /obj/item/stack/sheet/bluespace_crystal @@ -104,7 +104,7 @@ /datum/material/bananium name = "bananium" id = "bananium" - desc = "Material with hilarious properties" + desc = "A very rare material with hilarious properties." color = "#fff263" categories = list(MAT_CATEGORY_ORE = TRUE, MAT_CATEGORY_RIGID = TRUE) sheet_type = /obj/item/stack/sheet/mineral/bananium @@ -125,7 +125,7 @@ /datum/material/titanium name = "titanium" id = "titanium" - desc = "Titanium" + desc = "Titanium." color = "#b3c0c7" strength_modifier = 1.3 categories = list(MAT_CATEGORY_ORE = TRUE, MAT_CATEGORY_RIGID = TRUE) @@ -135,7 +135,7 @@ /datum/material/plastic name = "plastic" id = "plastic" - desc = "plastic" + desc = "Plastic." color = "#caccd9" strength_modifier = 0.85 sheet_type = /obj/item/stack/sheet/plastic @@ -151,7 +151,7 @@ //formed when freon react with o2, emits a lot of plasma when heated /datum/material/hot_ice name = "hot ice" - desc = "A weird kind of ice, feels warm to the touch" + desc = "A weird kind of ice, feels warm to the touch." color = "#88cdf1" alpha = 150 categories = list(MAT_CATEGORY_RIGID = TRUE) @@ -176,7 +176,7 @@ /datum/material/metalhydrogen name = "Metal Hydrogen" - desc = "Solid metallic hydrogen. Some say it should be impossible" + desc = "Solid metallic hydrogen. Some say it should be impossible." color = "#f2d5d7" alpha = 240 categories = list(MAT_CATEGORY_RIGID = TRUE) @@ -185,7 +185,7 @@ /datum/material/zaukerite name = "zaukerite" - desc = "A light absorbing crystal" + desc = "A light-absorbing crystal." color = COLOR_ALMOST_BLACK categories = list(MAT_CATEGORY_RIGID = TRUE, MAT_CATEGORY_ITEM_MATERIAL=TRUE) sheet_type = /obj/item/stack/sheet/mineral/zaukerite @@ -201,7 +201,7 @@ /datum/material/dilithium name = "dilithium crystal" id = "dilithium_crystal" - desc = "Crystals with dilithium properties" + desc = "Crystals with dilithium properties." color = "#506bc7" categories = list(MAT_CATEGORY_ORE = TRUE) sheet_type = /obj/item/stack/sheet/dilithium_crystal diff --git a/code/datums/ruins/space.dm b/code/datums/ruins/space.dm index d19b16310078..5c23c96e2fd1 100644 --- a/code/datums/ruins/space.dm +++ b/code/datums/ruins/space.dm @@ -103,7 +103,7 @@ id = "empty-shell" suffix = "emptyshell.dmm" name = "Empty Shell" - description = "Cosy, rural property available for young professional couple. Only twelve parsecs from the nearest hyperspace lane!" + description = "Cosy, rural property available for young professional couple. Only twelve parsecs from the nearest gigabeacon!" /datum/map_template/ruin/space/gas_the_lizards id = "gas-the-lizards" diff --git a/code/datums/status_effects/debuffs/debuffs.dm b/code/datums/status_effects/debuffs/debuffs.dm index ffeb5067fe8b..6089eb84b98a 100644 --- a/code/datums/status_effects/debuffs/debuffs.dm +++ b/code/datums/status_effects/debuffs/debuffs.dm @@ -1301,6 +1301,45 @@ for(var/i in S.damage_coeff) S.damage_coeff[i] /= power +/datum/status_effect/exposed/harpooned + id = "harpooned" + duration = 2 SECONDS + ///damage multiplier + power = 1.3 + +/datum/status_effect/exposed/harpooned/on_apply() + . = ..() + if(.) + owner.add_filter("exposed", 2, list("type" = "outline", "color" = COLOR_RED, "size" = 1)) + + if(ishuman(owner)) + var/mob/living/carbon/human/H = owner + H.physiology.brute_mod *= power + H.physiology.burn_mod *= power + H.physiology.tox_mod *= power + H.physiology.oxy_mod *= power + H.physiology.clone_mod *= power + H.physiology.stamina_mod *= power + else if(isanimal(owner)) + var/mob/living/simple_animal/S = owner + for(var/i in S.damage_coeff) + S.damage_coeff[i] *= power + +/datum/status_effect/exposed/harpooned/on_remove() + owner.remove_filter("exposed") + if(ishuman(owner)) + var/mob/living/carbon/human/H = owner + H.physiology.brute_mod /= power + H.physiology.burn_mod /= power + H.physiology.tox_mod /= power + H.physiology.oxy_mod /= power + H.physiology.clone_mod /= power + H.physiology.stamina_mod /= power + else if(isanimal(owner)) + var/mob/living/simple_animal/S = owner + for(var/i in S.damage_coeff) + S.damage_coeff[i] /= power + /datum/status_effect/knuckled id = "knuckle_wound" duration = 10 SECONDS diff --git a/code/game/area/areas/shuttles.dm b/code/game/area/areas/shuttles.dm index 494468db88ba..37c511734e47 100644 --- a/code/game/area/areas/shuttles.dm +++ b/code/game/area/areas/shuttles.dm @@ -99,7 +99,7 @@ ////////////////////////////Single-area shuttles//////////////////////////// /area/shuttle/transit - name = "Hyperspace" + name = "Bluespace" desc = "Weeeeee" static_lighting = FALSE base_lighting_alpha = 255 diff --git a/code/game/atoms_movable.dm b/code/game/atoms_movable.dm index cba4d4a5a013..56f4083ced98 100644 --- a/code/game/atoms_movable.dm +++ b/code/game/atoms_movable.dm @@ -927,6 +927,9 @@ if(throwing) return TRUE + if(SEND_SIGNAL(src, COMSIG_MOVABLE_SPACEMOVE, movement_dir) & COMSIG_MOVABLE_ALLOW_SPACEMOVE) + return TRUE + if(!isturf(loc)) return TRUE diff --git a/code/game/data_huds.dm b/code/game/data_huds.dm index f3d3ba070582..3589e558963f 100644 --- a/code/game/data_huds.dm +++ b/code/game/data_huds.dm @@ -165,14 +165,17 @@ Medical HUD! Basic mode needs suit sensors on. holder.pixel_y = I.Height() - world.icon_size if(HAS_TRAIT(src, TRAIT_XENO_HOST)) holder.icon_state = "hudxeno" + if(undergoing_cardiac_arrest() && stat != DEAD) //dripstation edit + holder.icon_state = "huddefib" //dripstation edit + return //dripstation edit else if(stat == DEAD || (HAS_TRAIT(src, TRAIT_FAKEDEATH))) if(HAS_TRAIT(src, TRAIT_FAKEDEATH)) - holder.icon_state = "huddefib" + holder.icon_state = "hudflatline" //dripstation edit return if(tod) var/tdelta = round(world.time - timeofdeath) if(tdelta < (DEFIB_TIME_LIMIT)) - holder.icon_state = "huddefib" + holder.icon_state = "hudflatline" //dripstation edit return holder.icon_state = "huddead" else diff --git a/code/game/gamemodes/brother/traitor_bro.dm b/code/game/gamemodes/brother/traitor_bro.dm index fc7417dd8e6a..beaacb372fe5 100644 --- a/code/game/gamemodes/brother/traitor_bro.dm +++ b/code/game/gamemodes/brother/traitor_bro.dm @@ -6,9 +6,10 @@ name = "traitor+brothers" config_tag = "traitorbro" restricted_jobs = list("AI", "Cyborg") - required_players = 8 //yogs - just a minor change + required_players = 20 //yogs - just a minor change title_icon = "ss13" + announce_span = "danger" announce_text = "There are Syndicate agents and Blood Brothers on the station!\n\ Traitors: Accomplish your objectives.\n\ diff --git a/code/game/gamemodes/changeling/changeling.dm b/code/game/gamemodes/changeling/changeling.dm index 38d9de8ed8dd..32ad3e2bb3a0 100644 --- a/code/game/gamemodes/changeling/changeling.dm +++ b/code/game/gamemodes/changeling/changeling.dm @@ -81,7 +81,7 @@ GLOBAL_VAR(changeling_team_objective_type) false_report_weight = 10 restricted_jobs = list("AI", "Cyborg") protected_jobs = list("Security Officer", "Warden", "Detective", "Head of Security", "Captain", "Head of Personnel", "Chief Engineer", "Chief Medical Officer", "Research Director", "Brig Physician") //YOGS - added hop and brig physician - required_players = 25 + required_players = 20 required_enemies = 2 recommended_enemies = 4 reroll_friendly = 1 diff --git a/code/game/gamemodes/changeling/traitor_chan.dm b/code/game/gamemodes/changeling/traitor_chan.dm index cb1c5b13c84f..f3e16fe471c6 100644 --- a/code/game/gamemodes/changeling/traitor_chan.dm +++ b/code/game/gamemodes/changeling/traitor_chan.dm @@ -5,7 +5,7 @@ false_report_weight = 10 traitors_possible = 3 //hard limit on traitors if scaling is turned off restricted_jobs = list("AI", "Cyborg") - required_players = 25 + required_players = 20 required_enemies = 1 // how many of each type are required recommended_enemies = 3 reroll_friendly = 1 diff --git a/code/game/gamemodes/clown_ops/clown_weapons.dm b/code/game/gamemodes/clown_ops/clown_weapons.dm index 3c1c015922eb..a7dfa85ac74e 100644 --- a/code/game/gamemodes/clown_ops/clown_weapons.dm +++ b/code/game/gamemodes/clown_ops/clown_weapons.dm @@ -14,7 +14,7 @@ //Clown shoes with combat stats and noslip. Of course they still squeak. /obj/item/clothing/shoes/clown_shoes/combat name = "combat clown shoes" - desc = "advanced clown shoes that protect the wearer and render them nearly immune to slipping on their own peels. They also squeak at 100% capacity." + desc = "A pair of advanced clown shoes that protect the wearer and render them nearly immune to slipping on their own peels. They also squeak at 100% capacity." clothing_flags = NOSLIP slowdown = SHOES_SLOWDOWN armor = list(MELEE = 25, BULLET = 25, LASER = 25, ENERGY = 25, BOMB = 50, BIO = 60, RAD = 0, FIRE = 70, ACID = 50) @@ -286,16 +286,7 @@ operation_req_access = list(ACCESS_SYNDICATE) internals_req_access = list(ACCESS_SYNDICATE) wreckage = /obj/structure/mecha_wreckage/honker/dark - max_equip = 3 - -/obj/mecha/combat/honker/dark/GrantActions(mob/living/user, human_occupant = 0) - ..() - thrusters_action.Grant(user, src) - - -/obj/mecha/combat/honker/dark/RemoveActions(mob/living/user, human_occupant = 0) - ..() - thrusters_action.Remove(user) + max_equip = 4 /obj/mecha/combat/honker/dark/add_cell(obj/item/stock_parts/cell/C) if(C) @@ -312,6 +303,8 @@ ME.attach(src) ME = new /obj/item/mecha_parts/mecha_equipment/weapon/ballistic/launcher/flashbang/tearstache()//The mousetrap mortar was not up-to-snuff. ME.attach(src) + ME = new /obj/item/mecha_parts/mecha_equipment/thrusters/ion() + ME.attach(src) /obj/mecha/combat/honker/dark/crew operation_req_access = list() diff --git a/code/game/gamemodes/cult/cult.dm b/code/game/gamemodes/cult/cult.dm index 00530fe4d1e5..645d1708fd3d 100644 --- a/code/game/gamemodes/cult/cult.dm +++ b/code/game/gamemodes/cult/cult.dm @@ -41,7 +41,7 @@ false_report_weight = 10 restricted_jobs = list("Chaplain","AI", "Cyborg", "Security Officer", "Warden", "Detective", "Head of Security", "Captain", "Head of Personnel", "Research Director", "Chief Engineer", "Chief Medical Officer", "Brig Physician") //Yogs: Added Brig Physician protected_jobs = list() - required_players = 29 + required_players = 24 required_enemies = 4 recommended_enemies = 4 enemy_minimum_age = 14 diff --git a/code/game/gamemodes/meteor/meteors.dm b/code/game/gamemodes/meteor/meteors.dm index 7c9fa59fd698..e83d8dbd2f50 100644 --- a/code/game/gamemodes/meteor/meteors.dm +++ b/code/game/gamemodes/meteor/meteors.dm @@ -88,19 +88,33 @@ GLOBAL_LIST_INIT(meteorsC, list(/obj/effect/meteor/dust)) //for space dust event icon_state = "small" density = TRUE anchored = TRUE - var/hits = 4 - var/hitpwr = 2 //Level of ex_act to be called on hit. - var/dest pass_flags = PASSTABLE - var/heavy = 0 + + ///The resilience of our meteor + var/hits = 4 + ///Level of ex_act to be called on hit. + var/hitpwr = EXPLODE_HEAVY + //Should we shake people's screens on impact + var/heavy = FALSE + ///Sound to play when you hit something var/meteorsound = 'sound/effects/meteorimpact.ogg' + ///Our starting z level, prevents infinite meteors var/z_original - var/threat = 0 // used for determining which meteors are most interesting - var/lifetime = DEFAULT_METEOR_LIFETIME - var/timerid = null + ///Used for determining which meteors are most interesting + var/threat = 0 + + //Potential items to spawn when you die var/list/meteordrop = list(/obj/item/stack/ore/iron) + ///How much stuff to spawn when you die var/dropamt = 2 + ///The thing we're moving towards, usually a turf + var/atom/dest + ///Lifetime in seconds + var/lifetime = DEFAULT_METEOR_LIFETIME + + var/timerid = null + /obj/effect/meteor/Move() if(z != z_original || loc == dest) qdel(src) @@ -134,6 +148,7 @@ GLOBAL_LIST_INIT(meteorsC, list(/obj/effect/meteor/dust)) //for space dust event SpinAnimation() timerid = QDEL_IN(src, lifetime) chase_target(target) + update_appearance() /obj/effect/meteor/Bump(atom/A) if(A) diff --git a/code/game/gamemodes/revolution/revolution.dm b/code/game/gamemodes/revolution/revolution.dm index bff987ecc363..fa74510a48aa 100644 --- a/code/game/gamemodes/revolution/revolution.dm +++ b/code/game/gamemodes/revolution/revolution.dm @@ -19,7 +19,7 @@ false_report_weight = 10 restricted_jobs = list("Security Officer", "Warden", "Detective", "AI", "Cyborg", "Captain", "Head of Personnel", "Head of Security", "Chief Engineer", "Research Director", "Chief Medical Officer", "Shaft Miner", "Mining Medic", "Brig Physician") //Yogs: Added Brig Physician required_jobs = list(list("Captain"=1),list("Head of Personnel"=1),list("Head of Security"=1),list("Chief Engineer"=1),list("Research Director"=1),list("Chief Medical Officer"=1)) //Any head present - required_players = 30 + required_players = 25 required_enemies = 2 recommended_enemies = 3 enemy_minimum_age = 14 diff --git a/code/game/machinery/computer/arcade.dm b/code/game/machinery/computer/arcade.dm index 1cf5d4dc2ab6..6086a909e646 100644 --- a/code/game/machinery/computer/arcade.dm +++ b/code/game/machinery/computer/arcade.dm @@ -57,7 +57,7 @@ GLOBAL_LIST_INIT(arcade_prize_pool, list( /obj/machinery/computer/arcade name = "random arcade" - desc = "random arcade machine" + desc = "A random arcade machine." icon_state = "arcade" icon_keyboard = null icon_screen = "invaders" diff --git a/code/game/machinery/doors/airlock.dm b/code/game/machinery/doors/airlock.dm index 4b17d6bd8892..a0248f48490b 100644 --- a/code/game/machinery/doors/airlock.dm +++ b/code/game/machinery/doors/airlock.dm @@ -1306,10 +1306,9 @@ return INVOKE_ASYNC(src, (density ? PROC_REF(open) : PROC_REF(close)), 2) - if(istype(I, /obj/item/jawsoflife) || istype(I, /obj/item/mantis/blade)) - if(isElectrified()) - if(shock(user,100))//it's like sticking a fork in a power socket - return + if(istype(I, /obj/item/jawsoflife) || istype(I, /obj/item/mantis/blade) || istype(I, /obj/item/mecha_parts/mecha_equipment/hydraulic_clamp)) + if(isElectrified() && shock(user,100))//it's like sticking a fork in a power socket + return if(istype(I, /obj/item/mantis/blade)) var/obj/item/mantis/blade/secondsword = user.get_inactive_held_item() @@ -1662,7 +1661,7 @@ qdel(src) /obj/machinery/door/airlock/rcd_vals(mob/user, obj/item/construction/rcd/the_rcd) - switch(the_rcd.mode) + switch(the_rcd.construction_mode) if(RCD_DECONSTRUCT) if(security_level != AIRLOCK_SECURITY_NONE) to_chat(user, span_notice("[src]'s reinforcement needs to be removed first.")) diff --git a/code/game/machinery/doors/airlock_electronics.dm b/code/game/machinery/doors/airlock_electronics.dm index 7bf3fefe4449..679557a011e8 100644 --- a/code/game/machinery/doors/airlock_electronics.dm +++ b/code/game/machinery/doors/airlock_electronics.dm @@ -3,9 +3,14 @@ req_access = list(ACCESS_MAINT_TUNNELS) custom_price = 5 + /// A list of all granded accesses var/list/accesses = list() + /// If the airlock should require ALL or only ONE of the listed accesses var/one_access = 0 - var/unres_sides = 0 //unrestricted sides, or sides of the airlock that will open regardless of access + /// Unrestricted sides, or sides of the airlock that will open regardless of access + var/unres_sides = 0 + /// A holder of the electronics, in case of them working as an integrated part + var/holder /obj/item/electronics/airlock/examine(mob/user) . = ..() @@ -49,40 +54,45 @@ return data -/obj/item/electronics/airlock/ui_act(action, params) - if(..()) - return +/// Shared by RCD and airlock electronics +/obj/item/electronics/airlock/proc/do_action(action, params) switch(action) if("clear_all") accesses = list() one_access = 0 - . = TRUE if("grant_all") accesses = get_all_accesses() - . = TRUE if("one_access") one_access = !one_access - . = TRUE if("set") var/access = text2num(params["access"]) if (!(access in accesses)) accesses += access else accesses -= access - . = TRUE if("direc_set") var/unres_direction = text2num(params["unres_direction"]) unres_sides ^= unres_direction //XOR, toggles only the bit that was clicked - . = TRUE if("grant_region") var/region = text2num(params["region"]) if(isnull(region)) return accesses |= get_region_accesses(region) - . = TRUE if("deny_region") var/region = text2num(params["region"]) if(isnull(region)) return accesses -= get_region_accesses(region) - . = TRUE + +/obj/item/electronics/airlock/ui_act(action, params) + . = ..() + if(.) + return + + do_action(action, params) + return TRUE + +/obj/item/electronics/airlock/ui_host() + if(holder) + return holder + return src diff --git a/code/game/machinery/doors/firedoor.dm b/code/game/machinery/doors/firedoor.dm index 19df2d845817..c21f917ef52e 100644 --- a/code/game/machinery/doors/firedoor.dm +++ b/code/game/machinery/doors/firedoor.dm @@ -506,7 +506,7 @@ icon_state = "frame[constructionStep]" /obj/structure/firelock_frame/rcd_vals(mob/user, obj/item/construction/rcd/the_rcd) - if(the_rcd.mode == RCD_DECONSTRUCT) + if(the_rcd.construction_mode == RCD_DECONSTRUCT) return list("mode" = RCD_DECONSTRUCT, "delay" = 50, "cost" = 16) return FALSE diff --git a/code/game/machinery/doors/windowdoor.dm b/code/game/machinery/doors/windowdoor.dm index 0b3471c5fe86..78d3195f7284 100644 --- a/code/game/machinery/doors/windowdoor.dm +++ b/code/game/machinery/doors/windowdoor.dm @@ -393,7 +393,7 @@ INVOKE_ASYNC(src, PROC_REF(open_and_close)) /obj/machinery/door/window/rcd_vals(mob/user, obj/item/construction/rcd/the_rcd) - switch(the_rcd.mode) + switch(the_rcd.construction_mode) if(RCD_DECONSTRUCT) return list("mode" = RCD_DECONSTRUCT, "delay" = 50, "cost" = 32) return FALSE diff --git a/code/game/mecha/combat/gygax.dm b/code/game/mecha/combat/gygax.dm index 6c11dc1e5e3b..13dbfdbb3c20 100644 --- a/code/game/mecha/combat/gygax.dm +++ b/code/game/mecha/combat/gygax.dm @@ -25,7 +25,7 @@ operation_req_access = list(ACCESS_SYNDICATE) internals_req_access = list(ACCESS_SYNDICATE) wreckage = /obj/structure/mecha_wreckage/gygax/dark - max_equip = 6 + max_equip = 7 destruction_sleep_duration = 20 /obj/mecha/combat/gygax/dark/loaded/Initialize(mapload) @@ -42,6 +42,8 @@ ME.attach(src) ME = new /obj/item/mecha_parts/mecha_equipment/emergency_eject ME.attach(src) + ME = new /obj/item/mecha_parts/mecha_equipment/thrusters/ion + ME.attach(src) max_ammo() /obj/mecha/combat/gygax/dark/add_cell(obj/item/stock_parts/cell/C=null) @@ -56,16 +58,6 @@ ..() overload_action.Grant(user, src) -/obj/mecha/combat/gygax/dark/GrantActions(mob/living/user, human_occupant = 0) - ..() - thrusters_action.Grant(user, src) - - /obj/mecha/combat/gygax/RemoveActions(mob/living/user, human_occupant = 0) ..() overload_action.Remove(user) - -/obj/mecha/combat/gygax/dark/RemoveActions(mob/living/user, human_occupant = 0) - ..() - thrusters_action.Remove(user) - diff --git a/code/game/mecha/combat/marauder.dm b/code/game/mecha/combat/marauder.dm index cedcdc143603..5ce4c06b372e 100644 --- a/code/game/mecha/combat/marauder.dm +++ b/code/game/mecha/combat/marauder.dm @@ -15,19 +15,17 @@ add_req_access = 0 internal_damage_threshold = 25 force = 40 - max_equip = 4 + max_equip = 5 bumpsmash = 1 /obj/mecha/combat/marauder/GrantActions(mob/living/user, human_occupant = 0) ..() smoke_action.Grant(user, src) - thrusters_action.Grant(user, src) zoom_action.Grant(user, src) /obj/mecha/combat/marauder/RemoveActions(mob/living/user, human_occupant = 0) ..() smoke_action.Remove(user) - thrusters_action.Remove(user) zoom_action.Remove(user) /obj/mecha/combat/marauder/loaded/Initialize(mapload) @@ -40,6 +38,8 @@ ME.attach(src) ME = new /obj/item/mecha_parts/mecha_equipment/antiproj_armor_booster(src) ME.attach(src) + ME = new /obj/item/mecha_parts/mecha_equipment/thrusters/ion(src) + ME.attach(src) max_ammo() /obj/mecha/combat/marauder/seraph @@ -53,7 +53,7 @@ wreckage = /obj/structure/mecha_wreckage/seraph internal_damage_threshold = 20 force = 50 - max_equip = 5 + max_equip = 6 /obj/mecha/combat/marauder/seraph/unloaded @@ -71,6 +71,8 @@ ME.attach(src) ME = new /obj/item/mecha_parts/mecha_equipment/antiproj_armor_booster(src) ME.attach(src) + ME = new /obj/item/mecha_parts/mecha_equipment/thrusters/ion(src) + ME.attach(src) max_ammo() /obj/mecha/combat/marauder/mauler @@ -80,7 +82,7 @@ operation_req_access = list(ACCESS_SYNDICATE) internals_req_access = list(ACCESS_SYNDICATE) wreckage = /obj/structure/mecha_wreckage/mauler - max_equip = 7 + max_equip = 8 destruction_sleep_duration = 20 ejection_distance = 8 @@ -100,6 +102,8 @@ ME.attach(src) ME = new /obj/item/mecha_parts/mecha_equipment/emergency_eject(src) // YEET ME.attach(src) + ME = new /obj/item/mecha_parts/mecha_equipment/thrusters/ion(src) + ME.attach(src) max_ammo() diff --git a/code/game/mecha/equipment/mecha_equipment.dm b/code/game/mecha/equipment/mecha_equipment.dm index 8bbdd4ce7015..72d643b50805 100644 --- a/code/game/mecha/equipment/mecha_equipment.dm +++ b/code/game/mecha/equipment/mecha_equipment.dm @@ -7,6 +7,8 @@ icon_state = "mecha_equip" force = 5 max_integrity = 300 + /// Prevents hitting stuff when trying to use certain equipment as tools + item_flags = NOBLUDGEON /// Cooldown after use var/equip_cooldown = 0 /// is the module ready for use @@ -27,8 +29,21 @@ var/destroy_sound = 'sound/mecha/critdestr.ogg' /// Bitflag. Used by exosuit fabricator to assign sub-categories based on which exosuits can equip this. var/mech_flags = NONE - //Special melee override for melee weapons + /// Special melee override for melee weapons var/melee_override = FALSE + /// Actions granted by this equipment + var/list/equip_actions = list() + +/obj/item/mecha_parts/mecha_equipment/Initialize(mapload) + . = ..() + var/list/action_type_list = equip_actions.Copy() + equip_actions = list() + for(var/path in action_type_list) + var/datum/action/innate/mecha/equipment/action = new path + action.equipment = src + equip_actions.Add(action) + qdel(action_type_list) + /obj/item/mecha_parts/mecha_equipment/proc/update_chassis_page() if(chassis) send_byjax(chassis.occupant,"exosuit.browser","eq_list",chassis.get_equipment_list()) @@ -55,6 +70,8 @@ chassis.occupant_message(span_danger("[src] is destroyed!")) chassis.occupant.playsound_local(chassis, destroy_sound, 50) chassis = null + for(var/datum/action/innate/mecha/equipment/E in equip_actions) + E.Destroy() return ..() /obj/item/mecha_parts/mecha_equipment/try_attach_part(mob/user, obj/mecha/M) @@ -103,7 +120,7 @@ return 0 return 1 -/obj/item/mecha_parts/mecha_equipment/proc/action(atom/target) +/obj/item/mecha_parts/mecha_equipment/proc/action(atom/target, mob/living/user, params) return 0 /obj/item/mecha_parts/mecha_equipment/proc/start_cooldown() @@ -140,9 +157,21 @@ forceMove(M) log_message("[src] initialized.", LOG_MECHA) update_chassis_page() + ADD_TRAIT(src, TRAIT_NODROP, "mecha") + item_flags |= NO_MAT_REDEMPTION // terrible + for(var/datum/action/innate/mecha/equipment/action as anything in equip_actions) + action.chassis = M + if(chassis.occupant) + grant_actions(chassis.occupant) return /obj/item/mecha_parts/mecha_equipment/proc/detach(atom/moveto=null) + if(chassis.occupant) + remove_actions(chassis.occupant) + for(var/datum/action/innate/mecha/equipment/action as anything in equip_actions) + action.chassis = null + item_flags &= ~NO_MAT_REDEMPTION + REMOVE_TRAIT(src, TRAIT_NODROP, "mecha") if(chassis.selected == src) src.on_deselect() moveto = moveto || get_turf(chassis) @@ -198,3 +227,16 @@ /obj/item/mecha_parts/mecha_equipment/proc/check_eva() return chassis?.check_eva() +// Some equipment can be used as tools +/obj/item/mecha_parts/mecha_equipment/tool_use_check(mob/living/user, amount) + return (chassis ? (chassis.cell.charge >= energy_drain) : FALSE) // but not if they aren't attached to a mech + +// Grant any actions to the pilot +/obj/item/mecha_parts/mecha_equipment/proc/grant_actions(mob/pilot) + for(var/datum/action/innate/mecha/equipment/action as anything in equip_actions) + action.Grant(pilot) + +// Remove the actions!!!! +/obj/item/mecha_parts/mecha_equipment/proc/remove_actions(mob/pilot) + for(var/datum/action/innate/mecha/equipment/action as anything in equip_actions) + action.Remove(pilot) diff --git a/code/game/mecha/equipment/tools/other_tools.dm b/code/game/mecha/equipment/tools/other_tools.dm index ecf3a724bcc0..345401e86c38 100644 --- a/code/game/mecha/equipment/tools/other_tools.dm +++ b/code/game/mecha/equipment/tools/other_tools.dm @@ -471,7 +471,105 @@ if(..()) radiation_pulse(get_turf(src), rad_per_cycle) +/////////////////////////////////////////// THRUSTERS ///////////////////////////////////////////// + +/obj/item/mecha_parts/mecha_equipment/thrusters + name = "generic exosuit thrusters" //parent object, in-game sources will be a child object + desc = "A generic set of thrusters, from an unknown source. Uses not-understood methods to propel exosuits seemingly for free." + icon_state = "thrusters" + equip_actions = list(/datum/action/innate/mecha/equipment/toggle_thrusters) + selectable = FALSE + var/thrusters_active = FALSE + var/datum/effect_system/trail_follow/thrust_trail = /datum/effect_system/trail_follow/sparks + +/obj/item/mecha_parts/mecha_equipment/thrusters/Initialize(mapload) + . = ..() + thrust_trail = new thrust_trail + thrust_trail.set_up(src) + +/obj/item/mecha_parts/mecha_equipment/thrusters/try_attach_part(mob/user, obj/mecha/M) + for(var/obj/item/mecha_parts/mecha_equipment/equip as anything in M.equipment) + if(istype(equip, type)) + to_chat(user, span_warning("[src] already has thrusters!")) + return FALSE + return ..() + +/obj/item/mecha_parts/mecha_equipment/thrusters/attach(obj/mecha/M) + . = ..() + if(thrusters_active) + thrust_trail.start() + RegisterSignal(M, COMSIG_MOVABLE_SPACEMOVE, PROC_REF(thrust)) + +/obj/item/mecha_parts/mecha_equipment/thrusters/detach(atom/moveto) + UnregisterSignal(chassis, COMSIG_MOVABLE_SPACEMOVE) + if(thrusters_active) + thrust_trail.stop() + return ..() + +/obj/item/mecha_parts/mecha_equipment/thrusters/proc/thrust(obj/mecha/exo, movement_dir) + if(!thrusters_active) + return + if(!chassis) + return + return COMSIG_MOVABLE_ALLOW_SPACEMOVE //This parent should never exist in-game outside admeme use, so why not let it be a creative thruster? + +/obj/item/mecha_parts/mecha_equipment/thrusters/get_equip_info() + return "[..()] \[Thrusters: [thrusters_active ? "Enabled" : "Disabled"]\]" + +/obj/item/mecha_parts/mecha_equipment/thrusters/gas + name = "RCS thruster package" + desc = "A set of thrusters that allow for exosuit movement in zero-gravity environments, by expelling gas from the internal life support tank." + thrust_trail = /datum/effect_system/trail_follow/smoke + var/move_cost = 0.05 // moles per step (5 times more than human jetpacks) +/obj/item/mecha_parts/mecha_equipment/thrusters/gas/thrust(obj/mecha/exo, movement_dir) + if(!thrusters_active) + return + if(!movement_dir) + return + var/obj/machinery/portable_atmospherics/canister/internal_tank = chassis.internal_tank + if(!internal_tank) + return + var/datum/gas_mixture/our_mix = internal_tank.return_air() + var/moles = our_mix.total_moles() + if(moles < move_cost) + thrusters_active = FALSE + thrust_trail.stop() + our_mix.remove(moles) + return + our_mix.remove(move_cost) + return COMSIG_MOVABLE_ALLOW_SPACEMOVE + +/obj/item/mecha_parts/mecha_equipment/thrusters/ion //for mechs with built-in thrusters, should never really exist un-attached to a mech + name = "ion thruster package" + desc = "A set of thrusters that allow for exosuit movement in zero-gravity environments." + thrust_trail = /datum/effect_system/trail_follow/ion + salvageable = FALSE + +/obj/item/mecha_parts/mecha_equipment/thrusters/ion/thrust(obj/mecha/exo, movement_dir) + if(!thrusters_active) + return + if(!chassis.use_power(chassis.step_energy_drain)) + thrusters_active = FALSE + thrust_trail.stop() + return + return COMSIG_MOVABLE_ALLOW_SPACEMOVE + +/datum/action/innate/mecha/equipment/toggle_thrusters + name = "Toggle Thrusters" + button_icon_state = "mech_thrusters_off" + +/datum/action/innate/mecha/equipment/toggle_thrusters/Activate() + var/obj/item/mecha_parts/mecha_equipment/thrusters/thruster = equipment + thruster.thrusters_active = !thruster.thrusters_active + if(thruster.thrusters_active) + thruster.thrust_trail.start() + else + thruster.thrust_trail.stop() + chassis.log_message("Toggled thrusters.", LOG_MECHA) + chassis.occupant_message("Thrusters [thruster.thrusters_active ?"en":"dis"]abled.") + button_icon_state = "mech_thrusters_[thruster.thrusters_active ? "on" : "off"]" + build_all_button_icons() /////////////////////////////////////////// EJECTION ///////////////////////////////////////////// diff --git a/code/game/mecha/equipment/tools/work_tools.dm b/code/game/mecha/equipment/tools/work_tools.dm index 56a7af725331..d24c6e86cbae 100644 --- a/code/game/mecha/equipment/tools/work_tools.dm +++ b/code/game/mecha/equipment/tools/work_tools.dm @@ -1,8 +1,6 @@ -#define DECONSTRUCT 0 -#define WALL 1 -#define AIRLOCK 2 -//Hydraulic clamp, Kill clamp, Extinguisher, RCD, Cable layer. + +//Hydraulic clamp, Kill clamp, Extinguisher, RCD, RPD, Cable layer. /obj/item/mecha_parts/mecha_equipment/hydraulic_clamp @@ -11,11 +9,29 @@ icon_state = "mecha_clamp" equip_cooldown = 15 energy_drain = 10 + toolspeed = 0.5 + usesound = 'sound/mecha/hydraulic.ogg' + tool_behaviour = TOOL_CROWBAR + equip_actions = list(/datum/action/innate/mecha/equipment/clamp_mode) /// How much damage does it apply when used var/dam_force = 20 var/obj/mecha/working/ripley/cargo_holder harmful = FALSE +/datum/action/innate/mecha/equipment/clamp_mode + name = "Toggle Clamp Mode" + button_icon_state = "clamp_crowbar" + +/datum/action/innate/mecha/equipment/clamp_mode/Activate() + if(equipment.tool_behaviour == TOOL_CROWBAR) + equipment.tool_behaviour = TOOL_WRENCH + else + equipment.tool_behaviour = TOOL_CROWBAR + button_icon_state = "clamp_[equipment.tool_behaviour]" + chassis.balloon_alert(owner, "clamp set to [(equipment.tool_behaviour==TOOL_CROWBAR) ? "pry" : "wrench"]") + playsound(chassis, 'sound/items/change_jaws.ogg', 50, 1) + build_all_button_icons() + /obj/item/mecha_parts/mecha_equipment/hydraulic_clamp/can_attach(obj/mecha/working/ripley/M as obj) if(..()) if(istype(M)) @@ -31,11 +47,18 @@ ..() cargo_holder = null -/obj/item/mecha_parts/mecha_equipment/hydraulic_clamp/action(atom/target) +/obj/item/mecha_parts/mecha_equipment/hydraulic_clamp/action(atom/target, mob/living/user, params) if(!action_checks(target)) return if(!cargo_holder) return + + // There are two ways things handle being pried, and I'm too lazy to make every single thing use the same one + if(target.tool_act(user, src, tool_behaviour) & TOOL_ACT_MELEE_CHAIN_BLOCKING) + return TRUE + if(target.attackby(src, user, params)) + return TRUE + if(ismecha(target)) var/obj/mecha/M = target var/have_ammo @@ -49,20 +72,14 @@ else to_chat(chassis.occupant, "No providable supplies found in cargo hold") return + if(isobj(target)) var/obj/O = target - if(istype(O, /obj/machinery/door/firedoor)) - var/obj/machinery/door/firedoor/D = O - D.try_to_crowbar(src,chassis.occupant) - return - if(istype(O, /obj/machinery/door/airlock/)) - var/obj/machinery/door/airlock/D = O - D.try_to_crowbar(src,chassis.occupant) - return if(!O.anchored) if(cargo_holder.cargo.len < cargo_holder.cargo_capacity) chassis.visible_message("[chassis] lifts [target] and starts to load it into cargo compartment.") O.anchored = TRUE + play_tool_sound(chassis) if(do_after_cooldown(target)) cargo_holder.cargo += O O.forceMove(chassis) @@ -242,133 +259,182 @@ name = "mounted RCD" desc = "An exosuit-mounted Rapid Construction Device." icon_state = "mecha_rcd" - equip_cooldown = 10 - energy_drain = 50 + equip_cooldown = 0 // internal RCD will handle it + energy_drain = 0 // uses matter instead of energy range = MECHA_MELEE|MECHA_RANGED item_flags = NO_MAT_REDEMPTION - var/mode = DECONSTRUCT - var/play_sound = TRUE //so fancy mime RCD can be silent + equip_actions = list(/datum/action/innate/mecha/equipment/rcd) + var/rcd_type = /obj/item/construction/rcd/exosuit + var/obj/item/construction/rcd/internal_rcd /obj/item/mecha_parts/mecha_equipment/rcd/Initialize(mapload) . = ..() GLOB.rcd_list += src + internal_rcd = new rcd_type(src) /obj/item/mecha_parts/mecha_equipment/rcd/Destroy() GLOB.rcd_list -= src + if(internal_rcd && !QDELETED(internal_rcd)) + qdel(internal_rcd) return ..() -/obj/item/mecha_parts/mecha_equipment/rcd/action(atom/target) - if(istype(target, /turf/open/space/transit))//>implying these are ever made -Sieve - return - - if(!isturf(target) && !istype(target, /obj/machinery/door/airlock)) - target = get_turf(target) - if(!action_checks(target) || get_dist(chassis, target)>3) - return - if(play_sound) - playsound(chassis, 'sound/machines/click.ogg', 50, 1) - - switch(mode) - if(DECONSTRUCT) - if(iswallturf(target)) - if(istype(target, /turf/closed/wall/r_wall)) - occupant_message("Wall reinforcements are too complex for deconstruction, must be deconstructed manually.") - return - energy_drain = 500 - var/turf/closed/wall/W = target - occupant_message("Deconstructing [W]...") - if(do_after_cooldown(W)) - chassis.spark_system.start() - W.ScrapeAway(flags = CHANGETURF_INHERIT_AIR) - if(play_sound) - playsound(W, 'sound/items/deconstruct.ogg', 50, 1) - if(target == /turf/closed/wall/r_wall) - energy_drain = 2000 - else if(isfloorturf(target)) - if(istype(target, /turf/open/floor/engine)) - occupant_message("Floor reinforcements prevent deconstruction, remove before continuing.") - return - energy_drain = 100 - var/turf/open/floor/F = target - occupant_message("Deconstructing [F]...") - if(do_after_cooldown(target)) - chassis.spark_system.start() - F.ScrapeAway(flags = CHANGETURF_INHERIT_AIR) - if(play_sound) - playsound(F, 'sound/items/deconstruct.ogg', 50, 1) - else if (istype(target, /obj/machinery/door/airlock)) - var/obj/machinery/door/airlock/A = target - if(A.damage_deflection > 21) - occupant_message("Airlock too reinforced for deconstruction, remove reinforcements before continuing.") - return - energy_drain = 500 - occupant_message("Deconstructing [target]...") - if(do_after_cooldown(target)) - chassis.spark_system.start() - qdel(target) - if(play_sound) - playsound(target, 'sound/items/deconstruct.ogg', 50, 1) - if(WALL) - if(isspaceturf(target)) - var/turf/open/space/S = target - occupant_message("Building Floor...") - if(do_after_cooldown(S)) - S.place_on_top(/turf/open/floor/plating, flags = CHANGETURF_INHERIT_AIR) - if(play_sound) - playsound(S, 'sound/items/deconstruct.ogg', 50, 1) - chassis.spark_system.start() - else if(isfloorturf(target)) - var/turf/open/floor/F = target - energy_drain = 750 - occupant_message("Building Wall...") - if(do_after_cooldown(F)) - F.place_on_top(/turf/closed/wall) - if(play_sound) - playsound(F, 'sound/items/deconstruct.ogg', 50, 1) - chassis.spark_system.start() - if(AIRLOCK) - if(isfloorturf(target)) - energy_drain = 750 - occupant_message("Building Airlock...") - if(do_after_cooldown(target)) - chassis.spark_system.start() - var/obj/machinery/door/airlock/T = new /obj/machinery/door/airlock(target) - T.autoclose = TRUE - if(play_sound) - playsound(target, 'sound/items/deconstruct.ogg', 50, 1) - playsound(target, 'sound/effects/sparks2.ogg', 50, 1) - - - -/obj/item/mecha_parts/mecha_equipment/rcd/do_after_cooldown(atom/target) +/obj/item/mecha_parts/mecha_equipment/rcd/attach(obj/mecha/M) . = ..() + internal_rcd.owner = M -/obj/item/mecha_parts/mecha_equipment/rcd/Topic(href,href_list) - ..() - if(href_list["mode"]) - mode = text2num(href_list["mode"]) - switch(mode) - if(0) - occupant_message("Switched RCD to Deconstruct.") - energy_drain = initial(energy_drain) - if(1) - occupant_message("Switched RCD to Construct.") - energy_drain = 2*initial(energy_drain) - if(2) - occupant_message("Switched RCD to Construct Airlock.") - energy_drain = 2*initial(energy_drain) - return +/obj/item/mecha_parts/mecha_equipment/rcd/detach(atom/moveto) + internal_rcd.owner = null + return ..() + +/obj/item/mecha_parts/mecha_equipment/rcd/action(atom/target, mob/living/user, params) + var/prox_flag = chassis.Adjacent(target) + if(prox_flag && (istype(target, /obj/item/stack) || istype(target, /obj/item/rcd_ammo) || istype(target, /obj/item/rcd_upgrade))) + chassis.matter_resupply(target, user) + return TRUE + if(!isliving(target)) + internal_rcd.afterattack(target, user, prox_flag, params) // RCD itself will handle it + return TRUE /obj/item/mecha_parts/mecha_equipment/rcd/get_equip_info() - return "[..()] \[D|C|A\]" + return "[..()] \[Matter: [internal_rcd ? internal_rcd.matter : 0]/[internal_rcd ? internal_rcd.max_matter : 0]\]" +/datum/action/innate/mecha/equipment/rcd + name = "Change RCD Mode" + button_icon_state = "rcd" + +/datum/action/innate/mecha/equipment/rcd/Activate() + var/obj/item/mecha_parts/mecha_equipment/rcd/E = equipment + E.internal_rcd.ui_interact(owner) /obj/item/mecha_parts/mecha_equipment/rcd/mime //special silent RCD name = "silenced mounted RCD" desc = "An expertly mimed exosuit-mounted Rapid Construction Device. Not a sound is made." - play_sound = FALSE + rcd_type = /obj/item/construction/rcd/exosuit/mime +/obj/item/mecha_parts/mecha_equipment/pipe_dispenser + name = "mounted RPD" + desc = "An exosuit-mounted Rapid Pipe Dispenser" + icon_state = "mecha_pipe_dispenser" + equip_cooldown = 0 // internal RPD will handle it + energy_drain = 0 // uses matter instead of energy + range = MECHA_MELEE|MECHA_RANGED + item_flags = NO_MAT_REDEMPTION + equip_actions = list(/datum/action/innate/mecha/equipment/pipe_dispenser) + var/rpd_type = /obj/item/pipe_dispenser/exosuit // in case there's ever any other type of RPD for mechs for some reason + var/obj/item/pipe_dispenser/internal_rpd + +/obj/item/mecha_parts/mecha_equipment/pipe_dispenser/Initialize(mapload) + . = ..() + internal_rpd = new rpd_type(src) + +/obj/item/mecha_parts/mecha_equipment/pipe_dispenser/Destroy() + if(internal_rpd && !QDELETED(internal_rpd)) + qdel(internal_rpd) + return ..() + +/obj/item/mecha_parts/mecha_equipment/pipe_dispenser/attach(obj/mecha/M) + . = ..() + internal_rpd.owner = M + +/obj/item/mecha_parts/mecha_equipment/pipe_dispenser/detach(atom/moveto) + internal_rpd.owner = null + return ..() + +/obj/item/mecha_parts/mecha_equipment/pipe_dispenser/action(atom/target, mob/living/user, params) + if(internal_rpd.pre_attack(target, user)) + return FALSE + chassis.Beam(target, icon_state="rped_upgrade",time=2) + return TRUE + +/datum/action/innate/mecha/equipment/pipe_dispenser + name = "Change RPD Mode" + button_icon_state = "rpd" + +/datum/action/innate/mecha/equipment/pipe_dispenser/Activate() + var/obj/item/mecha_parts/mecha_equipment/pipe_dispenser/E = equipment + E.internal_rpd.ui_interact(owner) + + +/obj/item/mecha_parts/mecha_equipment/t_scanner + name = "exosuit T-ray scanner" + desc = "An exosuit-mounted terahertz-ray emitter and scanner used to detect underfloor objects such as cables and pipes. Has much higher range than the handheld version." + icon_state = "mecha_t_scanner" + equip_actions = list(/datum/action/innate/mecha/equipment/t_scanner) + selectable = FALSE + /// Scanning distance + var/distance = 6 + /// Whether the scanning is enabled + var/scanning = FALSE + /// Stored t-ray scan images + var/list/t_ray_images + +/obj/item/mecha_parts/mecha_equipment/t_scanner/attach(obj/mecha/M) + . = ..() + RegisterSignal(M, COMSIG_MOVABLE_MOVED, PROC_REF(on_mech_move)) + +/obj/item/mecha_parts/mecha_equipment/t_scanner/detach(atom/moveto) + UnregisterSignal(chassis, COMSIG_MOVABLE_MOVED) + if(scanning) + STOP_PROCESSING(SSobj, src) + return ..() + +/obj/item/mecha_parts/mecha_equipment/t_scanner/process(delta_time) + if(!update_scan(chassis.occupant)) + return PROCESS_KILL + +/obj/item/mecha_parts/mecha_equipment/t_scanner/proc/on_mech_move() + if(chassis.occupant?.client) + update_scan(chassis.occupant) + +/obj/item/mecha_parts/mecha_equipment/t_scanner/proc/update_scan(mob/pilot, force_remove=FALSE) // twice the range, no downtime + if(!pilot?.client) + return FALSE + if(t_ray_images?.len) + pilot.client.images.Remove(t_ray_images) + QDEL_NULL(t_ray_images) + if(!scanning || force_remove) + return FALSE + + t_ray_images = list() + for(var/obj/O in orange(distance, chassis)) + if(HAS_TRAIT(O, TRAIT_T_RAY_VISIBLE)) + var/image/I = new(loc = get_turf(O)) + var/mutable_appearance/MA = new(O) + MA.alpha = 128 + MA.dir = O.dir + I.appearance = MA + t_ray_images += I + + if(t_ray_images.len) + pilot.client.images += t_ray_images + + return TRUE + +/obj/item/mecha_parts/mecha_equipment/t_scanner/grant_actions(mob/pilot) + . = ..() + update_scan(pilot) + +/obj/item/mecha_parts/mecha_equipment/t_scanner/remove_actions(mob/pilot) + update_scan(pilot, TRUE) + return ..() + +/datum/action/innate/mecha/equipment/t_scanner + name = "Toggle T-ray Scanner" + button_icon_state = "t_scanner_off" + +/datum/action/innate/mecha/equipment/t_scanner/Activate() + var/obj/item/mecha_parts/mecha_equipment/t_scanner/t_scan = equipment + t_scan.scanning = !t_scan.scanning + t_scan.update_scan(t_scan.chassis.occupant) + t_scan.chassis.occupant_message("You [t_scan.scanning ? "activate" : "deactivate"] [t_scan].") + button_icon_state = "t_scanner_[t_scan.scanning ? "on" : "off"]" + build_all_button_icons() + if(t_scan.scanning) + START_PROCESSING(SSobj, t_scan) + else + STOP_PROCESSING(SSobj, t_scan) + /obj/item/mecha_parts/mecha_equipment/cable_layer name = "cable layer" desc = "Equipment for engineering exosuits. Lays cable along the exosuit's path." @@ -561,7 +627,3 @@ qdel(M) playsound(get_turf(N),'sound/items/ratchet.ogg',50,1) return - -#undef DECONSTRUCT -#undef WALL -#undef AIRLOCK diff --git a/code/game/mecha/equipment/weapons/melee_weapons.dm b/code/game/mecha/equipment/weapons/melee_weapons.dm index dc1c60733b6f..06c42b2d4642 100644 --- a/code/game/mecha/equipment/weapons/melee_weapons.dm +++ b/code/game/mecha/equipment/weapons/melee_weapons.dm @@ -62,7 +62,7 @@ addtimer(CALLBACK(src, PROC_REF(set_ready_state), 1), chassis.melee_cooldown * attack_speed_modifier * check_eva()) //Guns only shoot so fast, but weapons can be used as fast as the chassis can swing it! //Melee weapon attacks are a little different in that they'll override the standard melee attack -/obj/item/mecha_parts/mecha_equipment/melee_weapon/action(atom/target, params) +/obj/item/mecha_parts/mecha_equipment/melee_weapon/action(atom/target, mob/living/user, params) if(!action_checks(target)) return 0 @@ -125,7 +125,7 @@ /obj/item/mecha_parts/mecha_equipment/melee_weapon/proc/cleave_attack() return 0 -/obj/item/mecha_parts/mecha_equipment/melee_weapon/proc/special_hit() //For special effects, slightly simplifies cleave/precise attack procs +/obj/item/mecha_parts/mecha_equipment/melee_weapon/proc/special_hit(atom/target) //For special effects, slightly simplifies cleave/precise attack procs return 1 /obj/item/mecha_parts/mecha_equipment/melee_weapon/on_select() @@ -199,7 +199,7 @@ if((isstructure(A) || ismachinery(A) || istype(A, /obj/mecha)) && can_stab_at(chassis, A)) //if it's a big thing we hit anyways. Structures ALWAYS are hit, machines and mechs can be protected var/obj/O = A - if(!O.density) //Make sure it's not an open door or something + if(!O.density && !istype(O, /obj/structure/spacevine)) //Make sure it's not an open door or something continue var/object_damage = max(chassis.force + weapon_damage, minimum_damage) * structure_damage_mult * (istype(A, /obj/mecha) ? mech_damage_multiplier : 1) //Half damage on mechs O.take_damage(object_damage, dam_type, "melee", 0) @@ -536,3 +536,126 @@ span_userdanger("[chassis.name] penetrates your suits armor with [src]!")) chassis.log_message("Hit [H] with [src.name] (precise attack).", LOG_MECHA) + +/obj/item/mecha_parts/mecha_equipment/melee_weapon/mop + name = "heavy mop" + desc = "A very big mop, designed to be attached to mechanical exosuits." + icon_state = "mecha_mop" + energy_drain = 5 + attack_sound = 'sound/effects/slosh.ogg' + + cleave = TRUE + precise_attacks = FALSE // cleave only + attack_sharpness = SHARP_NONE + harmful = FALSE + weapon_damage = 0 // no damage + structure_damage_mult = 0 // don't break stuff while trying to clean + equip_actions = list(/datum/action/innate/mecha/equipment/sweeping) + var/auto_sweep = TRUE + +/datum/action/innate/mecha/equipment/sweeping + name = "Toggle Auto-Mop" + button_icon_state = "sweep_on" + +/datum/action/innate/mecha/equipment/sweeping/Activate() + var/obj/item/mecha_parts/mecha_equipment/melee_weapon/mop/mop = equipment + mop.auto_sweep = !mop.auto_sweep + button_icon_state = "sweep_[mop.auto_sweep ? "on" : "off"]" + build_all_button_icons() + +/obj/item/mecha_parts/mecha_equipment/melee_weapon/mop/attach(obj/mecha/M) + . = ..() + RegisterSignal(M, COMSIG_MOVABLE_PRE_MOVE, PROC_REF(on_pre_move)) + +/obj/item/mecha_parts/mecha_equipment/melee_weapon/mop/detach(atom/moveto) + UnregisterSignal(chassis, COMSIG_MOVABLE_PRE_MOVE) + return ..() + +/obj/item/mecha_parts/mecha_equipment/melee_weapon/mop/can_attach(obj/mecha/M) + if(istype(M, /obj/mecha/working) && M.equipment.len < M.max_equip) + return TRUE + return ..() + +/obj/item/mecha_parts/mecha_equipment/melee_weapon/mop/proc/on_pre_move(obj/mecha/mech, atom/newloc) + if(!auto_sweep) + return + var/mop_dir = get_dir(mech, newloc) + if(mop_dir != mech.dir) // only sweep things in front of the mech + return + do_mop(mech, newloc) + +/obj/item/mecha_parts/mecha_equipment/melee_weapon/mop/proc/do_mop(obj/mecha/mech, atom/newloc, throw_power=1) + var/turf/mop_turf = newloc + var/turf/thrown_at = get_edge_target_turf(mop_turf, chassis.dir) + var/cleaned = FALSE + + if(mop_turf.wash(CLEAN_SCRUB)) + cleaned = TRUE + for(var/atom/movable/moved_atom in newloc) + if(istype(moved_atom, /obj/effect/decal/nuclear_waste)) // sweep that nuclear waste under the rug + cleaned = TRUE + playsound(moved_atom, 'sound/effects/gib_step.ogg', 50, 1) + qdel(moved_atom) + continue + if(moved_atom.wash(CLEAN_SCRUB)) + cleaned = TRUE + if(moved_atom.anchored) + continue + if(moved_atom == chassis) // it can clean itself, but not move itself + continue + moved_atom.throw_at(thrown_at, throw_power, 1, mech.occupant, (throw_power > 1)) + if(isliving(moved_atom) && throw_power > 1) + moved_atom.visible_message(span_danger("[mech] mops the floor with [moved_atom]!"), span_userdanger("[mech] mops the floor with you!")) + + if(cleaned) + playsound(newloc, 'sound/effects/slosh.ogg', 25, 1) + +/obj/item/mecha_parts/mecha_equipment/melee_weapon/mop/cleave_attack() + playsound(chassis, attack_sound, 50, 1) + for(var/turf/T in list(get_turf(chassis), get_step(chassis, chassis.dir), get_step(chassis, turn(chassis.dir, -45)), get_step(chassis, turn(chassis.dir, 45)))) + do_mop(chassis, T, 3) // mop the floor with them! + var/turf/cleave_effect_loc = get_step(get_turf(src), SOUTHWEST) + new cleave_effect(cleave_effect_loc, chassis.dir) + +/obj/item/mecha_parts/mecha_equipment/melee_weapon/flyswatter + name = "comically large flyswatter" + desc = "A comically large flyswatter, presumably for killing comically large bugs." + attack_sound = 'sound/effects/snap.ogg' + icon_state = "mecha_flyswatter" + cleave = FALSE + precise_attacks = TRUE + hit_effect = ATTACK_EFFECT_SMASH + ///Things in this list will be instantly splatted. + var/list/strong_against + ///Damage to mobs with the MOB_BUG biotype, quadrupled for simple mobs + var/bug_damage = 30 + +/obj/item/mecha_parts/mecha_equipment/melee_weapon/flyswatter/Initialize(mapload) + . = ..() + strong_against = typecacheof(list( + /mob/living/simple_animal/hostile/poison/bees, + /mob/living/simple_animal/butterfly, + /mob/living/simple_animal/cockroach, + /obj/item/queen_bee + )) + +/obj/item/mecha_parts/mecha_equipment/melee_weapon/flyswatter/precise_attack(atom/target) + var/mob/living/mob_target = target + if(is_type_in_typecache(target, strong_against)) + new /obj/effect/decal/cleanable/insectguts(target.drop_location()) + to_chat(chassis.occupant, span_warning("You easily splat the [target].")) + if(isliving(target)) + var/mob/living/bug = target + bug.death(TRUE) + else + qdel(target) + else if(isliving(target) && (mob_target.mob_biotypes & MOB_BUG)) + mob_target.apply_damage(bug_damage * (ishuman(mob_target) ? 1 : 4), BRUTE, wound_bonus=CANT_WOUND) // bonus damage to simple mobs + target.visible_message(span_warning("[chassis] splats [target] with [src]!"), span_userdanger("[chassis] splats you with [src]!")) + chassis.do_attack_animation(target, hit_effect) + playsound(chassis, attack_sound, 50, 1) + +/obj/item/mecha_parts/mecha_equipment/melee_weapon/flyswatter/can_attach(obj/mecha/M) + if(istype(M, /obj/mecha/working) && M.equipment.len < M.max_equip) + return TRUE + return ..() diff --git a/code/game/mecha/equipment/weapons/weapons.dm b/code/game/mecha/equipment/weapons/weapons.dm index 6069a2acf89b..05c7b50a1cdc 100644 --- a/code/game/mecha/equipment/weapons/weapons.dm +++ b/code/game/mecha/equipment/weapons/weapons.dm @@ -32,7 +32,7 @@ /obj/item/mecha_parts/mecha_equipment/weapon/proc/get_shot_amount() return projectiles_per_shot -/obj/item/mecha_parts/mecha_equipment/weapon/action(atom/target, params) +/obj/item/mecha_parts/mecha_equipment/weapon/action(atom/target, mob/living/user, params) if(!action_checks(target)) return 0 @@ -151,6 +151,7 @@ /obj/item/mecha_parts/mecha_equipment/weapon/energy/plasma equip_cooldown = 10 + range = MECHA_MELEE|MECHA_RANGED name = "217-D Heavy Plasma Cutter" desc = "A device that shoots resonant plasma bursts at extreme velocity. The blasts are capable of crushing rock and demolishing solid obstacles." icon_state = "mecha_plasmacutter" @@ -160,6 +161,9 @@ energy_drain = 30 projectile = /obj/projectile/plasma/adv/mech fire_sound = 'sound/weapons/plasma_cutter.ogg' + usesound = list('sound/items/welder.ogg', 'sound/items/welder2.ogg') + toolspeed = 0.25 // high-power cutting + tool_behaviour = TOOL_WELDER harmful = FALSE /obj/item/mecha_parts/mecha_equipment/weapon/energy/plasma/can_attach(obj/mecha/M) @@ -171,6 +175,18 @@ return 1 return 0 +/obj/item/mecha_parts/mecha_equipment/weapon/energy/plasma/action(atom/target, mob/living/user, params) + if(!chassis.Adjacent(target)) + return ..() + // Again, two ways using tools can be handled, so check both + if(target.tool_act(chassis.occupant, src, TOOL_WELDER) & TOOL_ACT_MELEE_CHAIN_BLOCKING) + return TRUE + if(target.attackby(src, chassis.occupant, params)) + return TRUE + if(user.a_intent == INTENT_HARM) // hurt things + chassis.default_melee_attack(target) + return TRUE + /obj/item/mecha_parts/mecha_equipment/weapon/energy/mecha_kineticgun equip_cooldown = 10 name = "Exosuit Proto-kinetic Accelerator" @@ -309,7 +325,7 @@ src.rearm() return -/obj/item/mecha_parts/mecha_equipment/weapon/ballistic/action(atom/target) +/obj/item/mecha_parts/mecha_equipment/weapon/ballistic/action(atom/target, mob/living/user, params) if(..()) projectiles -= get_shot_amount() send_byjax(chassis.occupant,"exosuit.browser","[REF(src)]",src.get_equip_info()) @@ -548,3 +564,42 @@ var/atom/movable/AM = hit_atom AM.safe_throw_at(get_edge_target_turf(AM,get_dir(src, AM)), 7, 2) qdel(src) + +// pressure washer, technically a gun +/obj/item/mecha_parts/mecha_equipment/weapon/pressure_washer + name = "exosuit-mounted pressure washer" + desc = "A high-power pressure washer." + icon_state = "mecha_washer" + range = MECHA_MELEE|MECHA_RANGED + projectile = /obj/projectile/reagent/pressure_washer + firing_effect_type = null + fire_sound = 'sound/effects/extinguish.ogg' + var/chem_amount = 5 + +/obj/item/mecha_parts/mecha_equipment/weapon/pressure_washer/Initialize(mapload) + . = ..() + create_reagents(1000) + reagents.add_reagent(/datum/reagent/water, 1000) + +/obj/item/mecha_parts/mecha_equipment/weapon/pressure_washer/action(atom/target, mob/living/user, params) + if(istype(target, /obj/structure/reagent_dispensers/watertank) && get_dist(chassis,target) <= 1) + var/obj/structure/reagent_dispensers/WT = target + WT.reagents.trans_to(src, 1000) + occupant_message(span_notice("Pressure washer refilled.")) + playsound(chassis, 'sound/effects/refill.ogg', 50, 1, -6) + return TRUE + else if(reagents.total_volume < 1) + occupant_message(span_notice("Not enough water!")) + return TRUE + if(..()) + reagents.remove_reagent(/datum/reagent/water, chem_amount) + return TRUE + return FALSE + +/obj/item/mecha_parts/mecha_equipment/weapon/pressure_washer/can_attach(obj/mecha/M) + if(istype(M, /obj/mecha/working) && M.equipment.len < M.max_equip) + return TRUE + return ..() + +/obj/item/mecha_parts/mecha_equipment/weapon/pressure_washer/get_equip_info() + return "[..()] \[[src.reagents.total_volume]\]" diff --git a/code/game/mecha/mecha.dm b/code/game/mecha/mecha.dm index f92f786b6d81..aae3755c65fb 100644 --- a/code/game/mecha/mecha.dm +++ b/code/game/mecha/mecha.dm @@ -4,8 +4,8 @@ #define MECHA_INT_TANK_BREACH (1<<3) #define MECHA_INT_CONTROL_LOST (1<<4) -#define MECHA_MELEE 1 -#define MECHA_RANGED 2 +#define MECHA_MELEE (1<<0) +#define MECHA_RANGED (1<<1) #define FRONT_ARMOUR 1 #define SIDE_ARMOUR 2 @@ -111,7 +111,6 @@ var/datum/action/innate/mecha/mech_cycle_equip/cycle_action = new var/datum/action/innate/mecha/mech_toggle_lights/lights_action = new var/datum/action/innate/mecha/mech_view_stats/stats_action = new - var/datum/action/innate/mecha/mech_toggle_thrusters/thrusters_action = new var/datum/action/innate/mecha/mech_defence_mode/defence_action = new var/datum/action/innate/mecha/mech_overload_mode/overload_action = new var/datum/effect_system/fluid_spread/smoke/smoke_system = new //not an action, but trigged by one @@ -122,7 +121,6 @@ var/datum/action/innate/mecha/strafe/strafing_action = new //Action vars - var/thrusters_active = FALSE var/defence_mode = FALSE var/defence_mode_deflect_chance = 15 var/leg_overload_mode = FALSE @@ -135,7 +133,7 @@ var/phasing_energy_drain = 200 var/phase_state = "" //icon_state when phasing var/strafe = FALSE //If we are strafing - var/canstrafe = TRUE + var/pivot_step = FALSE var/nextsmash = 0 var/smashcooldown = 3 //deciseconds var/ejection_distance = 0 //violently ejects the pilot when destroyed @@ -481,7 +479,7 @@ //////////////////////////// -/obj/mecha/proc/click_action(atom/target,mob/user,params) +/obj/mecha/proc/click_action(atom/target, mob/user, params) if(!occupant || occupant != user ) return if(!locate(/turf) in list(target,target.loc)) // Prevents inventory from being drilled @@ -524,7 +522,7 @@ if(HAS_TRAIT(L, TRAIT_NO_STUN_WEAPONS) && !selected.harmful) to_chat(user, span_warning("You cannot use non-lethal weapons!")) return - if(selected.action(target,params)) + if(selected.action(target, user, params)) selected.start_cooldown() else if(selected && selected.is_melee()) if(isliving(target) && selected.harmful && HAS_TRAIT(L, TRAIT_PACIFISM)) @@ -538,19 +536,22 @@ if(HAS_TRAIT(L, TRAIT_PACIFISM) && W.cleave) to_chat(user, span_warning("You don't want to harm other living beings!")) return - if(selected.action(target,params)) + if(selected.action(target, user, params)) selected.start_cooldown() else - if(internal_damage & MECHA_INT_CONTROL_LOST) - target = pick(oview(1,src)) - if(!melee_can_hit || !istype(target, /atom)) - return - if(equipment_disabled) - return - target.mech_melee_attack(src, TRUE) - melee_can_hit = FALSE - spawn(melee_cooldown) - melee_can_hit = TRUE + default_melee_attack(target) + +/obj/mecha/proc/default_melee_attack(atom/target) + if(internal_damage & MECHA_INT_CONTROL_LOST) + target = pick(oview(1,src)) + if(!melee_can_hit || !istype(target, /atom)) + return + if(equipment_disabled) + return + target.mech_melee_attack(src, TRUE) + melee_can_hit = FALSE + spawn(melee_cooldown) + melee_can_hit = TRUE /obj/mecha/proc/range_action(atom/target) @@ -573,8 +574,6 @@ . = ..() if(.) return TRUE - if(thrusters_active && movement_dir && use_power(step_energy_drain)) - return TRUE var/atom/movable/backup = get_spacemove_backup() if(backup) @@ -608,8 +607,10 @@ /obj/mecha/proc/domove(direction) if(can_move >= world.time) return FALSE - if(direction == DOWN || direction == UP) - return FALSE //nuh uh + if((direction & (DOWN|UP)) && !get_step_multiz(get_turf(src), direction)) + direction &= ~(DOWN|UP) // remove vertical component + if(!direction) // don't bother moving without a direction + return FALSE if(!Process_Spacemove(direction)) return FALSE if(!has_charge(step_energy_drain)) @@ -656,25 +657,30 @@ /obj/mecha/proc/mechturn(direction) setDir(direction) - if(turnsound) + if(turnsound && has_gravity()) playsound(src,turnsound,40,1) return TRUE /obj/mecha/proc/mechstep(direction) var/current_dir = dir var/result = step(src,direction) - if(strafe) + if(strafe && !pivot_step) setDir(current_dir) - if(result && stepsound) + if(result && stepsound && has_gravity()) playsound(src,stepsound,40,1) return result /obj/mecha/proc/mechsteprand() var/result = step_rand(src) - if(result && stepsound) + if(result && stepsound && has_gravity()) playsound(src,stepsound,40,1) return result +/obj/mecha/setDir() + . = ..() + if(occupant) + occupant.setDir(dir) // keep the pilot facing the direction of the mech or bad things happen + /obj/mecha/Bump(atom/obstacle) var/turf/newloc = get_step(src,dir) var/area/newarea = newloc.loc @@ -1274,6 +1280,13 @@ GLOBAL_VAR_INIT(year_integer, text2num(year)) // = 2013??? to_chat(user, span_notice("None of the equipment on this exosuit can use this ammo!")) return FALSE +// Matter resupply and upgrades for mounted RCDs +/obj/mecha/proc/matter_resupply(obj/item/I, mob/user) + for(var/obj/item/mecha_parts/mecha_equipment/rcd/R in equipment) + R.internal_rcd.attackby(I, user) + if(QDELETED(I)) + return + // Checks the pilot and their clothing for mech speed buffs /obj/mecha/proc/check_eva() var/evaNum = 1 diff --git a/code/game/mecha/mecha_actions.dm b/code/game/mecha/mecha_actions.dm index bebbc829af15..fc850f051ffb 100644 --- a/code/game/mecha/mecha_actions.dm +++ b/code/game/mecha/mecha_actions.dm @@ -8,8 +8,9 @@ cycle_action.Grant(user, src) lights_action.Grant(user, src) stats_action.Grant(user, src) - if(canstrafe) - strafing_action.Grant(user, src) + strafing_action.Grant(user, src) + for(var/obj/item/mecha_parts/mecha_equipment/E as anything in equipment) + E.grant_actions(user) /obj/mecha/proc/RemoveActions(mob/living/user, human_occupant = 0) @@ -19,8 +20,9 @@ cycle_action.Remove(user) lights_action.Remove(user) stats_action.Remove(user) - if(canstrafe) - strafing_action.Remove(user) + strafing_action.Remove(user) + for(var/obj/item/mecha_parts/mecha_equipment/E as anything in equipment) + E.remove_actions(user) /datum/action/innate/mecha check_flags = AB_CHECK_HANDS_BLOCKED | AB_CHECK_IMMOBILE | AB_CHECK_CONSCIOUS @@ -134,7 +136,7 @@ /datum/action/innate/mecha/strafe name = "Toggle Strafing. Disabled when Alt is held." - button_icon_state = "strafe" + button_icon_state = "strafe_off" /datum/action/innate/mecha/strafe/Activate() if(!owner || !chassis || chassis.occupant != owner) @@ -151,25 +153,12 @@ occupant_message("Toggled strafing mode [strafe?"on":"off"].") log_message("Toggled strafing mode [strafe?"on":"off"].", LOG_MECHA) + strafing_action.button_icon_state = "strafe_[strafe?"on":"off"]" strafing_action.build_all_button_icons() //////////////////////////////////////// Specific Ability Actions /////////////////////////////////////////////// //Need to be granted by the mech type, Not default abilities. -/datum/action/innate/mecha/mech_toggle_thrusters - name = "Toggle Thrusters" - button_icon_state = "mech_thrusters_off" - -/datum/action/innate/mecha/mech_toggle_thrusters/Activate() - if(!owner || !chassis || chassis.occupant != owner) - return - if(chassis.get_charge() > 0) - chassis.thrusters_active = !chassis.thrusters_active - button_icon_state = "mech_thrusters_[chassis.thrusters_active ? "on" : "off"]" - chassis.log_message("Toggled thrusters.", LOG_MECHA) - chassis.occupant_message("Thrusters [chassis.thrusters_active ?"en":"dis"]abled.") - - /datum/action/innate/mecha/mech_defence_mode name = "Toggle Defence Mode" button_icon_state = "mech_defence_mode_off" @@ -288,3 +277,18 @@ button_icon_state = "mech_phasing_[chassis.phasing ? "on" : "off"]" chassis.occupant_message("En":"#f00\">Dis"]abled phasing.") build_all_button_icons() + +//////////////////////////////////////// Equipment Actions /////////////////////////////////////////////// +//Equipment-based actions like RCD mode selection + +/datum/action/innate/mecha/equipment + var/obj/item/mecha_parts/mecha_equipment/equipment + +/datum/action/innate/mecha/equipment/Grant(mob/living/L, obj/mecha/M, obj/item/mecha_parts/mecha_equipment/E) + if(E) + equipment = E + return ..() + +/datum/action/innate/mecha/equipment/Destroy() + equipment = null + return ..() diff --git a/code/game/mecha/mecha_defense.dm b/code/game/mecha/mecha_defense.dm index ba6c833a217e..4b9591afbc3d 100644 --- a/code/game/mecha/mecha_defense.dm +++ b/code/game/mecha/mecha_defense.dm @@ -211,6 +211,15 @@ if(istype(W, /obj/item/mecha_ammo)) ammo_resupply(W, user) return + + if(istype(W, /obj/item/stack) || istype(W, /obj/item/rcd_ammo) || istype(W, /obj/item/rcd_upgrade)) + matter_resupply(W, user) + return + + if(istype(W, /obj/item/mecha_parts)) + var/obj/item/mecha_parts/P = W + P.try_attach_part(user, src) + return if(W.GetID()) if(add_req_access || maint_access) @@ -304,11 +313,6 @@ to_chat(user, span_warning("The [name] is at full integrity!")) return 1 - else if(istype(W, /obj/item/mecha_parts)) - var/obj/item/mecha_parts/P = W - P.try_attach_part(user, src) - return - else if(istype(W, /obj/item/airlock_scanner)) //yogs start var/obj/item/airlock_scanner/S = W S.show_access(src, user) //yogs end diff --git a/code/game/mecha/mecha_parts.dm b/code/game/mecha/mecha_parts.dm index 81f83e1c5f1f..45c9149eab5b 100644 --- a/code/game/mecha/mecha_parts.dm +++ b/code/game/mecha/mecha_parts.dm @@ -7,7 +7,7 @@ icon = 'icons/mecha/mech_construct.dmi' icon_state = "blank" w_class = WEIGHT_CLASS_GIGANTIC - flags_1 = CONDUCT_1 + flags_1 = CONDUCT_1 | RAD_NO_CONTAMINATE_1 /obj/item/mecha_parts/proc/try_attach_part(mob/user, obj/mecha/M) //For attaching parts to a finished mech if(!user.transferItemToLoc(src, M)) diff --git a/code/game/mecha/mecha_topic.dm b/code/game/mecha/mecha_topic.dm index 1dff7668054b..9c31593b3523 100644 --- a/code/game/mecha/mecha_topic.dm +++ b/code/game/mecha/mecha_topic.dm @@ -100,7 +100,6 @@ Environment pressure: [environment_pressure>WARNING_HIGH_PRESSURE ? span_danger("[environment_pressure]"): environment_pressure]kPa
Environment temperature: [environment_temperature]°K|[environment_temperature - T0C]°C
[dna_lock?"DNA-locked:
[dna_lock] \[Reset\]
":""]
- [thrusters_action.owner ? "Thrusters: [thrusters_active ? "Enabled" : "Disabled"]
" : ""] [defence_action.owner ? "Defence Mode: [defence_mode ? "Enabled" : "Disabled"]
" : ""] [overload_action.owner ? "Leg Actuators Overload: [leg_overload_mode ? "Enabled" : "Disabled"]
" : ""] [smoke_action.owner ? "Smoke: [smoke]
" : ""] diff --git a/code/game/mecha/medical/medical.dm b/code/game/mecha/medical/medical.dm index d605c64a839b..c379795ff78a 100644 --- a/code/game/mecha/medical/medical.dm +++ b/code/game/mecha/medical/medical.dm @@ -1,19 +1,5 @@ /obj/mecha/medical internals_req_access = list(ACCESS_MECH_SCIENCE, ACCESS_MECH_MEDICAL) - -/obj/mecha/medical/mechturn(direction) - setDir(direction) - playsound(src,'sound/mecha/mechmove01.ogg',40,1) - return 1 - -/obj/mecha/medical/mechstep(direction) - var/result = step(src,direction) - if(result) - playsound(src,'sound/mecha/mechstep.ogg',25,1) - return result - -/obj/mecha/medical/mechsteprand() - var/result = step_rand(src) - if(result) - playsound(src,'sound/mecha/mechstep.ogg',25,1) - return result \ No newline at end of file + stepsound = 'sound/mecha/mechstep.ogg' + turnsound = 'sound/mecha/mechmove01.ogg' + pivot_step = TRUE diff --git a/code/game/mecha/working/clarke.dm b/code/game/mecha/working/clarke.dm index 21219c90f8aa..69dc1e31b3af 100644 --- a/code/game/mecha/working/clarke.dm +++ b/code/game/mecha/working/clarke.dm @@ -6,16 +6,17 @@ max_temperature = 65000 max_integrity = 200 step_in = 1.25 - fast_pressure_step_in = 1.25 - slow_pressure_step_in = 1.8 + fast_pressure_step_in = 1.5 + slow_pressure_step_in = 2 resistance_flags = LAVA_PROOF | FIRE_PROOF | ACID_PROOF light_power = 7 deflect_chance = 10 - armor = list(MELEE = 20, BULLET = 10, LASER = 20, ENERGY = 0, BOMB = 60, BIO = 0, RAD = 70, FIRE = 100, ACID = 100) + flags_1 = HEAR_1 | RAD_PROTECT_CONTENTS_1 | RAD_NO_CONTAMINATE_1 + armor = list(MELEE = 20, BULLET = 10, LASER = 20, ENERGY = 0, BOMB = 60, BIO = 0, RAD = 100, FIRE = 100, ACID = 100) max_equip = 7 wreckage = /obj/structure/mecha_wreckage/clarke enter_delay = 40 - canstrafe = FALSE + pivot_step = TRUE /// Handles an internal ore box for Clarke var/obj/structure/ore_box/box omnidirectional_attacks = TRUE @@ -50,6 +51,14 @@ var/mob/living/brain/B = M.brainmob hud.show_to(B) +/obj/mecha/working/clarke/domove(direction) + if(ISDIAGONALDIR(direction) && strafe) + if(EWCOMPONENT(dir)) + direction &= ~(NORTH|SOUTH) + else if(NSCOMPONENT(dir)) + direction &= ~(EAST|WEST) + return ..(direction) + //Ore Box Controls ///Special equipment for the Clarke mech, handles moving ore without giving the mech a hydraulic clamp and cargo compartment. diff --git a/code/game/mecha/working/ripley.dm b/code/game/mecha/working/ripley.dm index 046ce62ff769..f9eb136da172 100644 --- a/code/game/mecha/working/ripley.dm +++ b/code/game/mecha/working/ripley.dm @@ -18,6 +18,9 @@ enclosed = FALSE //Normal ripley has an open cockpit design enter_delay = 10 //can enter in a quarter of the time of other mechs exit_delay = 10 + /// Custom Ripley step and turning sounds (from TGMC) + stepsound = 'sound/mecha/powerloader_step.ogg' + turnsound = 'sound/mecha/powerloader_turn2.ogg' opacity = FALSE //Ripley has a window /obj/mecha/working/ripley/Move() @@ -67,7 +70,8 @@ fast_pressure_step_in = 1.75 //step_in while in low pressure conditions slow_pressure_step_in = 3 //step_in while in normal pressure conditions step_in = 3 - armor = list(MELEE = 40, BULLET = 20, LASER = 10, ENERGY = 0, BOMB = 40, BIO = 100, RAD = 55, FIRE = 100, ACID = 100) + flags_1 = HEAR_1 | RAD_PROTECT_CONTENTS_1 | RAD_NO_CONTAMINATE_1 + armor = list(MELEE = 40, BULLET = 20, LASER = 10, ENERGY = 0, BOMB = 40, BIO = 100, RAD = 100, FIRE = 100, ACID = 100) wreckage = /obj/structure/mecha_wreckage/ripley/mkii enclosed = TRUE enter_delay = 40 @@ -80,12 +84,13 @@ icon_state = "firefighter" max_temperature = 65000 max_integrity = 250 - fast_pressure_step_in = 2 //step_in while in low pressure conditions - slow_pressure_step_in = 4 //step_in while in normal pressure conditions - step_in = 4 + fast_pressure_step_in = 1.75 //step_in while in low pressure conditions + slow_pressure_step_in = 3 //step_in while in normal pressure conditions + step_in = 3 resistance_flags = LAVA_PROOF | FIRE_PROOF | ACID_PROOF light_power = 7 - armor = list(MELEE = 40, BULLET = 30, LASER = 30, ENERGY = 0, BOMB = 60, BIO = 100, RAD = 70, FIRE = 100, ACID = 100) + flags_1 = HEAR_1 | RAD_PROTECT_CONTENTS_1 | RAD_NO_CONTAMINATE_1 + armor = list(MELEE = 40, BULLET = 30, LASER = 30, ENERGY = 0, BOMB = 60, BIO = 100, RAD = 100, FIRE = 100, ACID = 100) max_equip = 5 // More armor, less tools wreckage = /obj/structure/mecha_wreckage/ripley/firefighter enclosed = TRUE @@ -93,6 +98,15 @@ silicon_icon_state = null opacity = TRUE +// maybe janitor ERTs could get this or something? +/obj/mecha/working/ripley/janitorial/Initialize(mapload) + . = ..() + var/obj/item/mecha_parts/mecha_equipment/washer = new /obj/item/mecha_parts/mecha_equipment/weapon/pressure_washer + washer.attach(src) + var/obj/item/mecha_parts/mecha_equipment/big_mop = new /obj/item/mecha_parts/mecha_equipment/melee_weapon/mop + big_mop.attach(src) + var/obj/item/mecha_parts/mecha_equipment/swatter = new /obj/item/mecha_parts/mecha_equipment/melee_weapon/flyswatter + swatter.attach(src) /obj/mecha/working/ripley/deathripley desc = "OH SHIT IT'S THE DEATHSQUAD WE'RE ALL GONNA DIE" diff --git a/code/game/objects/effects/decals/cleanable.dm b/code/game/objects/effects/decals/cleanable.dm index 6d408ecaed6d..15b5bfe7d593 100644 --- a/code/game/objects/effects/decals/cleanable.dm +++ b/code/game/objects/effects/decals/cleanable.dm @@ -34,6 +34,10 @@ diseases_to_add += D if(LAZYLEN(diseases_to_add)) AddComponent(/datum/component/infective, diseases_to_add) + var/static/list/loc_connections = list( + COMSIG_ATOM_ENTERED = PROC_REF(on_entered), + ) + AddElement(/datum/element/connect_loc, loc_connections) /obj/effect/decal/cleanable/proc/replace_decal(obj/effect/decal/cleanable/C) // Returns true if we should give up in favor of the pre-existing decal if(mergeable_decal) diff --git a/code/game/objects/effects/decals/cleanable/humans.dm b/code/game/objects/effects/decals/cleanable/humans.dm index e686f9b57948..f700c847f6ee 100644 --- a/code/game/objects/effects/decals/cleanable/humans.dm +++ b/code/game/objects/effects/decals/cleanable/humans.dm @@ -130,7 +130,7 @@ /obj/effect/decal/cleanable/blood/gibs/ex_act(severity, target) return -/obj/effect/decal/cleanable/blood/gibs/Crossed(atom/movable/L) +/obj/effect/decal/cleanable/blood/gibs/on_entered(datum/source, atom/movable/L) if(isliving(L) && has_gravity(loc)) playsound(loc, 'sound/effects/gib_step.ogg', HAS_TRAIT(L, TRAIT_LIGHT_STEP) ? 20 : 50, TRUE) . = ..() diff --git a/code/game/objects/effects/effect_system/effects_other.dm b/code/game/objects/effects/effect_system/effects_other.dm index 81f3330f53cf..83583f844b3f 100644 --- a/code/game/objects/effects/effect_system/effects_other.dm +++ b/code/game/objects/effects/effect_system/effects_other.dm @@ -11,7 +11,7 @@ var/active = FALSE var/allow_overlap = FALSE var/auto_process = TRUE - var/qdel_in_time = 10 + var/qdel_in_time = 1 SECONDS var/fadetype = "ion_fade" var/fade = TRUE var/nograv_required = FALSE @@ -65,6 +65,16 @@ /datum/effect_system/trail_follow/steam effect_type = /obj/effect/particle_effect/steam +/datum/effect_system/trail_follow/sparks + effect_type = /obj/effect/particle_effect/sparks + nograv_required = TRUE + fade = FALSE + +/datum/effect_system/trail_follow/smoke + effect_type = /obj/effect/particle_effect/fluid/smoke/trail + nograv_required = TRUE + fade = FALSE + /obj/effect/particle_effect/ion_trails name = "ion trails" icon_state = "ion_trails" @@ -76,7 +86,7 @@ /datum/effect_system/trail_follow/ion effect_type = /obj/effect/particle_effect/ion_trails nograv_required = TRUE - qdel_in_time = 20 + qdel_in_time = 2 SECONDS /datum/effect_system/trail_follow/proc/set_dir(obj/effect/particle_effect/ion_trails/I) I.setDir(holder.dir) diff --git a/code/game/objects/effects/effect_system/fluid_spread/effects_smoke.dm b/code/game/objects/effects/effect_system/fluid_spread/effects_smoke.dm index 585fe1433621..f02dfc5396a7 100644 --- a/code/game/objects/effects/effect_system/fluid_spread/effects_smoke.dm +++ b/code/game/objects/effects/effect_system/fluid_spread/effects_smoke.dm @@ -156,6 +156,19 @@ /obj/effect/particle_effect/fluid/smoke/transparent opacity = FALSE +/// Special smoke used for the RCS thruster +/obj/effect/particle_effect/fluid/smoke/trail + lifetime = 1 SECONDS + opacity = FALSE + alpha = 100 + +/obj/effect/particle_effect/fluid/smoke/trail/Initialize(mapload, datum/fluid_group/group, ...) + . = ..() + var/matrix/start_transform = matrix(transform)/2 + var/matrix/end_transform = matrix(transform) + transform = start_transform + animate(src, alpha = 0, transform = end_transform, time = lifetime) + /** * A helper proc used to spawn small puffs of smoke. * diff --git a/code/game/objects/effects/mines.dm b/code/game/objects/effects/mines.dm index 930959270c27..691226b7836b 100644 --- a/code/game/objects/effects/mines.dm +++ b/code/game/objects/effects/mines.dm @@ -86,13 +86,23 @@ icon_state = "uglymine" alpha = 30 var/triggered = 0 + /// Can be set to FALSE if we want a short 'coming online' delay, then set to TRUE. Can still be set off by damage + var/armed = TRUE var/smartmine = FALSE var/disarm_time = 12 SECONDS var/disarm_product = /obj/item/deployablemine // ie what drops when the mine is disarmed + /// Who's got their foot on the mine's pressure plate + /// Stepping on the mine will set this to the first mob who stepped over it + /// The mine will not detonate via movement unless the first mob steps off of it + var/datum/weakref/foot_on_mine /obj/effect/mine/Initialize(mapload) . = ..() - layer = ABOVE_MOB_LAYER + var/static/list/loc_connections = list( + COMSIG_ATOM_ENTERED = PROC_REF(on_entered), + COMSIG_ATOM_EXITED = PROC_REF(on_exited), + ) + AddElement(/datum/element/connect_loc, loc_connections) /obj/effect/mine/attackby(obj/I, mob/user, params) if(istype(I, /obj/item/multitool)) @@ -107,18 +117,6 @@ /obj/effect/mine/proc/mineEffect(mob/victim) to_chat(victim, span_danger("*click*")) -/obj/effect/mine/Crossed(AM as mob|obj) - . = ..() - if(isturf(loc)) - if(ismob(AM)) - var/mob/MM = AM - if(!(MM.movement_type & FLYING)) - checksmartmine(AM) - else - if(istype(AM, /obj/projectile)) - return - triggermine(AM) - /obj/effect/mine/proc/checksmartmine(mob/target) if(smartmine && target && !HAS_TRAIT(target, TRAIT_MINDSHIELD)) triggermine(target) @@ -132,7 +130,7 @@ var/datum/effect_system/spark_spread/s = new /datum/effect_system/spark_spread s.set_up(1, 0, src) s.start() - mineEffect(victim) + INVOKE_ASYNC(src, PROC_REF(mineEffect), victim) triggered = 1 qdel(src) @@ -257,7 +255,7 @@ /obj/effect/mine/pickup name = "pickup" - desc = "pick me up" + desc = "Pick me up." icon = 'icons/effects/effects.dmi' icon_state = "electricity2" density = FALSE @@ -360,3 +358,45 @@ /obj/effect/mine/creampie/mineEffect(mob/victim) var/obj/item/reagent_containers/food/snacks/pie/cream/P = new /obj/item/reagent_containers/food/snacks/pie/cream(src) P.splat(victim) + +/// Can this mine trigger on the passed movable? +/obj/effect/mine/proc/can_trigger(atom/movable/on_who) + if(triggered || !isturf(loc) || iseffect(on_who)) + return FALSE + + var/mob/living/living_mob + if(ismob(on_who)) + if(!isliving(on_who)) //no ghosties. + return FALSE + living_mob = on_who + + if(living_mob?.incorporeal_move || (on_who.movement_type & MOVETYPES_NOT_TOUCHING_GROUND)) + return foot_on_mine ? IS_WEAKREF_OF(on_who, foot_on_mine) : FALSE //Only go boom if their foot was on the mine PRIOR to flying/phasing. You fucked up, you live with the consequences. + + return TRUE + + +/obj/effect/mine/proc/on_entered(datum/source, atom/movable/arrived) + SIGNAL_HANDLER + + if(!can_trigger(arrived)) + return + // Someone already on it + if(foot_on_mine?.resolve()) + return + + foot_on_mine = WEAKREF(arrived) + visible_message(span_danger("[icon2html(src, viewers(src))] *click*")) + playsound(src, 'sound/machines/click.ogg', 60, TRUE) + +/obj/effect/mine/proc/on_exited(datum/source, atom/movable/gone) + // SIGNAL_HANDLER we're not ready for this + + if(!can_trigger(gone)) + return + // Check that the guy who's on it is stepping off + if(foot_on_mine && !IS_WEAKREF_OF(gone, foot_on_mine)) + return + + triggermine(gone) + foot_on_mine = null diff --git a/code/game/objects/items/RCD.dm b/code/game/objects/items/RCD.dm index f32892331598..f0ab2f890b99 100644 --- a/code/game/objects/items/RCD.dm +++ b/code/game/objects/items/RCD.dm @@ -1,6 +1,3 @@ -#define GLOW_MODE 3 -#define LIGHT_MODE 2 -#define REMOVE_MODE 1 /* CONTAINS: @@ -41,6 +38,7 @@ RLD var/linked_switch_id = null //integer variable, the id for the assigned conveyor switch var/obj/machinery/conveyor/last_placed var/color_choice = null + var/silent = FALSE // does it make sound? (used for mime mech RCD) /obj/item/construction/Initialize(mapload) . = ..() @@ -50,13 +48,20 @@ RLD if(upgrade & RCD_UPGRADE_SILO_LINK) silo_mats = AddComponent(/datum/component/remote_materials, "RCD", mapload, FALSE) +/// Used for examining the RCD and for its UI +/obj/item/construction/proc/get_silo_iron() + if(silo_link && silo_mats.mat_container && !silo_mats.on_hold()) + return silo_mats.mat_container.get_material_amount(/datum/material/iron)/500 + return FALSE + /obj/item/construction/examine(mob/user) . = ..() . += "It currently holds [matter]/[max_matter] matter-units." if(upgrade & RCD_UPGRADE_SILO_LINK) . += "Remote storage link state: [silo_link ? "[silo_mats.on_hold() ? "ON HOLD" : "ON"]" : "OFF"]." - if(silo_link && silo_mats.mat_container && !silo_mats.on_hold()) - . += "Remote connection has iron in equivalent to [silo_mats.mat_container.get_material_amount(/datum/material/iron)/500] RCD unit\s." //1 matter for 1 floor tile, as 4 tiles are produced from 1 metal + var/iron = get_silo_iron() + if(iron) + . += "Remote connection has iron in equivalent to [iron] RCD unit\s." //1 matter for 1 floor tile, as 4 tiles are produced from 1 metal /obj/item/construction/Destroy() QDEL_NULL(spark_system) @@ -90,13 +95,15 @@ RLD upgrade |= rcd_up.upgrade if((rcd_up.upgrade & RCD_UPGRADE_SILO_LINK) && !silo_mats) silo_mats = AddComponent(/datum/component/remote_materials, "RCD", FALSE, FALSE) - playsound(src.loc, 'sound/machines/click.ogg', 50, TRUE) + if(!silent) + playsound(src.loc, 'sound/machines/click.ogg', 50, TRUE) qdel(rcd_up) /// Inserts matter into the RCD allowing it to build /obj/item/construction/proc/insert_matter(obj/O, mob/user) if(iscyborg(user)) return FALSE + var/loaded = FALSE if(istype(O, /obj/item/rcd_ammo)) var/obj/item/rcd_ammo/R = O @@ -108,7 +115,8 @@ RLD if(R.ammoamt <= 0) qdel(R) matter += load - playsound(src.loc, 'sound/machines/click.ogg', 50, TRUE) + if(!silent) + playsound(src.loc, 'sound/machines/click.ogg', 50, TRUE) loaded = TRUE else if(istype(O, /obj/item/stack)) loaded = loadwithsheets(O, user) @@ -127,17 +135,20 @@ RLD var/amount_to_use = min(S.amount, maxsheets) S.use(amount_to_use) matter += value*amount_to_use - playsound(src.loc, 'sound/machines/click.ogg', 50, TRUE) + if(!silent) + playsound(src.loc, 'sound/machines/click.ogg', 50, TRUE) to_chat(user, span_notice("You insert [amount_to_use] [S.name] sheets into [src]. ")) return TRUE to_chat(user, span_warning("You can't insert any more [S.name] sheets into [src]!")) return FALSE /obj/item/construction/proc/activate() - playsound(src.loc, 'sound/items/deconstruct.ogg', 50, TRUE) + if(!silent) + playsound(src.loc, 'sound/items/deconstruct.ogg', 50, TRUE) /obj/item/construction/attack_self(mob/user) - playsound(src.loc, 'sound/effects/pop.ogg', 50, FALSE) + if(!silent) + playsound(src.loc, 'sound/effects/pop.ogg', 50, FALSE) if(prob(20)) spark_system.start() @@ -169,6 +180,39 @@ RLD silo_mats.silo_log(src, "consume", -amount, "build", materials) return TRUE +/obj/item/construction/ui_data(mob/user) + var/list/data = list() + + //matter in the rcd + var/total_matter = ((upgrade & RCD_UPGRADE_SILO_LINK) && silo_link) ? get_silo_iron() : matter + if(!total_matter) + total_matter = 0 + data["matterLeft"] = total_matter + + //silo details + data["silo_upgraded"] = !!(upgrade & RCD_UPGRADE_SILO_LINK) + data["silo_enabled"] = silo_link + + return data + +///shared action for toggling silo link rcd,rld & plumbing +/obj/item/construction/ui_act(action, list/params) + . = ..() + if(.) + return + + if(action == "toggle_silo") + if(silo_mats) + if(!silo_mats.mat_container && !silo_link) // Allow them to turn off an invalid link + to_chat(usr, span_alert("No silo link detected. Connect to silo via multitool.")) + return FALSE + silo_link = !silo_link + to_chat(usr, span_notice("You change [src]'s storage link state: [silo_link ? "ON" : "OFF"].")) + else + to_chat(usr, span_warning("[src] doesn't have remote storage connection.")) + return TRUE + return FALSE + /obj/item/construction/proc/checkResource(amount, mob/user) if(!silo_link || !silo_mats || !silo_mats.mat_container) . = matter >= amount @@ -213,6 +257,27 @@ RLD return FALSE return TRUE +///each define maps to a variable used for construction in the RCD +#define CONSTRUCTION_MODE "construction_mode" +#define WINDOW_TYPE "window_type" +#define WINDOW_GLASS "window_glass" +#define WINDOW_SIZE "window_size" +#define COMPUTER_DIR "computer_dir" +#define FURNISH_TYPE "furnish_type" +#define FURNISH_COST "furnish_cost" +#define FURNISH_DELAY "furnish_delay" +#define AIRLOCK_TYPE "airlock_type" +#define CONVEYOR_TYPE "conveyor_type" + +///flags to be sent to UI +#define TITLE "title" +#define ICON "icon" + +///flags for creating icons shared by an entire category +#define CATEGORY_ICON_STATE "category_icon_state" +#define CATEGORY_ICON_SUFFIX "category_icon_suffix" +#define TITLE_ICON "ICON=TITLE" + /obj/item/construction/rcd name = "rapid-construction-device (RCD)" icon = 'icons/obj/tools.dmi' @@ -224,7 +289,104 @@ RLD slot_flags = ITEM_SLOT_BELT item_flags = NO_MAT_REDEMPTION | NOBLUDGEON has_ammobar = TRUE - var/mode = RCD_FLOORWALL + + ///all stuff used by RCD for construction + var/static/list/root_categories = list( + //1ST ROOT CATEGORY + "Construction" = list( //Stuff you use to make & decorate areas + //Walls & Windows + "Structures" = list( + list(CONSTRUCTION_MODE = RCD_FLOORWALL, ICON = "wallfloor", TITLE = "Wall/Floor"), + list(CONSTRUCTION_MODE = RCD_DECONSTRUCT, ICON = "delete", TITLE = "Deconstruct"), + list(CONSTRUCTION_MODE = RCD_WINDOWGRILLE, WINDOW_TYPE = /obj/structure/window, WINDOW_GLASS = RCD_WINDOW_NORMAL, WINDOW_SIZE = RCD_WINDOW_DIRECTIONAL, ICON = "dirwindow", TITLE = "Directional Window"), + list(CONSTRUCTION_MODE = RCD_WINDOWGRILLE, WINDOW_TYPE = /obj/structure/window/fulltile, WINDOW_GLASS = RCD_WINDOW_NORMAL, WINDOW_SIZE = RCD_WINDOW_FULLTILE, ICON = "fullwindow", TITLE = "Full Tile Window"), + list(CONSTRUCTION_MODE = RCD_WINDOWGRILLE, WINDOW_TYPE = /obj/structure/window/reinforced, WINDOW_GLASS = RCD_WINDOW_REINFORCED, WINDOW_SIZE = RCD_WINDOW_DIRECTIONAL, ICON = "dirwindow_r", TITLE = "Directional Reinforced Window"), + list(CONSTRUCTION_MODE = RCD_WINDOWGRILLE, WINDOW_TYPE = /obj/structure/window/reinforced/fulltile, WINDOW_GLASS = RCD_WINDOW_REINFORCED, WINDOW_SIZE = RCD_WINDOW_FULLTILE, ICON = "fullwindow_r", TITLE = "Full Tile Reinforced Window"), + ), + + //Computers & Machine Frames + "Machines" = list( + list(CONSTRUCTION_MODE = RCD_MACHINE, ICON = "box_1", TITLE = "Machine Frame"), + list(CONSTRUCTION_MODE = RCD_COMPUTER, COMPUTER_DIR = 1, ICON = "cnorth", TITLE = "Computer North"), + list(CONSTRUCTION_MODE = RCD_COMPUTER, COMPUTER_DIR = 2, ICON = "csouth", TITLE = "Computer South"), + list(CONSTRUCTION_MODE = RCD_COMPUTER, COMPUTER_DIR = 4, ICON = "ceast", TITLE = "Computer East"), + list(CONSTRUCTION_MODE = RCD_COMPUTER, COMPUTER_DIR = 8, ICON = "cwest", TITLE = "Computer West"), + ), + + //Interior Design[construction_mode = RCD_FURNISHING is implied] + "Furniture" = list( + list(FURNISH_TYPE = /obj/structure/chair, FURNISH_COST = 8, FURNISH_DELAY = 10, ICON = "chair", TITLE = "Chair"), + list(FURNISH_TYPE = /obj/structure/chair/stool, FURNISH_COST = 8, FURNISH_DELAY = 10, ICON = "stool", TITLE = "Stool"), + list(FURNISH_TYPE = /obj/structure/table, FURNISH_COST = 16, FURNISH_DELAY = 20, ICON = "table",TITLE = "Table"), + list(FURNISH_TYPE = /obj/structure/table/glass, FURNISH_COST = 16, FURNISH_DELAY = 20, ICON = "glass_table", TITLE = "Glass Table"), + ), + + //Conveyors & Switches + "Conveyors" = list( + list(CONSTRUCTION_MODE = RCD_CONVEYOR, ICON = "conveyor_construct", TITLE = "Conveyor Belt"), + list(CONSTRUCTION_MODE = RCD_SWITCH, ICON = "switch-off", TITLE = "Conveyor Switch"), + ) + ), + + //2ND ROOT CATEGORY[construction_mode = RCD_AIRLOCK is implied,"icon=closed"] + "Airlocks" = list( //used to seal/close areas + //Solid Airlocks[airlock_glass = FALSE is implied,no fill_closed overlay] + "Solid Airlocks" = list( + list(AIRLOCK_TYPE = /obj/machinery/door/airlock, TITLE = "Standard", CATEGORY_ICON_STATE = TITLE_ICON), + list(AIRLOCK_TYPE = /obj/machinery/door/airlock/public, TITLE = "Public"), + list(AIRLOCK_TYPE = /obj/machinery/door/airlock/engineering, TITLE = "Engineering"), + list(AIRLOCK_TYPE = /obj/machinery/door/airlock/atmos, TITLE = "Atmospherics"), + list(AIRLOCK_TYPE = /obj/machinery/door/airlock/security, TITLE = "Security"), + list(AIRLOCK_TYPE = /obj/machinery/door/airlock/command, TITLE = "Command"), + list(AIRLOCK_TYPE = /obj/machinery/door/airlock/medical, TITLE = "Medical"), + list(AIRLOCK_TYPE = /obj/machinery/door/airlock/research, TITLE = "Research"), + list(AIRLOCK_TYPE = /obj/machinery/door/airlock/freezer, TITLE = "Freezer"), + list(AIRLOCK_TYPE = /obj/machinery/door/airlock/virology, TITLE = "Virology"), + list(AIRLOCK_TYPE = /obj/machinery/door/airlock/mining, TITLE = "Mining"), + list(AIRLOCK_TYPE = /obj/machinery/door/airlock/maintenance, TITLE = "Maintenance"), + list(AIRLOCK_TYPE = /obj/machinery/door/airlock/external, TITLE = "External"), + list(AIRLOCK_TYPE = /obj/machinery/door/airlock/maintenance/external, TITLE = "External Maintenance"), + list(AIRLOCK_TYPE = /obj/machinery/door/airlock/hatch, TITLE = "Airtight Hatch"), + list(AIRLOCK_TYPE = /obj/machinery/door/airlock/maintenance_hatch, TITLE = "Maintenance Hatch"), + ), + + //Glass Airlocks[airlock_glass = TRUE is implied,do fill_closed overlay] + "Glass Airlocks" = list( + list(AIRLOCK_TYPE = /obj/machinery/door/airlock/glass, TITLE = "Standard", CATEGORY_ICON_STATE = TITLE_ICON, CATEGORY_ICON_SUFFIX = "Glass"), + list(AIRLOCK_TYPE = /obj/machinery/door/airlock/public/glass, TITLE = "Public"), + list(AIRLOCK_TYPE = /obj/machinery/door/airlock/engineering/glass, TITLE = "Engineering"), + list(AIRLOCK_TYPE = /obj/machinery/door/airlock/atmos/glass, TITLE = "Atmospherics"), + list(AIRLOCK_TYPE = /obj/machinery/door/airlock/security/glass, TITLE = "Security"), + list(AIRLOCK_TYPE = /obj/machinery/door/airlock/command/glass, TITLE = "Command"), + list(AIRLOCK_TYPE = /obj/machinery/door/airlock/medical/glass, TITLE = "Medical"), + list(AIRLOCK_TYPE = /obj/machinery/door/airlock/research/glass, TITLE = "Research"), + list(AIRLOCK_TYPE = /obj/machinery/door/airlock/virology/glass, TITLE = "Virology"), + list(AIRLOCK_TYPE = /obj/machinery/door/airlock/mining/glass, TITLE = "Mining"), + list(AIRLOCK_TYPE = /obj/machinery/door/airlock/maintenance/glass, TITLE = "Maintenance"), + list(AIRLOCK_TYPE = /obj/machinery/door/airlock/external/glass, TITLE = "External"), + list(AIRLOCK_TYPE = /obj/machinery/door/airlock/maintenance/external/glass, TITLE = "External Maintenance"), + ), + + //Window Doors[airlock_glass = TRUE is implied] + "Windoors" = list( + list(AIRLOCK_TYPE = /obj/machinery/door/window, ICON = "windoor", TITLE = "Windoor"), + list(AIRLOCK_TYPE = /obj/machinery/door/window/brigdoor, ICON = "secure_windoor", TITLE = "Secure Windoor"), + ), + ), + + //3RD CATEGORY Airlock access,empty list cause airlock_electronics UI will be displayed when this tab is selected + "Airlock Access" = list() + ) + + ///english name for the design to check if it was selected or not + var/design_title = "Wall/Floor" + var/design_category = "Structures" + var/root_category = "Construction" + var/closed = FALSE + ///owner of this rcd. It can either be an construction console or an player + var/owner + + var/construction_mode = RCD_FLOORWALL var/ranged = FALSE var/computer_dir = 1 var/airlock_type = /obj/machinery/door/airlock @@ -244,7 +406,7 @@ RLD var/obj/item/electronics/airlock/airlock_electronics /obj/item/construction/rcd/suicide_act(mob/user) - mode = RCD_FLOORWALL + construction_mode = RCD_FLOORWALL if(!rcd_create(get_turf(user), user)) return SHAME if(isfloorturf(get_turf(user))) @@ -252,350 +414,39 @@ RLD user.visible_message(span_suicide("[user] sets the RCD to 'Wall' and points it down [user.p_their()] throat! It looks like [user.p_theyre()] trying to commit suicide..")) return (BRUTELOSS) -/obj/item/construction/rcd/verb/toggle_window_glass_verb() - set name = "RCD : Toggle Window Glass" - set category = "Object" - set src in view(1) - - if(!usr.canUseTopic(src, BE_CLOSE)) - return - - toggle_window_glass(usr) - -/obj/item/construction/rcd/verb/toggle_window_size_verb() - set name = "RCD : Toggle Window Size" - set category = "Object" - set src in view(1) - - if(!usr.canUseTopic(src, BE_CLOSE)) - return - - toggle_window_size(usr) - -/obj/item/construction/rcd/proc/toggle_access(acc) - if (acc == "all") - conf_access = null - else if(acc == "one") - use_one_access = !use_one_access - else - var/req = text2num(acc) - - if (conf_access == null) - conf_access = list() - - if (!(req in conf_access)) - conf_access += req - else - conf_access -= req - if (!conf_access.len) - conf_access = null - -/// Toggles the usage of reinforced or normal glass -/obj/item/construction/rcd/proc/toggle_window_glass(mob/user) - if (window_glass != RCD_WINDOW_REINFORCED) - set_window_type(user, RCD_WINDOW_REINFORCED, window_size) - return - set_window_type(user, RCD_WINDOW_NORMAL, window_size) - -/// Toggles the usage of directional or full tile windows -/obj/item/construction/rcd/proc/toggle_window_size(mob/user) - if (window_size != RCD_WINDOW_DIRECTIONAL) - set_window_type(user, window_glass, RCD_WINDOW_DIRECTIONAL) - return - set_window_type(user, window_glass, RCD_WINDOW_FULLTILE) - -/// Sets the window type to be created based on parameters -/obj/item/construction/rcd/proc/set_window_type(mob/user, glass, size) - window_glass = glass - window_size = size - if(window_glass == RCD_WINDOW_REINFORCED) - if(window_size == RCD_WINDOW_DIRECTIONAL) - window_type = /obj/structure/window/reinforced - else - window_type = /obj/structure/window/reinforced/fulltile - else - if(window_size == RCD_WINDOW_DIRECTIONAL) - window_type = /obj/structure/window - else - window_type = /obj/structure/window/fulltile - - to_chat(user, span_notice("You change \the [src]'s window mode to [window_size] [window_glass] window.")) - -/obj/item/construction/rcd/proc/toggle_silo_link(mob/user) - if(silo_mats) - if(!silo_mats.mat_container) - to_chat(user, span_alert("No silo link detected. Connect to silo via multitool.")) - return FALSE - silo_link = !silo_link - to_chat(user, span_notice("You change \the [src]'s storage link state: [silo_link ? "ON" : "OFF"].")) - else - to_chat(user, span_warning("\the [src] doesn't have remote storage connection.")) - -/obj/item/construction/rcd/proc/get_airlock_image(airlock_type) - var/obj/machinery/door/airlock/proto = airlock_type - var/ic = initial(proto.icon) - var/mutable_appearance/MA = mutable_appearance(ic, "closed") - if(!initial(proto.glass)) - MA.overlays += "fill_closed" - //Not scaling these down to button size because they look horrible then, instead just bumping up radius. - return MA - -/obj/item/construction/rcd/proc/change_computer_dir(mob/user) - if(!user) - return - var/list/computer_dirs = list( - "NORTH" = image(icon = 'icons/mob/radial.dmi', icon_state = "cnorth"), - "EAST" = image(icon = 'icons/mob/radial.dmi', icon_state = "ceast"), - "SOUTH" = image(icon = 'icons/mob/radial.dmi', icon_state = "csouth"), - "WEST" = image(icon = 'icons/mob/radial.dmi', icon_state = "cwest") - ) - var/computerdirs = show_radial_menu(user, src, computer_dirs, custom_check = CALLBACK(src, PROC_REF(check_menu), user), require_near = TRUE, tooltips = TRUE) - if(!check_menu(user)) - return - switch(computerdirs) - if("NORTH") - computer_dir = 1 - if("EAST") - computer_dir = 4 - if("SOUTH") - computer_dir = 2 - if("WEST") - computer_dir = 8 - -/** - * Customizes RCD's airlock settings based on user's choices - * - * Arguments: - * * user The mob that is choosing airlock settings - * * remote_anchor The remote anchor for radial menus. If set, it will also remove proximity restrictions from the menus - */ -/obj/item/construction/rcd/proc/change_airlock_setting(mob/user, remote_anchor) - if(!user) - return - - var/list/solid_or_glass_choices = list( - "Solid" = get_airlock_image(/obj/machinery/door/airlock), - "Glass" = get_airlock_image(/obj/machinery/door/airlock/glass), - "Windoor" = image(icon = 'icons/mob/radial.dmi', icon_state = "windoor"), - "Secure Windoor" = image(icon = 'icons/mob/radial.dmi', icon_state = "secure_windoor") - ) - - var/list/solid_choices = list( - "Standard" = get_airlock_image(/obj/machinery/door/airlock), - "Public" = get_airlock_image(/obj/machinery/door/airlock/public), - "Engineering" = get_airlock_image(/obj/machinery/door/airlock/engineering), - "Atmospherics" = get_airlock_image(/obj/machinery/door/airlock/atmos), - "Security" = get_airlock_image(/obj/machinery/door/airlock/security), - "Command" = get_airlock_image(/obj/machinery/door/airlock/command), - "Medical" = get_airlock_image(/obj/machinery/door/airlock/medical), - "Research" = get_airlock_image(/obj/machinery/door/airlock/research), - "Freezer" = get_airlock_image(/obj/machinery/door/airlock/freezer), - "Science" = get_airlock_image(/obj/machinery/door/airlock/science), - "Virology" = get_airlock_image(/obj/machinery/door/airlock/virology), - "Mining" = get_airlock_image(/obj/machinery/door/airlock/mining), - "Maintenance" = get_airlock_image(/obj/machinery/door/airlock/maintenance), - "External" = get_airlock_image(/obj/machinery/door/airlock/external), - "External Maintenance" = get_airlock_image(/obj/machinery/door/airlock/maintenance/external), - "Airtight Hatch" = get_airlock_image(/obj/machinery/door/airlock/hatch), - "Maintenance Hatch" = get_airlock_image(/obj/machinery/door/airlock/maintenance_hatch) - ) - - var/list/glass_choices = list( - "Standard" = get_airlock_image(/obj/machinery/door/airlock/glass), - "Public" = get_airlock_image(/obj/machinery/door/airlock/public/glass), - "Engineering" = get_airlock_image(/obj/machinery/door/airlock/engineering/glass), - "Atmospherics" = get_airlock_image(/obj/machinery/door/airlock/atmos/glass), - "Security" = get_airlock_image(/obj/machinery/door/airlock/security/glass), - "Command" = get_airlock_image(/obj/machinery/door/airlock/command/glass), - "Medical" = get_airlock_image(/obj/machinery/door/airlock/medical/glass), - "Research" = get_airlock_image(/obj/machinery/door/airlock/research/glass), - "Science" = get_airlock_image(/obj/machinery/door/airlock/science/glass), - "Virology" = get_airlock_image(/obj/machinery/door/airlock/virology/glass), - "Mining" = get_airlock_image(/obj/machinery/door/airlock/mining/glass), - "Maintenance" = get_airlock_image(/obj/machinery/door/airlock/maintenance/glass), - "External" = get_airlock_image(/obj/machinery/door/airlock/external/glass), - "External Maintenance" = get_airlock_image(/obj/machinery/door/airlock/maintenance/external/glass) - ) - - var/airlockcat = show_radial_menu(user, remote_anchor || src, solid_or_glass_choices, custom_check = CALLBACK(src, PROC_REF(check_menu), user, remote_anchor), require_near = remote_anchor ? FALSE : TRUE, tooltips = TRUE) - switch(airlockcat) - if("Solid") - if(advanced_airlock_setting == 1) - var/airlockpaint = show_radial_menu(user, remote_anchor || src, solid_choices, radius = 42, custom_check = CALLBACK(src, PROC_REF(check_menu), user), require_near = remote_anchor ? FALSE : TRUE, tooltips = TRUE) - switch(airlockpaint) - if("Standard") - airlock_type = /obj/machinery/door/airlock - if("Public") - airlock_type = /obj/machinery/door/airlock/public - if("Engineering") - airlock_type = /obj/machinery/door/airlock/engineering - if("Atmospherics") - airlock_type = /obj/machinery/door/airlock/atmos - if("Security") - airlock_type = /obj/machinery/door/airlock/security - if("Command") - airlock_type = /obj/machinery/door/airlock/command - if("Medical") - airlock_type = /obj/machinery/door/airlock/medical - if("Research") - airlock_type = /obj/machinery/door/airlock/research - if("Freezer") - airlock_type = /obj/machinery/door/airlock/freezer - if("Science") - airlock_type = /obj/machinery/door/airlock/science - if("Virology") - airlock_type = /obj/machinery/door/airlock/virology - if("Mining") - airlock_type = /obj/machinery/door/airlock/mining - if("Maintenance") - airlock_type = /obj/machinery/door/airlock/maintenance - if("External") - airlock_type = /obj/machinery/door/airlock/external - if("External Maintenance") - airlock_type = /obj/machinery/door/airlock/maintenance/external - if("Airtight Hatch") - airlock_type = /obj/machinery/door/airlock/hatch - if("Maintenance Hatch") - airlock_type = /obj/machinery/door/airlock/maintenance_hatch - airlock_glass = FALSE - else - airlock_type = /obj/machinery/door/airlock - airlock_glass = FALSE - - if("Glass") - if(advanced_airlock_setting == 1) - var/airlockpaint = show_radial_menu(user, remote_anchor || src, glass_choices, radius = 42, custom_check = CALLBACK(src, PROC_REF(check_menu), user), require_near = remote_anchor ? FALSE : TRUE, tooltips = TRUE) - if(!check_menu(user)) - return - switch(airlockpaint) - if("Standard") - airlock_type = /obj/machinery/door/airlock/glass - if("Public") - airlock_type = /obj/machinery/door/airlock/public/glass - if("Engineering") - airlock_type = /obj/machinery/door/airlock/engineering/glass - if("Atmospherics") - airlock_type = /obj/machinery/door/airlock/atmos/glass - if("Security") - airlock_type = /obj/machinery/door/airlock/security/glass - if("Command") - airlock_type = /obj/machinery/door/airlock/command/glass - if("Medical") - airlock_type = /obj/machinery/door/airlock/medical/glass - if("Research") - airlock_type = /obj/machinery/door/airlock/research/glass - if("Science") - airlock_type = /obj/machinery/door/airlock/science/glass - if("Virology") - airlock_type = /obj/machinery/door/airlock/virology/glass - if("Mining") - airlock_type = /obj/machinery/door/airlock/mining/glass - if("Maintenance") - airlock_type = /obj/machinery/door/airlock/maintenance/glass - if("External") - airlock_type = /obj/machinery/door/airlock/external/glass - if("External Maintenance") - airlock_type = /obj/machinery/door/airlock/maintenance/external/glass - airlock_glass = TRUE - else - airlock_type = /obj/machinery/door/airlock/glass - airlock_glass = TRUE - if("Windoor") - airlock_type = /obj/machinery/door/window - airlock_glass = TRUE - if("Secure Windoor") - airlock_type = /obj/machinery/door/window/brigdoor - airlock_glass = TRUE - else - airlock_type = /obj/machinery/door/airlock - airlock_glass = FALSE - -/// Radial menu for choosing the object you want to be created with the furnishing mode -/obj/item/construction/rcd/proc/change_furnishing_type(mob/user) - if(!user) - return - var/static/list/choices = list( - "Chair" = image(icon = 'icons/mob/radial.dmi', icon_state = "chair"), - "Stool" = image(icon = 'icons/mob/radial.dmi', icon_state = "stool"), - "Table" = image(icon = 'icons/mob/radial.dmi', icon_state = "table"), - "Glass Table" = image(icon = 'icons/mob/radial.dmi', icon_state = "glass_table") - ) - var/choice = show_radial_menu(user, src, choices, custom_check = CALLBACK(src, PROC_REF(check_menu), user), require_near = TRUE, tooltips = TRUE) - if(!check_menu(user)) - return - switch(choice) - if("Chair") - furnish_type = /obj/structure/chair - furnish_cost = 8 - furnish_delay = 10 - if("Stool") - furnish_type = /obj/structure/chair/stool - furnish_cost = 8 - furnish_delay = 10 - if("Table") - furnish_type = /obj/structure/table - furnish_cost = 16 - furnish_delay = 20 - if("Glass Table") - furnish_type = /obj/structure/table/glass - furnish_cost = 16 - furnish_delay = 20 - /obj/item/construction/rcd/proc/rcd_create(atom/A, mob/user) var/list/rcd_results = A.rcd_vals(user, src) if(!rcd_results) return FALSE var/delay = rcd_results["delay"] * delay_mod - var/obj/effect/constructing_effect/rcd_effect = new(get_turf(A), delay, src.mode) + var/obj/effect/constructing_effect/rcd_effect = new(get_turf(A), delay, src.construction_mode) + var/datum/beam/rcd_beam if(checkResource(rcd_results["cost"], user)) - if(do_after(user, delay, A)) + if(!A.Adjacent(owner ? owner : user)) // ranged RCDs create beams + if(isatom(owner)) + var/atom/owner_atom = owner + rcd_beam = owner_atom.Beam(A,icon_state="rped_upgrade",time=delay) + else + rcd_beam = Beam(A,icon_state="rped_upgrade",time=delay) + if(do_after(user, delay, (owner ? owner : A))) if(checkResource(rcd_results["cost"], user)) if(A.rcd_act(user, src, rcd_results["mode"])) rcd_effect.end_animation() useResource(rcd_results["cost"], user) activate() - playsound(src.loc, 'sound/machines/click.ogg', 50, TRUE) + if(!silent) + playsound(src.loc, 'sound/machines/click.ogg', 50, TRUE) return TRUE + if(rcd_beam) + qdel(rcd_beam) qdel(rcd_effect) return FALSE -/obj/item/construction/rcd/proc/rcd_switch(atom/A, mob/user) - var/cost = 1 - var/delay = 1 - var/obj/effect/constructing_effect/rcd_effect = new(get_turf(A), delay, src.mode) - if(checkResource(cost, user)) - if(do_after(user, delay, A)) - if(checkResource(cost, user)) - rcd_effect.end_animation() - useResource(cost, user) - activate() - playsound(src.loc, 'sound/machines/click.ogg', 50, 1) - new /obj/item/conveyor_switch_construct(A) - qdel(rcd_effect) - -/obj/item/construction/rcd/proc/rcd_conveyor(atom/A, mob/user) - var/delay = 5 - var/cost = 5 - var/obj/effect/constructing_effect/rcd_effect = new(get_turf(A), delay, src.mode) - if(checkResource(cost, user)) - if(do_after(user, delay, target = A)) - if(checkResource(cost, user)) - rcd_effect.end_animation() - useResource(cost, user) - activate() - playsound(src.loc, 'sound/machines/click.ogg', 50, 1) - var/cdir = get_dir(A, user) - if (last_placed) - cdir = get_dir(A, last_placed) - if(cdir in GLOB.cardinals) - last_placed.setDir(get_dir(last_placed, A)) - last_placed = new/obj/machinery/conveyor(A, cdir, linked_switch_id) - qdel(rcd_effect) - /obj/item/construction/rcd/Initialize(mapload) . = ..() airlock_electronics = new(src) airlock_electronics.name = "Access Control" + airlock_electronics.holder = src GLOB.rcd_list += src /obj/item/construction/rcd/Destroy() @@ -603,127 +454,174 @@ RLD GLOB.rcd_list -= src . = ..() -/obj/item/construction/rcd/attack_self(mob/user) - ..() - var/list/choices = list( - "Airlock" = image(icon = 'icons/mob/radial.dmi', icon_state = "airlock"), - "Deconstruct" = image(icon= 'icons/mob/radial.dmi', icon_state = "delete"), - "Grilles & Windows" = image(icon = 'icons/mob/radial.dmi', icon_state = "grillewindow"), - "Floors & Walls" = image(icon = 'icons/mob/radial.dmi', icon_state = "wallfloor") +/obj/item/construction/rcd/ui_host(mob/user) + return owner || ..() + +/obj/item/construction/rcd/ui_interact(mob/user, datum/tgui/ui) + ui = SStgui.try_update_ui(user, src, ui) + if(!ui) + var/datum/asset/assets = get_asset_datum(/datum/asset/spritesheet/rcd) + assets.send(user) + ui = new(user, src, "RapidConstructionDevice", name) + ui.open() + +/obj/item/construction/rcd/ui_static_data(mob/user) + return airlock_electronics.ui_static_data(user) + +/obj/item/construction/rcd/ui_assets(mob/user) + return list( + get_asset_datum(/datum/asset/spritesheet/rcd), ) - if(upgrade & RCD_UPGRADE_FRAMES) - choices += list( - "Machine Frames" = image(icon = 'icons/mob/radial.dmi', icon_state = "machine"), - "Computer Frames" = image(icon = 'icons/mob/radial.dmi', icon_state = "computer_dir"), - ) - if(upgrade & RCD_UPGRADE_SILO_LINK) - choices += list( - "Silo Link" = image(icon = 'icons/obj/mining.dmi', icon_state = "silo"), - ) - if(upgrade & RCD_UPGRADE_FURNISHING) - choices += list( - "Furnishing" = image(icon = 'icons/mob/radial.dmi', icon_state = "chair") - ) - if(mode == RCD_AIRLOCK) - choices += list( - "Change Access" = image(icon = 'icons/mob/radial.dmi', icon_state = "access"), - "Change Airlock Type" = image(icon = 'icons/mob/radial.dmi', icon_state = "airlocktype") - ) - else if(mode == RCD_WINDOWGRILLE) - choices += list( - "Change Window Glass" = image(icon = 'icons/mob/radial.dmi', icon_state = "windowtype"), - "Change Window Size" = image(icon = 'icons/mob/radial.dmi', icon_state = "windowsize") - ) - else if(mode == RCD_FURNISHING) - choices += list( - "Change Furnishing Type" = image(icon = 'icons/mob/radial.dmi', icon_state = "chair") - ) - if(upgrade & RCD_UPGRADE_CONVEYORS) - choices += list( - "Conveyor" = image(icon = 'icons/obj/recycling.dmi', icon_state = "conveyor_construct"), - "Switch" = image(icon = 'icons/obj/recycling.dmi', icon_state = "switch-off") - ) - var/choice = show_radial_menu(user, src, choices, custom_check = CALLBACK(src, PROC_REF(check_menu), user), require_near = TRUE, tooltips = TRUE) - if(!check_menu(user)) + +/obj/item/construction/rcd/ui_data(mob/user) + var/list/data = ..() + + //main categories + data["selected_root"] = root_category + data["root_categories"] = list() + for(var/category in root_categories) + data["root_categories"] += category + + //create the category list + data["selected_category"] = design_category + data["selected_design"] = design_title + data["categories"] = list() + + var/category_icon_state + var/category_icon_suffix + for(var/list/sub_category as anything in root_categories[root_category]) + var/list/target_category = root_categories[root_category][sub_category] + if(target_category.len == 0) + continue + + //skip category if upgrades were not installed for these + if(sub_category == "Machines" && !(upgrade & RCD_UPGRADE_FRAMES)) + continue + if(sub_category == "Furniture" && !(upgrade & RCD_UPGRADE_FURNISHING)) + continue + if(sub_category == "Conveyors" && !(upgrade & RCD_UPGRADE_CONVEYORS)) + continue + category_icon_state = "" + category_icon_suffix = "" + + var/list/designs = list() //initialize all designs under this category + for(var/i in 1 to target_category.len) + var/list/design = target_category[i] + + //check for special icon flags + if(design[CATEGORY_ICON_STATE] != null) + category_icon_state = design[CATEGORY_ICON_STATE] + if(design[CATEGORY_ICON_SUFFIX] != null) + category_icon_suffix = design[CATEGORY_ICON_SUFFIX] + + //get icon or create it from pre defined flags + var/icon_state + if(design[ICON] != null) + icon_state = design[ICON] + else + icon_state = category_icon_state + if(icon_state == TITLE_ICON) + icon_state = design[TITLE] + icon_state = "[icon_state][category_icon_suffix]" + + //sanitize them so you dont go insane when icon names contain spaces in them + icon_state = sanitize_css_class_name(icon_state) + + designs += list(list("design_id" = i, TITLE = design[TITLE], ICON = icon_state)) + data["categories"] += list(list("cat_name" = sub_category, "designs" = designs)) + + //merge airlock_electronics ui data with this + var/list/airlock_data = airlock_electronics.ui_data(user) + for(var/key in airlock_data) + data[key] = airlock_data[key] + + return data + + +/obj/item/construction/rcd/ui_act(action, params) + . = ..() + if(.) return - switch(choice) - if("Floors & Walls") - mode = RCD_FLOORWALL - if("Airlock") - mode = RCD_AIRLOCK - if("Deconstruct") - mode = RCD_DECONSTRUCT - if("Grilles & Windows") - mode = RCD_WINDOWGRILLE - if("Machine Frames") - mode = RCD_MACHINE - if("Furnishing") - mode = RCD_FURNISHING - if("Computer Frames") - mode = RCD_COMPUTER - change_computer_dir(user) - return - if("Change Access") - airlock_electronics.ui_interact(user) - return - if("Change Airlock Type") - change_airlock_setting(user) - return - if("Change Window Glass") - toggle_window_glass(user) - return - if("Change Window Size") - toggle_window_size(user) - return - if("Change Furnishing Type") - change_furnishing_type(user) - return - if("Silo Link") - toggle_silo_link(user) - return - if("Conveyor") - mode = RCD_CONVEYOR - linked_switch_id = null - last_placed = null - if("Switch") - mode = RCD_SWITCH - else - return - playsound(src, 'sound/effects/pop.ogg', 50, FALSE) - to_chat(user, span_notice("You change RCD's mode to '[choice]'.")) + + switch(action) + if("root_category") + var/new_root = params["root_category"] + if(root_categories[new_root] != null) //is a valid category + root_category = new_root + + if("design") + var/category_name = params["category"] + var/index = params["index"] + + var/list/root = root_categories[root_category] + if(root == null) //not a valid root + return TRUE + var/list/category = root[category_name] + if(category == null) //not a valid category + return TRUE + var/list/design = category[index] + if(design == null) //not a valid design + return TRUE + + design_category = category_name + design_title = design["title"] + + if(category_name == "Structures") + construction_mode = design[CONSTRUCTION_MODE] + if(design[WINDOW_TYPE] != null) + window_type = design[WINDOW_TYPE] + if(design[WINDOW_GLASS] != null) + window_glass = design[WINDOW_GLASS] + if(design[WINDOW_SIZE] != null) + window_size = design[WINDOW_SIZE] + else if(category_name == "Machines") + construction_mode = design[CONSTRUCTION_MODE] + if(design[COMPUTER_DIR] != null) + computer_dir = design[COMPUTER_DIR] + else if(category_name == "Furniture") + construction_mode = RCD_FURNISHING + furnish_type = design[FURNISH_TYPE] + furnish_cost = design[FURNISH_COST] + furnish_delay = design[FURNISH_DELAY] + else if(category_name == "Conveyors") + construction_mode = design[CONSTRUCTION_MODE] + + if(root_category == "Airlocks") + construction_mode = RCD_AIRLOCK + airlock_glass = (category_name != "Solid AirLocks") + airlock_type = design[AIRLOCK_TYPE] + else + airlock_electronics.do_action(action, params) + + return TRUE + +/obj/item/construction/rcd/attack_self(mob/user) + . = ..() + ui_interact(user) /obj/item/construction/rcd/proc/target_check(atom/A, mob/user) // only returns true for stuff the device can actually work with - if((isturf(A) && A.density && mode==RCD_DECONSTRUCT) || (isturf(A) && !A.density) || (istype(A, /obj/machinery/door/airlock) && mode==RCD_DECONSTRUCT) || istype(A, /obj/structure/grille) || (istype(A, /obj/structure/window) && mode==RCD_DECONSTRUCT) || istype(A, /obj/structure/girder)) + if((isturf(A) && A.density && construction_mode==RCD_DECONSTRUCT) || (isturf(A) && !A.density) || (istype(A, /obj/machinery/door/airlock) && construction_mode==RCD_DECONSTRUCT) || istype(A, /obj/structure/grille) || (istype(A, /obj/structure/window) && construction_mode==RCD_DECONSTRUCT) || istype(A, /obj/structure/girder)) return TRUE else return FALSE /obj/item/construction/rcd/afterattack(atom/A, mob/user, proximity) . = ..() - if (mode == RCD_CONVEYOR) - if(!range_check(A, user) || !target_check(A,user) || istype(A, /obj/machinery/conveyor) || !isopenturf(A) || istype(A, /area/shuttle)) - to_chat(user, "Error! Invalid tile!") - return - if (!linked_switch_id) - to_chat(user, "Error! [src] is not linked!") - return - if (get_turf(A) == get_turf(user)) - to_chat(user, "Cannot place conveyor below your feet!") - return - if(!proximity) - return - rcd_conveyor(A, user) - if (mode == RCD_SWITCH) - if(!range_check(A, user) || !target_check(A,user) || istype(A, /obj/item/conveyor_switch_construct) || !isopenturf(A) || istype(A, /area/shuttle)) - to_chat(user, "Error! Invalid tile!") - return - if(!proximity) - return - rcd_switch(A, user) - else - if(!prox_check(proximity)) - return - rcd_create(A, user) + if(!prox_check(proximity) && !(ranged && range_check(A, user))) + return + if((upgrade & RCD_UPGRADE_CONVEYORS) && istype(A, /obj/machinery/conveyor_switch)) + var/obj/machinery/conveyor_switch/C = A + linked_switch_id = C.id + balloon_alert(user, "linked") + return + rcd_create(A, user) + +/obj/item/construction/rcd/attackby(obj/item/I, mob/user, params) + . = ..() + if((upgrade & RCD_UPGRADE_CONVEYORS) && istype(I, /obj/item/conveyor_switch_construct)) + var/obj/item/conveyor_switch_construct/C = I + linked_switch_id = C.id + balloon_alert(user, "linked") /obj/item/construction/rcd/proc/detonate_pulse() audible_message("[src] begins to vibrate and \ @@ -796,6 +694,23 @@ RLD matter = 500 canRturf = TRUE +#undef CONSTRUCTION_MODE +#undef WINDOW_TYPE +#undef WINDOW_GLASS +#undef WINDOW_SIZE +#undef COMPUTER_DIR +#undef FURNISH_TYPE +#undef FURNISH_COST +#undef FURNISH_DELAY +#undef AIRLOCK_TYPE + +#undef TITLE +#undef ICON + +#undef CATEGORY_ICON_STATE +#undef CATEGORY_ICON_SUFFIX +#undef TITLE_ICON + /obj/item/rcd_ammo name = "compressed matter cartridge" desc = "Highly compressed matter for the RCD." @@ -832,18 +747,43 @@ RLD has_ammobar = FALSE /obj/item/construction/rcd/arcd/afterattack(atom/A, mob/user) - ..() if(!range_check(A,user)) return - if(target_check(A,user)) - user.Beam(A,icon_state="rped_upgrade",time=30) - rcd_create(A,user) - + return ..() +/obj/item/construction/rcd/exosuit + name = "mounted RCD" + desc = "You're not supposed to see this!" + max_matter = 1000 + matter = 0 // starts off empty, load materials into the mech itself + delay_mod = 0.5 + ranged = TRUE + has_ammobar = FALSE // don't bother, you can't see it + item_flags = NO_MAT_REDEMPTION | DROPDEL | NOBLUDGEON + resistance_flags = INDESTRUCTIBLE | FIRE_PROOF | ACID_PROOF | UNACIDABLE // would be weird if it could somehow be destroyed inside the equipment item + +/obj/item/construction/rcd/exosuit/ui_state(mob/user) + return GLOB.pilot_state + +/obj/item/construction/rcd/exosuit/ui_status(mob/user) + if(!(owner && ismecha(owner))) + return UI_CLOSE + var/obj/mecha/gundam = owner + if(user != gundam.occupant) + return UI_CLOSE + if(!gundam.equipment_disabled && gundam.selected == loc) + return UI_INTERACTIVE + return UI_UPDATE + +/obj/item/construction/rcd/exosuit/mime + name = "silenced mounted RCD" + silent = TRUE // RAPID LIGHTING DEVICE - +#define GLOW_MODE 3 +#define LIGHT_MODE 2 +#define REMOVE_MODE 1 /obj/item/construction/rld name = "Rapid Lighting Device (RLD)" @@ -854,10 +794,12 @@ RLD righthand_file = 'icons/mob/inhands/equipment/tools_righthand.dmi' matter = 200 max_matter = 200 + slot_flags = ITEM_SLOT_BELT + ///it does not make sense why any of these should be installed + banned_upgrades = RCD_UPGRADE_FRAMES | RCD_UPGRADE_SIMPLE_CIRCUITS | RCD_UPGRADE_FURNISHING + var/matter_divisor = 35 var/mode = LIGHT_MODE - slot_flags = ITEM_SLOT_BELT - actions_types = list(/datum/action/item_action/pick_color) var/wallcost = 10 var/floorcost = 15 @@ -868,35 +810,62 @@ RLD var/floordelay = 10 var/decondelay = 15 -/obj/item/construction/rld/ui_action_click(mob/user, datum/action/A) - if(istype(A, /datum/action/item_action/pick_color)) - color_choice = input(user,"","Choose Color",color_choice) as color - else - ..() + ///reference to thr original icons + var/list/original_options = list( + "Color Pick" = icon(icon = 'icons/mob/radial.dmi', icon_state = "omni"), + "Glow Stick" = icon(icon = 'icons/obj/lighting.dmi', icon_state = "glowstick"), + "Deconstruct" = icon(icon = 'icons/obj/tools.dmi', icon_state = "wrench"), + "Light Fixture" = icon(icon = 'icons/obj/lighting.dmi', icon_state = "ltube"), + ) + ///will contain the original icons modified with the color choice + var/list/display_options = list() + +/obj/item/construction/rld/Initialize(mapload) + . = ..() + for(var/option in original_options) + display_options[option] = icon(original_options[option]) /obj/item/construction/rld/update_icon_state() . = ..() icon_state = "rld-[round(matter/35)]" /obj/item/construction/rld/attack_self(mob/user) - ..() - switch(mode) - if(REMOVE_MODE) + . = ..() + + if((upgrade & RCD_UPGRADE_SILO_LINK) && display_options["Silo Link"] == null) //silo upgrade instaled but option was not updated then update it just one + display_options["Silo Link"] = icon(icon = 'icons/obj/mining.dmi', icon_state = "silo") + var/choice = show_radial_menu(user, src, display_options, custom_check = CALLBACK(src, PROC_REF(check_menu), user), require_near = TRUE, tooltips = TRUE) + if(!check_menu(user)) + return + if(!choice) + return + + switch(choice) + if("Light Fixture") mode = LIGHT_MODE to_chat(user, span_notice("You change RLD's mode to 'Permanent Light Construction'.")) - if(LIGHT_MODE) + if("Glow Stick") mode = GLOW_MODE to_chat(user, span_notice("You change RLD's mode to 'Light Launcher'.")) - if(GLOW_MODE) + if("Color Pick") + var/new_choice = input(user,"","Choose Color",color_choice) as color + if(new_choice == null) + return + + var/list/new_rgb = ReadRGB(new_choice) + for(var/option in original_options) + if(option == "Color Pick" || option == "Deconstruct" || option == "Silo Link") + continue + var/icon/icon = icon(original_options[option]) + icon.SetIntensity(new_rgb[1]/255, new_rgb[2]/255, new_rgb[3]/255) //apply new scale + display_options[option] = icon + + color_choice = new_choice + if("Deconstruct") mode = REMOVE_MODE to_chat(user, span_notice("You change RLD's mode to 'Deconstruct'.")) - -/obj/item/construction/rcd/attackby(obj/item/I, mob/user, params) - ..() - if(upgrade & RCD_UPGRADE_CONVEYORS && istype(I, /obj/item/conveyor_switch_construct)) - to_chat(user, "You link the switch to the [src].") - var/obj/item/conveyor_switch_construct/C = I - linked_switch_id = C.id + else + ui_act("toggle_silo", list()) /obj/item/construction/rld/proc/checkdupes(target) . = list() @@ -917,7 +886,8 @@ RLD if(checkResource(deconcost, user)) to_chat(user, span_notice("You start deconstructing [A]...")) user.Beam(A,icon_state="nzcrentrs_power",time=15) - playsound(src.loc, 'sound/machines/click.ogg', 50, TRUE) + if(!silent) + playsound(src.loc, 'sound/machines/click.ogg', 50, TRUE) if(do_after(user, decondelay, A)) if(!useResource(deconcost, user)) return FALSE @@ -931,8 +901,9 @@ RLD if(checkResource(floorcost, user)) to_chat(user, span_notice("You start building a wall light...")) user.Beam(A,icon_state="nzcrentrs_power",time=15) - playsound(src.loc, 'sound/machines/click.ogg', 50, TRUE) - playsound(src.loc, 'sound/effects/light_flicker.ogg', 50, FALSE) + if(!silent) + playsound(src.loc, 'sound/machines/click.ogg', 50, TRUE) + playsound(src.loc, 'sound/effects/light_flicker.ogg', 50, FALSE) if(do_after(user, floordelay, A)) if(!istype(W)) return FALSE @@ -946,7 +917,8 @@ RLD candidates += C if(!candidates.len) to_chat(user, span_warning("Valid target not found...")) - playsound(src.loc, 'sound/misc/compiler-failure.ogg', 30, TRUE) + if(!silent) + playsound(src.loc, 'sound/misc/compiler-failure.ogg', 30, TRUE) return FALSE for(var/turf/open/O in candidates) if(istype(O)) @@ -977,8 +949,9 @@ RLD if(checkResource(floorcost, user)) to_chat(user, span_notice("You start building a floor light...")) user.Beam(A,icon_state="light_beam",time=15) - playsound(src.loc, 'sound/machines/click.ogg', 50, TRUE) - playsound(src.loc, 'sound/effects/light_flicker.ogg', 50, TRUE) + if(!silent) + playsound(src.loc, 'sound/machines/click.ogg', 50, TRUE) + playsound(src.loc, 'sound/effects/light_flicker.ogg', 50, TRUE) if(do_after(user, floordelay, A)) if(!istype(F)) return 0 diff --git a/code/game/objects/items/RPD.dm b/code/game/objects/items/RPD.dm index a58fe204b090..12d3e9973540 100644 --- a/code/game/objects/items/RPD.dm +++ b/code/game/objects/items/RPD.dm @@ -241,6 +241,8 @@ GLOBAL_LIST_INIT(fluid_duct_recipes, list( var/static/datum/pipe_info/first_plumbing var/mode = BUILD_MODE | PAINT_MODE | DESTROY_MODE | WRENCH_MODE var/locked = FALSE //wheter we can change categories. Useful for the plumber + /// The owner of this RCD. It can be a mech or a player. + var/owner /obj/item/pipe_dispenser/Initialize(mapload) . = ..() @@ -287,6 +289,9 @@ GLOBAL_LIST_INIT(fluid_duct_recipes, list( get_asset_datum(/datum/asset/spritesheet/pipes), ) +/obj/item/pipe_dispenser/ui_host(mob/user) + return owner || ..() + /obj/item/pipe_dispenser/ui_interact(mob/user, datum/tgui/ui) ui = SStgui.try_update_ui(user, src, ui) if(!ui) @@ -306,7 +311,7 @@ GLOBAL_LIST_INIT(fluid_duct_recipes, list( "selected_color" = paint_color, "paint_colors" = GLOB.pipe_paint_colors, "mode" = mode, - "locked" = locked + "locked" = locked, ) var/list/recipes @@ -330,10 +335,10 @@ GLOBAL_LIST_INIT(fluid_duct_recipes, list( return data /obj/item/pipe_dispenser/ui_act(action, params) - if(..()) - return - if(!usr.canUseTopic(src, BE_CLOSE)) + . = ..() + if(.) return + var/playeffect = TRUE switch(action) if("color") @@ -568,6 +573,24 @@ GLOBAL_LIST_INIT(fluid_duct_recipes, list( return to_chat(source, span_notice("You set the layer to [piping_layer].")) +/obj/item/pipe_dispenser/exosuit + name = "mounted pipe dispenser" + desc = "You shouldn't be seeing this!" + item_flags = NO_MAT_REDEMPTION | DROPDEL | NOBLUDGEON + resistance_flags = INDESTRUCTIBLE | FIRE_PROOF | ACID_PROOF | UNACIDABLE // would be weird if it could somehow be destroyed inside the equipment item + +/obj/item/pipe_dispenser/exosuit/ui_state(mob/user) + return GLOB.pilot_state + +// don't allow using this thing unless you're piloting the mech it's attached to +/obj/item/pipe_dispenser/exosuit/can_interact(mob/user) + if(!(owner && ismecha(owner))) + return FALSE + var/obj/mecha/gundam = owner + if(user == gundam.occupant && !gundam.equipment_disabled && gundam.selected == loc) + return TRUE + return FALSE + /obj/item/pipe_dispenser/plumbing name = "Plumberinator" desc = "A crude device to rapidly plumb things." diff --git a/code/game/objects/items/bell.dm b/code/game/objects/items/bell.dm index 7bb200f82249..f3b1b1d30467 100644 --- a/code/game/objects/items/bell.dm +++ b/code/game/objects/items/bell.dm @@ -1,6 +1,6 @@ /obj/item/deskbell name = "desk bell" - desc = "ding. ding." + desc = "Ding! Ding! Ding!" icon = 'icons/obj/bell.dmi' icon_state = "bell" force = 5 diff --git a/code/game/objects/items/devices/busterarm/busterharpoon.dm b/code/game/objects/items/devices/busterarm/busterharpoon.dm new file mode 100644 index 000000000000..31a2a43f6ba6 --- /dev/null +++ b/code/game/objects/items/devices/busterarm/busterharpoon.dm @@ -0,0 +1,108 @@ +/datum/action/cooldown/buster/megabuster/megaharpoon + name = "gasharpoon" + desc = "Charge up your harpoon and ready it to be fired, if it makes contact with a person it will drag them to you and immobilize them." + cooldown_time = 10 SECONDS + button_icon_state = "harpoonhead" + + +/obj/item/gun/magic/wire/harpoon + name = "Harpoon Head" + desc = "A harpoon head made of pure plasteel, hits like a freighter." + ammo_type = /obj/item/ammo_casing/magic/wire/harpoon + icon_state = "gasharpoon" + item_state = "chain" + lefthand_file = 'icons/mob/inhands/weapons/melee_lefthand.dmi' + righthand_file = 'icons/mob/inhands/weapons/melee_righthand.dmi' + fire_sound = 'sound/weapons/batonextend.ogg' + max_charges = 1 + item_flags = NEEDS_PERMIT | DROPDEL + force = 0 + can_charge = FALSE + +/obj/item/ammo_casing/magic/wire/harpoon + name = "harpoon" + desc = "A harpoon." + projectile_type = /obj/projectile/wire/harpoon + caliber = CALIBER_HOOK + icon_state = "harpoonhead" + +/obj/projectile/wire/harpoon/fire(setAngle) + if(firer) + wire = firer.Beam(src, icon_state = "harpoonrope", time = INFINITY, maxdistance = INFINITY) + ..() + +/obj/projectile/wire/harpoon + name = "harpoon" + icon_state = "harpoonhead" + icon = 'icons/obj/lavaland/artefacts.dmi' + pass_flags = PASSTABLE + damage = 10 + armour_penetration = 100 + damage_type = BRUTE + nodamage = TRUE + range = 8 + hitsound = 'sound/effects/splat.ogg' + immobilize = 1 SECONDS + +/obj/projectile/wire/harpoon/on_hit(atom/target) + var/mob/living/L = target + var/mob/living/carbon/human/H = firer + if(!L) + return + L.apply_status_effect(STATUS_EFFECT_EXPOSED_HARPOONED) + if(isobj(target)) // If it's an object + var/obj/item/I = target + if(!I?.anchored) // Give it to us if it's not anchored + I.throw_at(get_step_towards(H,I), 8, 2) + H.visible_message(span_danger("[I] is pulled by [H]'s harpoon!")) + if(istype(I, /obj/item/clothing/head)) + H.equip_to_slot_if_possible(I, ITEM_SLOT_HEAD) + H.visible_message(span_danger("[H] pulls [I] onto [H.p_their()] head!")) + else + H.put_in_hands(I) + return + zip(H, target) // Pull us towards it if it's anchored + if(isliving(target)) // If it's somebody + H.swap_hand(0) //for the sake of throttling people you catch + var/turf/T = get_step(get_turf(H), H.dir) + var/turf/Q = get_turf(H) + var/obj/item/bodypart/limb_to_hit = L.get_bodypart(H.zone_selected) + var/armor = L.run_armor_check(limb_to_hit, MELEE, armour_penetration = 35) + if(!L.anchored) // Only pull them if they're unanchored + if(istype(H)) + L.visible_message(span_danger("[L] is pulled by [H]'s harpoon!"),span_userdanger("A harpoon pierces you and pulls you towards [H]!")) + L.Immobilize(1.0 SECONDS) + if(T.density) // If we happen to be facing a wall after the wire snatches them + to_chat(H, span_warning("[H] catches [L] and throws [L.p_them()] against [T]!")) + to_chat(L, span_userdanger("[H] crushes you against [T]!")) + playsound(L,'sound/effects/pop_expl.ogg', 130, 1) + L.apply_damage(15, BRUTE, limb_to_hit, armor, wound_bonus=CANT_WOUND) + L.forceMove(Q) + return + // If we happen to be facing a dense object after the wire snatches them, like a table or window + for(var/obj/D in T.contents) + if(D.density == TRUE) + D.take_damage(50) + L.apply_damage(15, BRUTE, limb_to_hit, armor, wound_bonus=CANT_WOUND) + L.forceMove(Q) + to_chat(H, span_warning("[H] catches [L] throws [L.p_them()] against [D]!")) + playsound(L,'sound/effects/pop_expl.ogg', 20, 1) + return + L.forceMove(T) + if(iswallturf(target)) // If we hit a wall, pull us to it + var/turf/W = target + zip(H, W) + +/// Left buster-arm means megabuster goes in left hand -- I stole this from megabuster! -- cowbot93 +/datum/action/cooldown/buster/megabuster/megaharpoon/l/Activate() + var/obj/item/gun/magic/wire/harpoon/B = new() + owner.visible_message(span_userdanger("[owner]'s arm lets out a harrowing sound!")) + playsound(owner,'sound/weapons/bladeslice.ogg', 60, 1) + if(do_after(owner, 2 SECONDS, owner, timed_action_flags = IGNORE_USER_LOC_CHANGE)) + if(!owner.put_in_l_hand(B)) + to_chat(owner, span_warning("You can't do this with your left hand full!")) + else + owner.visible_message(span_danger("[owner]'s readies the harpoon to fire!")) + if(owner.active_hand_index % 2 == 0) + owner.swap_hand(0) + StartCooldown() diff --git a/code/game/objects/items/devices/busterarm/gasharpoon.dm b/code/game/objects/items/devices/busterarm/gasharpoon.dm new file mode 100644 index 000000000000..2889422101a0 --- /dev/null +++ b/code/game/objects/items/devices/busterarm/gasharpoon.dm @@ -0,0 +1,59 @@ +/obj/item/clothing/gloves/gasharpoon + name = "gasharpoon" + desc = "A metal gauntlet with a harpoon attatched, powered by gasoline and traditionally used by space-whalers." + ///reminder to channge all this -- I changed it :) + icon = 'icons/obj/traitor.dmi' + icon_state = "gasharpoon" + item_state = "gasharpoon" + lefthand_file = 'icons/mob/inhands/weapons/melee_lefthand.dmi' + righthand_file = 'icons/mob/inhands/weapons/melee_righthand.dmi' + attack_verb = list("harpooned", "gouged", "pierced") + force = 10 + throwforce = 10 + throw_range = 7 + strip_delay = 15 SECONDS + cold_protection = HANDS + heat_protection = HANDS + w_class = WEIGHT_CLASS_NORMAL + armor = list(MELEE = 0, BULLET = 0, LASER = 0, ENERGY = 0, BOMB = 0, BIO = 0, RAD = 0, FIRE = 100, ACID = 100, ELECTRIC = 100) + resistance_flags = FIRE_PROOF | ACID_PROOF + var/click_delay = 1.5 + + +/obj/item/clothing/gloves/gasharpoon/equipped(mob/user, slot) + . = ..() + if(slot & ITEM_SLOT_GLOVES) + RegisterSignal(user, COMSIG_HUMAN_EARLY_UNARMED_ATTACK, PROC_REF(power_harpoon)) + var/datum/action/cooldown/buster/megabuster/megaharpoon/l/harpoon = new(user) + harpoon.Grant(user) + +/obj/item/clothing/gloves/gasharpoon/dropped(mob/user) + . = ..() + if(user.get_item_by_slot(ITEM_SLOT_GLOVES)==src) + UnregisterSignal(user, COMSIG_HUMAN_EARLY_UNARMED_ATTACK) + var/datum/action/cooldown/buster/megabuster/megaharpoon/l/harpoon = locate(/datum/action/cooldown/buster/megabuster/megaharpoon/l) in user.actions + if(harpoon) + harpoon.Remove(user) + return ..() + + +/obj/item/clothing/gloves/gasharpoon/proc/power_harpoon(mob/living/user, atom/movable/target) + if(!user || user.a_intent!=INTENT_HARM || (!isliving(target) && !isobj(target)) || isitem(target)) + return + do_attack(user, target, force * 2) + playsound(loc, 'sound/weapons/bladeslice.ogg', 50, 1) + target.visible_message(span_danger("[user]'s gasharpoon pierces through [target.name]!")) + return COMPONENT_NO_ATTACK_HAND + +/obj/item/clothing/gloves/gasharpoon/attack(mob/living/target, mob/living/user) + power_harpoon(user, target) + +/obj/item/clothing/gloves/gasharpoon/proc/do_attack(mob/living/user, atom/target, punch_force) + if(isliving(target)) + var/mob/living/target_mob = target + target_mob.apply_damage(punch_force, BRUTE, wound_bonus = 30) + else if(isobj(target)) + var/obj/target_obj = target + target_obj.take_damage(punch_force, BRUTE, MELEE, FALSE) + user.do_attack_animation(target, ATTACK_EFFECT_SLASH) + user.changeNext_move(CLICK_CD_MELEE * click_delay) diff --git a/code/game/objects/items/flamethrower.dm b/code/game/objects/items/flamethrower.dm index d7d7cf9ef2fc..0792c4085680 100644 --- a/code/game/objects/items/flamethrower.dm +++ b/code/game/objects/items/flamethrower.dm @@ -1,3 +1,6 @@ +/// How many joules of energy from reactions required to cause 1 damage +#define JOULES_PER_DAMAGE 100000 + /obj/item/flamethrower name = "flamethrower" desc = "You are a firestarter!" @@ -54,7 +57,7 @@ if(M.is_holding(src)) location = M.loc if(isturf(location)) //start a fire if possible - igniter.flamethrower_process(location) + open_flame(igniter.heat) /obj/item/flamethrower/update_overlays() @@ -199,33 +202,21 @@ if(!istype(target)) return FALSE - var/ratio_removed = 1 - if(!release_all) - ratio_removed = min(ptank.distribute_pressure, ptank.air_contents.return_pressure()) / ptank.air_contents.return_pressure() + var/ratio_removed = min(ptank.distribute_pressure, ptank.air_contents.return_pressure()) / ptank.air_contents.return_pressure() + var/datum/gas_mixture/fuel_mix = ptank.air_contents.remove_ratio(ratio_removed) + var/datum/gas_mixture/turf_mix = target.return_air() + + fuel_mix.merge(turf_mix.copy()) // copy air from the turf to do reactions with + fuel_mix.set_temperature(igniter.heat) // heat the contents + + var/old_thermal_energy = fuel_mix.thermal_energy() + for(var/i in 1 to 10) // react a bunch of times on the target turf + if(!fuel_mix.react(target)) + break // break the loop if it stops reacting - // Return of the stimball flamethrower, wear radiation protection when using this or you're just as likely to die as your target - if(fuel_mix.get_moles(GAS_PLASMA) >= NITRO_BALL_MOLES_REQUIRED && fuel_mix.get_moles(GAS_NITRIUM) >= NITRO_BALL_MOLES_REQUIRED && fuel_mix.get_moles(GAS_PLUOXIUM) >= NITRO_BALL_MOLES_REQUIRED) - var/balls_shot = round(min(fuel_mix.get_moles(GAS_NITRIUM), fuel_mix.get_moles(GAS_PLUOXIUM), NITRO_BALL_MAX_REACT_RATE / NITRO_BALL_MOLES_REQUIRED)) - var/angular_increment = 360/balls_shot - var/random_starting_angle = rand(0,360) - for(var/i in 1 to balls_shot) - target.fire_nuclear_particle((i*angular_increment+random_starting_angle)) - fuel_mix.adjust_moles(GAS_PLASMA, -balls_shot * NITRO_BALL_MOLES_REQUIRED) // No free extra damage for you, conservation of mass go brrrrr - - // Funny rad flamethrower go brrr - if(fuel_mix.get_moles(GAS_TRITIUM)) // Tritium fires cause a bit of radiation - radiation_pulse(target, min(fuel_mix.get_moles(GAS_TRITIUM), fuel_mix.get_moles(GAS_O2)/2) * FIRE_HYDROGEN_ENERGY_RELEASED / TRITIUM_BURN_RADIOACTIVITY_FACTOR) - - // 8 damage at 0.5 mole transfer or ~17 kPa release pressure - // 16 damage at 1 mole transfer or ~35 kPa release pressure - var/damage = fuel_mix.get_moles(GAS_PLASMA) * 16 - // harder to achieve than plasma - damage += fuel_mix.get_moles(GAS_TRITIUM) * 24 // Lower damage than hydrogen, causes minor radiation - damage += fuel_mix.get_moles(GAS_H2) * 32 - // Maximum damage restricted by the available oxygen, with a hard cap at 16 - var/datum/gas_mixture/turf_air = target.return_air() - damage = min(damage, turf_air.get_moles(GAS_O2) + fuel_mix.get_moles(GAS_O2), max_damage) // capped by combined oxygen in the fuel mix and enviroment + // damage is based on the positive or negative energy of the reaction, with a cap + var/damage = min(abs(fuel_mix.thermal_energy() - old_thermal_energy) / JOULES_PER_DAMAGE, max_damage) // If there's not enough fuel and/or oxygen to do more than 1 damage, shut itself off if(damage < 1) @@ -251,22 +242,40 @@ for(var/turf/T in turflist) if(T == previousturf) continue //so we don't burn the tile we be standin on - for(var/obj/structure/blob/B in T) + var/cached_damage = 0 + + for(var/obj/structure/blob/blob in T) // This is run before atmos checks because blob can be atmos blocking but we still want to hit them // See /proc/default_ignite - var/damage = process_fuel(T) - if(!damage) - break // Out of gas, stop running pointlessly - B.take_damage(damage * 2, BURN, FIRE) // strong against blobs + if(!cached_damage) + cached_damage = process_fuel(T) + if(!lit) + break // stopped running, don't continue + if(QDELETED(blob)) + continue + blob.take_damage(cached_damage * 2, BURN, FIRE) // strong against blobs + + for(var/obj/structure/spacevine/vine in T) + // This is run before atmos checks because vines can be on top of a window or some other atmos-blocking structure + if(!cached_damage) + cached_damage = process_fuel(T) + if(!lit) + break // stopped running, don't continue + if(QDELETED(vine)) + continue + vine.take_damage(cached_damage * 3, BURN, FIRE, TRUE) // very strong against vines + var/list/turfs_sharing_with_prev = previousturf.GetAtmosAdjacentTurfs(alldir=1) if(!(T in turfs_sharing_with_prev)) break // Hit something that blocks atmos - if(igniter) - if(!igniter.ignite_turf(src,T)) - break // Out of gas, stop running pointlessly - else - if(!default_ignite(T)) - break // Out of gas, stop running pointlessly + + if(!cached_damage) + cached_damage = process_fuel(T) + if(!lit) + break // stopped running, don't continue + if(!burn_atoms_on_turf(T, cached_damage)) + break // Out of gas, stop running pointlessly + if(!sound_played) // play the sound once if we successfully ignite at least one thing sound_played = TRUE playsound(loc, pick(flame_sounds), 50, TRUE) @@ -281,10 +290,9 @@ // /obj/structure/blob/normal // Return value tells the parent whether to continue calculating the line -/obj/item/flamethrower/proc/default_ignite(turf/target, release_all = FALSE) - // do the fuel stuff - var/damage = process_fuel(target, release_all) - if(!damage) +/obj/item/flamethrower/proc/burn_atoms_on_turf(turf/target, damage) + // no damage? don't continue + if(damage <= 0) return FALSE //Burn it @@ -333,24 +341,17 @@ var/obj/projectile/P = hitby if(damage && attack_type == PROJECTILE_ATTACK && P.damage_type != STAMINA && prob(5)) owner.visible_message(span_danger("\The [attack_text] hits the fueltank on [owner]'s [name], rupturing it! What a shot!")) - var/target_turf = get_turf(owner) - igniter.ignite_turf(src,target_turf, release_all = TRUE) - qdel(ptank) - return 1 //It hit the flamethrower, not them - - -/obj/item/assembly/igniter/proc/flamethrower_process(turf/open/location) - location.hotspot_expose(700,2) - -/obj/item/assembly/igniter/proc/ignite_turf(obj/item/flamethrower/F, turf/open/location, release_all = FALSE) - return F.default_ignite(location, release_all) + var/turf/target_turf = get_turf(owner) + burn_atoms_on_turf(target_turf, process_fuel(target_turf)) + return TRUE //It hit the flamethrower, not them + return ..() ///////////////////// Flamethrower as an energy weapon ///////////////////// // Currently used exclusively in /obj/item/gun/energy/printer/flamethrower /obj/item/ammo_casing/energy/flamethrower projectile_type = /obj/projectile/bullet/incendiary/flamethrower select_name = "fire" - fire_sound = null + fire_sound = 'sound/weapons/flamethrower1.ogg' firing_effect_type = null e_cost = 50 @@ -361,3 +362,5 @@ sharpness = SHARP_NONE range = 6 penetration_flags = PENETRATE_OBJECTS | PENETRATE_MOBS + +#undef JOULES_PER_DAMAGE diff --git a/code/game/objects/items/grenades/chem_grenade.dm b/code/game/objects/items/grenades/chem_grenade.dm index 2423c687ef52..477af55a02f6 100644 --- a/code/game/objects/items/grenades/chem_grenade.dm +++ b/code/game/objects/items/grenades/chem_grenade.dm @@ -342,7 +342,7 @@ /obj/item/grenade/chem_grenade/radiation name = "Rad Bomb" - desc = "the best grenade to irridiate the fuck out of someone" + desc = "The best grenade to irradiate the fuck out of someone." stage = GRENADE_READY /obj/item/grenade/chem_grenade/radiation/Initialize(mapload) diff --git a/code/game/objects/items/handcuffs.dm b/code/game/objects/items/handcuffs.dm index c14723dd7e6c..18824aa5da65 100644 --- a/code/game/objects/items/handcuffs.dm +++ b/code/game/objects/items/handcuffs.dm @@ -268,7 +268,11 @@ /obj/item/restraints/legcuffs/beartrap/Initialize(mapload) . = ..() - update_appearance(UPDATE_ICON) + update_appearance() + var/static/list/loc_connections = list( + COMSIG_ATOM_ENTERED = PROC_REF(trap_stepped_on), + ) + AddElement(/datum/element/connect_loc, loc_connections) /obj/item/restraints/legcuffs/beartrap/update_icon_state() . = ..() @@ -310,6 +314,55 @@ update_appearance(UPDATE_ICON) playsound(src, 'sound/effects/snap.ogg', 50, TRUE) +/obj/item/restraints/legcuffs/beartrap/proc/trap_stepped_on(datum/source, atom/movable/entering, ...) + SIGNAL_HANDLER + + spring_trap(entering) + +/** + * Tries to spring the trap on the target movable. + * + * This proc is safe to call without knowing if the target is valid or if the trap is armed. + * + * Does not trigger on tiny mobs. + * If ignore_movetypes is FALSE, does not trigger on floating / flying / etc. mobs. + */ +/obj/item/restraints/legcuffs/beartrap/proc/spring_trap(atom/movable/target, ignore_movetypes = FALSE) + if(!armed || !isturf(loc) || !isliving(target)) + return + + var/mob/living/victim = target + if(istype(victim.buckled, /obj/vehicle)) + var/obj/vehicle/ridden_vehicle = victim.buckled + if(!ridden_vehicle.are_legs_exposed) //close the trap without injuring/trapping the rider if their legs are inside the vehicle at all times. + close_trap() + ridden_vehicle.visible_message(span_danger("[ridden_vehicle] triggers \the [src].")) + return + + //don't close the trap if they're as small as a mouse + if(victim.mob_size <= MOB_SIZE_TINY) + return + if(!ignore_movetypes && (victim.movement_type & MOVETYPES_NOT_TOUCHING_GROUND)) + return + + close_trap() + if(ignore_movetypes) + victim.visible_message(span_danger("\The [src] ensnares [victim]!"), \ + span_userdanger("\The [src] ensnares you!")) + else + victim.visible_message(span_danger("[victim] triggers \the [src]."), \ + span_userdanger("You trigger \the [src]!")) + var/def_zone = BODY_ZONE_CHEST + if(iscarbon(victim) && victim.body_position == STANDING_UP) + var/mob/living/carbon/carbon_victim = victim + def_zone = pick(BODY_ZONE_L_LEG, BODY_ZONE_R_LEG) + if(!carbon_victim.legcuffed && carbon_victim.num_legs >= 2) //beartrap can't cuff your leg if there's already a beartrap or legcuffs, or you don't have two legs. + INVOKE_ASYNC(carbon_victim, TYPE_PROC_REF(/mob/living/carbon, equip_to_slot), src, ITEM_SLOT_LEGCUFFED) + SSblackbox.record_feedback("tally", "handcuffs", 1, type) + + victim.apply_damage(trap_damage, BRUTE, def_zone) + + /obj/item/restraints/legcuffs/beartrap/Crossed(AM as mob|obj) if(armed && isturf(loc)) if(isliving(AM)) diff --git a/code/game/objects/items/manuals.dm b/code/game/objects/items/manuals.dm index 0b41e021e48e..b5f37de5e195 100644 --- a/code/game/objects/items/manuals.dm +++ b/code/game/objects/items/manuals.dm @@ -10,7 +10,7 @@ /obj/item/book/manual/ripley_build_and_repair name = "APLU \"Ripley\" Construction and Operation Manual" icon_state ="book" - author = "Weyland-Yutani Corp" + author = "Sano-Waltfield Industries" title = "APLU \"Ripley\" Construction and Operation Manual" dat = {" @@ -24,7 +24,7 @@
- Weyland-Yutani - Building Better Worlds + Sano-Waltfield - Forging Better Futures

Autonomous Power Loader Unit \"Ripley\"

Specifications:

diff --git a/code/game/objects/items/stacks/license_plates.dm b/code/game/objects/items/stacks/license_plates.dm index ece53770f9fa..92f7edc922ee 100644 --- a/code/game/objects/items/stacks/license_plates.dm +++ b/code/game/objects/items/stacks/license_plates.dm @@ -1,6 +1,6 @@ /obj/item/stack/license_plates name = "invalid plate" - desc = "someone fucked up" + desc = "Someone fucked up." icon = 'icons/obj/machines/prison.dmi' icon_state = "empty_plate" novariants = FALSE diff --git a/code/game/objects/items/stunbaton.dm b/code/game/objects/items/stunbaton.dm index d7b7421bf7b5..a02293e02c5a 100644 --- a/code/game/objects/items/stunbaton.dm +++ b/code/game/objects/items/stunbaton.dm @@ -33,6 +33,17 @@ var/preload_cell_type ///used for passive discharge var/cell_last_used = 0 + light_range = 1.5 + light_system = MOVABLE_LIGHT + light_on = FALSE + light_color = LIGHT_COLOR_ORANGE + light_power = 0.5 + +/// Toggles the stun baton's light +/obj/item/melee/baton/proc/toggle_light(mob/user) + set_light_on(!light_on) + return + /obj/item/melee/baton/get_cell() return cell @@ -76,6 +87,7 @@ if(status && cell.charge < hitcost) //we're below minimum, turn off status = FALSE + set_light_on(FALSE) update_appearance(UPDATE_ICON) playsound(loc, "sparks", 75, 1, -1) STOP_PROCESSING(SSobj, src) // no more charge? stop checking for discharge @@ -135,6 +147,8 @@ status = !status to_chat(user, span_notice("[src] is now [status ? "on" : "off"].")) playsound(loc, "sparks", 75, 1, -1) + toggle_light(user) + do_sparks(1, TRUE, src) cell_last_used = 0 if(status) START_PROCESSING(SSobj, src) @@ -306,3 +320,5 @@ desc = "A new power management circuit which enables stun batons to instantly stun, at the cost of double power usage." icon = 'icons/obj/module.dmi' icon_state = "cyborg_upgrade3" + + diff --git a/code/game/objects/items/toys.dm b/code/game/objects/items/toys.dm index 3a3da7c3be55..9cfe1022c7ac 100644 --- a/code/game/objects/items/toys.dm +++ b/code/game/objects/items/toys.dm @@ -456,6 +456,14 @@ w_class = WEIGHT_CLASS_TINY var/ash_type = /obj/effect/decal/cleanable/ash +/obj/item/toy/snappop/Initialize(mapload) + . = ..() + var/static/list/loc_connections = list( + COMSIG_ATOM_ENTERED = PROC_REF(on_entered), + ) + AddElement(/datum/element/connect_loc, loc_connections) + + /obj/item/toy/snappop/proc/pop_burst(n=3, c=1) var/datum/effect_system/spark_spread/s = new() s.set_up(n, c, src) @@ -473,8 +481,7 @@ if(!..()) pop_burst() -/obj/item/toy/snappop/Crossed(H as mob|obj) - . = ..() +/obj/item/toy/snappop/proc/on_entered(datum/source, atom/movable/H, ...) if(ishuman(H) || issilicon(H)) //i guess carp and shit shouldn't set them off var/mob/living/carbon/M = H if(issilicon(H) || M.m_intent == MOVE_INTENT_RUN) diff --git a/code/game/objects/items/trash.dm b/code/game/objects/items/trash.dm index 48f8af00a690..ddcdb6ba0bf0 100644 --- a/code/game/objects/items/trash.dm +++ b/code/game/objects/items/trash.dm @@ -46,7 +46,7 @@ /obj/item/trash/plate name = "plate" - desc = "a relic from a forgotten time... I miss eating off of plates..." + desc = "A relic from a forgotten time... I miss eating off of plates..." icon_state = "plate" resistance_flags = NONE diff --git a/code/game/objects/items/weaponry.dm b/code/game/objects/items/weaponry.dm index 9fd276f6ef92..cefc64e51f50 100644 --- a/code/game/objects/items/weaponry.dm +++ b/code/game/objects/items/weaponry.dm @@ -261,7 +261,7 @@ for further reading, please see: https://github.com/tgstation/tgstation/pull/301 /obj/item/katana/basalt name = "basalt katana" - desc = "a katana made out of hardened basalt. Particularly damaging to lavaland fauna. (Activate this item in hand to dodge roll in the direction you're facing)" + desc = "A katana made of hardened basalt. Particularly damaging to lavaland fauna.
(Activate this item in hand to dodge roll in the direction you're facing)" icon_state = "basalt_katana" item_state = "basalt_katana" force = 18 diff --git a/code/game/objects/structures/door_assembly.dm b/code/game/objects/structures/door_assembly.dm index 26ffaa271b51..30b8a116b360 100644 --- a/code/game/objects/structures/door_assembly.dm +++ b/code/game/objects/structures/door_assembly.dm @@ -319,7 +319,7 @@ qdel(src) /obj/structure/door_assembly/rcd_vals(mob/user, obj/item/construction/rcd/the_rcd) - if(the_rcd.mode == RCD_DECONSTRUCT) + if(the_rcd.construction_mode == RCD_DECONSTRUCT) return list("mode" = RCD_DECONSTRUCT, "delay" = 50, "cost" = 16) return FALSE diff --git a/code/game/objects/structures/girders.dm b/code/game/objects/structures/girders.dm index 8abaa8a5f237..f0438d4b89e2 100644 --- a/code/game/objects/structures/girders.dm +++ b/code/game/objects/structures/girders.dm @@ -377,7 +377,7 @@ qdel(src) /obj/structure/girder/rcd_vals(mob/user, obj/item/construction/rcd/the_rcd) - switch(the_rcd.mode) + switch(the_rcd.construction_mode) if(RCD_FLOORWALL) return list("mode" = RCD_FLOORWALL, "delay" = 20, "cost" = 8) if(RCD_DECONSTRUCT) diff --git a/code/game/objects/structures/grille.dm b/code/game/objects/structures/grille.dm index 0313894e0e60..999054d19ef1 100644 --- a/code/game/objects/structures/grille.dm +++ b/code/game/objects/structures/grille.dm @@ -68,7 +68,7 @@ . += span_notice("The anchoring screws are unscrewed. The rods look like they could be cut through.") /obj/structure/grille/rcd_vals(mob/user, obj/item/construction/rcd/the_rcd) - switch(the_rcd.mode) + switch(the_rcd.construction_mode) if(RCD_DECONSTRUCT) return list("mode" = RCD_DECONSTRUCT, "delay" = 20, "cost" = 5) if(RCD_WINDOWGRILLE) diff --git a/code/game/objects/structures/lattice.dm b/code/game/objects/structures/lattice.dm index c270c1d47913..ca111ff4fecf 100644 --- a/code/game/objects/structures/lattice.dm +++ b/code/game/objects/structures/lattice.dm @@ -52,7 +52,7 @@ qdel(src) /obj/structure/lattice/rcd_vals(mob/user, obj/item/construction/rcd/the_rcd) - if(the_rcd.mode == RCD_FLOORWALL) + if(the_rcd.construction_mode == RCD_FLOORWALL) return list("mode" = RCD_FLOORWALL, "delay" = 0, "cost" = 2) /obj/structure/lattice/rcd_act(mob/user, obj/item/construction/rcd/the_rcd, passed_mode) diff --git a/code/game/objects/structures/mirror.dm b/code/game/objects/structures/mirror.dm index 7d22e05d02f5..b143d3e1d2ce 100644 --- a/code/game/objects/structures/mirror.dm +++ b/code/game/objects/structures/mirror.dm @@ -144,7 +144,7 @@ /obj/item/wallframe/mirror name = "mirror" - desc = "a mirror on your hand, what are you gonna do?" + desc = "A mirror on your hand, what are you gonna do?" icon = 'icons/obj/watercloset.dmi' icon_state = "mirror" result_path = /obj/structure/mirror diff --git a/code/game/objects/structures/tables_racks.dm b/code/game/objects/structures/tables_racks.dm index 4a5968090268..094650274a29 100644 --- a/code/game/objects/structures/tables_racks.dm +++ b/code/game/objects/structures/tables_racks.dm @@ -236,7 +236,7 @@ qdel(src) /obj/structure/table/rcd_vals(mob/user, obj/item/construction/rcd/the_rcd) - switch(the_rcd.mode) + switch(the_rcd.construction_mode) if(RCD_DECONSTRUCT) return list("mode" = RCD_DECONSTRUCT, "delay" = 24, "cost" = 16) return FALSE diff --git a/code/game/objects/structures/window.dm b/code/game/objects/structures/window.dm index 205d357bee58..9327f9175fed 100644 --- a/code/game/objects/structures/window.dm +++ b/code/game/objects/structures/window.dm @@ -74,7 +74,7 @@ AddElement(/datum/element/connect_loc, loc_connections) /obj/structure/window/rcd_vals(mob/user, obj/item/construction/rcd/the_rcd) - switch(the_rcd.mode) + switch(the_rcd.construction_mode) if(RCD_DECONSTRUCT) return list("mode" = RCD_DECONSTRUCT, "delay" = 20, "cost" = 5) return FALSE @@ -83,7 +83,7 @@ if (resistance_flags & INDESTRUCTIBLE) return FALSE - switch(the_rcd.mode) + switch(the_rcd.construction_mode) if(RCD_DECONSTRUCT) to_chat(user, span_notice("You deconstruct the window.")) qdel(src) diff --git a/code/game/turfs/closed/walls.dm b/code/game/turfs/closed/walls.dm index d5460156c700..2127dc3bac60 100644 --- a/code/game/turfs/closed/walls.dm +++ b/code/game/turfs/closed/walls.dm @@ -196,7 +196,7 @@ return //get the user's location - if(!isturf(user.loc)) + if(!isturf(user.loc) && !ismecha(user.loc)) return //can't do this stuff whilst inside objects and such add_fingerprint(user) @@ -297,7 +297,7 @@ dismantle_wall(1) /turf/closed/wall/rcd_vals(mob/user, obj/item/construction/rcd/the_rcd) - switch(the_rcd.mode) + switch(the_rcd.construction_mode) if(RCD_DECONSTRUCT) return list("mode" = RCD_DECONSTRUCT, "delay" = 40, "cost" = 26) return FALSE diff --git a/code/game/turfs/open/chasm.dm b/code/game/turfs/open/chasm.dm index 532a3e5b3e9a..7871b313ea9e 100644 --- a/code/game/turfs/open/chasm.dm +++ b/code/game/turfs/open/chasm.dm @@ -36,7 +36,7 @@ return /turf/open/chasm/rcd_vals(mob/user, obj/item/construction/rcd/the_rcd) - switch(the_rcd.mode) + switch(the_rcd.construction_mode) if(RCD_FLOORWALL) return list("mode" = RCD_FLOORWALL, "delay" = 0, "cost" = 3) return FALSE diff --git a/code/game/turfs/open/floor.dm b/code/game/turfs/open/floor.dm index 80706649c786..67990c43ee7b 100644 --- a/code/game/turfs/open/floor.dm +++ b/code/game/turfs/open/floor.dm @@ -164,8 +164,8 @@ return FALSE /turf/open/floor/crowbar_act(mob/living/user, obj/item/I) - if(istype(I,/obj/item/jawsoflife/jimmy)) - to_chat(user,"The [I] cannot pry tiles.") + if(istype(I, /obj/item/jawsoflife/jimmy) || istype(I, /obj/item/mecha_parts/mecha_equipment/hydraulic_clamp)) + to_chat(user,"[I] cannot pry tiles.") return if(overfloor_placed && pry_tile(I, user)) return TRUE @@ -235,7 +235,7 @@ ScrapeAway(flags = CHANGETURF_INHERIT_AIR) /turf/open/floor/rcd_vals(mob/user, obj/item/construction/rcd/the_rcd) - switch(the_rcd.mode) + switch(the_rcd.construction_mode) if(RCD_FLOORWALL) return list("mode" = RCD_FLOORWALL, "delay" = 20, "cost" = 16) if(RCD_AIRLOCK) @@ -253,6 +253,10 @@ return list("mode" = RCD_COMPUTER, "delay" = 20, "cost" = 25) if(RCD_FURNISHING) return list("mode" = RCD_FURNISHING, "delay" = the_rcd.furnish_delay, "cost" = the_rcd.furnish_cost) + if(RCD_CONVEYOR) + return list("mode" = RCD_CONVEYOR, "delay" = 5, "cost" = 5) + if(RCD_SWITCH) + return list("mode" = RCD_SWITCH, "delay" = 1, "cost" = 1) return FALSE /turf/open/floor/rcd_act(mob/user, obj/item/construction/rcd/the_rcd, passed_mode) @@ -329,4 +333,19 @@ var/atom/new_furnish = new the_rcd.furnish_type(src) new_furnish.setDir(user.dir) return TRUE + if(RCD_CONVEYOR) + if(locate(/obj/machinery/conveyor) in src) + return FALSE + if(get_turf(user) == src) + return FALSE + var/obj/machinery/conveyor/new_conveyor = new /obj/machinery/conveyor(src) + new_conveyor.setDir(user.dir) + if(the_rcd.linked_switch_id) + new_conveyor.id = the_rcd.linked_switch_id // link the conveyor if possible + return TRUE + if(RCD_SWITCH) + if(locate(/obj/machinery/conveyor_switch) in src) + return FALSE + new /obj/machinery/conveyor_switch(src) + return TRUE return FALSE diff --git a/code/game/turfs/open/floor/plating.dm b/code/game/turfs/open/floor/plating.dm index 2c6a8bbd0005..115a9e89c71d 100644 --- a/code/game/turfs/open/floor/plating.dm +++ b/code/game/turfs/open/floor/plating.dm @@ -163,7 +163,7 @@ to_chat(user, span_danger("You hit [src], to no effect!")) /turf/open/floor/plating/foam/rcd_vals(mob/user, obj/item/construction/rcd/the_rcd) - if(the_rcd.mode == RCD_FLOORWALL) + if(the_rcd.construction_mode == RCD_FLOORWALL) return list("mode" = RCD_FLOORWALL, "delay" = 0, "cost" = 1) /turf/open/floor/plating/foam/rcd_act(mob/user, obj/item/construction/rcd/the_rcd, passed_mode) diff --git a/code/game/turfs/open/lava.dm b/code/game/turfs/open/lava.dm index f58f77d03e1f..eb63fc7dd6c8 100644 --- a/code/game/turfs/open/lava.dm +++ b/code/game/turfs/open/lava.dm @@ -127,7 +127,7 @@ STOP_PROCESSING(SSobj, src) /turf/open/lava/rcd_vals(mob/user, obj/item/construction/rcd/the_rcd) - switch(the_rcd.mode) + switch(the_rcd.construction_mode) if(RCD_FLOORWALL) return list("mode" = RCD_FLOORWALL, "delay" = 0, "cost" = 3) return FALSE diff --git a/code/game/turfs/open/openspace.dm b/code/game/turfs/open/openspace.dm index 5216f2280d96..2bf2f2c87af0 100644 --- a/code/game/turfs/open/openspace.dm +++ b/code/game/turfs/open/openspace.dm @@ -108,7 +108,7 @@ return can_build_on /turf/open/openspace/rcd_vals(mob/user, obj/item/construction/rcd/the_rcd) - switch(the_rcd.mode) + switch(the_rcd.construction_mode) if(RCD_FLOORWALL) return list("mode" = RCD_FLOORWALL, "delay" = 0, "cost" = 3) return FALSE diff --git a/code/game/turfs/open/space/space.dm b/code/game/turfs/open/space/space.dm index de3c5383a498..f370afc3123d 100644 --- a/code/game/turfs/open/space/space.dm +++ b/code/game/turfs/open/space/space.dm @@ -149,7 +149,7 @@ GLOBAL_LIST_EMPTY(starlight) return TRUE /turf/open/space/rcd_vals(mob/user, obj/item/construction/rcd/the_rcd) - switch(the_rcd.mode) + switch(the_rcd.construction_mode) if(RCD_FLOORWALL) return list("mode" = RCD_FLOORWALL, "delay" = 0, "cost" = 3) return FALSE diff --git a/code/game/turfs/open/space/transit.dm b/code/game/turfs/open/space/transit.dm index 61087e674021..fa5ce4bf686d 100644 --- a/code/game/turfs/open/space/transit.dm +++ b/code/game/turfs/open/space/transit.dm @@ -1,5 +1,5 @@ /turf/open/space/transit - name = "\proper hyperspace" + name = "\proper bluespace" desc = "What is this, light-speed? We need to go to plaid speed!" // spaceballs was a great movie icon_state = "black" dir = SOUTH diff --git a/code/game/turfs/turf.dm b/code/game/turfs/turf.dm index f7922e820a45..48ea42c20dd1 100644 --- a/code/game/turfs/turf.dm +++ b/code/game/turfs/turf.dm @@ -138,6 +138,7 @@ GLOBAL_LIST_EMPTY(station_turfs) if (smoothing_flags & (SMOOTH_CORNERS|SMOOTH_BITMASK)) QUEUE_SMOOTH(src) + QUEUE_SMOOTH_NEIGHBORS(src) //Yog code because there are some templates we load right into the map visibilityChanged() diff --git a/code/modules/antagonists/_common/antag_datum.dm b/code/modules/antagonists/_common/antag_datum.dm index 604ef5a2b179..ed357bb9d91a 100644 --- a/code/modules/antagonists/_common/antag_datum.dm +++ b/code/modules/antagonists/_common/antag_datum.dm @@ -17,7 +17,7 @@ GLOBAL_LIST_EMPTY(antagonists) var/antag_moodlet //typepath of moodlet that the mob will gain with their status var/can_hijack = HIJACK_NEUTRAL //If these antags are alone on shuttle hijack happens. ///The antag hud's icon file - var/hud_icon = 'yogstation/icons/mob/antag_hud.dmi' + var/hud_icon = 'modular_dripstation/icons/mob/hud.dmi' //dripstation edit ///Name of the antag hud we provide to this mob. var/antag_hud_name var/awake_stage = ANTAG_AWAKE //What stage we are of "waking up" diff --git a/code/modules/antagonists/bloodsuckers/vassal/vassal.dm b/code/modules/antagonists/bloodsuckers/vassal/vassal.dm index bf88783d06c6..9d21f401a298 100644 --- a/code/modules/antagonists/bloodsuckers/vassal/vassal.dm +++ b/code/modules/antagonists/bloodsuckers/vassal/vassal.dm @@ -276,7 +276,7 @@ show_in_antagpanel = FALSE silent = TRUE ui_name = FALSE - hud_icon = 'yogstation/icons/mob/hud.dmi' + hud_icon = 'modular_dripstation/icons/mob/hud.dmi' //dripstation edit ///The revenge vassal that brought us into the fold. var/datum/antagonist/vassal/revenge/revenge_vassal diff --git a/code/modules/antagonists/cult/cult_items.dm b/code/modules/antagonists/cult/cult_items.dm index a9dfd38d2af9..4d5fefa3d622 100644 --- a/code/modules/antagonists/cult/cult_items.dm +++ b/code/modules/antagonists/cult/cult_items.dm @@ -487,7 +487,7 @@ user.dropItemToGround(src, TRUE) /obj/item/clothing/glasses/hud/health/night/cultblind - desc = "may Nar'sie guide you through the darkness and shield you from the light." + desc = "May Nar'sie guide you through the darkness and shield you from the light." name = "zealot's blindfold" icon_state = "blindfold" item_state = "blindfold" diff --git a/code/modules/antagonists/cult/runes.dm b/code/modules/antagonists/cult/runes.dm index 9fede71f0ad6..0b72aa0f9a2d 100644 --- a/code/modules/antagonists/cult/runes.dm +++ b/code/modules/antagonists/cult/runes.dm @@ -17,7 +17,7 @@ Runes can either be invoked by one's self or with many different cultists. Each name = "rune" var/cultist_name = "basic rune" desc = "A rune vandalizing the station." - var/cultist_desc = "a basic rune with no function." //This is shown to cultists who examine the rune in order to determine its true purpose. + var/cultist_desc = "A basic rune with no function." //This is shown to cultists who examine the rune in order to determine its true purpose. anchored = TRUE icon = 'icons/obj/rune.dmi' icon_state = "1" @@ -193,7 +193,7 @@ structure_check() searches for nearby cultist structures required for the invoca //Malformed Rune: This forms if a rune is not drawn correctly. Invoking it does nothing but hurt the user. /obj/effect/rune/malformed cultist_name = "malformed rune" - cultist_desc = "a senseless rune written in gibberish. No good can come from invoking this." + cultist_desc = "A senseless rune written in gibberish. No good can come from invoking this." invocation = "Ra'sha yoka!" invoke_damage = 30 @@ -209,7 +209,7 @@ structure_check() searches for nearby cultist structures required for the invoca //Rite of Offering: Converts or sacrifices a target. /obj/effect/rune/convert cultist_name = "Offer" - cultist_desc = "offers a noncultist above it to Nar'sie, either converting them or sacrificing them." + cultist_desc = "Offers a non-cultist above it to Nar'sie, either converting them or sacrificing them." req_cultists_text = "2 for conversion, 3 for living sacrifices and sacrifice targets." invocation = "Mah'weyh pleggh at e'ntrath!" icon_state = "3" @@ -363,7 +363,7 @@ structure_check() searches for nearby cultist structures required for the invoca /obj/effect/rune/empower cultist_name = "Empower" - cultist_desc = "allows cultists to prepare greater amounts of blood magic at far less of a cost." + cultist_desc = "Allows cultists to prepare greater amounts of blood magic at far less of a cost." invocation = "H'drak v'loso, mir'kanas verbot!" icon_state = "3" color = RUNE_COLOR_TALISMAN @@ -377,7 +377,7 @@ structure_check() searches for nearby cultist structures required for the invoca /obj/effect/rune/teleport cultist_name = "Teleport" - cultist_desc = "warps everything above it to another chosen teleport rune." + cultist_desc = "Warps everything above it to another chosen teleport rune." invocation = "Sas'so c'arta forbici!" icon_state = "2" color = RUNE_COLOR_TELEPORT @@ -500,7 +500,7 @@ structure_check() searches for nearby cultist structures required for the invoca //Ritual of Dimensional Rending: Calls forth the avatar of Nar'sie upon the station. /obj/effect/rune/narsie cultist_name = "Nar'sie" - cultist_desc = "tears apart dimensional barriers, beginning the Red Harvest. You will need to protect 4 Bloodstones around the station, then the Anchor Bloodstone after invoking this rune or the summoning will backfire and need to be restarted. Requires 9 invokers, with the cult leader counting as half of this if they invoke the rune." + cultist_desc = "Tears apart dimensional barriers, beginning the Red Harvest. You will need to protect 4 Bloodstones around the station, then the Anchor Bloodstone after invoking this rune or the summoning will backfire and need to be restarted. Requires 9 invokers, with the cult leader counting as half of this if they invoke the rune." invocation = "TOK-LYR RQA-NAP G'OLT-ULOFT!!" req_cultists = 9 req_cultists_text = "9 cultists, with the cult leader counting as 5 if they are the invoker" @@ -591,7 +591,7 @@ GLOBAL_VAR_INIT(narsie_summon_count, 0) //Rite of Resurrection: Requires a dead or inactive cultist. When reviving the dead, you can only perform one revival for every three sacrifices your cult has carried out. /obj/effect/rune/raise_dead cultist_name = "Revive" - cultist_desc = "requires a dead, mindless, or inactive cultist placed upon the rune. Provided there have been sufficient sacrifices, they will be given a new life. This will cause large amounts of damage to the invoker and the revived corpse." + cultist_desc = "Requires a dead, mindless, or inactive cultist placed upon the rune. Provided there have been sufficient sacrifices, they will be given a new life. This will cause large amounts of damage to the invoker and the revived corpse." invocation = "Pasnar val'keriam usinar. Savrae ines amutan. Yam'toth remium il'tarat!" //Depends on the name of the user - see below icon_state = "1" color = RUNE_COLOR_MEDIUMRED @@ -685,7 +685,7 @@ GLOBAL_VAR_INIT(narsie_summon_count, 0) //Rite of the Corporeal Shield: When invoked, becomes solid and cannot be passed. Invoke again to undo. /obj/effect/rune/wall cultist_name = "Barrier" - cultist_desc = "when invoked, makes a temporary invisible wall to block passage. Can be invoked again to reverse this." + cultist_desc = "When invoked, makes a temporary invisible wall to block passage. Can be invoked again to reverse this." invocation = "Khari'd! Eske'te tannin!" icon_state = "4" color = RUNE_COLOR_DARKRED @@ -766,7 +766,7 @@ GLOBAL_VAR_INIT(narsie_summon_count, 0) //Rite of Joined Souls: Summons a single cultist. /obj/effect/rune/summon cultist_name = "Summon Cultist" - cultist_desc = "summons a single cultist to the rune. Requires 2 invokers." + cultist_desc = "Summons a single cultist to the rune. Requires 2 invokers." invocation = "N'ath reth sh'yro eth d'rekkathnor!" req_cultists = 2 invoke_damage = 10 @@ -824,7 +824,7 @@ GLOBAL_VAR_INIT(narsie_summon_count, 0) //Rite of Boiling Blood: Deals extremely high amounts of damage to non-cultists nearby /obj/effect/rune/blood_boil cultist_name = "Boil Blood" - cultist_desc = "boils the blood of non-believers who can see the rune, rapidly dealing extreme amounts of damage. Requires 3 invokers." + cultist_desc = "Boils the blood of non-believers who can see the rune, rapidly dealing extreme amounts of damage. Requires 3 invokers." invocation = "Dedo ol'btoh!" icon_state = "4" color = RUNE_COLOR_BURNTORANGE @@ -889,7 +889,7 @@ GLOBAL_VAR_INIT(narsie_summon_count, 0) //Rite of Spectral Manifestation: Summons a ghost on top of the rune as a cultist human with no items. User must stand on the rune at all times, and takes damage for each summoned ghost. /obj/effect/rune/manifest cultist_name = "Spirit Realm" - cultist_desc = "manifests a spirit servant of the Geometer and allows you to ascend as a spirit yourself. The invoker must not move from atop the rune, and will take damage for each summoned spirit." + cultist_desc = "Manifests a spirit servant of the Geometer and allows you to ascend as a spirit yourself. The invoker must not move from atop the rune, and will take damage for each summoned spirit." invocation = "Gal'h'rfikk harfrandid mud'gib!" //how the fuck do you pronounce this icon_state = "7" invoke_damage = 10 @@ -1016,7 +1016,7 @@ GLOBAL_VAR_INIT(narsie_summon_count, 0) /obj/effect/rune/apocalypse cultist_name = "Apocalypse" - cultist_desc = "a harbinger of the end times. Grows in strength with the cult's desperation - but at the risk of... side effects." + cultist_desc = "A harbinger of the end times. Grows in strength with the cult's desperation - but at the risk of... side effects." invocation = "Ta'gh fara'qha fel d'amar det!" icon = 'icons/effects/96x96.dmi' icon_state = "apoc" diff --git a/code/modules/antagonists/disease/disease_datum.dm b/code/modules/antagonists/disease/disease_datum.dm index fb18acc65d00..74c35d9d177c 100644 --- a/code/modules/antagonists/disease/disease_datum.dm +++ b/code/modules/antagonists/disease/disease_datum.dm @@ -76,7 +76,7 @@ return result.Join("
") /datum/antagonist/disease/get_preview_icon() - var/icon/icon = icon('icons/mob/hud.dmi', "virus_infected") + var/icon/icon = icon('modular_dripstation/icons/mob/hud.dmi', "virus_infected") //dripstation edit icon.Blend(COLOR_GREEN_GRAY, ICON_MULTIPLY) icon.Scale(ANTAGONIST_PREVIEW_ICON_SIZE, ANTAGONIST_PREVIEW_ICON_SIZE) return icon @@ -109,7 +109,7 @@ return FALSE /datum/antagonist/disease/get_preview_icon() - var/icon/disease_icon = icon('icons/mob/hud.dmi', "infected") + var/icon/disease_icon = icon('modular_dripstation/icons/mob/hud.dmi', "infected") //dripstation edit disease_icon.Blend(COLOR_GREEN_GRAY, ICON_MULTIPLY) disease_icon.Scale(ANTAGONIST_PREVIEW_ICON_SIZE, ANTAGONIST_PREVIEW_ICON_SIZE) return disease_icon diff --git a/code/modules/antagonists/eldritch_cult/eldritch_effects.dm b/code/modules/antagonists/eldritch_cult/eldritch_effects.dm index e3ae58f0497d..40c530c1efed 100644 --- a/code/modules/antagonists/eldritch_cult/eldritch_effects.dm +++ b/code/modules/antagonists/eldritch_cult/eldritch_effects.dm @@ -419,7 +419,7 @@ /obj/effect/penance_giver name = "code ing" - desc = "it takes your soul, and other stuff" + desc = "It takes your soul, and other stuff." icon = 'icons/mob/triangle.dmi' icon_state = "triangle" light_power = 2 diff --git a/code/modules/antagonists/revolution/revolution.dm b/code/modules/antagonists/revolution/revolution.dm index 51de65512872..77db2ed669ba 100644 --- a/code/modules/antagonists/revolution/revolution.dm +++ b/code/modules/antagonists/revolution/revolution.dm @@ -175,7 +175,7 @@ // Otherwise, the R gets cut off. final_icon.Scale(64, 64) - var/icon/rev_head_icon = icon('yogstation/icons/mob/antag_hud.dmi', "rev_head") + var/icon/rev_head_icon = icon('modular_dripstation/icons/mob/hud.dmi', "rev_head") //dripstation edit rev_head_icon.Scale(48, 48) rev_head_icon.Crop(1, 1, 64, 64) rev_head_icon.Shift(EAST, 10) diff --git a/code/modules/assembly/mousetrap.dm b/code/modules/assembly/mousetrap.dm index cd2eb6972683..75f8fd51ee9c 100644 --- a/code/modules/assembly/mousetrap.dm +++ b/code/modules/assembly/mousetrap.dm @@ -9,6 +9,13 @@ var/armed = FALSE +/obj/item/assembly/mousetrap/Initialize(mapload) + . = ..() + var/static/list/loc_connections = list( + COMSIG_ATOM_ENTERED = PROC_REF(trap_stepped_on), + ) + AddElement(/datum/element/connect_loc, loc_connections) + /obj/item/assembly/mousetrap/examine(mob/user) . = ..() . += span_notice("The pressure plate is [armed?"primed":"safe"].") @@ -109,7 +116,7 @@ return ..() -/obj/item/assembly/mousetrap/Crossed(atom/movable/AM as mob|obj) +/obj/item/assembly/mousetrap/proc/trap_stepped_on(datum/source, atom/movable/AM, ...) if(armed) if(ismob(AM)) var/mob/MM = AM @@ -124,7 +131,7 @@ triggered(MM) else if(AM.density) // For mousetrap grenades, set off by anything heavy triggered(AM) - ..() + return /obj/item/assembly/mousetrap/on_found(mob/finder) diff --git a/code/modules/asset_cache/asset_list_items.dm b/code/modules/asset_cache/asset_list_items.dm index fd72dc814a4d..0ac3e148490a 100644 --- a/code/modules/asset_cache/asset_list_items.dm +++ b/code/modules/asset_cache/asset_list_items.dm @@ -654,3 +654,59 @@ glow = "pod_glow_[glow]" podIcon.Blend(icon(icon_file, glow), ICON_OVERLAY) Insert("pod_asset[style]", podIcon) + +/datum/asset/spritesheet/rcd + name = "rcd-tgui" + +/datum/asset/spritesheet/rcd/create_spritesheets() + //We load airlock icons seperatly from other icons cause they need overlays + + //load all category essential icon_states. format is icon_file = list of icon states we need from that file + var/list/essentials = list( + 'icons/mob/radial.dmi' = list("wallfloor", "delete", "dirwindow", "fullwindow", "dirwindow_r", "fullwindow_r", "cnorth", "csouth", "ceast", "cwest", "chair", "stool", "windoor", "secure_windoor"), + 'icons/obj/recycling.dmi' = list("conveyor_construct", "switch-off"), + 'icons/obj/structures.dmi' = list("window0", "rwindow0", "table", "glass_table"), + 'icons/obj/stock_parts.dmi' = list("box_1"), + ) + + var/icon/icon + for(var/icon_file as anything in essentials) + for(var/icon_state as anything in essentials[icon_file]) + icon = icon(icon = icon_file, icon_state = icon_state) + Insert(sanitize_css_class_name(icon_state), icon) + + //for each airlock type we create its overlayed version with the suffix Glass in the sprite name + var/list/airlocks = list( + "Standard" = 'icons/obj/doors/airlocks/station/public.dmi', + "Public" = 'icons/obj/doors/airlocks/station2/glass.dmi', + "Engineering" = 'icons/obj/doors/airlocks/station/engineering.dmi', + "Atmospherics" = 'icons/obj/doors/airlocks/station/atmos.dmi', + "Security" = 'icons/obj/doors/airlocks/station/security.dmi', + "Command" = 'icons/obj/doors/airlocks/station/command.dmi', + "Medical" = 'icons/obj/doors/airlocks/station/medical.dmi', + "Research" = 'icons/obj/doors/airlocks/station/research.dmi', + "Freezer" = 'icons/obj/doors/airlocks/station/freezer.dmi', + "Virology" = 'icons/obj/doors/airlocks/station/virology.dmi', + "Mining" = 'icons/obj/doors/airlocks/station/mining.dmi', + "Maintenance" = 'icons/obj/doors/airlocks/station/maintenance.dmi', + "External" = 'icons/obj/doors/airlocks/external/external.dmi', + "External Maintenance" = 'icons/obj/doors/airlocks/station/maintenanceexternal.dmi', + "Airtight Hatch" = 'icons/obj/doors/airlocks/hatch/centcom.dmi', + "Maintenance Hatch" = 'icons/obj/doors/airlocks/hatch/maintenance.dmi' + ) + //these 3 types dont have glass doors + var/list/exclusion = list("Freezer", "Airtight Hatch", "Maintenance Hatch") + + for(var/airlock_name in airlocks) + //solid door with overlay + icon = icon(icon = airlocks[airlock_name] , icon_state = "closed" , dir = SOUTH) + icon.Blend(icon(icon = airlocks[airlock_name], icon_state = "fill_closed", dir = SOUTH), ICON_OVERLAY) + Insert(sanitize_css_class_name(airlock_name), icon) + + //exclude these glass types + if(airlock_name in exclusion) + continue + + //glass door no overlay + icon = icon(airlocks[airlock_name] , "closed" , SOUTH) + Insert(sanitize_css_class_name("[airlock_name]Glass"), icon) diff --git a/code/modules/atmospherics/gasmixtures/reactions.dm b/code/modules/atmospherics/gasmixtures/reactions.dm index f0e24ee776a6..2b1ae7d7d4a3 100644 --- a/code/modules/atmospherics/gasmixtures/reactions.dm +++ b/code/modules/atmospherics/gasmixtures/reactions.dm @@ -429,7 +429,7 @@ GAS_PLASMA = 10, ) -/datum/gas_reaction/bzformation/react(datum/gas_mixture/air) +/datum/gas_reaction/bzformation/react(datum/gas_mixture/air, datum/holder) var/pressure = air.return_pressure() var/old_thermal_energy = air.thermal_energy() @@ -448,7 +448,9 @@ air.adjust_moles(GAS_PLASMA, -2*reaction_efficency) //clamps by a minimum amount in the event of an underflow. - SSresearch.science_tech.add_point_type(TECHWEB_POINT_TYPE_DEFAULT, clamp((reaction_efficency**2)*BZ_RESEARCH_AMOUNT,0.01,BZ_RESEARCH_MAX_AMOUNT)) + var/turf/holder_turf = get_holder_turf(holder) + if(holder_turf && SSmapping.level_trait(holder_turf.z, ZTRAIT_STATION)) + SSresearch.science_tech.add_point_type(TECHWEB_POINT_TYPE_DEFAULT, clamp((reaction_efficency**2)*BZ_RESEARCH_AMOUNT,0.01,BZ_RESEARCH_MAX_AMOUNT)) if(energy_released > 0) var/new_heat_capacity = air.heat_capacity() @@ -467,7 +469,7 @@ GAS_TRITIUM = 10, "TEMP" = 5000000) -/datum/gas_reaction/nobliumformation/react(datum/gas_mixture/air) +/datum/gas_reaction/nobliumformation/react(datum/gas_mixture/air, datum/holder) var/initial_trit = air.get_moles(GAS_TRITIUM) var/initial_n2 = air.get_moles(GAS_N2) var/initial_bz = air.get_moles(GAS_BZ) @@ -480,7 +482,11 @@ air.adjust_moles(GAS_TRITIUM, -10*nob_formed) air.adjust_moles(GAS_N2, -20*nob_formed) air.adjust_moles(GAS_HYPERNOB, nob_formed) - SSresearch.science_tech.add_point_type(TECHWEB_POINT_TYPE_DEFAULT, clamp(nob_formed*NOBLIUM_RESEARCH_AMOUNT, 0.01, NOBLIUM_RESEARCH_MAX_AMOUNT)) + + var/turf/holder_turf = get_holder_turf(holder) + if(holder_turf && SSmapping.level_trait(holder_turf.z, ZTRAIT_STATION)) + SSresearch.science_tech.add_point_type(TECHWEB_POINT_TYPE_DEFAULT, clamp(nob_formed*NOBLIUM_RESEARCH_AMOUNT, 0.01, NOBLIUM_RESEARCH_MAX_AMOUNT)) + var/new_heat_capacity = air.heat_capacity() if(new_heat_capacity > MINIMUM_HEAT_CAPACITY) air.set_temperature(max(((old_thermal_energy - energy_taken)/new_heat_capacity),TCMB)) @@ -510,7 +516,10 @@ //Possibly burning a bit of organic matter through maillard reaction, so a *tiny* bit more heat would be understandable air.set_temperature(air.return_temperature() + cleaned_air * 0.002) - SSresearch.science_tech.add_point_type(TECHWEB_POINT_TYPE_DEFAULT, clamp(cleaned_air*MIASMA_RESEARCH_AMOUNT,0.01, MIASMA_RESEARCH_MAX_AMOUNT))//Turns out the burning of miasma is kinda interesting to scientists + + var/turf/holder_turf = get_holder_turf(holder) + if(holder_turf && SSmapping.level_trait(holder_turf.z, ZTRAIT_STATION)) + SSresearch.science_tech.add_point_type(TECHWEB_POINT_TYPE_DEFAULT, clamp(cleaned_air*MIASMA_RESEARCH_AMOUNT,0.01, MIASMA_RESEARCH_MAX_AMOUNT))//Turns out the burning of miasma is kinda interesting to scientists return REACTING /datum/gas_reaction/nitro_ball @@ -730,7 +739,9 @@ if (prob(25 * increase_factor)) air.adjust_moles(GAS_H2, -(heat_efficency * 10)) new /obj/item/stack/sheet/mineral/metal_hydrogen(location) - SSresearch.science_tech.add_point_type(TECHWEB_POINT_TYPE_DEFAULT, min((heat_efficency * increase_factor * 0.5), METAL_HYDROGEN_RESEARCH_MAX_AMOUNT)) + var/turf/holder_turf = get_holder_turf(holder) + if(holder_turf && SSmapping.level_trait(holder_turf.z, ZTRAIT_STATION)) + SSresearch.science_tech.add_point_type(TECHWEB_POINT_TYPE_DEFAULT, min((heat_efficency * increase_factor * 0.5), METAL_HYDROGEN_RESEARCH_MAX_AMOUNT)) if(energy_used > 0) var/new_heat_capacity = air.heat_capacity() diff --git a/code/modules/atmospherics/machinery/components/fusion/hfr_main_processes.dm b/code/modules/atmospherics/machinery/components/fusion/hfr_main_processes.dm index 700b970fb1d6..209408558b01 100644 --- a/code/modules/atmospherics/machinery/components/fusion/hfr_main_processes.dm +++ b/code/modules/atmospherics/machinery/components/fusion/hfr_main_processes.dm @@ -251,10 +251,11 @@ var/remove_amount = round(min(fuel_list[gas_id], fuel_consumption), 0.01) internal_fusion.adjust_moles(gas_id, -remove_amount) delta_fuel_list[gas_id] -= remove_amount + + var/add_remove_amount = round(scaled_production, 0.01) // gases on the same tier are produced at normal rate for(var/gas_id in fuel.primary_products) - var/add_amount = round(fuel_consumption * 0.5, 0.01) - internal_fusion.adjust_moles(gas_id, add_amount) - delta_fuel_list[gas_id] += add_amount + internal_fusion.adjust_moles(gas_id, add_remove_amount) + delta_fuel_list[gas_id] += add_remove_amount if(power_level < 1) return // can't produce any gases, don't need to continue @@ -262,8 +263,8 @@ // Each recipe provides a tier list of six output gases. // Which gases are produced depend on what the fusion level is. var/list/tier = fuel.secondary_products - moderator_internal.adjust_moles(tier[power_level], round(scaled_production, 0.01)) // gases on the same tier are produced at normal rate - delta_mod_list[tier[power_level]] += round(scaled_production, 0.01) + moderator_internal.adjust_moles(tier[power_level], add_remove_amount) + delta_mod_list[tier[power_level]] += add_remove_amount if(power_level < 6) moderator_internal.adjust_moles(tier[power_level + 1], round(scaled_production * 0.5, 0.01)) // gases on the above tier are produced at reduced rate delta_mod_list[tier[power_level + 1]] += round(scaled_production * 0.5, 0.01) diff --git a/code/modules/atmospherics/machinery/portable/canister.dm b/code/modules/atmospherics/machinery/portable/canister.dm index 42abcc19fd6f..d6de11c10b18 100644 --- a/code/modules/atmospherics/machinery/portable/canister.dm +++ b/code/modules/atmospherics/machinery/portable/canister.dm @@ -40,7 +40,7 @@ "generic striped" = /obj/machinery/portable_atmospherics/canister/generic/stripe, "generic hazard" = /obj/machinery/portable_atmospherics/canister/generic/hazard, "caution" = /obj/machinery/portable_atmospherics/canister, - "danger" = /obj/machinery/portable_atmospherics/canister/fusion_test, + "danger" = /obj/machinery/portable_atmospherics/canister/fusion, "n2" = /obj/machinery/portable_atmospherics/canister/nitrogen, "o2" = /obj/machinery/portable_atmospherics/canister/oxygen, "co2" = /obj/machinery/portable_atmospherics/canister/carbon_dioxide, @@ -168,56 +168,56 @@ /obj/machinery/portable_atmospherics/canister/freon name = "Freon canister" - desc = "Freon. Can absorb heat" + desc = "Freon. Can absorb heat." icon_state = "freon" gas_type = GAS_FREON filled = 1 /obj/machinery/portable_atmospherics/canister/hydrogen name = "Hydrogen canister" - desc = "Hydrogen, highly flammable" + desc = "Hydrogen, highly flammable." icon_state = "h2" gas_type = GAS_H2 filled = 1 /obj/machinery/portable_atmospherics/canister/healium name = "Healium canister" - desc = "Healium, causes deep sleep" + desc = "Healium, causes deep sleep." icon_state = "healium" gas_type = GAS_HEALIUM filled = 1 /obj/machinery/portable_atmospherics/canister/pluonium name = "Pluonium canister" - desc = "Pluonium, reacts differently with various gases" + desc = "Pluonium, reacts differently with various gases." icon_state = "pluonium" gas_type = GAS_PLUONIUM filled = 1 /obj/machinery/portable_atmospherics/canister/halon name = "Halon canister" - desc = "Halon, remove oxygen from high temperature fires and cool down the area" + desc = "Halon, remove oxygen from high temperature fires and cool down the area." icon_state = "halon" gas_type = GAS_HALON filled = 1 /obj/machinery/portable_atmospherics/canister/hexane name = "Hexane canister" - desc = "hexane, highly flammable." + desc = "Hexane, highly flammable." icon_state = "hexane" gas_type = GAS_HEXANE filled = 1 /obj/machinery/portable_atmospherics/canister/zauker name = "Zauker canister" - desc = "Zauker, highly toxic" + desc = "Zauker, highly toxic." icon_state = "zauker" gas_type = GAS_ZAUKER filled = 1 /obj/machinery/portable_atmospherics/canister/antinoblium name = "Antinoblium canister" - desc = "Antinoblium, we still don't know what it does, but it sells for a lot" + desc = "Antinoblium, we still don't know what it does, but it sells for a lot." icon_state = "antino" gas_type = GAS_ANTINOB filled = 1 @@ -566,6 +566,12 @@ analyzer_act(user, src) return ..() +/obj/machinery/portable_atmospherics/canister/fusion + name = "Fusion Canister" + desc = "A violent mix of gases resulting in a fusion reaction inside the canister.
\ + A note on the side reads: \"DANGER: DO NOT OPEN\"" + icon_state = "danger" + /* yog- ADMEME CANISTERS */ /// Canister 1 Kelvin below the fusion point. Is highly unoptimal, do not spawn to start fusion, only good for testing low instability mixes. diff --git a/code/modules/client/preferences_savefile.dm b/code/modules/client/preferences_savefile.dm index dd07e425d30a..21396361cc4b 100644 --- a/code/modules/client/preferences_savefile.dm +++ b/code/modules/client/preferences_savefile.dm @@ -183,7 +183,7 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car default_slot = sanitize_integer(default_slot, 1, max_save_slots, initial(default_slot)) player_alt_titles = SANITIZE_LIST(player_alt_titles) - toggles = sanitize_integer(toggles, 0, ~0, initial(toggles)) // Yogs -- Fixes toggles not having >16 bits of flagspace + toggles = sanitize_integer(toggles, 0, SHORT_REAL_LIMIT-1, initial(toggles)) key_bindings = sanitize_keybindings(key_bindings) diff --git a/code/modules/clothing/glasses/_glasses.dm b/code/modules/clothing/glasses/_glasses.dm index 64c244fa5b72..cd98d5465b88 100644 --- a/code/modules/clothing/glasses/_glasses.dm +++ b/code/modules/clothing/glasses/_glasses.dm @@ -11,22 +11,21 @@ materials = list(/datum/material/glass = 250) var/vision_flags = 0 var/invis_view = SEE_INVISIBLE_LIVING //admin only for now - var/invis_override = 0 //Override to allow glasses to set higher than normal see_invis - var/list/icon/current = list() //the current hud icons - var/vision_correction = 0 //does wearing these glasses correct some of our vision defects? - var/glass_colour_type //colors your vision when worn - + /// Override to allow glasses to set higher than normal see_invis + var/invis_override = 0 /// A percentage of how much rgb to "max" on the lighting plane /// This lets us brighten darkness without washing out bright color var/lighting_cutoff = null /// Similar to lighting_cutoff, except it has individual r g and b components in the same 0-100 scale var/list/color_cutoffs = null -// Potentially replace glass_color_type with a setup that colors lighting by dropping segments of different componets -// Like the current idea, but applied without the mass cutoff (maybe? somehow?) -// That or just a light color to the lighting plane, that'd work too -// Enough to make it visible but not so much that it's a pain - -// That, or just make stuff that uses lighting_cutoff have colored offsets and all, like you were planning + /// The current hud icons + var/list/icon/current = list() + /// Colors your vision when worn + var/glass_colour_type + /// Whether or not vision coloring is forcing + var/forced_glass_color = FALSE + //does wearing these glasses correct some of our vision defects? + var/vision_correction = 0 /obj/item/clothing/glasses/suicide_act(mob/living/carbon/user) user.visible_message(span_suicide("[user] is stabbing \the [src] into [user.p_their()] eyes! It looks like [user.p_theyre()] trying to commit suicide!")) @@ -533,14 +532,13 @@ return ..() && isliving(owner) /datum/action/cooldown/expose/Activate(atom/exposed) - StartCooldown(15 SECONDS) - if(owner.stat != CONSCIOUS) return FALSE if(!isliving(exposed) || exposed == owner) owner.balloon_alert(owner, "invalid exposed!") return FALSE - + StartCooldown(15 SECONDS) + var/mob/living/living_exposed = exposed living_exposed.apply_status_effect(STATUS_EFFECT_EXPOSED) living_exposed.adjust_jitter(5 SECONDS) diff --git a/code/modules/clothing/masks/miscellaneous.dm b/code/modules/clothing/masks/miscellaneous.dm index 5579278a21a3..70084ff9db3f 100644 --- a/code/modules/clothing/masks/miscellaneous.dm +++ b/code/modules/clothing/masks/miscellaneous.dm @@ -375,7 +375,7 @@ GLOBAL_LIST_INIT(cursed_animal_masks, list( /obj/item/clothing/mask/rmask name = "dusty mask" - desc = "A face is nothing, it’s what’s inside that matters." + desc = "A face is nothing, it's what's inside that matters." icon_state = "rmask" item_state = "rmaks" flags_inv = HIDEFACE|HIDEHAIR|HIDEFACIALHAIR @@ -384,7 +384,7 @@ GLOBAL_LIST_INIT(cursed_animal_masks, list( /obj/item/clothing/mask/pocketcatmask name = "peculiar cat mask" - desc = "this mask makes you a little uneasy" + desc = "This mask makes you a little uneasy." icon_state = "pocketmask" item_state = "pocketmask" flags_inv = HIDEFACE|HIDEHAIR|HIDEFACIALHAIR diff --git a/code/modules/clothing/neck/skillcapes/skillcapes.dm b/code/modules/clothing/neck/skillcapes/skillcapes.dm index 56972e5a33bc..6d67e97bed06 100644 --- a/code/modules/clothing/neck/skillcapes/skillcapes.dm +++ b/code/modules/clothing/neck/skillcapes/skillcapes.dm @@ -11,7 +11,7 @@ /obj/item/clothing/neck/skillcape/trimmed name = "trimmed cape of skill" - desc = "a golden trimmed cape, marks proof of excellence." + desc = "A golden-trimmed cape, marks proof of excellence." /obj/item/clothing/neck/skillcape/admin name = "cape of mighty judgement" diff --git a/code/modules/clothing/under/miscellaneous.dm b/code/modules/clothing/under/miscellaneous.dm index 78fbc7bae03f..64ab89735680 100644 --- a/code/modules/clothing/under/miscellaneous.dm +++ b/code/modules/clothing/under/miscellaneous.dm @@ -202,7 +202,7 @@ /obj/item/clothing/under/cloud name = "cloud" - desc = "cloud" + desc = "Cloud." icon_state = "cloud" can_adjust = FALSE diff --git a/code/modules/economy/pay_stand.dm b/code/modules/economy/pay_stand.dm index 1e32fe3adb1e..565956699d4e 100644 --- a/code/modules/economy/pay_stand.dm +++ b/code/modules/economy/pay_stand.dm @@ -1,6 +1,6 @@ /obj/machinery/paystand name = "unregistered pay stand" - desc = "an unregistered pay stand" + desc = "An unregistered pay stand, ready to be linked to an account." icon = 'icons/obj/economy.dmi' icon_state = "card_scanner" anchored = TRUE diff --git a/code/modules/events/shuttle_catastrophe.dm b/code/modules/events/shuttle_catastrophe.dm index 7fa850c78943..4ed74ae0b931 100644 --- a/code/modules/events/shuttle_catastrophe.dm +++ b/code/modules/events/shuttle_catastrophe.dm @@ -37,5 +37,5 @@ SSshuttle.load_template(new_shuttle) SSshuttle.existing_shuttle = SSshuttle.emergency SSshuttle.emergency.name = new_shuttle.name - SSshuttle.action_load(new_shuttle) + SSshuttle.action_load(new_shuttle, replace = TRUE) log_game("Shuttle Catastrophe set a new shuttle, [new_shuttle.name].") diff --git a/code/modules/food_and_drinks/drinks/drinks.dm b/code/modules/food_and_drinks/drinks/drinks.dm index 9880855e6d27..bbb28b85863c 100644 --- a/code/modules/food_and_drinks/drinks/drinks.dm +++ b/code/modules/food_and_drinks/drinks/drinks.dm @@ -3,7 +3,7 @@ //////////////////////////////////////////////////////////////////////////////// /obj/item/reagent_containers/food/drinks name = "drink" - desc = "yummy" + desc = "Yummy." icon = 'icons/obj/drinks.dmi' icon_state = "pineapplejuice" // Shouldn't see this anyways. lefthand_file = 'icons/mob/inhands/misc/food_lefthand.dmi' diff --git a/code/modules/food_and_drinks/food/snacks_seafood.dm b/code/modules/food_and_drinks/food/snacks_seafood.dm index d0574f6af193..46b3e93ee46f 100644 --- a/code/modules/food_and_drinks/food/snacks_seafood.dm +++ b/code/modules/food_and_drinks/food/snacks_seafood.dm @@ -178,7 +178,7 @@ /obj/item/reagent_containers/food/snacks/fishdumpling name = "fish dumpling" - desc = "a powerful little pocket of flavor." + desc = "A powerful little pocket of flavor." icon_state = "fishdumpling" bonus_reagents = list(/datum/reagent/consumable/nutriment = 6, /datum/reagent/consumable/nutriment/vitamin = 10) list_reagents = list(/datum/reagent/consumable/nutriment = 8, /datum/reagent/consumable/nutriment/vitamin = 15) //delicious onion and garlic and fish diff --git a/code/modules/holodeck/turfs.dm b/code/modules/holodeck/turfs.dm index dbcdde5169c5..c0b8bd142596 100644 --- a/code/modules/holodeck/turfs.dm +++ b/code/modules/holodeck/turfs.dm @@ -89,18 +89,18 @@ icon_state = SPACE_ICON_STATE // so realistic . = ..() -/turf/open/floor/holofloor/hyperspace - name = "\proper hyperspace" +/turf/open/floor/holofloor/bluespace + name = "\proper bluespace" icon = 'icons/turf/space.dmi' icon_state = "speedspace_ns_1" bullet_bounce_sound = null tiled_dirt = FALSE -/turf/open/floor/holofloor/hyperspace/Initialize(mapload) +/turf/open/floor/holofloor/bluespace/Initialize(mapload) icon_state = "speedspace_ns_[(x + 5*y + (y%2+1)*7)%15+1]" . = ..() -/turf/open/floor/holofloor/hyperspace/ns/Initialize(mapload) +/turf/open/floor/holofloor/bluespace/ns/Initialize(mapload) . = ..() icon_state = "speedspace_ns_[(x + 5*y + (y%2+1)*7)%15+1]" diff --git a/code/modules/jobs/departments/departments.dm b/code/modules/jobs/departments/departments.dm index a629c2eaab62..81b44473b7fa 100644 --- a/code/modules/jobs/departments/departments.dm +++ b/code/modules/jobs/departments/departments.dm @@ -43,7 +43,7 @@ department_experience_type = EXP_TYPE_COMMAND display_order = 1 label_class = "command" - ui_color = "#ccccff" + ui_color = "#6681a5" /datum/job_department/security @@ -53,7 +53,7 @@ department_experience_type = EXP_TYPE_SECURITY display_order = 2 label_class = "security" - ui_color = "#ffbbbb" + ui_color = "#d46a78" /datum/job_department/engineering @@ -63,7 +63,7 @@ department_experience_type = EXP_TYPE_ENGINEERING display_order = 3 label_class = "engineering" - ui_color = "#ffeeaa" + ui_color = "#dfb567" /datum/job_department/medical @@ -73,7 +73,7 @@ department_experience_type = EXP_TYPE_MEDICAL display_order = 4 label_class = "medical" - ui_color = "#c1e1ec" + ui_color = "#65b2bd" /datum/job_department/science @@ -83,7 +83,7 @@ department_experience_type = EXP_TYPE_SCIENCE display_order = 5 label_class = "science" - ui_color = "#ffddff" + ui_color = "#c973c9" /datum/job_department/cargo @@ -93,7 +93,7 @@ department_experience_type = EXP_TYPE_SUPPLY display_order = 6 label_class = "supply" - ui_color = "#d7b088" + ui_color = "#cf9c6c" /datum/job_department/service @@ -103,7 +103,7 @@ department_experience_type = EXP_TYPE_SERVICE display_order = 7 label_class = "service" - ui_color = "#ddddff" + ui_color = "#7cc46a" /datum/job_department/silicon @@ -113,7 +113,7 @@ department_experience_type = EXP_TYPE_SILICON display_order = 8 label_class = "silicon" - ui_color = "#ccffcc" + ui_color = "#5dbda0" /// Catch-all department for undefined jobs. diff --git a/code/modules/jobs/job_types/_job.dm b/code/modules/jobs/job_types/_job.dm index 0a7c80874597..f9ec46ba90f7 100644 --- a/code/modules/jobs/job_types/_job.dm +++ b/code/modules/jobs/job_types/_job.dm @@ -47,8 +47,6 @@ /// What kind of mob type joining players with this job as their assigned role are spawned as. var/spawn_type = /mob/living/carbon/human - /// Selection Color for job preferences - var/selection_color = "#ffffff" /// Alternate titles for the job var/list/alt_titles /// If this is set to TRUE, a text is printed to the player when jobs are assigned, telling him that he should let admins know that he has to disconnect. @@ -134,7 +132,6 @@ Here is another example of using this: /datum/job/doctor/proc/OmegaStationChanges() - selection_color = "#ffffff" total_positions = 3 spawn_positions = 3 added_access = list() diff --git a/code/modules/jobs/job_types/ai.dm b/code/modules/jobs/job_types/ai.dm index 62a8798e8b7c..c2f33e9b666b 100644 --- a/code/modules/jobs/job_types/ai.dm +++ b/code/modules/jobs/job_types/ai.dm @@ -6,7 +6,6 @@ faction = "Station" total_positions = 1 spawn_positions = 1 - selection_color = "#ccffcc" supervisors = "your laws" req_admin_notify = TRUE minimal_player_age = 30 diff --git a/code/modules/jobs/job_types/artist.dm b/code/modules/jobs/job_types/artist.dm index 55784466133e..28dfe08cc02e 100644 --- a/code/modules/jobs/job_types/artist.dm +++ b/code/modules/jobs/job_types/artist.dm @@ -7,7 +7,6 @@ total_positions = 1 spawn_positions = 1 supervisors = "the head of personnel" - selection_color = "#dddddd" outfit = /datum/outfit/job/artist alt_titles = list("Painter", "Composer", "Artisan") diff --git a/code/modules/jobs/job_types/assistant.dm b/code/modules/jobs/job_types/assistant.dm index 666a68b0f168..b2427dfdefde 100644 --- a/code/modules/jobs/job_types/assistant.dm +++ b/code/modules/jobs/job_types/assistant.dm @@ -9,7 +9,6 @@ Assistant total_positions = 5 spawn_positions = 5 supervisors = "absolutely everyone" - selection_color = "#dddddd" added_access = list() //See /datum/job/assistant/get_access() base_access = list() //See /datum/job/assistant/get_access() outfit = /datum/outfit/job/assistant diff --git a/code/modules/jobs/job_types/atmospheric_technician.dm b/code/modules/jobs/job_types/atmospheric_technician.dm index 2d4b57815cd2..dc0d460ed354 100644 --- a/code/modules/jobs/job_types/atmospheric_technician.dm +++ b/code/modules/jobs/job_types/atmospheric_technician.dm @@ -7,7 +7,6 @@ total_positions = 3 spawn_positions = 2 supervisors = "the chief engineer" - selection_color = "#fff5cc" exp_requirements = 180 exp_type = EXP_TYPE_CREW alt_titles = list("Life-support Technician", "Fire Suppression Specialist", "Atmospherics Trainee", "Environmental Maintainer", "Fusion Specialist") diff --git a/code/modules/jobs/job_types/bartender.dm b/code/modules/jobs/job_types/bartender.dm index 66fce46dc27a..eca2c26c67e6 100644 --- a/code/modules/jobs/job_types/bartender.dm +++ b/code/modules/jobs/job_types/bartender.dm @@ -7,7 +7,6 @@ total_positions = 1 spawn_positions = 1 supervisors = "the head of personnel" - selection_color = "#bbe291" exp_type_department = EXP_TYPE_SERVICE // This is so the jobs menu can work properly alt_titles = list("Barkeep", "Tapster", "Barista", "Mixologist") diff --git a/code/modules/jobs/job_types/botanist.dm b/code/modules/jobs/job_types/botanist.dm index 3e366db34668..b63b4e969c52 100644 --- a/code/modules/jobs/job_types/botanist.dm +++ b/code/modules/jobs/job_types/botanist.dm @@ -7,7 +7,6 @@ total_positions = 3 spawn_positions = 2 supervisors = "the head of personnel" - selection_color = "#bbe291" outfit = /datum/outfit/job/botanist diff --git a/code/modules/jobs/job_types/captain.dm b/code/modules/jobs/job_types/captain.dm index 6365594bd8dc..75d55d8b4aed 100644 --- a/code/modules/jobs/job_types/captain.dm +++ b/code/modules/jobs/job_types/captain.dm @@ -10,7 +10,6 @@ total_positions = 1 spawn_positions = 1 supervisors = "Nanotrasen officers and Space law" //Changed to officer to separate from CentCom officials being their superior. - selection_color = "#ccccff" req_admin_notify = 1 space_law_notify = 1 //Yogs minimal_player_age = 14 diff --git a/code/modules/jobs/job_types/cargo_technician.dm b/code/modules/jobs/job_types/cargo_technician.dm index 14ea8105f32b..ab2a5973a9bd 100644 --- a/code/modules/jobs/job_types/cargo_technician.dm +++ b/code/modules/jobs/job_types/cargo_technician.dm @@ -9,7 +9,6 @@ total_positions = 2 spawn_positions = 1 supervisors = "the quartermaster and the head of personnel" - selection_color = "#dcba97" outfit = /datum/outfit/job/cargo_tech diff --git a/code/modules/jobs/job_types/chaplain.dm b/code/modules/jobs/job_types/chaplain.dm index 3cd1ee881bd2..42a2cb83d797 100644 --- a/code/modules/jobs/job_types/chaplain.dm +++ b/code/modules/jobs/job_types/chaplain.dm @@ -8,7 +8,6 @@ total_positions = 1 spawn_positions = 1 supervisors = "the head of personnel" - selection_color = "#dddddd" outfit = /datum/outfit/job/chaplain diff --git a/code/modules/jobs/job_types/chemist.dm b/code/modules/jobs/job_types/chemist.dm index 140bd0337c28..72b93fbb9ddc 100644 --- a/code/modules/jobs/job_types/chemist.dm +++ b/code/modules/jobs/job_types/chemist.dm @@ -8,7 +8,6 @@ total_positions = 2 spawn_positions = 2 supervisors = "the chief medical officer" - selection_color = "#d4ebf2" exp_type = EXP_TYPE_CREW exp_requirements = 120 exp_type_department = EXP_TYPE_MEDICAL diff --git a/code/modules/jobs/job_types/chief_engineer.dm b/code/modules/jobs/job_types/chief_engineer.dm index 9c0b7297f63d..c7004ee741a3 100644 --- a/code/modules/jobs/job_types/chief_engineer.dm +++ b/code/modules/jobs/job_types/chief_engineer.dm @@ -10,7 +10,6 @@ total_positions = 1 spawn_positions = 1 supervisors = "the captain" - selection_color = "#ffeeaa" req_admin_notify = 1 minimal_player_age = 7 exp_requirements = 1500 //25 hours diff --git a/code/modules/jobs/job_types/chief_medical_officer.dm b/code/modules/jobs/job_types/chief_medical_officer.dm index 2bc428901cc5..2dec1ebd5fe6 100644 --- a/code/modules/jobs/job_types/chief_medical_officer.dm +++ b/code/modules/jobs/job_types/chief_medical_officer.dm @@ -10,7 +10,6 @@ total_positions = 1 spawn_positions = 1 supervisors = "the captain" - selection_color = "#c1e1ec" req_admin_notify = 1 minimal_player_age = 7 exp_requirements = 1500 //25 hours diff --git a/code/modules/jobs/job_types/clown.dm b/code/modules/jobs/job_types/clown.dm index 7fc1b36a9f38..4c38c09cb965 100644 --- a/code/modules/jobs/job_types/clown.dm +++ b/code/modules/jobs/job_types/clown.dm @@ -7,7 +7,6 @@ total_positions = 1 spawn_positions = 1 supervisors = "the head of personnel" - selection_color = "#dddddd" outfit = /datum/outfit/job/clown diff --git a/code/modules/jobs/job_types/cook.dm b/code/modules/jobs/job_types/cook.dm index b0efc565e7a6..3100197198af 100644 --- a/code/modules/jobs/job_types/cook.dm +++ b/code/modules/jobs/job_types/cook.dm @@ -7,7 +7,6 @@ total_positions = 2 spawn_positions = 1 supervisors = "the head of personnel" - selection_color = "#bbe291" var/cooks = 0 //Counts cooks amount outfit = /datum/outfit/job/cook diff --git a/code/modules/jobs/job_types/curator.dm b/code/modules/jobs/job_types/curator.dm index eb7aae9266a3..5d8e15bc38ec 100644 --- a/code/modules/jobs/job_types/curator.dm +++ b/code/modules/jobs/job_types/curator.dm @@ -8,7 +8,6 @@ total_positions = 1 spawn_positions = 1 supervisors = "the head of personnel" - selection_color = "#dddddd" outfit = /datum/outfit/job/curator diff --git a/code/modules/jobs/job_types/cyborg.dm b/code/modules/jobs/job_types/cyborg.dm index c1b202ae57f1..b2b714a9d6c1 100644 --- a/code/modules/jobs/job_types/cyborg.dm +++ b/code/modules/jobs/job_types/cyborg.dm @@ -7,7 +7,6 @@ total_positions = 0 spawn_positions = 2 supervisors = "your laws and the AI" //Nodrak - selection_color = "#ddffdd" minimal_player_age = 21 exp_requirements = 120 exp_type = EXP_TYPE_CREW diff --git a/code/modules/jobs/job_types/detective.dm b/code/modules/jobs/job_types/detective.dm index ddc4fd758b16..328700db625e 100644 --- a/code/modules/jobs/job_types/detective.dm +++ b/code/modules/jobs/job_types/detective.dm @@ -9,7 +9,6 @@ total_positions = 1 spawn_positions = 1 supervisors = "the head of security" - selection_color = "#ffeeee" minimal_player_age = 7 exp_requirements = 180 exp_type = EXP_TYPE_SECURITY diff --git a/code/modules/jobs/job_types/geneticist.dm b/code/modules/jobs/job_types/geneticist.dm index 2b92768b71bd..27db89c87a40 100644 --- a/code/modules/jobs/job_types/geneticist.dm +++ b/code/modules/jobs/job_types/geneticist.dm @@ -7,7 +7,6 @@ total_positions = 2 spawn_positions = 2 supervisors = "the chief medical officer and research director" - selection_color = "#d4ebf2" exp_type = EXP_TYPE_CREW exp_requirements = 60 alt_titles = list("DNA Mechanic", "Bioengineer", "Junior Geneticist", "Gene Splicer", "Mutation Specialist") diff --git a/code/modules/jobs/job_types/head_of_personnel.dm b/code/modules/jobs/job_types/head_of_personnel.dm index 4d684d9a14ca..681574e1cfaf 100644 --- a/code/modules/jobs/job_types/head_of_personnel.dm +++ b/code/modules/jobs/job_types/head_of_personnel.dm @@ -10,7 +10,6 @@ total_positions = 1 spawn_positions = 1 supervisors = "the captain" - selection_color = "#ddddff" req_admin_notify = 1 minimal_player_age = 10 exp_requirements = 720 //fairly low skill job diff --git a/code/modules/jobs/job_types/head_of_security.dm b/code/modules/jobs/job_types/head_of_security.dm index b3449b86cc8e..434c3627504c 100644 --- a/code/modules/jobs/job_types/head_of_security.dm +++ b/code/modules/jobs/job_types/head_of_security.dm @@ -10,7 +10,6 @@ total_positions = 1 spawn_positions = 1 supervisors = "the captain" - selection_color = "#ffdddd" req_admin_notify = 1 minimal_player_age = 14 exp_requirements = 1500 //25 hours diff --git a/code/modules/jobs/job_types/janitor.dm b/code/modules/jobs/job_types/janitor.dm index 55e6708188cd..a14f9ee38454 100644 --- a/code/modules/jobs/job_types/janitor.dm +++ b/code/modules/jobs/job_types/janitor.dm @@ -7,7 +7,6 @@ total_positions = 2 spawn_positions = 1 supervisors = "the head of personnel" - selection_color = "#bbe291" outfit = /datum/outfit/job/janitor diff --git a/code/modules/jobs/job_types/lawyer.dm b/code/modules/jobs/job_types/lawyer.dm index 2e4c1aaa7850..edcce8838c85 100644 --- a/code/modules/jobs/job_types/lawyer.dm +++ b/code/modules/jobs/job_types/lawyer.dm @@ -8,7 +8,6 @@ total_positions = 2 spawn_positions = 2 supervisors = "the head of personnel" - selection_color = "#dddddd" var/lawyers = 0 //Counts lawyer amount alt_titles = list("Prosecutor", "Defense Attorney", "Paralegal", "Ace Attorney") diff --git a/code/modules/jobs/job_types/medical_doctor.dm b/code/modules/jobs/job_types/medical_doctor.dm index dd83f89c8d16..b44a4dcf9e6a 100644 --- a/code/modules/jobs/job_types/medical_doctor.dm +++ b/code/modules/jobs/job_types/medical_doctor.dm @@ -8,7 +8,6 @@ total_positions = 5 spawn_positions = 3 supervisors = "the chief medical officer" - selection_color = "#d4ebf2" exp_requirements = 180 exp_type = EXP_TYPE_CREW alt_titles = list("Physician", "Surgeon", "Nurse", "Medical Resident", "Attending Physician", "General Practitioner") diff --git a/code/modules/jobs/job_types/mime.dm b/code/modules/jobs/job_types/mime.dm index c64526aeb6bb..3826212f52f1 100644 --- a/code/modules/jobs/job_types/mime.dm +++ b/code/modules/jobs/job_types/mime.dm @@ -7,7 +7,6 @@ total_positions = 1 spawn_positions = 1 supervisors = "the head of personnel" - selection_color = "#dddddd" outfit = /datum/outfit/job/mime diff --git a/code/modules/jobs/job_types/quartermaster.dm b/code/modules/jobs/job_types/quartermaster.dm index e30304d00b2c..4442590fe746 100644 --- a/code/modules/jobs/job_types/quartermaster.dm +++ b/code/modules/jobs/job_types/quartermaster.dm @@ -8,7 +8,6 @@ total_positions = 1 spawn_positions = 1 supervisors = "the head of personnel" - selection_color = "#d7b088" outfit = /datum/outfit/job/quartermaster alt_titles = list("Stock Controller", "Cargo Coordinator", "Shipping Overseer", "Postmaster General") added_access = list() diff --git a/code/modules/jobs/job_types/research_director.dm b/code/modules/jobs/job_types/research_director.dm index e381a867427a..b6a91ef5c87d 100644 --- a/code/modules/jobs/job_types/research_director.dm +++ b/code/modules/jobs/job_types/research_director.dm @@ -11,7 +11,6 @@ total_positions = 1 spawn_positions = 1 supervisors = "the captain" - selection_color = "#ffddff" req_admin_notify = 1 minimal_player_age = 7 exp_type_department = EXP_TYPE_SCIENCE diff --git a/code/modules/jobs/job_types/roboticist.dm b/code/modules/jobs/job_types/roboticist.dm index b798d1c85e75..b90ccf3d6aec 100644 --- a/code/modules/jobs/job_types/roboticist.dm +++ b/code/modules/jobs/job_types/roboticist.dm @@ -7,7 +7,6 @@ total_positions = 2 spawn_positions = 2 supervisors = "the research director" - selection_color = "#ffeeff" exp_requirements = 60 exp_type = EXP_TYPE_CREW alt_titles = list("Augmentation Theorist", "Cyborg Maintainer", "Robotics Intern", "Biomechanical Engineer", "Mechatronic Engineer", "Machinist", "Chrome Shaman", "Ripperdoc") diff --git a/code/modules/jobs/job_types/scientist.dm b/code/modules/jobs/job_types/scientist.dm index b69a337ab166..725a217f3155 100644 --- a/code/modules/jobs/job_types/scientist.dm +++ b/code/modules/jobs/job_types/scientist.dm @@ -7,7 +7,6 @@ total_positions = 5 spawn_positions = 3 supervisors = "the research director" - selection_color = "#ffeeff" exp_requirements = 180 exp_type = EXP_TYPE_CREW alt_titles = list("Researcher", "Toxins Specialist", "Physicist", "Test Associate", "Anomalist", "Quantum Physicist", "Theoretical Physicist", "Xenobiologist", "Explosives Technician", "Hypothetical Physicist") diff --git a/code/modules/jobs/job_types/security_officer.dm b/code/modules/jobs/job_types/security_officer.dm index 30564c5c89cf..1b231992929c 100644 --- a/code/modules/jobs/job_types/security_officer.dm +++ b/code/modules/jobs/job_types/security_officer.dm @@ -9,7 +9,6 @@ total_positions = 5 //Handled in /datum/controller/occupations/proc/setup_officer_positions() spawn_positions = 5 //Handled in /datum/controller/occupations/proc/setup_officer_positions() supervisors = "the head of security, and the head of your assigned department (if applicable)" - selection_color = "#ffeeee" minimal_player_age = 7 exp_requirements = 300 exp_type = EXP_TYPE_CREW diff --git a/code/modules/jobs/job_types/shaft_miner.dm b/code/modules/jobs/job_types/shaft_miner.dm index 1163f300518e..5776843d03b4 100644 --- a/code/modules/jobs/job_types/shaft_miner.dm +++ b/code/modules/jobs/job_types/shaft_miner.dm @@ -8,7 +8,6 @@ total_positions = 3 spawn_positions = 3 supervisors = "the quartermaster and the head of personnel" - selection_color = "#dcba97" alt_titles = list("Lavaland Scout", "Prospector", "Junior Miner", "Major Miner", "Surveyor") outfit = /datum/outfit/job/miner diff --git a/code/modules/jobs/job_types/station_engineer.dm b/code/modules/jobs/job_types/station_engineer.dm index 1caf26068293..e96c1dee2768 100644 --- a/code/modules/jobs/job_types/station_engineer.dm +++ b/code/modules/jobs/job_types/station_engineer.dm @@ -8,7 +8,6 @@ total_positions = 5 spawn_positions = 5 supervisors = "the chief engineer" - selection_color = "#fff5cc" exp_requirements = 180 exp_type = EXP_TYPE_CREW alt_titles = list("Engine Technician", "Solar Engineer", "Project Engineer", "Junior Engineer", "Construction Specialist") diff --git a/code/modules/jobs/job_types/virologist.dm b/code/modules/jobs/job_types/virologist.dm index 837e74c86c6a..1e31e5e5330f 100644 --- a/code/modules/jobs/job_types/virologist.dm +++ b/code/modules/jobs/job_types/virologist.dm @@ -8,7 +8,6 @@ total_positions = 1 spawn_positions = 1 supervisors = "the chief medical officer" - selection_color = "#d4ebf2" exp_type = EXP_TYPE_CREW exp_requirements = 120 minimal_player_age = 7 diff --git a/code/modules/jobs/job_types/warden.dm b/code/modules/jobs/job_types/warden.dm index ccb68f5c0e1c..84f8838d2b08 100644 --- a/code/modules/jobs/job_types/warden.dm +++ b/code/modules/jobs/job_types/warden.dm @@ -10,7 +10,6 @@ total_positions = 1 spawn_positions = 1 supervisors = "the head of security" - selection_color = "#ffeeee" minimal_player_age = 7 exp_requirements = 600 exp_type = EXP_TYPE_CREW diff --git a/code/modules/mining/aux_base_camera.dm b/code/modules/mining/aux_base_camera.dm index 284b9641ff30..46f4850e0a7a 100644 --- a/code/modules/mining/aux_base_camera.dm +++ b/code/modules/mining/aux_base_camera.dm @@ -22,7 +22,7 @@ dir = direct //This camera eye is visible as a drone, and needs to keep the dir updated ..() -/obj/item/construction/rcd/internal //Base console's internal RCD. Roundstart consoles are filled, rebuilt cosoles start empty. +/obj/item/construction/rcd/internal //Base console's internal RCD. Roundstart consoles are filled, rebuilt consoles start empty. name = "internal RCD" max_matter = 600 //Bigger container and faster speeds due to being specialized and stationary. no_ammo_message = span_warning("Internal matter exhausted. Please add additional materials.") @@ -43,10 +43,8 @@ var/obj/item/construction/rcd/internal/RCD //Internal RCD. The computer passes user commands to this in order to avoid massive copypaste. var/obj/machinery/computer/auxiliary_base/found_aux_console //Tracker for the Aux base console, so the eye can always find it. - var/datum/action/innate/aux_base/switch_mode/switch_mode_action = new //Action for switching the RCD's build modes + var/datum/action/innate/aux_base/configure_mode/configure_mode_action = new //Action for switching the RCD's build modes var/datum/action/innate/aux_base/build/build_action = new //Action for using the RCD - var/datum/action/innate/aux_base/airlock_type/airlock_mode_action = new //Action for setting the airlock type - var/datum/action/innate/aux_base/window_type/window_action = new //Action for setting the window type var/fans_remaining = 0 //Number of fans in stock. var/datum/action/innate/aux_base/place_fan/fan_action = new //Action for spawning fans var/turret_stock = 0 //Turrets in stock @@ -96,26 +94,16 @@ /obj/machinery/computer/camera_advanced/base_construction/GrantActions(mob/living/user) ..() - if(switch_mode_action) - switch_mode_action.target = src - switch_mode_action.Grant(user) - actions += switch_mode_action + if(configure_mode_action) + configure_mode_action.target = src + configure_mode_action.Grant(user) + actions += configure_mode_action if(build_action) build_action.target = src build_action.Grant(user) actions += build_action - if(airlock_mode_action) - airlock_mode_action.target = src - airlock_mode_action.Grant(user) - actions += airlock_mode_action - - if(window_action) - window_action.target = src - window_action.Grant(user) - actions += window_action - if(fan_action) fan_action.target = src fan_action.Grant(user) @@ -190,38 +178,17 @@ B.RCD.afterattack(rcd_target, owner, TRUE) //Activate the RCD and force it to work remotely! playsound(target_turf, 'sound/items/deconstruct.ogg', 60, 1) -/datum/action/innate/aux_base/switch_mode - name = "Switch Mode" - button_icon_state = "builder_mode" - -/datum/action/innate/aux_base/switch_mode/Activate() - if(..()) - return - - var/list/buildlist = list("Walls and Floors" = RCD_FLOORWALL,"Airlocks" = RCD_AIRLOCK,"Deconstruction" = RCD_DECONSTRUCT,"Windows and Grilles" = RCD_WINDOWGRILLE) - var/buildmode = input(owner, "Set construction mode.", "Base Console", null) in buildlist - B.RCD.mode = buildlist[buildmode] - to_chat(owner, "Build mode is now [buildmode].") +/datum/action/innate/aux_base/configure_mode + name = "Configure RCD" + button_icon = 'icons/obj/tools.dmi' + button_icon_state = "rcd" -/datum/action/innate/aux_base/airlock_type - name = "Select Airlock Type" - button_icon_state = "airlock_select" - -datum/action/innate/aux_base/airlock_type/Activate() +/datum/action/innate/aux_base/configure_mode/Activate() if(..()) return - B.RCD.change_airlock_setting(owner, remote_eye) - - -datum/action/innate/aux_base/window_type - name = "Select Window Glass" - button_icon_state = "window_select" - -datum/action/innate/aux_base/window_type/Activate() - if(..()) - return - B.RCD.toggle_window_glass(owner) + B.RCD.owner = B + B.RCD.ui_interact(owner) datum/action/innate/aux_base/place_fan name = "Place Tiny Fan" diff --git a/code/modules/mining/fulton.dm b/code/modules/mining/fulton.dm index 7e085227c744..19eea5ae191a 100644 --- a/code/modules/mining/fulton.dm +++ b/code/modules/mining/fulton.dm @@ -200,7 +200,7 @@ GLOBAL_LIST_EMPTY(total_extraction_beacons) /obj/effect/extraction_holder name = "extraction holder" - desc = "you shouldnt see this" + desc = "You shouldn't see this." var/atom/movable/stored_obj /obj/item/extraction_pack/proc/check_for_living_mobs(atom/A) diff --git a/code/modules/mining/lavaland/necropolis_chests.dm b/code/modules/mining/lavaland/necropolis_chests.dm index 8eb74ad1ddfe..859732d9b6d3 100644 --- a/code/modules/mining/lavaland/necropolis_chests.dm +++ b/code/modules/mining/lavaland/necropolis_chests.dm @@ -317,7 +317,7 @@ GLOBAL_LIST_EMPTY(aide_list) /obj/effect/wisp/proc/update_user_sight(mob/user) SIGNAL_HANDLER - user.sight |= sight_flags + user.add_sight(sight_flags) if(!isnull(color_cutoffs)) user.lighting_color_cutoffs = blend_cutoff_colors(user.lighting_color_cutoffs, color_cutoffs) diff --git a/code/modules/mining/machine_vending.dm b/code/modules/mining/machine_vending.dm index d6597e8a269f..41065300c24f 100644 --- a/code/modules/mining/machine_vending.dm +++ b/code/modules/mining/machine_vending.dm @@ -19,15 +19,19 @@ var/icon_deny = "mining-deny" var/list/prize_list = list( //if you add something to this, please, for the love of god, sort it by price/type. use tabs and not spaces. new /datum/data/mining_equipment("Kinetic Accelerator", /obj/item/gun/energy/kinetic_accelerator, 750, VENDING_WEAPON), - new /datum/data/mining_equipment("Kinetic Crusher", /obj/item/kinetic_crusher, 750, VENDING_WEAPON), + new /datum/data/mining_equipment("Kinetic Crusher", /obj/item/kinetic_crusher, 750, VENDING_WEAPON), new /datum/data/mining_equipment("Resonator", /obj/item/resonator, 800, VENDING_WEAPON), new /datum/data/mining_equipment("Super Resonator", /obj/item/resonator/upgraded, 2500, VENDING_WEAPON), new /datum/data/mining_equipment("Kinetic Javelin", /obj/item/kinetic_javelin/blue, 1000, VENDING_WEAPON), //YOGS EDIT new /datum/data/mining_equipment("Silver Pickaxe", /obj/item/pickaxe/silver, 1000, VENDING_WEAPON), new /datum/data/mining_equipment("Diamond Pickaxe", /obj/item/pickaxe/diamond, 2000, VENDING_WEAPON), new /datum/data/mining_equipment("Mini Plasma Cutter", /obj/item/gun/energy/plasmacutter/mini, 2500, VENDING_WEAPON), - new /datum/data/mining_equipment("Plasma Cutter Shotgun", /obj/item/gun/energy/plasmacutter/scatter, 6000, VENDING_WEAPON), - new /datum/data/mining_equipment("Plasma Shotgun Upgrade", /obj/item/upgrade/plasmacutter/defuser, 1000, VENDING_WEAPON), + new /datum/data/mining_equipment("Plasma Cutter Shotgun", /obj/item/gun/energy/plasmacutter/scatter, 5000, VENDING_WEAPON), + new /datum/data/mining_equipment("PC Defuser Upgrade", /obj/item/upgrade/plasmacutter/defuser, 1000, VENDING_UPGRADE), + new /datum/data/mining_equipment("PC Capacity Upgrade", /obj/item/upgrade/plasmacutter/capacity, 4500, VENDING_UPGRADE), + new /datum/data/mining_equipment("PC Cooldown Upgrade", /obj/item/upgrade/plasmacutter/cooldown, 5000, VENDING_UPGRADE), + new /datum/data/mining_equipment("PC Range Upgrade", /obj/item/upgrade/plasmacutter/range, 5000, VENDING_UPGRADE), + new /datum/data/mining_equipment("PC Ore Upgrade", /obj/item/upgrade/plasmacutter/ore, 10000, VENDING_UPGRADE), new /datum/data/mining_equipment("KA Minebot Passthrough", /obj/item/borg/upgrade/modkit/minebot_passthrough, 100, VENDING_UPGRADE), new /datum/data/mining_equipment("KA White Tracer Rounds", /obj/item/borg/upgrade/modkit/tracer, 100, VENDING_UPGRADE), new /datum/data/mining_equipment("KA Adjustable Tracer Rounds", /obj/item/borg/upgrade/modkit/tracer/adjustable, 150, VENDING_UPGRADE), @@ -303,9 +307,12 @@ new /datum/data/mining_equipment("Diamond Pickaxe", /obj/item/pickaxe/diamond, 1500, VENDING_WEAPON), new /datum/data/mining_equipment("Mini Plasma Cutter", /obj/item/gun/energy/plasmacutter/mini, 500, VENDING_WEAPON), new /datum/data/mining_equipment("Plasma Cutter" , /obj/item/gun/energy/plasmacutter, 2500, VENDING_WEAPON), - new /datum/data/mining_equipment("Plasma Cutter Shotgun", /obj/item/gun/energy/plasmacutter/scatter, 6000, VENDING_WEAPON), - new /datum/data/mining_equipment("PS Defuser Upgrade", /obj/item/upgrade/plasmacutter/defuser, 1000, VENDING_UPGRADE), - new /datum/data/mining_equipment("PS Capacity Upgrade", /obj/item/upgrade/plasmacutter/capacity, 4500, VENDING_UPGRADE), + new /datum/data/mining_equipment("Plasma Cutter Shotgun", /obj/item/gun/energy/plasmacutter/scatter, 5000, VENDING_WEAPON), + new /datum/data/mining_equipment("PC Defuser Upgrade", /obj/item/upgrade/plasmacutter/defuser, 1000, VENDING_UPGRADE), + new /datum/data/mining_equipment("PC Capacity Upgrade", /obj/item/upgrade/plasmacutter/capacity, 4500, VENDING_UPGRADE), + new /datum/data/mining_equipment("PC Cooldown Upgrade", /obj/item/upgrade/plasmacutter/cooldown, 5000, VENDING_UPGRADE), + new /datum/data/mining_equipment("PC Range Upgrade", /obj/item/upgrade/plasmacutter/range, 5000, VENDING_UPGRADE), + new /datum/data/mining_equipment("PC Ore Upgrade", /obj/item/upgrade/plasmacutter/ore, 10000, VENDING_UPGRADE), new /datum/data/mining_equipment("KA Minebot Passthrough", /obj/item/borg/upgrade/modkit/minebot_passthrough, 100, VENDING_UPGRADE), new /datum/data/mining_equipment("KA White Tracer Rounds", /obj/item/borg/upgrade/modkit/tracer, 100, VENDING_UPGRADE), new /datum/data/mining_equipment("KA Adjustable Tracer Rounds", /obj/item/borg/upgrade/modkit/tracer/adjustable, 150, VENDING_UPGRADE), diff --git a/code/modules/mob/dead/new_player/latejoin_menu.dm b/code/modules/mob/dead/new_player/latejoin_menu.dm index 80dd13b9359a..6a46a49dc1cc 100644 --- a/code/modules/mob/dead/new_player/latejoin_menu.dm +++ b/code/modules/mob/dead/new_player/latejoin_menu.dm @@ -43,15 +43,10 @@ GLOBAL_DATUM_INIT(latejoin_menu, /datum/latejoin_menu, new) // FIXME: this can cause a runtime since user can be a living mob if(istype(user)) user.jobs_menu_mounted = FALSE - addtimer(CALLBACK(src, PROC_REF(scream_at_player), user), 5 SECONDS) ui = new(user, src, "JobSelection", "Latejoin Menu") ui.open() -/datum/latejoin_menu/proc/scream_at_player(mob/dead/new_player/player) - if(!player.jobs_menu_mounted) - to_chat(player, span_notice("If the late join menu isn't showing, you can open the fallback menu using the verb in the Preferences tab!")) - /datum/latejoin_menu/ui_data(mob/user) var/mob/dead/new_player/owner = user var/list/departments = list() diff --git a/code/modules/mob/living/carbon/carbon.dm b/code/modules/mob/living/carbon/carbon.dm index 54235f77176e..6fe67f54b776 100644 --- a/code/modules/mob/living/carbon/carbon.dm +++ b/code/modules/mob/living/carbon/carbon.dm @@ -596,7 +596,7 @@ set_invis_see(min(glasses.invis_view, see_invisible)) if(!isnull(glasses.lighting_cutoff)) lighting_cutoff = max(lighting_cutoff, glasses.lighting_cutoff) - if(!isnull(glasses.color_cutoffs)) + if(length(glasses.color_cutoffs)) lighting_color_cutoffs = blend_cutoff_colors(lighting_color_cutoffs, glasses.color_cutoffs) diff --git a/code/modules/mob/living/carbon/inventory.dm b/code/modules/mob/living/carbon/inventory.dm index 21becca2178d..8e58ff3cf1a6 100644 --- a/code/modules/mob/living/carbon/inventory.dm +++ b/code/modules/mob/living/carbon/inventory.dm @@ -70,7 +70,7 @@ if(observe.client) observe.client.screen -= I I.forceMove(src) - I.plane = ABOVE_HUD_PLANE + SET_PLANE_EXPLICIT(I, ABOVE_HUD_PLANE, src) I.appearance_flags |= NO_CLIENT_COLOR var/not_handled = FALSE switch(slot) diff --git a/code/modules/mob/living/simple_animal/friendly/cockroach.dm b/code/modules/mob/living/simple_animal/friendly/cockroach.dm index b3ba2a8d27d0..de0c0ec01e7e 100644 --- a/code/modules/mob/living/simple_animal/friendly/cockroach.dm +++ b/code/modules/mob/living/simple_animal/friendly/cockroach.dm @@ -28,6 +28,16 @@ var/squish_chance = 50 del_on_death = 1 + +/mob/living/simple_animal/cockroach/Initialize(mapload) + . = ..() + AddComponent( \ + /datum/component/squashable, \ + squash_chance = 50, \ + squash_damage = 1, \ + squash_flags = SQUASHED_SHOULD_BE_GIBBED|SQUASHED_ALWAYS_IF_DEAD|SQUASHED_DONT_SQUASH_IN_CONTENTS, \ + ) + /mob/living/simple_animal/cockroach/death(gibbed) if(SSticker.mode && SSticker.mode.station_was_nuked) //If the nuke is going off, then cockroaches are invincible. Keeps the nuke from killing them, cause cockroaches are immune to nukes. return diff --git a/code/modules/mob/living/simple_animal/hostile/mining_mobs/drakeling.dm b/code/modules/mob/living/simple_animal/hostile/mining_mobs/drakeling.dm index 954cbf4cb10d..549cfc784d40 100644 --- a/code/modules/mob/living/simple_animal/hostile/mining_mobs/drakeling.dm +++ b/code/modules/mob/living/simple_animal/hostile/mining_mobs/drakeling.dm @@ -113,7 +113,7 @@ /datum/action/cooldown/spell/pointed/drakeling name = "ULTRA DRAGON ATTACK" - desc = "if you can see this something has probably gone very wrong and you should make a bug report." + desc = "If you can see this something has probably gone very wrong and you should make a bug report." background_icon_state = "bg_demon" panel = "Dragon" diff --git a/code/modules/mob/living/simple_animal/hostile/retaliate/frog.dm b/code/modules/mob/living/simple_animal/hostile/retaliate/frog.dm index 7ac2c9a5a278..681949c38483 100644 --- a/code/modules/mob/living/simple_animal/hostile/retaliate/frog.dm +++ b/code/modules/mob/living/simple_animal/hostile/retaliate/frog.dm @@ -36,9 +36,13 @@ icon_living = "rare_frog" icon_dead = "rare_frog_dead" butcher_results = list(/obj/item/reagent_containers/food/snacks/nugget = 5) + var/static/list/loc_connections = list( + COMSIG_ATOM_ENTERED = PROC_REF(on_entered), + ) + AddElement(/datum/element/connect_loc, loc_connections) -/mob/living/simple_animal/hostile/retaliate/frog/Crossed(AM as mob|obj) - . = ..() + +/mob/living/simple_animal/hostile/retaliate/frog/proc/on_entered(datum/source, atom/movable/AM, ...) if(!stat && isliving(AM)) var/mob/living/L = AM if(L.mob_size > MOB_SIZE_TINY) diff --git a/code/modules/mob/mob.dm b/code/modules/mob/mob.dm index 749f3a4387b1..d250293ede6c 100644 --- a/code/modules/mob/mob.dm +++ b/code/modules/mob/mob.dm @@ -161,7 +161,7 @@ hud_list[hud] = list() else - var/image/I = image('yogstation/icons/mob/hud.dmi', src, "") + var/image/I = image('modular_dripstation/icons/mob/hud.dmi', src, "") //dripstation edit I.appearance_flags = RESET_COLOR|RESET_TRANSFORM hud_list[hud] = I set_hud_image_active(hud, update_huds = FALSE) //by default everything is active. but dont add it to huds to keep control. diff --git a/code/modules/power/cable.dm b/code/modules/power/cable.dm index 6747f04952d6..c604ea038554 100644 --- a/code/modules/power/cable.dm +++ b/code/modules/power/cable.dm @@ -27,6 +27,7 @@ By design, d1 is the smallest direction and d2 is the highest desc = "A flexible, superconducting insulated cable for heavy-duty power transfer." icon = 'icons/obj/power_cond/cables.dmi' icon_state = "0-1" + plane = FLOOR_PLANE layer = WIRE_LAYER //Above hidden pipes, GAS_PIPE_HIDDEN_LAYER anchored = TRUE obj_flags = CAN_BE_HIT | ON_BLUEPRINTS @@ -89,7 +90,11 @@ By design, d1 is the smallest direction and d2 is the highest cable_color = param_color || cable_color || pick(cable_colors) if(cable_colors[cable_color]) cable_color = cable_colors[cable_color] + return INITIALIZE_HINT_LATELOAD + +/obj/structure/cable/LateInitialize() update_appearance(UPDATE_ICON) + //is_fully_initialized = TRUE /obj/structure/cable/Destroy() // called when a cable is deleted if(powernet) diff --git a/code/modules/power/reactor/reactor.dm b/code/modules/power/reactor/reactor.dm index 3819a4d72a5e..7de1e268229f 100644 --- a/code/modules/power/reactor/reactor.dm +++ b/code/modules/power/reactor/reactor.dm @@ -175,12 +175,15 @@ to_chat(user, span_notice("The reactor has no fuel rods!")) return TRUE var/obj/item/fuel_rod/rod = tgui_input_list(usr, "Select a fuel rod to remove", "Fuel Rods", fuel_rods) - if(rod && istype(rod) && I.use_tool(src, user, removal_time)) + if(rod && istype(rod) && I.use_tool(src, user, removal_time, volume=50)) if(temperature > REACTOR_TEMPERATURE_MINIMUM) var/turf/T = get_turf(src) T.atmos_spawn_air("water_vapor=[pressure/100];TEMP=[temperature]") user.rad_act(rod.fuel_power * 1000) fuel_rods.Remove(rod) + if(ismecha(user.loc)) + rod.forceMove(get_step(get_turf(user.loc), user.loc.dir)) + return TRUE if(!user.put_in_hands(rod)) rod.forceMove(user.loc) return TRUE diff --git a/code/modules/projectiles/ammunition/caseless/rocket.dm b/code/modules/projectiles/ammunition/caseless/rocket.dm index e82508d2c67d..558471acd3a7 100644 --- a/code/modules/projectiles/ammunition/caseless/rocket.dm +++ b/code/modules/projectiles/ammunition/caseless/rocket.dm @@ -30,7 +30,7 @@ /obj/item/ammo_casing/caseless/bolts name = "bolts" - desc = "rods, cut in half and ready to be shot" + desc = "Rods, cut in half and ready to be shot." caliber = null icon = 'icons/obj/ammo.dmi' icon_state = "bolt" diff --git a/code/modules/projectiles/ammunition/energy/plasma.dm b/code/modules/projectiles/ammunition/energy/plasma.dm index 922b950b9333..a74528a65381 100644 --- a/code/modules/projectiles/ammunition/energy/plasma.dm +++ b/code/modules/projectiles/ammunition/energy/plasma.dm @@ -5,6 +5,12 @@ delay = 15 e_cost = 25 +/obj/item/ammo_casing/energy/plasma/ready_proj(atom/target, mob/living/user, quiet, zone_override = "") + ..() + if(loc && istype(loc, /obj/item/gun/energy/plasmacutter)) + var/obj/item/gun/energy/plasmacutter/PC = loc + PC.modify_projectile(BB) + /obj/item/ammo_casing/energy/plasma/weak projectile_type = /obj/projectile/plasma/weak select_name = "weak plasma burst" diff --git a/code/modules/projectiles/guns/energy/special.dm b/code/modules/projectiles/guns/energy/special.dm index 03d6582fac10..467831b21e3f 100644 --- a/code/modules/projectiles/guns/energy/special.dm +++ b/code/modules/projectiles/guns/energy/special.dm @@ -1,3 +1,5 @@ +#define PLASMA_BASE_RECHARGE 500 + /obj/item/gun/energy/ionrifle name = "ion rifle" desc = "Invented in 2506 to quell attacks from SELF aligned IPCs, the NT-I1 is a bulky rifle designed to disable mechanical and electronic threats at range." @@ -129,26 +131,40 @@ var/progress_flash_divisor = 10 //copypasta is best pasta var/light_intensity = 1 var/charge_weld = 25 //amount of charge used up to start action (multiplied by amount) and per progress_flash_divisor ticks of welding - /// Contains the type paths for installed upgrades - var/installed_upgrades = list() - -/obj/item/gun/energy/plasmacutter/mini - name = "mini plasma cutter" - desc = "A weak plasma based mining tool." - icon_state = "plasmacutter_mini" - item_state = "plasmacutter_mini" - ammo_type = list(/obj/item/ammo_casing/energy/plasma/weak) - toolspeed = 2 + /// Contains the instances of installed upgrades + var/list/installed_upgrades = list() + /// Mod capacity of this item + var/mod_capacity = 80 + +/obj/item/gun/energy/plasmacutter/proc/modify_projectile(obj/projectile/plasma/K) + K.gun = src //do something special on-hit, easy! + for(var/obj/item/upgrade/plasmacutter/A in installed_upgrades) + A.modify_projectile(K) + +/obj/item/gun/energy/plasmacutter/proc/get_remaining_mod_capacity() + . = mod_capacity + for(var/obj/item/upgrade/plasmacutter/a in installed_upgrades) + . -= a.cost + return . /obj/item/gun/energy/plasmacutter/Initialize(mapload) AddElement(/datum/element/update_icon_blocker) . = ..() AddComponent(/datum/component/butchering, 25, 105, 0, 'sound/weapons/plasma_cutter.ogg') +/obj/item/gun/energy/plasmacutter/Destroy() + . = ..() + for(var/obj/item/upgrade/plasmacutter/a in installed_upgrades) + qdel(a) + QDEL_NULL(installed_upgrades) + /obj/item/gun/energy/plasmacutter/examine(mob/user) . = ..() if(cell) . += span_notice("[src] is [round(cell.percent())]% charged.") + . += span_boldnotice("[get_remaining_mod_capacity()]%
mod capacity remaining.") + for(var/obj/item/upgrade/plasmacutter/a in installed_upgrades) + . += span_notice("There is \a [a] installed, using [span_bold("[a.cost]%")] capacity.") /obj/item/gun/energy/plasmacutter/attackby(obj/item/I, mob/user) var/charge_multiplier = 0 //2 = Refined stack, 1 = Ore @@ -156,16 +172,20 @@ charge_multiplier = 2 if(istype(I, /obj/item/stack/ore/plasma)) charge_multiplier = 1 - if(charge_multiplier) - if(cell.charge == cell.maxcharge) - to_chat(user, span_notice("You try to insert [I] into [src], but it's fully charged.")) //my cell is round and full - return - I.use(1) - cell.give(500*charge_multiplier) - to_chat(user, span_notice("You insert [I] in [src], recharging it.")) - else - ..() + if(!charge_multiplier) + return ..() + + var/obj/item/stack/S = I + var/charge_amount = PLASMA_BASE_RECHARGE * charge_multiplier // Get the amount of charge per item + // Get remaining capacity and get the ideal amount to recharge or all of the stack whichever is smaller + var/amount_to_eat = ceil(min(((cell.maxcharge - cell.charge) / charge_amount), S.get_amount())) + if(amount_to_eat == 0) + to_chat(user, span_notice("You try to insert [I] into [src], but it's fully charged.")) //my cell is round and full + return + I.use(amount_to_eat) + cell.give(charge_amount * amount_to_eat) + to_chat(user, span_notice("You insert [I] in [src], recharging it.")) // Tool procs, in case plasma cutter is used as welder // Can we start welding? /obj/item/gun/energy/plasmacutter/tool_start_check(mob/living/user, amount) @@ -211,12 +231,54 @@ else . = ..(amount=1) +/obj/item/gun/energy/plasmacutter/attackby(obj/item/I, mob/user) + . = ..() + if(istype(I, /obj/item/upgrade/plasmacutter)) + var/obj/item/upgrade/plasmacutter/PC = I + if(get_remaining_mod_capacity() < PC.cost) + to_chat(user, span_warning("There is no more room for this upgrade.")) + return + if(!PC.stackable && is_type_in_list(PC, installed_upgrades)) + to_chat(user, span_notice("[I] has already been installed in [src]")) + return + to_chat(user, span_notice("You install [I] into [src]")) + playsound(loc, 'sound/items/screwdriver.ogg', 100, 1) + installed_upgrades += I + PC.install(src) + I.forceMove(src) + +/obj/item/gun/energy/plasmacutter/crowbar_act(mob/living/user, obj/item/I) + . = TRUE + if(installed_upgrades.len) + to_chat(user, span_notice("You pry the modifications out.")) + I.play_tool_sound(src, 100) + for(var/obj/item/upgrade/plasmacutter/M in installed_upgrades) + M.forceMove(drop_location()) // Uninstallation handled in Exited(). + else + to_chat(user, span_notice("There are no modifications currently installed.")) + +/obj/item/gun/energy/plasmacutter/Exited(atom/movable/gone, direction) + ..() + if(gone in installed_upgrades) + var/obj/item/upgrade/plasmacutter/MK = gone + MK.uninstall(src) + +/obj/item/gun/energy/plasmacutter/mini + name = "mini plasma cutter" + desc = "A weak plasma based mining tool." + icon_state = "plasmacutter_mini" + item_state = "plasmacutter_mini" + ammo_type = list(/obj/item/ammo_casing/energy/plasma/weak) + toolspeed = 2 + mod_capacity = 50 + /obj/item/gun/energy/plasmacutter/adv name = "advanced plasma cutter" icon_state = "adv_plasmacutter" item_state = "adv_plasmacutter" force = 15 ammo_type = list(/obj/item/ammo_casing/energy/plasma/adv) + mod_capacity = 100 /obj/item/gun/energy/plasmacutter/adv/mega name = "mega plasma cutter" @@ -224,6 +286,7 @@ item_state = "plasmacutter_mega" desc = "A mining tool capable of expelling concentrated plasma bursts. You could use it to cut limbs off xenos! Or, you know, mine stuff. This one has been enhanced with plasma magmite." ammo_type = list(/obj/item/ammo_casing/energy/plasma/adv/mega) + mod_capacity = 120 /obj/item/gun/energy/plasmacutter/scatter name = "plasma cutter shotgun" @@ -232,15 +295,7 @@ desc = "An industrial-grade, heavy-duty mining shotgun." force = 10 ammo_type = list(/obj/item/ammo_casing/energy/plasma/scatter) - - - -/obj/item/gun/energy/plasmacutter/attackby(obj/item/I, mob/user) - . = ..() - if(try_upgrade(I, user)) - to_chat(user, span_notice("You install [I] into [src]")) - playsound(loc, 'sound/items/screwdriver.ogg', 100, 1) - qdel(I) + mod_capacity = 100 /obj/item/gun/energy/plasmacutter/scatter/mega name = "mega plasma cutter shotgun" @@ -248,6 +303,7 @@ item_state = "miningshotgun_mega" desc = "An industrial-grade, heavy-duty mining shotgun. This one seems... mega!" ammo_type = list(/obj/item/ammo_casing/energy/plasma/scatter/adv/mega) + mod_capacity = 120 /obj/item/gun/energy/plasmacutter/adv/cyborg name = "cyborg advanced plasma cutter" @@ -255,6 +311,7 @@ force = 15 selfcharge = 1 ammo_type = list(/obj/item/ammo_casing/energy/plasma/adv/cyborg) + mod_capacity = 70 /obj/item/gun/energy/plasmacutter/adv/malf // Can't be subtype of cyborg or it will interfere with upgrades name = "cyborg malfunctioning plasma cutter" @@ -263,47 +320,71 @@ force = 15 selfcharge = 1 ammo_type = list(/obj/item/ammo_casing/energy/plasma/adv/cyborg/malf) + mod_capacity = 100 // Upgrades for plasma cutters /obj/item/upgrade/plasmacutter name = "generic upgrade kit" - desc = "An upgrade for plasma shotguns." + desc = "An upgrade for plasma cutters." icon = 'icons/obj/objects.dmi' icon_state = "modkit" w_class = WEIGHT_CLASS_SMALL + var/cost = 10 + var/stackable = FALSE + +/obj/item/upgrade/plasmacutter/proc/modify_projectile(obj/projectile/plasma/K) + +/obj/item/upgrade/plasmacutter/proc/install(obj/item/gun/energy/plasmacutter/P) + +/obj/item/upgrade/plasmacutter/proc/uninstall(obj/item/gun/energy/plasmacutter/P) + /obj/item/upgrade/plasmacutter/defuser name = "plasma cutter defusal kit" - desc = "An upgrade for plasma shotguns that allows it to automatically defuse gibtonite." + desc = "An upgrade for plasma cutters that allows it to automatically defuse gibtonite." + +/obj/item/upgrade/plasmacutter/defuser/modify_projectile(obj/projectile/plasma/K) + K.defuse = TRUE /obj/item/upgrade/plasmacutter/capacity name = "plasma cutter capacity kit" - desc = "An upgrade for plasma shotguns that doubles the tank capacity." + desc = "An upgrade for plasma cutters that doubles the tank capacity." + cost = 20 -/obj/item/gun/energy/plasmacutter/proc/try_upgrade(obj/item/I, mob/user) - if(I.type in installed_upgrades) - to_chat(user, span_notice("[I] has already been installed in [src]")) - return FALSE - return FALSE +/obj/item/upgrade/plasmacutter/capacity/install(obj/item/gun/energy/plasmacutter/P) + P.cell.maxcharge = initial(P.cell.maxcharge)*2 -/obj/item/gun/energy/plasmacutter/scatter/try_upgrade(obj/item/I, mob/user) - . = ..() - if(.) - return TRUE - if(istype(I, /obj/item/upgrade/plasmacutter/defuser)) - var/kaboom = new/obj/item/ammo_casing/energy/plasma/scatter/adv - ammo_type = list(kaboom) - installed_upgrades += I.type - return TRUE - if(istype(I, /obj/item/upgrade/plasmacutter/capacity)) - cell.maxcharge = initial(cell.maxcharge)*2 - installed_upgrades += I.type - return TRUE - return FALSE +/obj/item/upgrade/plasmacutter/capacity/uninstall(obj/item/gun/energy/plasmacutter/P) + P.cell.maxcharge = initial(P.cell.maxcharge) + P.cell.charge = min(P.cell.charge, P.cell.maxcharge) -//no upgrading this one either (for now) -/obj/item/gun/energy/plasmacutter/scatter/mega/try_upgrade(obj/item/I, mob/user) - return +/obj/item/upgrade/plasmacutter/cooldown + name = "plasma cutter cooldown kit" + desc = "An upgrade for plasma cutters that reduces the cooldown." + cost = 40 + stackable = TRUE + +/obj/item/upgrade/plasmacutter/cooldown/install(obj/item/gun/energy/plasmacutter/P) + P.fire_delay *= 0.5 + +/obj/item/upgrade/plasmacutter/cooldown/uninstall(obj/item/gun/energy/plasmacutter/P) + P.fire_delay *= 2 + +/obj/item/upgrade/plasmacutter/range + name = "plasma cutter range kit" + desc = "An upgrade for plasma cutters that increases the range." + cost = 30 + +/obj/item/upgrade/plasmacutter/range/modify_projectile(obj/projectile/plasma/K) + K.range += 4 + +/obj/item/upgrade/plasmacutter/ore + name = "plasma cutter ore kit" + desc = "An upgrade for plasma cutters that doubles ore output." + cost = 30 + +/obj/item/upgrade/plasmacutter/ore/modify_projectile(obj/projectile/plasma/K) + K.explosive = TRUE /obj/item/gun/energy/wormhole_projector name = "bluespace wormhole projector" @@ -512,3 +593,5 @@ icon_state = "prifle" item_state = "prifle" ammo_type = list(/obj/item/ammo_casing/energy/grimdark) + +#undef PLASMA_BASE_RECHARGE diff --git a/code/modules/projectiles/projectile.dm b/code/modules/projectiles/projectile.dm index cb890ec8514b..97428e8e26e9 100644 --- a/code/modules/projectiles/projectile.dm +++ b/code/modules/projectiles/projectile.dm @@ -244,8 +244,11 @@ splatter_dir = get_dir(starting, target_loca) if(isalien(L) || ispolysmorph(L)) new /obj/effect/temp_visual/dir_setting/bloodsplatter/xenosplatter(target_loca, splatter_dir) - else if (iscarbon(L) && !(NOBLOOD in C.dna.species.species_traits)) - new /obj/effect/temp_visual/dir_setting/bloodsplatter(target_loca, splatter_dir) + else if(iscarbon(L) && !(NOBLOOD in C.dna.species.species_traits)) + var/splatter_color + var/mob/living/carbon/carbon_bleeder = L + splatter_color = carbon_bleeder.dna.blood_type.color + new /obj/effect/temp_visual/dir_setting/bloodsplatter(target_loca, splatter_dir, splatter_color) else new /obj/effect/temp_visual/dir_setting/bloodsplatter/genericsplatter(target_loca, splatter_dir) var/obj/item/bodypart/B = L.get_bodypart(def_zone) diff --git a/code/modules/projectiles/projectile/special/plasma.dm b/code/modules/projectiles/projectile/special/plasma.dm index ce7137a504ab..85f746a4e30b 100644 --- a/code/modules/projectiles/projectile/special/plasma.dm +++ b/code/modules/projectiles/projectile/special/plasma.dm @@ -16,6 +16,10 @@ light_color = LIGHT_COLOR_PURPLE light_range = 2 + var/obj/item/gun/energy/plasmacutter/gun + var/defuse = FALSE + var/explosive = FALSE + /obj/projectile/plasma/weak name = "weak plasma blast" icon_state = "plasmacutter_weak" @@ -24,6 +28,7 @@ impact_effect_type = /obj/effect/temp_visual/impact_effect/red_laser light_color = LIGHT_COLOR_RED mine_range = 0 + //yogs begin /obj/projectile/plasma/Move(atom/newloc, dir) . = ..() @@ -34,9 +39,12 @@ //yogs end /obj/projectile/plasma/on_hit(atom/target) . = ..() + if(defuse && istype(target, /turf/closed/mineral/gibtonite)) + var/turf/closed/mineral/gibtonite/gib = target + gib.defuse() if(ismineralturf(target)) var/turf/closed/mineral/M = target - M.attempt_drill(firer) + M.attempt_drill(firer, explosive) if(mine_range) mine_range-- range++ @@ -52,12 +60,6 @@ return BULLET_ACT_FORCE_PIERCE // yogs end -/obj/projectile/plasma/scatter/adv/on_hit(atom/target) - if(istype(target, /turf/closed/mineral/gibtonite)) - var/turf/closed/mineral/gibtonite/gib = target - gib.defuse() - . = ..() - /obj/projectile/plasma/adv damage = 7 range = 5 @@ -78,6 +80,7 @@ // Same as the scatter but with automatic defusing /obj/projectile/plasma/scatter/adv + defuse = TRUE // Megafauna loot, possibly best cutter? /obj/projectile/plasma/scatter/adv/stalwart diff --git a/code/modules/projectiles/projectile/special/reagent.dm b/code/modules/projectiles/projectile/special/reagent.dm index 524180486c7b..e19024470544 100644 --- a/code/modules/projectiles/projectile/special/reagent.dm +++ b/code/modules/projectiles/projectile/special/reagent.dm @@ -47,6 +47,25 @@ last_volume = R.volume name = "\proper [lowertext(R.name)]" +// PRESSURE WASHER +/obj/projectile/reagent/pressure_washer + name = "\proper high-pressure water" + icon = 'icons/effects/effects.dmi' + icon_state = "extinguish" + range = 7 + reagents_list = list(/datum/reagent/water = 10) + speed = 0.6 // very high power + +/obj/projectile/reagent/pressure_washer/on_hit(atom/movable/target, blocked) + . = ..() + if(istype(target) && !target.anchored && prob(20)) + target.throw_at(get_step(target, dir), 1, 1, firer) + +/obj/projectile/reagent/pressure_washer/Move(atom/newloc, dir) + . = ..() + if(newloc) + newloc.wash(CLEAN_SCRUB) // wash everything in its path + /// Xeno neurotoxin /obj/projectile/reagent/neurotoxin name = "neurotoxin spit" diff --git a/code/modules/projectiles/projectile/special/rocket.dm b/code/modules/projectiles/projectile/special/rocket.dm index 3d220e4842a3..0a39cfd58b33 100644 --- a/code/modules/projectiles/projectile/special/rocket.dm +++ b/code/modules/projectiles/projectile/special/rocket.dm @@ -10,7 +10,7 @@ /obj/projectile/bullet/a84mm name ="\improper HEDP rocket" - desc = "USE A WEEL GUN" + desc = "USE A WEEL GUN." icon_state= "84mm-hedp" armor_flag = BOMB damage = 80 @@ -73,7 +73,7 @@ /obj/projectile/bullet/cball name = "cannonball" icon_state = "cannonball" - desc = "Not for bowling purposes" + desc = "Not for bowling purposes." damage = 30 demolition_mod = 20 // YARRR @@ -91,5 +91,5 @@ /obj/projectile/bullet/bolt name = "bolt" icon_state = "bolt" - desc = "smaller and faster rod" + desc = "A smaller and faster rod." damage = 25 diff --git a/code/modules/reagents/chemistry/reagents/alcohol_reagents.dm b/code/modules/reagents/chemistry/reagents/alcohol_reagents.dm index ce0225b4e1ea..ec3bea63fddd 100644 --- a/code/modules/reagents/chemistry/reagents/alcohol_reagents.dm +++ b/code/modules/reagents/chemistry/reagents/alcohol_reagents.dm @@ -97,7 +97,7 @@ All effects don't start immediately, but rather get worse over time; the rate is color = "#221915" // rgb: 34, 25, 21 taste_description = "malt and chocolate" glass_name = "glass of stout" - glass_desc = "a cold pint of 'genius' brand stout." + glass_desc = "A cold pint of 'genius' brand stout." /datum/reagent/consumable/ethanol/beer/stout/irishflip name = "Irish Flip" @@ -106,7 +106,7 @@ All effects don't start immediately, but rather get worse over time; the rate is taste_description = "chocolate cream and egg" glass_icon_state = "irish_flip" glass_name = "glass of irish flip" - glass_desc = "a fancy glass of creamy cocktail." + glass_desc = "A fancy glass of creamy cocktail." /datum/reagent/consumable/ethanol/beer/stout/blackvelvet name = "Black Velvet" @@ -115,7 +115,7 @@ All effects don't start immediately, but rather get worse over time; the rate is taste_description = "Champagne with a hint of chocolate." glass_icon_state = "black_velvet" glass_name = "glass of black velvet" - glass_desc = "a fancy drink with a melancholic past." + glass_desc = "A fancy drink with a melancholic past." /datum/reagent/consumable/ethanol/beer/stout/espressomartini name = "Espresso Martini" @@ -124,7 +124,7 @@ All effects don't start immediately, but rather get worse over time; the rate is taste_description = "bitterness, chocolate, and cream." glass_icon_state = "espresso_martini" glass_name = "glass of espresso martini" - glass_desc = "a cocktail guaranteed to keep you awake." + glass_desc = "A cocktail guaranteed to keep you awake." /////////////////////////////////////////// /datum/reagent/consumable/ethanol/beer/light name = "Light Beer" @@ -2281,7 +2281,7 @@ All effects don't start immediately, but rather get worse over time; the rate is taste_description = "dried plums and malt" glass_icon_state = "trappistglass" glass_name = "Trappist Beer" - glass_desc = "boozy Catholicism in a glass." + glass_desc = "Boozy Catholicism in a glass." /datum/reagent/consumable/ethanol/trappist/on_mob_life(mob/living/carbon/M) if(M.mind.holy_role) @@ -2440,7 +2440,7 @@ All effects don't start immediately, but rather get worse over time; the rate is taste_description = "tequila, creme de menthe, and a hint of medicine?" glass_icon_state = "flaming_moe2" glass_name = "Flaming Moe" - glass_desc = "an amazing concoction of various different bar drinks and a secret ingredient" + glass_desc = "An amazing concoction of various different bar drinks and a secret ingredient" /datum/reagent/consumable/ethanol/flaming_moe/on_mob_life(mob/living/carbon/M) M.adjust_drowsiness(-5 SECONDS) diff --git a/code/modules/research/designs/mecha_designs.dm b/code/modules/research/designs/mecha_designs.dm index 9b5a012ee9cd..14f89cc5dde3 100644 --- a/code/modules/research/designs/mecha_designs.dm +++ b/code/modules/research/designs/mecha_designs.dm @@ -411,6 +411,66 @@ construction_time = 1200 category = list("Exosuit Equipment") +/datum/design/mech_thrusters + name = "Exosuit Module (RCS Thruster Package)" + desc = "A thruster package for exosuits. Expels gas from the internal life-support air tank to generate thrust." + id = "mech_thrusters" + build_type = MECHFAB + build_path = /obj/item/mecha_parts/mecha_equipment/thrusters/gas + materials = list(/datum/material/iron=25000,/datum/material/titanium=5000,/datum/material/silver=3000) + construction_time = 100 + category = list("Exosuit Equipment") + +/datum/design/mech_pipe_dispenser + name = "Exosuit Module (Pipe Dispenser Module)" + desc = "An exosuit-mounted Rapid Pipe Dispenser." + id = "mech_pipe_dispenser" + build_type = MECHFAB + build_path = /obj/item/mecha_parts/mecha_equipment/pipe_dispenser + materials = list(/datum/material/iron=10000,/datum/material/glass=2000) + construction_time = 100 + category = list("Exosuit Equipment") + +/datum/design/mech_t_scanner + name = "Exosuit Module (T-ray Scanner Module)" + desc = "An exosuit-mounted Terahertz-Ray Scanner." + id = "mech_t_scanner" + build_type = MECHFAB + build_path = /obj/item/mecha_parts/mecha_equipment/t_scanner + materials = list(/datum/material/iron=2000) + construction_time = 50 + category = list("Exosuit Equipment") + +/datum/design/mech_washer + name = "Exosuit Module (Pressure Washer)" + desc = "An exosuit-mounted pressure washer." + id = "mech_washer" + build_type = MECHFAB + build_path = /obj/item/mecha_parts/mecha_equipment/weapon/pressure_washer + materials = list(/datum/material/iron=2000) + construction_time = 50 + category = list("Exosuit Equipment") + +/datum/design/mech_mop + name = "Exosuit Module (Mop)" + desc = "An exosuit-mounted mop." + id = "mech_mop" + build_type = MECHFAB + build_path = /obj/item/mecha_parts/mecha_equipment/melee_weapon/mop + materials = list(/datum/material/iron=2000) + construction_time = 50 + category = list("Exosuit Equipment") + +/datum/design/mech_flyswatter + name = "Exosuit Module (Flyswatter)" + desc = "An exosuit-mounted flyswatter." + id = "mech_flyswatter" + build_type = MECHFAB + build_path = /obj/item/mecha_parts/mecha_equipment/melee_weapon/flyswatter + materials = list(/datum/material/iron=2000) + construction_time = 50 + category = list("Exosuit Equipment") + /datum/design/mech_gravcatapult name = "Exosuit Module (Gravitational Catapult Module)" desc = "An exosuit mounted Gravitational Catapult." diff --git a/code/modules/research/designs/medical_designs.dm b/code/modules/research/designs/medical_designs.dm index eb8ec7b9a1af..ff01af524c1f 100644 --- a/code/modules/research/designs/medical_designs.dm +++ b/code/modules/research/designs/medical_designs.dm @@ -11,7 +11,7 @@ construction_time = 75 build_path = /obj/item/mmi category = list("Control Interfaces", "Medical Designs") - departmental_flags = DEPARTMENTAL_FLAG_MEDICAL | DEPARTMENTAL_FLAG_SCIENCE + departmental_flags = DEPARTMENTAL_FLAG_SCIENCE /datum/design/posibrain name = "Positronic Brain" @@ -22,7 +22,7 @@ construction_time = 75 build_path = /obj/item/mmi/posibrain category = list("Control Interfaces", "Medical Designs") - departmental_flags = DEPARTMENTAL_FLAG_MEDICAL | DEPARTMENTAL_FLAG_SCIENCE + departmental_flags = DEPARTMENTAL_FLAG_SCIENCE /datum/design/bluespacebeaker name = "Bluespace Beaker" @@ -708,7 +708,7 @@ ///////////////////// /datum/design/surgery name = "Surgery Design" - desc = "what" + desc = "What." id = "surgery_parent" research_icon = 'icons/misc/surgery_icons.dmi' research_icon_state = "surgery_any" diff --git a/code/modules/research/techweb/all_nodes.dm b/code/modules/research/techweb/all_nodes.dm index a0cc937c928b..2cb62f1d9d7b 100644 --- a/code/modules/research/techweb/all_nodes.dm +++ b/code/modules/research/techweb/all_nodes.dm @@ -39,7 +39,7 @@ starting_node = TRUE display_name = "Basic Exosuit Equipment" description = "Various tools fit for basic mech units" - design_ids = list("mech_drill", "mech_mscanner", "mech_extinguisher", "mech_cable_layer") + design_ids = list("mech_drill", "mech_mscanner", "mech_extinguisher", "mech_cable_layer", "mech_t_scanner", "mech_pipe_dispenser") /datum/techweb_node/clarke id = "mecha_clarke" @@ -620,7 +620,7 @@ display_name = "Advanced Sanitation Technology" description = "Clean things better, faster, stronger, and harder!" prereq_ids = list("adv_engi") - design_ids = list("advmop", "buffer", "blutrash", "light_replacer", "spraybottle", "beartrap") + design_ids = list("advmop", "buffer", "blutrash", "light_replacer", "spraybottle", "beartrap", "mech_washer", "mech_mop", "mech_flyswatter") research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) /datum/techweb_node/botany @@ -857,7 +857,7 @@ display_name = "Advanced Exosuit Equipment" description = "Tools for high level mech suits" prereq_ids = list("adv_mecha") - design_ids = list("mech_rcd") + design_ids = list("mech_rcd", "mech_thrusters") research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) /datum/techweb_node/med_mech_tools diff --git a/code/modules/shuttle/on_move.dm b/code/modules/shuttle/on_move.dm index 5f5bb52270e7..5a510273911f 100644 --- a/code/modules/shuttle/on_move.dm +++ b/code/modules/shuttle/on_move.dm @@ -50,10 +50,10 @@ All ShuttleMove procs go here //Destination turf changes //Baseturfs is definitely a list or this proc wouldnt be called var/shuttle_depth = depth_to_find_baseturf(/turf/baseturf_skipover/shuttle) - + if(!shuttle_depth) CRASH("A turf queued to move via shuttle somehow had no skipover in baseturfs. [src]([type]):[loc]") - newT.CopyOnTop(src, 1, shuttle_depth, TRUE, CHANGETURF_DEFER_CHANGE) + newT.CopyOnTop(src, 1, shuttle_depth, TRUE) SEND_SIGNAL(src, COMSIG_TURF_ON_SHUTTLE_MOVE, newT) return TRUE @@ -67,7 +67,7 @@ All ShuttleMove procs go here var/shuttle_depth = depth_to_find_baseturf(/turf/baseturf_skipover/shuttle) if(shuttle_depth) - oldT.ScrapeAway(shuttle_depth) + oldT.ScrapeAway(shuttle_depth, CHANGETURF_DEFER_CHANGE) if(rotation) shuttleRotate(rotation) //see shuttle_rotate.dm diff --git a/code/modules/shuttle/ripple.dm b/code/modules/shuttle/ripple.dm index 912d95488862..19269c6a83ba 100644 --- a/code/modules/shuttle/ripple.dm +++ b/code/modules/shuttle/ripple.dm @@ -1,6 +1,6 @@ /obj/effect/abstract/ripple - name = "hyperspace ripple" - desc = "Something is coming through hyperspace, you can see the \ + name = "bluespace ripple" + desc = "Something is coming through bluespace, you can see the \ visual disturbances. It's probably best not to be on top of these \ when whatever is tunneling comes through." icon = 'icons/effects/effects.dmi' diff --git a/code/modules/spells/spell_types/self/spacetime_distortion.dm b/code/modules/spells/spell_types/self/spacetime_distortion.dm index b41560aa1629..62e4edcc3d73 100644 --- a/code/modules/spells/spell_types/self/spacetime_distortion.dm +++ b/code/modules/spells/spell_types/self/spacetime_distortion.dm @@ -98,7 +98,7 @@ /obj/effect/cross_action name = "cross me" - desc = "for crossing" + desc = "For crossing." anchored = TRUE /obj/effect/cross_action/spacetime_dist diff --git a/code/modules/surgery/organs/augments_eyes.dm b/code/modules/surgery/organs/augments_eyes.dm index 067261c67490..67d77435c416 100644 --- a/code/modules/surgery/organs/augments_eyes.dm +++ b/code/modules/surgery/organs/augments_eyes.dm @@ -1,6 +1,6 @@ /obj/item/organ/cyberimp/eyes/hud name = "cybernetic hud" - desc = "artificial photoreceptors with specialized functionality" + desc = "A couple of artificial photoreceptors with specialized functionality." icon_state = "eye_implant" implant_overlay = "eye_implant_overlay" slot = ORGAN_SLOT_EYES diff --git a/code/modules/surgery/organs/eyes.dm b/code/modules/surgery/organs/eyes.dm index 7be34b681780..6bd6c3d7eb46 100644 --- a/code/modules/surgery/organs/eyes.dm +++ b/code/modules/surgery/organs/eyes.dm @@ -172,6 +172,12 @@ medium_light_cutoff = list(0, 20, 35) high_light_cutoff = list(0, 40, 50) +/obj/item/organ/eyes/zombie + name = "undead eyes" + desc = "Somewhat counterintuitively, these half-rotten eyes actually have superior vision to those of a living human." + color_cutoffs = list(25, 35, 5) + lighting_cutoff = LIGHTING_CUTOFF_HIGH + //innate nightvision eyes /obj/item/organ/eyes/alien name = "alien eyes" @@ -180,12 +186,6 @@ color_cutoffs = list(25, 5, 42) lighting_cutoff = LIGHTING_CUTOFF_HIGH -/obj/item/organ/eyes/zombie - name = "undead eyes" - desc = "Somewhat counterintuitively, these half-rotten eyes actually have superior vision to those of a living human." - color_cutoffs = list(25, 35, 5) - lighting_cutoff = LIGHTING_CUTOFF_HIGH - /obj/item/organ/eyes/shadow name = "burning red eyes" desc = "Even without their shadowy owner, looking at these eyes gives you a sense of dread." @@ -243,7 +243,7 @@ sight_flags = SEE_MOBS // We're gonna downshift green and blue a bit so darkness looks yellow color_cutoffs = list(25, 8, 5) - flash_protect = -1 + flash_protect = FLASH_PROTECTION_SENSITIVE /obj/item/organ/eyes/robotic/flashlight name = "flashlight eyes" @@ -279,7 +279,7 @@ /obj/item/organ/eyes/robotic/shield name = "shielded robotic eyes" desc = "These reactive micro-shields will protect you from welders and flashes without obscuring your vision." - flash_protect = 2 + flash_protect = FLASH_PROTECTION_WELDER /obj/item/organ/eyes/robotic/shield/emp_act(severity) return diff --git a/code/modules/tgui/states/pilot.dm b/code/modules/tgui/states/pilot.dm new file mode 100644 index 000000000000..c5b63b5ad1d8 --- /dev/null +++ b/code/modules/tgui/states/pilot.dm @@ -0,0 +1,9 @@ +GLOBAL_DATUM_INIT(pilot_state, /datum/ui_state/pilot_state, new) + +/datum/ui_state/pilot_state/can_use_topic(src_object, mob/user) + if(!ismecha(src_object)) + return UI_CLOSE + var/obj/mecha/gundam = src_object + if(user == gundam.occupant) + return UI_INTERACTIVE + return UI_CLOSE diff --git a/code/modules/uplink/uplink_items.dm b/code/modules/uplink/uplink_items.dm index 96460e519239..7699c09a3e46 100644 --- a/code/modules/uplink/uplink_items.dm +++ b/code/modules/uplink/uplink_items.dm @@ -339,6 +339,13 @@ GLOBAL_LIST_INIT(uplink_items, subtypesof(/datum/uplink_item)) manufacturer = /datum/corporation/traitor/cybersun surplus = 0 +/datum/uplink_item/dangerous/gasharpoon + name = "Gasharpoon" + desc = "A repurposed space-whaling tool attatched to a glove, can be used as a sturdy weapon in both hands, or worn as a glove to allow access to it's harpoon." + item = /obj/item/clothing/gloves/gasharpoon + cost = 10 + surplus = 0 + /datum/uplink_item/dangerous/rawketlawnchair name = "84mm Rocket Propelled Grenade Launcher" desc = "A reusable rocket propelled grenade launcher preloaded with a low-yield 84mm HE round. \ diff --git a/config/config.txt b/config/config.txt index e077fe2da1f1..e3e17849b3e1 100644 --- a/config/config.txt +++ b/config/config.txt @@ -422,6 +422,16 @@ DEFAULT_VIEW 19x15 ## You probably shouldn't ever be changing this, but it's here if you want to. DEFAULT_VIEW_SQUARE 15x15 + +## Enable automatic profiling - Byond 513.1506 and newer only. +#AUTO_PROFILE + +## Threshold (in deciseconds) for real time between ticks before we start dumping profiles +DRIFT_DUMP_THRESHOLD 40 + +## How long to wait (in deciseconds) after a profile dump before logging another tickdrift sourced one +DRIFT_PROFILE_DELAY 150 + ## Comment this out if you want to use the SQL based mentor system, the legacy system uses mentors.txt. ## You need to set up your database to use the SQL based system. ## This flag is automatically enabled if SQL_ENABLED isn't diff --git a/config/private_default.txt b/config/private_default.txt index 88850ee7cada..832186c7c650 100644 --- a/config/private_default.txt +++ b/config/private_default.txt @@ -86,9 +86,8 @@ VOICE_ANNOUNCE_DIR ../Yogstation.net/voice_announce_tmp ## Enable the demo subsystem #DEMOS_ENABLED -## Starlight for exterior walls and breaches. Uncomment for starlight! -## This is disabled by default to make testing quicker, should be enabled on production servers or testing servers messing with lighting -#STARLIGHT +## Enable automatic profiling - Byond 513.1506 and newer only. +#AUTO_PROFILE ## Assets can opt-in to caching their results into `tmp`. diff --git a/config/private_server.txt b/config/private_server.txt index 8b2019e124ee..f8d2ee73d29d 100644 --- a/config/private_server.txt +++ b/config/private_server.txt @@ -97,6 +97,9 @@ VOICE_ANNOUNCE_DIR data/voice_announcements ## Enable the demo subsystem DEMOS_ENABLED +## Enable automatic profiling - Byond 513.1506 and newer only. +AUTO_PROFILE + ## Starlight for exterior walls and breaches. Uncomment for starlight! ## This is disabled by default to make testing quicker, should be enabled on production servers or testing servers messing with lighting STARLIGHT diff --git a/html/changelog.html b/html/changelog.html index 4a251bd03991..edfa835aec8e 100644 --- a/html/changelog.html +++ b/html/changelog.html @@ -57,6 +57,102 @@ -->
+

23 February 2024

+

Cowbot92 & Chubbygummibear updated:

+
    +
  • Fixes a bunch of stuff you step on
  • +
  • Added new traitor item, the gasharpoon
  • +
+

Chubbygummibear updated:

+
    +
  • auto_profile config flag added to the private default and private server config files
  • +
  • private servers aren't dumpy unless you specifically request them to be
  • +
  • main yog server will be extra dumpy because we can handle it
  • +
  • no more double clerk and chaplain workplace spawns
  • +
+

Moltijoe updated:

+
    +
  • New ethereal bodyparts
  • +
  • Old ethereal bodyparts
  • +
+ +

21 February 2024

+

Identification updated:

+
    +
  • Restores walls to true top-down.
  • +
+

sapphicoverload, syncit21, zxaber updated:

+
    +
  • added a bunch more equipment for utility mechs
  • +
  • adds new sound effects for hydraulic clamp and APLU mech movement
  • +
  • hydraulic clamp works as a wrench or crowbar and can pry powered doors
  • +
  • mech plasma cutter can be used as a welder like the handheld version
  • +
  • mech RCD works like an actual RCD now
  • +
  • adds tgui RCD menu
  • +
  • strafe button icon shows whether or not you're strafing
  • +
  • APLU and Clarke mechs now have radiation shielding
  • +
  • fixed clarke movement not working correctly
  • +
  • fixes and re-adds multi-Z mech movement (no phasing through floors or teleporting to other z-levels this time)
  • +
+

13spacemen updated:

+
    +
  • The latejoin menu no longer has anemia.
  • +
+

AMyriad updated:

+
    +
  • Fixed the eye of god expose cooldown going off when an invalid target is selected
  • +
  • Fixed mention of Weyland-Yutani appearing in the ripley mech repair manual
  • +
  • "Hyperspace" no longer exists and never did, FTL travel is achieved by tunneling through bluespace
  • +
  • Players can no longer relabel gas canisters to a variant that's intended for admins and breaks the 4th wall
  • +
+

Chubbygummibear updated:

+
    +
  • index_out_of_bounds fixed on blend_cutoff_colors
  • +
  • turfs that smooth will spur their neighboring turfs to check their smoothing again when late loaded in
  • +
  • cables on the correct plane so they don't have weird lattice lighting filters
  • +
  • meteors with space lighting overlays rotate with the meteors instead of being disjointed and unmoving
  • +
  • shuttle atmos shouldn't get left behind on takeoff
  • +
+

LazennG updated:

+
    +
  • fixed seismic suplex animation and some text
  • +
+

adamsong updated:

+
    +
  • fixed shuttle catastrophe
  • +
  • fixed admin shuttle manipulator
  • +
+

cowbot92 updated:

+
    +
  • adjust some pop requirements for several antags
  • +
+

redmoogle updated:

+
    +
  • PC Range Upgrade
  • +
  • PC Cooldown Upgrade
  • +
  • Vending machines not containing upgrades
  • +
  • All plasma cutters can be upgraded
  • +
  • Plasmacutters can be recharged with one click now
  • +
+

warface1234455 updated:

+
    +
  • Partially revert undocumented change to shutter/blastdoor layer covering window but still keep the blast door covering the door
  • +
+ +

20 February 2024

+

Chubbygummibear updated:

+
    +
  • fix adminwho by skipping null clients in the admin list
  • +
+

cowbot92 updated:

+
    +
  • fixed beartraps not trapping
  • +
+

warface1234455 updated:

+
    +
  • cable coil maxstacks is now 40
  • +
+

19 February 2024

SapphicOverload updated:

    @@ -1284,61 +1380,6 @@

    cowbot92 updated:

    • Adds auxmos to the minor filter
    - -

    23 November 2023

    -

    SapphicOverload updated:

    -
      -
    • power-fist works like a glove now
    • -
    -

    SomeguyManperson updated:

    -
      -
    • gangrel gorilla transformation is now 15 armor down from 40
    • -
    -

    Yarinoi updated:

    -
      -
    • Medical can print chemical analyzer implants again.
    • -
    -

    warface1234455 updated:

    -
      -
    • Remove the portable pump cargo pack
    • -
    -

    ynot01 updated:

    -
      -
    • The door between the armory and the auxiliary armory are now default security access
    • -
    - -

    22 November 2023

    -

    PositiveEntropy, Cark, Blutsu updated:

    -
      -
    • new wood sprites from TG, and resprites on stairs by Blutsu
    • -
    • replaces old wood tile sprites
    • -
    -

    cark updated:

    -
      -
    • bridge on donut now has an APC and blast doors, apc in chapel is moved and some other minor fixes
    • -
    -

    00ze-cyclone updated:

    -
      -
    • Removed helmet, bulletproof helmet and riot helmet crates
    • -
    • armor, bulletproof armor and riot armor crates now contain helmets as well, price adjusted to cost the same as before
    • -
    -

    JohnFulpWillard updated:

    -
      -
    • Pancake overlays now work
    • -
    -

    SapphicOverload updated:

    -
      -
    • fixed people with the bald trait not being bald when cloned
    • -
    -

    Therandomhoboo updated:

    -
      -
    • Glycerol making results in 3 units instead of 1
    • -
    • Reinforced Window Damage deflection is now 11 instead of 10
    • -
    -

    wonderinghost updated:

    -
      -
    • Adds new programs and hardware to pdas
    • -
GoonStation 13 Development Team diff --git a/html/changelogs/.all_changelog.yml b/html/changelogs/.all_changelog.yml index 52a6b2804d08..73ff413e40ed 100644 --- a/html/changelogs/.all_changelog.yml +++ b/html/changelogs/.all_changelog.yml @@ -43177,3 +43177,74 @@ DO NOT EDIT THIS FILE BY HAND! AUTOMATICALLY GENERATED BY ss13_genchangelog.py. SapphicOverload: - bugfix: RCDs work on space tiles again - bugfix: Fixed space lighting not working in space +2024-02-20: + Chubbygummibear: + - bugfix: fix adminwho by skipping null clients in the admin list + cowbot92: + - bugfix: fixed beartraps not trapping + warface1234455: + - bugfix: cable coil maxstacks is now 40 +2024-02-21: + ' Identification': + - imageadd: Restores walls to true top-down. + ' sapphicoverload, syncit21, zxaber': + - rscadd: added a bunch more equipment for utility mechs + - soundadd: adds new sound effects for hydraulic clamp and APLU mech movement + - tweak: hydraulic clamp works as a wrench or crowbar and can pry powered doors + - tweak: mech plasma cutter can be used as a welder like the handheld version + - tweak: mech RCD works like an actual RCD now + - tweak: adds tgui RCD menu + - tweak: strafe button icon shows whether or not you're strafing + - tweak: APLU and Clarke mechs now have radiation shielding + - bugfix: fixed clarke movement not working correctly + - bugfix: fixes and re-adds multi-Z mech movement (no phasing through floors or + teleporting to other z-levels this time) + 13spacemen: + - tweak: The latejoin menu no longer has anemia. + AMyriad: + - bugfix: Fixed the eye of god expose cooldown going off when an invalid target + is selected + - spellcheck: Fixed mention of Weyland-Yutani appearing in the ripley mech repair + manual + - tweak: '"Hyperspace" no longer exists and never did, FTL travel is achieved by + tunneling through bluespace' + - bugfix: Players can no longer relabel gas canisters to a variant that's intended + for admins and breaks the 4th wall + Chubbygummibear: + - bugfix: index_out_of_bounds fixed on blend_cutoff_colors + - bugfix: turfs that smooth will spur their neighboring turfs to check their smoothing + again when late loaded in + - bugfix: cables on the correct plane so they don't have weird lattice lighting + filters + - bugfix: meteors with space lighting overlays rotate with the meteors instead of + being disjointed and unmoving + - bugfix: shuttle atmos shouldn't get left behind on takeoff + LazennG: + - bugfix: fixed seismic suplex animation and some text + adamsong: + - bugfix: fixed shuttle catastrophe + - bugfix: fixed admin shuttle manipulator + cowbot92: + - tweak: adjust some pop requirements for several antags + redmoogle: + - rscadd: PC Range Upgrade + - rscadd: PC Cooldown Upgrade + - bugfix: Vending machines not containing upgrades + - tweak: All plasma cutters can be upgraded + - tweak: Plasmacutters can be recharged with one click now + warface1234455: + - tweak: Partially revert undocumented change to shutter/blastdoor layer covering + window but still keep the blast door covering the door +2024-02-23: + ' Cowbot92 & Chubbygummibear': + - bugfix: Fixes a bunch of stuff you step on + - rscadd: Added new traitor item, the gasharpoon + Chubbygummibear: + - rscadd: auto_profile config flag added to the private default and private server + config files + - tweak: private servers aren't dumpy unless you specifically request them to be + - tweak: main yog server will be extra dumpy because we can handle it + - bugfix: no more double clerk and chaplain workplace spawns + Moltijoe: + - imageadd: New ethereal bodyparts + - imagedel: Old ethereal bodyparts diff --git a/html/changelogs/AutoChangelog-pr-21390.yml b/html/changelogs/AutoChangelog-pr-21390.yml new file mode 100644 index 000000000000..33de417ea20c --- /dev/null +++ b/html/changelogs/AutoChangelog-pr-21390.yml @@ -0,0 +1,4 @@ +author: " ktlwjec" +delete-after: true +changes: + - imageadd: "Lightens the outline for the bag of holding in-hand sprites." diff --git a/html/changelogs/AutoChangelog-pr-21415.yml b/html/changelogs/AutoChangelog-pr-21415.yml new file mode 100644 index 000000000000..56fdcabb14b4 --- /dev/null +++ b/html/changelogs/AutoChangelog-pr-21415.yml @@ -0,0 +1,4 @@ +author: "AMyriad" +delete-after: true +changes: + - spellcheck: "Fixed every description that didn't begin with a capital letter, make a bug report if you find something I missed" diff --git a/html/changelogs/AutoChangelog-pr-21430.yml b/html/changelogs/AutoChangelog-pr-21430.yml new file mode 100644 index 000000000000..c97868fc83b2 --- /dev/null +++ b/html/changelogs/AutoChangelog-pr-21430.yml @@ -0,0 +1,4 @@ +author: "Mqiib" +delete-after: true +changes: + - tweak: "Mech melee weapons now also hit vines properly when using cleave attacks" diff --git a/html/changelogs/AutoChangelog-pr-21437.yml b/html/changelogs/AutoChangelog-pr-21437.yml new file mode 100644 index 000000000000..b0e6631e8de6 --- /dev/null +++ b/html/changelogs/AutoChangelog-pr-21437.yml @@ -0,0 +1,7 @@ +author: "SapphicOverload" +delete-after: true +changes: + - tweak: "flamethrowers now react their fuel for damage and effects instead of using pre-determined values" + - tweak: "flamethrower tanks release some of their contents when shot instead of just deleting themselves" + - tweak: "flamethrowers can hit vines on windows" + - bugfix: "fixed flamethrowers sometimes using more fuel than intended" diff --git a/html/changelogs/AutoChangelog-pr-21474.yml b/html/changelogs/AutoChangelog-pr-21474.yml new file mode 100644 index 000000000000..210b6c682b74 --- /dev/null +++ b/html/changelogs/AutoChangelog-pr-21474.yml @@ -0,0 +1,4 @@ +author: "AMyriad" +delete-after: true +changes: + - tweak: "MMIs and positronic brains can no longer be printed from the medical techfab" diff --git a/html/changelogs/AutoChangelog-pr-21483.yml b/html/changelogs/AutoChangelog-pr-21483.yml new file mode 100644 index 000000000000..f02b7a33d652 --- /dev/null +++ b/html/changelogs/AutoChangelog-pr-21483.yml @@ -0,0 +1,4 @@ +author: "cowbot92" +delete-after: true +changes: + - rscadd: " Ports baton light up from TG" diff --git a/html/changelogs/AutoChangelog-pr-21493.yml b/html/changelogs/AutoChangelog-pr-21493.yml new file mode 100644 index 000000000000..b7eb51bc0cdf --- /dev/null +++ b/html/changelogs/AutoChangelog-pr-21493.yml @@ -0,0 +1,4 @@ +author: "warface1234455" +delete-after: true +changes: + - tweak: "HFR gas byproducts now uses scaled_production instead of fuel_consumption, and now scaled alongside with gas produced from moderator, code refactor" diff --git a/html/changelogs/AutoChangelog-pr-21496.yml b/html/changelogs/AutoChangelog-pr-21496.yml new file mode 100644 index 000000000000..1d9544e59ed1 --- /dev/null +++ b/html/changelogs/AutoChangelog-pr-21496.yml @@ -0,0 +1,4 @@ +author: "Mqiib" +delete-after: true +changes: + - tweak: "The clarke is now tied for fastest mech in the game with the ripley mk-I" diff --git a/icons/effects/beam.dmi b/icons/effects/beam.dmi index fbe6182716b7..9f06f421b549 100644 Binary files a/icons/effects/beam.dmi and b/icons/effects/beam.dmi differ diff --git a/icons/effects/blood.dmi b/icons/effects/blood.dmi index 432ef8861cfb..483ab0444233 100644 Binary files a/icons/effects/blood.dmi and b/icons/effects/blood.dmi differ diff --git a/icons/effects/footprints.dmi b/icons/effects/footprints.dmi index a98344abe41e..dc8ddb4e7341 100644 Binary files a/icons/effects/footprints.dmi and b/icons/effects/footprints.dmi differ diff --git a/icons/mecha/mecha_equipment.dmi b/icons/mecha/mecha_equipment.dmi index e64729a33764..abfa721d57d9 100644 Binary files a/icons/mecha/mecha_equipment.dmi and b/icons/mecha/mecha_equipment.dmi differ diff --git a/icons/mob/actions/actions_arm.dmi b/icons/mob/actions/actions_arm.dmi index 71bb415e8ad9..2154e742819e 100644 Binary files a/icons/mob/actions/actions_arm.dmi and b/icons/mob/actions/actions_arm.dmi differ diff --git a/icons/mob/actions/actions_mecha.dmi b/icons/mob/actions/actions_mecha.dmi index 81c706b22c8a..78a2ba5ec89a 100644 Binary files a/icons/mob/actions/actions_mecha.dmi and b/icons/mob/actions/actions_mecha.dmi differ diff --git a/icons/mob/clothing/hands/hands.dmi b/icons/mob/clothing/hands/hands.dmi index 57bef8c67fff..e07cfff4b117 100644 Binary files a/icons/mob/clothing/hands/hands.dmi and b/icons/mob/clothing/hands/hands.dmi differ diff --git a/icons/mob/human_parts_greyscale.dmi b/icons/mob/human_parts_greyscale.dmi index 004bf8ad9902..a7e311e3a225 100644 Binary files a/icons/mob/human_parts_greyscale.dmi and b/icons/mob/human_parts_greyscale.dmi differ diff --git a/icons/mob/inhands/equipment/backpack_lefthand.dmi b/icons/mob/inhands/equipment/backpack_lefthand.dmi index 15425dabca14..0183ae173468 100644 Binary files a/icons/mob/inhands/equipment/backpack_lefthand.dmi and b/icons/mob/inhands/equipment/backpack_lefthand.dmi differ diff --git a/icons/mob/inhands/equipment/backpack_righthand.dmi b/icons/mob/inhands/equipment/backpack_righthand.dmi index c51285f0867f..94b50fbb8d63 100644 Binary files a/icons/mob/inhands/equipment/backpack_righthand.dmi and b/icons/mob/inhands/equipment/backpack_righthand.dmi differ diff --git a/icons/mob/inhands/weapons/melee_lefthand.dmi b/icons/mob/inhands/weapons/melee_lefthand.dmi index 63624745e62c..dd0e7cfc86b0 100644 Binary files a/icons/mob/inhands/weapons/melee_lefthand.dmi and b/icons/mob/inhands/weapons/melee_lefthand.dmi differ diff --git a/icons/mob/inhands/weapons/melee_righthand.dmi b/icons/mob/inhands/weapons/melee_righthand.dmi index d50eb8ccea9d..6b66977d77a0 100644 Binary files a/icons/mob/inhands/weapons/melee_righthand.dmi and b/icons/mob/inhands/weapons/melee_righthand.dmi differ diff --git a/icons/mob/radial.dmi b/icons/mob/radial.dmi index 533e11521d65..9006b42b0700 100644 Binary files a/icons/mob/radial.dmi and b/icons/mob/radial.dmi differ diff --git a/icons/obj/guns/magic.dmi b/icons/obj/guns/magic.dmi index 94bb606cbfc5..7ae2646ec3b8 100644 Binary files a/icons/obj/guns/magic.dmi and b/icons/obj/guns/magic.dmi differ diff --git a/icons/obj/lavaland/artefacts.dmi b/icons/obj/lavaland/artefacts.dmi index 494c964d48f2..00d590b2ac43 100644 Binary files a/icons/obj/lavaland/artefacts.dmi and b/icons/obj/lavaland/artefacts.dmi differ diff --git a/icons/obj/traitor.dmi b/icons/obj/traitor.dmi index 92851f3708cd..4d7a4931bcaf 100644 Binary files a/icons/obj/traitor.dmi and b/icons/obj/traitor.dmi differ diff --git a/icons/turf/walls/false_walls.dmi b/icons/turf/walls/false_walls.dmi index 1b02b4bdbe6d..a64fbe06fa5b 100644 Binary files a/icons/turf/walls/false_walls.dmi and b/icons/turf/walls/false_walls.dmi differ diff --git a/icons/turf/walls/material_wall.dmi b/icons/turf/walls/material_wall.dmi index 2bd844c0b135..d4c48e66f6ea 100644 Binary files a/icons/turf/walls/material_wall.dmi and b/icons/turf/walls/material_wall.dmi differ diff --git a/icons/turf/walls/material_wall.png b/icons/turf/walls/material_wall.png index 1f636cb6db09..0c2533dec6f9 100644 Binary files a/icons/turf/walls/material_wall.png and b/icons/turf/walls/material_wall.png differ diff --git a/icons/turf/walls/reinforced_states.dmi b/icons/turf/walls/reinforced_states.dmi index 89c0114a8d6e..4fc5c06e05a9 100644 Binary files a/icons/turf/walls/reinforced_states.dmi and b/icons/turf/walls/reinforced_states.dmi differ diff --git a/icons/turf/walls/reinforced_wall.dmi b/icons/turf/walls/reinforced_wall.dmi index 65267a93b2d2..210268b4625a 100644 Binary files a/icons/turf/walls/reinforced_wall.dmi and b/icons/turf/walls/reinforced_wall.dmi differ diff --git a/icons/turf/walls/reinforced_wall.png b/icons/turf/walls/reinforced_wall.png index f8d07602c574..37093774fbdc 100644 Binary files a/icons/turf/walls/reinforced_wall.png and b/icons/turf/walls/reinforced_wall.png differ diff --git a/icons/turf/walls/wall.dmi b/icons/turf/walls/wall.dmi index 6cdd342fd9ed..043da38c0346 100644 Binary files a/icons/turf/walls/wall.dmi and b/icons/turf/walls/wall.dmi differ diff --git a/icons/turf/walls/wall.png b/icons/turf/walls/wall.png index 8f95ca652cdf..6e603751a6e0 100644 Binary files a/icons/turf/walls/wall.png and b/icons/turf/walls/wall.png differ diff --git a/modular_dripstation/code/modules/antagonists/nukeop/nukeop.dm b/modular_dripstation/code/modules/antagonists/nukeop/nukeop.dm index 888960577048..852269504c02 100644 --- a/modular_dripstation/code/modules/antagonists/nukeop/nukeop.dm +++ b/modular_dripstation/code/modules/antagonists/nukeop/nukeop.dm @@ -80,6 +80,9 @@ op_mob.real_name = "[newname]" +//////Nuke leader////// +/datum/antagonist/nukeop/leader + antag_hud_name = "syndleader" /datum/antagonist/nukeop/leader/give_alias() title = pick("Boss", "Commander", "Chief", "Director", "Overlord") @@ -203,4 +206,7 @@ var/obj/item/computer_hardware/card_slot/CS = ID.loc CS.holder?.update_label() balloon_alert(op, "name replaced") - search_id = 0 \ No newline at end of file + search_id = 0 + +/datum/antagonist/nukeop/lone + antag_hud_name = "loneop" \ No newline at end of file diff --git a/modular_dripstation/icons/mob/hud.dmi b/modular_dripstation/icons/mob/hud.dmi new file mode 100644 index 000000000000..cea3996fa7a5 Binary files /dev/null and b/modular_dripstation/icons/mob/hud.dmi differ diff --git a/sound/mecha/hydraulic.ogg b/sound/mecha/hydraulic.ogg new file mode 100644 index 000000000000..3281ed2dc0f0 Binary files /dev/null and b/sound/mecha/hydraulic.ogg differ diff --git a/sound/mecha/powerloader_step.ogg b/sound/mecha/powerloader_step.ogg new file mode 100644 index 000000000000..538ba1efed31 Binary files /dev/null and b/sound/mecha/powerloader_step.ogg differ diff --git a/sound/mecha/powerloader_turn2.ogg b/sound/mecha/powerloader_turn2.ogg new file mode 100644 index 000000000000..c3816df9d9e2 Binary files /dev/null and b/sound/mecha/powerloader_turn2.ogg differ diff --git a/tgui/packages/common/string.js b/tgui/packages/common/string.js index 16a0921a2559..5b4e5d6d7f2b 100644 --- a/tgui/packages/common/string.js +++ b/tgui/packages/common/string.js @@ -87,6 +87,19 @@ export const capitalize = str => { return str.charAt(0).toUpperCase() + str.slice(1).toLowerCase(); }; +/** + * Similar to capitalize, this takes a string and replaces all first letters + * of any words. + * + * @param {string} str + * @return {string} The string with the first letters capitalized. + * + * @example capitalizeAll('heLLo woRLd') === 'HeLLo WoRLd' + */ +export const capitalizeAll = (str) => { + return str.replace(/(^\w{1})|(\s+\w{1})/g, (letter) => letter.toUpperCase()); +}; + export const toTitleCase = str => { // Handle array if (Array.isArray(str)) { diff --git a/tgui/packages/tgui/interfaces/AirlockElectronics.js b/tgui/packages/tgui/interfaces/AirlockElectronics.js deleted file mode 100644 index a448f55e9b2e..000000000000 --- a/tgui/packages/tgui/interfaces/AirlockElectronics.js +++ /dev/null @@ -1,78 +0,0 @@ -import { useBackend } from '../backend'; -import { Button, LabeledList, Section } from '../components'; -import { Window } from '../layouts'; -import { AccessList } from './common/AccessList'; - -export const AirlockElectronics = (props, context) => { - const { act, data } = useBackend(context); - const { - oneAccess, - unres_direction, - } = data; - const regions = data.regions || []; - const accesses = data.accesses || []; - return ( - - -
- - -
- act('set', { - access: ref, - })} - grantAll={() => act('grant_all')} - denyAll={() => act('clear_all')} - grantDep={ref => act('grant_region', { - region: ref, - })} - denyDep={ref => act('deny_region', { - region: ref, - })} /> -
-
- ); -}; diff --git a/tgui/packages/tgui/interfaces/AirlockElectronics.tsx b/tgui/packages/tgui/interfaces/AirlockElectronics.tsx new file mode 100644 index 000000000000..9166106cc02b --- /dev/null +++ b/tgui/packages/tgui/interfaces/AirlockElectronics.tsx @@ -0,0 +1,109 @@ +import { BooleanLike } from 'common/react'; +import { useBackend } from '../backend'; +import { Button, Input, LabeledList, Section } from '../components'; +import { Window } from '../layouts'; +import { AccessConfig } from './common/AccessConfig'; + +type Data = { + oneAccess: BooleanLike; + unres_direction: number; + regions: string[]; + accesses: string[]; +}; + +export const AirLockMainSection = (props, context) => { + const { act, data } = useBackend(context); + const { + accesses = [], + oneAccess, + regions = [], + unres_direction, + } = data; + + return ( +
+ + +
+ ); +}; + +export const AirlockElectronics = (props, context) => { + return ( + + + + + + ); +}; diff --git a/tgui/packages/tgui/interfaces/RapidConstructionDevice.tsx b/tgui/packages/tgui/interfaces/RapidConstructionDevice.tsx new file mode 100644 index 000000000000..937c4b256029 --- /dev/null +++ b/tgui/packages/tgui/interfaces/RapidConstructionDevice.tsx @@ -0,0 +1,181 @@ +import { Window } from '../layouts'; +import { BooleanLike, classes } from 'common/react'; +import { capitalizeAll } from 'common/string'; +import { useBackend, useLocalState } from '../backend'; +import { LabeledList, Section, Button, Tabs, Stack, Box } from '../components'; +import { AirLockMainSection } from './AirlockElectronics'; + +type Data = { + matterLeft: number; + silo_upgraded: BooleanLike; + silo_enabled: BooleanLike; + root_categories: string[]; + selected_root: string; + categories: Category[]; + selected_category: string; + selected_design: string; + display_tabs: BooleanLike; +}; + +type Category = { + cat_name: string; + designs: Design[]; +}; + +type Design = { + title: string; + design_id: Number; + icon: string; +}; + +export const MatterItem = (props, context) => { + const { data } = useBackend(context); + const { matterLeft } = data; + return ( + +  {matterLeft} Units + + ); +}; + +export const SiloItem = (props, context) => { + const { act, data } = useBackend(context); + const { silo_enabled } = data; + return ( + + act('toggle_silo')} + /> + + ); +}; + +const CategoryItem = (props, context) => { + const { act, data } = useBackend(context); + const { root_categories = [], selected_root } = data; + return ( + + {root_categories.map((root) => ( + + ))} + + ); +}; + +const ConfigureSection = (props, context) => { + const { data } = useBackend(context); + const { selected_root } = data; + + return ( + + {selected_root === 'Airlock Access' ? ( + + ) : ( + + )} + + ); +}; + +export const RapidConstructionDevice = (props, context) => { + return ( + + + + + + + + + + + + + + + ); +}; diff --git a/tgui/packages/tgui/interfaces/common/AccessConfig.js b/tgui/packages/tgui/interfaces/common/AccessConfig.js new file mode 100644 index 000000000000..32828faca24c --- /dev/null +++ b/tgui/packages/tgui/interfaces/common/AccessConfig.js @@ -0,0 +1,135 @@ +import { sortBy } from 'common/collections'; +import { Section, Button, Flex, Tabs, Grid } from '../../components'; +import { useLocalState } from '../../backend'; + +export const AccessConfig = (props, context) => { + const { + accesses = [], + selectedList = [], + accessMod, + grantAll, + denyAll, + grantDep, + denyDep, + } = props; + const [selectedAccessName, setSelectedAccessName] = useLocalState( + context, + 'accessName', + accesses[0]?.name + ); + const selectedAccess = accesses.find( + (access) => access.name === selectedAccessName + ); + const selectedAccessEntries = sortBy((entry) => entry.desc)( + selectedAccess?.accesses || [] + ); + + const checkAccessIcon = (accesses) => { + let oneAccess = false; + let oneInaccess = false; + for (let element of accesses) { + if (selectedList.includes(element.ref)) { + oneAccess = true; + } else { + oneInaccess = true; + } + } + if (!oneAccess && oneInaccess) { + return 0; + } else if (oneAccess && oneInaccess) { + return 1; + } else { + return 2; + } + }; + + return ( +
+
+ ); +}; + +const diffMap = { + 0: { + icon: 'times-circle', + color: 'bad', + }, + 1: { + icon: 'stop-circle', + color: null, + }, + 2: { + icon: 'check-circle', + color: 'good', + }, +}; diff --git a/yogstation.dme b/yogstation.dme index d6dc71cbe357..2a73321698f4 100644 --- a/yogstation.dme +++ b/yogstation.dme @@ -427,6 +427,7 @@ #include "code\controllers\subsystem\garbage.dm" #include "code\controllers\subsystem\icon_smooth.dm" #include "code\controllers\subsystem\idlenpcpool.dm" +#include "code\controllers\subsystem\init_profiler.dm" #include "code\controllers\subsystem\input.dm" #include "code\controllers\subsystem\ipintel.dm" #include "code\controllers\subsystem\job.dm" @@ -634,6 +635,7 @@ #include "code\datums\components\spill.dm" #include "code\datums\components\spooky.dm" #include "code\datums\components\squeak.dm" +#include "code\datums\components\squishable.dm" #include "code\datums\components\stationloving.dm" #include "code\datums\components\summoning.dm" #include "code\datums\components\surgery_bed.dm" @@ -1344,6 +1346,8 @@ #include "code\game\objects\items\devices\transfer_valve.dm" #include "code\game\objects\items\devices\busterarm\_buster.dm" #include "code\game\objects\items\devices\busterarm\buster_limb.dm" +#include "code\game\objects\items\devices\busterarm\busterharpoon.dm" +#include "code\game\objects\items\devices\busterarm\gasharpoon.dm" #include "code\game\objects\items\devices\busterarm\megabuster.dm" #include "code\game\objects\items\devices\busterarm\wire_snatch.dm" #include "code\game\objects\items\devices\PDA\cart.dm" @@ -3847,6 +3851,7 @@ #include "code\modules\tgui\states\observer.dm" #include "code\modules\tgui\states\permissions.dm" #include "code\modules\tgui\states\physical.dm" +#include "code\modules\tgui\states\pilot.dm" #include "code\modules\tgui\states\self.dm" #include "code\modules\tgui\states\zlevel.dm" #include "code\modules\tgui_input\alert.dm" diff --git a/yogstation/code/datums/world_topic.dm b/yogstation/code/datums/world_topic.dm index 8fc07efea64f..97e34eb09d5e 100644 --- a/yogstation/code/datums/world_topic.dm +++ b/yogstation/code/datums/world_topic.dm @@ -31,6 +31,8 @@ GLOBAL_VAR_INIT(mentornoot, FALSE) var/list/admin_keys = list() for(var/adm in GLOB.permissions.admins) var/client/C = adm + if(isnull(C)) //Yog we're having issues with null holders breaking adminwho, so let's skip nulls + continue if(input["adminchannel"]) admin_keys += "[C][C.holder.fakekey ? "(Stealth)" : ""][C.is_afk() ? "(AFK)" : ""]" else if(!C.holder.fakekey) diff --git a/yogstation/code/game/objects/effects/landmarks.dm b/yogstation/code/game/objects/effects/landmarks.dm index afb45340a277..61140dd2e873 100644 --- a/yogstation/code/game/objects/effects/landmarks.dm +++ b/yogstation/code/game/objects/effects/landmarks.dm @@ -60,6 +60,7 @@ GLOBAL_LIST_EMPTY(chosen_station_templates) stack_trace("Station room spawner [src] at ([T.x], [T.y], [T.z]) has a null template.") if(!template_name || template_name == EMPTY_SPAWN) GLOB.stationroom_landmarks -= src + qdel(src) return FALSE GLOB.chosen_station_templates += template_name var/datum/map_template/template = SSmapping.station_room_templates[template_name] @@ -69,7 +70,7 @@ GLOBAL_LIST_EMPTY(chosen_station_templates) template.load(T, centered = FALSE) template.loaded++ GLOB.stationroom_landmarks -= src - //qdel(src) + qdel(src) return TRUE // Proc to allow you to add conditions for choosing templates, instead of just randomly picking from the template list. @@ -91,40 +92,22 @@ GLOBAL_LIST_EMPTY(chosen_station_templates) template_names = current_templates return chosen_template -/obj/effect/landmark/stationroom/box - ///Should this landmark load a template during setup? You might not want to in the case of the chapel or clerk office that uses - ///player preferences to determine which template loads on roundstart - var/load_on_init = TRUE - -/obj/effect/landmark/stationroom/box/load(template_name) - GLOB.stationroom_landmarks -= src - if(!load_on_init) - //don't actually load anything, we're going to do that ourselves - return TRUE - . = ..() - /obj/effect/landmark/stationroom/box/bar - load_on_init = FALSE template_names = list( "Bar Trek", "Bar Spacious", "Bar Box", "Bar Casino", "Bar Citadel", "Bar Conveyor", "Bar Diner", "Bar Disco", "Bar Purple", "Bar Cheese", "Bar Clock", "Bar Arcade") -/obj/effect/landmark/stationroom/box/bar/Initialize(mapload) - . = ..() - GLOB.bar_landmarks += src +/obj/effect/landmark/stationroom/box/bar/load(template_name) + GLOB.stationroom_landmarks -= src + return TRUE /obj/effect/landmark/stationroom/box/clerk - load_on_init = FALSE template_names = list("Clerk Box", "Clerk Pod", "Clerk Meta", "Clerk Gambling Hall") -/obj/effect/landmark/stationroom/box/clerk/Initialize(mapload) - . = ..() - GLOB.clerk_office_landmarks += src - -// /obj/effect/landmark/stationroom/box/clerk/load(template_name) -// GLOB.stationroom_landmarks -= src -// return TRUE +/obj/effect/landmark/stationroom/box/clerk/load(template_name) + GLOB.stationroom_landmarks -= src + return TRUE /obj/effect/landmark/stationroom/box/engine template_names = list("Engine SM" = 40, "Engine Singulo And Tesla" = 20, "Engine Nuclear Reactor" = 20,"Engine TEG" = 20) @@ -161,16 +144,11 @@ GLOBAL_LIST_EMPTY(chosen_station_templates) template_names = list("Transfer 1", "Transfer 2", "Transfer 3", "Transfer 4", "Transfer 5", "Transfer 6", "Transfer 7", "Transfer 8", "Transfer 9", "Transfer 10") /obj/effect/landmark/stationroom/box/chapel - load_on_init = FALSE template_names = list("Chapel 1", "Chapel 2") -/obj/effect/landmark/stationroom/box/chapel/Initialize(mapload) - . = ..() - GLOB.chapel_landmarks += src - -// /obj/effect/landmark/stationroom/box/chapel/load(template_name) -// GLOB.stationroom_landmarks -= src -// return TRUE +/obj/effect/landmark/stationroom/box/chapel/load(template_name) + GLOB.stationroom_landmarks -= src + return TRUE /obj/effect/landmark/stationroom/meta/engine template_names = list("Meta SM" = 25, "Meta Nuclear Reactor" = 45, "Meta TEG" = 25) // tesla is loud as fuck and singulo doesn't make sense, so SM/reactor only diff --git a/yogstation/code/game/objects/items/fishing/bait.dm b/yogstation/code/game/objects/items/fishing/bait.dm index 54e4abf3d3f8..d0c64df32657 100644 --- a/yogstation/code/game/objects/items/fishing/bait.dm +++ b/yogstation/code/game/objects/items/fishing/bait.dm @@ -1,6 +1,6 @@ /obj/item/reagent_containers/food/snacks/bait name = "development bait" - desc = "if you see this, get help" + desc = "If you see this, get help." icon = 'yogstation/icons/obj/fishing/fishing.dmi' icon_state = "bait_worm" tastes = list("sour, rotten water" = 1) diff --git a/yogstation/code/modules/clothing/gloves/miscellaneous.dm b/yogstation/code/modules/clothing/gloves/miscellaneous.dm index 076f56947d07..f30b0e6b7063 100644 --- a/yogstation/code/modules/clothing/gloves/miscellaneous.dm +++ b/yogstation/code/modules/clothing/gloves/miscellaneous.dm @@ -9,8 +9,8 @@ armor = list(melee = 35, bullet = 50, laser = 45, energy = 30, bomb = 50, bio = 50, rad = 40) /obj/item/clothing/gloves/yogs/army - desc = "Gloves often seen used by military folk. These gloves are fire-resistant." name = "military gloves" + desc = "Gloves often seen used by military folk. These gloves are fire-resistant." icon_state = "armygloves" item_state = "armygloves" cold_protection = HANDS @@ -20,12 +20,12 @@ resistance_flags = NONE /obj/item/clothing/gloves/yogs/namgloves - desc = "nam gloves to help show people just exactly what war is good for." name = "nam gloves" + desc = "Nam gloves to help show people just exactly what war is good for." icon_state = "namgloves" item_state = "namgloves" cold_protection = HANDS min_cold_protection_temperature = GLOVES_MIN_TEMP_PROTECT heat_protection = HANDS max_heat_protection_temperature = GLOVES_MAX_TEMP_PROTECT - resistance_flags = NONE \ No newline at end of file + resistance_flags = NONE diff --git a/yogstation/code/modules/clothing/suits/armor.dm b/yogstation/code/modules/clothing/suits/armor.dm index 6877bd5e8e12..ba67ea89f6eb 100644 --- a/yogstation/code/modules/clothing/suits/armor.dm +++ b/yogstation/code/modules/clothing/suits/armor.dm @@ -55,7 +55,7 @@ /obj/item/clothing/suit/armor/vest/hosjacket name = "head of security jacket" - desc = "all the style of a jacket with all the protection of a armor vest!" + desc = "All the style of a jacket with all the protection of a armor vest!" mob_overlay_icon = 'yogstation/icons/mob/clothing/suit/suit.dmi' icon = 'yogstation/icons/obj/clothing/suits.dmi' icon_state = "hos_jacket" @@ -63,7 +63,7 @@ /obj/item/clothing/suit/armor/vest/wardenjacket name = "warden's black jacket" - desc = "all the style of a jacket with all the protection of a armor vest!" + desc = "All the style of a jacket with all the protection of a armor vest!" mob_overlay_icon = 'yogstation/icons/mob/clothing/suit/suit.dmi' icon = 'yogstation/icons/obj/clothing/suits.dmi' icon_state = "warden_jacket" @@ -71,7 +71,7 @@ /obj/item/clothing/suit/armor/hos/germancoat name = "padded german coat" - desc = "for those cold german winters or for those head of securitys that want to show their true colors." + desc = "For those cold german winters or those heads of security that want to show their true colors." mob_overlay_icon = 'yogstation/icons/mob/clothing/suit/suit.dmi' icon = 'yogstation/icons/obj/clothing/suits.dmi' icon_state = "german_coat" diff --git a/yogstation/code/modules/clothing/suits/miscellaneous.dm b/yogstation/code/modules/clothing/suits/miscellaneous.dm index 5bf739e57c9f..ce8501efe69c 100644 --- a/yogstation/code/modules/clothing/suits/miscellaneous.dm +++ b/yogstation/code/modules/clothing/suits/miscellaneous.dm @@ -365,7 +365,7 @@ /obj/item/clothing/head/hooded/winterhood/northern name = "northern hat" - desc = "only this, and nothing more." + desc = "Only this, and nothing more." icon_state = "northern" item_state = "northern" diff --git a/yogstation/code/modules/jobs/job_types/brig_physician.dm b/yogstation/code/modules/jobs/job_types/brig_physician.dm index e3d0bdf1eef4..6bdbcc5b305c 100644 --- a/yogstation/code/modules/jobs/job_types/brig_physician.dm +++ b/yogstation/code/modules/jobs/job_types/brig_physician.dm @@ -7,7 +7,6 @@ total_positions = 1 spawn_positions = 1 supervisors = "the chief medical officer" - selection_color = "#d4ebf2" minimal_player_age = 5 //seriously stop griefing exp_requirements = 100 exp_type = EXP_TYPE_CREW diff --git a/yogstation/code/modules/jobs/job_types/clerk.dm b/yogstation/code/modules/jobs/job_types/clerk.dm index d7d9a2d4a114..230ee6c051ef 100644 --- a/yogstation/code/modules/jobs/job_types/clerk.dm +++ b/yogstation/code/modules/jobs/job_types/clerk.dm @@ -7,7 +7,6 @@ total_positions = 1 spawn_positions = 1 supervisors = "the head of personnel" - selection_color = "#dddddd" added_access = list() base_access = list(ACCESS_MANUFACTURING) alt_titles = list("Salesman", "Gift Shop Attendent", "Retail Worker") diff --git a/yogstation/code/modules/jobs/job_types/mining_medic.dm b/yogstation/code/modules/jobs/job_types/mining_medic.dm index 326c26a014f5..f02ce13fbc2f 100644 --- a/yogstation/code/modules/jobs/job_types/mining_medic.dm +++ b/yogstation/code/modules/jobs/job_types/mining_medic.dm @@ -7,7 +7,6 @@ total_positions = 1 spawn_positions = 1 supervisors = "the chief medical officer and the quartermaster" - selection_color = "#d4ebf2" minimal_player_age = 4 exp_requirements = 120 exp_type = EXP_TYPE_CREW diff --git a/yogstation/code/modules/jobs/job_types/network_admin.dm b/yogstation/code/modules/jobs/job_types/network_admin.dm index b84aac807a57..cd7a72bdc67a 100644 --- a/yogstation/code/modules/jobs/job_types/network_admin.dm +++ b/yogstation/code/modules/jobs/job_types/network_admin.dm @@ -7,7 +7,6 @@ total_positions = 1 spawn_positions = 1 supervisors = "the chief engineer and research director" - selection_color = "#fff5cc" exp_requirements = 180 exp_type = EXP_TYPE_CREW alt_titles = list("AI Tech Support", "SysOp") diff --git a/yogstation/code/modules/jobs/job_types/paramedic.dm b/yogstation/code/modules/jobs/job_types/paramedic.dm index 9f8d3fbd6cfb..45581225f83c 100644 --- a/yogstation/code/modules/jobs/job_types/paramedic.dm +++ b/yogstation/code/modules/jobs/job_types/paramedic.dm @@ -7,7 +7,6 @@ total_positions = 3 spawn_positions = 2 supervisors = "the chief medical officer" - selection_color = "#d4ebf2" alt_titles = list("EMT", "Paramedic Trainee", "Rapid Response Medic", "Space Search & Rescue") outfit = /datum/outfit/job/paramedic diff --git a/yogstation/code/modules/jobs/job_types/psychiatrist.dm b/yogstation/code/modules/jobs/job_types/psychiatrist.dm index 0fac1c0868ab..b7487fc5ea68 100644 --- a/yogstation/code/modules/jobs/job_types/psychiatrist.dm +++ b/yogstation/code/modules/jobs/job_types/psychiatrist.dm @@ -7,7 +7,6 @@ total_positions = 1 spawn_positions = 1 supervisors = "the chief medical officer" - selection_color = "#d4ebf2" alt_titles = list("Counsellor", "Therapist", "Mentalist") minimal_player_age = 5 //stop griefing diff --git a/yogstation/code/modules/jobs/job_types/tourist.dm b/yogstation/code/modules/jobs/job_types/tourist.dm index d5ebb5c1e177..ba5aab4c8fd1 100644 --- a/yogstation/code/modules/jobs/job_types/tourist.dm +++ b/yogstation/code/modules/jobs/job_types/tourist.dm @@ -6,7 +6,6 @@ total_positions = -1 spawn_positions = 0 supervisors = "the head of personnel" - selection_color = "#dddddd" added_access = list() base_access = list() alt_titles = list("Visitor", "Traveler", "Siteseer", "Fisher") diff --git a/yogstation/code/modules/jungleland/kinetic_javelin.dm b/yogstation/code/modules/jungleland/kinetic_javelin.dm index 1c48c6d4305d..d20f0be812a2 100644 --- a/yogstation/code/modules/jungleland/kinetic_javelin.dm +++ b/yogstation/code/modules/jungleland/kinetic_javelin.dm @@ -23,7 +23,7 @@ /obj/item/kinetic_javelin name = "kinetic javelin" - desc = "powerful thrown weapon best suited to exotic environments. It has a small piece of bluespace lodged inside of it's shaft, hitting a living being while in an exotic environment teleports it straight back to you." + desc = "Powerful thrown weapon best suited to exotic environments. It has a small piece of bluespace lodged inside of it's shaft, hitting a living being while in an exotic environment teleports it straight back to you." icon = 'yogstation/icons/obj/kinetic_javelin.dmi' lefthand_file = 'yogstation/icons/mob/inhands/lefthand.dmi' righthand_file = 'yogstation/icons/mob/inhands/righthand.dmi'