This tutorial was written by Hap of Freeform Interactive. This tutorial will create a Special Ops style chase cam. It also features a viewable weapon. You can download the exe and source files associated with this tutorial by clicking here. NOTE: This is a Beta 2 tutorial.

We first must edit the client.c file.

Go to line 866. Make the code around the area look something like this.

else if (IsKeyDown('4', Host->hWnd))
{
Client->CurrentWeapon = 3;
}
else if (IsKeyDown('0', Host->hWnd))
{
if (Client->Chasecam == TRUE)
Client->Chasecam = FALSE;
else
Client->Chasecam = TRUE;

}

else if (NewKeyDown(KeyLut[VK_CONTROL], Host->hWnd))

Next go to line 1731 and edit the code to look something like the code below

                geWorld_DestroyActor(Host->World, Player->Actor);
                Player->Actor = NULL;
            }        
           

// Make it render in chasecam
/*if (Client->ViewPlayer == PlayerIndex)             // Only render viewplayer in mirrors
{
                Player->Actor = geWorld_CreateActor(Host->World, ActorDef, GE_ACTOR_RENDER_MIRRORS|GE_ACTOR_COLLIDE, 0xffffffff);
                //Player->Actor = geWorld_CreateActor(Host->World, ActorDef, GE_ACTOR_COLLIDE, 0xffffffff);
            }
            else
            { */

                Player->Actor = geWorld_CreateActor(Host->World, ActorDef, GE_ACTOR_RENDER_NORMAL|GE_ACTOR_COLLIDE, 0xffffffff);
//            }


if (!Player->Actor)
                GenVS_Error("[CLIENT] CheckClientPlayerChanges: Could not add actor to world. ActorDef Name: %s.\n", Host->ActorIndex[ViewIndex].ActorName);

Now go to line 1884 to look something like the code below

    geVec3d             Pos;
    GPlayer             *Player;

float xtrans, ztrans;
float ydistance,distance; //Distance between Actor and camera
int tooClose = FALSE; //If the distance is too close, disable chasecam

GE_Collision Collision;
geVec3d Front, Back, In, Help;
geVec3d Mins = {-1.0f, -1.0f, -1.0f};
geVec3d Maxs = { 1.0f, 1.0f, 1.0f};


A few lines below that(the original line 1928) you will want to change the code to look like this

    Client->ViewXForm = Player->XForm;

    if (Client->Host->Demo.Mode != HOST_DEMO_PLAY && !(Player->ViewFlags & VIEW_TYPE_FORCE_XFORM))
    {
        Pos = Client->ViewXForm.Translation;

geXForm3d_GetIn(&Client->ViewXForm, &In);

//Send ray to examine if player is looking up or down by determining the height difference
//(300.0f = max camera distance)
geVec3d_AddScaled (&Pos, &In, -1000.0f, &Help);
ydistance = 300.0f - (float)fabs(Pos.Y - Help.Y);
ydistance *= 2; //we get headache when it moves too much

//Start sending ray 20.0f from behind Actor, or it will collide with the Actor self
geVec3d_AddScaled(&Pos, &In, -20.0f, &Front);

//Start sending ray in View-Height
Front.Y = Front.Y + 190.0f;
Back.Y = Back.Y + 190.0f;

//Look 10000.0f behind
geVec3d_AddScaled(&Front, &In, -10000.0f, &Back);

//if backward ray collides with wall decrease camera distance
if (geWorld_Collision(Client->Host->World, NULL, NULL, &Front, &Back, GE_COLLIDE_ALL, 0xffffffff, &Collision))
{
//Get Distance behind Actor and Wall
distance = (float)fabs(geVec3d_DistanceBetween(&Collision.Impact,&Front));
//Minimum between looking up/down and Wall behind
distance = min(distance, ydistance);
//distance ranges:
if (distance < 50.0f)
tooClose = TRUE; //if it is so damn close, use shouldercam
//if (distance < 50.0f)
// distance = 50.0f;
else if (distance > 300.0f)
distance = 300.0f;
}


// Clear the matrix
        geXForm3d_SetIdentity(&Client->ViewXForm);
        // Rotate then translate.
        geXForm3d_RotateZ(&Client->ViewXForm, Client->Angles.Z);

        geXForm3d_RotateX(&Client->ViewXForm, Client->Angles.X);
        geXForm3d_RotateY(&Client->ViewXForm, Client->Angles.Y);
   

if (Client->Chasecam && !tooClose)
{
xtrans = (float) (sin(Client->Angles.Y)*distance);
ztrans = (float) (cos(Client->Angles.Y)*distance);
}


        geXForm3d_Translate(&Client->ViewXForm, Pos.X, Pos.Y, Pos.Z);
    }
    // HACK the view height till we get it in
    // Just use a vakue that looks good for now...
    //Client->ViewXForm.Translation.Y += 140.0f;
Client->ViewXForm.Translation.Y += 190.0f;


if (Client->Chasecam && !tooClose)
{
Client->ViewXForm.Translation.X += xtrans;
Client->ViewXForm.Translation.Z += ztrans;
}


}

Next load up the client.h file for editing. Go to line 159 and edit the code to look somethiing like this

    float                 NextSend;

    GenVSI                 GenVSI;

int Chasecam; //use Chasecam

} Client_Client;

Lastly we need to change the guns offset. Load up the game.c file. Go to line 311 and edit the code to look something like this(CYAN=NEW CODE)

    Player->Maxs.X = 30.0f;
    Player->Maxs.Y = 160.0f;
    Player->Maxs.Z = 30.0f;

    //GenVSI_SetClientGunOffset(VSI, ClientHandle, 0.0f, 130.0f, 0.0f);
    Player->GunOffset.X = 0.0f;
    Player->GunOffset.Y = 190.0f;
    Player->GunOffset.Z = 0.0f;