Okay, I actually think I got this one on my own. I'd still appreciate someone looking it over though, if that's okay:

vertex shader:

attribute vec4 tangent;

varying vec3 L, SD, H;

varying float distance;

void main(void)

{

gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;

mat3 tbn;

tbn[0] = tangent.xyz;

tbn[1] = cross(tangent.xyz, gl_Normal) * tangent.w;

tbn[2] = gl_Normal;

vec4 P = gl_ModelViewMatrixInverse * gl_LightSource[0].position;

if(gl_LightSource[0].position.w != 0.0) {

vec4 LV = P - gl_Vertex;

distance = length(LV.xyz);

L = normalize(tbn * LV.xyz);

} else {

distance = 1.0;

L = normalize(tbn * P.xyz);

}

vec4 half = gl_ModelViewMatrixInverse * gl_LightSource[0].halfVector;

SD = normalize(tbn * gl_LightSource[0].spotDirection);

H = normalize(tbn * half.xyz);

gl_TexCoord[0] = gl_MultiTexCoord0;

}

fragment shader:

uniform sampler2D detail, normalmap, specmap;

varying vec3 L, SD, H;

varying float distance;

void main(void)

{

float attenuation = 1.0;

if(gl_LightSource[0].position.w != 0.0) {

float distance2 = distance * distance;

attenuation = 1.0 / (gl_LightSource[0].constantAttenuation +

(gl_LightSource[0].linearAttenuation * distance) +

(gl_LightSource[0].quadraticAttenuation * distance2));

}

float spotlight = 1.0;

if(gl_LightSource[0].spotCutoff != 180.0) {

float value = max(dot(L, SD), 0.0);

if(value < gl_LightSource[0].spotCosCutoff)

spotlight = 0.0;

else

spotlight = pow(value, gl_LightSource[0].spotExponent);

}

vec3 normal = normalize(2.0 * texture2D(normalmap, vec2(gl_TexCoord[0])).xyz - 1.0);

float diffuse = max(dot(L, normal), 0.0);

float specular = max(dot(H, normal), 0.0);

vec4 speccolor = texture2D(specmap, vec2(gl_TexCoord[0])) * gl_LightSource[0].specular;

vec4 texcolor = texture2D(detail, vec2(gl_TexCoord[0]));

float temp = attenuation * spotlight;

gl_FragColor = gl_FrontLightModelProduct.sceneColor;

gl_FragColor += temp * (gl_FrontLightProduct[0].ambient + (diffuse * gl_FrontLightProduct[0].diffuse));

gl_FragColor *= texcolor;

gl_FragColor += temp * (pow(specular, gl_FrontMaterial.shininess) * speccolor);

}

It seems to work. I see a sort of gloss on the metalic sections of the models. I assume that's what I should be seeing? The gloss moves as I move, just as I would expect in the real world. It's really subtle though and I cranked the shininess up to 128. It's a cool effect, I just hope I'm doing it properly.