diff --git a/code/_macros.dm b/code/_macros.dm
index 1038b6a2e46..463a7da26d9 100644
--- a/code/_macros.dm
+++ b/code/_macros.dm
@@ -42,6 +42,8 @@
#define isxeno(A) istype(A, /mob/living/simple_animal/xeno)
+#define isopenspace(A) istype(A, /turf/simulated/open)
+
#define isweakref(A) istype(A, /weakref)
#define RANDOM_BLOOD_TYPE pick(4;"O-", 36;"O+", 3;"A-", 28;"A+", 1;"B-", 20;"B+", 1;"AB-", 5;"AB+")
diff --git a/code/game/atoms_movable.dm b/code/game/atoms_movable.dm
index b511c9befd2..fe9f99b0328 100644
--- a/code/game/atoms_movable.dm
+++ b/code/game/atoms_movable.dm
@@ -115,12 +115,7 @@
else if(isturf(hit_atom))
src.throwing = 0
var/turf/T = hit_atom
- if(T.density)
- spawn(2)
- step(src, turn(src.last_move, 180))
- if(istype(src,/mob/living))
- var/mob/living/M = src
- M.turf_collision(T, speed)
+ T.hitby(src,speed)
//decided whether a movable atom being thrown can pass through the turf it is in.
/atom/movable/proc/hit_check(var/speed)
diff --git a/code/game/gamemodes/changeling/changeling_powers.dm b/code/game/gamemodes/changeling/changeling_powers.dm
index a60faeb8308..2234e0a540a 100644
--- a/code/game/gamemodes/changeling/changeling_powers.dm
+++ b/code/game/gamemodes/changeling/changeling_powers.dm
@@ -13,6 +13,8 @@ var/global/list/possible_changeling_IDs = list("Alpha","Beta","Gamma","Delta","E
var/isabsorbing = 0
var/geneticpoints = 5
var/max_geneticpoints = 5
+ var/readapts = 1
+ var/max_readapts = 2
var/list/purchased_powers = list()
var/mimicing = ""
var/cloaked = 0
@@ -60,6 +62,7 @@ var/global/list/possible_changeling_IDs = list("Alpha","Beta","Gamma","Delta","E
if(!mind.changeling) mind.changeling = new /datum/changeling(gender)
verbs += /datum/changeling/proc/EvolutionMenu
+ verbs += /mob/proc/changeling_respec
add_language("Changeling")
var/lesser_form = !ishuman(src)
diff --git a/code/game/gamemodes/changeling/powers/absorb.dm b/code/game/gamemodes/changeling/powers/absorb.dm
index 10cb5f9fbbe..396e6faf347 100644
--- a/code/game/gamemodes/changeling/powers/absorb.dm
+++ b/code/game/gamemodes/changeling/powers/absorb.dm
@@ -72,7 +72,12 @@
if(src.nutrition < 400)
src.nutrition = min((src.nutrition + T.nutrition), 400)
changeling.chem_charges += 10
- src.verbs += /mob/proc/changeling_respec
+ if(changeling.readapts <= 0)
+ changeling.readapts = 0 //SANITYYYYYY
+ changeling.readapts++
+ if(changeling.readapts > changeling.max_readapts)
+ changeling.readapts = changeling.max_readapts
+
src << "We can now re-adapt, reverting our evolution so that we may start anew, if needed."
var/datum/absorbed_dna/newDNA = new(T.real_name, T.dna, T.species.name, T.languages, T.identifying_gender, T.flavor_texts)
diff --git a/code/game/gamemodes/changeling/powers/bioelectrogenesis.dm b/code/game/gamemodes/changeling/powers/bioelectrogenesis.dm
index 3068f1eee56..c173ba55acc 100644
--- a/code/game/gamemodes/changeling/powers/bioelectrogenesis.dm
+++ b/code/game/gamemodes/changeling/powers/bioelectrogenesis.dm
@@ -24,7 +24,7 @@
if(held_item == null)
if(src.mind.changeling.recursive_enhancement)
- if(changeling_generic_weapon(/obj/item/weapon/electric_hand/efficent))
+ if(changeling_generic_weapon(/obj/item/weapon/electric_hand/efficent,0))
src << "We will shock others more efficently."
return 1
else
diff --git a/code/game/gamemodes/changeling/powers/respec.dm b/code/game/gamemodes/changeling/powers/respec.dm
index efdf67ec6b0..d984083aba9 100644
--- a/code/game/gamemodes/changeling/powers/respec.dm
+++ b/code/game/gamemodes/changeling/powers/respec.dm
@@ -6,9 +6,14 @@
var/datum/changeling/changeling = changeling_power(0,0,100)
if(!changeling)
return
+ if(src.mind.changeling.readapts <= 0)
+ to_chat(src, "We must first absorb another compatable creature!")
+ src.mind.changeling.readapts = 0
+ return
src.remove_changeling_powers() //First, remove the verbs.
var/datum/changeling/ling_datum = src.mind.changeling
+ ling_datum.readapts--
ling_datum.purchased_powers = list() //Then wipe all the powers we bought.
ling_datum.geneticpoints = ling_datum.max_geneticpoints //Now refund our points to the maximum.
ling_datum.chem_recharge_rate = 0.5 //If glands were bought, revert that upgrade.
@@ -26,4 +31,4 @@
ling_datum.purchased_powers_history.Add("Re-adapt (Reset to [ling_datum.max_geneticpoints])")
//Now to lose the verb, so no unlimited resets.
- src.verbs -= /mob/proc/changeling_respec
\ No newline at end of file
+
diff --git a/code/game/machinery/doors/blast_door.dm b/code/game/machinery/doors/blast_door.dm
index 209e3bb228f..3d899377cca 100644
--- a/code/game/machinery/doors/blast_door.dm
+++ b/code/game/machinery/doors/blast_door.dm
@@ -12,6 +12,7 @@
desc = "That looks like it doesn't open easily."
icon = 'icons/obj/doors/rapid_pdoor.dmi'
icon_state = null
+ min_force = 20 //minimum amount of force needed to damage the door with a melee weapon
// Icon states for different shutter types. Simply change this instead of rewriting the update_icon proc.
var/icon_state_open = null
@@ -78,7 +79,10 @@
// Proc: force_toggle()
// Parameters: None
// Description: Opens or closes the door, depending on current state. No checks are done inside this proc.
-/obj/machinery/door/blast/proc/force_toggle()
+/obj/machinery/door/blast/proc/force_toggle(var/forced = 0, mob/user as mob)
+ if (forced)
+ playsound(src.loc, 'sound/machines/airlock_creaking.ogg', 100, 1)
+
if(src.density)
src.force_open()
else
@@ -91,7 +95,7 @@
/obj/machinery/door/blast/attackby(obj/item/weapon/C as obj, mob/user as mob)
src.add_fingerprint(user)
if(istype(C, /obj/item/weapon)) // For reasons unknown, sometimes C is actually not what it is advertised as, like a mob.
- if(C.pry == 1) // Can we pry it open with something, like a crowbar/fireaxe/lingblade?
+ if(C.pry == 1 && (user.a_intent != I_HURT || (stat & BROKEN))) // Can we pry it open with something, like a crowbar/fireaxe/lingblade?
if(istype(C,/obj/item/weapon/material/twohanded/fireaxe)) // Fireaxes need to be in both hands to pry.
var/obj/item/weapon/material/twohanded/fireaxe/F = C
if(!F.wielded)
@@ -100,7 +104,8 @@
// If we're at this point, it's a fireaxe in both hands or something else that doesn't care for twohanding.
if(((stat & NOPOWER) || (stat & BROKEN)) && !( src.operating ))
- force_toggle()
+ force_toggle(1, user)
+
else
usr << "[src]'s motors resist your effort."
return
@@ -123,15 +128,33 @@
usr << "You don't have enough sheets to repair this! You need at least [amt] sheets."
+ else if(src.density)
+ var/obj/item/weapon/W = C
+ user.setClickCooldown(DEFAULT_ATTACK_COOLDOWN)
+ if(W.damtype == BRUTE || W.damtype == BURN)
+ user.do_attack_animation(src)
+ if(W.force < min_force)
+ user.visible_message("\The [user] hits \the [src] with \the [W] with no visible effect.")
+ else
+ user.visible_message("\The [user] forcefully strikes \the [src] with \the [W]!")
+ playsound(src.loc, hitsound, 100, 1)
+ take_damage(W.force*0.35) //it's a blast door, it should take a while. -Luke
+ return
+
// Proc: open()
// Parameters: None
// Description: Opens the door. Does necessary checks. Automatically closes if autoclose is true
-/obj/machinery/door/blast/open()
- if (src.operating || (stat & BROKEN || stat & NOPOWER))
- return
- force_open()
- if(autoclose)
+/obj/machinery/door/blast/open(var/forced = 0)
+ if(forced)
+ force_open()
+ return 1
+ else
+ if (src.operating || (stat & BROKEN || stat & NOPOWER))
+ return 1
+ force_open()
+
+ if(autoclose && src.operating && !(stat & BROKEN || stat & NOPOWER))
spawn(150)
close()
return 1
diff --git a/code/game/machinery/doors/door.dm b/code/game/machinery/doors/door.dm
index 185de7f06db..cd38f9f1ceb 100644
--- a/code/game/machinery/doors/door.dm
+++ b/code/game/machinery/doors/door.dm
@@ -312,6 +312,8 @@
/obj/machinery/door/examine(mob/user)
. = ..()
+ if(src.health <= 0)
+ user << "\The [src] is broken!"
if(src.health < src.maxhealth / 4)
user << "\The [src] looks like it's about to break!"
else if(src.health < src.maxhealth / 2)
diff --git a/code/game/objects/items/weapons/material/material_armor.dm b/code/game/objects/items/weapons/material/material_armor.dm
new file mode 100644
index 00000000000..1041fb5d1fd
--- /dev/null
+++ b/code/game/objects/items/weapons/material/material_armor.dm
@@ -0,0 +1,263 @@
+#define MATERIAL_ARMOR_COEFFICENT 0.05
+/*
+SEE code/modules/materials/materials.dm FOR DETAILS ON INHERITED DATUM.
+This class of armor takes armor and appearance data from a material "datum".
+They are also fragile based on material data and many can break/smash apart when hit.
+
+Materials has a var called protectiveness which plays a major factor in how good it is for armor.
+With the coefficent being 0.05, this is how strong different levels of protectiveness are (for melee)
+For bullets and lasers, material hardness and reflectivity also play a major role, respectively.
+
+
+Protectiveness | Armor %
+ 0 = 0%
+ 5 = 20%
+ 10 = 33%
+ 15 = 42%
+ 20 = 50%
+ 25 = 55%
+ 30 = 60%
+ 40 = 66%
+ 50 = 71%
+ 60 = 75%
+ 70 = 77%
+ 80 = 80%
+*/
+
+
+// Putting these at /clothing/ level saves a lot of code duplication in armor/helmets/gauntlets/etc
+/obj/item/clothing
+ var/material/material = null // Why isn't this a datum?
+ var/applies_material_color = TRUE
+ var/unbreakable = FALSE
+ var/default_material = null // Set this to something else if you want material attributes on init.
+ var/material_armor_modifer = 1 // Adjust if you want seperate types of armor made from the same material to have different protectiveness (e.g. makeshift vs real armor)
+
+/obj/item/clothing/New(var/newloc, var/material_key)
+ ..(newloc)
+ if(!material_key)
+ material_key = default_material
+ if(material_key) // May still be null if a material was not specified as a default.
+ set_material(material_key)
+
+/obj/item/clothing/Destroy()
+ processing_objects -= src
+ ..()
+
+/obj/item/clothing/get_material()
+ return material
+
+// Debating if this should be made an /obj/item/ proc.
+/obj/item/clothing/proc/set_material(var/new_material)
+ material = get_material_by_name(new_material)
+ if(!material)
+ qdel(src)
+ else
+ name = "[material.display_name] [initial(name)]"
+ health = round(material.integrity/10)
+ if(applies_material_color)
+ color = material.icon_colour
+ if(material.products_need_process())
+ processing_objects |= src
+ update_armor()
+
+// This is called when someone wearing the object gets hit in some form (melee, bullet_act(), etc).
+// Note that this cannot change if someone gets hurt, as it merely reacts to being hit.
+/obj/item/clothing/proc/clothing_impact(var/obj/source, var/damage)
+ if(material && damage)
+ material_impact(source, damage)
+
+/obj/item/clothing/proc/material_impact(var/obj/source, var/damage)
+ if(!material || unbreakable)
+ return
+
+ if(istype(source, /obj/item/projectile))
+ var/obj/item/projectile/P = source
+ if(P.pass_flags & PASSGLASS)
+ if(material.opacity - 0.3 <= 0)
+ return // Lasers ignore 'fully' transparent material.
+
+ if(material.is_brittle())
+ health = 0
+ else if(!prob(material.hardness))
+ health--
+
+ if(health <= 0)
+ shatter()
+
+/obj/item/clothing/proc/shatter()
+ if(!material)
+ return
+ var/turf/T = get_turf(src)
+ T.visible_message("\The [src] [material.destruction_desc]!")
+ if(istype(loc, /mob/living))
+ var/mob/living/M = loc
+ M.drop_from_inventory(src)
+ if(material.shard_type == SHARD_SHARD) // Wearing glass armor is a bad idea.
+ var/obj/item/weapon/material/shard/S = material.place_shard(T)
+ M.embed(S)
+
+ playsound(src, "shatter", 70, 1)
+ qdel(src)
+
+// Might be best to make ablative vests a material armor using a new material to cut down on this copypaste.
+/obj/item/clothing/suit/armor/handle_shield(mob/user, var/damage, atom/damage_source = null, mob/attacker = null, var/def_zone = null, var/attack_text = "the attack")
+ if(!material) // No point checking for reflection.
+ return ..()
+
+ if(material.reflectivity)
+ if(istype(damage_source, /obj/item/projectile/energy) || istype(damage_source, /obj/item/projectile/beam))
+ var/obj/item/projectile/P = damage_source
+
+ if(P.reflected) // Can't reflect twice
+ return ..()
+
+ var/reflectchance = (40 * material.reflectivity) - round(damage/3)
+ reflectchance *= material_armor_modifer
+ if(!(def_zone in list(BP_TORSO, BP_GROIN)))
+ reflectchance /= 2
+ if(P.starting && prob(reflectchance))
+ visible_message("\The [user]'s [src.name] reflects [attack_text]!")
+
+ // Find a turf near or on the original location to bounce to
+ var/new_x = P.starting.x + pick(0, 0, 0, 0, 0, -1, 1, -2, 2)
+ var/new_y = P.starting.y + pick(0, 0, 0, 0, 0, -1, 1, -2, 2)
+ var/turf/curloc = get_turf(user)
+
+ // redirect the projectile
+ P.redirect(new_x, new_y, curloc, user)
+ P.reflected = 1
+
+ return PROJECTILE_CONTINUE // complete projectile permutation
+
+/proc/calculate_material_armor(amount)
+ var/result = 1 - MATERIAL_ARMOR_COEFFICENT * amount / (1 + MATERIAL_ARMOR_COEFFICENT * abs(amount))
+ result = result * 100
+ result = abs(result - 100)
+ return round(result)
+
+
+/obj/item/clothing/proc/update_armor()
+ if(material)
+ var/melee_armor = 0, bullet_armor = 0, laser_armor = 0, energy_armor = 0, bomb_armor = 0
+
+ melee_armor = calculate_material_armor(material.protectiveness * material_armor_modifer)
+
+ bullet_armor = calculate_material_armor((material.protectiveness * (material.hardness / 100) * material_armor_modifer) * 0.7)
+
+ laser_armor = calculate_material_armor((material.protectiveness * (material.reflectivity + 1) * material_armor_modifer) * 0.7)
+ if(material.opacity != 1)
+ laser_armor *= max(material.opacity - 0.3, 0) // Glass and such has an opacity of 0.3, but lasers should go through glass armor entirely.
+
+ energy_armor = calculate_material_armor((material.protectiveness * material_armor_modifer) * 0.4)
+
+ bomb_armor = calculate_material_armor((material.protectiveness * material_armor_modifer) * 0.5)
+
+ // Makes sure the numbers stay capped.
+ for(var/number in list(melee_armor, bullet_armor, laser_armor, energy_armor, bomb_armor))
+ number = between(0, number, 100)
+
+ armor["melee"] = melee_armor
+ armor["bullet"] = bullet_armor
+ armor["laser"] = laser_armor
+ armor["energy"] = energy_armor
+ armor["bomb"] = bomb_armor
+
+ if(!isnull(material.conductivity))
+ siemens_coefficient = between(0, material.conductivity / 10, 10)
+ slowdown = between(0, round(material.weight / 10, 0.1), 6)
+
+/obj/item/clothing/suit/armor/material
+ name = "armor"
+ default_material = DEFAULT_WALL_MATERIAL
+
+/obj/item/clothing/suit/armor/material/makeshift
+ name = "sheet armor"
+ desc = "This appears to be two 'sheets' of a material held together by cable. If the sheets are strong, this could be rather protective."
+ icon_state = "material_armor_makeshift"
+
+/obj/item/clothing/suit/armor/material/makeshift/durasteel
+ default_material = "durasteel"
+
+/obj/item/clothing/suit/armor/material/makeshift/glass
+ default_material = "glass"
+
+// Used to craft sheet armor, and possibly other things in the Future(tm).
+/obj/item/weapon/material/armor_plating
+ name = "armor plating"
+ desc = "A sheet designed to protect something."
+ icon = 'icons/obj/items.dmi'
+ icon_state = "armor_plate"
+ unbreakable = TRUE
+ force_divisor = 0.05 // Really bad as a weapon.
+ thrown_force_divisor = 0.2
+ var/wired = FALSE
+
+/obj/item/weapon/material/armor_plating/attackby(var/obj/O, mob/user)
+ if(istype(O, /obj/item/stack/cable_coil))
+ var/obj/item/stack/cable_coil/S = O
+ if(wired)
+ to_chat(user, "This already has enough wires on it.")
+ return
+ if(S.use(20))
+ to_chat(user, "You attach several wires to \the [src]. Now it needs another plate.")
+ wired = TRUE
+ icon_state = "[initial(icon_state)]_wired"
+ return
+ else
+ to_chat(user, "You need more wire for that.")
+ return
+ if(istype(O, /obj/item/weapon/material/armor_plating))
+ var/obj/item/weapon/material/armor_plating/second_plate = O
+ if(!wired && !second_plate.wired)
+ to_chat(user, "You need something to hold the two pieces of plating together.")
+ return
+ if(second_plate.material != src.material)
+ to_chat(user, "Both plates need to be the same type of material.")
+ return
+ user.drop_from_inventory(src)
+ user.drop_from_inventory(second_plate)
+ var/obj/item/clothing/suit/armor/material/makeshift/new_armor = new(null, src.material.name)
+ user.put_in_hands(new_armor)
+ qdel(second_plate)
+ qdel(src)
+ else
+ ..()
+
+
+// Used to craft the makeshift helmet
+/obj/item/clothing/head/helmet/bucket
+ name = "bucket"
+ desc = "It's a bucket with a large hole cut into it. You could wear it on your head and look really stupid."
+ flags_inv = HIDEEARS|HIDEEYES|BLOCKHAIR
+ icon_state = "bucket"
+ armor = list(melee = 5, bullet = 0, laser = 0, energy = 0, bomb = 0, bio = 0, rad = 0)
+
+/obj/item/clothing/head/helmet/bucket/attackby(var/obj/O, mob/user)
+ if(istype(O, /obj/item/stack/material))
+ var/obj/item/stack/material/S = O
+ if(S.use(2))
+ to_chat(user, "You apply some [S.material.use_name] to \the [src]. Hopefully it'll make the makeshift helmet stronger.")
+ var/obj/item/clothing/head/helmet/material/makeshift/helmet = new(null, S.material.name)
+ user.put_in_hands(helmet)
+ user.drop_from_inventory(src)
+ qdel(src)
+ return
+ else
+ to_chat(user, "You don't have enough material to build a helmet!")
+ else
+ ..()
+
+/obj/item/clothing/head/helmet/material
+ name = "helmet"
+ flags_inv = HIDEEARS|HIDEEYES|BLOCKHAIR
+ default_material = DEFAULT_WALL_MATERIAL
+
+/obj/item/clothing/head/helmet/material/makeshift
+ name = "bucket"
+ desc = "A bucket with plating applied to the outside. Very crude, but could potentially be rather protective, if \
+ it was plated with something strong."
+ icon_state = "material_armor_makeshift"
+
+/obj/item/clothing/head/helmet/material/makeshift/durasteel
+ default_material = "durasteel"
\ No newline at end of file
diff --git a/code/game/turfs/turf.dm b/code/game/turfs/turf.dm
index c13b4606d36..028223ef26f 100644
--- a/code/game/turfs/turf.dm
+++ b/code/game/turfs/turf.dm
@@ -243,3 +243,11 @@ var/const/enterloopsanity = 100
/turf/proc/update_blood_overlays()
return
+// Called when turf is hit by a thrown object
+/turf/hitby(atom/movable/AM as mob|obj, var/speed)
+ if(src.density)
+ spawn(2)
+ step(AM, turn(AM.last_move, 180))
+ if(isliving(AM))
+ var/mob/living/M = AM
+ M.turf_collision(src, speed)
diff --git a/code/modules/clothing/suits/armor.dm b/code/modules/clothing/suits/armor.dm
index d08726371a9..f0903123205 100644
--- a/code/modules/clothing/suits/armor.dm
+++ b/code/modules/clothing/suits/armor.dm
@@ -80,6 +80,9 @@
if(istype(damage_source, /obj/item/projectile/energy) || istype(damage_source, /obj/item/projectile/beam))
var/obj/item/projectile/P = damage_source
+ if(P.reflected) // Can't reflect twice
+ return ..()
+
var/reflectchance = 40 - round(damage/3)
if(!(def_zone in list(BP_TORSO, BP_GROIN)))
reflectchance /= 2
diff --git a/code/modules/lore_codex/lore_data/species.dm b/code/modules/lore_codex/lore_data/species.dm
index fa8c6d96152..54d72e07182 100644
--- a/code/modules/lore_codex/lore_data/species.dm
+++ b/code/modules/lore_codex/lore_data/species.dm
@@ -38,16 +38,11 @@
/datum/lore/codex/page/unathi
name = "Unathi"
- data = "The author wishes to apologize to the reader, as they currently lack enough knowledge of the Unathi to write about them, as they are \
- rather rare inside Vir." // Replace this when Anewbe finishes the lizard rewrite.
- /*
- data = "Raging in from Moghes, the Unathi are a race of tall, reptilian humanoids that possess both crocodile-like and serpent-like features. \
- They are a proud, warlike species that favors honor and strength, their home, Moghes, is a desert planet but was once believed to be full of life. \
- Of all the currently known sentient species, the Unathi are the most unequal in gender with females tending to be property of the males. Most Unathi \
- outside of Moghes tend to be exiles however, and with influence of other species the gender difference is not nearly as pronounced. Unathi were \
- humanity's second contact, and despite their aggressive nature, seem to get along well enough with humanity, though are often considered to be \
- 'second-class' citizens and are rarely seen in jobs other than where muscle is needed." // This probably needs to be updated.
- */
+ data = "The Unathi are a race of tall, reptilian humanoids that possess a blend of serpentine features reminiscent of crocodiles. \
+ They are a proud, religious species that favors honor and strength, and originate from the desert planet of Moghes. \
+ The Unathi follow a religious code known as the Unity, and they carry this with them on their travels. \
+ Unathi once fought a serious war against SolGov, and as a result are often considered to be second-class citizens, \
+ rarely seen in jobs that don't require a little muscle."
/datum/lore/codex/page/tajaran
name = "Tajaran"
diff --git a/code/modules/materials/material_recipes.dm b/code/modules/materials/material_recipes.dm
index 11f6021c75b..68fb129108e 100644
--- a/code/modules/materials/material_recipes.dm
+++ b/code/modules/materials/material_recipes.dm
@@ -10,6 +10,7 @@
recipes += new/datum/stack_recipe("[display_name] baseball bat", /obj/item/weapon/material/twohanded/baseballbat, 10, time = 20, one_per_turf = 0, on_floor = 1, supplied_material = "[name]")
recipes += new/datum/stack_recipe("[display_name] ashtray", /obj/item/weapon/material/ashtray, 2, one_per_turf = 1, on_floor = 1, supplied_material = "[name]")
recipes += new/datum/stack_recipe("[display_name] spoon", /obj/item/weapon/material/kitchen/utensil/spoon/plastic, 1, on_floor = 1, supplied_material = "[name]")
+ recipes += new/datum/stack_recipe("[display_name] armor plate", /obj/item/weapon/material/armor_plating, 1, time = 20, on_floor = 1, supplied_material = "[name]")
if(integrity>=50)
recipes += new/datum/stack_recipe("[display_name] door", /obj/structure/simple_door, 10, one_per_turf = 1, on_floor = 1, supplied_material = "[name]")
diff --git a/code/modules/materials/materials.dm b/code/modules/materials/materials.dm
index 66dde62a17c..921b28d733e 100644
--- a/code/modules/materials/materials.dm
+++ b/code/modules/materials/materials.dm
@@ -90,10 +90,12 @@ var/list/name_to_material
var/ignition_point // K, point at which the material catches on fire.
var/melting_point = 1800 // K, walls will take damage if they're next to a fire hotter than this
var/integrity = 150 // General-use HP value for products.
+ var/protectiveness = 10 // How well this material works as armor. Higher numbers are better, diminishing returns applies.
var/opacity = 1 // Is the material transparent? 0.5< makes transparent walls/doors.
- var/reflectivity = 0 // How reflective to light is the material? Currently used for laser defense.
+ var/reflectivity = 0 // How reflective to light is the material? Currently used for laser reflection and defense.
var/explosion_resistance = 5 // Only used by walls currently.
var/conductive = 1 // Objects with this var add CONDUCTS to flags on spawn.
+ var/conductivity = null // How conductive the material is. Iron acts as the baseline, at 10.
var/list/composite_material // If set, object matter var will be a list containing these values.
// Placeholder vars for the time being, todo properly integrate windows/light tiles/rods.
@@ -103,7 +105,7 @@ var/list/name_to_material
var/list/window_options = list()
// Damage values.
- var/hardness = 60 // Prob of wall destruction by hulk, used for edge damage in weapons.
+ var/hardness = 60 // Prob of wall destruction by hulk, used for edge damage in weapons. Also used for bullet protection in armor.
var/weight = 20 // Determines blunt damage/throwforce for weapons.
// Noise when someone is faceplanted onto a table made of this material.
@@ -236,6 +238,7 @@ var/list/name_to_material
icon_colour = "#00FFE1"
opacity = 0.4
reflectivity = 0.6
+ conductivity = 1
shard_type = SHARD_SHARD
tableslam_noise = 'sound/effects/Glasshit.ogg'
hardness = 100
@@ -247,6 +250,7 @@ var/list/name_to_material
icon_colour = "#EDD12F"
weight = 24
hardness = 40
+ conductivity = 41
stack_origin_tech = list(TECH_MATERIAL = 4)
sheet_singular_name = "ingot"
sheet_plural_name = "ingots"
@@ -261,6 +265,7 @@ var/list/name_to_material
icon_colour = "#D1E6E3"
weight = 22
hardness = 50
+ conductivity = 63
stack_origin_tech = list(TECH_MATERIAL = 3)
sheet_singular_name = "ingot"
sheet_plural_name = "ingots"
@@ -304,6 +309,8 @@ var/list/name_to_material
shard_type = SHARD_STONE_PIECE
weight = 22
hardness = 55
+ protectiveness = 5 // 20%
+ conductivity = 5
door_icon_base = "stone"
sheet_singular_name = "brick"
sheet_plural_name = "bricks"
@@ -320,6 +327,8 @@ var/list/name_to_material
name = DEFAULT_WALL_MATERIAL
stack_type = /obj/item/stack/material/steel
integrity = 150
+ conductivity = 11 // Assuming this is carbon steel, it would actually be slightly less conductive than iron, but lets ignore that.
+ protectiveness = 10 // 33%
icon_base = "solid"
icon_reinf = "reinf_over"
icon_colour = "#666666"
@@ -355,6 +364,8 @@ var/list/name_to_material
explosion_resistance = 25
hardness = 80
weight = 23
+ protectiveness = 20 // 50%
+ conductivity = 13 // For the purposes of balance.
stack_origin_tech = list(TECH_MATERIAL = 2)
composite_material = list(DEFAULT_WALL_MATERIAL = SHEET_MATERIAL_AMOUNT, "platinum" = SHEET_MATERIAL_AMOUNT) //todo
@@ -370,6 +381,7 @@ var/list/name_to_material
explosion_resistance = 75
hardness = 100
weight = 28
+ protectiveness = 60 // 75%
reflectivity = 0.7 // Not a perfect mirror, but close.
stack_origin_tech = list(TECH_MATERIAL = 8)
composite_material = list("plasteel" = SHEET_MATERIAL_AMOUNT, "diamond" = SHEET_MATERIAL_AMOUNT) //shrug
@@ -377,6 +389,7 @@ var/list/name_to_material
/material/plasteel/titanium
name = "titanium"
stack_type = null
+ conductivity = 2.38
icon_base = "metal"
door_icon_base = "metal"
icon_colour = "#D1E6E3"
@@ -393,6 +406,8 @@ var/list/name_to_material
tableslam_noise = 'sound/effects/Glasshit.ogg'
hardness = 30
weight = 15
+ protectiveness = 0 // 0%
+ conductivity = 1 // Glass shards don't conduct.
door_icon_base = "stone"
destruction_desc = "shatters"
window_options = list("One Direction" = 1, "Full Window" = 4, "Windoor" = 2)
@@ -526,6 +541,8 @@ var/list/name_to_material
icon_colour = "#CCCCCC"
hardness = 10
weight = 12
+ protectiveness = 5 // 20%
+ conductivity = 2 // For the sake of material armor diversity, we're gonna pretend this plastic is a good insulator.
melting_point = T0C+371 //assuming heat resistant plastic
stack_origin_tech = list(TECH_MATERIAL = 3)
@@ -556,12 +573,14 @@ var/list/name_to_material
stack_type = /obj/item/stack/material/mhydrogen
icon_colour = "#E6C5DE"
stack_origin_tech = list(TECH_MATERIAL = 6, TECH_POWER = 6, TECH_MAGNET = 5)
+ conductivity = 100
/material/platinum
name = "platinum"
stack_type = /obj/item/stack/material/platinum
icon_colour = "#9999FF"
weight = 27
+ conductivity = 9.43
stack_origin_tech = list(TECH_MATERIAL = 2)
sheet_singular_name = "ingot"
sheet_plural_name = "ingots"
@@ -571,6 +590,7 @@ var/list/name_to_material
stack_type = /obj/item/stack/material/iron
icon_colour = "#5C5454"
weight = 22
+ conductivity = 10
sheet_singular_name = "ingot"
sheet_plural_name = "ingots"
@@ -585,6 +605,7 @@ var/list/name_to_material
explosion_resistance = 200 // Hull plating.
hardness = 500
weight = 500
+ protectiveness = 80 // 80%
// Likewise.
/material/alienalloy/elevatorium
@@ -603,6 +624,8 @@ var/list/name_to_material
shard_can_repair = 0 // you can't weld splinters back into planks
hardness = 15
weight = 18
+ protectiveness = 8 // 28%
+ conductivity = 1
melting_point = T0C+300 //okay, not melting in this case, but hot enough to destroy wood
ignition_point = T0C+288
stack_origin_tech = list(TECH_MATERIAL = 1, TECH_BIO = 1)
@@ -634,6 +657,7 @@ var/list/name_to_material
icon_colour = "#AAAAAA"
hardness = 1
weight = 1
+ protectiveness = 0 // 0%
ignition_point = T0C+232 //"the temperature at which book-paper catches fire, and burns." close enough
melting_point = T0C+232 //temperature at which cardboard walls would be destroyed
stack_origin_tech = list(TECH_MATERIAL = 1)
@@ -650,6 +674,7 @@ var/list/name_to_material
integrity = 1
hardness = 1
weight = 1
+ protectiveness = 0 // 0%
stack_origin_tech = list(TECH_MATERIAL = 1)
melting_point = T0C+1
destruction_desc = "crumples"
@@ -662,6 +687,7 @@ var/list/name_to_material
door_icon_base = "wood"
ignition_point = T0C+232
melting_point = T0C+300
+ protectiveness = 1 // 4%
flags = MATERIAL_PADDING
/material/cult
@@ -695,6 +721,7 @@ var/list/name_to_material
flags = MATERIAL_PADDING
ignition_point = T0C+300
melting_point = T0C+300
+ protectiveness = 3 // 13%
/material/carpet
name = "carpet"
@@ -706,6 +733,7 @@ var/list/name_to_material
melting_point = T0C+300
sheet_singular_name = "tile"
sheet_plural_name = "tiles"
+ protectiveness = 1 // 4%
/material/cotton
name = "cotton"
@@ -714,7 +742,9 @@ var/list/name_to_material
flags = MATERIAL_PADDING
ignition_point = T0C+232
melting_point = T0C+300
+ protectiveness = 1 // 4%
+// This all needs to be OOP'd and use inheritence if its ever used in the future.
/material/cloth_teal
name = "teal"
display_name ="teal"
@@ -723,6 +753,7 @@ var/list/name_to_material
flags = MATERIAL_PADDING
ignition_point = T0C+232
melting_point = T0C+300
+ protectiveness = 1 // 4%
/material/cloth_black
name = "black"
@@ -732,6 +763,7 @@ var/list/name_to_material
flags = MATERIAL_PADDING
ignition_point = T0C+232
melting_point = T0C+300
+ protectiveness = 1 // 4%
/material/cloth_green
name = "green"
@@ -741,6 +773,7 @@ var/list/name_to_material
flags = MATERIAL_PADDING
ignition_point = T0C+232
melting_point = T0C+300
+ protectiveness = 1 // 4%
/material/cloth_puple
name = "purple"
@@ -750,6 +783,7 @@ var/list/name_to_material
flags = MATERIAL_PADDING
ignition_point = T0C+232
melting_point = T0C+300
+ protectiveness = 1 // 4%
/material/cloth_blue
name = "blue"
@@ -759,6 +793,7 @@ var/list/name_to_material
flags = MATERIAL_PADDING
ignition_point = T0C+232
melting_point = T0C+300
+ protectiveness = 1 // 4%
/material/cloth_beige
name = "beige"
@@ -768,6 +803,7 @@ var/list/name_to_material
flags = MATERIAL_PADDING
ignition_point = T0C+232
melting_point = T0C+300
+ protectiveness = 1 // 4%
/material/cloth_lime
name = "lime"
@@ -777,6 +813,7 @@ var/list/name_to_material
flags = MATERIAL_PADDING
ignition_point = T0C+232
melting_point = T0C+300
+ protectiveness = 1 // 4%
/material/toy_foam
name = "foam"
@@ -787,4 +824,5 @@ var/list/name_to_material
melting_point = T0C+300
icon_colour = "#ff9900"
hardness = 1
- weight = 1
\ No newline at end of file
+ weight = 1
+ protectiveness = 0 // 0%
\ No newline at end of file
diff --git a/code/modules/mob/language/station.dm b/code/modules/mob/language/station.dm
index 85942fcb4e9..b1411f2faef 100644
--- a/code/modules/mob/language/station.dm
+++ b/code/modules/mob/language/station.dm
@@ -24,7 +24,7 @@
/datum/language/unathi
name = LANGUAGE_UNATHI
- desc = "The common language of Moghes, composed of sibilant hisses and rattles. Spoken natively by Unathi."
+ desc = "The common language of the Moghes Hegemony, composed of sibilant hisses and rattles. Spoken natively by Unathi."
speech_verb = "hisses"
ask_verb = "hisses"
exclaim_verb = "roars"
diff --git a/code/modules/mob/living/carbon/human/human.dm b/code/modules/mob/living/carbon/human/human.dm
index 1c4f4e841e3..5bdea526652 100644
--- a/code/modules/mob/living/carbon/human/human.dm
+++ b/code/modules/mob/living/carbon/human/human.dm
@@ -88,6 +88,7 @@
if(mind.changeling)
stat("Chemical Storage", mind.changeling.chem_charges)
stat("Genetic Damage Time", mind.changeling.geneticdamage)
+ stat("Re-Adaptations", "[mind.changeling.readapts]/[mind.changeling.max_readapts]")
/mob/living/carbon/human/ex_act(severity)
if(!blinded)
diff --git a/code/modules/mob/living/carbon/human/human_defense.dm b/code/modules/mob/living/carbon/human/human_defense.dm
index 86bbdebc15e..f5fa2f582ce 100644
--- a/code/modules/mob/living/carbon/human/human_defense.dm
+++ b/code/modules/mob/living/carbon/human/human_defense.dm
@@ -27,6 +27,11 @@ emp_act
if(!P.nodamage)
organ.add_autopsy_data("[P.name]", P.damage)
+ // Tell clothing we're wearing that it got hit by a bullet/laser/etc
+ var/list/clothing = get_clothing_list_organ(organ)
+ for(var/obj/item/clothing/C in clothing)
+ C.clothing_impact(P, P.damage)
+
//Shrapnel
if(P.can_embed())
var/armor = getarmor_organ(organ, "bullet")
@@ -130,6 +135,15 @@ emp_act
return siemens_coefficient
+// Returns a list of clothing that is currently covering def_zone.
+/mob/living/carbon/human/proc/get_clothing_list_organ(var/obj/item/organ/external/def_zone, var/type)
+ var/list/results = list()
+ var/list/clothing_items = list(head, wear_mask, wear_suit, w_uniform, gloves, shoes)
+ for(var/obj/item/clothing/C in clothing_items)
+ if(istype(C) && (C.body_parts_covered & def_zone.body_part))
+ results.Add(C)
+ return results
+
//this proc returns the armour value for a particular external organ.
/mob/living/carbon/human/proc/getarmor_organ(var/obj/item/organ/external/def_zone, var/type)
if(!type || !def_zone) return 0
@@ -246,6 +260,12 @@ emp_act
if(!affecting)
return 0
+ // Allow clothing to respond to being hit.
+ // This is done up here so that clothing damage occurs even if fully blocked.
+ var/list/clothing = get_clothing_list_organ(affecting)
+ for(var/obj/item/clothing/C in clothing)
+ C.clothing_impact(I, effective_force)
+
if(soaked >= effective_force)
return 0
diff --git a/code/modules/mob/living/carbon/human/species/station/station.dm b/code/modules/mob/living/carbon/human/species/station/station.dm
index 5015e19940d..c88c1c1028a 100644
--- a/code/modules/mob/living/carbon/human/species/station/station.dm
+++ b/code/modules/mob/living/carbon/human/species/station/station.dm
@@ -34,19 +34,21 @@
ambiguous_genders = TRUE
gluttonous = 1
slowdown = 0.5
- brute_mod = 0.9
- burn_mod = 0.9
+ brute_mod = 0.85
+ burn_mod = 0.85
+ metabolic_rate = 0.85
+ item_slowdown_halved = 1
num_alternate_languages = 3
secondary_langs = list(LANGUAGE_UNATHI)
name_language = LANGUAGE_UNATHI
health_hud_intensity = 2.5
- min_age = 18
- max_age = 60
+ min_age = 32
+ max_age = 260
blurb = "A heavily reptillian species, Unathi (or 'Sinta as they call themselves) hail from the \
- Uuosa-Eso system, which roughly translates to 'burning mother'.
Coming from a harsh, radioactive \
- desert planet, they mostly hold ideals of honesty, virtue, martial combat and bravery above all \
+ Uuosa-Eso system, which roughly translates to 'burning mother'.
Coming from a harsh, inhospitable \
+ planet, they mostly hold ideals of honesty, virtue, proficiency and bravery above all \
else, frequently even their own lives. They prefer warmer temperatures than most species and \
their native tongue is a heavy hissing laungage called Sinta'Unathi."
@@ -62,9 +64,34 @@
appearance_flags = HAS_HAIR_COLOR | HAS_LIPS | HAS_UNDERWEAR | HAS_SKIN_COLOR | HAS_EYE_COLOR
flesh_color = "#34AF10"
+ blood_color = "#b3cbc3"
+ base_color = "#066000"
reagent_tag = IS_UNATHI
- base_color = "#066000"
+
+ has_limbs = list(
+ BP_TORSO = list("path" = /obj/item/organ/external/chest/unathi),
+ BP_GROIN = list("path" = /obj/item/organ/external/groin/unathi),
+ BP_HEAD = list("path" = /obj/item/organ/external/head/unathi),
+ BP_L_ARM = list("path" = /obj/item/organ/external/arm),
+ BP_R_ARM = list("path" = /obj/item/organ/external/arm/right),
+ BP_L_LEG = list("path" = /obj/item/organ/external/leg),
+ BP_R_LEG = list("path" = /obj/item/organ/external/leg/right),
+ BP_L_HAND = list("path" = /obj/item/organ/external/hand),
+ BP_R_HAND = list("path" = /obj/item/organ/external/hand/right),
+ BP_L_FOOT = list("path" = /obj/item/organ/external/foot),
+ BP_R_FOOT = list("path" = /obj/item/organ/external/foot/right)
+ )
+
+ //No kidneys or appendix
+ has_organ = list(
+ O_HEART = /obj/item/organ/internal/heart/unathi,
+ O_LUNGS = /obj/item/organ/internal/lungs/unathi,
+ O_LIVER = /obj/item/organ/internal/liver/unathi,
+ O_BRAIN = /obj/item/organ/internal/brain/unathi,
+ O_EYES = /obj/item/organ/internal/eyes,
+ )
+
heat_discomfort_level = 295
heat_discomfort_strings = list(
diff --git a/code/modules/multiz/basic.dm b/code/modules/multiz/basic.dm
index e76c6516aa7..24d24b10497 100644
--- a/code/modules/multiz/basic.dm
+++ b/code/modules/multiz/basic.dm
@@ -11,25 +11,35 @@ var/z_levels = 0 // Each bit represents a connection between adjacent levels. S
qdel(src)
// The storage of connections between adjacent levels means some bitwise magic is needed.
-proc/HasAbove(var/z)
+/proc/HasAbove(var/z)
if(z >= world.maxz || z > 16 || z < 1)
return 0
return z_levels & (1 << (z - 1))
-proc/HasBelow(var/z)
+/proc/HasBelow(var/z)
if(z > world.maxz || z > 17 || z < 2)
return 0
return z_levels & (1 << (z - 2))
// Thankfully, no bitwise magic is needed here.
-proc/GetAbove(var/atom/atom)
+/proc/GetAbove(var/atom/atom)
var/turf/turf = get_turf(atom)
if(!turf)
return null
return HasAbove(turf.z) ? get_step(turf, UP) : null
-proc/GetBelow(var/atom/atom)
+/proc/GetBelow(var/atom/atom)
var/turf/turf = get_turf(atom)
if(!turf)
return null
return HasBelow(turf.z) ? get_step(turf, DOWN) : null
+
+/proc/GetConnectedZlevels(z)
+ . = list(z)
+ for(var/level = z, HasBelow(level), level--)
+ . |= level-1
+ for(var/level = z, HasAbove(level), level++)
+ . |= level+1
+
+proc/AreConnectedZLevels(var/zA, var/zB)
+ return zA == zB || (zB in GetConnectedZlevels(zA))
diff --git a/code/modules/multiz/movement.dm b/code/modules/multiz/movement.dm
index 586b6242602..122e1aa4cda 100644
--- a/code/modules/multiz/movement.dm
+++ b/code/modules/multiz/movement.dm
@@ -3,34 +3,38 @@
set category = "IC"
if(zMove(UP))
- to_chat(usr, "You move upwards.")
+ to_chat(src, "You move upwards.")
/mob/verb/down()
set name = "Move Down"
set category = "IC"
if(zMove(DOWN))
- to_chat(usr, "You move down.")
+ to_chat(src, "You move down.")
/mob/proc/zMove(direction)
if(eyeobj)
return eyeobj.zMove(direction)
if(!can_ztravel())
- to_chat(usr, "You lack means of travel in that direction.")
+ to_chat(src, "You lack means of travel in that direction.")
return
+ var/turf/start = loc
+ if(!istype(start))
+ to_chat(src, "You are unable to move from here.")
+ return 0
+
var/turf/destination = (direction == UP) ? GetAbove(src) : GetBelow(src)
-
if(!destination)
- to_chat(usr, "There is nothing of interest in this direction.")
+ to_chat(src, "There is nothing of interest in this direction.")
+ return 0
+
+ if(!start.CanZPass(src, direction))
+ to_chat(src, "\The [start] is in the way.")
return 0
- var/turf/start = get_turf(src)
- if(!start.CanZPass(src, direction))
- to_chat(usr, "\The [start] is in the way.")
- return 0
if(!destination.CanZPass(src, direction))
- to_chat(usr, "\The [destination] blocks your way.")
+ to_chat(src, "\The [destination] blocks your way.")
return 0
var/area/area = get_area(src)
@@ -46,12 +50,12 @@
to_chat(src, "You gave up on pulling yourself up.")
return 0
else
- to_chat(usr, "Gravity stops you from moving upward.")
+ to_chat(src, "Gravity stops you from moving upward.")
return 0
for(var/atom/A in destination)
if(!A.CanPass(src, start, 1.5, 0))
- to_chat(usr, "\The [A] blocks you.")
+ to_chat(src, "\The [A] blocks you.")
return 0
Move(destination)
return 1
@@ -61,14 +65,14 @@
if(destination)
forceMove(destination)
else
- to_chat(usr, "There is nothing of interest in this direction.")
+ to_chat(src, "There is nothing of interest in this direction.")
/mob/observer/eye/zMove(direction)
var/turf/destination = (direction == UP) ? GetAbove(src) : GetBelow(src)
if(destination)
setLoc(destination)
else
- to_chat(usr, "There is nothing of interest in this direction.")
+ to_chat(src, "There is nothing of interest in this direction.")
/mob/proc/can_ztravel()
return 0
diff --git a/code/modules/multiz/pipes.dm b/code/modules/multiz/pipes.dm
index 1cb5b9b4da7..6b6b24c4705 100644
--- a/code/modules/multiz/pipes.dm
+++ b/code/modules/multiz/pipes.dm
@@ -13,6 +13,9 @@ obj/machinery/atmospherics/pipe/zpipe
dir = SOUTH
initialize_directions = SOUTH
+ // node1 is the connection on the same Z
+ // node2 is the connection on the other Z
+
var/minimum_temperature_difference = 300
var/thermal_conductivity = 0 //WALL_HEAT_TRANSFER_COEFFICIENT No
diff --git a/code/modules/multiz/structures.dm b/code/modules/multiz/structures.dm
index 57278082764..18bb91a9e46 100644
--- a/code/modules/multiz/structures.dm
+++ b/code/modules/multiz/structures.dm
@@ -122,10 +122,6 @@
allowed_directions = UP|DOWN
icon_state = "ladder11"
-
-
-
-
/obj/structure/stairs
name = "Stairs"
desc = "Stairs leading to another deck. Not too useful if the gravity goes out."
diff --git a/code/modules/multiz/turf.dm b/code/modules/multiz/turf.dm
index 8389df7112b..b6845d076f1 100644
--- a/code/modules/multiz/turf.dm
+++ b/code/modules/multiz/turf.dm
@@ -36,6 +36,11 @@
..()
mover.fall()
+// Called when thrown object lands on this turf.
+/turf/simulated/open/hitby(var/atom/movable/AM, var/speed)
+ . = ..()
+ AM.fall()
+
/turf/simulated/open/proc/update()
below = GetBelow(src)
turf_changed_event.register(below, src, /turf/simulated/open/update_icon)
@@ -82,7 +87,7 @@
return
var/obj/item/stack/rods/R = C
if (R.use(1))
- user << "Constructing support lattice ..."
+ to_chat(user, "Constructing support lattice ...")
playsound(src, 'sound/weapons/Genhit.ogg', 50, 1)
ReplaceWithLattice()
return
@@ -99,7 +104,7 @@
ChangeTurf(/turf/simulated/floor/airless)
return
else
- user << "The plating is going to need some support."
+ to_chat(user, "The plating is going to need some support.")
//To lay cable.
if(istype(C, /obj/item/stack/cable_coil))
diff --git a/code/modules/organs/subtypes/unathi.dm b/code/modules/organs/subtypes/unathi.dm
new file mode 100644
index 00000000000..212330577ce
--- /dev/null
+++ b/code/modules/organs/subtypes/unathi.dm
@@ -0,0 +1,50 @@
+/obj/item/organ/external/chest/unathi
+ max_damage = 100
+ min_broken_damage = 40
+ encased = "upper ribplates"
+
+/obj/item/organ/external/groin/unathi
+ max_damage = 100
+ min_broken_damage = 40
+ encased = "lower ribplates"
+
+/obj/item/organ/external/head/unathi
+ max_damage = 75
+ min_broken_damage = 35
+ eye_icon = "eyes_s"
+ force = 5
+ throwforce = 10
+
+
+/obj/item/organ/internal/heart/unathi
+ icon_state = "unathi_heart-on"
+ dead_icon = "unath_heart-off"
+
+/obj/item/organ/internal/lungs/unathi
+ color = "#b3cbc3"
+
+/obj/item/organ/internal/liver/unathi
+ name = "filtration organ"
+ icon_state = "unathi_liver"
+
+//Unathi liver acts as kidneys, too.
+/obj/item/organ/internal/liver/unathi/process()
+ ..()
+ if(!owner) return
+
+ var/datum/reagent/coffee = locate(/datum/reagent/drink/coffee) in owner.reagents.reagent_list
+ if(coffee)
+ if(is_bruised())
+ owner.adjustToxLoss(0.1 * PROCESS_ACCURACY)
+ else if(is_broken())
+ owner.adjustToxLoss(0.3 * PROCESS_ACCURACY)
+
+ var/datum/reagent/sugar = locate(/datum/reagent/sugar) in owner.reagents.reagent_list
+ if(sugar)
+ if(is_bruised())
+ owner.adjustToxLoss(0.1 * PROCESS_ACCURACY)
+ else if(is_broken())
+ owner.adjustToxLoss(0.3 * PROCESS_ACCURACY)
+
+/obj/item/organ/internal/brain/unathi
+ color = "#b3cbc3"
\ No newline at end of file
diff --git a/code/modules/projectiles/gun.dm b/code/modules/projectiles/gun.dm
index 75d574ed632..f7d963523c6 100644
--- a/code/modules/projectiles/gun.dm
+++ b/code/modules/projectiles/gun.dm
@@ -425,21 +425,21 @@
/obj/item/weapon/gun/proc/handle_post_fire(mob/user, atom/target, var/pointblank=0, var/reflex=0)
if(silenced)
playsound(user, fire_sound, 10, 1)
+ to_chat(user, "You fire \the [src][pointblank ? " point blank at \the [target]":""][reflex ? " by reflex!":""]")
+ for(var/mob/living/L in oview(2,user))
+ if(L.stat)
+ continue
+ if(L.blinded)
+ to_chat(L, "You hear a [fire_sound_text]!")
+ continue
+ to_chat(L, "[user] fires \the [src][pointblank ? " point blank at \the [target]":""][reflex ? " by reflex!":""]")
else
playsound(user, fire_sound, 50, 1)
-
- if(reflex)
- user.visible_message(
- "\The [user] fires \the [src][pointblank ? " point blank at \the [target]":""] by reflex!",
- "You fire \the [src] by reflex!",
- "You hear a [fire_sound_text]!"
- )
- else
- user.visible_message(
- "\The [user] fires \the [src][pointblank ? " point blank at \the [target]":""]!",
- "You fire \the [src]!",
- "You hear a [fire_sound_text]!"
- )
+ user.visible_message(
+ "[user] fires \the [src][pointblank ? " point blank at \the [target]":""][reflex ? " by reflex!":""]",
+ "You fire \the [src][pointblank ? " point blank at \the [target]":""][reflex ? " by reflex!":""]",
+ "You hear a [fire_sound_text]!"
+ )
if(muzzle_flash)
set_light(muzzle_flash)
diff --git a/code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Dispenser.dm b/code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Dispenser.dm
index 1d8e7177738..5909ed906f3 100644
--- a/code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Dispenser.dm
+++ b/code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Dispenser.dm
@@ -96,6 +96,8 @@
strength_mod *= 5
if(alien == IS_TAJARA)
strength_mod *= 1.75
+ if(alien == IS_UNATHI)
+ strength_mod *= 0.75
if(alien == IS_DIONA)
strength_mod = 0
diff --git a/code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Food-Drinks.dm b/code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Food-Drinks.dm
index 2f34ebd93d3..4532dc43fca 100644
--- a/code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Food-Drinks.dm
+++ b/code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Food-Drinks.dm
@@ -2232,3 +2232,26 @@
glass_name = "special blend whiskey"
glass_desc = "Just when you thought regular station whiskey was good... This silky, amber goodness has to come along and ruin everything."
+/datum/reagent/ethanol/unathiliquor //Needs a better name
+ name = "Unathi Liquor"
+ id = "unathiliquor"
+ description = "This barely qualifies as a drink, and could give jetfuel a run for its money. Also known to cause feelings of euphoria and numbness."
+ taste_description = "spiced numbness"
+ color = "#242424"
+ strength = 5
+
+ glass_name = "unathi liquor"
+ glass_desc = "This barely qualifies as a drink, and may cause euphoria and numbness. Imbimber beware!"
+
+/datum/reagent/ethanol/unathiliquor/affect_ingest(var/mob/living/carbon/M, var/alien, var/removed)
+ ..()
+ if(alien == IS_DIONA)
+ return
+
+ var/drug_strength = 10
+ if(alien == IS_SKRELL)
+ drug_strength = drug_strength * 0.8
+
+ M.druggy = max(M.druggy, drug_strength)
+ if(prob(10) && isturf(M.loc) && !istype(M.loc, /turf/space) && M.canmove && !M.restrained())
+ step(M, pick(cardinal))
\ No newline at end of file
diff --git a/code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Toxins.dm b/code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Toxins.dm
index 19785e6a181..12540c2d049 100644
--- a/code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Toxins.dm
+++ b/code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Toxins.dm
@@ -429,6 +429,7 @@
glass_name = "beer"
glass_desc = "A freezing pint of beer"
+
/* Drugs */
/datum/reagent/space_drugs
diff --git a/code/modules/reagents/reagent_containers/glass.dm b/code/modules/reagents/reagent_containers/glass.dm
index ed27e1a259b..bd670cc8bce 100644
--- a/code/modules/reagents/reagent_containers/glass.dm
+++ b/code/modules/reagents/reagent_containers/glass.dm
@@ -243,6 +243,12 @@
user.drop_from_inventory(src)
qdel(src)
return
+ else if(istype(D, /obj/item/weapon/wirecutters))
+ to_chat(user, "You cut a big hole in \the [src] with \the [D]. It's kinda useless as a bucket now.")
+ user.put_in_hands(new /obj/item/clothing/head/helmet/bucket)
+ user.drop_from_inventory(src)
+ qdel(src)
+ return
else if(istype(D, /obj/item/weapon/mop))
if(reagents.total_volume < 1)
user << "\The [src] is empty!"
diff --git a/code/modules/turbolift/turbolift_map.dm b/code/modules/turbolift/turbolift_map.dm
index 2e2498f88db..8930bf34d62 100644
--- a/code/modules/turbolift/turbolift_map.dm
+++ b/code/modules/turbolift/turbolift_map.dm
@@ -221,7 +221,7 @@
var/turf/T = locate(int_panel_x, int_panel_y, uz)
lift.control_panel_interior = new(T, lift)
lift.control_panel_interior.set_dir(udir)
- lift.current_floor = lift.floors[uz]
+ lift.current_floor = lift.floors[1]
lift.open_doors()
diff --git a/html/changelogs/Anewbe - Unathi.yml b/html/changelogs/Anewbe - Unathi.yml
new file mode 100644
index 00000000000..f9228a9bc2d
--- /dev/null
+++ b/html/changelogs/Anewbe - Unathi.yml
@@ -0,0 +1,41 @@
+################################
+# Example Changelog File
+#
+# Note: This file, and files beginning with ".", and files that don't end in ".yml" will not be read. If you change this file, you will look really dumb.
+#
+# Your changelog will be merged with a master changelog. (New stuff added only, and only on the date entry for the day it was merged.)
+# When it is, any changes listed below will disappear.
+#
+# Valid Prefixes:
+# bugfix
+# wip (For works in progress)
+# tweak
+# soundadd
+# sounddel
+# rscadd (general adding of nice things)
+# rscdel (general deleting of nice things)
+# imageadd
+# imagedel
+# maptweak
+# spellcheck (typo fixes)
+# experiment
+#################################
+
+# Your name.
+author: Anewbe
+
+# Optional: Remove this file after generating master changelog. Useful for PR changelogs that won't get used again.
+delete-after: True
+
+# Any changes you've made. See valid prefix list above.
+# INDENT WITH TWO SPACES. NOT TABS. SPACES.
+# SCREW THIS UP AND IT WON'T WORK.
+# Also, all entries are changed into a single [] after a master changelog generation. Just remove the brackets when you add new entries.
+# Please surround your changes in double quotes ("), as certain characters otherwise screws up compiling. The quotes will not show up in the changelog.
+changes:
+ - rscadd: "Unathi ribcages now reach down to their lower torso."
+ - rscadd: "Unathi no longer have appendices or kidneys, the function of the kidneys is now a function of their liver."
+ - rscadd: "Unathi are more slightly more difficult to damage."'
+ - rscadd: "Unathi now process medicine 15% slower. Additionally, it's harder for them to get drunk."
+ - rscadd: "Unathi age range is now 32 to 260."
+ - rscadd: "Unathi are not as slowed by heavy items."
\ No newline at end of file
diff --git a/html/changelogs/LorenLuke - BlastDoor.yml b/html/changelogs/LorenLuke - BlastDoor.yml
new file mode 100644
index 00000000000..dccd074f555
--- /dev/null
+++ b/html/changelogs/LorenLuke - BlastDoor.yml
@@ -0,0 +1,36 @@
+################################
+# Example Changelog File
+#
+# Note: This file, and files beginning with ".", and files that don't end in ".yml" will not be read. If you change this file, you will look really dumb.
+#
+# Your changelog will be merged with a master changelog. (New stuff added only, and only on the date entry for the day it was merged.)
+# When it is, any changes listed below will disappear.
+#
+# Valid Prefixes:
+# bugfix
+# wip (For works in progress)
+# tweak
+# soundadd
+# sounddel
+# rscadd (general adding of nice things)
+# rscdel (general deleting of nice things)
+# imageadd
+# imagedel
+# maptweak
+# spellcheck (typo fixes)
+# experiment
+#################################
+
+# Your name.
+author: LorenLuke
+
+# Optional: Remove this file after generating master changelog. Useful for PR changelogs that won't get used again.
+delete-after: True
+
+# Any changes you've made. See valid prefix list above.
+# INDENT WITH TWO SPACES. NOT TABS. SPACES.
+# SCREW THIS UP AND IT WON'T WORK.
+# Also, all entries are changed into a single [] after a master changelog generation. Just remove the brackets when you add new entries.
+# Please surround your changes in double quotes ("), as certain characters otherwise screws up compiling. The quotes will not show up in the changelog.
+changes:
+ - rscadd: "Allows Blast doors to be attacked and broken like regular airlocks."
diff --git a/html/changelogs/LorenLuke - ChangelingRespec.yml b/html/changelogs/LorenLuke - ChangelingRespec.yml
new file mode 100644
index 00000000000..d173d3d580d
--- /dev/null
+++ b/html/changelogs/LorenLuke - ChangelingRespec.yml
@@ -0,0 +1,37 @@
+################################
+# Example Changelog File
+#
+# Note: This file, and files beginning with ".", and files that don't end in ".yml" will not be read. If you change this file, you will look really dumb.
+#
+# Your changelog will be merged with a master changelog. (New stuff added only, and only on the date entry for the day it was merged.)
+# When it is, any changes listed below will disappear.
+#
+# Valid Prefixes:
+# bugfix
+# wip (For works in progress)
+# tweak
+# soundadd
+# sounddel
+# rscadd (general adding of nice things)
+# rscdel (general deleting of nice things)
+# imageadd
+# imagedel
+# maptweak
+# spellcheck (typo fixes)
+# experiment
+#################################
+
+# Your name.
+author: LorenLuke
+
+# Optional: Remove this file after generating master changelog. Useful for PR changelogs that won't get used again.
+delete-after: True
+
+# Any changes you've made. See valid prefix list above.
+# INDENT WITH TWO SPACES. NOT TABS. SPACES.
+# SCREW THIS UP AND IT WON'T WORK.
+# Also, all entries are changed into a single [] after a master changelog generation. Just remove the brackets when you add new entries.
+# Please surround your changes in double quotes ("), as certain characters otherwise screws up compiling. The quotes will not show up in the changelog.
+changes:
+ - tweak: "Changelings can bank up to a maximum of 3 respecs at one time."
+ - tweak: "Changelings begin with 2 respecs."
diff --git a/html/changelogs/LorenLuke - SilencedWeapons.yml b/html/changelogs/LorenLuke - SilencedWeapons.yml
new file mode 100644
index 00000000000..4d4c82413bc
--- /dev/null
+++ b/html/changelogs/LorenLuke - SilencedWeapons.yml
@@ -0,0 +1,36 @@
+################################
+# Example Changelog File
+#
+# Note: This file, and files beginning with ".", and files that don't end in ".yml" will not be read. If you change this file, you will look really dumb.
+#
+# Your changelog will be merged with a master changelog. (New stuff added only, and only on the date entry for the day it was merged.)
+# When it is, any changes listed below will disappear.
+#
+# Valid Prefixes:
+# bugfix
+# wip (For works in progress)
+# tweak
+# soundadd
+# sounddel
+# rscadd (general adding of nice things)
+# rscdel (general deleting of nice things)
+# imageadd
+# imagedel
+# maptweak
+# spellcheck (typo fixes)
+# experiment
+#################################
+
+# Your name.
+author: LorenLuke
+
+# Optional: Remove this file after generating master changelog. Useful for PR changelogs that won't get used again.
+delete-after: True
+
+# Any changes you've made. See valid prefix list above.
+# INDENT WITH TWO SPACES. NOT TABS. SPACES.
+# SCREW THIS UP AND IT WON'T WORK.
+# Also, all entries are changed into a single [] after a master changelog generation. Just remove the brackets when you add new entries.
+# Please surround your changes in double quotes ("), as certain characters otherwise screws up compiling. The quotes will not show up in the changelog.
+changes:
+ - tweak: "Firing a silenced weapon gives a message in text to the user."
diff --git a/html/changelogs/Neerti-Armor.yml b/html/changelogs/Neerti-Armor.yml
new file mode 100644
index 00000000000..2cfb3e15f3c
--- /dev/null
+++ b/html/changelogs/Neerti-Armor.yml
@@ -0,0 +1,36 @@
+################################
+# Example Changelog File
+#
+# Note: This file, and files beginning with ".", and files that don't end in ".yml" will not be read. If you change this file, you will look really dumb.
+#
+# Your changelog will be merged with a master changelog. (New stuff added only, and only on the date entry for the day it was merged.)
+# When it is, any changes listed below will disappear.
+#
+# Valid Prefixes:
+# bugfix
+# wip (For works in progress)
+# tweak
+# soundadd
+# sounddel
+# rscadd (general adding of nice things)
+# rscdel (general deleting of nice things)
+# imageadd
+# imagedel
+# maptweak
+# spellcheck (typo fixes)
+# experiment
+#################################
+
+# Your name.
+author: Neerti
+
+# Optional: Remove this file after generating master changelog. Useful for PR changelogs that won't get used again.
+delete-after: True
+
+# Any changes you've made. See valid prefix list above.
+# INDENT WITH TWO SPACES. NOT TABS. SPACES.
+# SCREW THIS UP AND IT WON'T WORK.
+# Also, all entries are changed into a single [] after a master changelog generation. Just remove the brackets when you add new entries.
+# Please surround your changes in double quotes ("), as certain characters otherwise screws up compiling. The quotes will not show up in the changelog.
+changes:
+ - rscadd: "Adds makeshift armor for the head and chest regions. How protective they are depends on the material used to craft it. The helmet is made by using wirecutters on a bucket, then using a stack of material. The chestpiece is made by crafting two armor plate, using wires on one of them, then hiting one with the other."
diff --git a/icons/mob/head.dmi b/icons/mob/head.dmi
index 7407aeefb54..44f920fe30c 100644
Binary files a/icons/mob/head.dmi and b/icons/mob/head.dmi differ
diff --git a/icons/mob/human_races/r_lizard.dmi b/icons/mob/human_races/r_lizard.dmi
index 5fb2c58be46..97e6f04bdc1 100644
Binary files a/icons/mob/human_races/r_lizard.dmi and b/icons/mob/human_races/r_lizard.dmi differ
diff --git a/icons/mob/suit.dmi b/icons/mob/suit.dmi
index 5d7180da7cf..b2eb9c72fe8 100644
Binary files a/icons/mob/suit.dmi and b/icons/mob/suit.dmi differ
diff --git a/icons/obj/clothing/hats.dmi b/icons/obj/clothing/hats.dmi
index 9337d5127c0..ef18c7bf49c 100644
Binary files a/icons/obj/clothing/hats.dmi and b/icons/obj/clothing/hats.dmi differ
diff --git a/icons/obj/clothing/suits.dmi b/icons/obj/clothing/suits.dmi
index b1750efa362..c1183a4e939 100644
Binary files a/icons/obj/clothing/suits.dmi and b/icons/obj/clothing/suits.dmi differ
diff --git a/icons/obj/items.dmi b/icons/obj/items.dmi
index dc3456ba672..778ec461bb0 100644
Binary files a/icons/obj/items.dmi and b/icons/obj/items.dmi differ
diff --git a/icons/obj/surgery.dmi b/icons/obj/surgery.dmi
index b2ff3108ea6..39ed73fc3df 100644
Binary files a/icons/obj/surgery.dmi and b/icons/obj/surgery.dmi differ
diff --git a/polaris.dme b/polaris.dme
index b167a599e4b..1c2ee26d086 100644
--- a/polaris.dme
+++ b/polaris.dme
@@ -899,6 +899,7 @@
#include "code\game\objects\items\weapons\material\foam.dm"
#include "code\game\objects\items\weapons\material\kitchen.dm"
#include "code\game\objects\items\weapons\material\knives.dm"
+#include "code\game\objects\items\weapons\material\material_armor.dm"
#include "code\game\objects\items\weapons\material\material_weapons.dm"
#include "code\game\objects\items\weapons\material\misc.dm"
#include "code\game\objects\items\weapons\material\shards.dm"
@@ -1793,6 +1794,7 @@
#include "code\modules\organs\subtypes\machine.dm"
#include "code\modules\organs\subtypes\seromi.dm"
#include "code\modules\organs\subtypes\standard.dm"
+#include "code\modules\organs\subtypes\unathi.dm"
#include "code\modules\organs\subtypes\unbreakable.dm"
#include "code\modules\organs\subtypes\vox.dm"
#include "code\modules\overmap\_defines.dm"