Index: src/bzfs/ParseMaterial.h
===================================================================
--- src/bzfs/ParseMaterial.h	(revision 21338)
+++ src/bzfs/ParseMaterial.h	(working copy)
@@ -22,11 +22,13 @@
 
 extern bool parseMaterials(const char* cmd, std::istream& input,
 			   BzMaterial* materials, int materialCount,
-			   bool& error);
+			   bool& error,
+			   bool physics = false);
 
 extern bool parseMaterialsByName(const char* cmd, std::istream& input,
 				 BzMaterial* materials, const char** names,
-				 int materialCount, bool& error);
+				 int materialCount, bool& error,
+				 bool physics = false);
 
 #endif  /* __PARSE_MATERIAL_H__ */
 
Index: src/bzfs/ParseMaterial.cxx
===================================================================
--- src/bzfs/ParseMaterial.cxx	(revision 21338)
+++ src/bzfs/ParseMaterial.cxx	(working copy)
@@ -20,12 +20,13 @@
 
 /* common implementation headers */
 #include "ParseColor.h"
+#include "PhysicsDriver.h"
 #include "TextureMatrix.h"
 #include "DynamicColor.h"
 
 
 bool parseMaterials(const char* cmd, std::istream& input,
-		    BzMaterial* materials, int materialCount, bool& error)
+		    BzMaterial* materials, int materialCount, bool& error, bool physics)
 {
   int i;
   error = false;
@@ -247,6 +248,48 @@ bool parseMaterials(const char* cmd, std::istream&
       materials[i].clearShaders();
     }
   }
+  else if (physics && (strcasecmp(cmd, "phydrv") == 0)) {
+    std::string drvname;
+    if (!(input >> drvname)) {
+      std::cout << "missing Physics Driver parameter" << std::endl;
+      return false;
+    }
+    const int phydrv = PHYDRVMGR.findDriver(drvname);
+    if ((phydrv == -1) && (drvname != "-1")) {
+      std::cout << "couldn't find PhysicsDriver: " << drvname << std::endl;
+    }
+    else {
+      for (i = 0; i < materialCount; i++) {
+        materials[i].setPhyDrv(phydrv);
+      }
+    }
+  }
+  else if (physics && (strcasecmp(cmd, "smoothbounce") == 0)) {
+    for (i = 0; i < materialCount; i++) {
+      materials[i].setSmoothBounce(true);
+    }
+  }
+  else if (physics && (strcasecmp(cmd, "noclusters") == 0)) {
+    for (i = 0; i < materialCount; i++) {
+      materials[i].setNoClusters(true);
+    }
+  }
+  else if (physics && (strcasecmp(cmd, "drivethrough") == 0)) {
+    for (i = 0; i < materialCount; i++) {
+      materials[i].setDriveThrough(true);
+    }
+  }
+  else if (physics && (strcasecmp(cmd, "shootthrough") == 0)) {
+    for (i = 0; i < materialCount; i++) {
+      materials[i].setShootThrough(true);
+    }
+  }
+  else if (physics && (strcasecmp(cmd, "passable") == 0)) {
+    for (i = 0; i < materialCount; i++) {
+      materials[i].setDriveThrough(true);
+      materials[i].setShootThrough(true);
+    }
+  }
   else {
     return false;
   }
@@ -257,7 +300,7 @@ bool parseMaterials(const char* cmd, std::istream&
 
 bool parseMaterialsByName(const char* cmd, std::istream& input,
 			  BzMaterial* materials, const char** names,
-			  int materialCount, bool& error)
+			  int materialCount, bool& error, bool physics)
 {
   error = false;
 
@@ -270,7 +313,8 @@ bool parseMaterialsByName(const char* cmd, std::is
       if (!(parms >> matcmd)) {
 	error = true;
       } else {
-	if (!parseMaterials(matcmd.c_str(), parms, &materials[n], 1, error)) {
+	if (!parseMaterials(matcmd.c_str(), parms, &materials[n],
+	                    1, error, physics)) {
 	  error = true;
 	}
       }
Index: src/bzfs/CustomMeshFace.cxx
===================================================================
--- src/bzfs/CustomMeshFace.cxx	(revision 21338)
+++ src/bzfs/CustomMeshFace.cxx	(working copy)
@@ -126,9 +126,16 @@ bool CustomMeshFace::read(const char *cmd, std::is
 void CustomMeshFace::write(MeshObstacle *mesh) const
 {
   const BzMaterial* matref = MATERIALMGR.addMaterial(&material);
-  mesh->addFace(vertices, normals, texcoords, matref, phydrv,
-		noclusters, smoothBounce, driveThrough, shootThrough,
-		true /* triangulate if required */);
+  int matPhydrv = matref->getPhyDrv();
+  int fullPhydrv = (matPhydrv != -1) ? matPhydrv : phydrv;
+  if (matref->getName() != "NullMaterial") {
+    mesh->addFace(vertices, normals, texcoords, matref, fullPhydrv,
+                  noclusters   || matref->getNoClusters(),
+                  smoothBounce || matref->getSmoothBounce(),
+                  driveThrough || matref->getDriveThrough(),
+                  shootThrough || matref->getShootThrough(),
+                  true /* triangulate if required */);
+  }
   return;
 }
 
Index: src/bzfs/CustomMaterial.cxx
===================================================================
--- src/bzfs/CustomMaterial.cxx	(revision 21338)
+++ src/bzfs/CustomMaterial.cxx	(working copy)
@@ -41,7 +41,7 @@ bool CustomMaterial::read(const char *cmd, std::is
 {
   bool materror;
 
-  if (parseMaterials(cmd, input, &material, 1, materror)) {
+  if (parseMaterials(cmd, input, &material, 1, materror, true)) {
     if (materror) {
       return false;
     }
Index: src/bzfs/WorldInfo.cxx
===================================================================
--- src/bzfs/WorldInfo.cxx	(revision 21338)
+++ src/bzfs/WorldInfo.cxx	(working copy)
@@ -397,6 +397,13 @@ InBuildingType WorldInfo::classifyHit (const Obsta
 bool WorldInfo::getFlagDropPoint(const FlagInfo* fi, const float* pos,
 				float* pt) const
 {
+  // NOTE: zoneflag allegiance takes precedence over team safeties
+  const std::string& idQual =
+    CustomZone::getFlagIdQualifier(fi->getIndex());
+  if (entryZones.getClosePoint(idQual, pos, pt)) {
+    return true;
+  }
+
   FlagType* flagType = fi->flag.type;
   const int team = (int)flagType->flagTeam;
   const bool teamFlag = (team != NoTeam);
@@ -408,11 +415,6 @@ bool WorldInfo::getFlagDropPoint(const FlagInfo* f
       return true;
     }
   } else {
-    const std::string& idQual =
-      CustomZone::getFlagIdQualifier(fi->getIndex());
-    if (entryZones.getClosePoint(idQual, pos, pt)) {
-      return true;
-    }
     const std::string& typeQual =
       CustomZone::getFlagTypeQualifier(flagType);
     if (entryZones.getClosePoint(typeQual, pos, pt)) {
Index: src/bzflag/playing.cxx
===================================================================
--- src/bzflag/playing.cxx	(revision 21338)
+++ src/bzflag/playing.cxx	(working copy)
@@ -766,7 +766,7 @@ static void doKeyPlaying(const BzfKeyEvent& key, b
 
 static bool roamMouseWheel(const BzfKeyEvent& key, bool pressed)
 {
-  if ((key.button != BzfKeyEvent::WheelUp) && 
+  if ((key.button != BzfKeyEvent::WheelUp) &&
       (key.button != BzfKeyEvent::WheelDown)) {
     return false;
   }
@@ -802,7 +802,7 @@ static void doKey(const BzfKeyEvent& key, bool pre
     case BzfKeyEvent::RightMouse:  { rightMouseButton  = pressed; break; }
     case BzfKeyEvent::MiddleMouse: { middleMouseButton = pressed; break; }
   }
-    
+
   if (roamMouseWheel(key, pressed)) {
     return;
   }
@@ -3310,7 +3310,7 @@ static void *handleMsgSetVars(void *msg)
     msg = nboUnpackString(msg, value, valueLen);
     value[valueLen] = '\0';
 
-    BZDB.set(name, value); 
+    BZDB.set(name, value);
     BZDB.setPersistent(name, false);
     BZDB.setPermission(name, StateDatabase::Locked);
   }
@@ -4975,7 +4975,7 @@ static void renderRoamMouse()
   static const float color1[4] = { 1.0f, 1.0f, 1.0f, 1.0f };
 
   glLineWidth(1.49f);
-  glBegin(GL_LINES);  
+  glBegin(GL_LINES);
   glColor4fv(color0); glVertex2i(xc, yc);
   glColor4fv(color1); glVertex2i(mx, my);
   glEnd();
Index: src/game/BzMaterial.cxx
===================================================================
--- src/game/BzMaterial.cxx	(revision 21338)
+++ src/game/BzMaterial.cxx	(working copy)
@@ -265,6 +265,12 @@ void BzMaterial::reset()
   shaders = NULL;
   shaderCount = 0;
 
+  phydrv       = -1;
+  driveThrough = false;
+  shootThrough = false;
+  smoothBounce = false;
+  noClusters   = false;
+
   referenced = false;
 
   return;
@@ -343,6 +349,12 @@ BzMaterial& BzMaterial::operator=(const BzMaterial
     shaders[i] = m.shaders[i];
   }
 
+  phydrv       = m.phydrv;
+  driveThrough = m.driveThrough;
+  shootThrough = m.shootThrough;
+  smoothBounce = m.smoothBounce;
+  noClusters   = m.noClusters;
+
   return *this;
 }
 
@@ -387,6 +399,13 @@ bool BzMaterial::operator==(const BzMaterial& m) c
     }
   }
 
+  if (phydrv       != m.phydrv)       { return false; }
+  if (driveThrough != m.driveThrough) { return false; }
+  if (shootThrough != m.shootThrough) { return false; }
+  if (smoothBounce != m.smoothBounce) { return false; }
+  if (noClusters   != m.noClusters)   { return false; }
+
+
   return true;
 }
 
@@ -526,6 +545,12 @@ void* BzMaterial::unpack(void* buf)
     buf = nboUnpackStdString(buf, shaders[i].name);
   }
 
+  phydrv       = -1;
+  driveThrough = false;
+  shootThrough = false;
+  smoothBounce = false;
+  noClusters   = false;
+
   return buf;
 }
 
@@ -948,6 +973,36 @@ void BzMaterial::clearShaders()
 }
 
 
+void BzMaterial::setPhyDrv(int value)
+{
+  phydrv = value;
+}
+
+
+void BzMaterial::setDriveThrough(bool value)
+{
+  driveThrough = value;
+}
+
+
+void BzMaterial::setShootThrough(bool value)
+{
+  shootThrough = value;
+}
+
+
+void BzMaterial::setSmoothBounce(bool value)
+{
+  smoothBounce = value;
+}
+
+
+void BzMaterial::setNoClusters(bool value)
+{
+  noClusters = value;
+}
+
+
 /****************************************************************************/
 //
 // Parameter retrieval
Index: include/BzMaterial.h
===================================================================
--- include/BzMaterial.h	(revision 21338)
+++ include/BzMaterial.h	(working copy)
@@ -85,6 +85,12 @@ class BzMaterial {
     void setShader(const std::string&);
     void clearShaders(); // remove all shaders
 
+    void setPhyDrv(int);
+    void setDriveThrough(bool);
+    void setShootThrough(bool);
+    void setSmoothBounce(bool);
+    void setNoClusters(bool);
+
     //
     // Parameter getting
     //
@@ -120,6 +126,12 @@ class BzMaterial {
     int getShaderCount() const;
     const std::string& getShader(int) const;
 
+    int  getPhyDrv()       const { return phydrv;       }
+    bool getDriveThrough() const { return driveThrough; }
+    bool getShootThrough() const { return shootThrough; }
+    bool getSmoothBounce() const { return smoothBounce; }
+    bool getNoClusters()   const { return noClusters;   }
+
     //
     // Utilities
     //
@@ -184,6 +196,12 @@ class BzMaterial {
     } ShaderInfo;
     ShaderInfo* shaders;
 
+    int phydrv;
+    bool driveThrough;
+    bool shootThrough;
+    bool smoothBounce;
+    bool noClusters;
+
   private:
     static std::string nullString;
     static BzMaterial defaultMaterial;
