diff --git a/code/game/turfs/simulated/water.dm b/code/game/turfs/simulated/water.dm
index 12084f58584..5a3d0ec6186 100644
--- a/code/game/turfs/simulated/water.dm
+++ b/code/game/turfs/simulated/water.dm
@@ -73,6 +73,26 @@
water_breath.adjust_gas(gasid, BREATH_MOLES) // They have no oxygen, but non-zero moles and temp
water_breath.temperature = above_air.temperature
return water_breath
+ if(L && L.is_bad_swimmer() && depth >= 2 && !L.buckled())
+ L.visible_message("[L] splashes wildly.","You struggle to keep your head above the water!")
+ if(L.can_breathe_water())
+ var/datum/gas_mixture/water_breath = new()
+ var/datum/gas_mixture/above_air = return_air()
+ var/amount = 300
+ water_breath.adjust_gas("oxygen", amount) // Assuming water breathes just extract the oxygen directly from the water.
+ water_breath.temperature = above_air.temperature
+ return water_breath
+ else
+ var/gasid = "carbon_dioxide"
+ if(ishuman(L))
+ var/mob/living/carbon/human/H = L
+ if(H.species && H.species.exhale_type)
+ gasid = H.species.exhale_type
+ var/datum/gas_mixture/water_breath = new()
+ var/datum/gas_mixture/above_air = return_air()
+ water_breath.adjust_gas(gasid, BREATH_MOLES) // They have no oxygen, but non-zero moles and temp
+ water_breath.temperature = above_air.temperature
+ return water_breath
return return_air() // Otherwise their head is above the water, so get the air from the atmosphere instead.
/turf/simulated/floor/water/Entered(atom/movable/AM, atom/oldloc)
@@ -125,6 +145,14 @@
return species.can_breathe_water()
return ..()
+/mob/living/proc/is_bad_swimmer()
+ return FALSE
+
+/mob/living/carbon/human/is_bad_swimmer()
+ if(species)
+ return species.is_bad_swimmer()
+ return ..()
+
/mob/living/proc/check_submerged()
if(buckled)
return 0
diff --git a/code/modules/mob/living/carbon/human/species/species.dm b/code/modules/mob/living/carbon/human/species/species.dm
index e7722cff392..3d3f3dba5ed 100644
--- a/code/modules/mob/living/carbon/human/species/species.dm
+++ b/code/modules/mob/living/carbon/human/species/species.dm
@@ -137,6 +137,7 @@
var/poison_type = "phoron" // Poisonous air.
var/exhale_type = "carbon_dioxide" // Exhaled gas type.
var/water_breather = FALSE
+ var/bad_swimmer = FALSE
var/body_temperature = 310.15 // Species will try to stabilize at this temperature. (also affects temperature processing)
@@ -513,6 +514,10 @@
/datum/species/proc/can_breathe_water()
return water_breather
+// Called when standing on a water tile.
+/datum/species/proc/is_bad_swimmer()
+ return bad_swimmer
+
// Impliments different trails for species depending on if they're wearing shoes.
/datum/species/proc/get_move_trail(var/mob/living/carbon/human/H)
if( H.shoes || ( H.wear_suit && (H.wear_suit.body_parts_covered & FEET) ) )
diff --git a/code/modules/mob/living/carbon/human/species/station/traits_vr/negative.dm b/code/modules/mob/living/carbon/human/species/station/traits_vr/negative.dm
index 07e086b13d9..adc3c051f4d 100644
--- a/code/modules/mob/living/carbon/human/species/station/traits_vr/negative.dm
+++ b/code/modules/mob/living/carbon/human/species/station/traits_vr/negative.dm
@@ -168,3 +168,9 @@
custom_only = FALSE
varchange_type = TRAIT_VARCHANGE_MORE_BETTER
+/datum/trait/negative/bad_swimmer
+ name = "Bad Swimmer"
+ desc = "You can't swim very well, all water slows you down a lot and you drown in deep water."
+ cost = -1
+ custom_only = FALSE
+ var_changes = list("bad_swimmer" = 1, "water_movement" = 4)