diff --git a/code/game/gamemodes/changeling/powers/armblade.dm b/code/game/gamemodes/changeling/powers/armblade.dm
index 139950e900..5ab724789b 100644
--- a/code/game/gamemodes/changeling/powers/armblade.dm
+++ b/code/game/gamemodes/changeling/powers/armblade.dm
@@ -134,4 +134,5 @@
/obj/item/weapon/melee/changeling/claw/greater
name = "hand greatclaw"
force = 20
- armor_penetration = 20
\ No newline at end of file
+ armor_penetration = 20
+ pry = 1
\ No newline at end of file
diff --git a/code/game/gamemodes/cult/ritual.dm b/code/game/gamemodes/cult/ritual.dm
index ca1d5639e9..8db7a49255 100644
--- a/code/game/gamemodes/cult/ritual.dm
+++ b/code/game/gamemodes/cult/ritual.dm
@@ -123,7 +123,7 @@ var/global/list/rnwords = list("ire","ego","nahlizet","certum","veri","jatkaa","
if(word1 == cultwords["hell"] && word2 == cultwords["join"] && word3 == cultwords["self"])
return tearreality()
if(word1 == cultwords["destroy"] && word2 == cultwords["see"] && word3 == cultwords["technology"])
- return emp(src.loc,3)
+ return emp(src.loc,5)
if(word1 == cultwords["travel"] && word2 == cultwords["blood"] && word3 == cultwords["self"])
return drain()
if(word1 == cultwords["see"] && word2 == cultwords["hell"] && word3 == cultwords["join"])
diff --git a/code/modules/client/preference_setup/general/03_body.dm b/code/modules/client/preference_setup/general/03_body.dm
index c6500143f0..73d91129e7 100644
--- a/code/modules/client/preference_setup/general/03_body.dm
+++ b/code/modules/client/preference_setup/general/03_body.dm
@@ -3,6 +3,9 @@ var/global/list/valid_bloodtypes = list("A+", "A-", "B+", "B-", "AB+", "AB-", "O
/datum/preferences
var/equip_preview_mob = EQUIP_PREVIEW_ALL
+ var/icon/bgstate = "000"
+ var/list/bgstate_options = list("000", "fff", "steel", "white")
+
/datum/category_item/player_setup_item/general/body
name = "Body"
sort_order = 3
@@ -34,6 +37,7 @@ var/global/list/valid_bloodtypes = list("A+", "A-", "B+", "B-", "AB+", "AB-", "O
S["synth_green"] >> pref.g_synth
S["synth_blue"] >> pref.b_synth
pref.preview_icon = null
+ S["bgstate"] >> pref.bgstate
/datum/category_item/player_setup_item/general/body/save_character(var/savefile/S)
S["species"] << pref.species
@@ -61,6 +65,7 @@ var/global/list/valid_bloodtypes = list("A+", "A-", "B+", "B-", "AB+", "AB-", "O
S["synth_red"] << pref.r_synth
S["synth_green"] << pref.g_synth
S["synth_blue"] << pref.b_synth
+ S["bgstate"] << pref.bgstate
/datum/category_item/player_setup_item/general/body/sanitize_character(var/savefile/S)
if(!pref.species || !(pref.species in playable_species))
@@ -87,6 +92,8 @@ var/global/list/valid_bloodtypes = list("A+", "A-", "B+", "B-", "AB+", "AB-", "O
if(!pref.rlimb_data) pref.rlimb_data = list()
if(!pref.body_markings) pref.body_markings = list()
else pref.body_markings &= body_marking_styles_list
+ if(!pref.bgstate || !(pref.bgstate in pref.bgstate_options))
+ pref.bgstate = "000"
// Moved from /datum/preferences/proc/copy_to()
/datum/category_item/player_setup_item/general/body/copy_to_mob(var/mob/living/carbon/human/character)
@@ -268,6 +275,7 @@ var/global/list/valid_bloodtypes = list("A+", "A-", "B+", "B-", "AB+", "AB-", "O
. += "
Preview "
. += ""
+ . += " Cycle background"
. += " [pref.equip_preview_mob & EQUIP_PREVIEW_LOADOUT ? "Hide loadout" : "Show loadout"]"
. += " [pref.equip_preview_mob & EQUIP_PREVIEW_JOB ? "Hide job gear" : "Show job gear"]"
. += " | "
@@ -694,6 +702,10 @@ var/global/list/valid_bloodtypes = list("A+", "A-", "B+", "B-", "AB+", "AB-", "O
pref.b_synth = hex2num(copytext(new_color, 6, 8))
return TOPIC_REFRESH_UPDATE_PREVIEW
+ else if(href_list["cycle_bg"])
+ pref.bgstate = next_in_list(pref.bgstate, pref.bgstate_options)
+ return TOPIC_REFRESH_UPDATE_PREVIEW
+
return ..()
/datum/category_item/player_setup_item/general/body/proc/reset_limbs()
diff --git a/code/modules/integrated_electronics/subtypes/input.dm b/code/modules/integrated_electronics/subtypes/input.dm
index d752f0d5cd..00e5bf2ea4 100644
--- a/code/modules/integrated_electronics/subtypes/input.dm
+++ b/code/modules/integrated_electronics/subtypes/input.dm
@@ -619,3 +619,235 @@
activate_pin(2)
+/obj/item/integrated_circuit/input/atmo_scanner
+ name = "integrated atmospheric analyser"
+ desc = "The same atmospheric analysis module that is integrated into every PDA. \
+ This allows the machine to know the composition, temperature and pressure of the surrounding atmosphere."
+ icon_state = "medscan_adv"
+ complexity = 9
+ inputs = list()
+ outputs = list(
+ "pressure" = IC_PINTYPE_NUMBER,
+ "temperature" = IC_PINTYPE_NUMBER,
+ "oxygen" = IC_PINTYPE_NUMBER,
+ "nitrogen" = IC_PINTYPE_NUMBER,
+ "carbon dioxide" = IC_PINTYPE_NUMBER,
+ "phoron" = IC_PINTYPE_NUMBER,
+ "other" = IC_PINTYPE_NUMBER
+ )
+ activators = list("scan" = IC_PINTYPE_PULSE_IN, "on scanned" = IC_PINTYPE_PULSE_OUT)
+ spawn_flags = IC_SPAWN_RESEARCH
+ origin_tech = list(TECH_ENGINEERING = 3, TECH_DATA = 3)
+ power_draw_per_use = 60
+
+/obj/item/integrated_circuit/input/atmo_scanner/do_work()
+ var/turf/T = get_turf(src)
+ if(!istype(T)) //Invalid input
+ return
+ var/datum/gas_mixture/environment = T.return_air()
+
+ var/pressure = environment.return_pressure()
+ var/total_moles = environment.total_moles
+
+ if (total_moles)
+ var/o2_level = environment.gas["oxygen"]/total_moles
+ var/n2_level = environment.gas["nitrogen"]/total_moles
+ var/co2_level = environment.gas["carbon_dioxide"]/total_moles
+ var/phoron_level = environment.gas["phoron"]/total_moles
+ var/unknown_level = 1-(o2_level+n2_level+co2_level+phoron_level)
+ set_pin_data(IC_OUTPUT, 1, pressure)
+ set_pin_data(IC_OUTPUT, 2, round(environment.temperature-T0C,0.1))
+ set_pin_data(IC_OUTPUT, 3, round(o2_level*100,0.1))
+ set_pin_data(IC_OUTPUT, 4, round(n2_level*100,0.1))
+ set_pin_data(IC_OUTPUT, 5, round(co2_level*100,0.1))
+ set_pin_data(IC_OUTPUT, 6, round(phoron_level*100,0.01))
+ set_pin_data(IC_OUTPUT, 7, round(unknown_level, 0.01))
+ else
+ set_pin_data(IC_OUTPUT, 1, 0)
+ set_pin_data(IC_OUTPUT, 2, -273.15)
+ set_pin_data(IC_OUTPUT, 3, 0)
+ set_pin_data(IC_OUTPUT, 4, 0)
+ set_pin_data(IC_OUTPUT, 5, 0)
+ set_pin_data(IC_OUTPUT, 6, 0)
+ set_pin_data(IC_OUTPUT, 7, 0)
+ push_data()
+ activate_pin(2)
+
+/obj/item/integrated_circuit/input/pressure_sensor
+ name = "integrated pressure sensor"
+ desc = "A tiny pressure sensor module similar to that found in a PDA atmosphere analyser."
+ icon_state = "medscan_adv"
+ complexity = 3
+ inputs = list()
+ outputs = list(
+ "pressure" = IC_PINTYPE_NUMBER
+ )
+ activators = list("scan" = IC_PINTYPE_PULSE_IN, "on scanned" = IC_PINTYPE_PULSE_OUT)
+ spawn_flags = IC_SPAWN_RESEARCH
+ origin_tech = list(TECH_ENGINEERING = 3, TECH_DATA = 3)
+ power_draw_per_use = 20
+
+/obj/item/integrated_circuit/input/pressure_sensor/do_work()
+ var/turf/T = get_turf(src)
+ if(!istype(T)) //Invalid input
+ return
+ var/datum/gas_mixture/environment = T.return_air()
+
+ var/pressure = environment.return_pressure()
+ var/total_moles = environment.total_moles
+
+ if (total_moles)
+ set_pin_data(IC_OUTPUT, 1, pressure)
+ else
+ set_pin_data(IC_OUTPUT, 1, 0)
+ push_data()
+ activate_pin(2)
+
+/obj/item/integrated_circuit/input/temperature_sensor
+ name = "integrated temperature sensor"
+ desc = "A tiny temperature sensor module similar to that found in a PDA atmosphere analyser."
+ icon_state = "medscan_adv"
+ complexity = 3
+ inputs = list()
+ outputs = list(
+ "temperature" = IC_PINTYPE_NUMBER
+ )
+ activators = list("scan" = IC_PINTYPE_PULSE_IN, "on scanned" = IC_PINTYPE_PULSE_OUT)
+ spawn_flags = IC_SPAWN_RESEARCH
+ origin_tech = list(TECH_ENGINEERING = 3, TECH_DATA = 3)
+ power_draw_per_use = 20
+
+/obj/item/integrated_circuit/input/temperature_sensor/do_work()
+ var/turf/T = get_turf(src)
+ if(!istype(T)) //Invalid input
+ return
+ var/datum/gas_mixture/environment = T.return_air()
+
+ var/total_moles = environment.total_moles
+
+ if (total_moles)
+ set_pin_data(IC_OUTPUT, 1, round(environment.temperature-T0C,0.1))
+ else
+ set_pin_data(IC_OUTPUT, 1, -273.15)
+ push_data()
+ activate_pin(2)
+
+/obj/item/integrated_circuit/input/oxygen_sensor
+ name = "integrated oxygen sensor"
+ desc = "A tiny oxygen sensor module similar to that found in a PDA atmosphere analyser."
+ icon_state = "medscan_adv"
+ complexity = 3
+ inputs = list()
+ outputs = list(
+ "oxygen" = IC_PINTYPE_NUMBER
+ )
+ activators = list("scan" = IC_PINTYPE_PULSE_IN, "on scanned" = IC_PINTYPE_PULSE_OUT)
+ spawn_flags = IC_SPAWN_RESEARCH
+ origin_tech = list(TECH_ENGINEERING = 3, TECH_DATA = 3)
+ power_draw_per_use = 20
+
+/obj/item/integrated_circuit/input/oxygen_sensor/do_work()
+ var/turf/T = get_turf(src)
+ if(!istype(T)) //Invalid input
+ return
+ var/datum/gas_mixture/environment = T.return_air()
+
+ var/total_moles = environment.total_moles
+
+ if (total_moles)
+ var/o2_level = environment.gas["oxygen"]/total_moles
+ set_pin_data(IC_OUTPUT, 1, round(o2_level*100,0.1))
+ else
+ set_pin_data(IC_OUTPUT, 1, 0)
+ push_data()
+ activate_pin(2)
+
+/obj/item/integrated_circuit/input/co2_sensor
+ name = "integrated co2 sensor"
+ desc = "A tiny carbon dioxide sensor module similar to that found in a PDA atmosphere analyser."
+ icon_state = "medscan_adv"
+ complexity = 3
+ inputs = list()
+ outputs = list(
+ "co2" = IC_PINTYPE_NUMBER
+ )
+ activators = list("scan" = IC_PINTYPE_PULSE_IN, "on scanned" = IC_PINTYPE_PULSE_OUT)
+ spawn_flags = IC_SPAWN_RESEARCH
+ origin_tech = list(TECH_ENGINEERING = 3, TECH_DATA = 3)
+ power_draw_per_use = 20
+
+/obj/item/integrated_circuit/input/co2_sensor/do_work()
+ var/turf/T = get_turf(src)
+ if(!istype(T)) //Invalid input
+ return
+ var/datum/gas_mixture/environment = T.return_air()
+
+ var/total_moles = environment.total_moles
+
+ if (total_moles)
+ var/co2_level = environment.gas["carbon_dioxide"]/total_moles
+ set_pin_data(IC_OUTPUT, 1, round(co2_level*100,0.1))
+ else
+ set_pin_data(IC_OUTPUT, 1, 0)
+ push_data()
+ activate_pin(2)
+
+/obj/item/integrated_circuit/input/nitrogen_sensor
+ name = "integrated nitrogen sensor"
+ desc = "A tiny nitrogen sensor module similar to that found in a PDA atmosphere analyser."
+ icon_state = "medscan_adv"
+ complexity = 3
+ inputs = list()
+ outputs = list(
+ "nitrogen" = IC_PINTYPE_NUMBER
+ )
+ activators = list("scan" = IC_PINTYPE_PULSE_IN, "on scanned" = IC_PINTYPE_PULSE_OUT)
+ spawn_flags = IC_SPAWN_RESEARCH
+ origin_tech = list(TECH_ENGINEERING = 3, TECH_DATA = 3)
+ power_draw_per_use = 20
+
+/obj/item/integrated_circuit/input/nitrogen_sensor/do_work()
+ var/turf/T = get_turf(src)
+ if(!istype(T)) //Invalid input
+ return
+ var/datum/gas_mixture/environment = T.return_air()
+
+ var/total_moles = environment.total_moles
+
+ if (total_moles)
+ var/n2_level = environment.gas["nitrogen"]/total_moles
+ set_pin_data(IC_OUTPUT, 1, round(n2_level*100,0.1))
+ else
+ set_pin_data(IC_OUTPUT, 1, 0)
+ push_data()
+ activate_pin(2)
+
+/obj/item/integrated_circuit/input/phoron_sensor
+ name = "integrated phoron sensor"
+ desc = "A tiny phoron gas sensor module similar to that found in a PDA atmosphere analyser."
+ icon_state = "medscan_adv"
+ complexity = 3
+ inputs = list()
+ outputs = list(
+ "phoron" = IC_PINTYPE_NUMBER
+ )
+ activators = list("scan" = IC_PINTYPE_PULSE_IN, "on scanned" = IC_PINTYPE_PULSE_OUT)
+ spawn_flags = IC_SPAWN_RESEARCH
+ origin_tech = list(TECH_ENGINEERING = 3, TECH_DATA = 3)
+ power_draw_per_use = 20
+
+/obj/item/integrated_circuit/input/phoron_sensor/do_work()
+ var/turf/T = get_turf(src)
+ if(!istype(T)) //Invalid input
+ return
+ var/datum/gas_mixture/environment = T.return_air()
+
+ var/total_moles = environment.total_moles
+
+ if (total_moles)
+ var/phoron_level = environment.gas["phoron"]/total_moles
+ set_pin_data(IC_OUTPUT, 1, round(phoron_level*100,0.1))
+ else
+ set_pin_data(IC_OUTPUT, 1, 0)
+ push_data()
+ activate_pin(2)
\ No newline at end of file
diff --git a/code/modules/mob/living/carbon/human/update_icons.dm b/code/modules/mob/living/carbon/human/update_icons.dm
index 0909ed2575..807d6125c8 100644
--- a/code/modules/mob/living/carbon/human/update_icons.dm
+++ b/code/modules/mob/living/carbon/human/update_icons.dm
@@ -381,11 +381,13 @@ var/global/list/damage_icon_parts = list()
face_standing.Blend(facial_s, ICON_OVERLAY)
if(h_style && !(head && (head.flags_inv & BLOCKHEADHAIR)))
- var/datum/sprite_accessory/hair_style = hair_styles_list[h_style]
+ var/datum/sprite_accessory/hair/hair_style = hair_styles_list[h_style]
if(hair_style && (src.species.get_bodytype(src) in hair_style.species_allowed))
var/icon/hair_s = new/icon("icon" = hair_style.icon, "icon_state" = "[hair_style.icon_state]_s")
+ var/icon/hair_s_add = new/icon("icon" = hair_style.icon_add, "icon_state" = "[hair_style.icon_state]_s")
if(hair_style.do_colouration)
- hair_s.Blend(rgb(r_hair, g_hair, b_hair), ICON_ADD)
+ hair_s.Blend(rgb(r_hair, g_hair, b_hair), ICON_MULTIPLY)
+ hair_s.Blend(hair_s_add, ICON_ADD)
face_standing.Blend(hair_s, ICON_OVERLAY)
diff --git a/code/modules/mob/living/silicon/robot/robot.dm b/code/modules/mob/living/silicon/robot/robot.dm
index f516486f02..2deb4bc0b2 100644
--- a/code/modules/mob/living/silicon/robot/robot.dm
+++ b/code/modules/mob/living/silicon/robot/robot.dm
@@ -9,7 +9,7 @@
health = 200
mob_bump_flag = ROBOT
- mob_swap_flags = ROBOT|MONKEY|SLIME|SIMPLE_ANIMAL
+ mob_swap_flags = ~HEAVY
mob_push_flags = ~HEAVY //trundle trundle
var/lights_on = 0 // Is our integrated light on?
diff --git a/code/modules/mob/living/simple_animal/simple_animal.dm b/code/modules/mob/living/simple_animal/simple_animal.dm
index e1208f644c..eb3d691c66 100644
--- a/code/modules/mob/living/simple_animal/simple_animal.dm
+++ b/code/modules/mob/living/simple_animal/simple_animal.dm
@@ -107,7 +107,7 @@
var/friendly = "nuzzles" // What mobs do to people when they aren't really hostile
var/attack_sound = null // Sound to play when I attack
var/environment_smash = 0 // How much environment damage do I do when I hit stuff?
- var/melee_miss_chance = 25 // percent chance to miss a melee attack.
+ var/melee_miss_chance = 15 // percent chance to miss a melee attack.
var/melee_attack_minDelay = 5 // How long between attacks at least
var/melee_attack_maxDelay = 10 // How long between attacks at most
diff --git a/code/modules/mob/new_player/preferences_setup.dm b/code/modules/mob/new_player/preferences_setup.dm
index 5fa306b7b9..a96524f1f1 100644
--- a/code/modules/mob/new_player/preferences_setup.dm
+++ b/code/modules/mob/new_player/preferences_setup.dm
@@ -258,7 +258,7 @@
mannequin.delete_inventory(TRUE)
dress_preview_mob(mannequin)
- preview_icon = icon('icons/effects/effects.dmi', "nothing")
+ preview_icon = icon('icons/effects/128x48.dmi', bgstate)
preview_icon.Scale(48+32, 16+32)
mannequin.dir = NORTH
diff --git a/code/modules/mob/new_player/sprite_accessories.dm b/code/modules/mob/new_player/sprite_accessories.dm
index 42bc1280e2..752a2b5302 100644
--- a/code/modules/mob/new_player/sprite_accessories.dm
+++ b/code/modules/mob/new_player/sprite_accessories.dm
@@ -45,7 +45,8 @@
/datum/sprite_accessory/hair
- icon = 'icons/mob/Human_face.dmi' // default icon for all hairs
+ icon = 'icons/mob/Human_face_m.dmi' // default icon for all hairs
+ var/icon_add = 'icons/mob/human_face.dmi'
bald
name = "Bald"
diff --git a/code/modules/organs/organ_icon.dm b/code/modules/organs/organ_icon.dm
index 48759ae1cf..914dc8632e 100644
--- a/code/modules/organs/organ_icon.dm
+++ b/code/modules/organs/organ_icon.dm
@@ -89,11 +89,13 @@ var/global/list/limb_icon_cache = list()
overlays |= facial_s
if(owner.h_style && !(owner.head && (owner.head.flags_inv & BLOCKHEADHAIR)))
- var/datum/sprite_accessory/hair_style = hair_styles_list[owner.h_style]
+ var/datum/sprite_accessory/hair/hair_style = hair_styles_list[owner.h_style]
if(hair_style && (species.get_bodytype(owner) in hair_style.species_allowed))
var/icon/hair_s = new/icon("icon" = hair_style.icon, "icon_state" = "[hair_style.icon_state]_s")
+ var/icon/hair_s_add = new/icon("icon" = hair_style.icon_add, "icon_state" = "[hair_style.icon_state]_s")
if(hair_style.do_colouration && islist(h_col) && h_col.len >= 3)
- hair_s.Blend(rgb(h_col[1], h_col[2], h_col[3]), ICON_ADD)
+ hair_s.Blend(rgb(h_col[1], h_col[2], h_col[3]), ICON_MULTIPLY)
+ hair_s.Blend(hair_s_add, ICON_ADD)
overlays |= hair_s
return mob_icon
diff --git a/code/modules/power/apc.dm b/code/modules/power/apc.dm
index eb142aac1e..39ce99d188 100644
--- a/code/modules/power/apc.dm
+++ b/code/modules/power/apc.dm
@@ -681,13 +681,10 @@
else
flick("apc-spark", src)
if (do_after(user,6))
- if(prob(50))
- emagged = 1
- locked = 0
- to_chat(user,"You emag the APC interface.")
- update_icon()
- else
- to_chat(user,"The APC interface refused to unlock.")
+ emagged = 1
+ locked = 0
+ to_chat(user,"You emag the APC interface.")
+ update_icon()
return 1
/obj/machinery/power/apc/attack_hand(mob/user)
diff --git a/icons/effects/128x48.dmi b/icons/effects/128x48.dmi
new file mode 100644
index 0000000000..71038ffdbf
Binary files /dev/null and b/icons/effects/128x48.dmi differ
diff --git a/icons/mob/human_face_m.dmi b/icons/mob/human_face_m.dmi
new file mode 100644
index 0000000000..fda6c68b48
Binary files /dev/null and b/icons/mob/human_face_m.dmi differ