diff --git a/lib/bsp_loader/src/bsp.rs b/lib/bsp_loader/src/bsp.rs
index d05198924..19c2535b0 100644
--- a/lib/bsp_loader/src/bsp.rs
+++ b/lib/bsp_loader/src/bsp.rs
@@ -2,7 +2,7 @@ use std::borrow::Cow;
 
 use vbsp_entities_css::Entity;
 
-use strafesnet_common::{map,model,integer,gameplay_attributes};
+use strafesnet_common::{map,model,integer,gameplay_attributes as attr};
 use strafesnet_deferred_loader::deferred_loader::{MeshDeferredLoader,RenderConfigDeferredLoader};
 use strafesnet_deferred_loader::mesh::Meshes;
 use strafesnet_deferred_loader::texture::{RenderConfigs,Texture};
@@ -42,7 +42,7 @@ fn add_brush<'a>(
 	model:&'a str,
 	origin:vbsp::Vector,
 	rendercolor:vbsp::Color,
-	attributes:gameplay_attributes::CollisionAttributesId,
+	attributes:attr::CollisionAttributesId,
 ){
 	let transform=integer::Planar64Affine3::from_translation(
 		valve_transform(origin.into())
@@ -83,13 +83,40 @@ pub fn convert<'a>(
 )->PartialMap1{
 	let bsp=bsp.as_ref();
 	//figure out real attributes later
-	let mut unique_attributes=Vec::new();
-	unique_attributes.push(gameplay_attributes::CollisionAttributes::Decoration);
-	unique_attributes.push(gameplay_attributes::CollisionAttributes::contact_default());
-	unique_attributes.push(gameplay_attributes::CollisionAttributes::intersect_default());
-	const ATTRIBUTE_DECORATION:gameplay_attributes::CollisionAttributesId=gameplay_attributes::CollisionAttributesId::new(0);
-	const ATTRIBUTE_CONTACT_DEFAULT:gameplay_attributes::CollisionAttributesId=gameplay_attributes::CollisionAttributesId::new(1);
-	const ATTRIBUTE_INTERSECT_DEFAULT:gameplay_attributes::CollisionAttributesId=gameplay_attributes::CollisionAttributesId::new(2);
+	let unique_attributes=vec![
+		attr::CollisionAttributes::Decoration,
+		attr::CollisionAttributes::contact_default(),
+		attr::CollisionAttributes::intersect_default(),
+		// ladder
+		attr::CollisionAttributes::Contact(
+			attr::ContactAttributes{
+				contacting:attr::ContactingAttributes{
+					contact_behaviour:Some(attr::ContactingBehaviour::Ladder(
+						attr::ContactingLadder{sticky:true}
+					))
+				},
+				general:attr::GeneralAttributes::default(),
+			}
+		),
+		// water
+		attr::CollisionAttributes::Intersect(
+			attr::IntersectAttributes{
+				intersecting:attr::IntersectingAttributes{
+					water:Some(attr::IntersectingWater{
+						viscosity:integer::Planar64::ONE,
+						density:integer::Planar64::ONE,
+						velocity:integer::vec3::ZERO,
+					}),
+				},
+				general:attr::GeneralAttributes::default(),
+			}
+		),
+	];
+	const ATTRIBUTE_DECORATION:attr::CollisionAttributesId=attr::CollisionAttributesId::new(0);
+	const ATTRIBUTE_CONTACT_DEFAULT:attr::CollisionAttributesId=attr::CollisionAttributesId::new(1);
+	const ATTRIBUTE_INTERSECT_DEFAULT:attr::CollisionAttributesId=attr::CollisionAttributesId::new(2);
+	const ATTRIBUTE_LADDER_DEFAULT:attr::CollisionAttributesId=attr::CollisionAttributesId::new(3);
+	const ATTRIBUTE_WATER_DEFAULT:attr::CollisionAttributesId=attr::CollisionAttributesId::new(4);
 
 	//declare all prop models to Loader
 	let mut prop_models=bsp.static_props().map(|prop|{
@@ -237,9 +264,27 @@ pub fn convert<'a>(
 
 	// physics models
 	for brush in &bsp.brushes{
-		if !brush.flags.contains(vbsp::BrushFlags::SOLID){
+		const RELEVANT:vbsp::BrushFlags=
+			vbsp::BrushFlags::SOLID
+			.union(vbsp::BrushFlags::PLAYERCLIP)
+			.union(vbsp::BrushFlags::WATER)
+			.union(vbsp::BrushFlags::MOVEABLE)
+			.union(vbsp::BrushFlags::LADDER);
+		if !brush.flags.intersects(RELEVANT){
 			continue;
 		}
+		let is_ladder=brush.flags.contains(vbsp::BrushFlags::LADDER);
+		let is_water=brush.flags.contains(vbsp::BrushFlags::WATER);
+		let attributes=match (is_ladder,is_water){
+			(true,false)=>ATTRIBUTE_LADDER_DEFAULT,
+			(false,true)=>ATTRIBUTE_WATER_DEFAULT,
+			(false,false)=>ATTRIBUTE_CONTACT_DEFAULT,
+			(true,true)=>{
+				// water ladder? wtf
+				println!("brush is a water ladder o_o defaulting to ladder");
+				ATTRIBUTE_LADDER_DEFAULT
+			}
+		};
 		let mesh_result=crate::brush::brush_to_mesh(bsp,brush);
 		match mesh_result{
 			Ok(mesh)=>{
@@ -247,7 +292,7 @@ pub fn convert<'a>(
 				world_meshes.push(mesh);
 				world_models.push(model::Model{
 					mesh:mesh_id,
-					attributes:ATTRIBUTE_CONTACT_DEFAULT,
+					attributes,
 					transform:integer::Planar64Affine3::new(
 						integer::mat3::identity(),
 						integer::vec3::ZERO,
@@ -295,7 +340,7 @@ pub fn convert<'a>(
 
 //partially constructed map types
 pub struct PartialMap1{
-	attributes:Vec<strafesnet_common::gameplay_attributes::CollisionAttributes>,
+	attributes:Vec<attr::CollisionAttributes>,
 	prop_models:Vec<model::Model>,
 	world_meshes:Vec<model::Mesh>,
 	world_models:Vec<model::Model>,
@@ -317,7 +362,7 @@ impl PartialMap1{
 	}
 }
 pub struct PartialMap2{
-	attributes:Vec<strafesnet_common::gameplay_attributes::CollisionAttributes>,
+	attributes:Vec<attr::CollisionAttributes>,
 	prop_meshes:Vec<(model::MeshId,model::Mesh)>,
 	prop_models:Vec<model::Model>,
 	world_meshes:Vec<model::Mesh>,