diff --git a/xs/src/libslic3r/GCode/WipeTowerPrusaMM.cpp b/xs/src/libslic3r/GCode/WipeTowerPrusaMM.cpp
index 0b3a023a4..e51b43430 100644
--- a/xs/src/libslic3r/GCode/WipeTowerPrusaMM.cpp
+++ b/xs/src/libslic3r/GCode/WipeTowerPrusaMM.cpp
@@ -92,7 +92,7 @@ public:
 		if (! m_preview_suppressed && e > 0.f && len > 0.) {
 			// Width of a squished extrusion, corrected for the roundings of the squished extrusions.
 			// This is left zero if it is a travel move.
-			float width = float(double(e) * m_filament_area / (len * m_layer_height));
+			float width = float(double(e) * Filament_Area / (len * m_layer_height));
 			// Correct for the roundings of a squished extrusion.
 			width += m_layer_height * float(1. - M_PI / 4.);
 			if (m_extrusions.empty() || m_extrusions.back().pos != rotated_current_pos)
@@ -258,6 +258,25 @@ public:
 		return *this;
 	};
 
+
+	Writer& set_fan(unsigned int speed)
+	{
+		if (speed == m_last_fan_speed)
+			return *this;
+				
+		if (speed == 0)
+			m_gcode += "M107\n";
+		else
+		{
+			m_gcode += "M106 S";
+			char buf[128];
+			sprintf(buf,"%u\n",(unsigned int)(255.0 * speed / 100.0));
+			m_gcode += buf;
+		}
+		m_last_fan_speed = speed;
+		return *this;
+	}
+
 	Writer& comment_material(WipeTowerPrusaMM::material_type material)
 	{
 		m_gcode += "; material : ";
@@ -294,13 +313,15 @@ private:
 	std::string   m_gcode;
 	std::vector<WipeTower::Extrusion> m_extrusions;
 	float         m_elapsed_time;
-	const double  m_filament_area = 0.25*M_PI*1.75*1.75;
 	float   	  m_angle_deg = 0;
 	WipeTower::xy m_wipe_tower_pos;
 	float 		  m_wipe_tower_width;
 	float		  m_wipe_tower_depth;
+	float		  m_last_fan_speed = 0.f;
 
-	std::string   set_format_X(float x) {
+		std::string
+		set_format_X(float x)
+	{
 		char buf[64];
 		sprintf(buf, " X%.3f", x);
 		m_current_pos.x = x;
@@ -1116,7 +1137,7 @@ WipeTower::ToolChangeResult WipeTowerPrusaMM::finish_layer(Purpose purpose)
 
 // Appends a toolchange into m_plan and calculates neccessary depth of the corresponding box
 
-void WipeTowerPrusaMM::plan_toolchange(float z_par, float layer_height_par, unsigned int old_tool, unsigned int new_tool)
+void WipeTowerPrusaMM::plan_toolchange(float z_par, float layer_height_par, unsigned int old_tool, unsigned int new_tool,bool brim)
 {
 	assert(m_plan.back().z <= z_par);	// refuse to add a layer below the last one
 	
@@ -1131,20 +1152,18 @@ void WipeTowerPrusaMM::plan_toolchange(float z_par, float layer_height_par, unsi
 														  { 60, 40, 60,  0}};
 
 	float depth = (wipe_volumes[old_tool][new_tool]) / (m_extrusion_flow * Filament_Area); // length of extrusion
+	depth += 6 * 59; // reserved for ramming
+	depth += 2 * 59; // reserved for loading
+	depth -= 2 * 59; // we will also print borders
 	depth = floor(depth / m_wipe_tower_width + 1);	// number of lines to extrude
-	depth += 6; // reserved for ramming
-	depth += 2; // reserved for loading
-	depth -= 2; // we will also print borders
 	depth *= m_perimeter_width; // conversion to distance
 
 	if (m_plan.empty() || m_plan.back().z + WT_EPSILON < z_par) // if we moved to a new layer, we'll add it to m_plan along with the first toolchange
 		m_plan.push_back(WipeTowerInfo(z_par, layer_height_par));
 
-	if ( old_tool != new_tool )	{
-		if (!m_plan_brim_finished) {	// this toolchange prints brim, we need it in m_plan, but not to count its depth
-			m_plan_brim_finished = true;
+	if ( brim || old_tool != new_tool )	{
+		if (brim) // this toolchange prints brim, we need it in m_plan, but not to count its depth
 			depth = 0.f;
-		}
 		m_plan.back().tool_changes.push_back(WipeTowerInfo::ToolChange(old_tool, new_tool, depth));
 	}
 
@@ -1173,7 +1192,6 @@ void WipeTowerPrusaMM::generate(std::vector<std::vector<WipeTower::ToolChangeRes
 	
 	for (auto layer : m_plan)
 	{
-
 		set_layer(layer.z,layer.height,0,layer.z == m_plan.front().z,layer.z == m_plan.back().z);
 
 		for (const auto &toolchange : layer.tool_changes)
diff --git a/xs/src/libslic3r/GCode/WipeTowerPrusaMM.hpp b/xs/src/libslic3r/GCode/WipeTowerPrusaMM.hpp
index 574accd75..04e0b004a 100644
--- a/xs/src/libslic3r/GCode/WipeTowerPrusaMM.hpp
+++ b/xs/src/libslic3r/GCode/WipeTowerPrusaMM.hpp
@@ -92,7 +92,7 @@ public:
 
 	// Setter for internal structure m_plan containing info about the future wipe tower
 	// to be used before building begins. The entries must be added ordered in z.
-	void plan_toolchange(float z_par, float layer_height_par, unsigned int old_tool, unsigned int new_tool);
+	void plan_toolchange(float z_par, float layer_height_par, unsigned int old_tool, unsigned int new_tool, bool brim);
 
 	void generate(std::vector<std::vector<WipeTower::ToolChangeResult>> &result);
 
@@ -131,6 +131,7 @@ public:
 		// Calculates extrusion flow from desired line width, nozzle diameter, filament diameter and layer_height
 		m_extrusion_flow = extrusion_flow(layer_height);
 
+		// FIXME - ideally get rid of set_layer altogether and iterate through m_plan in generate(...)
 		m_layer_info = nullptr;
 		for (auto &a : m_plan)
 			if ( a.z > print_z - WT_EPSILON && a.z < print_z + WT_EPSILON ) {
@@ -170,12 +171,7 @@ public:
 	// the wipe tower has been completely covered by the tool change extrusions,
 	// or the rest of the tower has been filled by a sparse infill with the finish_layer() method.
 	virtual bool 			 layer_finished() const {
-		
-		if (m_is_first_layer) {
-			return (m_wipe_tower_depth - WT_EPSILON < m_current_wipe_start_y);
-		}
-		else
-			return (m_layer_info->depth - WT_EPSILON < m_current_wipe_start_y);
+		return ( (m_is_first_layer ? m_wipe_tower_depth : m_layer_info->depth) - WT_EPSILON < m_current_wipe_start_y);
 	}
 
 
@@ -241,10 +237,8 @@ private:
 	// after the wipe tower brim has been extruded?
 	float  			m_initial_extra_wipe = 0.f;
 	float			m_last_infill_tan = 1000.f;	// impossibly high value
-	bool 			m_plan_brim_finished = false;
 
-		float
-		extrusion_flow(float layer_height = -1.f)
+	float extrusion_flow(float layer_height = -1.f) const
 	{
 		if ( layer_height < 0 )
 			return m_extrusion_flow;
diff --git a/xs/src/libslic3r/Print.cpp b/xs/src/libslic3r/Print.cpp
index 8b7f9805c..64f4d6046 100644
--- a/xs/src/libslic3r/Print.cpp
+++ b/xs/src/libslic3r/Print.cpp
@@ -1050,10 +1050,10 @@ void Print::_make_wipe_tower()
         for (const auto &layer_tools : m_tool_ordering.layer_tools()) { // for all layers
             if (!layer_tools.has_wipe_tower) continue;
             bool first_layer = &layer_tools == &m_tool_ordering.front();
-            wipe_tower.plan_toolchange(layer_tools.print_z, layer_tools.wipe_tower_layer_height, current_extruder_id, current_extruder_id);
+            wipe_tower.plan_toolchange(layer_tools.print_z, layer_tools.wipe_tower_layer_height, current_extruder_id, current_extruder_id,false);
             for (const auto extruder_id : layer_tools.extruders) {
-                if ((first_layer && extruder_id == m_tool_ordering.all_extruders().back()) || extruder_id != current_extruder_id) {          
-                    wipe_tower.plan_toolchange(layer_tools.print_z, layer_tools.wipe_tower_layer_height, current_extruder_id, extruder_id);
+                if ((first_layer && extruder_id == m_tool_ordering.all_extruders().back()) || extruder_id != current_extruder_id) {
+                    wipe_tower.plan_toolchange(layer_tools.print_z, layer_tools.wipe_tower_layer_height, current_extruder_id, extruder_id, first_layer && extruder_id == m_tool_ordering.all_extruders().back());
                     current_extruder_id = extruder_id;
                 }
             }
@@ -1066,7 +1066,6 @@ void Print::_make_wipe_tower()
 
     // Generate the wipe tower layers.
     m_wipe_tower_tool_changes.reserve(m_tool_ordering.layer_tools().size());
-
     wipe_tower.generate(m_wipe_tower_tool_changes);
     
     // Set current_extruder_id to the last extruder primed.