I was recently asked how to add wheels to entities and also how to rotate the ones that align incorrectly. Below is the solution SourceOP uses:
Code:
const char szTires[][64] = {"models/props_vehicles/tire001c_car.mdl",
                            "models/props_vehicles/apc_tire001.mdl",
                            "models/props_vehicles/tire001a_tractor.mdl",
                            "models/props_wasteland/wheel01a.mdl",
                            "models/props_wasteland/wheel02a.mdl"};

...

////MAKE WHEEL////
CBaseEntity *pProp = NULL;
pProp = CreateEntityByName( "prop_physics_multiplayer" );

if(!pProp)
{
    SayTextChatHud(UTIL_VarArgs("[%s] Spawn failure.\n", pAdminOP.adminname));
    return PLUGIN_STOP;
}

QAngle angles;
VectorAngles(tr.plane.normal, angles);

VFuncs::KeyValue(pProp,  "model", szTires[wheel] );
VFuncs::KeyValue(pProp,  "spawnflags", "256" );
VFuncs::KeyValue(pProp,  "physdamagescale", "0.1" );
VFuncs::KeyValue(pProp,  "ExplodeDamage", "0" );
VFuncs::KeyValue(pProp,  "ExplodeRadius", "0" );
VFuncs::Spawn(pProp);
VFuncs::Activate(pProp);
VFuncs::SetModel( pProp, szTires[wheel] );
//////////////////

////GET SIZE////
int i = modelinfo->GetModelIndex( szTires[wheel] );
if ( i < 0 )
{
    SayTextChatHud(UTIL_VarArgs("[%s] Wheel not precached.\n", pAdminOP.adminname));
    return PLUGIN_STOP;
}
const model_t *mod = modelinfo->GetModel( i );
if ( !mod )
{
    SayTextChatHud(UTIL_VarArgs("[%s] Wheel has no model_t. This is an engine error.\n", pAdminOP.adminname));
    return PLUGIN_STOP;
}
modelinfo->GetModelBounds( mod, mins, maxs );
VectorSubtract( maxs, mins, vecSize );
////////////////

if(wheel < 3)
{
    VFuncs::Teleport(pProp, &(tr.endpos + (tr.plane.normal * (vecSize.x/2))), &angles, NULL );
}
else
{
    matrix3x4_t     m_rgflCoordinateFrame;
    Vector vecorigin = tr.endpos + tr.plane.normal * (maxs.y - (mins.y + maxs.y));
    VFuncs::Teleport(pProp, &vecorigin, &angles, NULL );
    /////////////ROTATE WHEELS THAT FACE WRONG DIRECTION/////////
    const float rotationAngle = -90;

    // calculate coordinate frame so that we don't have to use EntityToWorldTransform()
    AngleMatrix( angles, vecorigin, m_rgflCoordinateFrame );

    // compute rotation axis in entity local space
    // compute the transform as a matrix so we can concatenate it with the entity's current transform
    Vector rotationAxisLs = Vector(0,0,1);

    // build a transform that rotates around that axis in local space by the angle
    // if there were an AxisAngleMatrix() routine we could use that directly, but there isn't 
    // so convert to a quaternion first, then a matrix
    Quaternion q;

    // NOTE: assumes axis is a unit vector, non-unit vectors will bias the resulting rotation angle (but not the axis)
    AxisAngleQuaternion( rotationAxisLs, rotationAngle, q );
                        
    // convert to a matrix
    matrix3x4_t xform;
    QuaternionMatrix( q, vec3_origin, xform );
                        
    // apply the rotation to the entity input space (local)
    matrix3x4_t localToWorldMatrix;
    ConcatTransforms( m_rgflCoordinateFrame, xform, localToWorldMatrix );

    // extract the compound rotation as a QAngle
    QAngle localAngles;
    MatrixAngles( localToWorldMatrix, localAngles );
    /////////END ROTATE WHEELS THAT FACE WRONG DIRECTION/////////

    VFuncs::SetAbsAngles(pProp, localAngles);
}

spawnedEnts.AddToTail(VFuncs::entindex(pProp));
pAdminOP.spawnedServerEnts.AddToTail(VFuncs::entindex(pProp));
//////////////////

//////ADD HINGE//////////
IPhysicsConstraint  *m_pConstraint;
IPhysicsObject *pReference = VFuncs::VPhysicsGetObject(pSet);
IPhysicsObject *pAttached = VFuncs::VPhysicsGetObject(pProp);
if ( !pReference || !pAttached )
{
    return PLUGIN_STOP;
}

constraint_hingeparams_t hinged;
hinged.Defaults();
hinged.worldPosition = tr.endpos;
hinged.worldAxisDirection = tr.plane.normal;

m_pConstraint = physenv->CreateHingeConstraint( pReference, pAttached, NULL, hinged );
////////////////////////////

pConstraint = m_pConstraint;
if(pConstraint)
{
    physConstraints.AddToTail(pConstraint);
    SayTextChatHud(UTIL_VarArgs("[%s] Wheel added to ent %i. New ent = %i with constraint ID %i\n", pAdminOP.adminname, VFuncs::entindex(pSet), VFuncs::entindex(pProp), physConstraints.Tail()));
}
else
{
    SayTextChatHud(UTIL_VarArgs("[%s] Unable to add constraint.\n", pAdminOP.adminname));
}
Hopefully this is useful. You should be able to take the important parts and make it work in a SourceMod extension/plugin.

streeeeeeeeeeeeetchingpostwidthforeasierreadabilit ysorrymyforumsucksandisfromninetyninetyninestreeee eeeeeeeeetchingpostwidthforeasierreadabilitysorrym yforumsucksandisfromninetyninetynine