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