diff --git a/byond-extools.dll b/byond-extools.dll
index c404bf1be5..af036e9147 100644
Binary files a/byond-extools.dll and b/byond-extools.dll differ
diff --git a/byond-extools.pdb b/byond-extools.pdb
index f89dc06441..c80101f6b5 100644
Binary files a/byond-extools.pdb and b/byond-extools.pdb differ
diff --git a/code/__DEFINES/DNA.dm b/code/__DEFINES/DNA.dm
index 035563627f..a8026f752b 100644
--- a/code/__DEFINES/DNA.dm
+++ b/code/__DEFINES/DNA.dm
@@ -79,21 +79,22 @@
//DNA - Because fuck you and your magic numbers being all over the codebase.
#define DNA_BLOCK_SIZE 3
-#define DNA_UNI_IDENTITY_BLOCKS 14
+#define DNA_UNI_IDENTITY_BLOCKS 15
#define DNA_HAIR_COLOR_BLOCK 1
#define DNA_FACIAL_HAIR_COLOR_BLOCK 2
#define DNA_SKIN_TONE_BLOCK 3
-#define DNA_EYE_COLOR_BLOCK 4
-#define DNA_GENDER_BLOCK 5
-#define DNA_FACIAL_HAIR_STYLE_BLOCK 6
-#define DNA_HAIR_STYLE_BLOCK 7
-#define DNA_COLOR_ONE_BLOCK 8
-#define DNA_COLOR_TWO_BLOCK 9
-#define DNA_COLOR_THREE_BLOCK 10
-#define DNA_MUTANTTAIL_BLOCK 11
-#define DNA_MUTANTEAR_BLOCK 12
-#define DNA_MUTANTMARKING_BLOCK 13
-#define DNA_TAUR_BLOCK 14
+#define DNA_LEFT_EYE_COLOR_BLOCK 4
+#define DNA_RIGHT_EYE_COLOR_BLOCK 5
+#define DNA_GENDER_BLOCK 6
+#define DNA_FACIAL_HAIR_STYLE_BLOCK 7
+#define DNA_HAIR_STYLE_BLOCK 8
+#define DNA_COLOR_ONE_BLOCK 9
+#define DNA_COLOR_TWO_BLOCK 10
+#define DNA_COLOR_THREE_BLOCK 11
+#define DNA_MUTANTTAIL_BLOCK 12
+#define DNA_MUTANTEAR_BLOCK 13
+#define DNA_MUTANTMARKING_BLOCK 14
+#define DNA_TAUR_BLOCK 15
#define DNA_SEQUENCE_LENGTH 4
#define DNA_MUTATION_BLOCKS 8
diff --git a/code/__DEFINES/citadel_defines.dm b/code/__DEFINES/citadel_defines.dm
index 6aca5cd998..58125b5497 100644
--- a/code/__DEFINES/citadel_defines.dm
+++ b/code/__DEFINES/citadel_defines.dm
@@ -47,7 +47,7 @@
#define BALLS_SIZE_DEF 2
#define BALLS_SIZE_MAX 3
-#define CUM_RATE 2 // holy shit what a really shitty define name - relates to units per arbitrary measure of time?
+#define CUM_RATE 2 // units per 10 seconds
#define CUM_RATE_MULT 1
#define CUM_EFFICIENCY 1 //amount of nutrition required per life()
@@ -58,7 +58,7 @@
#define DEF_BREASTS_SHAPE "Pair"
-#define MILK_RATE 5
+#define MILK_RATE 3
#define MILK_RATE_MULT 1
#define MILK_EFFICIENCY 1
diff --git a/code/controllers/subsystem/air.dm b/code/controllers/subsystem/air.dm
index e207fe838a..e0c6c48eaa 100644
--- a/code/controllers/subsystem/air.dm
+++ b/code/controllers/subsystem/air.dm
@@ -77,6 +77,7 @@ SUBSYSTEM_DEF(air)
/datum/controller/subsystem/air/proc/extools_update_ssair()
/datum/controller/subsystem/air/proc/extools_update_reactions()
+/datum/controller/subsystem/air/proc/scan_for_active_turfs()
/datum/controller/subsystem/air/fire(resumed = 0)
var/timer = TICK_USAGE_REAL
@@ -164,6 +165,8 @@ SUBSYSTEM_DEF(air)
if(state != SS_RUNNING)
return
resumed = 0
+ if(get_amt_active_turfs() < 3000 && !TICK_CHECK)
+ scan_for_active_turfs()
currentpart = SSAIR_REBUILD_PIPENETS
diff --git a/code/datums/dna.dm b/code/datums/dna.dm
index 9486029fdd..843ea06f74 100644
--- a/code/datums/dna.dm
+++ b/code/datums/dna.dm
@@ -132,7 +132,8 @@
L[DNA_FACIAL_HAIR_STYLE_BLOCK] = construct_block(GLOB.facial_hair_styles_list.Find(H.facial_hair_style), GLOB.facial_hair_styles_list.len)
L[DNA_FACIAL_HAIR_COLOR_BLOCK] = sanitize_hexcolor(H.facial_hair_color)
L[DNA_SKIN_TONE_BLOCK] = construct_block(GLOB.skin_tones.Find(H.skin_tone), GLOB.skin_tones.len)
- L[DNA_EYE_COLOR_BLOCK] = sanitize_hexcolor(H.eye_color)
+ L[DNA_LEFT_EYE_COLOR_BLOCK] = sanitize_hexcolor(H.left_eye_color)
+ L[DNA_RIGHT_EYE_COLOR_BLOCK] = sanitize_hexcolor(H.right_eye_color)
L[DNA_COLOR_ONE_BLOCK] = sanitize_hexcolor(features["mcolor"], 6)
L[DNA_COLOR_TWO_BLOCK] = sanitize_hexcolor(features["mcolor2"], 6)
L[DNA_COLOR_THREE_BLOCK] = sanitize_hexcolor(features["mcolor3"], 6)
@@ -224,8 +225,10 @@
setblock(uni_identity, blocknumber, sanitize_hexcolor(H.facial_hair_color))
if(DNA_SKIN_TONE_BLOCK)
setblock(uni_identity, blocknumber, construct_block(GLOB.skin_tones.Find(H.skin_tone), GLOB.skin_tones.len))
- if(DNA_EYE_COLOR_BLOCK)
- setblock(uni_identity, blocknumber, sanitize_hexcolor(H.eye_color))
+ if(DNA_LEFT_EYE_COLOR_BLOCK)
+ setblock(uni_identity, blocknumber, sanitize_hexcolor(H.left_eye_color))
+ if(DNA_RIGHT_EYE_COLOR_BLOCK)
+ setblock(uni_identity, blocknumber, sanitize_hexcolor(H.right_eye_color))
if(DNA_GENDER_BLOCK)
switch(H.gender)
if(MALE)
@@ -464,7 +467,8 @@
hair_color = sanitize_hexcolor(getblock(structure, DNA_HAIR_COLOR_BLOCK))
facial_hair_color = sanitize_hexcolor(getblock(structure, DNA_FACIAL_HAIR_COLOR_BLOCK))
skin_tone = dna.skin_tone_override || GLOB.skin_tones[deconstruct_block(getblock(structure, DNA_SKIN_TONE_BLOCK), GLOB.skin_tones.len)]
- eye_color = sanitize_hexcolor(getblock(structure, DNA_EYE_COLOR_BLOCK))
+ left_eye_color = sanitize_hexcolor(getblock(structure, DNA_LEFT_EYE_COLOR_BLOCK))
+ right_eye_color = sanitize_hexcolor(getblock(structure, DNA_RIGHT_EYE_COLOR_BLOCK))
facial_hair_style = GLOB.facial_hair_styles_list[deconstruct_block(getblock(structure, DNA_FACIAL_HAIR_STYLE_BLOCK), GLOB.facial_hair_styles_list.len)]
hair_style = GLOB.hair_styles_list[deconstruct_block(getblock(structure, DNA_HAIR_STYLE_BLOCK), GLOB.hair_styles_list.len)]
if(icon_update)
diff --git a/code/game/gamemodes/objective_sabotage.dm b/code/game/gamemodes/objective_sabotage.dm
index f08d84eae2..c8f1ef4713 100644
--- a/code/game/gamemodes/objective_sabotage.dm
+++ b/code/game/gamemodes/objective_sabotage.dm
@@ -56,7 +56,7 @@
There are many other ways; be creative!\
"
-/datum/sabotage_objective/processing/supermatter
+/*/datum/sabotage_objective/processing/supermatter
name = "Sabotage the supermatter so that it goes under 50% integrity. If it is delaminated, you will fail."
sabotage_type = "supermatter"
special_equipment = list(/obj/item/paper/guides/antag/supermatter_sabotage)
@@ -77,7 +77,7 @@
/datum/sabotage_objective/processing/supermatter/can_run()
return (locate(/obj/machinery/power/supermatter_crystal) in GLOB.machines)
-/*
+
/datum/sabotage_objective/station_integrity
name = "Make sure the station is at less than 80% integrity by the end. Smash walls, windows etc. to reach this goal."
sabotage_type = "integrity"
diff --git a/code/game/machinery/_machinery.dm b/code/game/machinery/_machinery.dm
index b82d932e6d..46b4bbe574 100644
--- a/code/game/machinery/_machinery.dm
+++ b/code/game/machinery/_machinery.dm
@@ -381,6 +381,7 @@ Class Procs:
/obj/machinery/obj_break(damage_flag)
if(!(flags_1 & NODECONSTRUCT_1))
stat |= BROKEN
+ return TRUE
/obj/machinery/contents_explosion(severity, target)
if(occupant)
diff --git a/code/game/machinery/cryopod.dm b/code/game/machinery/cryopod.dm
index f7019e75ef..b48742d885 100644
--- a/code/game/machinery/cryopod.dm
+++ b/code/game/machinery/cryopod.dm
@@ -355,23 +355,23 @@
cryo_items -= I
//Update any existing objectives involving this mob.
- for(var/datum/objective/O in GLOB.objectives)
+ for(var/i in GLOB.objectives)
+ var/datum/objective/O = i
// We don't want revs to get objectives that aren't for heads of staff. Letting
// them win or lose based on cryo is silly so we remove the objective.
if(istype(O,/datum/objective/mutiny) && O.target == mob_occupant.mind)
qdel(O)
- else if(O.target && istype(O.target, /datum/mind))
- if(O.target == mob_occupant.mind)
- if(O.owner && O.owner.current)
- to_chat(O.owner.current, "
You get the feeling your target is no longer within reach. Time for Plan [pick("A","B","C","D","X","Y","Z")]. Objectives updated!")
- O.target = null
- spawn(10) //This should ideally fire after the occupant is deleted.
- if(!O)
- return
- O.find_target()
- O.update_explanation_text()
- if(!(O.target))
- qdel(O)
+ else if(O.target && istype(O.target, /datum/mind) && !O.check_completion())
+ if(O.target == mob_occupant.mind && O.owner?.current)
+ to_chat(O.owner.current, "
You get the feeling your target is no longer within reach. Time for Plan [pick("A","B","C","D","X","Y","Z")]. Objectives updated!")
+ O.target = null
+ spawn(10) //This should ideally fire after the occupant is deleted.
+ if(!O)
+ return
+ O.find_target()
+ O.update_explanation_text()
+ if(!(O.target))
+ qdel(O)
if(mob_occupant.mind)
//Handle job slot/tater cleanup.
diff --git a/code/game/machinery/porta_turret/portable_turret.dm b/code/game/machinery/porta_turret/portable_turret.dm
index 54d320e93b..8f7aee68ce 100644
--- a/code/game/machinery/porta_turret/portable_turret.dm
+++ b/code/game/machinery/porta_turret/portable_turret.dm
@@ -300,6 +300,7 @@
else
to_chat(user, "You remove the turret but did not manage to salvage anything.")
qdel(src)
+ return
else if((istype(I, /obj/item/wrench)) && (!on))
if(raised)
diff --git a/code/game/machinery/porta_turret/portable_turret_construct.dm b/code/game/machinery/porta_turret/portable_turret_construct.dm
index 7c2000175e..2a73ee8d89 100644
--- a/code/game/machinery/porta_turret/portable_turret_construct.dm
+++ b/code/game/machinery/porta_turret/portable_turret_construct.dm
@@ -151,6 +151,7 @@
turret.installation = installed_gun.type
turret.setup(installed_gun)
qdel(src)
+ return
else if(istype(I, /obj/item/crowbar))
I.play_tool_sound(src, 75)
diff --git a/code/game/machinery/poweredfans/fan_assembly.dm b/code/game/machinery/poweredfans/fan_assembly.dm
new file mode 100644
index 0000000000..651b3342ac
--- /dev/null
+++ b/code/game/machinery/poweredfans/fan_assembly.dm
@@ -0,0 +1,100 @@
+/obj/machinery/fan_assembly
+ name = "fan assembly"
+ desc = "A basic microfan assembly."
+ icon = 'icons/obj/poweredfans.dmi'
+ icon_state = "mfan_assembly"
+ max_integrity = 150
+ use_power = NO_POWER_USE
+ power_channel = ENVIRON
+ idle_power_usage = 0
+ active_power_usage = 0
+ layer = ABOVE_NORMAL_TURF_LAYER
+ anchored = FALSE
+ density = FALSE
+ CanAtmosPass = ATMOS_PASS_YES
+ stat = 1
+ var/buildstacktype = /obj/item/stack/sheet/plasteel
+ var/buildstackamount = 5
+ /*
+ 1 = Wrenched in place
+ 2 = Welded in place
+ 3 = Wires attached to it, this makes it change to the full thing.
+ */
+
+/obj/machinery/fan_assembly/attackby(obj/item/W, mob/living/user, params)
+ switch(stat)
+ if(1)
+ // Stat 1
+ if(istype(W, /obj/item/weldingtool))
+ if(weld(W, user))
+ to_chat(user, "You weld the fan assembly securely into place.")
+ setAnchored(TRUE)
+ stat = 2
+ update_icon_state()
+ return
+ if(2)
+ // Stat 2
+ if(istype(W, /obj/item/stack/cable_coil))
+ if(!W.tool_start_check(user, amount=2))
+ to_chat(user, "You need two lengths of cable to wire the fan assembly!")
+ return
+ to_chat(user, "You start to add wires to the assembly...")
+ if(W.use_tool(src, user, 30, volume=50, amount=2))
+ to_chat(user, "You add wires to the fan assembly.")
+ stat = 3
+ var/obj/machinery/poweredfans/F = new(loc, src)
+ forceMove(F)
+ F.setDir(src.dir)
+ return
+ else if(istype(W, /obj/item/weldingtool))
+ if(weld(W, user))
+ to_chat(user, "You unweld the fan assembly from its place.")
+ stat = 1
+ update_icon_state()
+ setAnchored(FALSE)
+ return
+ return ..()
+
+/obj/machinery/fan_assembly/wrench_act(mob/user, obj/item/I)
+ if(stat != 1)
+ return FALSE
+ user.visible_message("[user] disassembles [src].",
+ "You start to disassemble [src]...", "You hear wrenching noises.")
+ if(I.use_tool(src, user, 30, volume=50))
+ deconstruct()
+ return TRUE
+
+/obj/machinery/fan_assembly/proc/weld(obj/item/weldingtool/W, mob/living/user)
+ if(!W.tool_start_check(user, amount=0))
+ return FALSE
+ switch(stat)
+ if(1)
+ to_chat(user, "You start to weld \the [src]...")
+ if(2)
+ to_chat(user, "You start to unweld \the [src]...")
+ if(W.use_tool(src, user, 30, volume=50))
+ return TRUE
+ return FALSE
+
+/obj/machinery/fan_assembly/deconstruct(disassembled = TRUE)
+ if(!(flags_1 & NODECONSTRUCT_1))
+ new buildstacktype(loc,buildstackamount)
+ qdel(src)
+
+/obj/machinery/fan_assembly/examine(mob/user)
+ . = ..()
+ switch(stat)
+ if(1)
+ to_chat(user, "The fan assembly seems to be unwelded and loose.")
+ if(2)
+ to_chat(user, "The fan assembly seems to be welded, but missing wires.")
+ if(3)
+ to_chat(user, "The outer plating is wired firmly in place.")
+
+/obj/machinery/fan_assembly/update_icon_state()
+ . = ..()
+ switch(stat)
+ if(1)
+ icon_state = "mfan_assembly"
+ if(2)
+ icon_state = "mfan_welded"
diff --git a/code/game/machinery/poweredfans/poweredfans.dm b/code/game/machinery/poweredfans/poweredfans.dm
new file mode 100644
index 0000000000..3349a6894e
--- /dev/null
+++ b/code/game/machinery/poweredfans/poweredfans.dm
@@ -0,0 +1,56 @@
+/obj/machinery/poweredfans
+ icon = 'icons/obj/poweredfans.dmi'
+ icon_state = "mfan_powered"
+ name = "micro powered fan"
+ desc = "A handmade fan, releasing a thin gust of air."
+ use_power = ACTIVE_POWER_USE
+ power_channel = ENVIRON
+ idle_power_usage = 5
+ active_power_usage = 10
+ max_integrity = 150
+ layer = ABOVE_NORMAL_TURF_LAYER
+ anchored = TRUE
+ density = FALSE
+ CanAtmosPass = ATMOS_PASS_NO
+ var/obj/machinery/fan_assembly/assembly
+
+/obj/machinery/poweredfans/deconstruct(disassembled = TRUE)
+ if(!(flags_1 & NODECONSTRUCT_1))
+ if(!assembly)
+ assembly = new()
+ assembly.forceMove(drop_location())
+ assembly.stat = 2
+ assembly.setAnchored(TRUE)
+ assembly.setDir(dir)
+ assembly = null
+ new /obj/item/stack/cable_coil(loc, 2)
+ qdel(src)
+
+/obj/machinery/poweredfans/wirecutter_act(mob/living/user, obj/item/I)
+ user.visible_message("[user] removes the wires from the [src].",
+ "You start to remove the wires from the [src]...", "You hear clanking and banging noises.")
+ if(I.use_tool(src, user, 30, volume=50))
+ deconstruct()
+ return TRUE
+
+/obj/machinery/poweredfans/Initialize(mapload, obj/machinery/fan_assembly/FA)
+ . = ..()
+ if(FA)
+ assembly = FA
+ else
+ assembly = new(src)
+ assembly.stat = 3
+ air_update_turf(1)
+
+/obj/machinery/poweredfans/power_change()
+ ..()
+ if(powered())
+ icon_state = "mfan_powered"
+ CanAtmosPass = ATMOS_PASS_NO
+ air_update_turf(1)
+ else
+ icon_state = "mfan_unpowered"
+ CanAtmosPass = ATMOS_PASS_YES
+ air_update_turf(1)
+ update_icon_state()
+
diff --git a/code/game/objects/items/implants/implant_hijack.dm b/code/game/objects/items/implants/implant_hijack.dm
index 5dd610059c..36e58d8887 100644
--- a/code/game/objects/items/implants/implant_hijack.dm
+++ b/code/game/objects/items/implants/implant_hijack.dm
@@ -7,7 +7,8 @@
activated = 1
var/toggled = FALSE
icon_state = "hijack"
- var/eye_color
+ var/left_eye_color
+ var/right_eye_color
var/stealthmode = FALSE
var/stealthcooldown = 0
var/hijacking = FALSE
@@ -25,8 +26,10 @@
return
var/on = toggled && !stealthmode
var/mob/living/carbon/human/H = imp_in
- H.eye_color = on ? "ff0" : eye_color
- H.dna.update_ui_block(DNA_EYE_COLOR_BLOCK)
+ H.left_eye_color = on ? "ff0" : left_eye_color
+ H.right_eye_color = on ? "ff0" : right_eye_color
+ H.dna.update_ui_block(DNA_LEFT_EYE_COLOR_BLOCK)
+ H.dna.update_ui_block(DNA_RIGHT_EYE_COLOR_BLOCK)
H.update_body()
/obj/item/implant/hijack/implant(mob/living/target, mob/user, silent = FALSE)
@@ -34,7 +37,8 @@
ADD_TRAIT(target, TRAIT_HIJACKER, "implant")
if (ishuman(target))
var/mob/living/carbon/human/H = target
- eye_color = H.eye_color
+ left_eye_color = H.left_eye_color
+ right_eye_color = H.right_eye_color
return TRUE
/obj/item/implant/hijack/removed(mob/living/source, silent = FALSE, special = 0)
@@ -49,7 +53,8 @@
apc.update_icon()
if (ishuman(source))
var/mob/living/carbon/human/H = source
- H.eye_color = eye_color
+ H.left_eye_color = left_eye_color
+ H.right_eye_color = left_eye_color
return TRUE
/obj/item/implant/hijack/proc/InterceptClickOn(mob/living/user,params,atom/object)
diff --git a/code/game/objects/items/stacks/sheets/sheet_types.dm b/code/game/objects/items/stacks/sheets/sheet_types.dm
index c3028c2fd5..fa52ec4520 100644
--- a/code/game/objects/items/stacks/sheets/sheet_types.dm
+++ b/code/game/objects/items/stacks/sheets/sheet_types.dm
@@ -179,6 +179,7 @@ GLOBAL_LIST_INIT(metal_recipes, list ( \
GLOBAL_LIST_INIT(plasteel_recipes, list ( \
new/datum/stack_recipe("AI core", /obj/structure/AIcore, 4, time = 50, one_per_turf = TRUE), \
new/datum/stack_recipe("bomb assembly", /obj/machinery/syndicatebomb/empty, 10, time = 50), \
+ new/datum/stack_recipe("micro powered fan assembly", /obj/machinery/fan_assembly, 5, time = 50, one_per_turf = TRUE, on_floor = TRUE), \
new /datum/stack_recipe_list("crates", list( \
new /datum/stack_recipe("gray crate", /obj/structure/closet/crate, 5, time = 50, one_per_turf = 1, on_floor = 1), \
new /datum/stack_recipe("internals crate", /obj/structure/closet/crate/internals, 5, time = 50, one_per_turf = 1, on_floor = 1), \
diff --git a/code/game/objects/structures/holosign.dm b/code/game/objects/structures/holosign.dm
index dc5355e9d8..1e278a9f88 100644
--- a/code/game/objects/structures/holosign.dm
+++ b/code/game/objects/structures/holosign.dm
@@ -9,6 +9,7 @@
armor = list("melee" = 0, "bullet" = 50, "laser" = 50, "energy" = 50, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 20, "acid" = 20)
var/obj/item/holosign_creator/projector
var/init_vis_overlay = TRUE
+ rad_flags = RAD_NO_CONTAMINATE
/obj/structure/holosign/Initialize(mapload, source_projector)
. = ..()
diff --git a/code/game/objects/structures/mirror.dm b/code/game/objects/structures/mirror.dm
index 237cfdbf0b..758685ede7 100644
--- a/code/game/objects/structures/mirror.dm
+++ b/code/game/objects/structures/mirror.dm
@@ -229,17 +229,32 @@
H.update_hair()
if(BODY_ZONE_PRECISE_EYES)
- var/new_eye_color = input(H, "Choose your eye color", "Eye Color","#"+H.eye_color) as color|null
- if(!user.canUseTopic(src, BE_CLOSE, FALSE, NO_TK))
- return
- if(new_eye_color)
- var/n_color = sanitize_hexcolor(new_eye_color)
- var/obj/item/organ/eyes/eyes = H.getorganslot(ORGAN_SLOT_EYES)
- if(eyes)
- eyes.eye_color = n_color
- H.eye_color = n_color
- H.dna.update_ui_block(DNA_EYE_COLOR_BLOCK)
- H.dna.species.handle_body()
+ var/eye_type = input(H, "Choose the eye you want to color", "Eye Color") as null|anything in list("Both Eyes", "Left Eye", "Right Eye")
+ if(eye_type)
+ var/input_color = H.left_eye_color
+ if(eye_type == "Right Eye")
+ input_color = H.right_eye_color
+ var/new_eye_color = input(H, "Choose your eye color", "Eye Color","#"+input_color) as color|null
+ if(!user.canUseTopic(src, BE_CLOSE, FALSE, NO_TK))
+ return
+ if(new_eye_color)
+ var/n_color = sanitize_hexcolor(new_eye_color)
+ var/obj/item/organ/eyes/eyes = H.getorganslot(ORGAN_SLOT_EYES)
+ var/left_color = n_color
+ var/right_color = n_color
+ if(eye_type == "Left Eye")
+ right_color = H.right_eye_color
+ else
+ if(eye_type == "Right Eye")
+ left_color = H.left_eye_color
+ if(eyes)
+ eyes.left_eye_color = left_color
+ eyes.right_eye_color = right_color
+ H.left_eye_color = left_color
+ H.right_eye_color = right_color
+ H.dna.update_ui_block(DNA_LEFT_EYE_COLOR_BLOCK)
+ H.dna.update_ui_block(DNA_RIGHT_EYE_COLOR_BLOCK)
+ H.dna.species.handle_body()
if(choice)
curse(user)
diff --git a/code/modules/admin/create_mob.dm b/code/modules/admin/create_mob.dm
index 59651b17d5..e287d9b1b3 100644
--- a/code/modules/admin/create_mob.dm
+++ b/code/modules/admin/create_mob.dm
@@ -24,7 +24,9 @@
H.facial_hair_style = random_facial_hair_style(H.gender)
H.hair_color = random_short_color()
H.facial_hair_color = H.hair_color
- H.eye_color = random_eye_color()
+ var/random_eye_color = random_eye_color()
+ H.left_eye_color = random_eye_color
+ H.right_eye_color = random_eye_color
H.dna.blood_type = random_blood_type()
H.saved_underwear = H.underwear
H.saved_undershirt = H.undershirt
diff --git a/code/modules/antagonists/cult/cult.dm b/code/modules/antagonists/cult/cult.dm
index 87e116166e..61f6ec9998 100644
--- a/code/modules/antagonists/cult/cult.dm
+++ b/code/modules/antagonists/cult/cult.dm
@@ -142,8 +142,10 @@
if(ishuman(current))
var/mob/living/carbon/human/H = current
var/obj/item/organ/eyes/eyes = H.getorganslot(ORGAN_SLOT_EYES)
- H.eye_color = eyes?.eye_color || initial(H.eye_color)
- H.dna.update_ui_block(DNA_EYE_COLOR_BLOCK)
+ H.left_eye_color = eyes?.left_eye_color || initial(H.left_eye_color)
+ H.right_eye_color = eyes?.right_eye_color || initial(H.right_eye_color)
+ H.dna?.update_ui_block(DNA_LEFT_EYE_COLOR_BLOCK)
+ H.dna?.update_ui_block(DNA_RIGHT_EYE_COLOR_BLOCK)
REMOVE_TRAIT(H, TRAIT_CULT_EYES, "valid_cultist")
H.update_body()
H.cut_overlays()
@@ -236,8 +238,10 @@
if(ishuman(current))
var/mob/living/carbon/human/H = current
- H.eye_color = initial(H.eye_color)
- H.dna.update_ui_block(DNA_EYE_COLOR_BLOCK)
+ H.left_eye_color = initial(H.left_eye_color)
+ H.right_eye_color = initial(H.right_eye_color)
+ H.dna?.update_ui_block(DNA_LEFT_EYE_COLOR_BLOCK)
+ H.dna?.update_ui_block(DNA_RIGHT_EYE_COLOR_BLOCK)
REMOVE_TRAIT(H, TRAIT_CULT_EYES, "valid_cultist")
H.cut_overlays()
H.regenerate_icons()
@@ -312,8 +316,10 @@
/datum/team/cult/proc/rise(cultist)
if(ishuman(cultist))
var/mob/living/carbon/human/H = cultist
- H.eye_color = "f00"
- H.dna?.update_ui_block(DNA_EYE_COLOR_BLOCK)
+ H.left_eye_color = "f00"
+ H.right_eye_color = "f00"
+ H.dna?.update_ui_block(DNA_LEFT_EYE_COLOR_BLOCK)
+ H.dna?.update_ui_block(DNA_RIGHT_EYE_COLOR_BLOCK)
ADD_TRAIT(H, TRAIT_CULT_EYES, "valid_cultist")
H.update_body()
diff --git a/code/modules/antagonists/fugitive/fugitive_outfits.dm b/code/modules/antagonists/fugitive/fugitive_outfits.dm
index be11960692..242a7cc7fd 100644
--- a/code/modules/antagonists/fugitive/fugitive_outfits.dm
+++ b/code/modules/antagonists/fugitive/fugitive_outfits.dm
@@ -30,7 +30,8 @@
if(visualsOnly)
return
H.fully_replace_character_name(null,"Waldo")
- H.eye_color = "000"
+ H.left_eye_color = "000"
+ H.right_eye_color = "000"
H.gender = MALE
H.skin_tone = "caucasian3"
H.hair_style = "Business Hair 3"
diff --git a/code/modules/antagonists/traitor/classes/subterfuge.dm b/code/modules/antagonists/traitor/classes/subterfuge.dm
index ad049f3264..07707b69e1 100644
--- a/code/modules/antagonists/traitor/classes/subterfuge.dm
+++ b/code/modules/antagonists/traitor/classes/subterfuge.dm
@@ -23,18 +23,23 @@
maroon_objective.find_target()
T.add_objective(maroon_objective)
else
- if(prob(15) && !(locate(/datum/objective/download) in T.objectives) && !(T.owner.assigned_role in list("Research Director", "Scientist", "Roboticist")))
- var/datum/objective/download/download_objective = new
- download_objective.owner = T.owner
- download_objective.gen_amount_goal()
- T.add_objective(download_objective)
- else if(prob(70)) // cum. not counting download: 40%.
- var/datum/objective/steal/steal_objective = new
- steal_objective.owner = T.owner
- steal_objective.find_target()
- T.add_objective(steal_objective)
- else
- var/datum/objective/sabotage/sabotage_objective = new
- sabotage_objective.owner = T.owner
- sabotage_objective.find_target()
- T.add_objective(sabotage_objective)
+ var/list/weights = list()
+ weights["sabo"] = length(subtypesof(/datum/sabotage_objective))
+ weights["steal"] = length(subtypesof(/datum/objective_item/steal))
+ weights["download"] = !(locate(/datum/objective/download) in T.objectives || (T.owner.assigned_role in list("Research Director", "Scientist", "Roboticist")))
+ switch(pickweight(weights))
+ if("sabo")
+ var/datum/objective/sabotage/sabotage_objective = new
+ sabotage_objective.owner = T.owner
+ sabotage_objective.find_target()
+ T.add_objective(sabotage_objective)
+ if("steal")
+ var/datum/objective/steal/steal_objective = new
+ steal_objective.owner = T.owner
+ steal_objective.find_target()
+ T.add_objective(steal_objective)
+ if("download")
+ var/datum/objective/download/download_objective = new
+ download_objective.owner = T.owner
+ download_objective.gen_amount_goal()
+ T.add_objective(download_objective)
diff --git a/code/modules/arousal/genitals.dm b/code/modules/arousal/genitals.dm
index 65eeca75fe..67de745d22 100644
--- a/code/modules/arousal/genitals.dm
+++ b/code/modules/arousal/genitals.dm
@@ -146,7 +146,7 @@
aroused_state = FALSE
/obj/item/organ/genital/proc/generate_fluid(datum/reagents/R)
- var/amount = clamp((fluid_rate * ((world.time - last_orgasmed) / SSmobs.wait) * fluid_mult),0,fluid_max_volume)
+ var/amount = clamp((fluid_rate * ((world.time - last_orgasmed) / (10 SECONDS)) * fluid_mult),0,fluid_max_volume)
R.clear_reagents()
R.maximum_volume = fluid_max_volume
if(fluid_id)
diff --git a/code/modules/client/preferences.dm b/code/modules/client/preferences.dm
index b219af8b6d..a673012118 100644
--- a/code/modules/client/preferences.dm
+++ b/code/modules/client/preferences.dm
@@ -95,7 +95,9 @@ GLOBAL_LIST_EMPTY(preferences_datums)
var/facial_hair_color = "000000" //Facial hair color
var/skin_tone = "caucasian1" //Skin color
var/use_custom_skin_tone = FALSE
- var/eye_color = "000000" //Eye color
+ var/left_eye_color = "000000" //Eye color
+ var/right_eye_color = "000000"
+ var/split_eye_colors = FALSE
var/datum/species/pref_species = new /datum/species/human() //Mutant race
var/list/features = list("mcolor" = "FFFFFF",
"mcolor2" = "FFFFFF",
@@ -472,15 +474,22 @@ GLOBAL_LIST_EMPTY(preferences_datums)
dat += "Sprite Size: [features["body_size"]*100]%
"
if((EYECOLOR in pref_species.species_traits) && !(NOEYES in pref_species.species_traits))
-
if(!use_skintones && !mutant_colors)
dat += APPEARANCE_CATEGORY_COLUMN
-
- dat += "Eye Color
"
-
- dat += " Change
"
-
- dat += ""
+ if(left_eye_color != right_eye_color)
+ split_eye_colors = TRUE
+ dat += "Heterochromia
"
+ dat += "[split_eye_colors ? "Enabled" : "Disabled"]"
+ if(!split_eye_colors)
+ dat += "Eye Color
"
+ dat += " Change"
+ dat += ""
+ else
+ dat += "Left Eye Color
"
+ dat += " Change"
+ dat += "Right Eye Color
"
+ dat += " Change
"
+ dat += ""
else if(use_skintones || mutant_colors)
dat += ""
@@ -1373,7 +1382,9 @@ GLOBAL_LIST_EMPTY(preferences_datums)
socks = random_socks()
socks_color = random_short_color()
if(BODY_ZONE_PRECISE_EYES)
- eye_color = random_eye_color()
+ var/random_eye_color = random_eye_color()
+ left_eye_color = random_eye_color
+ right_eye_color = random_eye_color
if("s_tone")
skin_tone = random_skin_tone()
use_custom_skin_tone = null
@@ -1557,9 +1568,24 @@ GLOBAL_LIST_EMPTY(preferences_datums)
socks_color = sanitize_hexcolor(n_socks_color, 6)
if("eyes")
- var/new_eyes = input(user, "Choose your character's eye colour:", "Character Preference","#"+eye_color) as color|null
+ var/new_eyes = input(user, "Choose your character's eye colour:", "Character Preference","#"+left_eye_color) as color|null
if(new_eyes)
- eye_color = sanitize_hexcolor(new_eyes, 6)
+ left_eye_color = sanitize_hexcolor(new_eyes, 6)
+ right_eye_color = sanitize_hexcolor(new_eyes, 6)
+
+ if("eye_left")
+ var/new_eyes = input(user, "Choose your character's left eye colour:", "Character Preference","#"+left_eye_color) as color|null
+ if(new_eyes)
+ left_eye_color = sanitize_hexcolor(new_eyes, 6)
+
+ if("eye_right")
+ var/new_eyes = input(user, "Choose your character's right eye colour:", "Character Preference","#"+right_eye_color) as color|null
+ if(new_eyes)
+ right_eye_color = sanitize_hexcolor(new_eyes, 6)
+
+ if("toggle_split_eyes")
+ split_eye_colors = !split_eye_colors
+ right_eye_color = left_eye_color
if("species")
var/result = input(user, "Select a species", "Species Selection") as null|anything in GLOB.roundstart_race_names
@@ -2536,12 +2562,15 @@ GLOBAL_LIST_EMPTY(preferences_datums)
character.gender = gender
character.age = age
- character.eye_color = eye_color
+ character.left_eye_color = left_eye_color
+ character.right_eye_color = right_eye_color
var/obj/item/organ/eyes/organ_eyes = character.getorgan(/obj/item/organ/eyes)
if(organ_eyes)
- if(!initial(organ_eyes.eye_color))
- organ_eyes.eye_color = eye_color
- organ_eyes.old_eye_color = eye_color
+ if(!initial(organ_eyes.left_eye_color))
+ organ_eyes.left_eye_color = left_eye_color
+ organ_eyes.right_eye_color = right_eye_color
+ organ_eyes.old_left_eye_color = left_eye_color
+ organ_eyes.old_right_eye_color = right_eye_color
character.hair_color = hair_color
character.facial_hair_color = facial_hair_color
character.skin_tone = skin_tone
diff --git a/code/modules/client/preferences_savefile.dm b/code/modules/client/preferences_savefile.dm
index 5856a7b6e1..fb8a6b17bd 100644
--- a/code/modules/client/preferences_savefile.dm
+++ b/code/modules/client/preferences_savefile.dm
@@ -5,7 +5,7 @@
// You do not need to raise this if you are adding new values that have sane defaults.
// Only raise this value when changing the meaning/format/name/layout of an existing value
// where you would want the updater procs below to run
-#define SAVEFILE_VERSION_MAX 35
+#define SAVEFILE_VERSION_MAX 36
/*
SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Carn
@@ -204,6 +204,10 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
if(S["species"] == "lizard")
features["mam_snouts"] = features["snout"]
+ if(current_version < 36)
+ left_eye_color = S["eye_color"]
+ right_eye_color = S["eye_color"]
+
/datum/preferences/proc/load_path(ckey,filename="preferences.sav")
if(!ckey)
return
@@ -476,7 +480,8 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
S["age"] >> age
S["hair_color"] >> hair_color
S["facial_hair_color"] >> facial_hair_color
- S["eye_color"] >> eye_color
+ S["left_eye_color"] >> left_eye_color
+ S["right_eye_color"] >> left_eye_color
S["use_custom_skin_tone"] >> use_custom_skin_tone
S["skin_tone"] >> skin_tone
S["hair_style_name"] >> hair_style
@@ -654,7 +659,8 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
age = sanitize_integer(age, AGE_MIN, AGE_MAX, initial(age))
hair_color = sanitize_hexcolor(hair_color, 6, FALSE)
facial_hair_color = sanitize_hexcolor(facial_hair_color, 6, FALSE)
- eye_color = sanitize_hexcolor(eye_color, 6, FALSE)
+ left_eye_color = sanitize_hexcolor(left_eye_color, 6, FALSE)
+ right_eye_color = sanitize_hexcolor(right_eye_color, 6, FALSE)
var/static/allow_custom_skintones
if(isnull(allow_custom_skintones))
@@ -783,7 +789,8 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
WRITE_FILE(S["age"] , age)
WRITE_FILE(S["hair_color"] , hair_color)
WRITE_FILE(S["facial_hair_color"] , facial_hair_color)
- WRITE_FILE(S["eye_color"] , eye_color)
+ WRITE_FILE(S["left_eye_color"] , left_eye_color)
+ WRITE_FILE(S["right_eye_color"] , right_eye_color)
WRITE_FILE(S["use_custom_skin_tone"] , use_custom_skin_tone)
WRITE_FILE(S["skin_tone"] , skin_tone)
WRITE_FILE(S["hair_style_name"] , hair_style)
diff --git a/code/modules/clothing/glasses/_glasses.dm b/code/modules/clothing/glasses/_glasses.dm
index 3f6d21bcd2..11de0124cb 100644
--- a/code/modules/clothing/glasses/_glasses.dm
+++ b/code/modules/clothing/glasses/_glasses.dm
@@ -373,7 +373,7 @@
/obj/item/clothing/glasses/sunglasses/blindfold/white/update_icon(mob/living/carbon/human/user)
if(ishuman(user) && !colored_before)
- add_atom_colour("#[user.eye_color]", FIXED_COLOUR_PRIORITY)
+ add_atom_colour("#[user.left_eye_color]", FIXED_COLOUR_PRIORITY)
colored_before = TRUE
/obj/item/clothing/glasses/sunglasses/blindfold/white/worn_overlays(isinhands = FALSE, icon_file, used_state, style_flags = NONE)
@@ -382,7 +382,7 @@
var/mob/living/carbon/human/H = loc
var/mutable_appearance/M = mutable_appearance('icons/mob/clothing/eyes.dmi', "blindfoldwhite")
M.appearance_flags |= RESET_COLOR
- M.color = "#[H.eye_color]"
+ M.color = "#[H.left_eye_color]"
. += M
/obj/item/clothing/glasses/sunglasses/big
diff --git a/code/modules/clothing/under/jobs/engineering.dm b/code/modules/clothing/under/jobs/engineering.dm
index 5693468b3b..e5340fe411 100644
--- a/code/modules/clothing/under/jobs/engineering.dm
+++ b/code/modules/clothing/under/jobs/engineering.dm
@@ -45,10 +45,18 @@
/obj/item/clothing/under/rank/engineering/engineer/hazard
name = "engineer's hazard jumpsuit"
desc = "A high visibility jumpsuit made from heat and radiation resistant materials."
- icon_state = "hazard"
- item_state = "suit-orange"
+ icon_state = "hazard_orange"
+ item_state = "engi_suit"
alt_covers_chest = TRUE
+/obj/item/clothing/under/rank/engineering/engineer/hazard/green
+ icon_state = "hazard_green"
+ item_state = "g_suit"
+
+/obj/item/clothing/under/rank/engineering/engineer/hazard/white
+ icon_state = "hazard_white"
+ item_state = "gy_suit"
+
/obj/item/clothing/under/rank/engineering/engineer/skirt
name = "engineer's jumpskirt"
desc = "It's an orange high visibility jumpskirt worn by engineers."
diff --git a/code/modules/mining/lavaland/necropolis_chests.dm b/code/modules/mining/lavaland/necropolis_chests.dm
index 82492052a9..a967fea75a 100644
--- a/code/modules/mining/lavaland/necropolis_chests.dm
+++ b/code/modules/mining/lavaland/necropolis_chests.dm
@@ -986,7 +986,8 @@
if(1)
to_chat(user, "Your appearance morphs to that of a very small humanoid ash dragon! You get to look like a freak without the cool abilities.")
H.dna.features = list("mcolor" = "A02720", "tail_lizard" = "Dark Tiger", "tail_human" = "None", "snout" = "Sharp", "horns" = "Curled", "ears" = "None", "wings" = "None", "frills" = "None", "spines" = "Long", "body_markings" = "Dark Tiger Body", "legs" = "Digitigrade")
- H.eye_color = "fee5a3"
+ H.left_eye_color = "fee5a3"
+ H.right_eye_color = "fee5a3"
H.set_species(/datum/species/lizard)
if(2)
to_chat(user, "Your flesh begins to melt! Miraculously, you seem fine otherwise.")
diff --git a/code/modules/mob/dead/new_player/preferences_setup.dm b/code/modules/mob/dead/new_player/preferences_setup.dm
index b77fae68c8..c3c0787aa8 100644
--- a/code/modules/mob/dead/new_player/preferences_setup.dm
+++ b/code/modules/mob/dead/new_player/preferences_setup.dm
@@ -17,7 +17,9 @@
facial_hair_style = random_facial_hair_style(gender)
hair_color = random_short_color()
facial_hair_color = hair_color
- eye_color = random_eye_color()
+ var/random_eye_color = random_eye_color()
+ left_eye_color = random_eye_color
+ right_eye_color = random_eye_color
if(!pref_species)
var/rando_race = pick(GLOB.roundstart_races)
pref_species = new rando_race()
diff --git a/code/modules/mob/living/carbon/human/examine.dm b/code/modules/mob/living/carbon/human/examine.dm
index 16470d81ce..6af171568b 100644
--- a/code/modules/mob/living/carbon/human/examine.dm
+++ b/code/modules/mob/living/carbon/human/examine.dm
@@ -92,7 +92,7 @@
if(!(SLOT_GLASSES in obscured))
if(glasses)
. += "[t_He] [t_has] [glasses.get_examine_string(user)] covering [t_his] eyes."
- else if(eye_color == BLOODCULT_EYE && iscultist(src) && HAS_TRAIT(src, TRAIT_CULT_EYES))
+ else if((left_eye_color == BLOODCULT_EYE || right_eye_color == BLOODCULT_EYE) && iscultist(src) && HAS_TRAIT(src, TRAIT_CULT_EYES))
. += "[t_His] eyes are glowing an unnatural red!"
else if(HAS_TRAIT(src, TRAIT_HIJACKER))
var/obj/item/implant/hijack/H = user.getImplant(/obj/item/implant/hijack)
diff --git a/code/modules/mob/living/carbon/human/human_defines.dm b/code/modules/mob/living/carbon/human/human_defines.dm
index 13456ed61c..a6a3f408dc 100644
--- a/code/modules/mob/living/carbon/human/human_defines.dm
+++ b/code/modules/mob/living/carbon/human/human_defines.dm
@@ -24,7 +24,8 @@
var/facial_hair_style = "Shaved"
//Eye colour
- var/eye_color = "000"
+ var/left_eye_color = "000"
+ var/right_eye_color = "000"
var/skin_tone = "caucasian1" //Skin tone
diff --git a/code/modules/mob/living/carbon/human/species.dm b/code/modules/mob/living/carbon/human/species.dm
index fa9df8dd48..d433ca1821 100644
--- a/code/modules/mob/living/carbon/human/species.dm
+++ b/code/modules/mob/living/carbon/human/species.dm
@@ -570,19 +570,21 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
// eyes
if(!(NOEYES in species_traits))
var/has_eyes = H.getorganslot(ORGAN_SLOT_EYES)
- var/mutable_appearance/eye_overlay
if(!has_eyes)
- eye_overlay = mutable_appearance('icons/mob/human_face.dmi', "eyes_missing", -BODY_LAYER)
+ standing += mutable_appearance('icons/mob/human_face.dmi', "eyes_missing", -BODY_LAYER)
else
- eye_overlay = mutable_appearance('icons/mob/human_face.dmi', "eyes", -BODY_LAYER)
- if((EYECOLOR in species_traits) && has_eyes)
- eye_overlay.color = "#" + H.eye_color
-
- if(OFFSET_EYES in H.dna.species.offset_features)
- eye_overlay.pixel_x += H.dna.species.offset_features[OFFSET_EYES][1]
- eye_overlay.pixel_y += H.dna.species.offset_features[OFFSET_EYES][2]
-
- standing += eye_overlay
+ var/mutable_appearance/left_eye = mutable_appearance('icons/mob/human_face.dmi', "left_eye", -BODY_LAYER)
+ var/mutable_appearance/right_eye = mutable_appearance('icons/mob/human_face.dmi', "right_eye", -BODY_LAYER)
+ if((EYECOLOR in species_traits) && has_eyes)
+ left_eye.color = "#" + H.left_eye_color
+ right_eye.color = "#" + H.right_eye_color
+ if(OFFSET_EYES in offset_features)
+ left_eye.pixel_x += offset_features[OFFSET_EYES][1]
+ left_eye.pixel_y += offset_features[OFFSET_EYES][2]
+ right_eye.pixel_x += offset_features[OFFSET_EYES][1]
+ right_eye.pixel_y += offset_features[OFFSET_EYES][2]
+ standing += left_eye
+ standing += right_eye
//Underwear, Undershirts & Socks
if(!(NO_UNDERWEAR in species_traits))
@@ -783,7 +785,7 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
if(FACEHAIR)
accessory_overlay.color = "#[H.facial_hair_color]"
if(EYECOLOR)
- accessory_overlay.color = "#[H.eye_color]"
+ accessory_overlay.color = "#[H.left_eye_color]"
if(HORNCOLOR)
accessory_overlay.color = "#[H.dna.features["horns_color"]]"
if(WINGCOLOR)
@@ -838,7 +840,7 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
if(FACEHAIR)
extra_accessory_overlay.color = "#[H.facial_hair_color]"
if(EYECOLOR)
- extra_accessory_overlay.color = "#[H.eye_color]"
+ extra_accessory_overlay.color = "#[H.left_eye_color]"
if(HORNCOLOR)
extra_accessory_overlay.color = "#[H.dna.features["horns_color"]]"
diff --git a/code/modules/mob/living/carbon/human/species_types/ipc.dm b/code/modules/mob/living/carbon/human/species_types/ipc.dm
index 806782a8b2..b675925aeb 100644
--- a/code/modules/mob/living/carbon/human/species_types/ipc.dm
+++ b/code/modules/mob/living/carbon/human/species_types/ipc.dm
@@ -5,7 +5,8 @@
default_color = "00FF00"
blacklisted = 0
sexes = 0
- species_traits = list(MUTCOLORS,NOEYES,NOTRANSSTING,HAS_FLESH,HAS_BONE)
+ species_traits = list(MUTCOLORS,NOEYES,NOTRANSSTING,HAS_FLESH,HAS_BONE,HAIR)
+ hair_alpha = 210
inherent_biotypes = MOB_ROBOTIC|MOB_HUMANOID
mutant_bodyparts = list("ipc_screen" = "Blank", "ipc_antenna" = "None")
meat = /obj/item/reagent_containers/food/snacks/meat/slab/human/mutant/ipc
diff --git a/code/modules/mob/living/carbon/human/update_icons.dm b/code/modules/mob/living/carbon/human/update_icons.dm
index 9b39438563..cfb35fbb00 100644
--- a/code/modules/mob/living/carbon/human/update_icons.dm
+++ b/code/modules/mob/living/carbon/human/update_icons.dm
@@ -758,17 +758,22 @@ use_mob_overlay_icon: if FALSE, it will always use the default_icon_file even if
// eyes
if(!(NOEYES in dna.species.species_traits))
var/has_eyes = getorganslot(ORGAN_SLOT_EYES)
- var/mutable_appearance/eye_overlay
if(!has_eyes)
- eye_overlay = mutable_appearance('icons/mob/human_face.dmi', "eyes_missing", -BODY_LAYER)
+ add_overlay(mutable_appearance('icons/mob/human_face.dmi', "eyes_missing", -BODY_LAYER))
else
- eye_overlay = mutable_appearance('icons/mob/human_face.dmi', "eyes", -BODY_LAYER)
- if((EYECOLOR in dna.species.species_traits) && has_eyes)
- eye_overlay.color = "#" + eye_color
- if(OFFSET_EYES in dna.species.offset_features)
- eye_overlay.pixel_x += dna.species.offset_features[OFFSET_EYES][1]
- eye_overlay.pixel_y += dna.species.offset_features[OFFSET_EYES][2]
- add_overlay(eye_overlay)
+ var/mutable_appearance/left_eye = mutable_appearance('icons/mob/human_face.dmi', "left_eye", -BODY_LAYER)
+ var/mutable_appearance/right_eye = mutable_appearance('icons/mob/human_face.dmi', "right_eye", -BODY_LAYER)
+ if((EYECOLOR in dna.species.species_traits) && has_eyes)
+ left_eye.color = "#" + left_eye_color
+ right_eye.color = "#" + right_eye_color
+ if(OFFSET_EYES in dna.species.offset_features)
+ left_eye.pixel_x += dna.species.offset_features[OFFSET_EYES][1]
+ left_eye.pixel_y += dna.species.offset_features[OFFSET_EYES][2]
+ right_eye.pixel_x += dna.species.offset_features[OFFSET_EYES][1]
+ right_eye.pixel_y += dna.species.offset_features[OFFSET_EYES][2]
+ add_overlay(left_eye)
+ add_overlay(right_eye)
+
dna.species.handle_hair(src)
diff --git a/code/modules/mob/living/life.dm b/code/modules/mob/living/life.dm
index 9de75702db..e7727fcedc 100644
--- a/code/modules/mob/living/life.dm
+++ b/code/modules/mob/living/life.dm
@@ -1,5 +1,5 @@
/**
- * Called by SSmobs at (hopefully) an interval of 1 second.
+ * Called by SSmobs at an interval of 2 seconds.
* Splits off into PhysicalLife() and BiologicalLife(). Override those instead of this.
*/
/mob/living/proc/Life(seconds, times_fired)
diff --git a/code/modules/mob/living/simple_animal/parrot.dm b/code/modules/mob/living/simple_animal/parrot.dm
index 4bab410d66..3ca29b6746 100644
--- a/code/modules/mob/living/simple_animal/parrot.dm
+++ b/code/modules/mob/living/simple_animal/parrot.dm
@@ -978,7 +978,8 @@
/mob/living/simple_animal/parrot/Poly/ghost
name = "The Ghost of Poly"
desc = "Doomed to squawk the Earth."
- color = "#FFFFFF77"
+ color = "#FFFFFF"
+ alpha = 77
speak_chance = 20
status_flags = GODMODE
incorporeal_move = INCORPOREAL_MOVE_BASIC
diff --git a/code/modules/power/generator.dm b/code/modules/power/generator.dm
index 93fd9fe3d9..bc921b5b26 100644
--- a/code/modules/power/generator.dm
+++ b/code/modules/power/generator.dm
@@ -66,7 +66,7 @@
var/energy_transfer = delta_temperature*hot_air_heat_capacity*cold_air_heat_capacity/(hot_air_heat_capacity+cold_air_heat_capacity)
var/heat = energy_transfer*(1-efficiency)
- lastgen += LOGISTIC_FUNCTION(1250000,0.0001,delta_temperature,50000)
+ lastgen += LOGISTIC_FUNCTION(500000,0.0009,delta_temperature,10000)
hot_air.set_temperature(hot_air.return_temperature() - energy_transfer/hot_air_heat_capacity)
cold_air.set_temperature(cold_air.return_temperature() + heat/cold_air_heat_capacity)
diff --git a/code/modules/research/designs/misc_designs.dm b/code/modules/research/designs/misc_designs.dm
index 75e862778a..a54fe857e9 100644
--- a/code/modules/research/designs/misc_designs.dm
+++ b/code/modules/research/designs/misc_designs.dm
@@ -375,7 +375,7 @@
materials = list(/datum/material/iron = 1500, /datum/material/silver = 150, /datum/material/glass = 3000)
build_path = /obj/item/lightreplacer
category = list("Equipment")
- departmental_flags = DEPARTMENTAL_FLAG_SERVICE
+ departmental_flags = DEPARTMENTAL_FLAG_SERVICE | DEPARTMENTAL_FLAG_ENGINEERING
/datum/design/normtrash
name = "Trashbag"
diff --git a/code/modules/research/designs/tool_designs.dm b/code/modules/research/designs/tool_designs.dm
index 4fe07cb02f..5ef050efe9 100644
--- a/code/modules/research/designs/tool_designs.dm
+++ b/code/modules/research/designs/tool_designs.dm
@@ -97,7 +97,7 @@
desc = "A new advanced atmospheric analyzer design, capable of performing scans at long range."
id = "ranged_analyzer"
build_type = PROTOLATHE
- materials = list(/datum/material/iron = 400, /datum/material/glass = 1000, /datum/material/uranium = 800, /datum/material/gold = 200, /datum/material/plastic = 200)
+ materials = list(/datum/material/iron = 400, /datum/material/glass = 1000, /datum/material/uranium = 800, /datum/material/gold = 200, /datum/material/diamond = 50)
build_path = /obj/item/analyzer/ranged
category = list("Tool Designs")
departmental_flags = DEPARTMENTAL_FLAG_SCIENCE | DEPARTMENTAL_FLAG_ENGINEERING
diff --git a/code/modules/surgery/bodyparts/head.dm b/code/modules/surgery/bodyparts/head.dm
index 13b1140527..b6a0a387e2 100644
--- a/code/modules/surgery/bodyparts/head.dm
+++ b/code/modules/surgery/bodyparts/head.dm
@@ -180,13 +180,17 @@
. += lips_overlay
// eyes
- var/image/eyes_overlay = image('icons/mob/human_face.dmi', "eyes", -BODY_LAYER, SOUTH)
- . += eyes_overlay
- if(!eyes)
- eyes_overlay.icon_state = "eyes_missing"
-
- else if(eyes.eye_color)
- eyes_overlay.color = "#" + eyes.eye_color
+ if(eyes)
+ var/image/left_eye = image('icons/mob/human_face.dmi', "left_eye", -BODY_LAYER, SOUTH)
+ var/image/right_eye = image('icons/mob/human_face.dmi', "right_eye", -BODY_LAYER, SOUTH)
+ if(eyes.left_eye_color && eyes.right_eye_color)
+ left_eye.color = "#" + eyes.left_eye_color
+ right_eye.color = "#" + eyes.right_eye_color
+ . += left_eye
+ . += right_eye
+ else
+ var/eyes_overlay = image('icons/mob/human_face.dmi', "eyes_missing", -BODY_LAYER, SOUTH)
+ . += eyes_overlay
/obj/item/bodypart/head/monkey
icon = 'icons/mob/animal_parts.dmi'
diff --git a/code/modules/surgery/organs/eyes.dm b/code/modules/surgery/organs/eyes.dm
index f23a03da5b..e3ab44213f 100644
--- a/code/modules/surgery/organs/eyes.dm
+++ b/code/modules/surgery/organs/eyes.dm
@@ -26,8 +26,10 @@
var/sight_flags = 0
var/see_in_dark = 2
var/tint = 0
- var/eye_color = "" //set to a hex code to override a mob's eye color
- var/old_eye_color = "fff"
+ var/left_eye_color = "" //set to a hex code to override a mob's eye color
+ var/right_eye_color = ""
+ var/old_left_eye_color = "fff"
+ var/old_right_eye_color = "fff"
var/flash_protect = 0
var/see_invisible = SEE_INVISIBLE_LIVING
var/lighting_alpha
@@ -44,11 +46,19 @@
owner.become_blind(EYE_DAMAGE)
if(ishuman(owner))
var/mob/living/carbon/human/H = owner
- old_eye_color = H.eye_color
- if(eye_color)
- H.eye_color = eye_color
+ old_left_eye_color = H.left_eye_color
+ old_right_eye_color = H.right_eye_color
+
+ if(left_eye_color)
+ H.left_eye_color = left_eye_color
else
- eye_color = H.eye_color
+ left_eye_color = H.left_eye_color
+
+ if(right_eye_color)
+ H.right_eye_color = right_eye_color
+ else
+ right_eye_color = H.right_eye_color
+
if(!special)
H.dna?.species?.handle_body(H) //regenerate eyeballs overlays.
M.update_tint()
@@ -64,9 +74,10 @@
C.clear_fullscreen("eye_damage")
if(BLIND_VISION_THREE)
C.cure_blind(EYE_DAMAGE)
- if(ishuman(C) && eye_color)
+ if(ishuman(C) && left_eye_color && right_eye_color)
var/mob/living/carbon/human/H = C
- H.eye_color = old_eye_color
+ H.left_eye_color = old_left_eye_color
+ H.right_eye_color = old_right_eye_color
if(!special)
H.dna.species.handle_body(H)
if(!special)
@@ -162,14 +173,16 @@
/obj/item/organ/eyes/robotic/xray
name = "\improper X-ray eyes"
desc = "These cybernetic eyes will give you X-ray vision. Blinking is futile."
- eye_color = "000"
+ left_eye_color = "000"
+ right_eye_color = "000"
see_in_dark = 8
sight_flags = SEE_MOBS | SEE_OBJS | SEE_TURFS
/obj/item/organ/eyes/robotic/thermals
name = "thermal eyes"
desc = "These cybernetic eye implants will give you thermal vision. Vertical slit pupil included."
- eye_color = "FC0"
+ left_eye_color = "FC0"
+ right_eye_color = "FC0"
sight_flags = SEE_MOBS
lighting_alpha = LIGHTING_PLANE_ALPHA_MOSTLY_VISIBLE
flash_protect = -1
@@ -178,7 +191,8 @@
/obj/item/organ/eyes/robotic/flashlight
name = "flashlight eyes"
desc = "It's two flashlights rigged together with some wire. Why would you put these in someone's head?"
- eye_color ="fee5a3"
+ left_eye_color ="fee5a3"
+ right_eye_color ="fee5a3"
icon = 'icons/obj/lighting.dmi'
icon_state = "flashlight_eyes"
flash_protect = 2
@@ -219,7 +233,8 @@
/obj/item/organ/eyes/robotic/glow
name = "High Luminosity Eyes"
desc = "Special glowing eyes, used by snowflakes who want to be special."
- eye_color = "000"
+ left_eye_color = "000"
+ right_eye_color = "000"
actions_types = list(/datum/action/item_action/organ_action/use, /datum/action/item_action/organ_action/toggle)
var/current_color_string = "#ffffff"
var/active = FALSE
@@ -276,7 +291,9 @@
#define MAX_LIGHTNESS 256
/obj/item/organ/eyes/robotic/glow/proc/assume_rgb(newcolor)
- eye_color = RGB2EYECOLORSTRING(newcolor)
+ var/current_color = RGB2EYECOLORSTRING(newcolor)
+ left_eye_color = current_color
+ right_eye_color = current_color
var/list/hsv = ReadHSV(RGBtoHSV(newcolor))
hsv[2] = clamp(hsv[2], 0, MAX_SATURATION)
hsv[3] = clamp(hsv[3], 0, MAX_LIGHTNESS)
diff --git a/code/modules/vending/wardrobes.dm b/code/modules/vending/wardrobes.dm
index 37c21fc2eb..bbe0e40d9b 100644
--- a/code/modules/vending/wardrobes.dm
+++ b/code/modules/vending/wardrobes.dm
@@ -91,6 +91,9 @@
/obj/item/clothing/suit/hooded/wintercoat/engineering = 3,
/obj/item/clothing/under/rank/engineering/engineer = 5,
/obj/item/clothing/under/rank/engineering/engineer/skirt = 5,
+ /obj/item/clothing/under/rank/engineering/engineer/hazard = 5,
+ /obj/item/clothing/under/rank/engineering/engineer/hazard/green = 5,
+ /obj/item/clothing/under/rank/engineering/engineer/hazard/white = 5,
/obj/item/clothing/suit/hazardvest = 5,
/obj/item/clothing/shoes/workboots = 5,
/obj/item/clothing/head/hardhat = 5,
diff --git a/html/changelog.html b/html/changelog.html
index 5650ae6a8a..901d6f8572 100644
--- a/html/changelog.html
+++ b/html/changelog.html
@@ -50,6 +50,24 @@
-->
+
27 September 2020
+
SiliconMain updated:
+
+ - Holograms made from projectors (atmos, engi, sec, medical, ect...) can no longer be contaminated by radiation
+
+
+
26 September 2020
+
CoreFlare updated:
+
+ - IPC's can have hair. Why wasn't this added earlier. Use the bald hairstyle for no hair.
+
+
+
25 September 2020
+
Putnam3145 updated:
+
+ - Removed a non-working proc that already had its functionality implemented in another proc in the same file.
+
+
24 September 2020
Putnam3145 updated:
@@ -1213,81 +1231,6 @@
- modern pickle technology now allows people who have been turned into pickles, to be retrieved through the medical course of dying
-
- 26 July 2020
- DeltaFire15 updated:
-
- - Organs now decay again.
-
- Iatots updated:
-
- - Licking wounds now may cause you to spit out a hairball once in a while!
- - You can now craft a catgirl plushie with 3 of a new ingredient occasionally found in medbay!
-
- dapnee updated:
-
- - removed legacy public mining shuttle area and remade lounge
-
-
- 25 July 2020
- CameronWoof updated:
-
- - Aloe now has an icon.
-
- timothyteakettle updated:
-
- - beepsky replaces the word THREAT_LEVEL with the actual threat level
-
-
- 24 July 2020
- EmeraldSundisk updated:
-
- - Adds a CMO office, along with Virology and Genetics labs to Omega Station
- - Adds a second chemistry station to the chemistry lab
- - Adjusts the locations of some objects in medical to accommodate these new additions
- - Relocates the morgue
- - Relocates items in impacted areas of maintenance as well as the library
- - Fixes an air line Bartholomew somehow knocked out
-
- Linzolle updated:
-
- - wounds now have a description on examine
-
- Owai-Seek updated:
-
- - Meatball Sub, Meatloaf + Meatloaf Slices, Bear Chili, Mashed Potatoes
- - Buttered Potatoes, Fancy Cracker Pack, Spiral Soup, Sweet and Sour Chicken
- - Organised the Food DMI a bit.
- - Deleted some stray pixels on some sprites.
- - Nuggie boxes are now centered correctly.
- - Icons for the the food items in this PR.
-
- Sneakyrat6 updated:
-
- - Fixes dressers not giving you undies
- - Fixes Snaxi not loading properly because of typos
- - You can now burn photos
-
- Zandario updated:
-
- - Murdered **tipes** and gave birth to **is**.
-
- silicons updated:
-
- - sanitization now doesn't cut off 15.7 or something million possible colors from character preferences (instead of only allowing 16 values for R G and B, it now allows 256 each)
- - projectiles are by default 17.5 tiles per second instead of 12.5
-
- timothyteakettle updated:
-
- - due to recent innovative research in the medical field, you now have bones
- - zombie claws are now sharp and do less damage, but can destroy non-lifeforms far faster
- - zombies now take less stamina damage
- - beepsky can now wear hats
-
- zeroisthebiggay updated:
-
- - rad and kravglove sprites
-
GoonStation 13 Development Team
diff --git a/html/changelogs/.all_changelog.yml b/html/changelogs/.all_changelog.yml
index 9d46e34381..864b017314 100644
--- a/html/changelogs/.all_changelog.yml
+++ b/html/changelogs/.all_changelog.yml
@@ -27364,3 +27364,15 @@ DO NOT EDIT THIS FILE BY HAND! AUTOMATICALLY GENERATED BY ss13_genchangelog.py.
2020-09-24:
Putnam3145:
- refactor: Atmos is free.
+2020-09-25:
+ Putnam3145:
+ - bugfix: Removed a non-working proc that already had its functionality implemented
+ in another proc in the same file.
+2020-09-26:
+ CoreFlare:
+ - rscadd: IPC's can have hair. Why wasn't this added earlier. Use the bald hairstyle
+ for no hair.
+2020-09-27:
+ SiliconMain:
+ - tweak: Holograms made from projectors (atmos, engi, sec, medical, ect...) can
+ no longer be contaminated by radiation
diff --git a/html/changelogs/AutoChangeLog-pr-13286.yml b/html/changelogs/AutoChangeLog-pr-13286.yml
new file mode 100644
index 0000000000..fb10542ea5
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-13286.yml
@@ -0,0 +1,4 @@
+author: "timothyteakettle"
+delete-after: True
+changes:
+ - rscadd: "you can now have heterochromia and select individual eye colours"
diff --git a/html/changelogs/AutoChangeLog-pr-13397.yml b/html/changelogs/AutoChangeLog-pr-13397.yml
new file mode 100644
index 0000000000..8045738d9c
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-13397.yml
@@ -0,0 +1,4 @@
+author: "ArchieBeepBoop"
+delete-after: True
+changes:
+ - rscadd: "Craftable Micro Powered Fans"
diff --git a/html/changelogs/AutoChangeLog-pr-13411.yml b/html/changelogs/AutoChangeLog-pr-13411.yml
new file mode 100644
index 0000000000..9c65f02837
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-13411.yml
@@ -0,0 +1,6 @@
+author: "Tupinambis"
+delete-after: True
+changes:
+ - imageadd: "Replaced old chair sprites with new ones ported and modified from eris."
+ - tweak: "Beds can now be placed both right and left."
+ - tweak: "Subtle changes to stool legs to give them more of a shine."
diff --git a/html/changelogs/AutoChangeLog-pr-13412.yml b/html/changelogs/AutoChangeLog-pr-13412.yml
new file mode 100644
index 0000000000..20aad4aa5d
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-13412.yml
@@ -0,0 +1,5 @@
+author: "Putnam3145"
+delete-after: True
+changes:
+ - rscdel: "Supermatter sabotage objective's gone."
+ - balance: "Subterfuge objectives are now all equally likely."
diff --git a/html/changelogs/AutoChangeLog-pr-13413.yml b/html/changelogs/AutoChangeLog-pr-13413.yml
new file mode 100644
index 0000000000..377ea8b762
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-13413.yml
@@ -0,0 +1,4 @@
+author: "Putnam3145"
+delete-after: True
+changes:
+ - balance: "G fuid production is now much lower."
diff --git a/html/changelogs/AutoChangeLog-pr-13414.yml b/html/changelogs/AutoChangeLog-pr-13414.yml
new file mode 100644
index 0000000000..8640abfedf
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-13414.yml
@@ -0,0 +1,4 @@
+author: "Putnam3145"
+delete-after: True
+changes:
+ - spellcheck: "Replaced a \"(hopefully) 1\" with a \"2\""
diff --git a/html/changelogs/AutoChangeLog-pr-13415.yml b/html/changelogs/AutoChangeLog-pr-13415.yml
new file mode 100644
index 0000000000..127559d35b
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-13415.yml
@@ -0,0 +1,4 @@
+author: "Tupinambis"
+delete-after: True
+changes:
+ - imageadd: "Updates TEG, Antimatter, Jetpack sprites (CO2 and Oxy from Eris)."
diff --git a/html/changelogs/AutoChangeLog-pr-13419.yml b/html/changelogs/AutoChangeLog-pr-13419.yml
new file mode 100644
index 0000000000..86b7b65a29
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-13419.yml
@@ -0,0 +1,4 @@
+author: "Degirin2120"
+delete-after: True
+changes:
+ - rscadd: "Added engineering hazard jumpsuits, can be found in the engidrobe, comes in 3 varieties."
diff --git a/html/changelogs/AutoChangeLog-pr-13420.yml b/html/changelogs/AutoChangeLog-pr-13420.yml
new file mode 100644
index 0000000000..1e40c80610
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-13420.yml
@@ -0,0 +1,4 @@
+author: "thakyZ"
+delete-after: True
+changes:
+ - rscadd: "Added the ability to print the Light Replacer at the Engineering Protolathe"
diff --git a/html/changelogs/AutoChangeLog-pr-13421.yml b/html/changelogs/AutoChangeLog-pr-13421.yml
new file mode 100644
index 0000000000..46d64f8545
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-13421.yml
@@ -0,0 +1,4 @@
+author: "raspy-on-osu"
+delete-after: True
+changes:
+ - tweak: "TEG power generation"
diff --git a/html/changelogs/AutoChangeLog-pr-13424.yml b/html/changelogs/AutoChangeLog-pr-13424.yml
new file mode 100644
index 0000000000..980cbe4543
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-13424.yml
@@ -0,0 +1,4 @@
+author: "Putnam3145"
+delete-after: True
+changes:
+ - tweak: "Cryoing no longer unwins already-won objectives."
diff --git a/html/changelogs/AutoChangeLog-pr-13427.yml b/html/changelogs/AutoChangeLog-pr-13427.yml
new file mode 100644
index 0000000000..ca270c0f79
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-13427.yml
@@ -0,0 +1,4 @@
+author: "Trilbyspaceclone"
+delete-after: True
+changes:
+ - tweak: "Most drinks now have some animation in them, from basic soda bubbles fizzing around to ice cubes bobbing just a bit."
diff --git a/html/changelogs/AutoChangeLog-pr-13430.yml b/html/changelogs/AutoChangeLog-pr-13430.yml
deleted file mode 100644
index 94c68481da..0000000000
--- a/html/changelogs/AutoChangeLog-pr-13430.yml
+++ /dev/null
@@ -1,4 +0,0 @@
-author: "Putnam3145"
-delete-after: True
-changes:
- - bugfix: "Removed a non-working proc that already had its functionality implemented in another proc in the same file."
diff --git a/html/changelogs/AutoChangeLog-pr-13432.yml b/html/changelogs/AutoChangeLog-pr-13432.yml
new file mode 100644
index 0000000000..9c7edcd0e1
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-13432.yml
@@ -0,0 +1,4 @@
+author: "SiliconMain"
+delete-after: True
+changes:
+ - tweak: "Minor adjustment to material cost of long range atmos analyzer"
diff --git a/html/changelogs/AutoChangeLog-pr-13436.yml b/html/changelogs/AutoChangeLog-pr-13436.yml
new file mode 100644
index 0000000000..53a7e18056
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-13436.yml
@@ -0,0 +1,4 @@
+author: "Putnam3145"
+delete-after: True
+changes:
+ - tweak: "Added a brute-force check-every-single-tile step to SSair when it has enough time to run."
diff --git a/html/changelogs/AutoChangeLog-pr-13437.yml b/html/changelogs/AutoChangeLog-pr-13437.yml
new file mode 100644
index 0000000000..9249df45a0
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-13437.yml
@@ -0,0 +1,4 @@
+author: "timothyteakettle"
+delete-after: True
+changes:
+ - bugfix: "turrets can once again be broken"
diff --git a/html/changelogs/AutoChangeLog-pr-13439.yml b/html/changelogs/AutoChangeLog-pr-13439.yml
new file mode 100644
index 0000000000..f393f38858
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-13439.yml
@@ -0,0 +1,4 @@
+author: "Tupinambis"
+delete-after: True
+changes:
+ - bugfix: "Ghost poly's color value is now a hex value instead of an oct value. This has been a thing for OVER FIVE YEARS"
diff --git a/icons/mob/clothing/uniform.dmi b/icons/mob/clothing/uniform.dmi
index 8d16ff9a62..6d02f752c3 100644
Binary files a/icons/mob/clothing/uniform.dmi and b/icons/mob/clothing/uniform.dmi differ
diff --git a/icons/mob/clothing/uniform_digi.dmi b/icons/mob/clothing/uniform_digi.dmi
index bcb894033e..e3e0b89a7c 100644
Binary files a/icons/mob/clothing/uniform_digi.dmi and b/icons/mob/clothing/uniform_digi.dmi differ
diff --git a/icons/mob/human_face.dmi b/icons/mob/human_face.dmi
index 8055233ea7..1e67d7baba 100644
Binary files a/icons/mob/human_face.dmi and b/icons/mob/human_face.dmi differ
diff --git a/icons/obj/bedsheets.dmi b/icons/obj/bedsheets.dmi
index 1cc99e09e9..05535334cf 100644
Binary files a/icons/obj/bedsheets.dmi and b/icons/obj/bedsheets.dmi differ
diff --git a/icons/obj/chairs.dmi b/icons/obj/chairs.dmi
index 1c09cf94dc..847d0187c5 100644
Binary files a/icons/obj/chairs.dmi and b/icons/obj/chairs.dmi differ
diff --git a/icons/obj/clothing/uniforms.dmi b/icons/obj/clothing/uniforms.dmi
index 8b90eeb802..0554326e5c 100644
Binary files a/icons/obj/clothing/uniforms.dmi and b/icons/obj/clothing/uniforms.dmi differ
diff --git a/icons/obj/drinks.dmi b/icons/obj/drinks.dmi
index 008618199a..1b28b910c1 100644
Binary files a/icons/obj/drinks.dmi and b/icons/obj/drinks.dmi differ
diff --git a/icons/obj/machines/antimatter.dmi b/icons/obj/machines/antimatter.dmi
index dd71e80ccc..d54ecc21d0 100644
Binary files a/icons/obj/machines/antimatter.dmi and b/icons/obj/machines/antimatter.dmi differ
diff --git a/icons/obj/objects.dmi b/icons/obj/objects.dmi
index b93f878c9e..f14f77585b 100644
Binary files a/icons/obj/objects.dmi and b/icons/obj/objects.dmi differ
diff --git a/icons/obj/power.dmi b/icons/obj/power.dmi
index 1f84da44d4..9544ea77c0 100644
Binary files a/icons/obj/power.dmi and b/icons/obj/power.dmi differ
diff --git a/icons/obj/poweredfans.dmi b/icons/obj/poweredfans.dmi
new file mode 100644
index 0000000000..9df1a4f816
Binary files /dev/null and b/icons/obj/poweredfans.dmi differ
diff --git a/icons/obj/tank.dmi b/icons/obj/tank.dmi
index 00855e6543..0c0d220373 100644
Binary files a/icons/obj/tank.dmi and b/icons/obj/tank.dmi differ
diff --git a/libbyond-extools.so b/libbyond-extools.so
index bdae36893f..63c5729007 100644
Binary files a/libbyond-extools.so and b/libbyond-extools.so differ
diff --git a/modular_citadel/code/modules/custom_loadout/custom_items.dm b/modular_citadel/code/modules/custom_loadout/custom_items.dm
index 8dfb613594..bc9f8bce49 100644
--- a/modular_citadel/code/modules/custom_loadout/custom_items.dm
+++ b/modular_citadel/code/modules/custom_loadout/custom_items.dm
@@ -565,4 +565,6 @@
icon_state = "halo"
item_state = "halo"
icon = 'icons/mob/clothing/custom_w.dmi'
- mob_overlay_icon = 'icons/mob/clothing/custom_w.dmi'
\ No newline at end of file
+ mob_overlay_icon = 'icons/mob/clothing/custom_w.dmi'
+ dynamic_hair_suffix = ""
+
diff --git a/tgstation.dme b/tgstation.dme
index c781c9893a..143f66a656 100644
--- a/tgstation.dme
+++ b/tgstation.dme
@@ -808,6 +808,8 @@
#include "code\game\machinery\mass_driver.dm"
#include "code\game\machinery\navbeacon.dm"
#include "code\game\machinery\PDApainter.dm"
+#include "code\game\machinery\poweredfans\fan_assembly.dm"
+#include "code\game\machinery\poweredfans\poweredfans.dm"
#include "code\game\machinery\quantum_pad.dm"
#include "code\game\machinery\recharger.dm"
#include "code\game\machinery\rechargestation.dm"