diff --git a/.gitignore b/.gitignore index 9744499e37..3b85a6ec30 100644 --- a/.gitignore +++ b/.gitignore @@ -192,6 +192,7 @@ Temporary Items #Visual studio stuff *.vscode/* +tools/MapAtmosFixer/MapAtmosFixer/obj/x86/Debug/MapAtmosFixer.csproj.CoreCompileInputs.cache #GitHub Atom .atom-build.json diff --git a/_maps/map_files/Mining/Lavaland.dmm b/_maps/map_files/Mining/Lavaland.dmm index 2b542e23bc..0d0ee8e152 100644 --- a/_maps/map_files/Mining/Lavaland.dmm +++ b/_maps/map_files/Mining/Lavaland.dmm @@ -196,6 +196,7 @@ /area/mine/laborcamp) "aI" = ( /obj/machinery/door/airlock{ + cyclelinkeddir = 4; name = "Labor Camp External Access" }, /turf/open/floor/plasteel, @@ -286,6 +287,7 @@ /area/lavaland/surface/outdoors/explored) "aY" = ( /obj/machinery/door/airlock/glass_security{ + cyclelinkeddir = 4; name = "Labor Camp Shuttle Security Airlock"; req_access_txt = "2" }, @@ -449,6 +451,7 @@ /area/mine/eva) "bx" = ( /obj/machinery/door/airlock/glass_security{ + cyclelinkeddir = 4; name = "Labor Camp Shuttle Prisoner Airlock"; req_access_txt = "0" }, @@ -659,6 +662,7 @@ /area/mine/eva) "bX" = ( /obj/machinery/door/airlock/external{ + cyclelinkeddir = 4; glass = 1; name = "Mining External Airlock"; opacity = 0; @@ -744,6 +748,7 @@ /area/mine/laborcamp) "cj" = ( /obj/machinery/door/airlock/external{ + cyclelinkeddir = 4; glass = 1; name = "Mining Shuttle Airlock"; opacity = 0; @@ -3317,6 +3322,49 @@ /obj/effect/mapping_helpers/planet_z, /turf/open/lava/smooth/lava_land_surface, /area/lavaland/surface/outdoors) +"WA" = ( +/obj/machinery/door/airlock{ + cyclelinkeddir = 8; + name = "Labor Camp External Access" + }, +/turf/open/floor/plasteel, +/area/mine/laborcamp) +"WB" = ( +/obj/machinery/door/airlock/glass_security{ + cyclelinkeddir = 8; + name = "Labor Camp Shuttle Security Airlock"; + req_access_txt = "2" + }, +/turf/open/floor/plasteel, +/area/mine/laborcamp) +"WC" = ( +/obj/machinery/door/airlock/glass_security{ + cyclelinkeddir = 8; + name = "Labor Camp Shuttle Prisoner Airlock"; + req_access_txt = "0" + }, +/turf/open/floor/plasteel, +/area/mine/laborcamp) +"WD" = ( +/obj/machinery/door/airlock/external{ + cyclelinkeddir = 8; + glass = 1; + name = "Mining External Airlock"; + opacity = 0; + req_access_txt = "54" + }, +/turf/open/floor/plasteel, +/area/mine/eva) +"WE" = ( +/obj/machinery/door/airlock/external{ + cyclelinkeddir = 8; + glass = 1; + name = "Mining Shuttle Airlock"; + opacity = 0; + req_access_txt = "0" + }, +/turf/open/floor/plasteel, +/area/mine/production) (1,1,1) = {" aa @@ -8415,11 +8463,11 @@ aH az aQ aq -aY +WB aq bi aq -bx +WC aq bZ bZ @@ -11238,7 +11286,7 @@ an an aD aq -aI +WA aq aT aD @@ -17930,7 +17978,7 @@ aj aj br br -cj +WE br br ab @@ -21270,7 +21318,7 @@ aj ab bf bg -bX +WD bg bf ai diff --git a/code/__DEFINES/atmospherics.dm b/code/__DEFINES/atmospherics.dm index f607c34ae8..dacd09c995 100644 --- a/code/__DEFINES/atmospherics.dm +++ b/code/__DEFINES/atmospherics.dm @@ -1,14 +1,5 @@ -#define FIRE_DAMAGE_MODIFIER 0.0215 //Higher values result in more external fire damage to the skin (default 0.0215) -#define AIR_DAMAGE_MODIFIER 2.025 //More means less damage from hot air scalding lungs, less = more damage. (default 2.025) - -#define MOLES_CELLSTANDARD (ONE_ATMOSPHERE*CELL_VOLUME/(T20C*R_IDEAL_GAS_EQUATION)) //moles in a 2.5 m^3 cell at 101.325 Pa and 20 degC -#define M_CELL_WITH_RATIO (MOLES_CELLSTANDARD * 0.005) -#define O2STANDARD 0.21 -#define N2STANDARD 0.79 -#define MOLES_O2STANDARD (MOLES_CELLSTANDARD*O2STANDARD) // O2 standard value (21%) -#define MOLES_N2STANDARD (MOLES_CELLSTANDARD*N2STANDARD) // N2 standard value (79%) - -//indices of values in gas lists. used by listmos. +//LISTMOS +//indices of values in gas lists. #define MOLES 1 #define ARCHIVE 2 #define GAS_META 3 @@ -19,32 +10,35 @@ #define META_GAS_DANGER 5 #define META_GAS_ID 6 -//stuff you should probably leave well alone! //ATMOS -#define CELL_VOLUME 2500 //liters in a cell -#define BREATH_VOLUME 0.5 //liters in a normal breath -#define BREATH_PERCENTAGE (BREATH_VOLUME/CELL_VOLUME) //Amount of air to take a from a tile -#define HUMAN_NEEDED_OXYGEN (MOLES_CELLSTANDARD*BREATH_PERCENTAGE*0.16) //Amount of air needed before pass out/suffocation commences -#define NORMPIPERATE 30 //pipe-insulation rate divisor -#define HEATPIPERATE 8 //heat-exch pipe insulation -#define FLOWFRAC 0.99 //fraction of gas transfered per process -#define TANK_MELT_TEMPERATURE 1000000 -#define TANK_LEAK_PRESSURE (30.*ONE_ATMOSPHERE) //Tank starts leaking -#define TANK_RUPTURE_PRESSURE (35.*ONE_ATMOSPHERE) //Tank spills all contents into atmosphere -#define TANK_FRAGMENT_PRESSURE (40.*ONE_ATMOSPHERE) //Boom 3x3 base explosion -#define TANK_FRAGMENT_SCALE (6.*ONE_ATMOSPHERE) //+1 for each SCALE kPa aboe threshold -#define MINIMUM_AIR_RATIO_TO_SUSPEND 0.1 //Ratio of air that must move to/from a tile to reset group processing -#define MINIMUM_AIR_RATIO_TO_MOVE 0.001 //Minimum ratio of air that must move to/from a tile -#define MINIMUM_AIR_TO_SUSPEND (MOLES_CELLSTANDARD*MINIMUM_AIR_RATIO_TO_SUSPEND) //Minimum amount of air that has to move before a group processing can be suspended -#define MINIMUM_MOLES_DELTA_TO_MOVE (MOLES_CELLSTANDARD*MINIMUM_AIR_RATIO_TO_MOVE) //Either this must be active -#define EXCITED_GROUP_BREAKDOWN_CYCLES 4 -#define EXCITED_GROUP_DISMANTLE_CYCLES 16 -#define MINIMUM_TEMPERATURE_TO_MOVE (T20C+100) //or this (or both, obviously) -#define MINIMUM_TEMPERATURE_RATIO_TO_SUSPEND 0.012 +//stuff you should probably leave well alone! +#define MOLES_CELLSTANDARD (ONE_ATMOSPHERE*CELL_VOLUME/(T20C*R_IDEAL_GAS_EQUATION)) //moles in a 2.5 m^3 cell at 101.325 Pa and 20 degC +#define M_CELL_WITH_RATIO (MOLES_CELLSTANDARD * 0.005) //compared against for superconductivity +#define O2STANDARD 0.21 //percentage of oxygen in a normal mixture of air +#define N2STANDARD 0.79 //same but for nitrogen +#define MOLES_O2STANDARD (MOLES_CELLSTANDARD*O2STANDARD) // O2 standard value (21%) +#define MOLES_N2STANDARD (MOLES_CELLSTANDARD*N2STANDARD) // N2 standard value (79%) +#define CELL_VOLUME 2500 //liters in a cell +#define BREATH_VOLUME 0.5 //liters in a normal breath +#define BREATH_PERCENTAGE (BREATH_VOLUME/CELL_VOLUME) //Amount of air to take a from a tile +#define HUMAN_NEEDED_OXYGEN (MOLES_CELLSTANDARD*BREATH_PERCENTAGE*0.16) //Amount of air needed before pass out/suffocation commences + +//EXCITED GROUPS +#define EXCITED_GROUP_BREAKDOWN_CYCLES 4 //number of FULL air controller ticks before an excited group breaks down (averages gas contents across turfs) +#define EXCITED_GROUP_DISMANTLE_CYCLES 16 //number of FULL air controller ticks before an excited group dismantles and removes its turfs from active +#define MINIMUM_AIR_RATIO_TO_SUSPEND 0.1 //Ratio of air that must move to/from a tile to reset group processing +#define MINIMUM_AIR_RATIO_TO_MOVE 0.001 //Minimum ratio of air that must move to/from a tile +#define MINIMUM_AIR_TO_SUSPEND (MOLES_CELLSTANDARD*MINIMUM_AIR_RATIO_TO_SUSPEND) //Minimum amount of air that has to move before a group processing can be suspended +#define MINIMUM_MOLES_DELTA_TO_MOVE (MOLES_CELLSTANDARD*MINIMUM_AIR_RATIO_TO_MOVE) //Either this must be active +#define MINIMUM_TEMPERATURE_TO_MOVE (T20C+100) //or this (or both, obviously) #define MINIMUM_TEMPERATURE_DELTA_TO_SUSPEND 4 //Minimum temperature difference before group processing is suspended #define MINIMUM_TEMPERATURE_DELTA_TO_CONSIDER 0.5 //Minimum temperature difference before the gas temperatures are just set to be equal #define MINIMUM_TEMPERATURE_FOR_SUPERCONDUCTION T20C+10 #define MINIMUM_TEMPERATURE_START_SUPERCONDUCTION T20C+200 + +//HEAT TRANSFER COEFFICIENTS +//Must be between 0 and 1. Values closer to 1 equalize temperature faster +//Should not exceed 0.4 else strange heat flow occur #define FLOOR_HEAT_TRANSFER_COEFFICIENT 0.4 #define WALL_HEAT_TRANSFER_COEFFICIENT 0.0 #define DOOR_HEAT_TRANSFER_COEFFICIENT 0.0 @@ -52,20 +46,31 @@ #define OPEN_HEAT_TRANSFER_COEFFICIENT 0.4 #define WINDOW_HEAT_TRANSFER_COEFFICIENT 0.1 //a hack for now #define HEAT_CAPACITY_VACUUM 7000 //a hack to help make vacuums "cold", sacrificing realism for gameplay - //Must be between 0 and 1. Values closer to 1 equalize temperature faster - //Should not exceed 0.4 else strange heat flow occur + +//FIRE #define FIRE_MINIMUM_TEMPERATURE_TO_SPREAD 150+T0C #define FIRE_MINIMUM_TEMPERATURE_TO_EXIST 100+T0C #define FIRE_SPREAD_RADIOSITY_SCALE 0.85 #define FIRE_GROWTH_RATE 40000 //For small fires #define CARBON_LIFEFORM_FIRE_RESISTANCE 200+T0C //Resistance to fire damage #define CARBON_LIFEFORM_FIRE_DAMAGE 4 //Fire damage +#define PLASMA_MINIMUM_BURN_TEMPERATURE 100+T0C + +//GASES #define MIN_TOXIC_GAS_DAMAGE 1 #define MAX_TOXIC_GAS_DAMAGE 10 #define MOLES_GAS_VISIBLE 0.5 //Moles in a standard cell after which gases are visible -#define STOP_REACTIONS 2 -#define PLASMA_MINIMUM_BURN_TEMPERATURE 100+T0C -#define GAS_STIM_MINIMUM 0.002 + +//REACTIONS +//return values for reactions (bitflags) +#define NO_REACTION 0 +#define REACTING 1 +#define STOP_REACTIONS 2 + +//HUMANS +//Hurty numbers +#define FIRE_DAMAGE_MODIFIER 0.0215 //Higher values result in more external fire damage to the skin +#define AIR_DAMAGE_MODIFIER 2.025 //More means less damage from hot air scalding lungs, less = more damage // Pressure limits. #define HAZARD_HIGH_PRESSURE 550 //This determins at what pressure the ultra-high pressure red icon is displayed. (This one is set as a constant) @@ -107,65 +112,71 @@ #define SHOES_MIN_TEMP_PROTECT 2.0 //For gloves #define SHOES_MAX_TEMP_PROTECT 1500 //For gloves - #define PRESSURE_DAMAGE_COEFFICIENT 4 //The amount of pressure damage someone takes is equal to (pressure / HAZARD_HIGH_PRESSURE)*PRESSURE_DAMAGE_COEFFICIENT, with the maximum of MAX_PRESSURE_DAMAGE #define MAX_HIGH_PRESSURE_DAMAGE 4 #define LOW_PRESSURE_DAMAGE 4 //The amount of damage someone takes when in a low pressure area (The pressure threshold is so low that it doesn't make sense to do any calculations, so it just applies this flat value). #define COLD_SLOWDOWN_FACTOR 20 //Humans are slowed by the difference between bodytemp and BODYTEMP_COLD_DAMAGE_LIMIT divided by this -// Atmos pipe limits +//PIPES +//Atmos pipe limits #define MAX_OUTPUT_PRESSURE 4500 // (kPa) What pressure pumps and powered equipment max out at. #define MAX_TRANSFER_RATE 200 // (L/s) Maximum speed powered equipment can work at. -//Atmos machinery pipenet stuff - -// used for device_type vars; used by DEVICE_TYPE_LOOP +//used for device_type vars; used by DEVICE_TYPE_LOOP #define UNARY 1 #define BINARY 2 #define TRINARY 3 #define QUATERNARY 4 -// this is the standard for loop used by all sorts of atmos machinery procs +//TODO: finally remove this bullshit +//this is the standard for loop used by all sorts of atmos machinery procs #define DEVICE_TYPE_LOOP var/I in 1 to device_type -// defines for the various machinery lists -// NODE_I, AIR_I, PARENT_I are used within DEVICE_TYPE_LOOP +//defines for the various machinery lists +//NODE_I, AIR_I, PARENT_I are used within DEVICE_TYPE_LOOP -// nodes list - all atmos machinery +//nodes list - all atmos machinery #define NODE1 nodes[1] #define NODE2 nodes[2] #define NODE3 nodes[3] #define NODE4 nodes[4] #define NODE_I nodes[I] -// airs list - components only +//airs list - components only #define AIR1 airs[1] #define AIR2 airs[2] #define AIR3 airs[3] #define AIR_I airs[I] -// parents list - components only +//parents list - components only #define PARENT1 parents[1] #define PARENT2 parents[2] #define PARENT3 parents[3] #define PARENT_I parents[I] -//Tanks -#define TANK_MAX_RELEASE_PRESSURE (ONE_ATMOSPHERE*3) -#define TANK_MIN_RELEASE_PRESSURE 0 -#define TANK_DEFAULT_RELEASE_PRESSURE 16 - +//TANKS +#define TANK_MELT_TEMPERATURE 1000000 //temperature in kelvins at which a tank will start to melt +#define TANK_LEAK_PRESSURE (30.*ONE_ATMOSPHERE) //Tank starts leaking +#define TANK_RUPTURE_PRESSURE (35.*ONE_ATMOSPHERE) //Tank spills all contents into atmosphere +#define TANK_FRAGMENT_PRESSURE (40.*ONE_ATMOSPHERE) //Boom 3x3 base explosion +#define TANK_FRAGMENT_SCALE (6.*ONE_ATMOSPHERE) //+1 for each SCALE kPa aboe threshold +#define TANK_MAX_RELEASE_PRESSURE (ONE_ATMOSPHERE*3) +#define TANK_MIN_RELEASE_PRESSURE 0 +#define TANK_DEFAULT_RELEASE_PRESSURE 16 +//CANATMOSPASS #define ATMOS_PASS_YES 1 #define ATMOS_PASS_NO 0 #define ATMOS_PASS_PROC -1 //ask CanAtmosPass() #define ATMOS_PASS_DENSITY -2 //just check density #define CANATMOSPASS(A, O) ( A.CanAtmosPass == ATMOS_PASS_PROC ? A.CanAtmosPass(O) : ( A.CanAtmosPass == ATMOS_PASS_DENSITY ? !A.density : A.CanAtmosPass ) ) +//LAVALAND #define LAVALAND_EQUIPMENT_EFFECT_PRESSURE 50 //what pressure you have to be under to increase the effect of equipment meant for lavaland #define LAVALAND_DEFAULT_ATMOS "o2=14;n2=23;TEMP=300" +//MULTIPIPES //IF YOU EVER CHANGE THESE CHANGE SPRITES TO MATCH. #define PIPING_LAYER_MIN 1 #define PIPING_LAYER_MAX 3 @@ -179,6 +190,7 @@ #define PIPING_DEFAULT_LAYER_ONLY 4 //can only exist at PIPING_LAYER_DEFAULT #define PIPING_CARDINAL_AUTONORMALIZE 8 //north/south east/west doesn't matter, auto normalize on build. +//HELPERS #define THERMAL_ENERGY(gas) (gas.temperature * gas.heat_capacity()) #define ADD_GAS(gas_id, out_list)\ diff --git a/code/__DEFINES/components.dm b/code/__DEFINES/components.dm index 7da895a593..87c226b839 100644 --- a/code/__DEFINES/components.dm +++ b/code/__DEFINES/components.dm @@ -77,6 +77,10 @@ #define COMSIG_MACHINE_PROCESS "machine_process" //from machinery subsystem fire(): () #define COMSIG_MACHINE_PROCESS_ATMOS "machine_process_atmos" //from air subsystem process_atmos_machinery(): () + // /mob/living/carbon/human signals #define COMSIG_HUMAN_MELEE_UNARMED_ATTACK "human_melee_unarmed_attack" //from mob/living/carbon/human/UnarmedAttack(): (atom/target) #define COMSIG_HUMAN_MELEE_UNARMED_ATTACKBY "human_melee_unarmed_attackby" //from mob/living/carbon/human/UnarmedAttack(): (mob/living/carbon/human/attacker) + +#define CALTROP_BYPASS_SHOES 1 +#define CALTROP_IGNORE_WALKERS 2 diff --git a/code/__HELPERS/_lists.dm b/code/__HELPERS/_lists.dm index c8163f980a..631214de98 100644 --- a/code/__HELPERS/_lists.dm +++ b/code/__HELPERS/_lists.dm @@ -9,6 +9,16 @@ * Misc */ +#define LAZYINITLIST(L) if (!L) L = list() +#define UNSETEMPTY(L) if (L && !L.len) L = null +#define LAZYREMOVE(L, I) if(L) { L -= I; if(!L.len) { L = null; } } +#define LAZYADD(L, I) if(!L) { L = list(); } L += I; +#define LAZYACCESS(L, I) (L ? (isnum(I) ? (I > 0 && I <= L.len ? L[I] : null) : L[I]) : null) +#define LAZYSET(L, K, V) if(!L) { L = list(); } L[K] = V; +#define LAZYLEN(L) length(L) +#define LAZYCLEARLIST(L) if(L) L.Cut() +#define SANITIZE_LIST(L) ( islist(L) ? L : list() ) + //Returns a list in plain english as a string /proc/english_list(list/input, nothing_text = "nothing", and_text = " and ", comma_text = ", ", final_comma_text = "" ) var/total = input.len @@ -32,7 +42,7 @@ //Returns list element or null. Should prevent "index out of bounds" error. /proc/listgetindex(list/L, index) - if(istype(L)) + if(LAZYLEN(L)) if(isnum(index) && IsInteger(index)) if(IsInRange(index,1,L.len)) return L[index] @@ -42,7 +52,7 @@ //Return either pick(list) or null if list is not of type /list or is empty /proc/safepick(list/L) - if(istype(L) && L.len) + if(LAZYLEN(L)) return pick(L) //Checks if the list is empty @@ -53,7 +63,7 @@ //Checks for specific types in a list /proc/is_type_in_list(atom/A, list/L) - if(!L || !L.len || !A) + if(!LAZYLEN(L) || !A) return FALSE for(var/type in L) if(istype(A, type)) @@ -62,7 +72,7 @@ //Checks for specific types in specifically structured (Assoc "type" = TRUE) lists ('typecaches') /proc/is_type_in_typecache(atom/A, list/L) - if(!L || !L.len || !A) + if(!LAZYLEN(L) || !A) return FALSE if(ispath(A)) @@ -72,7 +82,7 @@ //Checks for a string in a list /proc/is_string_in_list(string, list/L) - if(!L || !L.len || !string) + if(!LAZYLEN(L) || !string) return for(var/V in L) if(string == V) @@ -81,7 +91,7 @@ //Removes a string from a list /proc/remove_strings_from_list(string, list/L) - if(!L || !L.len || !string) + if(!LAZYLEN(L) || !string) return for(var/V in L) if(V == string) @@ -486,16 +496,6 @@ //Picks from the list, with some safeties, and returns the "default" arg if it fails #define DEFAULTPICK(L, default) ((islist(L) && length(L)) ? pick(L) : default) -#define LAZYINITLIST(L) if (!L) L = list() -#define UNSETEMPTY(L) if (L && !L.len) L = null -#define LAZYREMOVE(L, I) if(L) { L -= I; if(!L.len) { L = null; } } -#define LAZYADD(L, I) if(!L) { L = list(); } L += I; -#define LAZYACCESS(L, I) (L ? (isnum(I) ? (I > 0 && I <= L.len ? L[I] : null) : L[I]) : null) -#define LAZYSET(L, K, V) if(!L) { L = list(); } L[K] = V; -#define LAZYLEN(L) length(L) -#define LAZYCLEARLIST(L) if(L) L.Cut() -#define SANITIZE_LIST(L) ( islist(L) ? L : list() ) - /* Definining a counter as a series of key -> numeric value entries * All these procs modify in place. diff --git a/code/__HELPERS/game.dm b/code/__HELPERS/game.dm index 57fe0559fa..0e1c1c3979 100644 --- a/code/__HELPERS/game.dm +++ b/code/__HELPERS/game.dm @@ -326,25 +326,6 @@ return M return null -// Will return a list of active candidates. It increases the buffer 5 times until it finds a candidate which is active within the buffer. - -/proc/get_candidates(be_special_type, afk_bracket = CONFIG_GET(number/inactivity_period), jobbanType) - var/list/candidates = list() - // Keep looping until we find a non-afk candidate within the time bracket (we limit the bracket to 10 minutes (6000)) - var/afk_period = CONFIG_GET(number/afk_period) - while(!candidates.len && afk_bracket < afk_period) - for(var/mob/dead/observer/G in GLOB.player_list) - if(G.client != null) - if(!(G.mind && G.mind.current && G.mind.current.stat != DEAD)) - if(!G.client.is_afk(afk_bracket) && (be_special_type in G.client.prefs.be_special)) - if (jobbanType) - if(!(jobban_isbanned(G, jobbanType) || jobban_isbanned(G, "Syndicate"))) - candidates += G.client - else - candidates += G.client - afk_bracket += 600 // Add a minute to the bracket, for every attempt - return candidates - /proc/considered_alive(datum/mind/M, enforce_human = TRUE) if(M && M.current) if(enforce_human) diff --git a/code/__HELPERS/maths.dm b/code/__HELPERS/maths.dm index 9b071d0143..0af8b8ae1a 100644 --- a/code/__HELPERS/maths.dm +++ b/code/__HELPERS/maths.dm @@ -198,7 +198,7 @@ GLOBAL_LIST_INIT(sqrtTable, list(1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 4, var/list/screen_loc_Y = splittext(screen_loc_params[2],":") var/x = (text2num(screen_loc_X[1]) * 32 + text2num(screen_loc_X[2]) - 32) var/y = (text2num(screen_loc_Y[1]) * 32 + text2num(screen_loc_Y[2]) - 32) - var/list/screenview = getviewsize(client) + var/list/screenview = getviewsize(client.view) var/screenviewX = screenview[1] * world.icon_size var/screenviewY = screenview[2] * world.icon_size var/ox = round(screenviewX/2) - client.pixel_x //"origin" x diff --git a/code/__HELPERS/type2type.dm b/code/__HELPERS/type2type.dm index 64ea8de756..bae773b27e 100644 --- a/code/__HELPERS/type2type.dm +++ b/code/__HELPERS/type2type.dm @@ -14,30 +14,23 @@ //breaks when hittin invalid characters thereafter /proc/hex2num(hex) . = 0 - if(istext(hex)) - var/negative = 0 - var/len = length(hex) - for(var/i=1, i<=len, i++) - var/num = text2ascii(hex,i) - switch(num) - if(48 to 57) - num -= 48 //0-9 - if(97 to 102) - num -= 87 //a-f - if(65 to 70) - num -= 55 //A-F - if(45) - negative = 1//- - else - if(num) - break - else - continue - . *= 16 - . += num - if(negative) - . *= -1 - return . + var/place = 1 + for(var/i in length(hex) to 1 step -1) + var/num = text2ascii(hex, i) + switch(num) + if(48 to 57) + num -= 48 //0-9 + if(97 to 102) + num -= 87 //a-f + if(65 to 70) + num -= 55 //A-F + if(45) + return . * -1 // - + else + CRASH("Malformed hex number") + + . += num * place + place *= 16 //Returns the hex value of a decimal number //len == length of returned string diff --git a/code/_globalvars/configuration.dm b/code/_globalvars/configuration.dm index 391744e34c..8ecf572ea7 100644 --- a/code/_globalvars/configuration.dm +++ b/code/_globalvars/configuration.dm @@ -35,4 +35,3 @@ GLOBAL_PROTECT(MAX_EX_FLASH_RANGE) GLOBAL_VAR_INIT(MAX_EX_FLAME_RANGE, 14) GLOBAL_PROTECT(MAX_EX_FLAME_RANGE) GLOBAL_VAR_INIT(DYN_EX_SCALE, 0.5) - diff --git a/code/_onclick/click.dm b/code/_onclick/click.dm index 0cc24607f4..ce9e1ead82 100644 --- a/code/_onclick/click.dm +++ b/code/_onclick/click.dm @@ -285,7 +285,7 @@ if(!stat && mind && iscarbon(A) && A != src) var/datum/antagonist/changeling/C = mind.has_antag_datum(/datum/antagonist/changeling) if(C && C.chosen_sting) - C.chosen_sting.try_to_sting(src,A) + C.chosen_sting.try_to_sting(src,A) next_click = world.time + 5 return swap_hand() @@ -349,7 +349,7 @@ if(!stat && mind && iscarbon(A) && A != src) var/datum/antagonist/changeling/C = mind.has_antag_datum(/datum/antagonist/changeling) if(C && C.chosen_sting) - C.chosen_sting.try_to_sting(src,A) + C.chosen_sting.try_to_sting(src,A) next_click = world.time + 5 return ..() @@ -433,28 +433,38 @@ else setDir(WEST) +//debug +/obj/screen/proc/scale_to(x1,y1) + if(!y1) + y1 = x1 + var/matrix/M = new + M.Scale(x1,y1) + transform = M + /obj/screen/click_catcher icon = 'icons/mob/screen_gen.dmi' - icon_state = "flash" + icon_state = "catcher" plane = CLICKCATCHER_PLANE mouse_opacity = MOUSE_OPACITY_OPAQUE screen_loc = "CENTER" +#define MAX_SAFE_BYOND_ICON_SCALE_TILES (MAX_SAFE_BYOND_ICON_SCALE_PX / world.icon_size) +#define MAX_SAFE_BYOND_ICON_SCALE_PX 33 * 32 //Not using world.icon_size on purpose. + /obj/screen/click_catcher/proc/UpdateGreed(view_size_x = 15, view_size_y = 15) - var/icon/newicon = icon('icons/mob/screen_gen.dmi', "flash") - if(view_size_x > 32 || view_size_y > 32) - newicon.Scale(16 * world.icon_size,16 * world.icon_size) - icon = newicon - var/tx = ((view_size_x - 1)*0.5)/16 - var/ty = ((view_size_y - 1)*0.5)/16 - var/matrix/M = new - M.Scale(tx, ty) - transform = M - screen_loc = "CENTER-16,CENTER-16" - else - screen_loc = "CENTER-[(view_size_x-1)*0.5],CENTER-[(view_size_y-1)*0.5]" - newicon.Scale(view_size_x * world.icon_size,view_size_y * world.icon_size) - icon = newicon + var/icon/newicon = icon('icons/mob/screen_gen.dmi', "catcher") + var/ox = min(MAX_SAFE_BYOND_ICON_SCALE_TILES, view_size_x) + var/oy = min(MAX_SAFE_BYOND_ICON_SCALE_TILES, view_size_y) + var/px = view_size_x * world.icon_size + var/py = view_size_y * world.icon_size + var/sx = min(MAX_SAFE_BYOND_ICON_SCALE_PX, px) + var/sy = min(MAX_SAFE_BYOND_ICON_SCALE_PX, py) + newicon.Scale(sx, sy) + icon = newicon + screen_loc = "CENTER-[(ox-1)*0.5],CENTER-[(oy-1)*0.5]" + var/matrix/M = new + M.Scale(px/sx, py/sy) + transform = M /obj/screen/click_catcher/Click(location, control, params) var/list/modifiers = params2list(params) diff --git a/code/citadel/cit_weapons.dm b/code/citadel/cit_weapons.dm index c709fe90e9..b661294ae7 100644 --- a/code/citadel/cit_weapons.dm +++ b/code/citadel/cit_weapons.dm @@ -11,7 +11,7 @@ attack_verb = list("poked", "jabbed", "hit") light_color = "#37FFF7" var/light_brightness = 3 - actions_types = list(/datum/action/item_action/pick_color) + actions_types = list() /obj/item/toy/sword/cx/attack_self(mob/user) active = !( active ) @@ -57,18 +57,21 @@ var/mob/M = loc M.update_inv_hands() -/obj/item/toy/sword/cx/ui_action_click(mob/user, var/datum/action/A) - if(istype(A, /datum/action/item_action/pick_color)) - if(alert("Are you sure you want to recolor your blade?", "Confirm Repaint", "Yes", "No") == "Yes") - var/energy_color_input = input(usr,"Choose Energy Color") as color|null - if(energy_color_input) - light_color = sanitize_hexcolor(energy_color_input, desired_format=6, include_crunch=1) - update_icon() - update_light() - A.UpdateButtonIcon() +/obj/item/toy/sword/cx/AltClick(mob/living/user) + if(user.incapacitated() || !istype(user)) + to_chat(user, "You can't do that right now!") + return + if(!in_range(src, user)) + return + if(user.incapacitated() || !istype(user) || !in_range(src, user)) + return - else - ..() + if(alert("Are you sure you want to recolor your blade?", "Confirm Repaint", "Yes", "No") == "Yes") + var/energy_color_input = input(usr,"Choose Energy Color") as color|null + if(energy_color_input) + light_color = sanitize_hexcolor(energy_color_input, desired_format=6, include_crunch=1) + update_icon() + update_light() /obj/item/toy/sword/cx/worn_overlays(isinhands, icon_file) . = ..() @@ -79,7 +82,21 @@ . += blade_inhand /obj/item/toy/sword/cx/attackby(obj/item/W, mob/living/user, params) - return //NO MORE MAKING DUAL ESWORDS + if(istype(W, /obj/item/toy/sword/cx)) + if((W.flags_1 & NODROP_1) || (flags_1 & NODROP_1)) + to_chat(user, "\the [flags_1 & NODROP_1 ? src : W] is stuck to your hand, you can't attach it to \the [flags_1 & NODROP_1 ? W : src]!") + return + else + to_chat(user, "You combine the two plastic swords, making a single supermassive toy! You're fake-cool.") + new /obj/item/twohanded/hypereutactic/toy(user.loc) + qdel(W) + qdel(src) + else + return ..() + +/obj/item/toy/sword/cx/examine(mob/user) + ..() + to_chat(user, "Alt-click to recolor it.") /*///autolathe memes/// I really need to stop doing this and find a proper way of adding in my toys @@ -124,7 +141,7 @@ origin_tech = "combat=3;magnets=4" block_chance = 60 light_color = "#37FFF7" - actions_types = list(/datum/action/item_action/pick_color) + actions_types = list() /obj/item/melee/transforming/energy/sword/cx/transform_weapon(mob/living/user, supress_message_text) active = !active //I'd use a ..() here but it'd inherit from the regular esword's proc instead, so SPAGHETTI CODE @@ -152,9 +169,6 @@ update_icon() transform_messages(user, supress_message_text) add_fingerprint(user) - for(var/X in actions) - var/datum/action/A = X - A.UpdateButtonIcon() return TRUE /obj/item/melee/transforming/energy/sword/cx/transform_messages(mob/living/user, supress_message_text) @@ -181,18 +195,25 @@ var/mob/M = loc M.update_inv_hands() -/obj/item/melee/transforming/energy/sword/cx/ui_action_click(mob/user, var/datum/action/A) - if(istype(A, /datum/action/item_action/pick_color)) - if(alert("Are you sure you want to recolor your blade?", "Confirm Repaint", "Yes", "No") == "Yes") - var/energy_color_input = input(usr,"Choose Energy Color") as color|null - if(energy_color_input) - light_color = sanitize_hexcolor(energy_color_input, desired_format=6, include_crunch=1) - update_icon() - update_light() - A.UpdateButtonIcon() +/obj/item/melee/transforming/energy/sword/cx/AltClick(mob/living/user) + if(user.incapacitated() || !istype(user)) + to_chat(user, "You can't do that right now!") + return + if(!in_range(src, user)) + return + if(user.incapacitated() || !istype(user) || !in_range(src, user)) + return - else - ..() + if(alert("Are you sure you want to recolor your blade?", "Confirm Repaint", "Yes", "No") == "Yes") + var/energy_color_input = input(usr,"Choose Energy Color") as color|null + if(energy_color_input) + light_color = sanitize_hexcolor(energy_color_input, desired_format=6, include_crunch=1) + update_icon() + update_light() + +/obj/item/melee/transforming/energy/sword/cx/examine(mob/user) + ..() + to_chat(user, "Alt-click to recolor it.") /obj/item/melee/transforming/energy/sword/cx/worn_overlays(isinhands, icon_file) . = ..() diff --git a/code/citadel/custom_loadout/custom_items.dm b/code/citadel/custom_loadout/custom_items.dm index 885e06d83b..108e50b07a 100644 --- a/code/citadel/custom_loadout/custom_items.dm +++ b/code/citadel/custom_loadout/custom_items.dm @@ -16,17 +16,20 @@ /obj/item/clothing/neck/cloak/inferno name = "Kiara's Cloak" desc = "The design on this seems a little too familiar." - icon = 'icons/obj/clothing/cloaks.dmi' - icon_state = "infcloak" - item_state = "infcloak" + icon = 'icons/obj/custom.dmi' + icon_state = "infcloak-i" + icon_override = 'icons/obj/custom.dmi' + item_state = "infcloak-w" w_class = WEIGHT_CLASS_SMALL body_parts_covered = CHEST|GROIN|LEGS|ARMS /obj/item/clothing/neck/petcollar/inferno name = "Kiara's Collar" desc = "A soft black collar that seems to stretch to fit whoever wears it." - icon_state = "infcollar" - item_state = "infcollar" + icon = 'icons/obj/custom.dmi' + icon_state = "infcollar-i" + icon_override = 'icons/obj/custom.dmi' + item_state = "infcollar-w" item_color = null tagname = null @@ -43,7 +46,7 @@ /obj/item/lighter/gold name = "\improper Engraved Zippo" desc = "A shiny and relatively expensive zippo lighter. There's a small etched in verse on the bottom that reads, 'No Gods, No Masters, Only Man.'" - icon = 'icons/obj/cigarettes.dmi' + icon = 'icons/obj/custom.dmi' icon_state = "gold_zippo" item_state = "gold_zippo" w_class = WEIGHT_CLASS_TINY @@ -58,16 +61,20 @@ /obj/item/clothing/neck/scarf/zomb //Default white color, same functionality as beanies. name = "A special scarf" - icon_state = "zombscarf" + icon = 'icons/obj/custom.dmi' + icon_state = "zombscarf-i" desc = "A fashionable collar" - item_color = "zombscarf" + icon_override = 'icons/obj/custom.dmi' + item_color = "zombscarf-w" dog_fashion = /datum/dog_fashion/head /obj/item/clothing/suit/toggle/labcoat/mad/red name = "\improper The Mad's labcoat" desc = "An oddly special looking coat." - icon_state = "labred" - item_state = "labred" + icon = 'icons/obj/custom.dmi' + icon_state = "labred-i" + icon_override = 'icons/obj/custom.dmi' + item_state = "labred-w" /*PLACEHOLDER*/ @@ -86,17 +93,17 @@ /obj/item/clothing/neck/cloak/carrot name = "carrot cloak" desc = "A cloak in the shape and color of a carrot!" - icon = 'icons/obj/clothing/cloaks.dmi' - icon_override = 'icons/mob/citadel/suit.dmi' - icon_state = "carrotcloak" - item_state = "carrotcloak" + icon = 'icons/obj/custom.dmi' + icon_override = 'icons/obj/custom.dmi' + icon_state = "carrotcloak-i" + item_state = "carrotcloak-w" w_class = WEIGHT_CLASS_SMALL body_parts_covered = CHEST|GROIN|LEGS|ARMS /obj/item/toy/plush/tree name = "christmass tree plushie" desc = "A festive plush that squeeks when you squeeze it!" - icon = 'icons/obj/plushes.dmi' + icon = 'icons/obj/custom.dmi' icon_state = "pine_c" item_state = "pine_c" w_class = WEIGHT_CLASS_SMALL @@ -107,10 +114,10 @@ /obj/item/clothing/neck/cloak/festive name = "Celebratory Cloak of Morozko" desc = " It probably will protect from snow, charcoal or elves." - icon = 'icons/obj/clothing/cloaks.dmi' - icon_override = 'icons/mob/citadel/suit.dmi' - icon_state = "festivecloak" - item_state = "festiveloak" + icon = 'icons/obj/custom.dmi' + icon_state = "festive-i" + item_state = "festive-w" + icon_override = 'icons/obj/custom.dmi' w_class = WEIGHT_CLASS_SMALL body_parts_covered = CHEST|GROIN|LEGS|ARMS @@ -119,9 +126,10 @@ /obj/item/clothing/mask/luchador/zigfie name = "Alboroto Rosa mask" - icon = 'icons/mob/mask.dmi' - icon_state = "lucharzigfie" - item_state = "lucharzigfie" + icon = 'icons/obj/custom.dmi' + icon_state = "lucharzigfie-i" + icon_override = 'icons/obj/custom.dmi' + item_state = "lucharzigfie-w" /*PLACEHOLDER*/ @@ -159,8 +167,10 @@ /obj/item/clothing/suit/trenchcoat/green name = "Reece's Great Coat" desc = "You would swear this was in your nightmares after eating too many veggies." - icon_state = "hos-g" - item_state = "hos-g" + icon = 'icons/obj/custom.dmi' + icon_state = "hos-g-i" + icon_override = 'icons/obj/custom.dmi' + item_state = "hos-g-w" body_parts_covered = CHEST|GROIN|ARMS|LEGS @@ -170,14 +180,15 @@ desc = "Every good russian spaceman knows it's a good idea to bring along a couple of pints of whiskey wherever they go." icon = 'icons/obj/custom.dmi' icon_state = "russianflask" - item_state = "russianflask" volume = 60 /obj/item/clothing/mask/gas/stalker name = "S.T.A.L.K.E.R. mask" desc = "Smells like reactor four." - item_state = "stalker" - icon_state = "stalker" + icon = 'icons/obj/custom.dmi' + item_state = "stalker-w" + icon_override = 'icons/obj/custom.dmi' + icon_state = "stalker-i" /*Sylas*/ @@ -185,8 +196,9 @@ name = "collar" desc = "It's a collar..." icon = 'icons/obj/custom.dmi' - icon_state = "petcollar-stripe" - item_color = "petcollar-stripe" + icon_state = "petcollar-stripe-i" + icon_override = 'icons/obj/custom.dmi' + item_state = "petcollar-stripe-w" tagname = null @@ -194,17 +206,21 @@ /obj/item/clothing/under/singery/custom name = "bluish performer's outfit" desc = "Just looking at this makes you want to sing." - icon_state = "ssing" - item_state = "ssing" - item_color = "ssing" + icon = 'icons/obj/custom.dmi' + icon_state = "singer-i" + icon_override = 'icons/obj/custom.dmi' + item_state = "singer-w" + item_color = "singer-i" fitted = NO_FEMALE_UNIFORM alternate_worn_layer = ABOVE_SHOES_LAYER can_adjust = 0 /obj/item/clothing/shoes/sneakers/pink - icon_state = "pink" - item_state = "pink" + icon = 'icons/obj/custom.dmi' + icon_state = "pink-i" + icon_override = 'icons/obj/custom.dmi' + item_state = "pink-w" /*Fractious*/ @@ -212,10 +228,8 @@ /obj/item/clothing/suit/vermillion name = "vermillion clothing" desc = "Some clothing." - icon_state = "vermillion-w" - item_state = "vermillion-i" + icon_state = "vermillion-i" + item_state = "vermillion-w" body_parts_covered = CHEST|GROIN|LEGS|ARMS|HANDS icon = 'icons/obj/custom.dmi' - - - + icon_override = 'icons/obj/custom.dmi' diff --git a/code/controllers/configuration/configuration.dm b/code/controllers/configuration/configuration.dm index 70be8cfa0c..e9c0aa71b8 100644 --- a/code/controllers/configuration/configuration.dm +++ b/code/controllers/configuration/configuration.dm @@ -168,7 +168,10 @@ GLOBAL_PROTECT(config_dir) mode_names[M.config_tag] = M.name probabilities[M.config_tag] = M.probability mode_reports[M.config_tag] = M.generate_report() - mode_false_report_weight[M.config_tag] = M.false_report_weight + if(M.probability) + mode_false_report_weight[M.config_tag] = M.false_report_weight + else + mode_false_report_weight[M.config_tag] = 1 if(M.votable) votable_modes += M.config_tag qdel(M) diff --git a/code/controllers/configuration/entries/config.dm b/code/controllers/configuration/entries/config.dm index d7dc0ff84d..37081c15dd 100644 --- a/code/controllers/configuration/entries/config.dm +++ b/code/controllers/configuration/entries/config.dm @@ -208,9 +208,9 @@ CONFIG_DEF(string/panic_server_name) /datum/config_entry/string/panic_server_name/ValidateAndSet(str_val) return str_val != "\[Put the name here\]" && ..() -CONFIG_DEF(string/panic_address) //Reconnect a player this linked server if this server isn't accepting new players +CONFIG_DEF(string/panic_server_address) //Reconnect a player this linked server if this server isn't accepting new players -/datum/config_entry/string/panic_address/ValidateAndSet(str_val) +/datum/config_entry/string/panic_server_address/ValidateAndSet(str_val) return str_val != "byond://address:port" && ..() CONFIG_DEF(string/invoke_youtubedl) @@ -377,7 +377,7 @@ CONFIG_TWEAK(number/mc_tick_rate/ValidateAndSet(str_val)) CONFIG_DEF(flag/resume_after_initializations) -CONFIG_TWEAK(flag/ValidateAndSet(str_val)) +CONFIG_TWEAK(flag/resume_after_initializations/ValidateAndSet(str_val)) . = ..() if(. && Master.current_runlevel) world.sleep_offline = !value @@ -385,3 +385,6 @@ CONFIG_TWEAK(flag/ValidateAndSet(str_val)) CONFIG_DEF(number/rounds_until_hard_restart) value = -1 min_val = 0 + +CONFIG_DEF(string/default_view) + value = "15x15" diff --git a/code/controllers/configuration/entries/game_options.dm b/code/controllers/configuration/entries/game_options.dm index 1b58d86db2..b04d7845f5 100644 --- a/code/controllers/configuration/entries/game_options.dm +++ b/code/controllers/configuration/entries/game_options.dm @@ -263,4 +263,4 @@ CONFIG_DEF(number/emergency_shuttle_autocall_threshold) max_val = 1 integer = FALSE -CONFIG_DEF(flag/ic_printing) \ No newline at end of file +CONFIG_DEF(flag/ic_printing) diff --git a/code/controllers/subsystem/ticker.dm b/code/controllers/subsystem/ticker.dm index dfdff1890a..881bb7fcb7 100755 --- a/code/controllers/subsystem/ticker.dm +++ b/code/controllers/subsystem/ticker.dm @@ -33,8 +33,8 @@ SUBSYSTEM_DEF(ticker) SCRIPTURE_APPLICATION = FALSE) //list of clockcult scripture states for announcements var/delay_end = 0 //if set true, the round will not restart on it's own - var/admin_delay_notice = "" //a message to display to anyone who tries to restart the world after a delay + var/ready_for_reboot = FALSE //all roundend preparation done with, all that's left is reboot var/triai = 0 //Global holder for Triumvirate var/tipped = 0 //Did we broadcast the tip of the day yet? @@ -584,10 +584,17 @@ SUBSYSTEM_DEF(ticker) SSblackbox.Seal() sleep(50) - if(mode.station_was_nuked) - Reboot("Station destroyed by Nuclear Device.", "nuke") + ready_for_reboot = TRUE + standard_reboot() + +/datum/controller/subsystem/ticker/proc/standard_reboot() + if(ready_for_reboot) + if(mode.station_was_nuked) + Reboot("Station destroyed by Nuclear Device.", "nuke") + else + Reboot("Round ended.", "proper completion") else - Reboot("Round ended.", "proper completion") + CRASH("Attempted standard reboot without ticker roundend completion") /datum/controller/subsystem/ticker/proc/send_tip_of_the_round() var/m diff --git a/code/controllers/subsystem/weather.dm b/code/controllers/subsystem/weather.dm index 2909d1c70a..dafd9d6fd0 100644 --- a/code/controllers/subsystem/weather.dm +++ b/code/controllers/subsystem/weather.dm @@ -41,5 +41,14 @@ SUBSYSTEM_DEF(weather) if(W.name == weather_name && W.target_z == Z) W.telegraph() +/datum/controller/subsystem/weather/proc/is_weather_affecting_area(area/A, weather_datum_type) + for(var/V in processing) + var/datum/weather/W = V + if(!istype(W, weather_datum_type)) + continue + if(A in W.impacted_areas) + return TRUE + return FALSE + /datum/controller/subsystem/weather/proc/make_z_eligible(zlevel) eligible_zlevels |= zlevel diff --git a/code/datums/antagonists/wizard.dm b/code/datums/antagonists/wizard.dm index a8cce02fa1..e1e6dc09c8 100644 --- a/code/datums/antagonists/wizard.dm +++ b/code/datums/antagonists/wizard.dm @@ -71,7 +71,7 @@ var/datum/objective/escape/escape_objective = new escape_objective.owner = owner objectives += escape_objective - + if(31 to 60) var/datum/objective/steal/steal_objective = new steal_objective.owner = owner @@ -103,8 +103,8 @@ if (!(locate(/datum/objective/hijack) in owner.objectives)) var/datum/objective/hijack/hijack_objective = new hijack_objective.owner = owner - objectives += hijack_objective - + objectives += hijack_objective + for(var/datum/objective/O in objectives) owner.objectives += O @@ -128,7 +128,7 @@ if(H.age < wiz_age) H.age = wiz_age H.equipOutfit(outfit_type) - + /datum/antagonist/wizard/greet() to_chat(owner, "You are the Space Wizard!") to_chat(owner, "The Space Wizards Federation has given you the following tasks:") @@ -208,7 +208,7 @@ owner.AddSpell(new /obj/effect/proc_holder/spell/aoe_turf/knock(null)) owner.AddSpell(new /obj/effect/proc_holder/spell/targeted/mind_transfer(null)) to_chat(owner, "Your service has not gone unrewarded, however. Studying under [master.current.real_name], you have learned stealthy, robeless spells. You are able to cast knock and mindswap.") - + /datum/antagonist/wizard/apprentice/create_objectives() var/datum/objective/protect/new_objective = new /datum/objective/protect new_objective.owner = owner @@ -221,6 +221,7 @@ /datum/antagonist/wizard/apprentice/imposter name = "Wizard Imposter" allow_rename = FALSE + move_to_lair = FALSE /datum/antagonist/wizard/apprentice/imposter/greet() to_chat(owner, "You are an imposter! Trick and confuse the crew to misdirect malice from your handsome original!") @@ -266,7 +267,7 @@ /datum/antagonist/wizard/academy/equip_wizard() . = ..() - + owner.AddSpell(new /obj/effect/proc_holder/spell/targeted/ethereal_jaunt) owner.AddSpell(new /obj/effect/proc_holder/spell/targeted/projectile/magic_missile) owner.AddSpell(new /obj/effect/proc_holder/spell/aimed/fireball) @@ -274,7 +275,7 @@ var/mob/living/M = owner.current if(!istype(M)) return - + var/obj/item/implant/exile/Implant = new/obj/item/implant/exile(M) Implant.implant(M) diff --git a/code/datums/brain_damage/severe.dm b/code/datums/brain_damage/severe.dm index 505112bdcf..08cee65085 100644 --- a/code/datums/brain_damage/severe.dm +++ b/code/datums/brain_damage/severe.dm @@ -28,7 +28,7 @@ /datum/brain_trauma/severe/blindness name = "Cerebral Blindness" desc = "Patient's brain is no longer connected to its eyes." - scan_desc = "extensive damage to the brain's frontal lobe" + scan_desc = "extensive damage to the brain's occipital lobe" gain_text = "You can't see!" lose_text = "Your vision returns." diff --git a/code/datums/brain_damage/special.dm b/code/datums/brain_damage/special.dm index fd7aa1445d..ddb8f8e6e6 100644 --- a/code/datums/brain_damage/special.dm +++ b/code/datums/brain_damage/special.dm @@ -10,13 +10,21 @@ gain_text = "You feel a higher power inside your mind..." lose_text = "The divine presence leaves your head, no longer interested." var/next_speech = 0 + var/inspiration = FALSE + +/datum/brain_trauma/special/godwoken/on_life() + ..() + if(!inspiration && world.time > next_speech && prob(4)) + to_chat(owner, "[pick("You feel inspired!","You feel power course through you...","You feel something within you itching to speak...")]") + inspiration = TRUE /datum/brain_trauma/special/godwoken/on_say(message) - if(world.time > next_speech && prob(10)) + if(world.time > next_speech && inspiration) playsound(get_turf(owner), 'sound/magic/clockwork/invoke_general.ogg', 300, 1, 5) var/cooldown = voice_of_god(message, owner, list("colossus","yell"), 2) cooldown *= 0.33 next_speech = world.time + cooldown + inspiration = FALSE return "" else return message diff --git a/code/datums/components/caltrop.dm b/code/datums/components/caltrop.dm new file mode 100644 index 0000000000..5b8adf0175 --- /dev/null +++ b/code/datums/components/caltrop.dm @@ -0,0 +1,60 @@ +/datum/component/caltrop + var/min_damage + var/max_damage + var/probability + var/flags + + var/cooldown = 0 + +/datum/component/caltrop/Initialize(_min_damage = 0, _max_damage = 0, _probability = 100, _flags = NONE) + min_damage = _min_damage + max_damage = max(_min_damage, _max_damage) + probability = _probability + flags = _flags + + RegisterSignal(list(COMSIG_MOVABLE_CROSSED), .proc/Crossed) + +/datum/component/caltrop/proc/Crossed(atom/movable/AM) + var/atom/A = parent + if(!A.has_gravity()) + return + + if(!prob(probability)) + return + + if(ishuman(AM)) + var/mob/living/carbon/human/H = AM + if(PIERCEIMMUNE in H.dna.species.species_traits) + return + + if((flags & CALTROP_IGNORE_WALKERS) && H.m_intent == MOVE_INTENT_WALK) + return + + var/picked_def_zone = pick("l_leg", "r_leg") + var/obj/item/bodypart/O = H.get_bodypart(picked_def_zone) + if(!istype(O)) + return + if(O.status == BODYPART_ROBOTIC) + return + + var/feetCover = (H.wear_suit && (H.wear_suit.body_parts_covered & FEET)) || (H.w_uniform && (H.w_uniform.body_parts_covered & FEET)) + + if(!(flags & CALTROP_BYPASS_SHOES) && (H.shoes || feetCover)) + return + + if((H.movement_type & FLYING) || H.buckled) + return + + var/damage = rand(min_damage, max_damage) + H.apply_damage(damage, BRUTE, picked_def_zone) + + if(cooldown < world.time - 10) //cooldown to avoid message spam. + if(!H.incapacitated(ignore_restraints = TRUE)) + H.visible_message("[H] steps on [A].", \ + "You step on [A]!") + else + H.visible_message("[H] slides on [A]!", \ + "You slide on [A]!") + + cooldown = world.time + H.Knockdown(60) diff --git a/code/datums/components/material_container.dm b/code/datums/components/material_container.dm index 5e989005be..b33cee4059 100644 --- a/code/datums/components/material_container.dm +++ b/code/datums/components/material_container.dm @@ -58,7 +58,7 @@ return . = COMPONENT_NO_AFTERATTACK var/datum/callback/pc = precondition - if(pc && !pc.Invoke()) + if(pc && !pc.Invoke(user)) return var/material_amount = get_item_material_amount(I) if(!material_amount) diff --git a/code/datums/components/riding.dm b/code/datums/components/riding.dm index 4b18f91014..e21db3e094 100644 --- a/code/datums/components/riding.dm +++ b/code/datums/components/riding.dm @@ -1,326 +1,326 @@ -/datum/component/riding - var/next_vehicle_move = 0 //used for move delays - var/vehicle_move_delay = 2 //tick delay between movements, lower = faster, higher = slower - var/keytype - - var/slowed = FALSE - var/slowvalue = 1 - - var/list/riding_offsets = list() //position_of_user = list(dir = list(px, py)), or RIDING_OFFSET_ALL for a generic one. - var/list/directional_vehicle_layers = list() //["[DIRECTION]"] = layer. Don't set it for a direction for default, set a direction to null for no change. - var/list/directional_vehicle_offsets = list() //same as above but instead of layer you have a list(px, py) - var/list/allowed_turf_typecache - var/list/forbid_turf_typecache //allow typecache for only certain turfs, forbid to allow all but those. allow only certain turfs will take precedence. - var/allow_one_away_from_valid_turf = TRUE //allow moving one tile away from a valid turf but not more. - var/override_allow_spacemove = FALSE - var/drive_verb = "drive" - var/ride_check_rider_incapacitated = FALSE - var/ride_check_rider_restrained = FALSE - var/ride_check_ridden_incapacitated = FALSE - -/datum/component/riding/Initialize() - if(!ismovableatom(parent)) - . = COMPONENT_INCOMPATIBLE - CRASH("RIDING COMPONENT ASSIGNED TO NON ATOM MOVABLE!") - RegisterSignal(COMSIG_MOVABLE_BUCKLE, .proc/vehicle_mob_buckle) - RegisterSignal(COMSIG_MOVABLE_UNBUCKLE, .proc/vehicle_mob_unbuckle) - RegisterSignal(COMSIG_MOVABLE_MOVED, .proc/vehicle_moved) - -/datum/component/riding/proc/vehicle_mob_unbuckle(mob/living/M, force = FALSE) - restore_position(M) - unequip_buckle_inhands(M) - -/datum/component/riding/proc/vehicle_mob_buckle(mob/living/M, force = FALSE) - handle_vehicle_offsets() - -/datum/component/riding/proc/handle_vehicle_layer() - var/atom/movable/AM = parent - var/static/list/defaults = list(TEXT_NORTH = OBJ_LAYER, TEXT_SOUTH = ABOVE_MOB_LAYER, TEXT_EAST = ABOVE_MOB_LAYER, TEXT_WEST = ABOVE_MOB_LAYER) - . = defaults["[AM.dir]"] - if(directional_vehicle_layers["[AM.dir]"]) - . = directional_vehicle_layers["[AM.dir]"] - if(isnull(.)) //you can set it to null to not change it. - . = AM.layer - AM.layer = . - -/datum/component/riding/proc/set_vehicle_dir_layer(dir, layer) - directional_vehicle_layers["[dir]"] = layer - -/datum/component/riding/proc/vehicle_moved() - var/atom/movable/AM = parent - for(var/i in AM.buckled_mobs) - ride_check(i) - handle_vehicle_offsets() - handle_vehicle_layer() - -/datum/component/riding/proc/ride_check(mob/living/M) - var/atom/movable/AM = parent - var/mob/AMM = AM - if((ride_check_rider_restrained && M.restrained(TRUE)) || (ride_check_rider_incapacitated && M.incapacitated(FALSE, TRUE)) || (ride_check_ridden_incapacitated && istype(AMM) && AMM.incapacitated(FALSE, TRUE))) - AM.visible_message("[M] falls off of [AM]!") - AM.unbuckle_mob(M) - return TRUE - -/datum/component/riding/proc/force_dismount(mob/living/M) - var/atom/movable/AM = parent - AM.unbuckle_mob(M) - -/datum/component/riding/proc/handle_vehicle_offsets() - var/atom/movable/AM = parent - var/AM_dir = "[AM.dir]" - var/passindex = 0 - if(AM.has_buckled_mobs()) - for(var/m in AM.buckled_mobs) - passindex++ - var/mob/living/buckled_mob = m - var/list/offsets = get_offsets(passindex) - var/rider_dir = get_rider_dir(passindex) - buckled_mob.setDir(rider_dir) - dir_loop: - for(var/offsetdir in offsets) - if(offsetdir == AM_dir) - var/list/diroffsets = offsets[offsetdir] - buckled_mob.pixel_x = diroffsets[1] - if(diroffsets.len >= 2) - buckled_mob.pixel_y = diroffsets[2] - if(diroffsets.len == 3) - buckled_mob.layer = diroffsets[3] - break dir_loop - var/list/static/default_vehicle_pixel_offsets = list(TEXT_NORTH = list(0, 0), TEXT_SOUTH = list(0, 0), TEXT_EAST = list(0, 0), TEXT_WEST = list(0, 0)) - var/px = default_vehicle_pixel_offsets[AM_dir] - var/py = default_vehicle_pixel_offsets[AM_dir] - if(directional_vehicle_offsets[AM_dir]) - if(isnull(directional_vehicle_offsets[AM_dir])) - px = AM.pixel_x - py = AM.pixel_y - else - px = directional_vehicle_offsets[AM_dir][1] - py = directional_vehicle_offsets[AM_dir][2] - AM.pixel_x = px - AM.pixel_y = py - -/datum/component/riding/proc/set_vehicle_dir_offsets(dir, x, y) - directional_vehicle_offsets["[dir]"] = list(x, y) - -//Override this to set your vehicle's various pixel offsets -/datum/component/riding/proc/get_offsets(pass_index) // list(dir = x, y, layer) - . = list(TEXT_NORTH = list(0, 0), TEXT_SOUTH = list(0, 0), TEXT_EAST = list(0, 0), TEXT_WEST = list(0, 0)) - if(riding_offsets["[pass_index]"]) - . = riding_offsets["[pass_index]"] - else if(riding_offsets["[RIDING_OFFSET_ALL]"]) - . = riding_offsets["[RIDING_OFFSET_ALL]"] - -/datum/component/riding/proc/set_riding_offsets(index, list/offsets) - if(!islist(offsets)) - return FALSE - riding_offsets["[index]"] = offsets - -//Override this to set the passengers/riders dir based on which passenger they are. -//ie: rider facing the vehicle's dir, but passenger 2 facing backwards, etc. -/datum/component/riding/proc/get_rider_dir(pass_index) - var/atom/movable/AM = parent - return AM.dir - -//KEYS -/datum/component/riding/proc/keycheck(mob/user) - return !keytype || user.is_holding_item_of_type(keytype) - -//BUCKLE HOOKS -/datum/component/riding/proc/restore_position(mob/living/buckled_mob) - if(buckled_mob) - buckled_mob.pixel_x = 0 - buckled_mob.pixel_y = 0 - if(buckled_mob.client) - buckled_mob.client.change_view(world.view) - -//MOVEMENT -/datum/component/riding/proc/turf_check(turf/next, turf/current) - if(allowed_turf_typecache && !allowed_turf_typecache[next.type]) - return (allow_one_away_from_valid_turf && allowed_turf_typecache[current.type]) - else if(forbid_turf_typecache && forbid_turf_typecache[next.type]) - return (allow_one_away_from_valid_turf && !forbid_turf_typecache[current.type]) - return TRUE - -/datum/component/riding/proc/handle_ride(mob/user, direction) - var/atom/movable/AM = parent - if(user.incapacitated()) - Unbuckle(user) - return - - if(world.time < next_vehicle_move) - return - next_vehicle_move = world.time + vehicle_move_delay - - if(keycheck(user)) - var/turf/next = get_step(AM, direction) - var/turf/current = get_turf(AM) - if(!istype(next) || !istype(current)) - return //not happening. - if(!turf_check(next, current)) - to_chat(user, "Your \the [AM] can not go onto [next]!") - return - if(!Process_Spacemove(direction) || !isturf(AM.loc)) - return - step(AM, direction) - - handle_vehicle_layer() - handle_vehicle_offsets() - else - to_chat(user, "You'll need the keys in one of your hands to [drive_verb] [AM].") - -/datum/component/riding/proc/Unbuckle(atom/movable/M) - addtimer(CALLBACK(parent, /atom/movable/.proc/unbuckle_mob, M), 0, TIMER_UNIQUE) - -/datum/component/riding/proc/Process_Spacemove(direction) - var/atom/movable/AM = parent - return override_allow_spacemove || AM.has_gravity() - -/datum/component/riding/proc/account_limbs(mob/living/M) - if(M.get_num_legs() < 2 && !slowed) - vehicle_move_delay = vehicle_move_delay + slowvalue - slowed = TRUE - else if(slowed) - vehicle_move_delay = vehicle_move_delay - slowvalue - slowed = FALSE - -///////Yes, I said humans. No, this won't end well...////////// -/datum/component/riding/human - -/datum/component/riding/human/Initialize() - . = ..() - RegisterSignal(COMSIG_HUMAN_MELEE_UNARMED_ATTACK, .proc/on_host_unarmed_melee) - -/datum/component/riding/human/proc/on_host_unarmed_melee(atom/target) - var/mob/living/carbon/human/AM = parent - if(AM.a_intent == INTENT_DISARM && (target in AM.buckled_mobs)) - force_dismount(target) - -/datum/component/riding/human/handle_vehicle_layer() - var/atom/movable/AM = parent - if(AM.buckled_mobs && AM.buckled_mobs.len) - if(AM.dir == SOUTH) - AM.layer = ABOVE_MOB_LAYER - else - AM.layer = OBJ_LAYER - else - AM.layer = MOB_LAYER - -/datum/component/riding/human/force_dismount(mob/living/user) - var/atom/movable/AM = parent - AM.unbuckle_mob(user) - user.Knockdown(60) - user.visible_message("[AM] pushes [user] off of them!") - -/datum/component/riding/cyborg - -/datum/component/riding/cyborg/ride_check(mob/user) - var/atom/movable/AM = parent - if(user.incapacitated()) - var/kick = TRUE - if(iscyborg(AM)) - var/mob/living/silicon/robot/R = AM - if(R.module && R.module.ride_allow_incapacitated) - kick = FALSE - if(kick) - to_chat(user, "You fall off of [AM]!") - Unbuckle(user) - return - if(iscarbon(user)) - var/mob/living/carbon/carbonuser = user - if(!carbonuser.get_num_arms()) - Unbuckle(user) - to_chat(user, "You can't grab onto [AM] with no hands!") - return - -/datum/component/riding/cyborg/handle_vehicle_layer() - var/atom/movable/AM = parent - if(AM.buckled_mobs && AM.buckled_mobs.len) - if(AM.dir == SOUTH) - AM.layer = ABOVE_MOB_LAYER - else - AM.layer = OBJ_LAYER - else - AM.layer = MOB_LAYER - -/datum/component/riding/cyborg/get_offsets(pass_index) // list(dir = x, y, layer) - return list(TEXT_NORTH = list(0, 4), TEXT_SOUTH = list(0, 4), TEXT_EAST = list(-6, 3), TEXT_WEST = list( 6, 3)) - -/datum/component/riding/cyborg/handle_vehicle_offsets() - var/atom/movable/AM = parent - if(AM.has_buckled_mobs()) - for(var/mob/living/M in AM.buckled_mobs) - M.setDir(AM.dir) - if(iscyborg(AM)) - var/mob/living/silicon/robot/R = AM - if(istype(R.module)) - M.pixel_x = R.module.ride_offset_x[dir2text(AM.dir)] - M.pixel_y = R.module.ride_offset_y[dir2text(AM.dir)] - else - ..() - -/datum/component/riding/cyborg/force_dismount(mob/living/M) - var/atom/movable/AM = parent - AM.unbuckle_mob(M) - var/turf/target = get_edge_target_turf(AM, AM.dir) - var/turf/targetm = get_step(get_turf(AM), AM.dir) - M.Move(targetm) - M.visible_message("[M] is thrown clear of [AM]!") - M.throw_at(target, 14, 5, AM) - M.Knockdown(60) - -/datum/component/riding/proc/equip_buckle_inhands(mob/living/carbon/human/user, amount_required = 1) - var/atom/movable/AM = parent - var/amount_equipped = 0 - for(var/amount_needed = amount_required, amount_needed > 0, amount_needed--) - var/obj/item/riding_offhand/inhand = new /obj/item/riding_offhand(user) - inhand.rider = user - inhand.parent = AM - if(user.put_in_hands(inhand, TRUE)) - amount_equipped++ - else - break - if(amount_equipped >= amount_required) - return TRUE - else - unequip_buckle_inhands(user) - return FALSE - -/datum/component/riding/proc/unequip_buckle_inhands(mob/living/carbon/user) - var/atom/movable/AM = parent - for(var/obj/item/riding_offhand/O in user.contents) - if(O.parent != AM) - CRASH("RIDING OFFHAND ON WRONG MOB") - continue - if(O.selfdeleting) - continue - else - qdel(O) - return TRUE - -/obj/item/riding_offhand - name = "offhand" - icon = 'icons/obj/items_and_weapons.dmi' - icon_state = "offhand" - w_class = WEIGHT_CLASS_HUGE - flags_1 = ABSTRACT_1 | DROPDEL_1 | NOBLUDGEON_1 - resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | UNACIDABLE | ACID_PROOF - var/mob/living/carbon/rider - var/mob/living/parent - var/selfdeleting = FALSE - -/obj/item/riding_offhand/dropped() - selfdeleting = TRUE - . = ..() - -/obj/item/riding_offhand/equipped() - if(loc != rider) - selfdeleting = TRUE - qdel(src) - . = ..() - -/obj/item/riding_offhand/Destroy() - var/atom/movable/AM = parent - if(selfdeleting) - if(rider in AM.buckled_mobs) - AM.unbuckle_mob(rider) - . = ..() +/datum/component/riding + var/next_vehicle_move = 0 //used for move delays + var/vehicle_move_delay = 2 //tick delay between movements, lower = faster, higher = slower + var/keytype + + var/slowed = FALSE + var/slowvalue = 1 + + var/list/riding_offsets = list() //position_of_user = list(dir = list(px, py)), or RIDING_OFFSET_ALL for a generic one. + var/list/directional_vehicle_layers = list() //["[DIRECTION]"] = layer. Don't set it for a direction for default, set a direction to null for no change. + var/list/directional_vehicle_offsets = list() //same as above but instead of layer you have a list(px, py) + var/list/allowed_turf_typecache + var/list/forbid_turf_typecache //allow typecache for only certain turfs, forbid to allow all but those. allow only certain turfs will take precedence. + var/allow_one_away_from_valid_turf = TRUE //allow moving one tile away from a valid turf but not more. + var/override_allow_spacemove = FALSE + var/drive_verb = "drive" + var/ride_check_rider_incapacitated = FALSE + var/ride_check_rider_restrained = FALSE + var/ride_check_ridden_incapacitated = FALSE + +/datum/component/riding/Initialize() + if(!ismovableatom(parent)) + . = COMPONENT_INCOMPATIBLE + CRASH("RIDING COMPONENT ASSIGNED TO NON ATOM MOVABLE!") + RegisterSignal(COMSIG_MOVABLE_BUCKLE, .proc/vehicle_mob_buckle) + RegisterSignal(COMSIG_MOVABLE_UNBUCKLE, .proc/vehicle_mob_unbuckle) + RegisterSignal(COMSIG_MOVABLE_MOVED, .proc/vehicle_moved) + +/datum/component/riding/proc/vehicle_mob_unbuckle(mob/living/M, force = FALSE) + restore_position(M) + unequip_buckle_inhands(M) + +/datum/component/riding/proc/vehicle_mob_buckle(mob/living/M, force = FALSE) + handle_vehicle_offsets() + +/datum/component/riding/proc/handle_vehicle_layer() + var/atom/movable/AM = parent + var/static/list/defaults = list(TEXT_NORTH = OBJ_LAYER, TEXT_SOUTH = ABOVE_MOB_LAYER, TEXT_EAST = ABOVE_MOB_LAYER, TEXT_WEST = ABOVE_MOB_LAYER) + . = defaults["[AM.dir]"] + if(directional_vehicle_layers["[AM.dir]"]) + . = directional_vehicle_layers["[AM.dir]"] + if(isnull(.)) //you can set it to null to not change it. + . = AM.layer + AM.layer = . + +/datum/component/riding/proc/set_vehicle_dir_layer(dir, layer) + directional_vehicle_layers["[dir]"] = layer + +/datum/component/riding/proc/vehicle_moved() + var/atom/movable/AM = parent + for(var/i in AM.buckled_mobs) + ride_check(i) + handle_vehicle_offsets() + handle_vehicle_layer() + +/datum/component/riding/proc/ride_check(mob/living/M) + var/atom/movable/AM = parent + var/mob/AMM = AM + if((ride_check_rider_restrained && M.restrained(TRUE)) || (ride_check_rider_incapacitated && M.incapacitated(FALSE, TRUE)) || (ride_check_ridden_incapacitated && istype(AMM) && AMM.incapacitated(FALSE, TRUE))) + AM.visible_message("[M] falls off of [AM]!") + AM.unbuckle_mob(M) + return TRUE + +/datum/component/riding/proc/force_dismount(mob/living/M) + var/atom/movable/AM = parent + AM.unbuckle_mob(M) + +/datum/component/riding/proc/handle_vehicle_offsets() + var/atom/movable/AM = parent + var/AM_dir = "[AM.dir]" + var/passindex = 0 + if(AM.has_buckled_mobs()) + for(var/m in AM.buckled_mobs) + passindex++ + var/mob/living/buckled_mob = m + var/list/offsets = get_offsets(passindex) + var/rider_dir = get_rider_dir(passindex) + buckled_mob.setDir(rider_dir) + dir_loop: + for(var/offsetdir in offsets) + if(offsetdir == AM_dir) + var/list/diroffsets = offsets[offsetdir] + buckled_mob.pixel_x = diroffsets[1] + if(diroffsets.len >= 2) + buckled_mob.pixel_y = diroffsets[2] + if(diroffsets.len == 3) + buckled_mob.layer = diroffsets[3] + break dir_loop + var/list/static/default_vehicle_pixel_offsets = list(TEXT_NORTH = list(0, 0), TEXT_SOUTH = list(0, 0), TEXT_EAST = list(0, 0), TEXT_WEST = list(0, 0)) + var/px = default_vehicle_pixel_offsets[AM_dir] + var/py = default_vehicle_pixel_offsets[AM_dir] + if(directional_vehicle_offsets[AM_dir]) + if(isnull(directional_vehicle_offsets[AM_dir])) + px = AM.pixel_x + py = AM.pixel_y + else + px = directional_vehicle_offsets[AM_dir][1] + py = directional_vehicle_offsets[AM_dir][2] + AM.pixel_x = px + AM.pixel_y = py + +/datum/component/riding/proc/set_vehicle_dir_offsets(dir, x, y) + directional_vehicle_offsets["[dir]"] = list(x, y) + +//Override this to set your vehicle's various pixel offsets +/datum/component/riding/proc/get_offsets(pass_index) // list(dir = x, y, layer) + . = list(TEXT_NORTH = list(0, 0), TEXT_SOUTH = list(0, 0), TEXT_EAST = list(0, 0), TEXT_WEST = list(0, 0)) + if(riding_offsets["[pass_index]"]) + . = riding_offsets["[pass_index]"] + else if(riding_offsets["[RIDING_OFFSET_ALL]"]) + . = riding_offsets["[RIDING_OFFSET_ALL]"] + +/datum/component/riding/proc/set_riding_offsets(index, list/offsets) + if(!islist(offsets)) + return FALSE + riding_offsets["[index]"] = offsets + +//Override this to set the passengers/riders dir based on which passenger they are. +//ie: rider facing the vehicle's dir, but passenger 2 facing backwards, etc. +/datum/component/riding/proc/get_rider_dir(pass_index) + var/atom/movable/AM = parent + return AM.dir + +//KEYS +/datum/component/riding/proc/keycheck(mob/user) + return !keytype || user.is_holding_item_of_type(keytype) + +//BUCKLE HOOKS +/datum/component/riding/proc/restore_position(mob/living/buckled_mob) + if(buckled_mob) + buckled_mob.pixel_x = 0 + buckled_mob.pixel_y = 0 + if(buckled_mob.client) + buckled_mob.client.change_view(CONFIG_GET(string/default_view)) + +//MOVEMENT +/datum/component/riding/proc/turf_check(turf/next, turf/current) + if(allowed_turf_typecache && !allowed_turf_typecache[next.type]) + return (allow_one_away_from_valid_turf && allowed_turf_typecache[current.type]) + else if(forbid_turf_typecache && forbid_turf_typecache[next.type]) + return (allow_one_away_from_valid_turf && !forbid_turf_typecache[current.type]) + return TRUE + +/datum/component/riding/proc/handle_ride(mob/user, direction) + var/atom/movable/AM = parent + if(user.incapacitated()) + Unbuckle(user) + return + + if(world.time < next_vehicle_move) + return + next_vehicle_move = world.time + vehicle_move_delay + + if(keycheck(user)) + var/turf/next = get_step(AM, direction) + var/turf/current = get_turf(AM) + if(!istype(next) || !istype(current)) + return //not happening. + if(!turf_check(next, current)) + to_chat(user, "Your \the [AM] can not go onto [next]!") + return + if(!Process_Spacemove(direction) || !isturf(AM.loc)) + return + step(AM, direction) + + handle_vehicle_layer() + handle_vehicle_offsets() + else + to_chat(user, "You'll need the keys in one of your hands to [drive_verb] [AM].") + +/datum/component/riding/proc/Unbuckle(atom/movable/M) + addtimer(CALLBACK(parent, /atom/movable/.proc/unbuckle_mob, M), 0, TIMER_UNIQUE) + +/datum/component/riding/proc/Process_Spacemove(direction) + var/atom/movable/AM = parent + return override_allow_spacemove || AM.has_gravity() + +/datum/component/riding/proc/account_limbs(mob/living/M) + if(M.get_num_legs() < 2 && !slowed) + vehicle_move_delay = vehicle_move_delay + slowvalue + slowed = TRUE + else if(slowed) + vehicle_move_delay = vehicle_move_delay - slowvalue + slowed = FALSE + +///////Yes, I said humans. No, this won't end well...////////// +/datum/component/riding/human + +/datum/component/riding/human/Initialize() + . = ..() + RegisterSignal(COMSIG_HUMAN_MELEE_UNARMED_ATTACK, .proc/on_host_unarmed_melee) + +/datum/component/riding/human/proc/on_host_unarmed_melee(atom/target) + var/mob/living/carbon/human/AM = parent + if(AM.a_intent == INTENT_DISARM && (target in AM.buckled_mobs)) + force_dismount(target) + +/datum/component/riding/human/handle_vehicle_layer() + var/atom/movable/AM = parent + if(AM.buckled_mobs && AM.buckled_mobs.len) + if(AM.dir == SOUTH) + AM.layer = ABOVE_MOB_LAYER + else + AM.layer = OBJ_LAYER + else + AM.layer = MOB_LAYER + +/datum/component/riding/human/force_dismount(mob/living/user) + var/atom/movable/AM = parent + AM.unbuckle_mob(user) + user.Knockdown(60) + user.visible_message("[AM] pushes [user] off of them!") + +/datum/component/riding/cyborg + +/datum/component/riding/cyborg/ride_check(mob/user) + var/atom/movable/AM = parent + if(user.incapacitated()) + var/kick = TRUE + if(iscyborg(AM)) + var/mob/living/silicon/robot/R = AM + if(R.module && R.module.ride_allow_incapacitated) + kick = FALSE + if(kick) + to_chat(user, "You fall off of [AM]!") + Unbuckle(user) + return + if(iscarbon(user)) + var/mob/living/carbon/carbonuser = user + if(!carbonuser.get_num_arms()) + Unbuckle(user) + to_chat(user, "You can't grab onto [AM] with no hands!") + return + +/datum/component/riding/cyborg/handle_vehicle_layer() + var/atom/movable/AM = parent + if(AM.buckled_mobs && AM.buckled_mobs.len) + if(AM.dir == SOUTH) + AM.layer = ABOVE_MOB_LAYER + else + AM.layer = OBJ_LAYER + else + AM.layer = MOB_LAYER + +/datum/component/riding/cyborg/get_offsets(pass_index) // list(dir = x, y, layer) + return list(TEXT_NORTH = list(0, 4), TEXT_SOUTH = list(0, 4), TEXT_EAST = list(-6, 3), TEXT_WEST = list( 6, 3)) + +/datum/component/riding/cyborg/handle_vehicle_offsets() + var/atom/movable/AM = parent + if(AM.has_buckled_mobs()) + for(var/mob/living/M in AM.buckled_mobs) + M.setDir(AM.dir) + if(iscyborg(AM)) + var/mob/living/silicon/robot/R = AM + if(istype(R.module)) + M.pixel_x = R.module.ride_offset_x[dir2text(AM.dir)] + M.pixel_y = R.module.ride_offset_y[dir2text(AM.dir)] + else + ..() + +/datum/component/riding/cyborg/force_dismount(mob/living/M) + var/atom/movable/AM = parent + AM.unbuckle_mob(M) + var/turf/target = get_edge_target_turf(AM, AM.dir) + var/turf/targetm = get_step(get_turf(AM), AM.dir) + M.Move(targetm) + M.visible_message("[M] is thrown clear of [AM]!") + M.throw_at(target, 14, 5, AM) + M.Knockdown(60) + +/datum/component/riding/proc/equip_buckle_inhands(mob/living/carbon/human/user, amount_required = 1) + var/atom/movable/AM = parent + var/amount_equipped = 0 + for(var/amount_needed = amount_required, amount_needed > 0, amount_needed--) + var/obj/item/riding_offhand/inhand = new /obj/item/riding_offhand(user) + inhand.rider = user + inhand.parent = AM + if(user.put_in_hands(inhand, TRUE)) + amount_equipped++ + else + break + if(amount_equipped >= amount_required) + return TRUE + else + unequip_buckle_inhands(user) + return FALSE + +/datum/component/riding/proc/unequip_buckle_inhands(mob/living/carbon/user) + var/atom/movable/AM = parent + for(var/obj/item/riding_offhand/O in user.contents) + if(O.parent != AM) + CRASH("RIDING OFFHAND ON WRONG MOB") + continue + if(O.selfdeleting) + continue + else + qdel(O) + return TRUE + +/obj/item/riding_offhand + name = "offhand" + icon = 'icons/obj/items_and_weapons.dmi' + icon_state = "offhand" + w_class = WEIGHT_CLASS_HUGE + flags_1 = ABSTRACT_1 | DROPDEL_1 | NOBLUDGEON_1 + resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | UNACIDABLE | ACID_PROOF + var/mob/living/carbon/rider + var/mob/living/parent + var/selfdeleting = FALSE + +/obj/item/riding_offhand/dropped() + selfdeleting = TRUE + . = ..() + +/obj/item/riding_offhand/equipped() + if(loc != rider) + selfdeleting = TRUE + qdel(src) + . = ..() + +/obj/item/riding_offhand/Destroy() + var/atom/movable/AM = parent + if(selfdeleting) + if(rider in AM.buckled_mobs) + AM.unbuckle_mob(rider) + . = ..() diff --git a/code/datums/components/uplink.dm b/code/datums/components/uplink.dm index 407965aeb9..175ac9469c 100644 --- a/code/datums/components/uplink.dm +++ b/code/datums/components/uplink.dm @@ -1,204 +1,204 @@ -GLOBAL_LIST_EMPTY(uplinks) - -/** - * Uplinks - * - * All /obj/item(s) have a hidden_uplink var. By default it's null. Give the item one with 'new(src') (it must be in it's contents). Then add 'uses.' - * Use whatever conditionals you want to check that the user has an uplink, and then call interact() on their uplink. - * You might also want the uplink menu to open if active. Check if the uplink is 'active' and then interact() with it. -**/ -/datum/component/uplink - dupe_mode = COMPONENT_DUPE_UNIQUE - var/name = "syndicate uplink" - var/active = FALSE - var/lockable = TRUE - var/locked = TRUE - var/telecrystals - var/selected_cat - var/owner = null - var/datum/game_mode/gamemode - var/spent_telecrystals = 0 - var/datum/uplink_purchase_log/purchase_log - var/list/uplink_items - var/hidden_crystals = 0 - -/datum/component/uplink/Initialize(_owner, _lockable = TRUE, _enabled = FALSE, datum/game_mode/_gamemode, starting_tc = 20) - if(!isitem(parent)) - return COMPONENT_INCOMPATIBLE - GLOB.uplinks += src - uplink_items = get_uplink_items(gamemode) - RegisterSignal(COMSIG_PARENT_ATTACKBY, .proc/OnAttackBy) - RegisterSignal(COMSIG_ITEM_ATTACK_SELF, .proc/interact) - owner = _owner - if(owner) - LAZYINITLIST(GLOB.uplink_purchase_logs_by_key) - if(GLOB.uplink_purchase_logs_by_key[owner]) - purchase_log = GLOB.uplink_purchase_logs_by_key[owner] - else - purchase_log = new(owner, src) - lockable = _lockable - active = _enabled - gamemode = _gamemode - telecrystals = starting_tc - if(!lockable) - active = TRUE - locked = FALSE - -/datum/component/uplink/InheritComponent(datum/component/uplink/U) - lockable |= U.lockable - active |= U.active - if(!gamemode) - gamemode = U.gamemode - telecrystals += U.telecrystals - if(purchase_log && U.purchase_log) - purchase_log.MergeWithAndDel(U.purchase_log) - -/datum/component/uplink/Destroy() - GLOB.uplinks -= src - gamemode = null - return ..() - -/datum/component/uplink/proc/LoadTC(mob/user, obj/item/stack/telecrystal/TC, silent = FALSE) - if(!silent) - to_chat(user, "You slot [TC] into [parent] and charge its internal uplink.") - var/amt = TC.amount - telecrystals += amt - TC.use(amt) - -/datum/component/uplink/proc/set_gamemode(_gamemode) - gamemode = _gamemode - uplink_items = get_uplink_items(gamemode) - -/datum/component/uplink/proc/OnAttackBy(obj/item/I, mob/user) - if(!active) - return //no hitting everyone/everything just to try to slot tcs in! - if(istype(I, /obj/item/stack/telecrystal)) - LoadTC(user, I) - for(var/item in subtypesof(/datum/uplink_item)) - var/datum/uplink_item/UI = item - var/path = null - if(initial(UI.refund_path)) - path = initial(UI.refund_path) - else - path = initial(UI.item) - var/cost = 0 - if(initial(UI.refund_amount)) - cost = initial(UI.refund_amount) - else - cost = initial(UI.cost) - var/refundable = initial(UI.refundable) - if(I.type == path && refundable && I.check_uplink_validity()) - telecrystals += cost - spent_telecrystals -= cost - to_chat(user, "[I] refunded.") - qdel(I) - return - -/datum/component/uplink/proc/interact(mob/user) - if(locked) - return - active = TRUE - if(user) - ui_interact(user) - -/datum/component/uplink/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, \ - datum/tgui/master_ui = null, datum/ui_state/state = GLOB.inventory_state) - active = TRUE - ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open) - if(!ui) - ui = new(user, src, ui_key, "uplink", name, 450, 750, master_ui, state) - ui.set_autoupdate(FALSE) // This UI is only ever opened by one person, and never is updated outside of user input. - ui.set_style("syndicate") - ui.open() - -/datum/component/uplink/ui_data(mob/user) - if(!user.mind) - return - var/list/data = list() - data["telecrystals"] = telecrystals - data["lockable"] = lockable - - data["categories"] = list() - for(var/category in uplink_items) - var/list/cat = list( - "name" = category, - "items" = (category == selected_cat ? list() : null)) - if(category == selected_cat) - for(var/item in uplink_items[category]) - var/datum/uplink_item/I = uplink_items[category][item] - if(I.limited_stock == 0) - continue - if(I.restricted_roles.len) - var/is_inaccessible = 1 - for(var/R in I.restricted_roles) - if(R == user.mind.assigned_role) - is_inaccessible = 0 - if(is_inaccessible) - continue - cat["items"] += list(list( - "name" = I.name, - "cost" = I.cost, - "desc" = I.desc, - )) - data["categories"] += list(cat) - return data - -/datum/component/uplink/ui_act(action, params) - if(!active) - return - - switch(action) - if("buy") - var/item = params["item"] - - var/list/buyable_items = list() - for(var/category in uplink_items) - buyable_items += uplink_items[category] - - if(item in buyable_items) - var/datum/uplink_item/I = buyable_items[item] - MakePurchase(usr, I) - . = TRUE - if("lock") - active = FALSE - locked = TRUE - telecrystals += hidden_crystals - hidden_crystals = 0 - SStgui.close_uis(src) - if("select") - selected_cat = params["category"] - return TRUE - -/datum/component/uplink/proc/MakePurchase(mob/user, datum/uplink_item/U) - if(!istype(U)) - return - if (!user || user.incapacitated()) - return - - if(telecrystals < U.cost || U.limited_stock == 0) - return - telecrystals -= U.cost - - var/atom/A = U.spawn_item(get_turf(user), src, user) - if(U.purchase_log_vis && purchase_log) - var/obj/item/storage/box/B = A - var/list/atom/logging = list() - if(istype(B) && B.contents.len > 0) - logging |= list(B) - else - logging |= A - for(var/atom/_logging in logging) - purchase_log.LogPurchase(_logging, U.cost) - - if(U.limited_stock > 0) - U.limited_stock -= 1 - - SSblackbox.record_feedback("nested tally", "traitor_uplink_items_bought", 1, list("[initial(U.name)]", "[U.cost]")) - if(ishuman(user) && istype(A, /obj/item)) - var/mob/living/carbon/human/H = user - if(H.put_in_hands(A)) - to_chat(H, "[A] materializes into your hands!") - else - to_chat(H, "\The [A] materializes onto the floor.") - return TRUE - +GLOBAL_LIST_EMPTY(uplinks) + +/** + * Uplinks + * + * All /obj/item(s) have a hidden_uplink var. By default it's null. Give the item one with 'new(src') (it must be in it's contents). Then add 'uses.' + * Use whatever conditionals you want to check that the user has an uplink, and then call interact() on their uplink. + * You might also want the uplink menu to open if active. Check if the uplink is 'active' and then interact() with it. +**/ +/datum/component/uplink + dupe_mode = COMPONENT_DUPE_UNIQUE + var/name = "syndicate uplink" + var/active = FALSE + var/lockable = TRUE + var/locked = TRUE + var/telecrystals + var/selected_cat + var/owner = null + var/datum/game_mode/gamemode + var/spent_telecrystals = 0 + var/datum/uplink_purchase_log/purchase_log + var/list/uplink_items + var/hidden_crystals = 0 + +/datum/component/uplink/Initialize(_owner, _lockable = TRUE, _enabled = FALSE, datum/game_mode/_gamemode, starting_tc = 20) + if(!isitem(parent)) + return COMPONENT_INCOMPATIBLE + GLOB.uplinks += src + uplink_items = get_uplink_items(gamemode) + RegisterSignal(COMSIG_PARENT_ATTACKBY, .proc/OnAttackBy) + RegisterSignal(COMSIG_ITEM_ATTACK_SELF, .proc/interact) + owner = _owner + if(owner) + LAZYINITLIST(GLOB.uplink_purchase_logs_by_key) + if(GLOB.uplink_purchase_logs_by_key[owner]) + purchase_log = GLOB.uplink_purchase_logs_by_key[owner] + else + purchase_log = new(owner, src) + lockable = _lockable + active = _enabled + gamemode = _gamemode + telecrystals = starting_tc + if(!lockable) + active = TRUE + locked = FALSE + +/datum/component/uplink/InheritComponent(datum/component/uplink/U) + lockable |= U.lockable + active |= U.active + if(!gamemode) + gamemode = U.gamemode + telecrystals += U.telecrystals + if(purchase_log && U.purchase_log) + purchase_log.MergeWithAndDel(U.purchase_log) + +/datum/component/uplink/Destroy() + GLOB.uplinks -= src + gamemode = null + return ..() + +/datum/component/uplink/proc/LoadTC(mob/user, obj/item/stack/telecrystal/TC, silent = FALSE) + if(!silent) + to_chat(user, "You slot [TC] into [parent] and charge its internal uplink.") + var/amt = TC.amount + telecrystals += amt + TC.use(amt) + +/datum/component/uplink/proc/set_gamemode(_gamemode) + gamemode = _gamemode + uplink_items = get_uplink_items(gamemode) + +/datum/component/uplink/proc/OnAttackBy(obj/item/I, mob/user) + if(!active) + return //no hitting everyone/everything just to try to slot tcs in! + if(istype(I, /obj/item/stack/telecrystal)) + LoadTC(user, I) + for(var/item in subtypesof(/datum/uplink_item)) + var/datum/uplink_item/UI = item + var/path = null + if(initial(UI.refund_path)) + path = initial(UI.refund_path) + else + path = initial(UI.item) + var/cost = 0 + if(initial(UI.refund_amount)) + cost = initial(UI.refund_amount) + else + cost = initial(UI.cost) + var/refundable = initial(UI.refundable) + if(I.type == path && refundable && I.check_uplink_validity()) + telecrystals += cost + spent_telecrystals -= cost + to_chat(user, "[I] refunded.") + qdel(I) + return + +/datum/component/uplink/proc/interact(mob/user) + if(locked) + return + active = TRUE + if(user) + ui_interact(user) + +/datum/component/uplink/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, \ + datum/tgui/master_ui = null, datum/ui_state/state = GLOB.inventory_state) + active = TRUE + ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open) + if(!ui) + ui = new(user, src, ui_key, "uplink", name, 450, 750, master_ui, state) + ui.set_autoupdate(FALSE) // This UI is only ever opened by one person, and never is updated outside of user input. + ui.set_style("syndicate") + ui.open() + +/datum/component/uplink/ui_data(mob/user) + if(!user.mind) + return + var/list/data = list() + data["telecrystals"] = telecrystals + data["lockable"] = lockable + + data["categories"] = list() + for(var/category in uplink_items) + var/list/cat = list( + "name" = category, + "items" = (category == selected_cat ? list() : null)) + if(category == selected_cat) + for(var/item in uplink_items[category]) + var/datum/uplink_item/I = uplink_items[category][item] + if(I.limited_stock == 0) + continue + if(I.restricted_roles.len) + var/is_inaccessible = 1 + for(var/R in I.restricted_roles) + if(R == user.mind.assigned_role) + is_inaccessible = 0 + if(is_inaccessible) + continue + cat["items"] += list(list( + "name" = I.name, + "cost" = I.cost, + "desc" = I.desc, + )) + data["categories"] += list(cat) + return data + +/datum/component/uplink/ui_act(action, params) + if(!active) + return + + switch(action) + if("buy") + var/item = params["item"] + + var/list/buyable_items = list() + for(var/category in uplink_items) + buyable_items += uplink_items[category] + + if(item in buyable_items) + var/datum/uplink_item/I = buyable_items[item] + MakePurchase(usr, I) + . = TRUE + if("lock") + active = FALSE + locked = TRUE + telecrystals += hidden_crystals + hidden_crystals = 0 + SStgui.close_uis(src) + if("select") + selected_cat = params["category"] + return TRUE + +/datum/component/uplink/proc/MakePurchase(mob/user, datum/uplink_item/U) + if(!istype(U)) + return + if (!user || user.incapacitated()) + return + + if(telecrystals < U.cost || U.limited_stock == 0) + return + telecrystals -= U.cost + + var/atom/A = U.spawn_item(get_turf(user), src, user) + if(U.purchase_log_vis && purchase_log) + var/obj/item/storage/box/B = A + var/list/atom/logging = list() + if(istype(B) && B.contents.len > 0) + logging |= list(B) + else + logging |= A + for(var/atom/_logging in logging) + purchase_log.LogPurchase(_logging, U.cost) + + if(U.limited_stock > 0) + U.limited_stock -= 1 + + SSblackbox.record_feedback("nested tally", "traitor_uplink_items_bought", 1, list("[initial(U.name)]", "[U.cost]")) + if(ishuman(user) && istype(A, /obj/item)) + var/mob/living/carbon/human/H = user + if(H.put_in_hands(A)) + to_chat(H, "[A] materializes into your hands!") + else + to_chat(H, "\The [A] materializes onto the floor.") + return TRUE + diff --git a/code/datums/datumvars.dm b/code/datums/datumvars.dm index fc2aa1533c..1df8d60d39 100644 --- a/code/datums/datumvars.dm +++ b/code/datums/datumvars.dm @@ -104,15 +104,7 @@ else atomsnowflake += "[D]" - var/formatted_type = "[type]" - if(length(formatted_type) > 25) - var/middle_point = length(formatted_type) / 2 - var/splitpoint = findtext(formatted_type,"/",middle_point) - if(splitpoint) - formatted_type = "[copytext(formatted_type,1,splitpoint)]
[copytext(formatted_type,splitpoint)]" - else - formatted_type = "Type too long" //No suitable splitpoint (/) found. - + var/formatted_type = replacetext("[type]", "/", "/") var/marked if(holder && holder.marked_datum && holder.marked_datum == D) marked = "
Marked Object" diff --git a/code/game/area/Space_Station_13_areas.dm b/code/game/area/Space_Station_13_areas.dm index c3296175fb..c5e3d25375 100644 --- a/code/game/area/Space_Station_13_areas.dm +++ b/code/game/area/Space_Station_13_areas.dm @@ -171,6 +171,7 @@ NOTE: there are two lists of areas in the end of this file: centcom and station /area/maintenance/department/science/xenobiology name = "Xenobiology Maintenance" icon_state = "xenomaint" + xenobiology_compatible = TRUE //Maintenance - Generic diff --git a/code/game/area/areas.dm b/code/game/area/areas.dm index 17f75fc336..28209558d7 100644 --- a/code/game/area/areas.dm +++ b/code/game/area/areas.dm @@ -61,6 +61,7 @@ var/list/cameras var/list/firealarms var/firedoors_last_closed_on = 0 + var/xenobiology_compatible = FALSE //Can the Xenobio management console transverse this area by default? /*Adding a wizard area teleport list because motherfucking lag -- Urist*/ /*I am far too lazy to make it a proper list of areas so I'll just make it run the usual telepot routine at the start of the game*/ diff --git a/code/game/gamemodes/miniantags/borer/borer_event.dm b/code/game/gamemodes/miniantags/borer/borer_event.dm index 6875a97db5..567adddf53 100644 --- a/code/game/gamemodes/miniantags/borer/borer_event.dm +++ b/code/game/gamemodes/miniantags/borer/borer_event.dm @@ -1,8 +1,8 @@ /datum/round_event_control/borer name = "Borer" typepath = /datum/round_event/borer - weight = 10 //Default weight - max_occurrences = 1 + weight = 0 + max_occurrences = 0 min_players = 20 //10 is MINIMUM needed, but this is not a gamemode that does well in lowpop earliest_start = 24000 //40 min, double default timer diff --git a/code/game/gamemodes/miniantags/revenant/revenant.dm b/code/game/gamemodes/miniantags/revenant/revenant.dm index 04a5f4d2be..727203b150 100644 --- a/code/game/gamemodes/miniantags/revenant/revenant.dm +++ b/code/game/gamemodes/miniantags/revenant/revenant.dm @@ -411,6 +411,11 @@ revenant = null qdel(src) +/obj/item/ectoplasm/revenant/suicide_act(mob/user) + user.visible_message("[user] is inhaling [src]! It looks like [user.p_theyre()] trying to visit the shadow realm!") + scatter() + return (OXYLOSS) + /obj/item/ectoplasm/revenant/Destroy() if(!QDELETED(revenant)) qdel(revenant) diff --git a/code/game/gamemodes/nuclear/nuclearbomb.dm b/code/game/gamemodes/nuclear/nuclearbomb.dm index a36503e7c4..908ecd797f 100644 --- a/code/game/gamemodes/nuclear/nuclearbomb.dm +++ b/code/game/gamemodes/nuclear/nuclearbomb.dm @@ -551,16 +551,25 @@ This is here to make the tiles around the station mininuke change when it's arme /obj/item/disk/nuclear/suicide_act(mob/user) user.visible_message("[user] is going delta! It looks like [user.p_theyre()] trying to commit suicide!") - playsound(user.loc, 'sound/machines/alarm.ogg', 50, -1, 1) + playsound(src, 'sound/machines/alarm.ogg', 50, -1, 1) for(var/i in 1 to 100) addtimer(CALLBACK(user, /atom/proc/add_atom_colour, (i % 2)? "#00FF00" : "#FF0000", ADMIN_COLOUR_PRIORITY), i) - addtimer(CALLBACK(user, /atom/proc/remove_atom_colour, ADMIN_COLOUR_PRIORITY), 101) - addtimer(CALLBACK(user, /atom/proc/visible_message, "[user] was destroyed by the nuclear blast!"), 101) - addtimer(CALLBACK(user, /mob/living/proc/adjustOxyLoss, 200), 101) - addtimer(CALLBACK(user, /mob/proc/death, 0), 101) + addtimer(CALLBACK(src, .proc/manual_suicide, user), 101) return MANUAL_SUICIDE + +/obj/item/disk/proc/manual_suicide(mob/living/user) + user.remove_atom_colour(ADMIN_COLOUR_PRIORITY) + user.visible_message("[user] was destroyed by the nuclear blast!") + user.adjustOxyLoss(200) + user.death(0) /obj/item/disk/fakenucleardisk name = "cheap plastic imitation of the nuclear authentication disk" desc = "Broken dreams and a faint odor of cheese." icon_state = "nucleardisk" + +/obj/item/disk/fakenucleardisk/suicide_act(mob/user) + user.visible_message("[user] is pretending to go delta! It looks like [user.p_theyre()] trying to commit suicide!") + playsound(src, 'sound/machines/alarm.ogg', 30, -1, 1) + addtimer(CALLBACK(src, .proc/manual_suicide, user), 101) + return MANUAL_SUICIDE \ No newline at end of file diff --git a/code/game/gamemodes/wizard/spellbook.dm b/code/game/gamemodes/wizard/spellbook.dm index 1cf172d3a6..b086854ab6 100644 --- a/code/game/gamemodes/wizard/spellbook.dm +++ b/code/game/gamemodes/wizard/spellbook.dm @@ -897,6 +897,9 @@ to_chat(user,"[src] suddenly vanishes!") qdel(src) +/obj/item/spellbook/oneuse/random + icon_state = "random_book" + /obj/item/spellbook/oneuse/random/Initialize() ..() var/static/banned_spells = list(/obj/item/spellbook/oneuse/mimery_blockade, /obj/item/spellbook/oneuse/mimery_guns) diff --git a/code/game/machinery/vending.dm b/code/game/machinery/vending.dm index ec6a53f308..444e7583e9 100644 --- a/code/game/machinery/vending.dm +++ b/code/game/machinery/vending.dm @@ -138,7 +138,7 @@ if(isnull(amount)) amount = 0 - var/atom/temp = new typepath(null) + var/atom/temp = typepath var/datum/data/vending_product/R = new /datum/data/vending_product() R.product_name = initial(temp.name) R.product_path = typepath @@ -638,7 +638,8 @@ IF YOU MODIFY THE PRODUCTS LIST OF A MACHINE, MAKE SURE TO UPDATE ITS RESUPPLY C /obj/item/reagent_containers/food/drinks/bottle/cream = 4, /obj/item/reagent_containers/food/drinks/soda_cans/tonic = 8, /obj/item/reagent_containers/food/drinks/soda_cans/cola = 8, /obj/item/reagent_containers/food/drinks/soda_cans/sodawater = 15, /obj/item/reagent_containers/food/drinks/drinkingglass = 30, /obj/item/reagent_containers/food/drinks/ice = 10, - /obj/item/reagent_containers/food/drinks/drinkingglass/shotglass = 12, /obj/item/reagent_containers/food/drinks/flask = 3) + /obj/item/reagent_containers/food/drinks/drinkingglass/shotglass = 12, /obj/item/reagent_containers/food/drinks/flask = 3, + /obj/item/reagent_containers/food/drinks/beer = 6) contraband = list(/obj/item/reagent_containers/food/drinks/mug/tea = 12) product_slogans = "I hope nobody asks me for a bloody cup o' tea...;Alcohol is humanity's friend. Would you abandon a friend?;Quite delighted to serve you!;Is nobody thirsty on this station?" product_ads = "Drink up!;Booze is good for you!;Alcohol is humanity's best friend.;Quite delighted to serve you!;Care for a nice, cold beer?;Nothing cures you like booze!;Have a sip!;Have a drink!;Have a beer!;Beer is good for you!;Only the finest alcohol!;Best quality booze since 2053!;Award-winning wine!;Maximum alcohol!;Man loves beer.;A toast for progress!" @@ -678,6 +679,7 @@ IF YOU MODIFY THE PRODUCTS LIST OF A MACHINE, MAKE SURE TO UPDATE ITS RESUPPLY C /obj/machinery/vending/snack/random name = "\improper Random Snackies" + icon_state = "random_snack" desc = "Uh oh!" /obj/machinery/vending/snack/random/Initialize() @@ -730,6 +732,7 @@ IF YOU MODIFY THE PRODUCTS LIST OF A MACHINE, MAKE SURE TO UPDATE ITS RESUPPLY C /obj/machinery/vending/cola/random name = "\improper Random Drinkies" + icon_state = "random_cola" desc = "Uh oh!" /obj/machinery/vending/cola/random/Initialize() diff --git a/code/game/mecha/mech_fabricator.dm b/code/game/mecha/mech_fabricator.dm index 11d111befc..59aad6154f 100644 --- a/code/game/mecha/mech_fabricator.dm +++ b/code/game/mecha/mech_fabricator.dm @@ -34,9 +34,11 @@ "Misc" ) + var/datum/component/material_container/materials + /obj/machinery/mecha_part_fabricator/Initialize() - var/datum/component/material_container/materials = AddComponent(/datum/component/material_container, - list(MAT_METAL, MAT_GLASS, MAT_SILVER, MAT_GOLD, MAT_DIAMOND, MAT_PLASMA, MAT_URANIUM, MAT_BANANIUM, MAT_TITANIUM, MAT_BLUESPACE), + materials = AddComponent(/datum/component/material_container, + list(MAT_METAL, MAT_GLASS, MAT_SILVER, MAT_GOLD, MAT_DIAMOND, MAT_PLASMA, MAT_URANIUM, MAT_BANANIUM, MAT_TITANIUM, MAT_BLUESPACE), 0, FALSE, list(/obj/item/stack, /obj/item/ore/bluespace_crystal), CALLBACK(src, .proc/is_insertion_ready), CALLBACK(src, .proc/AfterMaterialInsert)) materials.precise_insertion = TRUE return ..() diff --git a/code/game/mecha/mecha.dm b/code/game/mecha/mecha.dm index 10d4638eb0..ba41609fca 100644 --- a/code/game/mecha/mecha.dm +++ b/code/game/mecha/mecha.dm @@ -970,7 +970,7 @@ setDir(dir_in) if(L && L.client) - L.client.change_view(world.view) + L.client.change_view(CONFIG_GET(string/default_view)) zoom_mode = 0 ///////////////////////// @@ -1042,4 +1042,4 @@ GLOBAL_VAR_INIT(year_integer, text2num(year)) // = 2013??? /obj/mecha/update_remote_sight(mob/living/user) if(occupant_sight_flags) if(user == occupant) - user.sight |= occupant_sight_flags \ No newline at end of file + user.sight |= occupant_sight_flags diff --git a/code/game/mecha/mecha_actions.dm b/code/game/mecha/mecha_actions.dm index ec6bd6e471..480c24b87f 100644 --- a/code/game/mecha/mecha_actions.dm +++ b/code/game/mecha/mecha_actions.dm @@ -244,7 +244,7 @@ owner.client.change_view(12) SEND_SOUND(owner, sound('sound/mecha/imag_enh.ogg',volume=50)) else - owner.client.change_view(world.view) //world.view - default mob view size + owner.client.change_view(CONFIG_GET(string/default_view)) //world.view - default mob view size UpdateButtonIcon() /datum/action/innate/mecha/mech_switch_damtype diff --git a/code/game/objects/items/bodybag.dm b/code/game/objects/items/bodybag.dm index a7ebf8251d..d9c2ac970e 100644 --- a/code/game/objects/items/bodybag.dm +++ b/code/game/objects/items/bodybag.dm @@ -20,6 +20,16 @@ R.add_fingerprint(user) qdel(src) +/obj/item/bodybag/suicide_act(mob/user) + if(isopenturf(user.loc)) + user.visible_message("[user] is crawling into [src]! It looks like [user.p_theyre()] trying to commit suicide!") + var/obj/structure/closet/body_bag/R = new unfoldedbag_path(user.loc) + R.add_fingerprint(user) + qdel(src) + user.forceMove(R) + playsound(src, 'sound/items/zip.ogg', 15, 1, -3) + return (OXYLOSS) + ..() // Bluespace bodybag diff --git a/code/game/objects/items/cosmetics.dm b/code/game/objects/items/cosmetics.dm index 8ec32f088e..a3ad685406 100644 --- a/code/game/objects/items/cosmetics.dm +++ b/code/game/objects/items/cosmetics.dm @@ -25,9 +25,11 @@ /obj/item/lipstick/random name = "lipstick" + icon_state = "random_lipstick" /obj/item/lipstick/random/New() ..() + icon_state = "lipstick" colour = pick("red","purple","lime","black","green","blue","white") name = "[colour] lipstick" diff --git a/code/game/objects/items/defib.dm b/code/game/objects/items/defib.dm index bdde32fb8a..f05d35c5a9 100644 --- a/code/game/objects/items/defib.dm +++ b/code/game/objects/items/defib.dm @@ -18,11 +18,11 @@ armor = list(melee = 0, bullet = 0, laser = 0, energy = 0, bomb = 0, bio = 0, rad = 0, fire = 50, acid = 50) var/on = FALSE //if the paddles are equipped (1) or on the defib (0) - var/safety = 1 //if you can zap people with the defibs on harm mode - var/powered = 0 //if there's a cell in the defib with enough power for a revive, blocks paddles from reviving otherwise + var/safety = TRUE //if you can zap people with the defibs on harm mode + var/powered = FALSE //if there's a cell in the defib with enough power for a revive, blocks paddles from reviving otherwise var/obj/item/twohanded/shockpaddles/paddles var/obj/item/stock_parts/cell/high/cell - var/combat = 0 //can we revive through space suits? + var/combat = FALSE //can we revive through space suits? var/grab_ghost = FALSE // Do we pull the ghost back into their body? /obj/item/defibrillator/get_cell() @@ -49,11 +49,11 @@ /obj/item/defibrillator/proc/update_power() if(cell) if(cell.charge < paddles.revivecost) - powered = 0 + powered = FALSE else powered = 1 else - powered = 0 + powered = FALSE /obj/item/defibrillator/proc/update_overlays() cut_overlays() @@ -98,8 +98,8 @@ ..() /obj/item/defibrillator/MouseDrop(obj/over_object) - if(ismob(src.loc)) - var/mob/M = src.loc + if(ismob(loc)) + var/mob/M = loc if(!M.incapacitated() && istype(over_object, /obj/screen/inventory/hand)) var/obj/screen/inventory/hand/H = over_object M.putItemFromInventoryInHandIfPossible(src, H.held_index) @@ -134,23 +134,23 @@ /obj/item/defibrillator/emag_act(mob/user) if(safety) - safety = 0 + safety = FALSE to_chat(user, "You silently disable [src]'s safety protocols with the cryptographic sequencer.") else - safety = 1 + safety = TRUE to_chat(user, "You silently enable [src]'s safety protocols with the cryptographic sequencer.") /obj/item/defibrillator/emp_act(severity) if(cell) deductcharge(1000 / severity) if(safety) - safety = 0 - src.visible_message("[src] beeps: Safety protocols disabled!") - playsound(get_turf(src), 'sound/machines/defib_saftyOff.ogg', 50, 0) + safety = FALSE + visible_message("[src] beeps: Safety protocols disabled!") + playsound(src, 'sound/machines/defib_saftyOff.ogg', 50, 0) else - safety = 1 - src.visible_message("[src] beeps: Safety protocols enabled!") - playsound(get_turf(src), 'sound/machines/defib_saftyOn.ogg', 50, 0) + safety = TRUE + visible_message("[src] beeps: Safety protocols enabled!") + playsound(src, 'sound/machines/defib_saftyOn.ogg', 50, 0) update_icon() ..() @@ -167,7 +167,7 @@ to_chat(user, "You need a free hand to hold the paddles!") update_icon() return - paddles.loc = user + paddles.forceMove(user) else //Remove from their hands and back onto the defib unit paddles.unwield() @@ -207,25 +207,25 @@ /obj/item/defibrillator/proc/deductcharge(chrgdeductamt) if(cell) if(cell.charge < (paddles.revivecost+chrgdeductamt)) - powered = 0 + powered = FALSE update_icon() if(cell.use(chrgdeductamt)) update_icon() - return 1 + return TRUE else update_icon() - return 0 + return FALSE /obj/item/defibrillator/proc/cooldowncheck(mob/user) spawn(50) if(cell) if(cell.charge >= paddles.revivecost) user.visible_message("[src] beeps: Unit ready.") - playsound(get_turf(src), 'sound/machines/defib_ready.ogg', 50, 0) + playsound(src, 'sound/machines/defib_ready.ogg', 50, 0) else user.visible_message("[src] beeps: Charge depleted.") - playsound(get_turf(src), 'sound/machines/defib_failed.ogg', 50, 0) - paddles.cooldown = 0 + playsound(src, 'sound/machines/defib_failed.ogg', 50, 0) + paddles.cooldown = FALSE paddles.update_icon() update_icon() @@ -240,7 +240,7 @@ /obj/item/defibrillator/compact/item_action_slot_check(slot, mob/user) if(slot == user.getBeltSlot()) - return 1 + return TRUE /obj/item/defibrillator/compact/loaded/Initialize() . = ..() @@ -251,8 +251,8 @@ /obj/item/defibrillator/compact/combat name = "combat defibrillator" desc = "A belt-equipped blood-red defibrillator that can be rapidly deployed. Does not have the restrictions or safeties of conventional defibrillators and can revive through space suits." - combat = 1 - safety = 0 + combat = TRUE + safety = FALSE /obj/item/defibrillator/compact/combat/loaded/Initialize() . = ..() @@ -280,24 +280,24 @@ w_class = WEIGHT_CLASS_BULKY var/revivecost = 1000 - var/cooldown = 0 + var/cooldown = FALSE var/busy = FALSE var/obj/item/defibrillator/defib - var/req_defib = 1 - var/combat = 0 //If it penetrates armor and gives additional functionality + var/req_defib = TRUE + var/combat = FALSE //If it penetrates armor and gives additional functionality var/grab_ghost = FALSE var/tlimit = DEFIB_TIME_LIMIT * 10 /obj/item/twohanded/shockpaddles/proc/recharge(var/time) if(req_defib || !time) return - cooldown = 1 + cooldown = TRUE update_icon() sleep(time) var/turf/T = get_turf(src) T.audible_message("[src] beeps: Unit is recharged.") - playsound(T, 'sound/machines/defib_ready.ogg', 50, 0) - cooldown = 0 + playsound(src, 'sound/machines/defib_ready.ogg', 50, 0) + cooldown = FALSE update_icon() /obj/item/twohanded/shockpaddles/New(mainunit) @@ -318,7 +318,7 @@ user.visible_message("[user] is putting the live paddles on [user.p_their()] chest! It looks like [user.p_theyre()] trying to commit suicide!") if(req_defib) defib.deductcharge(revivecost) - playsound(get_turf(src), 'sound/machines/defib_zap.ogg', 50, 1, -1) + playsound(src, 'sound/machines/defib_zap.ogg', 50, 1, -1) return (OXYLOSS) /obj/item/twohanded/shockpaddles/dropped(mob/user) @@ -336,12 +336,12 @@ /obj/item/twohanded/shockpaddles/proc/check_defib_exists(mainunit, mob/living/carbon/human/M, obj/O) if(!req_defib) - return 1 //If it doesn't need a defib, just say it exists + return TRUE //If it doesn't need a defib, just say it exists if (!mainunit || !istype(mainunit, /obj/item/defibrillator)) //To avoid weird issues from admin spawns qdel(O) - return 0 + return FALSE else - return 1 + return TRUE /obj/item/twohanded/shockpaddles/attack(mob/M, mob/user) @@ -349,7 +349,7 @@ return if(req_defib && !defib.powered) user.visible_message("[defib] beeps: Unit is unpowered.") - playsound(get_turf(src), 'sound/machines/defib_failed.ogg', 50, 0) + playsound(src, 'sound/machines/defib_failed.ogg', 50, 0) return if(!wielded) if(iscyborg(user)) @@ -397,6 +397,13 @@ var/obj/item/organ/brain/BR = H.getorgan(/obj/item/organ/brain) return (!H.suiciding && !(H.disabilities & NOCLONE) && !H.hellbound && ((world.time - H.timeofdeath) < tlimit) && (H.getBruteLoss() < 180) && (H.getFireLoss() < 180) && H.getorgan(/obj/item/organ/heart) && BR && !BR.damaged_brain) +/obj/item/twohanded/shockpaddles/proc/shock_touching(dmg, mob/H) + if(isliving(H.pulledby)) //CLEAR! + var/mob/living/M = H.pulledby + if(M.electrocute_act(30, src)) + M.visible_message("[M] is electrocuted by their contact with [H]!") + M.emote("scream") + /obj/item/twohanded/shockpaddles/proc/do_disarm(mob/living/M, mob/living/user) if(req_defib && defib.safety) return @@ -408,12 +415,12 @@ M.adjustStaminaLoss(50) M.Knockdown(100) M.updatehealth() //forces health update before next life tick - playsound(get_turf(src), 'sound/machines/defib_zap.ogg', 50, 1, -1) + playsound(src, 'sound/machines/defib_zap.ogg', 50, 1, -1) M.emote("gasp") add_logs(user, M, "stunned", src) if(req_defib) defib.deductcharge(revivecost) - cooldown = 1 + cooldown = TRUE busy = FALSE update_icon() if(req_defib) @@ -434,7 +441,7 @@ user.visible_message("[user] places [src] on [H]'s chest.", "You place [src] on [H]'s chest and begin to charge them.") var/turf/T = get_turf(defib) - playsound(get_turf(src), 'sound/machines/defib_charge.ogg', 50, 0) + playsound(src, 'sound/machines/defib_charge.ogg', 50, 0) if(req_defib) T.audible_message("\The [defib] lets out an urgent beep and lets out a steadily rising hum...") else @@ -446,14 +453,15 @@ return if(H && H.stat == DEAD) to_chat(user, "[H] is dead.") - playsound(get_turf(src), 'sound/machines/defib_failed.ogg', 50, 0) + playsound(src, 'sound/machines/defib_failed.ogg', 50, 0) busy = FALSE update_icon() return user.visible_message("[user] shocks [H] with \the [src]!", "You shock [H] with \the [src]!") - playsound(get_turf(src), 'sound/machines/defib_zap.ogg', 100, 1, -1) - playsound(loc, 'sound/weapons/egloves.ogg', 100, 1, -1) + playsound(src, 'sound/machines/defib_zap.ogg', 100, 1, -1) + playsound(src, 'sound/weapons/egloves.ogg', 100, 1, -1) H.emote("scream") + shock_touching(45, H) if(H.can_heartattack() && !H.undergoing_cardiac_arrest()) if(!H.stat) H.visible_message("[H] thrashes wildly, clutching at their chest!", @@ -465,7 +473,7 @@ H.Jitter(100) if(req_defib) defib.deductcharge(revivecost) - cooldown = 1 + cooldown = TRUE busy = FALSE update_icon() if(!req_defib) @@ -481,7 +489,7 @@ update_icon() if(do_after(user, 30, target = H)) //beginning to place the paddles on patient's chest to allow some time for people to move away to stop the process user.visible_message("[user] places [src] on [H]'s chest.", "You place [src] on [H]'s chest.") - playsound(get_turf(src), 'sound/machines/defib_charge.ogg', 50, 0) + playsound(src, 'sound/machines/defib_charge.ogg', 75, 0) var/tplus = world.time - H.timeofdeath // past this much time the patient is unrecoverable // (in deciseconds) @@ -493,20 +501,20 @@ if(do_after(user, 20, target = H)) //placed on chest and short delay to shock for dramatic effect, revive time is 5sec total for(var/obj/item/carried_item in H.contents) if(istype(carried_item, /obj/item/clothing/suit/space)) - if((!src.combat && !req_defib) || (req_defib && !defib.combat)) + if((!combat && !req_defib) || (req_defib && !defib.combat)) user.audible_message("[req_defib ? "[defib]" : "[src]"] buzzes: Patient's chest is obscured. Operation aborted.") - playsound(get_turf(src), 'sound/machines/defib_failed.ogg', 50, 0) + playsound(src, 'sound/machines/defib_failed.ogg', 50, 0) busy = FALSE update_icon() return if(H.stat == DEAD) H.visible_message("[H]'s body convulses a bit.") - playsound(get_turf(src), "bodyfall", 50, 1) - playsound(get_turf(src), 'sound/machines/defib_zap.ogg', 50, 1, -1) + playsound(src, "bodyfall", 50, 1) + playsound(src, 'sound/machines/defib_zap.ogg', 75, 1, -1) total_brute = H.getBruteLoss() total_burn = H.getFireLoss() - - var/failed = null + shock_touching(30, H) + var/failed if (H.suiciding || (H.disabilities & NOCLONE)) failed = "[req_defib ? "[defib]" : "[src]"] buzzes: Resuscitation failed - Recovery of patient impossible. Further attempts futile." @@ -527,7 +535,7 @@ if(failed) user.visible_message(failed) - playsound(get_turf(src), 'sound/machines/defib_failed.ogg', 50, 0) + playsound(src, 'sound/machines/defib_failed.ogg', 50, 0) else //If the body has been fixed so that they would not be in crit when defibbed, give them oxyloss to put them back into crit if (H.health > HALFWAYCRITDEATH) @@ -541,7 +549,7 @@ H.adjustBruteLoss((mobhealth - HALFWAYCRITDEATH) * (total_brute / overall_damage), 0) H.updatehealth() // Previous "adjust" procs don't update health, so we do it manually. user.visible_message("[req_defib ? "[defib]" : "[src]"] pings: Resuscitation successful.") - playsound(get_turf(src), 'sound/machines/defib_success.ogg', 50, 0) + playsound(src, 'sound/machines/defib_success.ogg', 50, 0) H.set_heartattack(FALSE) H.revive() H.emote("gasp") @@ -559,16 +567,16 @@ recharge(60) else if (!H.getorgan(/obj/item/organ/heart)) user.visible_message("[req_defib ? "[defib]" : "[src]"] buzzes: Patient's heart is missing. Operation aborted.") - playsound(get_turf(src), 'sound/machines/defib_failed.ogg', 50, 0) + playsound(src, 'sound/machines/defib_failed.ogg', 50, 0) else if(H.undergoing_cardiac_arrest()) H.set_heartattack(FALSE) user.visible_message("[req_defib ? "[defib]" : "[src]"] pings: Patient's heart is now beating again.") - playsound(get_turf(src), 'sound/machines/defib_zap.ogg', 50, 1, -1) + playsound(src, 'sound/machines/defib_zap.ogg', 50, 1, -1) else user.visible_message("[req_defib ? "[defib]" : "[src]"] buzzes: Patient is not in a valid state. Operation aborted.") - playsound(get_turf(src), 'sound/machines/defib_failed.ogg', 50, 0) + playsound(src, 'sound/machines/defib_failed.ogg', 50, 0) busy = FALSE update_icon() diff --git a/code/game/objects/items/devices/flashlight.dm b/code/game/objects/items/devices/flashlight.dm index 18e64c3639..ba1c90687d 100644 --- a/code/game/objects/items/devices/flashlight.dm +++ b/code/game/objects/items/devices/flashlight.dm @@ -488,16 +488,14 @@ /obj/item/device/flashlight/glowstick/random name = "random colored glowstick" + icon_state = "random_glowstick" + color = null /obj/item/device/flashlight/glowstick/random/Initialize() - var/list/glowtypes = typesof(/obj/item/device/flashlight/glowstick) - glowtypes -= /obj/item/device/flashlight/glowstick/random - - var/obj/item/device/flashlight/glowstick/glowtype = pick(glowtypes) - - name = initial(glowtype.name) - color = initial(glowtype.color) . = ..() + var/T = pick(typesof(/obj/item/device/flashlight/glowstick) - /obj/item/device/flashlight/glowstick/random) + new T(loc) + return INITIALIZE_HINT_QDEL /obj/item/device/flashlight/spotlight //invisible lighting source name = "disco light" diff --git a/code/game/objects/items/devices/taperecorder.dm b/code/game/objects/items/devices/taperecorder.dm index 912a083171..69b6e54841 100644 --- a/code/game/objects/items/devices/taperecorder.dm +++ b/code/game/objects/items/devices/taperecorder.dm @@ -289,6 +289,9 @@ fix() //Random colour tapes +/obj/item/device/tape/random + icon_state = "random_tape" + /obj/item/device/tape/random/New() icon_state = "tape_[pick("white", "blue", "red", "yellow", "purple")]" ..() diff --git a/code/game/objects/items/devices/uplink_devices.dm b/code/game/objects/items/devices/uplink_devices.dm index 3f3970fe51..2541b33e27 100644 --- a/code/game/objects/items/devices/uplink_devices.dm +++ b/code/game/objects/items/devices/uplink_devices.dm @@ -1,31 +1,31 @@ - -// A collection of pre-set uplinks, for admin spawns. -/obj/item/device/radio/uplink/Initialize(mapload, _owner, _tc_amount = 20) - . = ..() - icon_state = "radio" - lefthand_file = 'icons/mob/inhands/misc/devices_lefthand.dmi' - righthand_file = 'icons/mob/inhands/misc/devices_righthand.dmi' - LoadComponent(/datum/component/uplink, _owner, FALSE, TRUE, null, _tc_amount) - -/obj/item/device/radio/uplink/nuclear/Initialize() - . = ..() - GET_COMPONENT(hidden_uplink, /datum/component/uplink) - hidden_uplink.set_gamemode(/datum/game_mode/nuclear) - -/obj/item/device/multitool/uplink/Initialize(mapload, _owner, _tc_amount = 20) - . = ..() - LoadComponent(/datum/component/uplink, _owner, FALSE, TRUE, null, _tc_amount) - -/obj/item/pen/uplink/Initialize(mapload, _owner, _tc_amount = 20) - . = ..() - LoadComponent(/datum/component/uplink) - traitor_unlock_degrees = 360 - -/obj/item/device/radio/uplink/old - name = "dusty radio" - desc = "A dusty looking radio." - -/obj/item/device/radio/uplink/old/Initialize(mapload, _owner, _tc_amount = 10) - . = ..() - GET_COMPONENT(hidden_uplink, /datum/component/uplink) - hidden_uplink.name = "dusty radio" + +// A collection of pre-set uplinks, for admin spawns. +/obj/item/device/radio/uplink/Initialize(mapload, _owner, _tc_amount = 20) + . = ..() + icon_state = "radio" + lefthand_file = 'icons/mob/inhands/misc/devices_lefthand.dmi' + righthand_file = 'icons/mob/inhands/misc/devices_righthand.dmi' + LoadComponent(/datum/component/uplink, _owner, FALSE, TRUE, null, _tc_amount) + +/obj/item/device/radio/uplink/nuclear/Initialize() + . = ..() + GET_COMPONENT(hidden_uplink, /datum/component/uplink) + hidden_uplink.set_gamemode(/datum/game_mode/nuclear) + +/obj/item/device/multitool/uplink/Initialize(mapload, _owner, _tc_amount = 20) + . = ..() + LoadComponent(/datum/component/uplink, _owner, FALSE, TRUE, null, _tc_amount) + +/obj/item/pen/uplink/Initialize(mapload, _owner, _tc_amount = 20) + . = ..() + LoadComponent(/datum/component/uplink) + traitor_unlock_degrees = 360 + +/obj/item/device/radio/uplink/old + name = "dusty radio" + desc = "A dusty looking radio." + +/obj/item/device/radio/uplink/old/Initialize(mapload, _owner, _tc_amount = 10) + . = ..() + GET_COMPONENT(hidden_uplink, /datum/component/uplink) + hidden_uplink.name = "dusty radio" diff --git a/code/game/objects/items/dice.dm b/code/game/objects/items/dice.dm index 7cf88e77ef..334be4a645 100644 --- a/code/game/objects/items/dice.dm +++ b/code/game/objects/items/dice.dm @@ -30,6 +30,10 @@ if(special_die == "100") new /obj/item/dice/d100(src) +/obj/item/storage/pill_bottle/dice/suicide_act(mob/user) + user.visible_message("[user] is gambling with death! It looks like [user.p_theyre()] trying to commit suicide!") + return (OXYLOSS) + /obj/item/dice //depreciated d6, use /obj/item/dice/d6 if you actually want a d6 name = "die" desc = "A die with six sides. Basic and servicable." @@ -47,6 +51,10 @@ update_icon() ..() +/obj/item/dice/suicide_act(mob/user) + user.visible_message("[user] is gambling with death! It looks like [user.p_theyre()] trying to commit suicide!") + return (OXYLOSS) + /obj/item/dice/d1 name = "d1" desc = "A die with one side. Deterministic!" @@ -65,6 +73,10 @@ icon_state = "d4" sides = 4 +/obj/item/dice/d4/Initialize(mapload) + . = ..() + AddComponent(/datum/component/caltrop, 4) + /obj/item/dice/d6 name = "d6" @@ -174,14 +186,6 @@ else if(!src.throwing) //Dice was thrown and is coming to rest visible_message("[src] rolls to a stop, landing on [result]. [comment]") -/obj/item/dice/d4/Crossed(mob/living/carbon/human/H) - if(istype(H) && !H.shoes) - if(PIERCEIMMUNE in H.dna.species.species_traits) - return 0 - to_chat(H, "You step on the D4!") - H.apply_damage(4,BRUTE,(pick("l_leg", "r_leg"))) - H.Knockdown(60) - /obj/item/dice/update_icon() cut_overlays() add_overlay("[src.icon_state][src.result]") diff --git a/code/game/objects/items/grenades/clusterbuster.dm b/code/game/objects/items/grenades/clusterbuster.dm index 9f2cb1ab88..167c3114ec 100644 --- a/code/game/objects/items/grenades/clusterbuster.dm +++ b/code/game/objects/items/grenades/clusterbuster.dm @@ -129,6 +129,9 @@ //random clusterbuster spawner +/obj/item/grenade/clusterbuster/random + icon_state = "random_clusterbang" + /obj/item/grenade/clusterbuster/random/New() var/real_type = pick(subtypesof(/obj/item/grenade/clusterbuster)) new real_type(loc) diff --git a/code/game/objects/items/implants/implantuplink.dm b/code/game/objects/items/implants/implantuplink.dm index 5365f71ca7..d1d5adf4b5 100644 --- a/code/game/objects/items/implants/implantuplink.dm +++ b/code/game/objects/items/implants/implantuplink.dm @@ -1,49 +1,49 @@ -/obj/item/implant/uplink - name = "uplink implant" - desc = "Sneeki breeki." - icon = 'icons/obj/radio.dmi' - icon_state = "radio" - lefthand_file = 'icons/mob/inhands/misc/devices_lefthand.dmi' - righthand_file = 'icons/mob/inhands/misc/devices_righthand.dmi' - var/starting_tc = 0 - -/obj/item/implant/uplink/Initialize(mapload, _owner) - . = ..() - LoadComponent(/datum/component/uplink, _owner, TRUE, FALSE, null, starting_tc) - -/obj/item/implant/uplink/implant(mob/living/target, mob/user, silent = 0) - GET_COMPONENT(hidden_uplink, /datum/component/uplink) - if(hidden_uplink) - for(var/X in target.implants) - if(istype(X, type)) - var/obj/item/implant/imp_e = X - GET_COMPONENT_FROM(their_hidden_uplink, /datum/component/uplink, imp_e) - if(their_hidden_uplink) - their_hidden_uplink.telecrystals += hidden_uplink.telecrystals - qdel(src) - return TRUE - else - qdel(imp_e) //INFERIOR AND EMPTY! - - if(..()) - if(hidden_uplink) - hidden_uplink.owner = "[user.key]" - return TRUE - return FALSE - -/obj/item/implant/uplink/activate() - GET_COMPONENT(hidden_uplink, /datum/component/uplink) - if(hidden_uplink) - hidden_uplink.locked = FALSE - hidden_uplink.interact(usr) - -/obj/item/implanter/uplink - name = "implanter (uplink)" - imp_type = /obj/item/implant/uplink - -/obj/item/implanter/uplink/precharged - name = "implanter (precharged uplink)" - imp_type = /obj/item/implant/uplink/precharged - -/obj/item/implant/uplink/precharged - starting_tc = 10 +/obj/item/implant/uplink + name = "uplink implant" + desc = "Sneeki breeki." + icon = 'icons/obj/radio.dmi' + icon_state = "radio" + lefthand_file = 'icons/mob/inhands/misc/devices_lefthand.dmi' + righthand_file = 'icons/mob/inhands/misc/devices_righthand.dmi' + var/starting_tc = 0 + +/obj/item/implant/uplink/Initialize(mapload, _owner) + . = ..() + LoadComponent(/datum/component/uplink, _owner, TRUE, FALSE, null, starting_tc) + +/obj/item/implant/uplink/implant(mob/living/target, mob/user, silent = 0) + GET_COMPONENT(hidden_uplink, /datum/component/uplink) + if(hidden_uplink) + for(var/X in target.implants) + if(istype(X, type)) + var/obj/item/implant/imp_e = X + GET_COMPONENT_FROM(their_hidden_uplink, /datum/component/uplink, imp_e) + if(their_hidden_uplink) + their_hidden_uplink.telecrystals += hidden_uplink.telecrystals + qdel(src) + return TRUE + else + qdel(imp_e) //INFERIOR AND EMPTY! + + if(..()) + if(hidden_uplink) + hidden_uplink.owner = "[user.key]" + return TRUE + return FALSE + +/obj/item/implant/uplink/activate() + GET_COMPONENT(hidden_uplink, /datum/component/uplink) + if(hidden_uplink) + hidden_uplink.locked = FALSE + hidden_uplink.interact(usr) + +/obj/item/implanter/uplink + name = "implanter (uplink)" + imp_type = /obj/item/implant/uplink + +/obj/item/implanter/uplink/precharged + name = "implanter (precharged uplink)" + imp_type = /obj/item/implant/uplink/precharged + +/obj/item/implant/uplink/precharged + starting_tc = 10 diff --git a/code/game/objects/items/pet_carrier.dm b/code/game/objects/items/pet_carrier.dm new file mode 100644 index 0000000000..cab363f188 --- /dev/null +++ b/code/game/objects/items/pet_carrier.dm @@ -0,0 +1,194 @@ +#define pet_carrier_full(carrier) carrier.occupants.len >= carrier.max_occupants || carrier.occupant_weight >= carrier.max_occupant_weight + +//Used to transport little animals without having to drag them across the station. +//Comes with a handy lock to prevent them from running off. +/obj/item/pet_carrier + name = "pet carrier" + desc = "A big white-and-blue pet carrier. Good for carrying meat to the chef cute animals around." + icon = 'icons/obj/pet_carrier.dmi' + icon_state = "pet_carrier_open" + item_state = "pet_carrier" + lefthand_file = 'icons/mob/inhands/items_lefthand.dmi' + righthand_file = 'icons/mob/inhands/items_righthand.dmi' + force = 5 + attack_verb = list("bashed", "carried") + w_class = WEIGHT_CLASS_BULKY + throw_speed = 2 + throw_range = 3 + materials = list(MAT_METAL = 7500, MAT_GLASS = 100) + var/open = TRUE + var/locked = FALSE + var/list/occupants = list() + var/occupant_weight = 0 + var/max_occupants = 3 //Hard-cap so you can't have infinite mice or something in one carrier + var/max_occupant_weight = MOB_SIZE_SMALL //This is calculated from the mob sizes of occupants + +/obj/item/pet_carrier/Destroy() + if(occupants.len) + for(var/V in occupants) + remove_occupant(V) + return ..() + +/obj/item/pet_carrier/Exited(atom/movable/occupant) + if(occupant in occupants && isliving(occupant)) + var/mob/living/L = occupant + occupants -= occupant + occupant_weight -= L.mob_size + +/obj/item/pet_carrier/handle_atom_del(atom/A) + if(A in occupants && isliving(A)) + var/mob/living/L = A + occupants -= L + occupant_weight -= L.mob_size + ..() + +/obj/item/pet_carrier/examine(mob/user) + ..() + if(occupants.len) + for(var/V in occupants) + var/mob/living/L = V + to_chat(user, "It has [L] inside.") + else + to_chat(user, "It has nothing inside.") + if(user.canUseTopic(src)) + to_chat(user, "Activate it in your hand to [open ? "close" : "open"] its door.") + if(!open) + to_chat(user, "Alt-click to [locked ? "unlock" : "lock"] its door.") + +/obj/item/pet_carrier/attack_self(mob/living/user) + if(open) + to_chat(user, "You close [src]'s door.") + playsound(user, 'sound/effects/bin_close.ogg', 50, TRUE) + open = FALSE + else + if(locked) + to_chat(user, "[src] is locked!") + return + to_chat(user, "You open [src]'s door.") + playsound(user, 'sound/effects/bin_open.ogg', 50, TRUE) + open = TRUE + update_icon() + +/obj/item/pet_carrier/AltClick(mob/living/user) + if(open || !user.canUseTopic(src, be_close=TRUE)) + return + locked = !locked + to_chat(user, "You flip the lock switch [locked ? "down" : "up"].") + if(locked) + playsound(user, 'sound/machines/boltsdown.ogg', 30, TRUE) + else + playsound(user, 'sound/machines/boltsup.ogg', 30, TRUE) + update_icon() + +/obj/item/pet_carrier/attack(mob/living/target, mob/living/user) + if(user.a_intent == INTENT_HARM) + return ..() + if(!open) + to_chat(user, "You need to open [src]'s door!") + return + if(target.mob_size > max_occupant_weight) + if(ishuman(target)) + var/mob/living/carbon/human/H = target + if(iscatperson(H)) + to_chat(user, "You'd need a lot of catnip and treats, plus maybe a laser pointer, for that to work.") + else + to_chat(user, "Humans, generally, do not fit into pet carriers.") + else + to_chat(user, "You get the feeling [target] isn't meant for a [name].") + return + if(user == target) + to_chat(user, "Why would you ever do that?") + return + load_occupant(user, target) + +/obj/item/pet_carrier/relaymove(mob/living/user, direction) + if(open) + loc.visible_message("[user] climbs out of [src]!", \ + "[user] jumps out of [src]!") + remove_occupant(user) + return + else if(!locked) + loc.visible_message("[user] pushes open the door to [src]!", \ + "[user] pushes open the door of [src]!") + open = TRUE + update_icon() + return + else if(user.client) + container_resist(user) + +/obj/item/pet_carrier/container_resist(mob/living/user) + user.changeNext_move(CLICK_CD_BREAKOUT) + user.last_special = world.time + CLICK_CD_BREAKOUT + if(user.mob_size <= MOB_SIZE_SMALL) + to_chat(user, "You poke a limb through [src]'s bars and start fumbling for the lock switch... (This will take some time.)") + to_chat(loc, "You see [user] reach through the bars and fumble for the lock switch!") + if(!do_after(user, rand(300, 400), target = user) || open || !locked || !user in occupants) + return + loc.visible_message("[user] flips the lock switch on [src] by reaching through!", ignored_mob = user) + to_chat(user, "Bingo! The lock pops open!") + locked = FALSE + playsound(src, 'sound/machines/boltsup.ogg', 30, TRUE) + update_icon() + else + loc.visible_message("[src] starts rattling as something pushes against the door!", ignored_mob = user) + to_chat(user, "You start pushing out of [src]... (This will take about 20 seconds.)") + if(!do_after(user, 200, target = user) || open || !locked || !user in occupants) + return + loc.visible_message("[user] shoves out of [src]!", ignored_mob = user) + to_chat(user, "You shove open [src]'s door against the lock's resistance and fall out!") + locked = FALSE + open = TRUE + update_icon() + remove_occupant(user) + +/obj/item/pet_carrier/update_icon() + cut_overlay("unlocked") + cut_overlay("locked") + if(open) + icon_state = initial(icon_state) + else + icon_state = "pet_carrier_[!occupants.len ? "closed" : "occupied"]" + add_overlay("[locked ? "" : "un"]locked") + +/obj/item/pet_carrier/MouseDrop(atom/over_atom) + if(isopenturf(over_atom) && usr.Adjacent(over_atom) && open && occupants.len) + usr.visible_message("[usr] unloads [src].", \ + "You unload [src] onto [over_atom].") + for(var/V in occupants) + remove_occupant(V, over_atom) + +/obj/item/pet_carrier/proc/load_occupant(mob/living/user, mob/living/target) + if(pet_carrier_full(src)) + to_chat(user, "[src] is already carrying too much!") + return + user.visible_message("[user] starts loading [target] into [src].", \ + "You start loading [target] into [src]...", ignored_mob = target) + to_chat(target, "[user] starts loading you into their [name]!") + if(!do_mob(user, target, 30)) + return + if(target in occupants) + return + if(pet_carrier_full(src)) //Run the checks again, just in case + to_chat(user, "[src] is already carrying too much!") + return + user.visible_message("[user] loads [target] into [src]!", \ + "You load [target] into [src].", ignored_mob = target) + to_chat(target, "[user] loads you into their [name]!") + add_occupant(target) + +/obj/item/pet_carrier/proc/add_occupant(mob/living/occupant) + if(occupant in occupants || !istype(occupant)) + return + occupant.forceMove(src) + occupants += occupant + occupant_weight += occupant.mob_size + +/obj/item/pet_carrier/proc/remove_occupant(mob/living/occupant, turf/new_turf) + if(!occupant in occupants || !istype(occupant)) + return + occupant.forceMove(new_turf ? new_turf : drop_location()) + occupants -= occupant + occupant_weight -= occupant.mob_size + occupant.setDir(SOUTH) + +#undef pet_carrier_full diff --git a/code/game/objects/items/stacks/medical.dm b/code/game/objects/items/stacks/medical.dm index 6c073f4b69..8db91578f5 100644 --- a/code/game/objects/items/stacks/medical.dm +++ b/code/game/objects/items/stacks/medical.dm @@ -113,6 +113,10 @@ origin_tech = "biotech=2" self_delay = 20 +/obj/item/stack/medical/bruise_pack/suicide_act(mob/user) + user.visible_message("[user] is bludgeoning [user.p_them()]self with [src]! It looks like [user.p_theyre()] trying to commit suicide!") + return (BRUTELOSS) + /obj/item/stack/medical/gauze name = "medical gauze" desc = "A roll of elastic cloth that is extremely effective at stopping bleeding, but does not heal wounds." diff --git a/code/game/objects/items/stacks/sheets/glass.dm b/code/game/objects/items/stacks/sheets/glass.dm index c6a5d074e7..a70692a07d 100644 --- a/code/game/objects/items/stacks/sheets/glass.dm +++ b/code/game/objects/items/stacks/sheets/glass.dm @@ -205,6 +205,7 @@ GLOBAL_LIST_INIT(prglass_recipes, list ( \ /obj/item/shard/Initialize() . = ..() + AddComponent(/datum/component/caltrop, force) icon_state = pick("large", "medium", "small") switch(icon_state) if("small") @@ -257,27 +258,4 @@ GLOBAL_LIST_INIT(prglass_recipes, list ( \ /obj/item/shard/Crossed(mob/AM) if(istype(AM) && has_gravity(loc)) playsound(loc, 'sound/effects/glass_step.ogg', 50, 1) - if(ishuman(AM)) - var/mob/living/carbon/human/H = AM - if(PIERCEIMMUNE in H.dna.species.species_traits) - return - var/picked_def_zone = pick("l_leg", "r_leg") - var/obj/item/bodypart/O = H.get_bodypart(picked_def_zone) - if(!istype(O)) - return - if(O.status == BODYPART_ROBOTIC) - return - var/feetCover = (H.wear_suit && H.wear_suit.body_parts_covered & FEET) || (H.w_uniform && H.w_uniform.body_parts_covered & FEET) - if(H.shoes || feetCover || H.movement_type & FLYING || H.buckled) - return - H.apply_damage(5, BRUTE, picked_def_zone) - if(cooldown < world.time - 10) //cooldown to avoid message spam. - if(!H.incapacitated()) - H.visible_message("[H] steps in the broken glass!", \ - "You step in the broken glass!") - else - H.visible_message("[H] slides on the broken glass!", \ - "You slide on the broken glass!") - - cooldown = world.time - H.Knockdown(60) + . = ..() diff --git a/code/game/objects/items/storage/firstaid.dm b/code/game/objects/items/storage/firstaid.dm index 4dc90de6be..2b7a1695cd 100644 --- a/code/game/objects/items/storage/firstaid.dm +++ b/code/game/objects/items/storage/firstaid.dm @@ -167,6 +167,10 @@ usr.s_active.close(usr) src.show_to(usr) +/obj/item/storage/pill_bottle/suicide_act(mob/user) + user.visible_message("[user] is trying to get the cap off [src]! It looks like [user.p_theyre()] trying to commit suicide!") + return (TOXLOSS) + /obj/item/storage/pill_bottle/charcoal name = "bottle of charcoal pills" desc = "Contains pills used to counter toxins." diff --git a/code/game/objects/items/storage/wallets.dm b/code/game/objects/items/storage/wallets.dm index 7747c3843d..885dbc3830 100644 --- a/code/game/objects/items/storage/wallets.dm +++ b/code/game/objects/items/storage/wallets.dm @@ -72,6 +72,9 @@ else return ..() +/obj/item/storage/wallet/random + icon_state = "random_wallet" + /obj/item/storage/wallet/random/PopulateContents() var/item1_type = pick( /obj/item/stack/spacecash/c10, /obj/item/stack/spacecash/c100, /obj/item/stack/spacecash/c1000, /obj/item/stack/spacecash/c20, /obj/item/stack/spacecash/c200, /obj/item/stack/spacecash/c50, /obj/item/stack/spacecash/c500) var/item2_type @@ -86,3 +89,4 @@ new item2_type(src) if(item3_type) new item3_type(src) + update_icon() diff --git a/code/game/objects/items/theft_tools.dm b/code/game/objects/items/theft_tools.dm index 5f3e493677..e00513a47a 100644 --- a/code/game/objects/items/theft_tools.dm +++ b/code/game/objects/items/theft_tools.dm @@ -34,6 +34,10 @@ cooldown = world.time flick(pulseicon, src) radiation_pulse(src, 400, 2) + +/obj/item/nuke_core/suicide_act(mob/user) + user.visible_message("[user] is rubbing [src] against [user.p_them()]self! It looks like [user.p_theyre()] trying to commit suicide!") + return (TOXLOSS) //nuke core box, for carrying the core /obj/item/nuke_core_container diff --git a/code/game/objects/items/vending_items.dm b/code/game/objects/items/vending_items.dm index e84295f8ed..d44b933f83 100644 --- a/code/game/objects/items/vending_items.dm +++ b/code/game/objects/items/vending_items.dm @@ -37,8 +37,8 @@ /obj/item/vending_refill/boozeomat machine_name = "Booze-O-Mat" icon_state = "refill_booze" - charges = list(54, 4, 0)//of 159 standard, 12 contraband - init_charges = list(54, 4, 0) + charges = list(58, 4, 0)//of 174 standard, 12 contraband + init_charges = list(58, 4, 0) /obj/item/vending_refill/coffee machine_name = "Solar's Best Hot Drinks" diff --git a/code/game/objects/items/weaponry.dm b/code/game/objects/items/weaponry.dm index c112e103b2..4356102efd 100644 --- a/code/game/objects/items/weaponry.dm +++ b/code/game/objects/items/weaponry.dm @@ -398,7 +398,7 @@ icon_state = "ectoplasm" /obj/item/ectoplasm/suicide_act(mob/user) - user.visible_message("[user] is inhaling [src]! It looks like [user.p_theyre()] trying to visit the astral plane.") + user.visible_message("[user] is inhaling [src]! It looks like [user.p_theyre()] trying to visit the astral plane!") return (OXYLOSS) /obj/item/mounted_chainsaw diff --git a/code/game/objects/structures/bedsheet_bin.dm b/code/game/objects/structures/bedsheet_bin.dm index 238c83725b..aa9acae22c 100644 --- a/code/game/objects/structures/bedsheet_bin.dm +++ b/code/game/objects/structures/bedsheet_bin.dm @@ -225,7 +225,7 @@ LINEN BINS /obj/item/bedsheet/random - icon_state = "sheetrainbow" + icon_state = "random_bedsheet" item_color = "rainbow" name = "random bedsheet" desc = "If you're reading this description ingame, something has gone wrong! Honk!" diff --git a/code/game/objects/structures/crates_lockers/closets/secure/medical.dm b/code/game/objects/structures/crates_lockers/closets/secure/medical.dm index 0351fdc596..5402abdfee 100644 --- a/code/game/objects/structures/crates_lockers/closets/secure/medical.dm +++ b/code/game/objects/structures/crates_lockers/closets/secure/medical.dm @@ -73,6 +73,7 @@ new /obj/item/device/autosurgeon/cmo(src) new /obj/item/door_remote/chief_medical_officer(src) new /obj/item/clothing/neck/petcollar(src) + new /obj/item/pet_carrier(src) /obj/structure/closet/secure_closet/animal name = "animal control" diff --git a/code/game/objects/structures/crates_lockers/closets/secure/security.dm b/code/game/objects/structures/crates_lockers/closets/secure/security.dm index 3cb3edb8c2..7f36acaae9 100644 --- a/code/game/objects/structures/crates_lockers/closets/secure/security.dm +++ b/code/game/objects/structures/crates_lockers/closets/secure/security.dm @@ -12,6 +12,7 @@ new /obj/item/storage/backpack/satchel/cap(src) new /obj/item/clothing/neck/cloak/cap(src) new /obj/item/clothing/neck/petcollar(src) + new /obj/item/pet_carrier(src) new /obj/item/storage/backpack/duffelbag/captain(src) new /obj/item/clothing/head/crown/fancy(src) new /obj/item/clothing/suit/captunic(src) @@ -53,6 +54,7 @@ new /obj/item/restraints/handcuffs/cable/zipties(src) new /obj/item/gun/energy/e_gun/cx(src) new /obj/item/clothing/neck/petcollar(src) + new /obj/item/pet_carrier(src) new /obj/item/door_remote/civillian(src) /obj/structure/closet/secure_closet/hos diff --git a/code/game/objects/structures/flora.dm b/code/game/objects/structures/flora.dm index 260285aff9..f7071cd0a5 100644 --- a/code/game/objects/structures/flora.dm +++ b/code/game/objects/structures/flora.dm @@ -285,10 +285,13 @@ user.remove_alt_appearance("sneaking_mission") /obj/item/twohanded/required/kirbyplants/random + icon = 'icons/obj/flora/_flora.dmi' + icon_state = "random_plant" var/list/static/states /obj/item/twohanded/required/kirbyplants/random/Initialize() . = ..() + icon = 'icons/obj/flora/plants.dmi' if(!states) generate_states() icon_state = pick(states) diff --git a/code/game/objects/structures/grille.dm b/code/game/objects/structures/grille.dm index 45aa4a0889..009bbcd70e 100644 --- a/code/game/objects/structures/grille.dm +++ b/code/game/objects/structures/grille.dm @@ -26,7 +26,7 @@ update_icon() /obj/structure/grille/update_icon() - if(QDELETED(src)) + if(QDELETED(src) || broken) return var/ratio = obj_integrity / max_integrity diff --git a/code/game/objects/structures/manned_turret.dm b/code/game/objects/structures/manned_turret.dm index 669abb792a..ceef3ef0c0 100644 --- a/code/game/objects/structures/manned_turret.dm +++ b/code/game/objects/structures/manned_turret.dm @@ -37,7 +37,7 @@ buckled_mob.pixel_x = 0 buckled_mob.pixel_y = 0 if(buckled_mob.client) - buckled_mob.client.change_view(world.view) + buckled_mob.client.change_view(CONFIG_GET(string/default_view)) anchored = FALSE . = ..() STOP_PROCESSING(SSfastprocess, src) diff --git a/code/game/turfs/simulated/walls.dm b/code/game/turfs/simulated/walls.dm index 6d8db55ad8..337bb051a8 100644 --- a/code/game/turfs/simulated/walls.dm +++ b/code/game/turfs/simulated/walls.dm @@ -1,3 +1,5 @@ +#define MAX_DENT_DECALS 15 + /turf/closed/wall name = "wall" desc = "A huge chunk of metal used to separate rooms." @@ -297,6 +299,9 @@ return FALSE /turf/closed/wall/proc/add_dent(denttype, x=rand(-8, 8), y=rand(-8, 8)) + if(LAZYLEN(dent_decals) >= MAX_DENT_DECALS) + return + var/mutable_appearance/decal = pick(dent_decal_list[denttype]) decal.pixel_x = x decal.pixel_y = y @@ -304,3 +309,5 @@ cut_overlay(dent_decals) LAZYADD(dent_decals, decal) add_overlay(dent_decals) + +#undef MAX_DENT_DECALS diff --git a/code/modules/admin/topic.dm b/code/modules/admin/topic.dm index 4a332abbb9..3e27ae323d 100644 --- a/code/modules/admin/topic.dm +++ b/code/modules/admin/topic.dm @@ -393,6 +393,8 @@ log_admin("[key_name(usr)] [msg]") message_admins("[key_name_admin(usr)] [msg]") href_list["secrets"] = "check_antagonist" + if(SSticker.ready_for_reboot && !SSticker.delay_end) //we undelayed after standard reboot would occur + SSticker.standard_reboot() else if(href_list["end_round"]) if(!check_rights(R_ADMIN)) diff --git a/code/modules/admin/verbs/machine_upgrade.dm b/code/modules/admin/verbs/machine_upgrade.dm index 463ee70ac8..58deff2a24 100644 --- a/code/modules/admin/verbs/machine_upgrade.dm +++ b/code/modules/admin/verbs/machine_upgrade.dm @@ -1,6 +1,9 @@ /proc/machine_upgrade(obj/machinery/M in world) set name = "Tweak Component Ratings" set category = "Debug" + if (!istype(M)) + return + var/new_rating = input("Enter new rating:","Num") as num if(new_rating && M.component_parts) for(var/obj/item/stock_parts/P in M.component_parts) diff --git a/code/modules/admin/verbs/randomverbs.dm b/code/modules/admin/verbs/randomverbs.dm index a4e26e5c9a..48ba94bb76 100644 --- a/code/modules/admin/verbs/randomverbs.dm +++ b/code/modules/admin/verbs/randomverbs.dm @@ -651,10 +651,10 @@ Traitors and the like can also be revived with the previous role mostly intact. set name = "Change View Range" set desc = "switches between 1x and custom views" - if(view == world.view) + if(view == CONFIG_GET(string/default_view)) change_view(input("Select view range:", "FUCK YE", 7) in list(1,2,3,4,5,6,7,8,9,10,11,12,13,14,128)) else - change_view(world.view) + change_view(CONFIG_GET(string/default_view)) log_admin("[key_name(usr)] changed their view range to [view].") //message_admins("\blue [key_name_admin(usr)] changed their view range to [view].") //why? removed by order of XSI diff --git a/code/modules/atmospherics/environmental/LINDA_turf_tile.dm b/code/modules/atmospherics/environmental/LINDA_turf_tile.dm index 5ef9469295..f2d1a241f2 100644 --- a/code/modules/atmospherics/environmental/LINDA_turf_tile.dm +++ b/code/modules/atmospherics/environmental/LINDA_turf_tile.dm @@ -7,7 +7,7 @@ //list of open turfs adjacent to us var/list/atmos_adjacent_turfs //bitfield of dirs in which we are superconducitng - var/atmos_supeconductivity = 0 + var/atmos_supeconductivity = NONE //used to determine whether we should archive var/archived_cycle = 0 @@ -25,8 +25,7 @@ var/pressure_direction = 0 var/datum/excited_group/excited_group - var/excited = 0 - var/recently_active = 0 + var/excited = FALSE var/datum/gas_mixture/turf/air var/obj/effect/hotspot/active_hotspot @@ -54,10 +53,10 @@ /turf/open/assume_air(datum/gas_mixture/giver) //use this for machines to adjust air if(!giver) - return 0 + return FALSE air.merge(giver) update_visuals() - return 1 + return TRUE /turf/open/remove_air(amount) var/datum/gas_mixture/ours = return_air() @@ -83,7 +82,7 @@ /turf/temperature_expose() if(temperature > heat_capacity) - to_be_destroyed = 1 + to_be_destroyed = TRUE /turf/proc/archive() temperature_archived = temperature @@ -102,7 +101,7 @@ #if DM_VERSION >= 513 #warning 512 is stable now for sure, remove the old code #endif - + #if DM_VERSION >= 512 if (atmos_overlay_types) for(var/overlay in atmos_overlay_types-new_overlay_types) //doesn't remove overlays that would only be added @@ -175,64 +174,48 @@ for(var/t in adjacent_turfs) var/turf/open/enemy_tile = t - if(fire_count > enemy_tile.current_cycle) - enemy_tile.archive() + if(fire_count <= enemy_tile.current_cycle) + continue + enemy_tile.archive() - /******************* GROUP HANDLING START *****************************************************************/ + /******************* GROUP HANDLING START *****************************************************************/ - var/should_share_air = FALSE - var/datum/gas_mixture/enemy_air = enemy_tile.air - if(enemy_tile.excited) - //cache for sanic speed - var/datum/excited_group/enemy_excited_group = enemy_tile.excited_group - if(our_excited_group) - if(enemy_excited_group) - if(our_excited_group != enemy_excited_group) - //combine groups (this also handles updating the excited_group var of all involved turfs) - our_excited_group.merge_groups(enemy_excited_group) - our_excited_group = excited_group //update our cache - should_share_air = TRUE - else - if((recently_active == 1 && enemy_tile.recently_active == 1) || our_air.compare(enemy_air)) - our_excited_group.add_turf(enemy_tile) //add enemy to our group - should_share_air = TRUE + var/should_share_air = FALSE + var/datum/gas_mixture/enemy_air = enemy_tile.air + + //cache for sanic speed + var/datum/excited_group/enemy_excited_group = enemy_tile.excited_group + + if(our_excited_group && enemy_excited_group) + if(our_excited_group != enemy_excited_group) + //combine groups (this also handles updating the excited_group var of all involved turfs) + our_excited_group.merge_groups(enemy_excited_group) + our_excited_group = excited_group //update our cache + should_share_air = TRUE + + else if(our_air.compare(enemy_air)) + if(!enemy_tile.excited) + SSair.add_to_active(enemy_tile) + var/datum/excited_group/EG = our_excited_group || enemy_excited_group || new + if(!our_excited_group) + EG.add_turf(src) + if(!enemy_excited_group) + EG.add_turf(enemy_tile) + our_excited_group = excited_group + should_share_air = TRUE + + //air sharing + if(should_share_air) + var/difference = our_air.share(enemy_air, adjacent_turfs_length) + if(difference) + if(difference > 0) + consider_pressure_difference(enemy_tile, difference) else - if(enemy_excited_group) - if((recently_active == 1 && enemy_tile.recently_active == 1) || our_air.compare(enemy_air)) - enemy_excited_group.add_turf(src) //join self to enemy group - our_excited_group = excited_group //update our cache - should_share_air = TRUE - else - if((recently_active == 1 && enemy_tile.recently_active == 1) || our_air.compare(enemy_air)) - var/datum/excited_group/EG = new //generate new group - EG.add_turf(src) - EG.add_turf(enemy_tile) - our_excited_group = excited_group //update our cache - should_share_air = TRUE - else - if(our_air.compare(enemy_air)) //compare if - SSair.add_to_active(enemy_tile) //excite enemy - if(our_excited_group) - our_excited_group.add_turf(enemy_tile) //add enemy to group - else - var/datum/excited_group/EG = new //generate new group - EG.add_turf(src) - EG.add_turf(enemy_tile) - our_excited_group = excited_group //update our cache - should_share_air = TRUE - - //air sharing - if(should_share_air) - var/difference = our_air.share(enemy_air, adjacent_turfs_length) - if(difference) - if(difference > 0) - consider_pressure_difference(enemy_tile, difference) - else - enemy_tile.consider_pressure_difference(src, -difference) - LAST_SHARE_CHECK + enemy_tile.consider_pressure_difference(src, -difference) + LAST_SHARE_CHECK - /******************* GROUP HANDLING FINISH *********************************************************************/ + /******************* GROUP HANDLING FINISH *********************************************************************/ if (planet_atmos) //share our air with the "atmosphere" "above" the turf var/datum/gas_mixture/G = new @@ -250,12 +233,8 @@ update_visuals() - var/remove = TRUE - if(our_air.temperature > MINIMUM_TEMPERATURE_START_SUPERCONDUCTION) - if(consider_superconductivity(starting = 1)) - remove = FALSE - - if ((!our_excited_group && remove) || (cached_atmos_cooldown > (EXCITED_GROUP_DISMANTLE_CYCLES * 2))) + if((!our_excited_group && !(our_air.temperature > MINIMUM_TEMPERATURE_START_SUPERCONDUCTION && consider_superconductivity(starting = TRUE))) \ + || (cached_atmos_cooldown > (EXCITED_GROUP_DISMANTLE_CYCLES * 2))) SSair.remove_from_active(src) atmos_cooldown = cached_atmos_cooldown @@ -279,9 +258,9 @@ var/const/PROBABILITY_OFFSET = 25 var/const/PROBABILITY_BASE_PRECENT = 75 set waitfor = 0 - . = 0 + . = FALSE if (!anchored && !pulledby) - . = 1 + . = TRUE if (last_high_pressure_movement_air_cycle < SSair.times_fired) var/move_prob = 100 if (pressure_resistance > 0) @@ -304,7 +283,6 @@ /datum/excited_group/proc/add_turf(turf/open/T) turf_list += T T.excited_group = src - T.recently_active = 1 reset_cooldowns() /datum/excited_group/proc/merge_groups(datum/excited_group/E) @@ -328,25 +306,27 @@ dismantle_cooldown = 0 //argument is so world start can clear out any turf differences quickly. -/datum/excited_group/proc/self_breakdown(space_is_all_consuming = 0) +/datum/excited_group/proc/self_breakdown(space_is_all_consuming = FALSE) var/datum/gas_mixture/A = new //make local for sanic speed var/list/A_gases = A.gases var/list/turf_list = src.turf_list var/turflen = turf_list.len - var/space_in_group = 0 + var/space_in_group = FALSE for(var/t in turf_list) var/turf/open/T = t if (space_is_all_consuming && !space_in_group && istype(T.air, /datum/gas_mixture/immutable/space)) - space_in_group = 1 + space_in_group = TRUE qdel(A) - A = new/datum/gas_mixture/immutable/space() + A = new /datum/gas_mixture/immutable/space() + A_gases = A.gases //update the cache + break A.merge(T.air) for(var/id in A_gases) - A_gases[id][MOLES] = A_gases[id][MOLES]/turflen + A_gases[id][MOLES] /= turflen for(var/t in turf_list) var/turf/open/T = t @@ -359,8 +339,7 @@ /datum/excited_group/proc/dismantle() for(var/t in turf_list) var/turf/open/T = t - T.excited = 0 - T.recently_active = 0 + T.excited = FALSE T.excited_group = null SSair.active_turfs -= T garbage_collect() @@ -432,7 +411,7 @@ //Make sure still hot enough to continue conducting heat if(temp < MINIMUM_TEMPERATURE_FOR_SUPERCONDUCTION) SSair.active_super_conductivity -= src - return 0 + return FALSE /turf/open/finish_superconduction() //Conduct with air on my tile if I have it @@ -442,21 +421,21 @@ /turf/proc/consider_superconductivity() if(!thermal_conductivity) - return 0 + return FALSE SSair.active_super_conductivity |= src - return 1 + return TRUE /turf/open/consider_superconductivity(starting) if(air.temperature < (starting?MINIMUM_TEMPERATURE_START_SUPERCONDUCTION:MINIMUM_TEMPERATURE_FOR_SUPERCONDUCTION)) - return 0 + return FALSE if(air.heat_capacity() < M_CELL_WITH_RATIO) // Was: MOLES_CELLSTANDARD*0.1*0.05 Since there are no variables here we can make this a constant. - return 0 + return FALSE return ..() /turf/closed/consider_superconductivity(starting) if(temperature < (starting?MINIMUM_TEMPERATURE_START_SUPERCONDUCTION:MINIMUM_TEMPERATURE_FOR_SUPERCONDUCTION)) - return 0 + return FALSE return ..() /turf/proc/radiate_to_spess() //Radiate excess tile heat to space @@ -465,7 +444,7 @@ if((heat_capacity > 0) && (abs(delta_temperature) > MINIMUM_TEMPERATURE_DELTA_TO_CONSIDER)) var/heat = thermal_conductivity*delta_temperature* \ - (heat_capacity*700000/(heat_capacity+700000)) //700000 is the heat_capacity from a space turf, hardcoded here + (heat_capacity*HEAT_CAPACITY_VACUUM/(heat_capacity+HEAT_CAPACITY_VACUUM)) temperature -= heat/heat_capacity /turf/open/proc/temperature_share_open_to_solid(turf/sharer) diff --git a/code/modules/atmospherics/gasmixtures/reactions.dm b/code/modules/atmospherics/gasmixtures/reactions.dm index 07339807da..5a88c6837e 100644 --- a/code/modules/atmospherics/gasmixtures/reactions.dm +++ b/code/modules/atmospherics/gasmixtures/reactions.dm @@ -1,5 +1,3 @@ -#define NO_REACTION 0 -#define REACTING 1 //Plasma fire properties #define OXYGEN_BURN_RATE_BASE 1.4 #define PLASMA_BURN_RATE_DELTA 9 @@ -359,9 +357,6 @@ if(new_heat_capacity > MINIMUM_HEAT_CAPACITY) air.temperature = max(((air.temperature*old_heat_capacity - energy_taken)/new_heat_capacity),TCMB) - -#undef REACTING -#undef NO_REACTION #undef OXYGEN_BURN_RATE_BASE #undef PLASMA_BURN_RATE_DELTA #undef PLASMA_UPPER_TEMPERATURE @@ -386,4 +381,4 @@ #undef CATALYST_COEFFICENT #undef FUSION_PURITY_THRESHOLD #undef FUSION_HEAT_DROPOFF -#undef NOBLIUM_FORMATION_ENERGY \ No newline at end of file +#undef NOBLIUM_FORMATION_ENERGY diff --git a/code/modules/atmospherics/machinery/airalarm.dm b/code/modules/atmospherics/machinery/airalarm.dm index efe45f4e84..952ee0e068 100644 --- a/code/modules/atmospherics/machinery/airalarm.dm +++ b/code/modules/atmospherics/machinery/airalarm.dm @@ -356,6 +356,9 @@ . = TRUE if("threshold") var/env = params["env"] + if(text2path(env)) + env = text2path(env) + var/name = params["var"] var/datum/tlv/tlv = TLV[env] if(isnull(tlv)) diff --git a/code/modules/awaymissions/super_secret_room.dm b/code/modules/awaymissions/super_secret_room.dm index fa9aff7f43..b1f505a27e 100644 --- a/code/modules/awaymissions/super_secret_room.dm +++ b/code/modules/awaymissions/super_secret_room.dm @@ -17,6 +17,8 @@ var/list/json = json_decode(file2text(json_file)) shenanigans = json["phrases"] +#define TIMEWASTE_MEDAL "Overextended The Joke" + /obj/structure/speaking_tile/interact(mob/user) if(!isliving(user) || speaking) return @@ -45,11 +47,11 @@ SpeakPeace(list("Alright maybe that's too boring.", "I can't keep manually typing these lines out though.", "It's hard to explain but the code structure I'm using is kind of terrible.")) if(10) SpeakPeace(list("Oh I have an idea!", "Lets outsource this endless banter to Poly!", "Then you'll be able to keep listening to this without getting bored!")) - if(isnull(shenanigans)) + if(isnull(shenanigans) || !shenanigans.len) shenanigans = list("Except the poly file is missing...") if(11 to 14, 16 to 50, 52 to 99, 103 to 107, 109 to 203, 205 to 249, 252 to 665, 667 to 999, 1001 to 5642) SpeakPeace(list(pick(shenanigans),pick(shenanigans),pick(shenanigans))) - if(times_spoken_to * 0.1 == round(times_spoken_to * 0.1)) + if(times_spoken_to % 10 == 0) SpeakPeace(list("That's [times_spoken_to] times you've spoken to me by the way.")) if(15) SpeakPeace(list("See? Isn't this fun?","Now you can mash this for hours without getting bored.","Anyway I'll leave you it.")) @@ -79,6 +81,7 @@ if(1000) SpeakPeace(list("The ends exists somewhere beyond meaningful milestones.", "There will be no more messages until then.", "You disgust me.")) if(5643) + UnlockMedal(TIMEWASTE_MEDAL,user.client) var/obj/item/reagent_containers/food/drinks/trophy/gold_cup/never_ends = new(get_turf(user)) never_ends.name = "Overextending The Joke: First Place" never_ends.desc = "And so we are left alone with our regrets." @@ -87,7 +90,7 @@ speaking = FALSE times_spoken_to++ - +#undef TIMEWASTE_MEDAL /obj/structure/speaking_tile/proc/SpeakPeace(list/statements) for(var/i in 1 to statements.len) say("[statements[i]]") diff --git a/code/modules/client/client_procs.dm b/code/modules/client/client_procs.dm index 7b9e2ee4e7..43ae694b84 100644 --- a/code/modules/client/client_procs.dm +++ b/code/modules/client/client_procs.dm @@ -442,7 +442,7 @@ GLOBAL_LIST(external_rsc_urls) message_admins("Failed Login: [key] - New account attempting to connect during panic bunker") to_chat(src, "Sorry but the server is currently not accepting connections from never before seen players.") var/list/connectiontopic_a = params2list(connectiontopic) - var/list/panic_addr = CONFIG_GET(string/panic_address) + var/list/panic_addr = CONFIG_GET(string/panic_server_address) if(panic_addr && !connectiontopic_a["redirect"]) var/panic_name = CONFIG_GET(string/panic_server_name) to_chat(src, "Sending you to [panic_name ? panic_name : panic_addr].") diff --git a/code/modules/client/verbs/suicide.dm b/code/modules/client/verbs/suicide.dm index f4ebeda886..a5f9dfee68 100644 --- a/code/modules/client/verbs/suicide.dm +++ b/code/modules/client/verbs/suicide.dm @@ -119,11 +119,9 @@ death(0) /mob/living/silicon/pai/verb/suicide() - set category = "pAI Commands" - set desc = "Kill yourself and become a ghost (You will receive a confirmation prompt)" - set name = "pAI Suicide" - var/answer = input("REALLY kill yourself? This action can't be undone.", "Suicide", "No") in list ("Yes", "No") - if(answer == "Yes") + set hidden = 1 + var/confirm = alert("Are you sure you want to commit suicide?", "Confirm Suicide", "Yes", "No") + if(confirm == "Yes") var/turf/T = get_turf(src.loc) T.visible_message("[src] flashes a message across its screen, \"Wiping core files. Please acquire a new personality to continue using pAI device functions.\"", null, \ "[src] bleeps electronically.") diff --git a/code/modules/clothing/glasses/engine_goggles.dm b/code/modules/clothing/glasses/engine_goggles.dm index e3a99fdb9a..b2b869edae 100644 --- a/code/modules/clothing/glasses/engine_goggles.dm +++ b/code/modules/clothing/glasses/engine_goggles.dm @@ -8,7 +8,8 @@ /obj/item/clothing/glasses/meson/engine name = "engineering scanner goggles" desc = "Goggles used by engineers. The Meson Scanner mode lets you see basic structural and terrain layouts through walls, the T-ray Scanner mode lets you see underfloor objects such as cables and pipes, and the Radiation Scanner mode let's you see objects contaminated by radiation." - icon_state = "trayson" + icon_state = "trayson-meson" + item_state = "trayson-meson" actions_types = list(/datum/action/item_action/toggle_mode) origin_tech = "materials=3;magnets=3;engineering=3;plasmatech=3" @@ -117,14 +118,22 @@ flick_overlay(pic, list(user.client), 8) /obj/item/clothing/glasses/meson/engine/update_icon() - icon_state = "[initial(icon_state)]-[mode]" - if(istype(loc, /mob/living/carbon/human/)) - var/mob/living/carbon/human/user = loc - if(user.glasses == src) + icon_state = "trayson-[mode]" + update_mob() + +/obj/item/clothing/glasses/meson/engine/proc/update_mob() + item_state = icon_state + if(isliving(loc)) + var/mob/living/user = loc + if(user.get_item_by_slot(slot_glasses) == src) user.update_inv_glasses() + else + user.update_inv_hands() /obj/item/clothing/glasses/meson/engine/tray //atmos techs have lived far too long without tray goggles while those damned engineers get their dual-purpose gogles all to themselves name = "optical t-ray scanner" + icon_state = "trayson-t-ray" + item_state = "trayson-t-ray" desc = "Used by engineering staff to see underfloor objects such as cables and pipes." origin_tech = "materials=3;magnets=2;engineering=2" diff --git a/code/modules/clothing/gloves/color.dm b/code/modules/clothing/gloves/color.dm index 8b714f25dd..257318ce80 100644 --- a/code/modules/clothing/gloves/color.dm +++ b/code/modules/clothing/gloves/color.dm @@ -188,7 +188,7 @@ /obj/item/clothing/gloves/color/random name = "random gloves" desc = "These gloves are supposed to be a random color..." - icon_state = "white" + icon_state = "random_gloves" item_state = "wgloves" item_color = "mime" diff --git a/code/modules/clothing/spacesuits/flightsuit.dm b/code/modules/clothing/spacesuits/flightsuit.dm index 79886b1446..7e4b0bad89 100644 --- a/code/modules/clothing/spacesuits/flightsuit.dm +++ b/code/modules/clothing/spacesuits/flightsuit.dm @@ -856,21 +856,22 @@ return TRUE /obj/item/clothing/suit/space/hardsuit/flightsuit/proc/unlock_suit(mob/wearer) - if(suittoggled) - usermessage("You must retract the helmet before unlocking your suit!", "boldwarning") - return FALSE - if(pack && pack.flight) - usermessage("You must shut off the flight-pack before unlocking your suit!", "boldwarning") - return FALSE - if(deployedpack) - usermessage("Your flightpack must be fully retracted first!", "boldwarning") - return FALSE - if(deployedshoes) - usermessage("Your flight shoes must be fully retracted first!", "boldwarning") - return FALSE - if(wearer) - user.visible_message("[wearer]'s flight suit detaches from their body, becoming nothing more then a bulky metal skeleton.") - playsound(src.loc, 'sound/items/rped.ogg', 65, 1) + if(user) + if(suittoggled) + usermessage("You must retract the helmet before unlocking your suit!", "boldwarning") + return FALSE + if(pack && pack.flight) + usermessage("You must shut off the flight-pack before unlocking your suit!", "boldwarning") + return FALSE + if(deployedpack) + usermessage("Your flightpack must be fully retracted first!", "boldwarning") + return FALSE + if(deployedshoes) + usermessage("Your flight shoes must be fully retracted first!", "boldwarning") + return FALSE + if(wearer) + user.visible_message("[wearer]'s flight suit detaches from their body, becoming nothing more then a bulky metal skeleton.") + playsound(src, 'sound/items/rped.ogg', 65, 1) resync() strip_delay = initial(strip_delay) locked = FALSE @@ -911,7 +912,7 @@ user.update_inv_wear_suit() user.visible_message("[user]'s [pack.name] detaches from their back and retracts into their [src]!") pack.forceMove(src) - playsound(src.loc, 'sound/mecha/mechmove03.ogg', 50, 1) + playsound(src, 'sound/mecha/mechmove03.ogg', 50, 1) deployedpack = FALSE /obj/item/clothing/suit/space/hardsuit/flightsuit/proc/extend_flightshoes(forced = FALSE) @@ -936,7 +937,7 @@ /obj/item/clothing/suit/space/hardsuit/flightsuit/proc/retract_flightshoes(forced = FALSE) shoes.flags_1 &= ~NODROP_1 - playsound(src.loc, 'sound/mecha/mechmove03.ogg', 50, 1) + playsound(src, 'sound/mecha/mechmove03.ogg', 50, 1) if(user) user.transferItemToLoc(shoes, src, TRUE) user.update_inv_wear_suit() @@ -1092,15 +1093,16 @@ /obj/item/clothing/head/helmet/space/hardsuit/flightsuit/dropped(mob/living/carbon/human/wearer) ..() - for(var/hudtype in datahuds) - var/datum/atom_hud/H = GLOB.huds[hudtype] - H.remove_hud_from(wearer) - if(zoom) - toggle_zoom(wearer, TRUE) + if(wearer) + for(var/hudtype in datahuds) + var/datum/atom_hud/H = GLOB.huds[hudtype] + H.remove_hud_from(wearer) + if(zoom) + toggle_zoom(wearer, TRUE) /obj/item/clothing/head/helmet/space/hardsuit/flightsuit/proc/toggle_zoom(mob/living/user, force_off = FALSE) if(zoom || force_off) - user.client.change_view(world.view) + user.client.change_view(CONFIG_GET(string/default_view)) to_chat(user, "Disabling smart zooming image enhancement...") zoom = FALSE return FALSE diff --git a/code/modules/events/camerafailure.dm b/code/modules/events/camerafailure.dm index 9f85628629..cbc2d95776 100644 --- a/code/modules/events/camerafailure.dm +++ b/code/modules/events/camerafailure.dm @@ -6,11 +6,9 @@ alertadmins = 0 /datum/round_event/camera_failure - startWhen = 1 - endWhen = 2 fakeable = FALSE -/datum/round_event/camera_failure/tick() +/datum/round_event/camera_failure/start() var/iterations = 1 var/obj/machinery/camera/C = pick(GLOB.cameranet.cameras) while(prob(round(100/iterations))) diff --git a/code/modules/events/wizard/curseditems.dm b/code/modules/events/wizard/curseditems.dm index 121a0e5083..00d8c3b829 100644 --- a/code/modules/events/wizard/curseditems.dm +++ b/code/modules/events/wizard/curseditems.dm @@ -11,29 +11,29 @@ /datum/round_event/wizard/cursed_items/start() var/item_set = pick("wizardmimic", "swords", "bigfatdoobie", "boxing", "voicemodulators", "catgirls2015") - var/list/wearslots = list(slot_wear_suit, slot_shoes, slot_head, slot_wear_mask, slot_gloves, slot_ears) - var/list/loadout = list() + var/list/loadout[slots_amt] var/ruins_spaceworthiness var/ruins_wizard_loadout - loadout.len = 7 switch(item_set) if("wizardmimic") - loadout = list(/obj/item/clothing/suit/wizrobe, /obj/item/clothing/shoes/sandal/magic, /obj/item/clothing/head/wizard) + loadout[slot_wear_suit] = /obj/item/clothing/suit/wizrobe + loadout[slot_shoes] = /obj/item/clothing/shoes/sandal/magic + loadout[slot_head] = /obj/item/clothing/head/wizard ruins_spaceworthiness = 1 if("swords") - loadout[5] = /obj/item/katana/cursed + loadout[slot_hands] = /obj/item/katana/cursed if("bigfatdoobie") - loadout[4] = /obj/item/clothing/mask/cigarette/rollie/trippy + loadout[slot_wear_mask] = /obj/item/clothing/mask/cigarette/rollie/trippy ruins_spaceworthiness = 1 if("boxing") - loadout[4] = /obj/item/clothing/mask/luchador - loadout[6] = /obj/item/clothing/gloves/boxing + loadout[slot_wear_mask] = /obj/item/clothing/mask/luchador + loadout[slot_gloves] = /obj/item/clothing/gloves/boxing ruins_spaceworthiness = 1 if("voicemodulators") - loadout[4] = /obj/item/clothing/mask/chameleon + loadout[slot_wear_mask] = /obj/item/clothing/mask/chameleon if("catgirls2015") - loadout[3] = /obj/item/clothing/head/kitty + loadout[slot_head] = /obj/item/clothing/head/kitty ruins_spaceworthiness = 1 ruins_wizard_loadout = 1 @@ -44,14 +44,13 @@ continue if(item_set == "catgirls2015") //Wizard code means never having to say you're sorry H.gender = FEMALE - var/list/slots = list(H.wear_suit, H.shoes, H.head, H.wear_mask, H.gloves, H.ears) //add new slots as needed to back for(var/i in 1 to loadout.len) if(loadout[i]) var/obj/item/J = loadout[i] var/obj/item/I = new J //dumb but required because of byond throwing a fit anytime new gets too close to a list - H.temporarilyRemoveItemFromInventory(slots[i], TRUE) - H.equip_to_slot_or_del(I, wearslots[i]) - I.flags_1 |= NODROP_1 + H.dropItemToGround(H.get_item_by_slot(i), TRUE) + H.equip_to_slot_or_del(I, i) + I.flags_1 |= NODROP_1 | DROPDEL_1 I.name = "cursed " + I.name for(var/mob/living/carbon/human/H in GLOB.alive_mob_list) diff --git a/code/modules/events/wizard/imposter.dm b/code/modules/events/wizard/imposter.dm index 54d3d8ed41..4b2147bd9e 100644 --- a/code/modules/events/wizard/imposter.dm +++ b/code/modules/events/wizard/imposter.dm @@ -6,12 +6,11 @@ earliest_start = 0 /datum/round_event/wizard/imposter/start() - for(var/datum/mind/M in SSticker.mode.wizards) if(!ishuman(M.current)) continue var/mob/living/carbon/human/W = M.current - var/list/candidates = get_candidates(ROLE_WIZARD) + var/list/candidates = pollGhostCandidates("Would you like to be an imposter wizard?", ROLE_WIZARD) if(!candidates) return //Sad Trombone var/client/C = pick(candidates) @@ -28,10 +27,10 @@ var/datum/antagonist/wizard/master = M.has_antag_datum(/datum/antagonist/wizard) if(!master.wiz_team) master.create_wiz_team() - var/datum/antagonist/wizard/apprentice/imposter = new(I.mind) + var/datum/antagonist/wizard/apprentice/imposter/imposter = new(I.mind) imposter.master = M imposter.wiz_team = master.wiz_team - master.wiz_team += imposter + master.wiz_team.add_member(imposter) I.mind.add_antag_datum(imposter) //Remove if possible SSticker.mode.apprentices += I.mind diff --git a/code/modules/events/wizard/race.dm b/code/modules/events/wizard/race.dm index e054be9b08..29773d95b2 100644 --- a/code/modules/events/wizard/race.dm +++ b/code/modules/events/wizard/race.dm @@ -22,7 +22,7 @@ for(var/mob/living/carbon/human/H in GLOB.carbon_list) //yes, even the dead H.set_species(new_species) - H.real_name = new_species.random_name(H.gender,1) + H.real_name = H.dna.species.random_name(H.gender,1) H.dna.unique_enzymes = H.dna.generate_unique_enzymes() to_chat(H, "You feel somehow... different?") if(!all_the_same) diff --git a/code/modules/food_and_drinks/drinks/drinks.dm b/code/modules/food_and_drinks/drinks/drinks.dm index 5d3cd09f51..7217fe0b28 100644 --- a/code/modules/food_and_drinks/drinks/drinks.dm +++ b/code/modules/food_and_drinks/drinks/drinks.dm @@ -115,6 +115,7 @@ I.Blend(B.broken_outline, ICON_OVERLAY, rand(5), 1) I.SwapColor(rgb(255, 0, 220, 255), rgb(0, 0, 0, 0)) B.icon = I + B.name = "broken [name]" if(prob(33)) new/obj/item/shard(drop_location()) playsound(src, "shatter", 70, 1) @@ -186,7 +187,7 @@ // Formatting is the same as food. /obj/item/reagent_containers/food/drinks/coffee - name = "Robust Coffee" + name = "robust coffee" desc = "Careful, the beverage you're about to enjoy is extremely hot." icon_state = "coffee" list_reagents = list("coffee" = 30) @@ -195,7 +196,7 @@ isGlass = FALSE /obj/item/reagent_containers/food/drinks/ice - name = "Ice Cup" + name = "ice cup" desc = "Careful, cold ice, do not chew." icon_state = "coffee" list_reagents = list("ice" = 30) @@ -216,12 +217,12 @@ icon_state = "tea_empty" /obj/item/reagent_containers/food/drinks/mug/tea - name = "Duke Purple Tea" + name = "Duke Purple tea" desc = "An insult to Duke Purple is an insult to the Space Queen! Any proper gentleman will fight you, if you sully this tea." list_reagents = list("tea" = 30) /obj/item/reagent_containers/food/drinks/mug/coco - name = "Dutch Hot Coco" + name = "Dutch hot coco" desc = "Made in Space South America." list_reagents = list("hot_coco" = 30, "sugar" = 5) foodtype = SUGAR @@ -230,7 +231,7 @@ /obj/item/reagent_containers/food/drinks/dry_ramen - name = "Cup Ramen" + name = "cup ramen" desc = "Just add 10ml of water, self heats! A taste that reminds you of your school years." icon_state = "ramen" list_reagents = list("dry_ramen" = 30) @@ -238,7 +239,7 @@ isGlass = FALSE /obj/item/reagent_containers/food/drinks/beer - name = "Space Beer" + name = "space beer" desc = "Beer. In space." icon_state = "beer" list_reagents = list("beer" = 30) @@ -282,7 +283,7 @@ I.Blend(B.broken_outline, ICON_OVERLAY, rand(5), 1) I.SwapColor(rgb(255, 0, 220, 255), rgb(0, 0, 0, 0)) B.icon = I - B.name = "broken carton" + B.name = "broken [name]" B.force = 0 B.throwforce = 0 B.desc = "A carton with the bottom half burst open. Might give you a papercut." @@ -420,28 +421,28 @@ foodtype = SUGAR /obj/item/reagent_containers/food/drinks/soda_cans/tonic - name = "T-Borg's Tonic Water" + name = "T-Borg's tonic water" desc = "Quinine tastes funny, but at least it'll keep that Space Malaria away." icon_state = "tonic" list_reagents = list("tonic" = 50) foodtype = ALCOHOL /obj/item/reagent_containers/food/drinks/soda_cans/sodawater - name = "Soda Water" + name = "soda water" desc = "A can of soda water. Why not make a scotch and soda?" icon_state = "sodawater" list_reagents = list("sodawater" = 50) /obj/item/reagent_containers/food/drinks/soda_cans/lemon_lime - name = "Orange Soda" + name = "orange soda" desc = "You wanted ORANGE. It gave you Lemon Lime." icon_state = "lemon-lime" list_reagents = list("lemon_lime" = 30) foodtype = FRUIT -/obj/item/reagent_containers/food/drinks/soda_cans/lemon_lime/New() - ..() - name = "Lemon-Lime Soda" +/obj/item/reagent_containers/food/drinks/soda_cans/lemon_lime/Initialize() + . = ..() + name = "lemon-lime soda" /obj/item/reagent_containers/food/drinks/soda_cans/space_up name = "Space-Up!" @@ -485,14 +486,14 @@ list_reagents = list("pwr_game" = 30) /obj/item/reagent_containers/food/drinks/soda_cans/shamblers - name = "Shambler's Juice" + name = "Shambler's juice" desc = "~Shake me up some of that Shambler's Juice!~" icon_state = "shamblers" list_reagents = list("shamblers" = 30) foodtype = SUGAR | JUNKFOOD /obj/item/reagent_containers/food/drinks/soda_cans/air - name = "Canned Air" + name = "canned air" desc = "There is no air shortage. Do not drink." icon_state = "air" list_reagents = list("nitrogen" = 24, "oxygen" = 6) diff --git a/code/modules/food_and_drinks/drinks/drinks/bottle.dm b/code/modules/food_and_drinks/drinks/drinks/bottle.dm index 5625a752b3..005dda29ca 100644 --- a/code/modules/food_and_drinks/drinks/drinks/bottle.dm +++ b/code/modules/food_and_drinks/drinks/drinks/bottle.dm @@ -35,10 +35,10 @@ new/obj/item/shard(drop_location()) playsound(src, "shatter", 70, 1) else - B.name = "broken carton" B.force = 0 B.throwforce = 0 B.desc = "A carton with the bottom half burst open. Might give you a papercut." + B.name = "broken [name]" transfer_fingerprints_to(B) qdel(src) @@ -119,7 +119,7 @@ //Keeping this here for now, I'll ask if I should keep it here. /obj/item/broken_bottle - name = "Broken Bottle" + name = "broken bottle" desc = "A bottle with a sharp broken bottom." icon = 'icons/obj/drinks.dmi' icon_state = "broken_bottle" @@ -135,37 +135,37 @@ sharpness = IS_SHARP /obj/item/reagent_containers/food/drinks/bottle/gin - name = "Griffeater Gin" + name = "Griffeater gin" desc = "A bottle of high quality gin, produced in the New London Space Station." icon_state = "ginbottle" list_reagents = list("gin" = 100) /obj/item/reagent_containers/food/drinks/bottle/whiskey - name = "Uncle Git's Special Reserve" + name = "Uncle Git's special reserve" desc = "A premium single-malt whiskey, gently matured inside the tunnels of a nuclear shelter. TUNNEL WHISKEY RULES." icon_state = "whiskeybottle" list_reagents = list("whiskey" = 100) /obj/item/reagent_containers/food/drinks/bottle/vodka - name = "Tunguska Triple Distilled" + name = "Tunguska triple distilled" desc = "Aah, vodka. Prime choice of drink AND fuel by Russians worldwide." icon_state = "vodkabottle" list_reagents = list("vodka" = 100) /obj/item/reagent_containers/food/drinks/bottle/vodka/badminka - name = "Badminka Vodka" + name = "Badminka vodka" desc = "The label's written in Cyrillic. All you can make out is the name and a word that looks vaguely like 'Vodka'." icon_state = "badminka" list_reagents = list("vodka" = 100) /obj/item/reagent_containers/food/drinks/bottle/tequila - name = "Caccavo Guaranteed Quality Tequila" + name = "Caccavo guaranteed quality tequila" desc = "Made from premium petroleum distillates, pure thalidomide and other fine quality ingredients!" icon_state = "tequilabottle" list_reagents = list("tequila" = 100) /obj/item/reagent_containers/food/drinks/bottle/bottleofnothing - name = "Bottle of Nothing" + name = "bottle of nothing" desc = "A bottle filled with nothing." icon_state = "bottleofnothing" list_reagents = list("nothing" = 100) @@ -178,13 +178,13 @@ list_reagents = list("patron" = 100) /obj/item/reagent_containers/food/drinks/bottle/rum - name = "Captain Pete's Cuban Spiced Rum" + name = "Captain Pete's Cuban spiced rum" desc = "This isn't just rum, oh no. It's practically GRIFF in a bottle." icon_state = "rumbottle" list_reagents = list("rum" = 100) /obj/item/reagent_containers/food/drinks/bottle/holywater - name = "Flask of Holy Water" + name = "flask of holy water" desc = "A flask of the chaplain's holy water." icon_state = "holyflask" list_reagents = list("holywater" = 100) @@ -195,39 +195,39 @@ list_reagents = list("hell_water" = 100) /obj/item/reagent_containers/food/drinks/bottle/vermouth - name = "Goldeneye Vermouth" + name = "Goldeneye vermouth" desc = "Sweet, sweet dryness~" icon_state = "vermouthbottle" list_reagents = list("vermouth" = 100) /obj/item/reagent_containers/food/drinks/bottle/kahlua - name = "Robert Robust's Coffee Liqueur" + name = "Robert Robust's coffee liqueur" desc = "A widely known, Mexican coffee-flavoured liqueur. In production since 1936, HONK." icon_state = "kahluabottle" list_reagents = list("kahlua" = 100) foodtype = VEGETABLES /obj/item/reagent_containers/food/drinks/bottle/goldschlager - name = "College Girl Goldschlager" + name = "College Girl goldschlager" desc = "Because they are the only ones who will drink 100 proof cinnamon schnapps." icon_state = "goldschlagerbottle" list_reagents = list("goldschlager" = 100) /obj/item/reagent_containers/food/drinks/bottle/cognac - name = "Chateau De Baton Premium Cognac" + name = "Chateau de Baton premium cognac" desc = "A sweet and strongly alchoholic drink, made after numerous distillations and years of maturing. You might as well not scream 'SHITCURITY' this time." icon_state = "cognacbottle" list_reagents = list("cognac" = 100) /obj/item/reagent_containers/food/drinks/bottle/wine - name = "Doublebeard Bearded Special Wine" + name = "Doublebeard's bearded special wine" desc = "A faint aura of unease and asspainery surrounds the bottle." icon_state = "winebottle" list_reagents = list("wine" = 100) foodtype = FRUIT | ALCOHOL /obj/item/reagent_containers/food/drinks/bottle/absinthe - name = "Extra-Strong Absinthe" + name = "extra-strong absinthe" desc = "An strong alcoholic drink brewed and distributed by" icon_state = "absinthebottle" list_reagents = list("absinthe" = 100) @@ -272,7 +272,7 @@ /obj/item/reagent_containers/food/drinks/bottle/absinthe/premium - name = "Gwyn's Premium Absinthe" + name = "Gwyn's premium absinthe" desc = "A potent alcoholic beverage, almost makes you forget the ash in your lungs." icon_state = "absinthepremium" @@ -280,7 +280,7 @@ return /obj/item/reagent_containers/food/drinks/bottle/lizardwine - name = "Bottle of lizard wine" + name = "bottle of lizard wine" desc = "An alcoholic beverage from Space China, made by infusing lizard tails in ethanol. Inexplicably popular among command staff." icon_state = "lizardwine" list_reagents = list("lizardwine" = 100) @@ -302,7 +302,7 @@ //////////////////////////JUICES AND STUFF /////////////////////// /obj/item/reagent_containers/food/drinks/bottle/orangejuice - name = "Orange Juice" + name = "orange juice" desc = "Full of vitamins and deliciousness!" icon_state = "orangejuice" item_state = "carton" @@ -313,7 +313,7 @@ foodtype = FRUIT /obj/item/reagent_containers/food/drinks/bottle/cream - name = "Milk Cream" + name = "milk cream" desc = "It's cream. Made from milk. What else did you think you'd find in there?" icon_state = "cream" item_state = "carton" @@ -324,7 +324,7 @@ foodtype = DAIRY /obj/item/reagent_containers/food/drinks/bottle/tomatojuice - name = "Tomato Juice" + name = "tomato juice" desc = "Well, at least it LOOKS like tomato juice. You can't tell with all that redness." icon_state = "tomatojuice" item_state = "carton" @@ -335,7 +335,7 @@ foodtype = VEGETABLES /obj/item/reagent_containers/food/drinks/bottle/limejuice - name = "Lime Juice" + name = "lime juice" desc = "Sweet-sour goodness." icon_state = "limejuice" item_state = "carton" diff --git a/code/modules/food_and_drinks/food/snacks_other.dm b/code/modules/food_and_drinks/food/snacks_other.dm index 0c626ab71e..c32ebfb765 100644 --- a/code/modules/food_and_drinks/food/snacks_other.dm +++ b/code/modules/food_and_drinks/food/snacks_other.dm @@ -380,7 +380,7 @@ foodtype = VEGETABLES | FRIED | DAIRY /obj/item/reagent_containers/food/snacks/cubannachos - name = "cuban nachos" + name = "Cuban nachos" desc = "That's some dangerously spicy nachos." icon_state = "cubannachos" bonus_reagents = list("nutriment" = 2, "vitamin" = 3) diff --git a/code/modules/food_and_drinks/food/snacks_pastry.dm b/code/modules/food_and_drinks/food/snacks_pastry.dm index ef518bf5fc..284784484f 100644 --- a/code/modules/food_and_drinks/food/snacks_pastry.dm +++ b/code/modules/food_and_drinks/food/snacks_pastry.dm @@ -4,7 +4,7 @@ /obj/item/reagent_containers/food/snacks/donut name = "donut" - desc = "Goes great with Robust Coffee." + desc = "Goes great with robust coffee." icon_state = "donut1" bitesize = 5 bonus_reagents = list("sugar" = 1) diff --git a/code/modules/hydroponics/beekeeping/beebox.dm b/code/modules/hydroponics/beekeeping/beebox.dm index 141336cf5d..4bf76a1a46 100644 --- a/code/modules/hydroponics/beekeeping/beebox.dm +++ b/code/modules/hydroponics/beekeeping/beebox.dm @@ -58,6 +58,7 @@ /obj/structure/beebox/premade/New() ..() + icon_state = "beebox" var/datum/reagent/R = null if(random_reagent) R = pick(subtypesof(/datum/reagent)) @@ -80,6 +81,7 @@ /obj/structure/beebox/premade/random + icon_state = "random_beebox" random_reagent = TRUE diff --git a/code/modules/hydroponics/grown/melon.dm b/code/modules/hydroponics/grown/melon.dm index 027832de5e..5e64d716ec 100644 --- a/code/modules/hydroponics/grown/melon.dm +++ b/code/modules/hydroponics/grown/melon.dm @@ -14,6 +14,13 @@ mutatelist = list(/obj/item/seeds/watermelon/holy) reagents_add = list("water" = 0.2, "vitamin" = 0.04, "nutriment" = 0.2) +/obj/item/seeds/watermelon/suicide_act(mob/user) + user.visible_message("[user] is swallowing [src]! It looks like [user.p_theyre()] trying to commit suicide!") + user.gib() + new product(drop_location()) + qdel(src) + return MANUAL_SUICIDE + /obj/item/reagent_containers/food/snacks/grown/watermelon seed = /obj/item/seeds/watermelon name = "watermelon" diff --git a/code/modules/hydroponics/grown/random.dm b/code/modules/hydroponics/grown/random.dm index 4ba2451a5a..8f25eff215 100644 --- a/code/modules/hydroponics/grown/random.dm +++ b/code/modules/hydroponics/grown/random.dm @@ -16,9 +16,9 @@ randomize_stats() ..() if(prob(60)) - add_random_reagents() + add_random_reagents(1, 3) if(prob(50)) - add_random_traits() + add_random_traits(1, 2) add_random_plant_type(35) /obj/item/reagent_containers/food/snacks/grown/random diff --git a/code/modules/integrated_electronics/subtypes/output.dm b/code/modules/integrated_electronics/subtypes/output.dm index 7f61968c04..a1ddf2eee1 100644 --- a/code/modules/integrated_electronics/subtypes/output.dm +++ b/code/modules/integrated_electronics/subtypes/output.dm @@ -207,6 +207,15 @@ spawn_flags = IC_SPAWN_RESEARCH origin_tech = list(TECH_ENGINEERING = 2, TECH_DATA = 2, TECH_BIO = 1) +/obj/item/integrated_circuit/output/sound/vox + name = "ai vox sound circuit" + desc = "Takes a sound name as an input, and will play said sound when pulsed. This circuit is often found in AI announcement systems." + spawn_flags = IC_SPAWN_RESEARCH + +/obj/item/integrated_circuit/output/sound/vox/Initialize() + .= ..() + sounds = GLOB.vox_sounds + extended_desc = "The first input pin determines which sound is used. It uses the AI Vox Broadcast word list. So either experiment to find words that work, or ask the AI to help in figuring them out. The second pin determines the volume of sound that is played, and the third determines if the frequency of the sound will vary with each activation." /obj/item/integrated_circuit/output/text_to_speech name = "text-to-speech circuit" diff --git a/code/modules/library/random_books.dm b/code/modules/library/random_books.dm index 769c9ac66b..e101a7143a 100644 --- a/code/modules/library/random_books.dm +++ b/code/modules/library/random_books.dm @@ -1,3 +1,6 @@ +/obj/item/book/manual/random + icon_state = "random_book" + /obj/item/book/manual/random/Initialize() ..() var/static/banned_books = list(/obj/item/book/manual/random, /obj/item/book/manual/nuclear, /obj/item/book/manual/wiki) @@ -6,6 +9,7 @@ return INITIALIZE_HINT_QDEL /obj/item/book/random + icon_state = "random_book" var/amount = 1 var/category = null @@ -20,6 +24,7 @@ /obj/structure/bookcase/random var/category = null var/book_count = 2 + icon_state = "random_bookcase" anchored = TRUE state = 2 diff --git a/code/modules/mining/lavaland/ash_flora.dm b/code/modules/mining/lavaland/ash_flora.dm index 6d6587a73a..6ecdc91635 100644 --- a/code/modules/mining/lavaland/ash_flora.dm +++ b/code/modules/mining/lavaland/ash_flora.dm @@ -137,18 +137,10 @@ regrowth_time_low = 4800 regrowth_time_high = 7200 -/obj/structure/flora/ash/cacti/Crossed(mob/AM) - if(ishuman(AM) && has_gravity(loc) && prob(70)) - var/mob/living/carbon/human/H = AM - if(!H.shoes && !H.lying) //ouch, my feet. - var/picked_def_zone = pick("l_leg", "r_leg") - var/obj/item/bodypart/O = H.get_bodypart(picked_def_zone) - if(!istype(O) || (PIERCEIMMUNE in H.dna.species.species_traits)) - return - H.apply_damage(rand(3, 6), BRUTE, picked_def_zone) - H.Knockdown(40) - H.visible_message("[H] steps on a cactus!", \ - "You step on a cactus!") +/obj/structure/flora/ash/cacti/Initialize(mapload) + . = ..() + // min dmg 3, max dmg 6, prob(70) + AddComponent(/datum/component/caltrop, 3, 6, 70) /obj/item/reagent_containers/food/snacks/grown/ash_flora name = "mushroom shavings" diff --git a/code/modules/mob/dead/observer/observer.dm b/code/modules/mob/dead/observer/observer.dm index bb4c0f559b..d19f3d4bf8 100644 --- a/code/modules/mob/dead/observer/observer.dm +++ b/code/modules/mob/dead/observer/observer.dm @@ -320,7 +320,7 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp if(mind.current.key && copytext(mind.current.key,1,2)!="@") //makes sure we don't accidentally kick any clients to_chat(usr, "Another consciousness is in your body...It is resisting you.") return - client.change_view(world.view) + client.change_view(CONFIG_GET(string/default_view)) SStgui.on_transfer(src, mind.current) // Transfer NanoUIs. mind.current.key = key return 1 @@ -456,7 +456,7 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp set desc = "Change your view range." var/max_view = client.prefs.unlock_content ? GHOST_MAX_VIEW_RANGE_MEMBER : GHOST_MAX_VIEW_RANGE_DEFAULT - if(client.view == world.view) + if(client.view == CONFIG_GET(string/default_view)) var/list/views = list() for(var/i in 7 to max_view) views |= i @@ -464,7 +464,7 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp if(new_view) client.change_view(Clamp(new_view, 7, max_view)) else - client.change_view(world.view) + client.change_view(CONFIG_GET(string/default_view)) /mob/dead/observer/verb/add_view_range(input as num) set name = "Add View Range" diff --git a/code/modules/mob/living/silicon/ai/ai.dm b/code/modules/mob/living/silicon/ai/ai.dm index ed36e62492..47d5a0ffd8 100644 --- a/code/modules/mob/living/silicon/ai/ai.dm +++ b/code/modules/mob/living/silicon/ai/ai.dm @@ -817,7 +817,8 @@ return (GLOB.cameranet && GLOB.cameranet.checkTurfVis(get_turf_pixel(A))) || apc_override //AI is carded/shunted //view(src) returns nothing for carded/shunted AIs and they have x-ray vision so just use get_dist - return get_dist(src, A) <= client.view + var/list/viewscale = getviewsize(client.view) + return get_dist(src, A) <= max(viewscale[1]*0.5,viewscale[2]*0.5) /mob/living/silicon/ai/proc/relay_speech(message, atom/movable/speaker, datum/language/message_language, raw_message, radio_freq, list/spans, message_mode) raw_message = lang_treat(speaker, message_language, raw_message, spans, message_mode) diff --git a/code/modules/mob/living/silicon/pai/pai.dm b/code/modules/mob/living/silicon/pai/pai.dm index ed4e79f273..8853b07445 100644 --- a/code/modules/mob/living/silicon/pai/pai.dm +++ b/code/modules/mob/living/silicon/pai/pai.dm @@ -114,12 +114,14 @@ . = ..() + var/datum/action/innate/pai/software/SW = new var/datum/action/innate/pai/shell/AS = new /datum/action/innate/pai/shell var/datum/action/innate/pai/chassis/AC = new /datum/action/innate/pai/chassis var/datum/action/innate/pai/rest/AR = new /datum/action/innate/pai/rest var/datum/action/innate/pai/light/AL = new /datum/action/innate/pai/light var/datum/action/language_menu/ALM = new + SW.Grant(src) AS.Grant(src) AC.Grant(src) AR.Grant(src) @@ -200,6 +202,15 @@ return 0 P = owner +/datum/action/innate/pai/software + name = "Software Interface" + button_icon_state = "pai" + background_icon_state = "bg_tech" + +/datum/action/innate/pai/software/Trigger() + ..() + P.paiInterface() + /datum/action/innate/pai/shell name = "Toggle Holoform" button_icon_state = "pai_holoform" diff --git a/code/modules/mob/living/silicon/pai/software.dm b/code/modules/mob/living/silicon/pai/software.dm index 7df929f20a..e73792e705 100644 --- a/code/modules/mob/living/silicon/pai/software.dm +++ b/code/modules/mob/living/silicon/pai/software.dm @@ -22,9 +22,7 @@ "remote signaller" = 5, ) -/mob/living/silicon/pai/verb/paiInterface() - set category = "pAI Commands" - set name = "Software Interface" +/mob/living/silicon/pai/proc/paiInterface() var/dat = "" var/left_part = "" var/right_part = softwareMenu() diff --git a/code/modules/mob/living/silicon/robot/robot_movement.dm b/code/modules/mob/living/silicon/robot/robot_movement.dm index a1f0dbf4be..5c24b15267 100644 --- a/code/modules/mob/living/silicon/robot/robot_movement.dm +++ b/code/modules/mob/living/silicon/robot/robot_movement.dm @@ -1,21 +1,21 @@ -/mob/living/silicon/robot/Process_Spacemove(movement_dir = 0) - if(ionpulse()) - return 1 - return ..() - -/mob/living/silicon/robot/movement_delay() - . = ..() - var/static/config_robot_delay - if(isnull(config_robot_delay)) - config_robot_delay = CONFIG_GET(number/robot_delay) - . += speed + config_robot_delay - -/mob/living/silicon/robot/mob_negates_gravity() - return magpulse - -/mob/living/silicon/robot/mob_has_gravity() - return ..() || mob_negates_gravity() - -/mob/living/silicon/robot/experience_pressure_difference(pressure_difference, direction) - if(!magpulse) - return ..() +/mob/living/silicon/robot/Process_Spacemove(movement_dir = 0) + if(ionpulse()) + return 1 + return ..() + +/mob/living/silicon/robot/movement_delay() + . = ..() + var/static/config_robot_delay + if(isnull(config_robot_delay)) + config_robot_delay = CONFIG_GET(number/robot_delay) + . += speed + config_robot_delay + +/mob/living/silicon/robot/mob_negates_gravity() + return magpulse + +/mob/living/silicon/robot/mob_has_gravity() + return ..() || mob_negates_gravity() + +/mob/living/silicon/robot/experience_pressure_difference(pressure_difference, direction) + if(!magpulse) + return ..() diff --git a/code/modules/mob/living/silicon/say.dm b/code/modules/mob/living/silicon/say.dm index 77ce3fc18f..785d55e5f4 100644 --- a/code/modules/mob/living/silicon/say.dm +++ b/code/modules/mob/living/silicon/say.dm @@ -10,14 +10,14 @@ var/mob/living/silicon/S = src desig = trim_left(S.designation + " " + S.job) var/message_a = say_quote(message, get_spans()) - var/rendered = "Robotic Talk, [name] [message_a]" + var/rendered = "Robotic Talk, [name] [message_a]" for(var/mob/M in GLOB.player_list) if(M.binarycheck()) if(isAI(M)) var/renderedAI = "Robotic Talk, [name] ([desig]) [message_a]" to_chat(M, renderedAI) else - to_chat(M, rendered) + to_chat(M, "[rendered]") if(isobserver(M)) var/following = src // If the AI talks on binary chat, we still want to follow @@ -26,7 +26,7 @@ var/mob/living/silicon/ai/ai = src following = ai.eyeobj var/link = FOLLOW_LINK(M, following) - to_chat(M, "[link] [rendered]") + to_chat(M, "[link] [rendered]") /mob/living/silicon/binarycheck() return 1 diff --git a/code/modules/mob/living/simple_animal/friendly/cat.dm b/code/modules/mob/living/simple_animal/friendly/cat.dm index a333f22c38..42d38e40a3 100644 --- a/code/modules/mob/living/simple_animal/friendly/cat.dm +++ b/code/modules/mob/living/simple_animal/friendly/cat.dm @@ -9,8 +9,8 @@ gender = MALE speak = list("Meow!", "Esp!", "Purr!", "HSSSSS") speak_emote = list("purrs", "meows") - emote_hear = list("meows", "mews") - emote_see = list("shakes its head", "shivers") + emote_hear = list("meows.", "mews.") + emote_see = list("shakes its head.", "shivers.") speak_chance = 1 turns_per_move = 5 see_in_dark = 6 @@ -22,7 +22,7 @@ unsuitable_atmos_damage = 1 animal_species = /mob/living/simple_animal/pet/cat childtype = list(/mob/living/simple_animal/pet/cat/kitten) - butcher_results = list(/obj/item/reagent_containers/food/snacks/meat/slab = 2) + butcher_results = list(/obj/item/reagent_containers/food/snacks/meat/slab = 2, /obj/item/organ/ears/cat = 1, /obj/item/organ/tail/cat = 1) response_help = "pets" response_disarm = "gently pushes aside" response_harm = "kicks" diff --git a/code/modules/mob/login.dm b/code/modules/mob/login.dm index 1442ce332c..e7608f524b 100644 --- a/code/modules/mob/login.dm +++ b/code/modules/mob/login.dm @@ -46,7 +46,7 @@ if(client) client.click_intercept = null - client.change_view(world.view) // Resets the client.view in case it was changed. + client.change_view(CONFIG_GET(string/default_view)) // Resets the client.view in case it was changed. if(!GLOB.individual_log_list[ckey]) GLOB.individual_log_list[ckey] = logging diff --git a/code/modules/power/lighting.dm b/code/modules/power/lighting.dm index 920d2f5b52..3acac6cee5 100644 --- a/code/modules/power/lighting.dm +++ b/code/modules/power/lighting.dm @@ -2,7 +2,7 @@ // // consists of light fixtures (/obj/machinery/light) and light tube/bulb items (/obj/item/light) - +#define LIGHT_EMERGENCY_POWER_USE 0.2 //How much power emergency lights will consume per tick // status values shared between lighting fixtures and items #define LIGHT_OK 0 #define LIGHT_EMPTY 1 @@ -284,7 +284,6 @@ return ..() /obj/machinery/light/update_icon() - switch(status) // set icon_states if(LIGHT_OK) if(emergency_mode) @@ -293,18 +292,17 @@ icon_state = "[base_state][on]" if(LIGHT_EMPTY) icon_state = "[base_state]-empty" - on = FALSE if(LIGHT_BURNED) icon_state = "[base_state]-burned" - on = FALSE if(LIGHT_BROKEN) icon_state = "[base_state]-broken" - on = FALSE return // update the icon_state and luminosity of the light depending on its state /obj/machinery/light/proc/update(trigger = 1) - + switch(status) + if(LIGHT_BROKEN,LIGHT_BURNED,LIGHT_EMPTY) + on = FALSE emergency_mode = FALSE if(on) if(!light || light.light_range != brightness) @@ -318,7 +316,7 @@ else use_power = ACTIVE_POWER_USE set_light(brightness, 1, "#FFFFFF") - else if(has_emergency_power() && !turned_off()) + else if(has_emergency_power(LIGHT_EMERGENCY_POWER_USE) && !turned_off()) use_power = IDLE_POWER_USE emergency_mode = TRUE else @@ -338,8 +336,8 @@ /obj/machinery/light/process() if(has_power() && cell) - cell.charge = min(cell.maxcharge, cell.charge + 0.2) //Recharge emergency power automatically while not using it - if(emergency_mode && !use_emergency_power(0.2)) + cell.charge = min(cell.maxcharge, cell.charge + LIGHT_EMERGENCY_POWER_USE) //Recharge emergency power automatically while not using it + if(emergency_mode && !use_emergency_power(LIGHT_EMERGENCY_POWER_USE)) update(FALSE) //Disables emergency mode and sets the color to normal /obj/machinery/light/proc/burn_out() @@ -494,7 +492,7 @@ // if a light is turned off, it won't activate emergency power /obj/machinery/light/proc/turned_off() var/area/A = get_area(src) - return !A.lightswitch && A.power_light + return !A.lightswitch && A.power_light || !flickering // returns whether this light has power // true if area has power and lightswitch is on @@ -511,7 +509,7 @@ return status == LIGHT_OK // attempts to use power from the installed emergency cell, returns true if it does and false if it doesn't -/obj/machinery/light/proc/use_emergency_power(pwr = 0.2) +/obj/machinery/light/proc/use_emergency_power(pwr = LIGHT_EMERGENCY_POWER_USE) if(!has_emergency_power(pwr)) return FALSE if(cell.charge > 300) //it's meant to handle 120 W, ya doofus @@ -678,7 +676,7 @@ force = 2 throwforce = 5 w_class = WEIGHT_CLASS_TINY - var/status = 0 // LIGHT_OK, LIGHT_BURNED or LIGHT_BROKEN + var/status = LIGHT_OK // LIGHT_OK, LIGHT_BURNED or LIGHT_BROKEN var/base_state var/switchcount = 0 // number of times switched materials = list(MAT_GLASS=100) @@ -761,7 +759,7 @@ /obj/item/light/proc/shatter() if(status == LIGHT_OK || status == LIGHT_BURNED) - src.visible_message("[name] shatters.","You hear a small glass object shatter.") + visible_message("[name] shatters.","You hear a small glass object shatter.") status = LIGHT_BROKEN force = 5 playsound(src.loc, 'sound/effects/glasshit.ogg', 75, 1) diff --git a/code/modules/power/singularity/emitter.dm b/code/modules/power/singularity/emitter.dm index 7596d890e0..1c5f0a3375 100644 --- a/code/modules/power/singularity/emitter.dm +++ b/code/modules/power/singularity/emitter.dm @@ -335,7 +335,7 @@ buckled_mob.pixel_x = 0 buckled_mob.pixel_y = 0 if(buckled_mob.client) - buckled_mob.client.change_view(world.view) + buckled_mob.client.change_view(CONFIG_GET(string/default_view)) auto.Remove(buckled_mob) . = ..() diff --git a/code/modules/projectiles/gun.dm b/code/modules/projectiles/gun.dm index 085c618c42..f6435a954c 100644 --- a/code/modules/projectiles/gun.dm +++ b/code/modules/projectiles/gun.dm @@ -500,7 +500,7 @@ user.client.pixel_x = world.icon_size*_x user.client.pixel_y = world.icon_size*_y else - user.client.change_view(world.view) + user.client.change_view(CONFIG_GET(string/default_view)) user.client.pixel_x = 0 user.client.pixel_y = 0 return zoomed diff --git a/code/modules/projectiles/guns/ballistic/automatic.dm b/code/modules/projectiles/guns/ballistic/automatic.dm index 7fc37b8c56..9b7b8fb2e9 100644 --- a/code/modules/projectiles/guns/ballistic/automatic.dm +++ b/code/modules/projectiles/guns/ballistic/automatic.dm @@ -223,7 +223,7 @@ /obj/item/gun/ballistic/automatic/ar name = "\improper NT-ARG 'Boarder'" - desc = "A robust assault rile used by Nanotrasen fighting forces." + desc = "A robust assault rifle used by Nanotrasen fighting forces." icon_state = "arg" item_state = "arg" slot_flags = 0 diff --git a/code/modules/projectiles/guns/beam_rifle.dm b/code/modules/projectiles/guns/beam_rifle.dm index a88e271056..9b34d9ce0f 100644 --- a/code/modules/projectiles/guns/beam_rifle.dm +++ b/code/modules/projectiles/guns/beam_rifle.dm @@ -179,7 +179,7 @@ zoom_animating = 0 animate(current_user.client, pixel_x = 0, pixel_y = 0, 0, FALSE, LINEAR_EASING, ANIMATION_END_NOW) zoom_current_view_increase = 0 - current_user.client.change_view(world.view) + current_user.client.change_view(CONFIG_GET(string/default_view)) zooming_angle = 0 current_zoom_x = 0 current_zoom_y = 0 @@ -358,8 +358,8 @@ if(lastfire > world.time + delay) return lastfire = world.time + . = ..() stop_aiming() - return ..() /obj/item/gun/energy/beam_rifle/proc/sync_ammo() for(var/obj/item/ammo_casing/energy/beam_rifle/AC in contents) diff --git a/code/modules/reagents/chemistry/machinery/chem_dispenser.dm b/code/modules/reagents/chemistry/machinery/chem_dispenser.dm index 654b9e0e69..745843474e 100644 --- a/code/modules/reagents/chemistry/machinery/chem_dispenser.dm +++ b/code/modules/reagents/chemistry/machinery/chem_dispenser.dm @@ -59,6 +59,11 @@ recharge() dispensable_reagents = sortList(dispensable_reagents) +/obj/machinery/chem_dispenser/Destroy() + QDEL_NULL(beaker) + QDEL_NULL(cell) + return ..() + /obj/machinery/chem_dispenser/process() if(recharged < 0) @@ -303,6 +308,7 @@ if(beaker) beaker.forceMove(drop_location()) beaker = null + return ..() /obj/machinery/chem_dispenser/drinks name = "soda dispenser" diff --git a/code/modules/reagents/chemistry/machinery/chem_heater.dm b/code/modules/reagents/chemistry/machinery/chem_heater.dm index f8d2a66247..a6d958220a 100644 --- a/code/modules/reagents/chemistry/machinery/chem_heater.dm +++ b/code/modules/reagents/chemistry/machinery/chem_heater.dm @@ -13,6 +13,28 @@ var/heater_coefficient = 0.1 var/on = FALSE +/obj/machinery/chem_heater/Destroy() + QDEL_NULL(beaker) + return ..() + +/obj/machinery/chem_heater/handle_atom_del(atom/A) + . = ..() + if(A == beaker) + beaker = null + update_icon() + +/obj/machinery/chem_heater/update_icon() + if(beaker) + icon_state = "mixer1b" + else + icon_state = "mixer0b" + +/obj/machinery/chem_heater/proc/eject_beaker() + if(beaker) + beaker.forceMove(drop_location()) + beaker = null + update_icon() + /obj/machinery/chem_heater/RefreshParts() heater_coefficient = 0.1 for(var/obj/item/stock_parts/micro_laser/M in component_parts) @@ -52,12 +74,13 @@ return beaker = I to_chat(user, "You add [I] to [src].") - icon_state = "mixer1b" + update_icon() return return ..() /obj/machinery/chem_heater/on_deconstruction() eject_beaker() + return ..() /obj/machinery/chem_heater/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, \ datum/tgui/master_ui = null, datum/ui_state/state = GLOB.default_state) @@ -108,10 +131,3 @@ on = FALSE eject_beaker() . = TRUE - -/obj/machinery/chem_heater/proc/eject_beaker() - if(beaker) - beaker.forceMove(drop_location()) - beaker.reagents.handle_reactions() - beaker = null - icon_state = "mixer0b" diff --git a/code/modules/reagents/chemistry/machinery/chem_master.dm b/code/modules/reagents/chemistry/machinery/chem_master.dm index 434996fb08..3e06449e3a 100644 --- a/code/modules/reagents/chemistry/machinery/chem_master.dm +++ b/code/modules/reagents/chemistry/machinery/chem_master.dm @@ -13,7 +13,7 @@ var/obj/item/reagent_containers/beaker = null var/obj/item/storage/pill_bottle/bottle = null var/mode = 1 - var/condi = 0 + var/condi = FALSE var/screen = "home" var/analyzeVars[0] var/useramount = 30 // Last used amount @@ -23,6 +23,11 @@ add_overlay("waitlight") . = ..() +/obj/machinery/chem_master/Destroy() + QDEL_NULL(beaker) + QDEL_NULL(bottle) + return ..() + /obj/machinery/chem_master/RefreshParts() reagents.maximum_volume = 0 for(var/obj/item/reagent_containers/glass/beaker/B in component_parts) @@ -44,10 +49,22 @@ if(A == beaker) beaker = null reagents.clear_reagents() - icon_state = "mixer0" + update_icon() else if(A == bottle) bottle = null +/obj/machinery/chem_master/update_icon() + if(beaker) + icon_state = "mixer1" + else + icon_state = "mixer0" + +/obj/machinery/chem_master/proc/eject_beaker() + if(beaker) + beaker.forceMove(drop_location()) + adjust_item_drop_location(beaker) + beaker = null + update_icon() /obj/machinery/chem_master/blob_act(obj/structure/blob/B) if (prob(50)) @@ -61,15 +78,6 @@ /obj/machinery/chem_master/attackby(obj/item/I, mob/user, params) if(default_deconstruction_screwdriver(user, "mixer0_nopower", "mixer0", I)) - if(beaker) - beaker.forceMove(drop_location()) - adjust_item_drop_location(beaker) - beaker = null - reagents.clear_reagents() - if(bottle) - bottle.forceMove(drop_location()) - adjust_item_drop_location(bottle) - bottle = null return else if(exchange_parts(user, I)) @@ -94,7 +102,7 @@ beaker = I to_chat(user, "You add [I] to [src].") src.updateUsrDialog() - icon_state = "mixer1" + update_icon() else if(!condi && istype(I, /obj/item/storage/pill_bottle)) if(bottle) @@ -109,6 +117,13 @@ else return ..() +/obj/machinery/chem_master/on_deconstruction() + eject_beaker() + if(bottle) + bottle.forceMove(drop_location()) + adjust_item_drop_location(bottle) + bottle = null + return ..() /obj/machinery/chem_master/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, \ datum/tgui/master_ui = null, datum/ui_state/state = GLOB.default_state) @@ -154,13 +169,8 @@ return switch(action) if("eject") - if(beaker) - beaker.forceMove(drop_location()) - adjust_item_drop_location(beaker) - beaker = null - reagents.clear_reagents() - icon_state = "mixer0" - . = TRUE + eject_beaker() + . = TRUE if("ejectp") if(bottle) @@ -348,7 +358,7 @@ #if DM_VERSION >= 513 #warning 512 is definitely stable now, remove the old code #endif - + #if DM_VERSION >= 512 . += hex2num(md5[i]) #else @@ -361,4 +371,4 @@ /obj/machinery/chem_master/condimaster name = "CondiMaster 3000" desc = "Used to create condiments and other cooking supplies." - condi = 1 + condi = TRUE diff --git a/code/modules/reagents/chemistry/machinery/pandemic.dm b/code/modules/reagents/chemistry/machinery/pandemic.dm index 466aa047ad..f6b0f464fd 100644 --- a/code/modules/reagents/chemistry/machinery/pandemic.dm +++ b/code/modules/reagents/chemistry/machinery/pandemic.dm @@ -25,6 +25,12 @@ QDEL_NULL(beaker) return ..() +/obj/machinery/computer/pandemic/handle_atom_del(atom/A) + . = ..() + if(A == beaker) + beaker = null + update_icon() + /obj/machinery/computer/pandemic/proc/get_by_index(thing, index) if(!beaker || !beaker.reagents) return @@ -121,9 +127,10 @@ add_overlay("waitlight") /obj/machinery/computer/pandemic/proc/eject_beaker() - beaker.forceMove(drop_location()) - beaker = null - update_icon() + if(beaker) + beaker.forceMove(drop_location()) + beaker = null + update_icon() /obj/machinery/computer/pandemic/ui_interact(mob/user, ui_key = "main", datum/tgui/ui, force_open = FALSE, datum/tgui/master_ui, datum/ui_state/state = GLOB.default_state) ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open) @@ -159,8 +166,7 @@ return switch(action) if("eject_beaker") - if(beaker) - eject_beaker() + eject_beaker() . = TRUE if("empty_beaker") if(beaker) @@ -236,7 +242,5 @@ return ..() /obj/machinery/computer/pandemic/on_deconstruction() - if(beaker) - beaker.forceMove(drop_location()) - beaker = null + eject_beaker() . = ..() diff --git a/code/modules/reagents/chemistry/reagents/alcohol_reagents.dm b/code/modules/reagents/chemistry/reagents/alcohol_reagents.dm index 9321c6b015..6a3b1a1637 100644 --- a/code/modules/reagents/chemistry/reagents/alcohol_reagents.dm +++ b/code/modules/reagents/chemistry/reagents/alcohol_reagents.dm @@ -109,7 +109,7 @@ All effects don't start immediately, but rather get worse over time; the rate is color = "#664300" // rgb: 102, 67, 0 boozepwr = 45 glass_icon_state = "kahluaglass" - glass_name = "glass of RR Coffee Liquor" + glass_name = "glass of RR coffee liquor" glass_desc = "DAMN, THIS THING LOOKS ROBUST!" shot_glass_icon_state = "shotglasscream" @@ -341,7 +341,7 @@ All effects don't start immediately, but rather get worse over time; the rate is boozepwr = 25 taste_description = "burning cinnamon" glass_icon_state = "goldschlagerglass" - glass_name = "glass of Goldschlager" + glass_name = "glass of goldschlager" glass_desc = "100% proof that teen girls will drink anything with gold in it." shot_glass_icon_state = "shotglassgold" @@ -396,7 +396,7 @@ All effects don't start immediately, but rather get worse over time; the rate is boozepwr = 70 taste_description = "cola" glass_icon_state = "whiskeycolaglass" - glass_name = "Whiskey Cola" + glass_name = "whiskey cola" glass_desc = "An innocent-looking mixture of cola and Whiskey. Delicious." /datum/reagent/consumable/ethanol/martini @@ -706,7 +706,7 @@ All effects don't start immediately, but rather get worse over time; the rate is boozepwr = 70 taste_description = "soda" glass_icon_state = "whiskeysodaglass2" - glass_name = "Whiskey Soda" + glass_name = "whiskey soda" glass_desc = "Ultimate refreshment." /datum/reagent/consumable/ethanol/antifreeze @@ -785,7 +785,7 @@ All effects don't start immediately, but rather get worse over time; the rate is boozepwr = 70 taste_description = "tart bitterness" glass_icon_state = "vodkatonicglass" - glass_name = "Vodka and Tonic" + glass_name = "vodka and tonic" glass_desc = "For when a gin and tonic isn't Russian enough." @@ -797,7 +797,7 @@ All effects don't start immediately, but rather get worse over time; the rate is boozepwr = 45 taste_description = "dry, tart lemons" glass_icon_state = "ginfizzglass" - glass_name = "Gin Fizz" + glass_name = "gin fizz" glass_desc = "Refreshingly lemony, deliciously dry." @@ -870,7 +870,7 @@ All effects don't start immediately, but rather get worse over time; the rate is boozepwr = 15 taste_description = "refreshingly cold" glass_icon_state = "iced_beerglass" - glass_name = "Iced Beer" + glass_name = "iced beer" glass_desc = "A beer so frosty, the air around it freezes." /datum/reagent/consumable/ethanol/iced_beer/on_mob_life(mob/living/M) @@ -1069,7 +1069,7 @@ All effects don't start immediately, but rather get worse over time; the rate is boozepwr = 35 taste_description = "sour lemons" glass_icon_state = "whiskey_sour" - glass_name = "Whiskey Sour" + glass_name = "whiskey sour" glass_desc = "Lemon juice mixed with whiskey and a dash of sugar. Surprisingly satisfying." /datum/reagent/consumable/ethanol/hcider @@ -1081,7 +1081,7 @@ All effects don't start immediately, but rather get worse over time; the rate is boozepwr = 25 taste_description = "apples" glass_icon_state = "whiskeyglass" - glass_name = "Hard Cider" + glass_name = "hard cider" glass_desc = "Tastes like autumn." shot_glass_icon_state = "shotglassbrown" @@ -1279,5 +1279,5 @@ All effects don't start immediately, but rather get worse over time; the rate is boozepwr = 1 taste_description = "custard and alcohol" glass_icon_state = "glass_yellow" - glass_name = "Eggnog" + glass_name = "eggnog" glass_desc = "For enjoying the most wonderful time of the year." diff --git a/code/modules/reagents/chemistry/reagents/drink_reagents.dm b/code/modules/reagents/chemistry/reagents/drink_reagents.dm index 308fd47a16..b62afb80c0 100644 --- a/code/modules/reagents/chemistry/reagents/drink_reagents.dm +++ b/code/modules/reagents/chemistry/reagents/drink_reagents.dm @@ -148,7 +148,7 @@ description = "Absolutely nothing." taste_description = "nothing" glass_icon_state = "nothing" - glass_name = "Nothing" + glass_name = "nothing" glass_desc = "Absolutely nothing." shot_glass_icon_state = "shotglass" @@ -319,7 +319,7 @@ nutriment_factor = 0 taste_description = "bitter coldness" glass_icon_state = "icedcoffeeglass" - glass_name = "Iced Coffee" + glass_name = "iced coffee" glass_desc = "A drink to perk you up and refresh you!" /datum/reagent/consumable/icecoffee/on_mob_life(mob/living/M) @@ -340,7 +340,7 @@ nutriment_factor = 0 taste_description = "sweet tea" glass_icon_state = "icedteaglass" - glass_name = "Iced Tea" + glass_name = "iced tea" glass_desc = "All natural, antioxidant-rich flavour sensation." /datum/reagent/consumable/icetea/on_mob_life(mob/living/M) @@ -361,7 +361,7 @@ color = "#100800" // rgb: 16, 8, 0 taste_description = "cola" glass_icon_state = "glass_brown" - glass_name = "glass of space Cola" + glass_name = "glass of Space Cola" glass_desc = "A glass of refreshing Space Cola." /datum/reagent/consumable/space_cola/on_mob_life(mob/living/M) @@ -377,7 +377,7 @@ color = "#100800" // rgb: 16, 8, 0 taste_description = "the future" glass_icon_state = "nuka_colaglass" - glass_name = "Nuka Cola" + glass_name = "glass of Nuka Cola" glass_desc = "Don't cry, Don't raise your eye, It's only nuclear wasteland." /datum/reagent/consumable/nuka_cola/on_mob_life(mob/living/M) @@ -434,7 +434,7 @@ color = "#00FF00" // rgb: 0, 255, 0 taste_description = "cherry soda" glass_icon_state = "space-up_glass" - glass_name = "glass of Space-up" + glass_name = "glass of Space-Up" glass_desc = "Space-up. It helps you keep your cool." @@ -450,7 +450,7 @@ color = "#8CFF00" // rgb: 135, 255, 0 taste_description = "tangy lime and lemon soda" glass_icon_state = "glass_yellow" - glass_name = "glass of Lemon-Lime" + glass_name = "glass of lemon-lime" glass_desc = "You're pretty certain a real fruit has never actually touched this." @@ -481,7 +481,7 @@ color = "#f00060" // rgb: 94, 0, 38 taste_description = "carbonated metallic soda" glass_icon_state = "glass_red" - glass_name = "glass of Shambler's Juice" + glass_name = "glass of Shambler's juice" glass_desc = "Mmm mm, shambly." /datum/reagent/consumable/shamblers/on_mob_life(mob/living/M) @@ -495,7 +495,7 @@ color = "#619494" // rgb: 97, 148, 148 taste_description = "carbonated water" glass_icon_state = "glass_clear" - glass_name = "glass of Soda Water" + glass_name = "glass of soda water" glass_desc = "Soda water. Why not make a scotch and soda?" /datum/reagent/consumable/sodawater/on_mob_life(mob/living/M) @@ -512,7 +512,7 @@ color = "#0064C8" // rgb: 0, 100, 200 taste_description = "tart and fresh" glass_icon_state = "glass_clear" - glass_name = "glass of Tonic Water" + glass_name = "glass of tonic water" glass_desc = "Quinine tastes funny, but at least it'll keep that Space Malaria away." /datum/reagent/consumable/tonic/on_mob_life(mob/living/M) @@ -546,7 +546,7 @@ color = "#664300" // rgb: 102, 67, 0 taste_description = "creamy coffee" glass_icon_state = "soy_latte" - glass_name = "Soy Latte" + glass_name = "soy latte" glass_desc = "A nice and refreshing beverage while you're reading." /datum/reagent/consumable/soy_latte/on_mob_life(mob/living/M) @@ -568,7 +568,7 @@ color = "#664300" // rgb: 102, 67, 0 taste_description = "bitter cream" glass_icon_state = "cafe_latte" - glass_name = "Cafe Latte" + glass_name = "cafe latte" glass_desc = "A nice, strong and refreshing beverage while you're reading." /datum/reagent/consumable/cafe_latte/on_mob_life(mob/living/M) @@ -612,7 +612,7 @@ nutriment_factor = 4 * REAGENTS_METABOLISM taste_description = "sweet chocolate" glass_icon_state = "chocolatepudding" - glass_name = "Chocolate Pudding" + glass_name = "chocolate pudding" glass_desc = "Tasty." /datum/reagent/consumable/vanillapudding @@ -623,7 +623,7 @@ nutriment_factor = 4 * REAGENTS_METABOLISM taste_description = "sweet vanilla" glass_icon_state = "vanillapudding" - glass_name = "Vanilla Pudding" + glass_name = "vanilla pudding" glass_desc = "Tasty." /datum/reagent/consumable/cherryshake @@ -634,7 +634,7 @@ nutriment_factor = 4 * REAGENTS_METABOLISM taste_description = "creamy cherry" glass_icon_state = "cherryshake" - glass_name = "Cherry Shake" + glass_name = "cherry shake" glass_desc = "A cherry flavored milkshake." /datum/reagent/consumable/bluecherryshake @@ -645,7 +645,7 @@ nutriment_factor = 4 * REAGENTS_METABOLISM taste_description = "creamy blue cherry" glass_icon_state = "bluecherryshake" - glass_name = "Blue Cherry Shake" + glass_name = "blue cherry shake" glass_desc = "An exotic blue milkshake." /datum/reagent/consumable/pumpkin_latte @@ -656,7 +656,7 @@ nutriment_factor = 3 * REAGENTS_METABOLISM taste_description = "creamy pumpkin" glass_icon_state = "pumpkin_latte" - glass_name = "Pumpkin Latte" + glass_name = "pumpkin latte" glass_desc = "A mix of coffee and pumpkin juice." /datum/reagent/consumable/gibbfloats diff --git a/code/modules/reagents/chemistry/reagents/other_reagents.dm b/code/modules/reagents/chemistry/reagents/other_reagents.dm index f6e57d57ca..219d9df8ef 100644 --- a/code/modules/reagents/chemistry/reagents/other_reagents.dm +++ b/code/modules/reagents/chemistry/reagents/other_reagents.dm @@ -117,7 +117,7 @@ taste_description = "water" var/cooling_temperature = 2 glass_icon_state = "glass_clear" - glass_name = "glass of Water" + glass_name = "glass of water" glass_desc = "The father of all refreshments." shot_glass_icon_state = "shotglassclear" @@ -188,7 +188,7 @@ description = "Water blessed by some deity." color = "#E0E8EF" // rgb: 224, 232, 239 glass_icon_state = "glass_clear" - glass_name = "glass of Holy Water" + glass_name = "glass of holy water" glass_desc = "A glass of holy water." /datum/reagent/water/holywater/reaction_mob(mob/living/M, method=TOUCH, reac_volume) diff --git a/code/modules/reagents/chemistry/recipes/pyrotechnics.dm b/code/modules/reagents/chemistry/recipes/pyrotechnics.dm index aa97dd3180..c6cc360758 100644 --- a/code/modules/reagents/chemistry/recipes/pyrotechnics.dm +++ b/code/modules/reagents/chemistry/recipes/pyrotechnics.dm @@ -139,7 +139,6 @@ /datum/chemical_reaction/reagent_explosion/methsplosion name = "Meth explosion" id = "methboom1" - results = list("methboom1" = 1) required_temp = 380 //slightly above the meth mix time. required_reagents = list("methamphetamine" = 1) strengthdiv = 6 @@ -154,9 +153,9 @@ ..() /datum/chemical_reaction/reagent_explosion/methsplosion/methboom2 + id = "methboom2" required_reagents = list("diethylamine" = 1, "iodine" = 1, "phosphorus" = 1, "hydrogen" = 1) //diethylamine is often left over from mixing the ephedrine. - required_temp = 300 //room temperature, chilling it even a little will prevent the explosion - results = list("methboom1" = 4) // this is ugly. Sorry goof. + required_temp = 300 //room temperature, chilling it even a little will prevent the explosion /datum/chemical_reaction/sorium name = "Sorium" diff --git a/code/modules/reagents/reagent_containers/blood_pack.dm b/code/modules/reagents/reagent_containers/blood_pack.dm index a4d766539f..bc92521b93 100644 --- a/code/modules/reagents/reagent_containers/blood_pack.dm +++ b/code/modules/reagents/reagent_containers/blood_pack.dm @@ -40,6 +40,9 @@ if(51 to INFINITY) icon_state = "full" +/obj/item/reagent_containers/blood/random + icon_state = "random_bloodpack" + /obj/item/reagent_containers/blood/random/Initialize() blood_type = pick("A+", "A-", "B+", "B-", "O+", "O-", "L") . = ..() diff --git a/code/modules/research/circuitprinter.dm b/code/modules/research/circuitprinter.dm index 2e8c47231d..582efaa474 100644 --- a/code/modules/research/circuitprinter.dm +++ b/code/modules/research/circuitprinter.dm @@ -30,7 +30,7 @@ using metal and glass, it uses glass and reagents (usually sulfuric acis). var/datum/component/material_container/materials /obj/machinery/r_n_d/circuit_imprinter/Initialize() - materials = AddComponent(/datum/component/material_container, list(MAT_GLASS, MAT_GOLD, MAT_DIAMOND, MAT_METAL, MAT_BLUESPACE), + materials = AddComponent(/datum/component/material_container, list(MAT_GLASS, MAT_GOLD, MAT_DIAMOND, MAT_METAL, MAT_BLUESPACE), 0, FALSE, list(/obj/item/stack, /obj/item/ore/bluespace_crystal), CALLBACK(src, .proc/is_insertion_ready), CALLBACK(src, .proc/AfterMaterialInsert)) materials.precise_insertion = TRUE create_reagents(0) diff --git a/code/modules/research/designs/autolathe_designs.dm b/code/modules/research/designs/autolathe_designs.dm index d8ace5f9c9..39fd0bf182 100644 --- a/code/modules/research/designs/autolathe_designs.dm +++ b/code/modules/research/designs/autolathe_designs.dm @@ -800,6 +800,13 @@ build_path = /obj/item/device/slime_scanner category = list("initial", "Misc") +/datum/design/pet_carrier + name = "Pet Carrier" + id = "pet_carrier" + build_type = AUTOLATHE + materials = list(MAT_METAL = 7500, MAT_GLASS = 100) + build_path = /obj/item/pet_carrier + /datum/design/miniature_power_cell name = "Light Fixture Battery" id = "miniature_power_cell" diff --git a/code/modules/research/protolathe.dm b/code/modules/research/protolathe.dm index a675f1e550..b4412556c5 100644 --- a/code/modules/research/protolathe.dm +++ b/code/modules/research/protolathe.dm @@ -30,11 +30,13 @@ Note: Must be placed west/left of and R&D console to function. "Computer Parts" ) + var/datum/component/material_container/materials + /obj/machinery/r_n_d/protolathe/Initialize() create_reagents(0) - var/datum/component/material_container/materials = AddComponent(/datum/component/material_container, - list(MAT_METAL, MAT_GLASS, MAT_SILVER, MAT_GOLD, MAT_DIAMOND, MAT_PLASMA, MAT_URANIUM, MAT_BANANIUM, MAT_TITANIUM, MAT_BLUESPACE), + materials = AddComponent(/datum/component/material_container, + list(MAT_METAL, MAT_GLASS, MAT_SILVER, MAT_GOLD, MAT_DIAMOND, MAT_PLASMA, MAT_URANIUM, MAT_BANANIUM, MAT_TITANIUM, MAT_BLUESPACE), 0, FALSE, list(/obj/item/stack, /obj/item/ore/bluespace_crystal), CALLBACK(src, .proc/is_insertion_ready), CALLBACK(src, .proc/AfterMaterialInsert)) materials.precise_insertion = TRUE return ..() diff --git a/code/modules/research/xenobiology/xenobio_camera.dm b/code/modules/research/xenobiology/xenobio_camera.dm index 02180b273f..576ba6fe8c 100644 --- a/code/modules/research/xenobiology/xenobio_camera.dm +++ b/code/modules/research/xenobiology/xenobio_camera.dm @@ -12,7 +12,7 @@ /mob/camera/aiEye/remote/xenobio/setLoc(var/t) var/area/new_area = get_area(t) - if(new_area && new_area.name == allowed_area || istype(new_area, /area/science/xenobiology )) + if(new_area && new_area.name == allowed_area || new_area && new_area.xenobiology_compatible) return ..() else return diff --git a/code/modules/research/xenobiology/xenobiology.dm b/code/modules/research/xenobiology/xenobiology.dm index 6f9db6c8e2..b809401ed1 100644 --- a/code/modules/research/xenobiology/xenobiology.dm +++ b/code/modules/research/xenobiology/xenobiology.dm @@ -508,14 +508,14 @@ /obj/item/areaeditor/blueprints/slime name = "cerulean prints" - desc = "A one use yet of blueprints made of jelly like organic material. Renaming an area to 'Xenobiology Lab' will extend the reach of the management console." + desc = "A one use yet of blueprints made of jelly like organic material. Extends the reach of the management console." color = "#2956B2" /obj/item/areaeditor/blueprints/slime/edit_area() - var/success = ..() + ..() var/area/A = get_area(src) - if(success) - for(var/turf/T in A) - T.remove_atom_colour(WASHABLE_COLOUR_PRIORITY) - T.add_atom_colour("#2956B2", FIXED_COLOUR_PRIORITY) - qdel(src) + for(var/turf/T in A) + T.remove_atom_colour(WASHABLE_COLOUR_PRIORITY) + T.add_atom_colour("#2956B2", FIXED_COLOUR_PRIORITY) + A.xenobiology_compatible = TRUE + qdel(src) diff --git a/code/modules/shuttle/navigation_computer.dm b/code/modules/shuttle/navigation_computer.dm index dd27d40e91..cedebc8edb 100644 --- a/code/modules/shuttle/navigation_computer.dm +++ b/code/modules/shuttle/navigation_computer.dm @@ -69,7 +69,7 @@ var/mob/camera/aiEye/remote/shuttle_docker/the_eye = eyeobj user.client.images -= the_eye.placement_images user.client.images -= the_eye.placed_images - user.client.change_view(world.view) + user.client.change_view(CONFIG_GET(string/default_view)) /obj/machinery/computer/camera_advanced/shuttle_docker/proc/placeLandingSpot() if(!checkLandingSpot()) diff --git a/code/modules/shuttle/on_move.dm b/code/modules/shuttle/on_move.dm index 51c62029e0..15f0dbb011 100644 --- a/code/modules/shuttle/on_move.dm +++ b/code/modules/shuttle/on_move.dm @@ -92,7 +92,7 @@ All ShuttleMove procs go here return TRUE // Called on atoms after everything has been moved -/atom/movable/proc/afterShuttleMove(list/movement_force, shuttle_dir, shuttle_preferred_direction, move_dir, rotation) +/atom/movable/proc/afterShuttleMove(turf/oldT, list/movement_force, shuttle_dir, shuttle_preferred_direction, move_dir, rotation) if(light) update_light() if(rotation) @@ -148,7 +148,7 @@ All ShuttleMove procs go here A.air_tight = TRUE INVOKE_ASYNC(A, /obj/machinery/door/.proc/close) -/obj/machinery/door/airlock/afterShuttleMove(list/movement_force, shuttle_dir, shuttle_preferred_direction, move_dir, rotation) +/obj/machinery/door/airlock/afterShuttleMove(turf/oldT, list/movement_force, shuttle_dir, shuttle_preferred_direction, move_dir, rotation) . = ..() shuttledocked = 1 for(var/obj/machinery/door/airlock/A in range(1, src)) @@ -160,24 +160,24 @@ All ShuttleMove procs go here . |= MOVE_CONTENTS GLOB.cameranet.removeCamera(src) -/obj/machinery/camera/afterShuttleMove(list/movement_force, shuttle_dir, shuttle_preferred_direction, move_dir, rotation) +/obj/machinery/camera/afterShuttleMove(turf/oldT, list/movement_force, shuttle_dir, shuttle_preferred_direction, move_dir, rotation) . = ..() GLOB.cameranet.addCamera(src) -/obj/machinery/telecomms/afterShuttleMove(list/movement_force, shuttle_dir, shuttle_preferred_direction, move_dir, rotation) +/obj/machinery/telecomms/afterShuttleMove(turf/oldT, list/movement_force, shuttle_dir, shuttle_preferred_direction, move_dir, rotation) . = ..() listening_level = z // Update listening Z, just in case you have telecomm relay on a shuttle -/obj/machinery/mech_bay_recharge_port/afterShuttleMove(list/movement_force, shuttle_dir, shuttle_preferred_direction, move_dir) +/obj/machinery/mech_bay_recharge_port/afterShuttleMove(turf/oldT, list/movement_force, shuttle_dir, shuttle_preferred_direction, move_dir) . = ..() recharging_turf = get_step(loc, dir) -/obj/machinery/atmospherics/afterShuttleMove(list/movement_force, shuttle_dir, shuttle_preferred_direction, move_dir, rotation) +/obj/machinery/atmospherics/afterShuttleMove(turf/oldT, list/movement_force, shuttle_dir, shuttle_preferred_direction, move_dir, rotation) . = ..() if(pipe_vision_img) pipe_vision_img.loc = loc -/obj/machinery/computer/auxillary_base/afterShuttleMove(list/movement_force, shuttle_dir, shuttle_preferred_direction, move_dir, rotation) +/obj/machinery/computer/auxillary_base/afterShuttleMove(turf/oldT, list/movement_force, shuttle_dir, shuttle_preferred_direction, move_dir, rotation) . = ..() if(z == ZLEVEL_MINING) //Avoids double logging and landing on other Z-levels due to badminnery SSblackbox.record_feedback("associative", "colonies_dropped", 1, list("x" = x, "y" = y, "z" = z)) @@ -187,7 +187,7 @@ All ShuttleMove procs go here on = FALSE update_list() -/obj/machinery/gravity_generator/main/afterShuttleMove(list/movement_force, shuttle_dir, shuttle_preferred_direction, move_dir, rotation) +/obj/machinery/gravity_generator/main/afterShuttleMove(turf/oldT, list/movement_force, shuttle_dir, shuttle_preferred_direction, move_dir, rotation) . = ..() if(charge_count != 0 && charging_state != POWER_UP) on = TRUE @@ -198,7 +198,7 @@ All ShuttleMove procs go here if(. & MOVE_AREA) . |= MOVE_CONTENTS -/obj/machinery/atmospherics/afterShuttleMove(list/movement_force, shuttle_dir, shuttle_preferred_direction, move_dir, rotation) +/obj/machinery/atmospherics/afterShuttleMove(turf/oldT, list/movement_force, shuttle_dir, shuttle_preferred_direction, move_dir, rotation) . = ..() var/missing_nodes = FALSE for(DEVICE_TYPE_LOOP) @@ -227,7 +227,7 @@ All ShuttleMove procs go here // atmosinit() calls update_icon(), so we don't need to call it update_icon() -/obj/machinery/atmospherics/pipe/afterShuttleMove(list/movement_force, shuttle_dir, shuttle_preferred_direction, move_dir, rotation) +/obj/machinery/atmospherics/pipe/afterShuttleMove(turf/oldT, list/movement_force, shuttle_dir, shuttle_preferred_direction, move_dir, rotation) . = ..() var/turf/T = loc hide(T.intact) @@ -237,7 +237,7 @@ All ShuttleMove procs go here GLOB.navbeacons["[z]"] -= src GLOB.deliverybeacons -= src -/obj/machinery/navbeacon/afterShuttleMove(list/movement_force, shuttle_dir, shuttle_preferred_direction, move_dir, rotation) +/obj/machinery/navbeacon/afterShuttleMove(turf/oldT, list/movement_force, shuttle_dir, shuttle_preferred_direction, move_dir, rotation) . = ..() var/turf/T = loc hide(T.intact) @@ -249,7 +249,7 @@ All ShuttleMove procs go here GLOB.deliverybeacons += src GLOB.deliverybeacontags += location -/obj/machinery/power/terminal/afterShuttleMove(list/movement_force, shuttle_dir, shuttle_preferred_direction, move_dir, rotation) +/obj/machinery/power/terminal/afterShuttleMove(turf/oldT, list/movement_force, shuttle_dir, shuttle_preferred_direction, move_dir, rotation) . = ..() var/turf/T = src.loc if(level==1) @@ -257,7 +257,7 @@ All ShuttleMove procs go here /************************************Item move procs************************************/ -/obj/item/storage/pod/afterShuttleMove(list/movement_force, shuttle_dir, shuttle_preferred_direction, move_dir, rotation) +/obj/item/storage/pod/afterShuttleMove(turf/oldT, list/movement_force, shuttle_dir, shuttle_preferred_direction, move_dir, rotation) . = ..() unlocked = TRUE // If the pod was launched, the storage will always open. @@ -269,7 +269,7 @@ All ShuttleMove procs go here return . = ..() -/mob/afterShuttleMove(list/movement_force, shuttle_dir, shuttle_preferred_direction, move_dir, rotation) +/mob/afterShuttleMove(turf/oldT, list/movement_force, shuttle_dir, shuttle_preferred_direction, move_dir, rotation) if(!move_on_shuttle) return . = ..() @@ -279,7 +279,7 @@ All ShuttleMove procs go here shake_force *= 0.25 shake_camera(src, shake_force, 1) -/mob/living/afterShuttleMove(list/movement_force, shuttle_dir, shuttle_preferred_direction, move_dir, rotation) +/mob/living/afterShuttleMove(turf/oldT, list/movement_force, shuttle_dir, shuttle_preferred_direction, move_dir, rotation) . = ..() if(movement_force && !buckled) if(movement_force["THROW"]) @@ -307,11 +307,11 @@ All ShuttleMove procs go here if(. & MOVE_AREA) . |= MOVE_CONTENTS -/obj/structure/disposalpipe/afterShuttleMove(list/movement_force, shuttle_dir, shuttle_preferred_direction, move_dir, rotation) +/obj/structure/disposalpipe/afterShuttleMove(turf/oldT, list/movement_force, shuttle_dir, shuttle_preferred_direction, move_dir, rotation) . = ..() update() -/obj/structure/cable/afterShuttleMove(list/movement_force, shuttle_dir, shuttle_preferred_direction, move_dir, rotation) +/obj/structure/cable/afterShuttleMove(turf/oldT, list/movement_force, shuttle_dir, shuttle_preferred_direction, move_dir, rotation) . = ..() var/turf/T = loc if(level==1) diff --git a/code/modules/shuttle/shuttle.dm b/code/modules/shuttle/shuttle.dm index 2f0fb711bd..2e0248b2cd 100644 --- a/code/modules/shuttle/shuttle.dm +++ b/code/modules/shuttle/shuttle.dm @@ -631,7 +631,7 @@ if(moving_atom.loc != oldT) //fix for multi-tile objects continue moving_atom.onShuttleMove(newT, oldT, movement_force, movement_direction, old_dock, src) //atoms - moved_atoms += moving_atom + moved_atoms[moving_atom] = oldT if(move_mode & MOVE_TURF) oldT.onShuttleMove(newT, movement_force, movement_direction) //turfs @@ -665,7 +665,10 @@ for(var/i in 1 to moved_atoms.len) CHECK_TICK var/atom/movable/moved_object = moved_atoms[i] - moved_object.afterShuttleMove(movement_force, dir, preferred_direction, movement_direction, rotation)//atoms + if(QDELETED(moved_object)) + continue + var/turf/oldT = moved_atoms[moved_object] + moved_object.afterShuttleMove(oldT, movement_force, dir, preferred_direction, movement_direction, rotation)//atoms for(var/i in 1 to old_turfs.len) CHECK_TICK diff --git a/code/modules/surgery/organs/lungs.dm b/code/modules/surgery/organs/lungs.dm index 9e364e49d8..a7ea63f101 100644 --- a/code/modules/surgery/organs/lungs.dm +++ b/code/modules/surgery/organs/lungs.dm @@ -28,7 +28,8 @@ var/safe_toxins_max = 0.05 var/SA_para_min = 1 //Sleeping agent var/SA_sleep_min = 5 //Sleeping agent - var/BZ_trip_balls_min = 1 //BZ gas. + var/BZ_trip_balls_min = 1 //BZ gas + var/gas_stimulation_min = 0.002 //Nitryl and Stimulum var/oxy_breath_dam_min = MIN_TOXIC_GAS_DAMAGE var/oxy_breath_dam_max = MAX_TOXIC_GAS_DAMAGE @@ -274,14 +275,14 @@ else H.adjustFireLoss(nitryl_pp/4) gas_breathed = breath_gases[/datum/gas/nitryl][MOLES] - if (gas_breathed > GAS_STIM_MINIMUM) + if (gas_breathed > gas_stimulation_min) H.reagents.add_reagent("nitryl_gas",1) breath_gases[/datum/gas/nitryl][MOLES]-=gas_breathed gas_breathed = 0 // Stimulum gas_breathed = breath_gases[/datum/gas/stimulum][MOLES] - if (gas_breathed > GAS_STIM_MINIMUM) + if (gas_breathed > gas_stimulation_min) H.reagents.add_reagent("stimulum",1) breath_gases[/datum/gas/stimulum][MOLES]-=gas_breathed handle_breath_temperature(breath, H) diff --git a/code/modules/tooltip/tooltip.dm b/code/modules/tooltip/tooltip.dm index afafbbdf66..5110b98e8e 100644 --- a/code/modules/tooltip/tooltip.dm +++ b/code/modules/tooltip/tooltip.dm @@ -41,21 +41,21 @@ Notes: /datum/tooltip/New(client/C) if (C) - src.owner = C - src.owner << browse(file2text('code/modules/tooltip/tooltip.html'), "window=[src.control]") + owner = C + owner << browse(file2text('code/modules/tooltip/tooltip.html'), "window=[control]") ..() /datum/tooltip/proc/show(atom/movable/thing, params = null, title = null, content = null, theme = "default", special = "none") - if (!thing || !params || (!title && !content) || !src.owner || !isnum(world.icon_size)) + if (!thing || !params || (!title && !content) || !owner || !isnum(world.icon_size)) return 0 - if (!src.init) + if (!init) //Initialize some vars - src.init = 1 - src.owner << output(list2params(list(world.icon_size, src.control)), "[src.control]:tooltip.init") + init = 1 + owner << output(list2params(list(world.icon_size, control)), "[control]:tooltip.init") - src.showing = 1 + showing = 1 if (title && content) title = "

[title]

" @@ -73,18 +73,19 @@ Notes: params = {"{ "cursor": "[params]", "screenLoc": "[thing.screen_loc]" }"} //Send stuff to the tooltip - src.owner << output(list2params(list(params, src.owner.view, "[title][content]", theme, special)), "[src.control]:tooltip.update") + var/view_size = getviewsize(owner.view) + owner << output(list2params(list(params, view_size[1] , view_size[2], "[title][content]", theme, special)), "[control]:tooltip.update") //If a hide() was hit while we were showing, run hide() again to avoid stuck tooltips - src.showing = 0 - if (src.queueHide) - src.hide() + showing = 0 + if (queueHide) + hide() return 1 /datum/tooltip/proc/hide() - if (src.queueHide) + if (queueHide) addtimer(CALLBACK(src, .proc/do_hide), 1) else do_hide() diff --git a/code/modules/tooltip/tooltip.html b/code/modules/tooltip/tooltip.html index 859ee3134d..67fb8a77f1 100644 --- a/code/modules/tooltip/tooltip.html +++ b/code/modules/tooltip/tooltip.html @@ -99,7 +99,8 @@ 'tileSize': 32, 'control': '', 'params': {}, - 'clientView': 0, + 'client_view_w': 0, + 'client_view_h': 0, 'text': '', 'theme': '', 'padding': 2, @@ -121,7 +122,7 @@ //Get the real icon size according to the client view var mapWidth = map['view-size'].x, mapHeight = map['view-size'].y, - tilesShown = (tooltip.clientView * 2) + 1, + tilesShown = tooltip.client_view_w realIconSize = mapWidth / tilesShown, resizeRatio = realIconSize / tooltip.tileSize, //Calculate letterboxing offsets @@ -230,10 +231,11 @@ tooltip.hide(); }); }, - update: function(params, clientView, text, theme, special) { + update: function(params, client_vw , clien_vh , text, theme, special) { //Assign our global object tooltip.params = $.parseJSON(params); - tooltip.clientView = parseInt(clientView); + tooltip.client_view_w = parseInt(client_vw); + tooltip.client_view_h = parseInt(clien_vh); tooltip.text = text; tooltip.theme = theme; tooltip.special = special; diff --git a/code/modules/vehicles/ridden.dm b/code/modules/vehicles/ridden.dm index ea3a05470a..32975e1e0f 100644 --- a/code/modules/vehicles/ridden.dm +++ b/code/modules/vehicles/ridden.dm @@ -1,76 +1,76 @@ -/obj/vehicle/ridden - name = "ridden vehicle" - can_buckle = TRUE - max_buckled_mobs = 1 - buckle_lying = FALSE - default_driver_move = FALSE - var/legs_required = 2 - var/arms_requires = 0 //why not? - -/obj/vehicle/ridden/Initialize() - . = ..() - LoadComponent(/datum/component/riding) - -/obj/vehicle/ridden/examine(mob/user) - . = ..() - to_chat(user, "Put a key inside it by clicking it with the key. If there's a key inside, you can remove it via Alt-Click!") - -/obj/vehicle/ridden/generate_action_type(actiontype) - var/datum/action/vehicle/ridden/A = ..() - . = A - if(istype(A)) - A.vehicle_ridden_target = src - -/obj/vehicle/ridden/post_unbuckle_mob(mob/living/M) - remove_occupant(M) - return ..() - -/obj/vehicle/ridden/post_buckle_mob(mob/living/M) - add_occupant(M) - return ..() - -/obj/vehicle/ridden/attackby(obj/item/I, mob/user, params) - if(key_type && !is_key(inserted_key) && is_key(I)) - if(user.transferItemToLoc(I, src)) - to_chat(user, "You insert \the [I] into \the [src].") - if(inserted_key) //just in case there's an invalid key - inserted_key.forceMove(drop_location()) - inserted_key = I - else - to_chat(user, "[I] seems to be stuck to your hand!") - return - return ..() - -/obj/vehicle/ridden/AltClick(mob/user) - if(user.Adjacent(src) && inserted_key) - if(!is_occupant(user)) - to_chat(user, "You must be riding the [src] to remove [src]'s key!") - return - to_chat(user, "You remove \the [inserted_key] from \the [src].") - inserted_key.forceMove(drop_location()) - user.put_in_hands(inserted_key) - inserted_key = null - return ..() - -/obj/vehicle/ridden/driver_move(mob/user, direction) - if(key_type && !is_key(inserted_key)) - to_chat(user, "[src] has no key inserted!") - return FALSE - var/datum/component/riding/R = GetComponent(/datum/component/riding) - R.handle_ride(user, direction) - return ..() - -/obj/vehicle/ridden/user_buckle_mob(mob/living/M, mob/user, check_loc = TRUE) - if(user.incapacitated()) - return - for(var/atom/movable/A in get_turf(src)) - if(A.density) - if(A != src && A != M) - return - M.forceMove(get_turf(src)) - . = ..() - -/obj/vehicle/ridden/buckle_mob(mob/living/M, force = FALSE, check_loc = TRUE) - if(!force && occupant_amount() >= max_occupants) - return FALSE - return ..() +/obj/vehicle/ridden + name = "ridden vehicle" + can_buckle = TRUE + max_buckled_mobs = 1 + buckle_lying = FALSE + default_driver_move = FALSE + var/legs_required = 2 + var/arms_requires = 0 //why not? + +/obj/vehicle/ridden/Initialize() + . = ..() + LoadComponent(/datum/component/riding) + +/obj/vehicle/ridden/examine(mob/user) + . = ..() + to_chat(user, "Put a key inside it by clicking it with the key. If there's a key inside, you can remove it via Alt-Click!") + +/obj/vehicle/ridden/generate_action_type(actiontype) + var/datum/action/vehicle/ridden/A = ..() + . = A + if(istype(A)) + A.vehicle_ridden_target = src + +/obj/vehicle/ridden/post_unbuckle_mob(mob/living/M) + remove_occupant(M) + return ..() + +/obj/vehicle/ridden/post_buckle_mob(mob/living/M) + add_occupant(M) + return ..() + +/obj/vehicle/ridden/attackby(obj/item/I, mob/user, params) + if(key_type && !is_key(inserted_key) && is_key(I)) + if(user.transferItemToLoc(I, src)) + to_chat(user, "You insert \the [I] into \the [src].") + if(inserted_key) //just in case there's an invalid key + inserted_key.forceMove(drop_location()) + inserted_key = I + else + to_chat(user, "[I] seems to be stuck to your hand!") + return + return ..() + +/obj/vehicle/ridden/AltClick(mob/user) + if(user.Adjacent(src) && inserted_key) + if(!is_occupant(user)) + to_chat(user, "You must be riding the [src] to remove [src]'s key!") + return + to_chat(user, "You remove \the [inserted_key] from \the [src].") + inserted_key.forceMove(drop_location()) + user.put_in_hands(inserted_key) + inserted_key = null + return ..() + +/obj/vehicle/ridden/driver_move(mob/user, direction) + if(key_type && !is_key(inserted_key)) + to_chat(user, "[src] has no key inserted!") + return FALSE + var/datum/component/riding/R = GetComponent(/datum/component/riding) + R.handle_ride(user, direction) + return ..() + +/obj/vehicle/ridden/user_buckle_mob(mob/living/M, mob/user, check_loc = TRUE) + if(user.incapacitated()) + return + for(var/atom/movable/A in get_turf(src)) + if(A.density) + if(A != src && A != M) + return + M.forceMove(get_turf(src)) + . = ..() + +/obj/vehicle/ridden/buckle_mob(mob/living/M, force = FALSE, check_loc = TRUE) + if(!force && occupant_amount() >= max_occupants) + return FALSE + return ..() diff --git a/code/modules/vehicles/vehicle_actions.dm b/code/modules/vehicles/vehicle_actions.dm index 79a24c8b11..865834495f 100644 --- a/code/modules/vehicles/vehicle_actions.dm +++ b/code/modules/vehicles/vehicle_actions.dm @@ -1,112 +1,112 @@ -//VEHICLE DEFAULT HANDLING -/obj/vehicle/proc/generate_actions() - return - -/obj/vehicle/proc/generate_action_type(actiontype) - var/datum/action/vehicle/A = new actiontype - if(!istype(A)) - return - A.vehicle_target = src - return A - -/obj/vehicle/proc/initialize_passenger_action_type(actiontype) - autogrant_actions_passenger += actiontype - for(var/i in occupants) - grant_passenger_actions(i) //refresh - -/obj/vehicle/proc/initialize_controller_action_type(actiontype, control_flag) - LAZYINITLIST(autogrant_actions_controller["[control_flag]"]) - autogrant_actions_controller["[control_flag]"] += actiontype - for(var/i in occupants) - grant_controller_actions(i) //refresh - -/obj/vehicle/proc/grant_action_type_to_mob(actiontype, mob/m) - if(!occupants[m] || !actiontype) - return FALSE - LAZYINITLIST(occupant_actions[m]) - if(occupant_actions[m][actiontype]) - return TRUE - var/datum/action/action = generate_action_type(actiontype) - action.Grant(m) - occupant_actions[m][action.type] = action - return TRUE - -/obj/vehicle/proc/remove_action_type_from_mob(actiontype, mob/m) - if(!occupants[m] || !actiontype) - return FALSE - LAZYINITLIST(occupant_actions[m]) - if(occupant_actions[m][actiontype]) - var/datum/action/action = occupant_actions[m][actiontype] - action.Remove(m) - occupant_actions[m] -= actiontype - return TRUE - -/obj/vehicle/proc/grant_passenger_actions(mob/M) - for(var/v in autogrant_actions_passenger) - grant_action_type_to_mob(v, M) - -/obj/vehicle/proc/remove_passenger_actions(mob/M) - for(var/v in autogrant_actions_passenger) - remove_action_type_from_mob(v, M) - -/obj/vehicle/proc/grant_controller_actions(mob/M) - if(!istype(M) || !occupants[M]) - return FALSE - for(var/i in GLOB.bitflags) - if(occupants[M] & i) - grant_controller_actions_by_flag(M, i) - return TRUE - -/obj/vehicle/proc/remove_controller_actions(mob/M) - if(!istype(M) || !occupants[M]) - return FALSE - for(var/i in GLOB.bitflags) - remove_controller_actions_by_flag(M, i) - return TRUE - -/obj/vehicle/proc/grant_controller_actions_by_flag(mob/M, flag) - if(!istype(M) || !autogrant_actions_controller["[flag]"]) - return FALSE - for(var/v in autogrant_actions_controller["[flag]"]) - grant_action_type_to_mob(v, M) - return TRUE - -/obj/vehicle/proc/remove_controller_actions_by_flag(mob/M, flag) - if(!istype(M) || autogrant_actions_controller["[flag]"]) - return FALSE - for(var/v in autogrant_actions_controller["[flag]"]) - remove_action_type_from_mob(v, M) - return TRUE - -/obj/vehicle/proc/cleanup_actions_for_mob(mob/M) - if(!istype(M)) - return FALSE - LAZYINITLIST(occupant_actions[M]) - for(var/path in occupant_actions[M]) - stack_trace("Leftover action type [path] in vehicle type [type] for mob type [M.type] - THIS SHOULD NOT BE HAPPENING!") - var/datum/action/action = occupant_actions[M] - action.Remove(M) - occupant_actions -= M - return TRUE - -//ACTION DATUMS - -/datum/action/vehicle - check_flags = AB_CHECK_RESTRAINED | AB_CHECK_STUN | AB_CHECK_CONSCIOUS - icon_icon = 'icons/mob/actions/actions_vehicle.dmi' - button_icon_state = "vehicle_eject" - var/obj/vehicle/vehicle_target - -/datum/action/vehicle/sealed - var/obj/vehicle/sealed/vehicle_entered_target - -/datum/action/vehicle/sealed/climb_out - name = "Climb Out" - desc = "Climb out of your vehicle!" - -/datum/action/vehicle/sealed/climb_out/Trigger() - if(..() && istype(vehicle_entered_target)) - vehicle_entered_target.mob_try_exit(owner, owner) - -/datum/action/vehicle/ridden - var/obj/vehicle/ridden/vehicle_ridden_target +//VEHICLE DEFAULT HANDLING +/obj/vehicle/proc/generate_actions() + return + +/obj/vehicle/proc/generate_action_type(actiontype) + var/datum/action/vehicle/A = new actiontype + if(!istype(A)) + return + A.vehicle_target = src + return A + +/obj/vehicle/proc/initialize_passenger_action_type(actiontype) + autogrant_actions_passenger += actiontype + for(var/i in occupants) + grant_passenger_actions(i) //refresh + +/obj/vehicle/proc/initialize_controller_action_type(actiontype, control_flag) + LAZYINITLIST(autogrant_actions_controller["[control_flag]"]) + autogrant_actions_controller["[control_flag]"] += actiontype + for(var/i in occupants) + grant_controller_actions(i) //refresh + +/obj/vehicle/proc/grant_action_type_to_mob(actiontype, mob/m) + if(!occupants[m] || !actiontype) + return FALSE + LAZYINITLIST(occupant_actions[m]) + if(occupant_actions[m][actiontype]) + return TRUE + var/datum/action/action = generate_action_type(actiontype) + action.Grant(m) + occupant_actions[m][action.type] = action + return TRUE + +/obj/vehicle/proc/remove_action_type_from_mob(actiontype, mob/m) + if(!occupants[m] || !actiontype) + return FALSE + LAZYINITLIST(occupant_actions[m]) + if(occupant_actions[m][actiontype]) + var/datum/action/action = occupant_actions[m][actiontype] + action.Remove(m) + occupant_actions[m] -= actiontype + return TRUE + +/obj/vehicle/proc/grant_passenger_actions(mob/M) + for(var/v in autogrant_actions_passenger) + grant_action_type_to_mob(v, M) + +/obj/vehicle/proc/remove_passenger_actions(mob/M) + for(var/v in autogrant_actions_passenger) + remove_action_type_from_mob(v, M) + +/obj/vehicle/proc/grant_controller_actions(mob/M) + if(!istype(M) || !occupants[M]) + return FALSE + for(var/i in GLOB.bitflags) + if(occupants[M] & i) + grant_controller_actions_by_flag(M, i) + return TRUE + +/obj/vehicle/proc/remove_controller_actions(mob/M) + if(!istype(M) || !occupants[M]) + return FALSE + for(var/i in GLOB.bitflags) + remove_controller_actions_by_flag(M, i) + return TRUE + +/obj/vehicle/proc/grant_controller_actions_by_flag(mob/M, flag) + if(!istype(M) || !autogrant_actions_controller["[flag]"]) + return FALSE + for(var/v in autogrant_actions_controller["[flag]"]) + grant_action_type_to_mob(v, M) + return TRUE + +/obj/vehicle/proc/remove_controller_actions_by_flag(mob/M, flag) + if(!istype(M) || autogrant_actions_controller["[flag]"]) + return FALSE + for(var/v in autogrant_actions_controller["[flag]"]) + remove_action_type_from_mob(v, M) + return TRUE + +/obj/vehicle/proc/cleanup_actions_for_mob(mob/M) + if(!istype(M)) + return FALSE + LAZYINITLIST(occupant_actions[M]) + for(var/path in occupant_actions[M]) + stack_trace("Leftover action type [path] in vehicle type [type] for mob type [M.type] - THIS SHOULD NOT BE HAPPENING!") + var/datum/action/action = occupant_actions[M] + action.Remove(M) + occupant_actions -= M + return TRUE + +//ACTION DATUMS + +/datum/action/vehicle + check_flags = AB_CHECK_RESTRAINED | AB_CHECK_STUN | AB_CHECK_CONSCIOUS + icon_icon = 'icons/mob/actions/actions_vehicle.dmi' + button_icon_state = "vehicle_eject" + var/obj/vehicle/vehicle_target + +/datum/action/vehicle/sealed + var/obj/vehicle/sealed/vehicle_entered_target + +/datum/action/vehicle/sealed/climb_out + name = "Climb Out" + desc = "Climb out of your vehicle!" + +/datum/action/vehicle/sealed/climb_out/Trigger() + if(..() && istype(vehicle_entered_target)) + vehicle_entered_target.mob_try_exit(owner, owner) + +/datum/action/vehicle/ridden + var/obj/vehicle/ridden/vehicle_ridden_target diff --git a/code/modules/vehicles/vehicle_key.dm b/code/modules/vehicles/vehicle_key.dm index 204a10bd17..e34ad9253d 100644 --- a/code/modules/vehicles/vehicle_key.dm +++ b/code/modules/vehicles/vehicle_key.dm @@ -1,15 +1,15 @@ -/obj/item/key - name = "key" - desc = "A small grey key." - icon = 'icons/obj/vehicles.dmi' - icon_state = "key" - w_class = WEIGHT_CLASS_TINY - -/obj/item/key/security - desc = "A keyring with a small steel key, and a rubber stun baton accessory." - icon_state = "keysec" - -/obj/item/key/janitor - desc = "A keyring with a small steel key, and a pink fob reading \"Pussy Wagon\"." - icon_state = "keyjanitor" - +/obj/item/key + name = "key" + desc = "A small grey key." + icon = 'icons/obj/vehicles.dmi' + icon_state = "key" + w_class = WEIGHT_CLASS_TINY + +/obj/item/key/security + desc = "A keyring with a small steel key, and a rubber stun baton accessory." + icon_state = "keysec" + +/obj/item/key/janitor + desc = "A keyring with a small steel key, and a pink fob reading \"Pussy Wagon\"." + icon_state = "keyjanitor" + diff --git a/config/config.txt b/config/config.txt index a05e463f45..fb648a5fa9 100644 --- a/config/config.txt +++ b/config/config.txt @@ -386,3 +386,10 @@ DISABLE_HIGH_POP_MC_MODE_AMOUNT 60 ## Uncomment to set the number of /world/Reboot()s before the DreamDaemon restarts itself. 0 means restart every round. Requires tgstation server tools. #ROUNDS_UNTIL_HARD_RESTART 10 + + +##Default screen resolution, in tiles. +## By default, this is 15x15, which gets simplified to 7 by BYOND, as it is a 1:1 screen ratio. +## For reference, Goonstation uses a resolution of 21x15 for it's widescreen mode. +## Do note that changing this value will affect the title screen. The title screen will have to be updated manually if this is changed. +DEFAULT_VIEW 15x15 diff --git a/html/changelogs/AutoChangeLog-pr-4176.yml b/html/changelogs/AutoChangeLog-pr-4176.yml new file mode 100644 index 0000000000..76ccbf0925 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-4176.yml @@ -0,0 +1,8 @@ +author: "Toriate" +delete-after: True +changes: + - rscadd: "Added Lavaknights, a new ghost role of cat people in knight armor." + - rscadd: "Added Hypereutactic blades, NEBs on steroids." + - tweak: "Made NEBs alt click to recolor +wip: Added lavaknight spawners. Someone else needs to add it in to a map or ruin properly." + - imageadd: "added sprites for hypereutactic blades" diff --git a/html/changelogs/AutoChangeLog-pr-4260.yml b/html/changelogs/AutoChangeLog-pr-4260.yml new file mode 100644 index 0000000000..1880edb973 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-4260.yml @@ -0,0 +1,4 @@ +author: "Xhuis" +delete-after: True +changes: + - rscadd: "You can now make pet carriers from the autolathe, to carry around chef meat and other small animals without having to drag them. The HoP, captain, and CMO also start with carriers in their lockers for their pets." diff --git a/html/changelogs/AutoChangeLog-pr-4261.yml b/html/changelogs/AutoChangeLog-pr-4261.yml new file mode 100644 index 0000000000..d7b0bcebf5 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-4261.yml @@ -0,0 +1,4 @@ +author: "Fox McCloud" +delete-after: True +changes: + - tweak: "Slime blueprints can now make an area compatible with Xenobio consoles, regardless of the name of the new area" diff --git a/html/changelogs/AutoChangeLog-pr-4264.yml b/html/changelogs/AutoChangeLog-pr-4264.yml new file mode 100644 index 0000000000..3a3b5c1f42 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-4264.yml @@ -0,0 +1,5 @@ +author: "CitadelStationBot" +delete-after: True +changes: + - rscadd: "You now can get a medal for wasting hours talking to the secret debug tile." + - bugfix: "Fixed runtime for the tile when poly's speech file doesn't exist." diff --git a/html/changelogs/AutoChangeLog-pr-4266.yml b/html/changelogs/AutoChangeLog-pr-4266.yml new file mode 100644 index 0000000000..e66348d5b4 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-4266.yml @@ -0,0 +1,5 @@ +author: "CitadelStationBot" +delete-after: True +changes: + - bugfix: "Fixed the camera failure, race swap, cursed items, and imposter wizard random events" + - tweak: "The cursed items event no longer nullspaces items" diff --git a/html/changelogs/AutoChangeLog-pr-4267.yml b/html/changelogs/AutoChangeLog-pr-4267.yml new file mode 100644 index 0000000000..97e3a17b9a --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-4267.yml @@ -0,0 +1,4 @@ +author: "MrDoomBringer" +delete-after: True +changes: + - imageadd: "All stations have been outfitted with brand new Smoke Machines! They have nicer sprites now!" diff --git a/html/changelogs/AutoChangeLog-pr-4270.yml b/html/changelogs/AutoChangeLog-pr-4270.yml new file mode 100644 index 0000000000..06c99c93ee --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-4270.yml @@ -0,0 +1,4 @@ +author: "deathride58" +delete-after: True +changes: + - config: "The default view range can now be defined in the config. The default is 15x15, which is simplified to 7 by BYOND. For reference, Goonstation's widescreen range is 21x15. Do note that changing this value will affect the title screen. The title screen images and the title screen area on the Centcom z-level will have to be updated if the default view range is changed." diff --git a/html/changelogs/AutoChangeLog-pr-4274.yml b/html/changelogs/AutoChangeLog-pr-4274.yml new file mode 100644 index 0000000000..b1915f089b --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-4274.yml @@ -0,0 +1,4 @@ +author: "Dax Dupont" +delete-after: True +changes: + - bugfix: "Fixed observer chat flavor of silicon chat." diff --git a/html/changelogs/AutoChangeLog-pr-4279.yml b/html/changelogs/AutoChangeLog-pr-4279.yml new file mode 100644 index 0000000000..cddc887068 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-4279.yml @@ -0,0 +1,4 @@ +author: "Dax Dupont" +delete-after: True +changes: + - bugfix: "Grilles now no longer revert to a pre-broken icon state when you hit them after they broke." diff --git a/html/changelogs/AutoChangeLog-pr-4283.yml b/html/changelogs/AutoChangeLog-pr-4283.yml new file mode 100644 index 0000000000..a96b866609 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-4283.yml @@ -0,0 +1,4 @@ +author: "CitadelStationBot" +delete-after: True +changes: + - tweak: "The pAI software interface is now accessible via an action button." diff --git a/html/changelogs/AutoChangeLog-pr-4286.yml b/html/changelogs/AutoChangeLog-pr-4286.yml new file mode 100644 index 0000000000..83ede8f21d --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-4286.yml @@ -0,0 +1,4 @@ +author: "CitadelStationBot" +delete-after: True +changes: + - bugfix: "External airlocks of the mining base and gulag are now cycle-linked." diff --git a/html/changelogs/AutoChangeLog-pr-4287.yml b/html/changelogs/AutoChangeLog-pr-4287.yml new file mode 100644 index 0000000000..55bbeb05c2 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-4287.yml @@ -0,0 +1,4 @@ +author: "XDTM" +delete-after: True +changes: + - tweak: "Instead of activating randomly on speech, Godwoken Syndrome randomly grants inspiration, causing the next message to be a Voice of God." diff --git a/html/changelogs/AutoChangeLog-pr-4289.yml b/html/changelogs/AutoChangeLog-pr-4289.yml new file mode 100644 index 0000000000..d0da6e0f58 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-4289.yml @@ -0,0 +1,5 @@ +author: "CitadelStationBot" +delete-after: True +changes: + - rscadd: "Nanotrasen would like to remind crewmembers and especially medical personnel to stand clear of cadeavers before applying a defibrillator shock. (You get shocked if you're pulling/grabbing someone being defibbed.)" + - tweak: "defib shock/charge sounds upped from 50% to 75%." diff --git a/html/changelogs/AutoChangeLog-pr-4290.yml b/html/changelogs/AutoChangeLog-pr-4290.yml new file mode 100644 index 0000000000..a7a034433f --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-4290.yml @@ -0,0 +1,4 @@ +author: "Swindly" +delete-after: True +changes: + - rscadd: "You can kill yourself with a few more items." diff --git a/html/changelogs/AutoChangeLog-pr-4292.yml b/html/changelogs/AutoChangeLog-pr-4292.yml new file mode 100644 index 0000000000..14dda4b668 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-4292.yml @@ -0,0 +1,4 @@ +author: "Xhuis" +delete-after: True +changes: + - tweak: "Flickering lights will now actually flicker and not go between emergency lights and normal lighting." diff --git a/html/changelogs/AutoChangeLog-pr-4296.yml b/html/changelogs/AutoChangeLog-pr-4296.yml new file mode 100644 index 0000000000..1e87a3fdaf --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-4296.yml @@ -0,0 +1,4 @@ +author: "Xhuis" +delete-after: True +changes: + - bugfix: "Emergency lights no longer stay on forever in some cases." diff --git a/html/changelogs/AutoChangeLog-pr-4306.yml b/html/changelogs/AutoChangeLog-pr-4306.yml new file mode 100644 index 0000000000..0a6361f11d --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-4306.yml @@ -0,0 +1,4 @@ +author: "Improvedname" +delete-after: True +changes: + - tweak: "cats now drop their ears and tail when butchered." diff --git a/html/changelogs/AutoChangeLog-pr-4308.yml b/html/changelogs/AutoChangeLog-pr-4308.yml new file mode 100644 index 0000000000..5f277e0e53 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-4308.yml @@ -0,0 +1,4 @@ +author: "CitadelStationBot" +delete-after: True +changes: + - bugfix: "Booze-o-mats have beer" diff --git a/html/changelogs/AutoChangeLog-pr-4312.yml b/html/changelogs/AutoChangeLog-pr-4312.yml new file mode 100644 index 0000000000..8c05f5d79e --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-4312.yml @@ -0,0 +1,4 @@ +author: "Robustin" +delete-after: True +changes: + - bugfix: "Modes not in rotation have had their \"false report\" weights for the Command Report standardized" diff --git a/html/changelogs/AutoChangeLog-pr-4314.yml b/html/changelogs/AutoChangeLog-pr-4314.yml new file mode 100644 index 0000000000..e471271981 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-4314.yml @@ -0,0 +1,7 @@ +author: "CitadelStationBot" +delete-after: True +changes: + - bugfix: "flightsuits should no longer disappear when you take them off involuntarily" + - bugfix: "beam rifles actually fire striaght now" + - bugfix: "click catchers now actually work" + - bugfix: "you no longer see space in areas you normally can't see, instead of black. in reality you can still see space but it's faint enough that you can't tell so I'll say I fixed it." diff --git a/icons/effects/vanguard_target.dmi b/icons/effects/vanguard_target.dmi index 73ba014e2d..5220c325e5 100644 Binary files a/icons/effects/vanguard_target.dmi and b/icons/effects/vanguard_target.dmi differ diff --git a/icons/emoji.dmi b/icons/emoji.dmi index 9d3e0630a7..b0434f431f 100644 Binary files a/icons/emoji.dmi and b/icons/emoji.dmi differ diff --git a/icons/mob/actions.dmi b/icons/mob/actions.dmi index 0255204f60..3a7b0648fd 100644 Binary files a/icons/mob/actions.dmi and b/icons/mob/actions.dmi differ diff --git a/icons/mob/actions/actions_clockcult.dmi b/icons/mob/actions/actions_clockcult.dmi index 19fd68f836..4aad4ba569 100644 Binary files a/icons/mob/actions/actions_clockcult.dmi and b/icons/mob/actions/actions_clockcult.dmi differ diff --git a/icons/mob/feet.dmi b/icons/mob/feet.dmi index de8587dba5..2eab8fa78e 100644 Binary files a/icons/mob/feet.dmi and b/icons/mob/feet.dmi differ diff --git a/icons/mob/head.dmi b/icons/mob/head.dmi index 89eb9dbcbc..3aa655b574 100644 Binary files a/icons/mob/head.dmi and b/icons/mob/head.dmi differ diff --git a/icons/mob/hud.dmi b/icons/mob/hud.dmi index 0cdee31ae1..70988dbef5 100644 Binary files a/icons/mob/hud.dmi and b/icons/mob/hud.dmi differ diff --git a/icons/mob/inhands/clothing_lefthand.dmi b/icons/mob/inhands/clothing_lefthand.dmi index 38c89769d2..76adebdc11 100644 Binary files a/icons/mob/inhands/clothing_lefthand.dmi and b/icons/mob/inhands/clothing_lefthand.dmi differ diff --git a/icons/mob/inhands/clothing_righthand.dmi b/icons/mob/inhands/clothing_righthand.dmi index c14fbb3fb2..a12053ae1d 100644 Binary files a/icons/mob/inhands/clothing_righthand.dmi and b/icons/mob/inhands/clothing_righthand.dmi differ diff --git a/icons/mob/inhands/items_lefthand.dmi b/icons/mob/inhands/items_lefthand.dmi index 198c2ee663..9a7b318e19 100644 Binary files a/icons/mob/inhands/items_lefthand.dmi and b/icons/mob/inhands/items_lefthand.dmi differ diff --git a/icons/mob/inhands/items_righthand.dmi b/icons/mob/inhands/items_righthand.dmi index cef6409ca2..9d9350e644 100644 Binary files a/icons/mob/inhands/items_righthand.dmi and b/icons/mob/inhands/items_righthand.dmi differ diff --git a/icons/mob/mask.dmi b/icons/mob/mask.dmi index 3854f252eb..e83588d5ed 100644 Binary files a/icons/mob/mask.dmi and b/icons/mob/mask.dmi differ diff --git a/icons/mob/neck.dmi b/icons/mob/neck.dmi index b5b851a8d5..59635b8c7d 100644 Binary files a/icons/mob/neck.dmi and b/icons/mob/neck.dmi differ diff --git a/icons/mob/screen_cyborg.dmi b/icons/mob/screen_cyborg.dmi index e9fd4ed401..fc236ac7e2 100644 Binary files a/icons/mob/screen_cyborg.dmi and b/icons/mob/screen_cyborg.dmi differ diff --git a/icons/mob/screen_full.dmi b/icons/mob/screen_full.dmi index 988bf59592..502e9ad3f9 100644 Binary files a/icons/mob/screen_full.dmi and b/icons/mob/screen_full.dmi differ diff --git a/icons/mob/screen_gen.dmi b/icons/mob/screen_gen.dmi index 40500e84a8..5a088e451f 100644 Binary files a/icons/mob/screen_gen.dmi and b/icons/mob/screen_gen.dmi differ diff --git a/icons/mob/suit.dmi b/icons/mob/suit.dmi index c251b93f2e..241db46d08 100644 Binary files a/icons/mob/suit.dmi and b/icons/mob/suit.dmi differ diff --git a/icons/obj/Cryogenic2.dmi b/icons/obj/Cryogenic2.dmi new file mode 100644 index 0000000000..9d7b7510c5 Binary files /dev/null and b/icons/obj/Cryogenic2.dmi differ diff --git a/icons/obj/assemblies/electronic_components.dmi b/icons/obj/assemblies/electronic_components.dmi index cdfa386233..cc0367b682 100644 Binary files a/icons/obj/assemblies/electronic_components.dmi and b/icons/obj/assemblies/electronic_components.dmi differ diff --git a/icons/obj/bedsheets.dmi b/icons/obj/bedsheets.dmi index 17dc5b8fb2..d492ae52f6 100644 Binary files a/icons/obj/bedsheets.dmi and b/icons/obj/bedsheets.dmi differ diff --git a/icons/obj/biogenerator.dmi b/icons/obj/biogenerator.dmi new file mode 100644 index 0000000000..7989d6f355 Binary files /dev/null and b/icons/obj/biogenerator.dmi differ diff --git a/icons/obj/bloodpack.dmi b/icons/obj/bloodpack.dmi index 423b5bb641..ac879aa33c 100644 Binary files a/icons/obj/bloodpack.dmi and b/icons/obj/bloodpack.dmi differ diff --git a/icons/obj/chemical.dmi b/icons/obj/chemical.dmi index 3507d9db53..367be13b3b 100644 Binary files a/icons/obj/chemical.dmi and b/icons/obj/chemical.dmi differ diff --git a/icons/obj/cigarettes.dmi b/icons/obj/cigarettes.dmi index ed8f37c4da..76ac7bd0a8 100644 Binary files a/icons/obj/cigarettes.dmi and b/icons/obj/cigarettes.dmi differ diff --git a/icons/obj/clockwork_objects.dmi b/icons/obj/clockwork_objects.dmi index 561359959b..784c0f55eb 100644 Binary files a/icons/obj/clockwork_objects.dmi and b/icons/obj/clockwork_objects.dmi differ diff --git a/icons/obj/cloning.dmi b/icons/obj/cloning.dmi new file mode 100644 index 0000000000..5aa439df6b Binary files /dev/null and b/icons/obj/cloning.dmi differ diff --git a/icons/obj/clothing/accessories.dmi b/icons/obj/clothing/accessories.dmi index 4c3c0fe5ce..63c036ce14 100644 Binary files a/icons/obj/clothing/accessories.dmi and b/icons/obj/clothing/accessories.dmi differ diff --git a/icons/obj/clothing/cloaks.dmi b/icons/obj/clothing/cloaks.dmi index 31aab0ae26..dd1ae7d727 100644 Binary files a/icons/obj/clothing/cloaks.dmi and b/icons/obj/clothing/cloaks.dmi differ diff --git a/icons/obj/clothing/gloves.dmi b/icons/obj/clothing/gloves.dmi index 48f37887cf..6c193f1044 100644 Binary files a/icons/obj/clothing/gloves.dmi and b/icons/obj/clothing/gloves.dmi differ diff --git a/icons/obj/clothing/hats.dmi b/icons/obj/clothing/hats.dmi index 6ec16c836f..2a6d2004b3 100644 Binary files a/icons/obj/clothing/hats.dmi and b/icons/obj/clothing/hats.dmi differ diff --git a/icons/obj/clothing/masks.dmi b/icons/obj/clothing/masks.dmi index 786a8c7fd0..b1d7a7106d 100644 Binary files a/icons/obj/clothing/masks.dmi and b/icons/obj/clothing/masks.dmi differ diff --git a/icons/obj/clothing/neck.dmi b/icons/obj/clothing/neck.dmi index c41db68326..0f3668ce10 100644 Binary files a/icons/obj/clothing/neck.dmi and b/icons/obj/clothing/neck.dmi differ diff --git a/icons/obj/clothing/shoes.dmi b/icons/obj/clothing/shoes.dmi index 2cf675c571..77b62691d2 100644 Binary files a/icons/obj/clothing/shoes.dmi and b/icons/obj/clothing/shoes.dmi differ diff --git a/icons/obj/clothing/suits.dmi b/icons/obj/clothing/suits.dmi index d0326b1141..f44fc29f7c 100644 Binary files a/icons/obj/clothing/suits.dmi and b/icons/obj/clothing/suits.dmi differ diff --git a/icons/obj/custom.dmi b/icons/obj/custom.dmi index 8fe4c9619b..6c1dabef23 100644 Binary files a/icons/obj/custom.dmi and b/icons/obj/custom.dmi differ diff --git a/icons/obj/decals.dmi b/icons/obj/decals.dmi index 0669549b02..31e700d23d 100644 Binary files a/icons/obj/decals.dmi and b/icons/obj/decals.dmi differ diff --git a/icons/obj/device.dmi b/icons/obj/device.dmi index 876f747fc1..88aa6f7985 100644 Binary files a/icons/obj/device.dmi and b/icons/obj/device.dmi differ diff --git a/icons/obj/flora/_flora.dmi b/icons/obj/flora/_flora.dmi new file mode 100644 index 0000000000..d3e800576e Binary files /dev/null and b/icons/obj/flora/_flora.dmi differ diff --git a/icons/obj/grenade.dmi b/icons/obj/grenade.dmi index 7d413895ca..7f4d65e081 100644 Binary files a/icons/obj/grenade.dmi and b/icons/obj/grenade.dmi differ diff --git a/icons/obj/guns/bayonets.dmi b/icons/obj/guns/bayonets.dmi index 176005b7d7..32b5448b8e 100644 Binary files a/icons/obj/guns/bayonets.dmi and b/icons/obj/guns/bayonets.dmi differ diff --git a/icons/obj/hydroponics/equipment.dmi b/icons/obj/hydroponics/equipment.dmi index ad5f8bc863..3d125d68c7 100644 Binary files a/icons/obj/hydroponics/equipment.dmi and b/icons/obj/hydroponics/equipment.dmi differ diff --git a/icons/obj/items_and_weapons.dmi b/icons/obj/items_and_weapons.dmi index 636d895450..446b093167 100644 Binary files a/icons/obj/items_and_weapons.dmi and b/icons/obj/items_and_weapons.dmi differ diff --git a/icons/obj/library.dmi b/icons/obj/library.dmi index 2048725e56..776bf7a9ec 100644 Binary files a/icons/obj/library.dmi and b/icons/obj/library.dmi differ diff --git a/icons/obj/machines/research.dmi b/icons/obj/machines/research.dmi index cd74eed322..a150880d39 100644 Binary files a/icons/obj/machines/research.dmi and b/icons/obj/machines/research.dmi differ diff --git a/icons/obj/pda.dmi b/icons/obj/pda.dmi index 5404b908c6..241bb46b98 100644 Binary files a/icons/obj/pda.dmi and b/icons/obj/pda.dmi differ diff --git a/icons/obj/pet_carrier.dmi b/icons/obj/pet_carrier.dmi new file mode 100644 index 0000000000..340636056c Binary files /dev/null and b/icons/obj/pet_carrier.dmi differ diff --git a/icons/obj/plushes.dmi b/icons/obj/plushes.dmi index 7eec51e46e..f0eb817549 100644 Binary files a/icons/obj/plushes.dmi and b/icons/obj/plushes.dmi differ diff --git a/icons/obj/storage.dmi b/icons/obj/storage.dmi index f563af642f..dadf843041 100644 Binary files a/icons/obj/storage.dmi and b/icons/obj/storage.dmi differ diff --git a/icons/obj/suitstorage.dmi b/icons/obj/suitstorage.dmi new file mode 100644 index 0000000000..e61f9567c6 Binary files /dev/null and b/icons/obj/suitstorage.dmi differ diff --git a/icons/obj/surgery.dmi b/icons/obj/surgery.dmi index 18bbcb3610..d18a1bf262 100755 Binary files a/icons/obj/surgery.dmi and b/icons/obj/surgery.dmi differ diff --git a/icons/obj/vending.dmi b/icons/obj/vending.dmi index c7b9bbcdc8..a1471e6418 100644 Binary files a/icons/obj/vending.dmi and b/icons/obj/vending.dmi differ diff --git a/icons/obj/vending_restock.dmi b/icons/obj/vending_restock.dmi index 7f8289a087..a59fdd0f52 100644 Binary files a/icons/obj/vending_restock.dmi and b/icons/obj/vending_restock.dmi differ diff --git a/modular_citadel/citadel_ghostrole_spawners.dm b/modular_citadel/citadel_ghostrole_spawners.dm new file mode 100644 index 0000000000..b0cddbd594 --- /dev/null +++ b/modular_citadel/citadel_ghostrole_spawners.dm @@ -0,0 +1,43 @@ +/obj/effect/mob_spawn/human/lavaknight + name = "odd cryogenics pod" + desc = "A humming cryo pod. You can barely recognise a faint glow underneath the built up ice. The machine is attempting to wake up its occupant." + mob_name = "a displaced knight from another dimension" + icon = 'icons/obj/machines/sleeper.dmi' + icon_state = "sleeper" + roundstart = FALSE + death = FALSE + random = TRUE + outfit = /datum/outfit/lavaknight + mob_species = /datum/species/human + flavour_text = "You are a knight who conveniently has some form of retrograde amnesia. \ + You cannot remember where you came from. However, a few things remain burnt into your mind, most prominently a vow to never harm another sapient being under any circumstances unless it is hellbent on ending your life. \ + Remember: hostile creatures and such are fair game for attacking, but under no circumstances are you to attack anything capable of thought and/or speech unless it has made it its life's calling to chase you to the ends of the earth." + assignedrole = "Cydonian Knight" + +/obj/effect/mob_spawn/human/lavaknight/special(mob/living/new_spawn) + if(ishuman(new_spawn)) + var/mob/living/carbon/human/H = new_spawn + H.dna.features["ears"] = "Cat" //cat people + H.update_body() + +/obj/effect/mob_spawn/human/lavaknight/Destroy() + new/obj/structure/showcase/machinery/oldpod/used(drop_location()) + return ..() + +/datum/outfit/lavaknight + name = "Cydonian Knight" + uniform = /obj/item/clothing/under/assistantformal + mask = /obj/item/clothing/mask/breath + shoes = /obj/item/clothing/shoes/sneakers/black + r_pocket = /obj/item/melee/transforming/energy/sword/cx + suit = /obj/item/clothing/suit/space/hardsuit/lavaknight + suit_store = /obj/item/tank/internals/oxygen + +/obj/effect/mob_spawn/human/lavaknight/captain + name = "odd gilded cryogenics pod" + desc = "A humming cryo pod that appears to be gilded. You can barely recognise a faint glow underneath the built up ice. The machine is attempting to wake up its occupant." + flavour_text = "You are a knight who conveniently has some form of retrograde amnesia. \ + You cannot remember where you came from. However, a few things remain burnt into your mind, most prominently a vow to never harm another sapient being under any circumstances unless it is hellbent on ending your life. \ + Remember: hostile creatures and such are fair game for attacking, but under no circumstances are you to attack anything capable of thought and/or speech unless it has made it its life's calling to chase you to the ends of the earth. \ + You feel a natural instict to lead, and as such, you should strive to lead your comrades to safety, and hopefully home. You also feel a burning determination to uphold your vow, as well as your fellow comrade's." + l_pocket = /obj/item/twohanded/hypereutactic diff --git a/modular_citadel/cydonian_armor.dm b/modular_citadel/cydonian_armor.dm new file mode 100644 index 0000000000..0189358d36 --- /dev/null +++ b/modular_citadel/cydonian_armor.dm @@ -0,0 +1,160 @@ +/* + CYDONIAN ARMOR THAT IS RGB AND STUFF WOOOOOOOOOO +*/ + +/obj/item/clothing/head/helmet/space/hardsuit/lavaknight + name = "cydonian helmet" + desc = "A helmet designed with both form and function in mind, it protects the user against physical trauma and hazardous conditions while also having polychromic light strips." + icon = 'modular_citadel/icons/lavaknight/item/head.dmi' + icon_state = "knight_cydonia" + item_state = "knight_yellow" + item_color = null + alternate_worn_icon = 'modular_citadel/icons/lavaknight/mob/head.dmi' + max_heat_protection_temperature = FIRE_SUIT_MAX_TEMP_PROTECT + resistance_flags = FIRE_PROOF | LAVA_PROOF + heat_protection = HEAD + armor = list(melee = 50, bullet = 10, laser = 10, energy = 10, bomb = 50, bio = 100, rad = 50, fire = 100, acid = 100) + brightness_on = 7 + allowed = list(/obj/item/device/flashlight, /obj/item/tank/internals, /obj/item/resonator, /obj/item/device/mining_scanner, /obj/item/device/t_scanner/adv_mining_scanner, /obj/item/gun/energy/kinetic_accelerator) + var/energy_color = "#35FFF0" + var/obj/item/clothing/suit/space/hardsuit/lavaknight/linkedsuit = null + +/obj/item/clothing/head/helmet/space/hardsuit/lavaknight/New() + ..() + if(istype(loc, /obj/item/clothing/suit/space/hardsuit/lavaknight)) + linkedsuit = loc + +/obj/item/clothing/head/helmet/space/hardsuit/lavaknight/attack_self(mob/user) + on = !on + + if(on) + set_light(brightness_on) + else + set_light(0) + for(var/X in actions) + var/datum/action/A = X + A.UpdateButtonIcon() + +/obj/item/clothing/head/helmet/space/hardsuit/lavaknight/update_icon() + var/mutable_appearance/helm_overlay = mutable_appearance('modular_citadel/icons/lavaknight/item/head.dmi', "knight_cydonia_overlay", LIGHTING_LAYER + 1) + + if(energy_color) + helm_overlay.color = energy_color + + helm_overlay.plane = LIGHTING_PLANE + 1 //Magic number is used here because we have no ABOVE_LIGHTING_PLANE plane defined. Lighting plane is 15, HUD is 18 + + cut_overlays() //So that it doesn't keep stacking overlays non-stop on top of each other + + add_overlay(helm_overlay) + + emissivelights() + +/obj/item/clothing/head/helmet/space/hardsuit/lavaknight/equipped(mob/user, slot) + ..() + if(slot == slot_head) + emissivelights() + +/obj/item/clothing/head/helmet/space/hardsuit/lavaknight/dropped(mob/user) + ..() + emissivelightsoff() + +/obj/item/clothing/head/helmet/space/hardsuit/lavaknight/proc/emissivelights(mob/user = usr) + var/mutable_appearance/energy_overlay = mutable_appearance('modular_citadel/icons/lavaknight/mob/head.dmi', "knight_cydonia_overlay", LIGHTING_LAYER + 1) + energy_overlay.color = energy_color + energy_overlay.plane = LIGHTING_PLANE + 1 + user.cut_overlay(energy_overlay) //honk + user.add_overlay(energy_overlay) //honk + +/obj/item/clothing/head/helmet/space/hardsuit/lavaknight/proc/emissivelightsoff(mob/user = usr) + user.cut_overlay() + linkedsuit.emissivelights() //HONK HONK HONK MAXIMUM SPAGHETTI + user.regenerate_icons() //honk + +/obj/item/clothing/suit/space/hardsuit/lavaknight + icon = 'modular_citadel/icons/lavaknight/item/suit.dmi' + icon_state = "knight_cydonia" + name = "cydonian armor" + desc = "A suit designed with both form and function in mind, it protects the user against physical trauma and hazardous conditions while also having polychromic light strips." + item_state = "swat_suit" + alternate_worn_icon = 'modular_citadel/icons/lavaknight/mob/suit.dmi' + max_heat_protection_temperature = FIRE_SUIT_MAX_TEMP_PROTECT + resistance_flags = FIRE_PROOF | LAVA_PROOF + armor = list(melee = 50, bullet = 10, laser = 10, energy = 10, bomb = 50, bio = 100, rad = 50, fire = 100, acid = 100) + allowed = list(/obj/item/device/flashlight, /obj/item/tank/internals, /obj/item/storage/bag/ore, /obj/item/pickaxe) + helmettype = /obj/item/clothing/head/helmet/space/hardsuit/lavaknight + heat_protection = CHEST|GROIN|LEGS|FEET|ARMS|HANDS + actions_types = list(/datum/action/item_action/toggle_helmet) + var/obj/item/clothing/head/helmet/space/hardsuit/lavaknight/linkedhelm + + var/energy_color = "#35FFF0" + +/obj/item/clothing/suit/space/hardsuit/lavaknight/New() + ..() + if(helmet) + linkedhelm = helmet + light_color = energy_color + set_light(1) + +/obj/item/clothing/suit/space/hardsuit/lavaknight/Initialize() + ..() + update_icon() + +/obj/item/clothing/suit/space/hardsuit/lavaknight/update_icon() + var/mutable_appearance/suit_overlay = mutable_appearance('modular_citadel/icons/lavaknight/item/suit.dmi', "knight_cydonia_overlay", LIGHTING_LAYER + 1) + + if(energy_color) + suit_overlay.color = energy_color + + suit_overlay.plane = LIGHTING_PLANE + 1 //Magic number is used here because we have no ABOVE_LIGHTING_PLANE plane defined. Lighting plane is 15. + + cut_overlays() //So that it doesn't keep stacking overlays non-stop on top of each other + + add_overlay(suit_overlay) + +/obj/item/clothing/suit/space/hardsuit/lavaknight/equipped(mob/user, slot) + ..() + if(slot == slot_wear_suit) + emissivelights() + +/obj/item/clothing/suit/space/hardsuit/lavaknight/dropped(mob/user) + ..() + emissivelightsoff() + +/obj/item/clothing/suit/space/hardsuit/lavaknight/proc/emissivelights(mob/user = usr) + var/mutable_appearance/energy_overlay = mutable_appearance('modular_citadel/icons/lavaknight/mob/suit.dmi', "knight_cydonia_overlay", LIGHTING_LAYER + 1) + energy_overlay.color = energy_color + energy_overlay.plane = LIGHTING_PLANE + 1 + user.cut_overlay(energy_overlay) //honk + user.add_overlay(energy_overlay) //honk + +/obj/item/clothing/suit/space/hardsuit/lavaknight/proc/emissivelightsoff(mob/user = usr) + user.cut_overlays() + user.regenerate_icons() //honk + +/obj/item/clothing/suit/space/hardsuit/lavaknight/AltClick(mob/living/user) + if(user.incapacitated() || !istype(user)) + to_chat(user, "You can't do that right now!") + return + if(!in_range(src, user)) + return + if(user.incapacitated() || !istype(user) || !in_range(src, user)) + return + + if(alert("Are you sure you want to recolor your armor stripes?", "Confirm Repaint", "Yes", "No") == "Yes") + var/energy_color_input = input(usr,"Choose Energy Color") as color|null + if(energy_color_input) + energy_color = sanitize_hexcolor(energy_color_input, desired_format=6, include_crunch=1) + user.update_inv_wear_suit() + if(linkedhelm) + linkedhelm.energy_color = sanitize_hexcolor(energy_color_input, desired_format=6, include_crunch=1) + user.update_inv_head() + linkedhelm.update_icon() + update_icon() + user.update_inv_wear_suit() + light_color = energy_color + emissivelights() + update_light() + +/obj/item/clothing/suit/space/hardsuit/lavaknight/examine(mob/user) + ..() + to_chat(user, "Alt-click to recolor it.") \ No newline at end of file diff --git a/modular_citadel/hypereutactic_blade.dm b/modular_citadel/hypereutactic_blade.dm new file mode 100644 index 0000000000..e96789c43f --- /dev/null +++ b/modular_citadel/hypereutactic_blade.dm @@ -0,0 +1,278 @@ +/* fuckhuge esword thingy */ + +/obj/item/twohanded/hypereutactic + icon = 'modular_citadel/icons/hypereutactic/item/hypereutactic.dmi' + icon_state = "hypereutactic" + lefthand_file = 'modular_citadel/icons/hypereutactic/mob/hypereutactic_left.dmi' + righthand_file = 'modular_citadel/icons/hypereutactic/mob/hypereutactic_right.dmi' + item_state = "hypereutactic" + inhand_x_dimension = 64 + inhand_y_dimension = 64 + name = "hypereutactic blade" + desc = "A supermassive weapon envisioned to cleave the very fabric of space and time itself in twain, the hypereutactic blade dynamically flash-forges a hypereutactic crystaline nanostructure capable of passing through most known forms of matter like a hot knife through butter." + force = 3 + throwforce = 5 + throw_speed = 3 + throw_range = 5 + w_class = WEIGHT_CLASS_SMALL + var/w_class_on = WEIGHT_CLASS_BULKY + force_unwielded = 3 + force_wielded = 40 + wieldsound = 'sound/weapons/nebon.ogg' + unwieldsound = 'sound/weapons/neboff.ogg' + hitsound = "swing_hit" + armour_penetration = 40 + origin_tech = "magnets=6;syndicate=1" + light_color = "#37FFF7" + attack_verb = list("attacked", "slashed", "stabbed", "sliced", "destroyed", "ripped", "devastated", "shredded") + block_chance = 75 + max_integrity = 200 + armor = list(melee = 0, bullet = 0, laser = 0, energy = 0, bomb = 0, bio = 0, rad = 0, fire = 100, acid = 70) + resistance_flags = FIRE_PROOF + var/brightness_on = 6 //TWICE AS BRIGHT AS A REGULAR ESWORD + flags_2 = SLOWS_WHILE_IN_HAND_2 + +/obj/item/twohanded/hypereutactic/wield(mob/living/carbon/M) //Specific wield () hulk checks due to reflection chance for balance issues and switches hitsounds. + if(M.has_dna()) + if(M.dna.check_mutation(HULK)) + to_chat(M, "You lack the grace to wield this!") + return + ..() + if(wielded) + sharpness = IS_SHARP + w_class = w_class_on + hitsound = 'sound/weapons/nebhit.ogg' + START_PROCESSING(SSobj, src) + set_light(brightness_on) + slowdown = 1 + +/obj/item/twohanded/hypereutactic/unwield() //Specific unwield () to switch hitsounds. + sharpness = initial(sharpness) + w_class = initial(w_class) + ..() + hitsound = "swing_hit" + STOP_PROCESSING(SSobj, src) + set_light(0) + slowdown = initial(slowdown) + +/obj/item/twohanded/hypereutactic/update_icon() + var/mutable_appearance/blade_overlay = mutable_appearance('modular_citadel/icons/hypereutactic/item/hypereutactic.dmi', "hypereutactic_blade") + var/mutable_appearance/gem_overlay = mutable_appearance('modular_citadel/icons/hypereutactic/item/hypereutactic.dmi', "hypereutactic_gem") + + if(light_color) + blade_overlay.color = light_color + gem_overlay.color = light_color + + cut_overlays() //So that it doesn't keep stacking overlays non-stop on top of each other + + add_overlay(gem_overlay) + + if(wielded) + add_overlay(blade_overlay) + + if(ismob(loc)) + var/mob/M = loc + M.update_inv_hands() + + clean_blood()//blood overlays get weird otherwise, because the sprite changes. (retained from original desword because I have no idea what this is) + +/obj/item/twohanded/hypereutactic/AltClick(mob/living/user) + if(user.incapacitated() || !istype(user)) + to_chat(user, "You can't do that right now!") + return + if(!in_range(src, user)) + return + if(user.incapacitated() || !istype(user) || !in_range(src, user)) + return + + if(alert("Are you sure you want to recolor your blade?", "Confirm Repaint", "Yes", "No") == "Yes") + var/energy_color_input = input(usr,"Choose Energy Color") as color|null + if(energy_color_input) + light_color = sanitize_hexcolor(energy_color_input, desired_format=6, include_crunch=1) + update_icon() + update_light() + +/obj/item/twohanded/hypereutactic/worn_overlays(isinhands, icon_file) + . = ..() + if(isinhands) + var/mutable_appearance/gem_inhand = mutable_appearance(icon_file, "hypereutactic_gem") + gem_inhand.color = light_color + . += gem_inhand + if(wielded) + var/mutable_appearance/blade_inhand = mutable_appearance(icon_file, "hypereutactic_blade") + blade_inhand.color = light_color + . += blade_inhand + +/obj/item/twohanded/hypereutactic/examine(mob/user) + ..() + to_chat(user, "Alt-click to recolor it.") + + + +////////// stuff beneath this is all taken from the desword //////////// + + + +/obj/item/twohanded/hypereutactic/attack(mob/target, mob/living/carbon/human/user) + if(user.has_dna()) + if(user.dna.check_mutation(HULK)) + to_chat(user, "You grip the blade too hard and accidentally close it!") + unwield() + return + ..() + if(user.disabilities & CLUMSY && (wielded) && prob(40)) + impale(user) + return + +/obj/item/twohanded/hypereutactic/Destroy() + STOP_PROCESSING(SSobj, src) + . = ..() + +/obj/item/twohanded/hypereutactic/proc/impale(mob/living/user) + to_chat(user, "You spin around a bit before losing your balance and impaling yourself on [src].") + if (force_wielded) + user.take_bodypart_damage(20,25) + else + user.adjustStaminaLoss(25) + +/obj/item/twohanded/hypereutactic/hit_reaction(mob/living/carbon/human/owner, atom/movable/hitby, attack_text = "the attack", final_block_chance = 0, damage = 0, attack_type = MELEE_ATTACK) + if(wielded) + return ..() + return 0 + +/obj/item/twohanded/hypereutactic/attack_hulk(mob/living/carbon/human/user, does_attack_animation = 0) //In case thats just so happens that it is still activated on the groud, prevents hulk from picking it up + if(wielded) + to_chat(user, "You can't pick up such dangerous item with your meaty hands without losing fingers, better not to!") + return 1 + +/obj/item/twohanded/hypereutactic/process() + if(wielded) + open_flame() + else + STOP_PROCESSING(SSobj, src) + +/obj/item/twohanded/hypereutactic/IsReflect() + if(wielded) + return 1 + +/obj/item/twohanded/hypereutactic/ignition_effect(atom/A, mob/user) + // same as /obj/item/melee/transforming/energy, mostly + if(!wielded) + return "" + var/in_mouth = "" + if(iscarbon(user)) + var/mob/living/carbon/C = user + if(C.wear_mask == src) + in_mouth = ", barely missing their nose" + . = "[user] swings [user.p_their()] [src][in_mouth]. [user.p_they()] light[user.p_s()] [A] in the process." + playsound(loc, hitsound, get_clamped_volume(), 1, -1) + add_fingerprint(user) + + +////////////////// TOY VERSION ///////////////////////////// + +/obj/item/twohanded/hypereutactic/toy + name = "\improper DX Hyper-Euplastic LightSword" + desc = "A supermassive toy envisioned to cleave the very fabric of space and time itself in twain. Realistic visuals and sounds! Ages 8 and up." + force = 0 + throwforce = 0 + throw_speed = 3 + throw_range = 5 + force_unwielded = 0 + force_wielded = 0 + origin_tech = null + attack_verb = list("attacked", "struck", "hit") + +/obj/item/twohanded/hypereutactic/toy/hit_reaction(mob/living/carbon/human/owner, atom/movable/hitby, attack_text = "the attack", final_block_chance = 0, damage = 0, attack_type = MELEE_ATTACK) + return 0 + +/obj/item/twohanded/hypereutactic/toy/IsReflect()//Stops it from reflecting energy projectiles + return 0 + +/* old code that don't work no more +/obj/item/toy/sword/cx/hyper + name = "\improper DX Hyper-Euplastic LightSword" + desc = "A supermassive toy envisioned to cleave the very fabric of space and time itself in twain. Realistic visuals and sounds! Ages 8 and up." + icon = 'modular_citadel/icons/hypereutactic/item/hypereutactic.dmi' + icon_state = "hypereutactic" + lefthand_file = 'modular_citadel/icons/hypereutactic/mob/hypereutactic_left.dmi' + righthand_file = 'modular_citadel/icons/hypereutactic/mob/hypereutactic_right.dmi' + item_state = "hypereutactic" + inhand_x_dimension = 64 + inhand_y_dimension = 64 + active = FALSE + w_class = WEIGHT_CLASS_SMALL + attack_verb = list("poked", "devastated", "jabbed") + light_color = "#37FFF7" + light_brightness = 3 + actions_types = list() + +/obj/item/toy/sword/cx/hyper/attack_self(mob/user) + active = !( active ) + + if (active) + to_chat(user, "You activate the holographic blade with a press of a button.") + playsound(user, 'sound/weapons/nebon.ogg', 50, 1) + w_class = WEIGHT_CLASS_BULKY + attack_verb = list("slashed", "stabbed", "ravaged") + set_light(light_brightness) + update_icon() + + else + to_chat(user, "You deactivate the holographic blade with a press of a button.") + playsound(user, 'sound/weapons/neboff.ogg', 50, 1) + w_class = WEIGHT_CLASS_SMALL + attack_verb = list("poked", "jabbed", "hit") + set_light(0) + update_icon() + + add_fingerprint(user) + +/obj/item/toy/sword/cx/hyper/update_icon() + var/mutable_appearance/blade_overlay = mutable_appearance('modular_citadel/icons/hypereutactic/item/hypereutactic.dmi', "hypereutactic_blade") + var/mutable_appearance/gem_overlay = mutable_appearance('modular_citadel/icons/hypereutactic/item/hypereutactic.dmi', "hypereutactic_gem") + + if(light_color) + blade_overlay.color = light_color + gem_overlay.color = light_color + + cut_overlays() //So that it doesn't keep stacking overlays non-stop on top of each other + + add_overlay(gem_overlay) + + if(active) + add_overlay(blade_overlay) + + if(ismob(loc)) + var/mob/M = loc + M.update_inv_hands() + +/obj/item/toy/sword/cx/hyper/AltClick(mob/living/user) + if(user.incapacitated() || !istype(user)) + to_chat(user, "You can't do that right now!") + return + if(!in_range(src, user)) + return + if(user.incapacitated() || !istype(user) || !in_range(src, user)) + return + + if(alert("Are you sure you want to recolor your blade?", "Confirm Repaint", "Yes", "No") == "Yes") + var/energy_color_input = input(usr,"Choose Energy Color") as color|null + if(energy_color_input) + light_color = sanitize_hexcolor(energy_color_input, desired_format=6, include_crunch=1) + update_icon() + update_light() + +/obj/item/toy/sword/cx/hyper/worn_overlays(isinhands, icon_file) + if(isinhands) + var/mutable_appearance/gem_inhand = mutable_appearance(icon_file, "hypereutactic_gem") + gem_inhand.color = light_color + . += gem_inhand + if(active) + var/mutable_appearance/blade_inhand = mutable_appearance(icon_file, "hypereutactic_blade") + blade_inhand.color = light_color + . += blade_inhand + +/obj/item/toy/sword/cx/hyper/attackby(obj/item/W, mob/living/user, params) + return +*/ \ No newline at end of file diff --git a/modular_citadel/icons/hypereutactic/item/hypereutactic.dmi b/modular_citadel/icons/hypereutactic/item/hypereutactic.dmi new file mode 100644 index 0000000000..90a665f676 Binary files /dev/null and b/modular_citadel/icons/hypereutactic/item/hypereutactic.dmi differ diff --git a/modular_citadel/icons/hypereutactic/mob/hypereutactic_left.dmi b/modular_citadel/icons/hypereutactic/mob/hypereutactic_left.dmi new file mode 100644 index 0000000000..ca94055113 Binary files /dev/null and b/modular_citadel/icons/hypereutactic/mob/hypereutactic_left.dmi differ diff --git a/modular_citadel/icons/hypereutactic/mob/hypereutactic_right.dmi b/modular_citadel/icons/hypereutactic/mob/hypereutactic_right.dmi new file mode 100644 index 0000000000..a9b90da740 Binary files /dev/null and b/modular_citadel/icons/hypereutactic/mob/hypereutactic_right.dmi differ diff --git a/modular_citadel/icons/lavaknight/item/head.dmi b/modular_citadel/icons/lavaknight/item/head.dmi new file mode 100644 index 0000000000..950d4894e9 Binary files /dev/null and b/modular_citadel/icons/lavaknight/item/head.dmi differ diff --git a/modular_citadel/icons/lavaknight/item/suit.dmi b/modular_citadel/icons/lavaknight/item/suit.dmi new file mode 100644 index 0000000000..49cd14b666 Binary files /dev/null and b/modular_citadel/icons/lavaknight/item/suit.dmi differ diff --git a/modular_citadel/icons/lavaknight/mob/head.dmi b/modular_citadel/icons/lavaknight/mob/head.dmi new file mode 100644 index 0000000000..5084c9c66f Binary files /dev/null and b/modular_citadel/icons/lavaknight/mob/head.dmi differ diff --git a/modular_citadel/icons/lavaknight/mob/suit.dmi b/modular_citadel/icons/lavaknight/mob/suit.dmi new file mode 100644 index 0000000000..ed51ceaaa4 Binary files /dev/null and b/modular_citadel/icons/lavaknight/mob/suit.dmi differ diff --git a/tgstation.dme b/tgstation.dme index a678fe8a1b..d6ec553545 100755 --- a/tgstation.dme +++ b/tgstation.dme @@ -341,6 +341,7 @@ #include "code\datums\brain_damage\split_personality.dm" #include "code\datums\components\_component.dm" #include "code\datums\components\archaeology.dm" +#include "code\datums\components\caltrop.dm" #include "code\datums\components\chasm.dm" #include "code\datums\components\decal.dm" #include "code\datums\components\infective.dm" @@ -878,6 +879,7 @@ #include "code\game\objects\items\mop.dm" #include "code\game\objects\items\paint.dm" #include "code\game\objects\items\paiwire.dm" +#include "code\game\objects\items\pet_carrier.dm" #include "code\game\objects\items\pinpointer.dm" #include "code\game\objects\items\plushes.dm" #include "code\game\objects\items\pneumaticCannon.dm" @@ -2426,6 +2428,9 @@ #include "interface\skin.dmf" #include "modular_citadel\cit_medkits.dm" #include "modular_citadel\cit_screenshake.dm" +#include "modular_citadel\citadel_ghostrole_spawners.dm" +#include "modular_citadel\cydonian_armor.dm" +#include "modular_citadel\hypereutactic_blade.dm" #include "modular_citadel\polychromic_clothes.dm" #include "modular_citadel\code\datums\uplink_items_cit.dm" // END_INCLUDE