Scripting - Proportional edit mesh
Smooth Shading.

A look at the docs bge.types.KX_MeshProxy reveals that 


  Vertices will be split by face if necessary. Vertices can only be
  shared between faces if:
  
  
  They are at the same position
  UV coordinates are the same
  Their normals are the same (both polygons are “Set Smooth”)
  They are the same color, for example: a cube has 24 vertices: 6 faces with 4 vertices per face
  


Smooth shading will stop the face separating from the mesh. Un-comment the lines marked with #SS in script below to test.

Pseudo linear falloff on a sphere.

Test script, on sensor event selects a random face, calculates the face center, finds all verts within a distance of that face center (arbitrary hardcoded 0.4) and moves them away using the face center vector.  (Using a sphere to test where the origin is centroid, so any local point on surface is also a radial vector (normal))

A vert at the center of the face can be moved the maximum (1.1) units away falling off linearly to zero for verts on or outside 0.4 from calculated center of face.

from mathutils import Vector
from random import randint

def deform(cont):
    ob = cont.owner

    if not cont.sensors["Mouse"].positive:
        return None

    mesh = ob.meshes[0]
    poly = mesh.getPolygon(randint(0, mesh.numPolygons - 1))
    material_index = poly.getMaterialIndex()
    # find center of poly
    cent = Vector()
    n = poly.getNumVertex()
    for i in range(n):
        v = mesh.getVertex(material_index, getattr(poly, "v%d" % (i + 1)))
        cent += v.XYZ
        v.color = [1.0, 1.0, 0.0, 1.0] # juicy yellow head.
        #v.XYZ *= 1.1 #SS
    cent /= n
    #return # SS
    # get all the verts within 0.4 radius of cent
    for v_index in range(mesh.getVertexArrayLength(material_index)):
         v = mesh.getVertex(material_index, v_index)
         d = (v.XYZ - cent)
         if d.length &lt;= 0.4:
             v.XYZ += 1.1 / 0.4 * (0.4 - d.length) * cent.normalized()