Basic Clientmuzzle & 3D Hud
Tutorial
This tutorial is divided
into two parts:
- the first part describes how to create a simple 3D Hud which is accessable
from the game dll.
- the second pard describes how to spawn a Muzzleflash entity on this Hud.
1. 3D Hud
The first thing a 3D hud
needs are objects. These objects have to
be available in the game dll for easier use. They also have to be available
on the client. A good object with this properties is an entity.
You also can give entities different effects like EF_QUAD.
Sometimes they will lag down clients and servers, but since
Aimbots are easy to create Quake2 is only playable on LAN.
So let us start with the
shit... ;) the first thing we need is
an identification for a Hud model - a flag. A flag which stays
for the main Hud model is the RF_WEAPONMODEL flag. We will use
it to tell the client which is a Hud model and which not.
The next thing we need is a pointer to the owner: ent->owner.
A Hud model will only be sent to this owner - not to the other clients.
So we need the source to block it... and her it is:
open up "sv_ents.c"
from your Quake2.exe source and add this code
in SV_BuildClientFrame:
<C&NBSP;CODE>
[...]
// ignore ents without visible models unless they have an effect
if (!ent->s.modelindex && !ent->s.effects && !ent->s.sound
&& !ent->s.event)
continue;
// ignore if not touching a PV leaf
//==== added (RF_WEAPONMODEL) ====
if (ent->s.renderfx & RF_WEAPONMODEL)
{
if (clent != ent->owner)
continue;
} else
//========
if (ent != clent)
{
// check area
if (!CM_AreasConnected (clientarea, ent->areanum))
{ // doors can legally straddle two areas, so
// we may need to check another one
if (!ent->areanum2
|| !CM_AreasConnected (clientarea, ent->areanum2))
continue; // blocked by a door
}
[...]
</C&NBSP;CODE>
Ok - this is the stuff on the server. Now we need a function on the client.
This function looks thru all entities and does some special calculations for
the Hud models: first it will rotate the entities to the right position
in the clients view. The secont thing it does is to copy the clients angles
to the entity. At last it will move it to right screen position:
you have to insert the
following code into "cl_ents.c". Scroll
down to CL_AddPacketEntities.
<C&NBSP;CODE>
[...]
else
{ // interpolate angles
float a1, a2;
for (i=0 ; i<3 ; i++)
{
a1 = cent->current.angles[i];
a2 = cent->prev.angles[i];
ent.angles[i] = LerpAngle (a2, a1, cl.lerpfrac);
}
}
//==== added (RF_WEAPONMODEL) ====
if (renderfx & RF_WEAPONMODEL)
{
int n;
// rotate the model position
for (n=0; n<3; n++)
{
int n_prev = (n==2) ? (0) : (n+1);
int n_real = (n_prev==2) ? (0) : (n_prev+1);
float sin_w = sin (cl.refdef.viewangles[n_real] * 3.1415926536897932384626433832795 / 180);
float cos_w = cos (cl.refdef.viewangles[n_real] * 3.1415926536897932384626433832795 / 180);
float temp_new = ent.origin[n_prev];
float temp_old = ent.oldorigin[n_prev];
ent.origin[n_prev] = cos_w * temp_new - sin_w * ent.origin[n_real];
ent.origin[n_real] = sin_w * temp_new + cos_w * ent.origin[n_real];
ent.oldorigin[n_prev] = cos_w * temp_old - sin_w * ent.oldorigin[n_real];
ent.oldorigin[n_real] = sin_w * temp_old + cos_w * ent.oldorigin[n_real];
}
// copy player angles
ent.angles[0] = cl.refdef.viewangles[0];
ent.angles[1] = cl.refdef.viewangles[1];
ent.angles[2] = -cl.refdef.viewangles[2];
// move the model to vieworg
VectorAdd(ent.origin, cl.refdef.vieworg, ent.origin);
VectorAdd(ent.oldorigin, cl.refdef.vieworg, ent.oldorigin);
}
//========
if (s1->number == cl.playernum+1)
{
ent.flags |= RF_VIEWERMODEL; // only draw from mirrors
// FIXME: still pass to refresh
if (effects & EF_FLAG1)
V_AddLight (ent.origin, 225, 1.0, 0.1, 0.1);
else if (effects & EF_FLAG2)
V_AddLight (ent.origin, 225, 0.1, 0.1, 1.0);
else if (effects & EF_TAGTRAIL) //PGM
V_AddLight (ent.origin, 225, 1.0, 1.0, 0.0); //PGM
else if (effects & EF_TRACKERTRAIL) //PGM
V_AddLight (ent.origin, 225, -1.0, -1.0, -1.0); //PGM
continue;
}
[...]
</C&NBSP;CODE>
Thats it - the whole 3D Hud code !!! (whew ;)
2. Basic Client Muzzle
Now we only have to spawn
an entity with the RF_WEAPONMODEL flag
turned on and an owner client:
open
"g_local.h" and add a pointer to our Muzzle entity:
put this code at the very end of the file:
<C&NBSP;CODE>
gitem_t *item; // for bonus items
// common data blocks
moveinfo_t moveinfo;
monsterinfo_t monsterinfo;
//==== added (player muzzle) ====
edict_t *muzzle_ent;
//========
};
</C&NBSP;CODE>
now you have to spawn a Muzzle entity, if a player uses his weapon...
add this code in Weapon_Generic:
<C&NBSP;CODE>
[...]
if (ent->client->weaponstate == WEAPON_FIRING)
{
for (n = 0; fire_frames[n]; n++)
{
if (ent->client->ps.gunframe == fire_frames[n])
{
if (ent->client->quad_framenum > level.framenum)
gi.sound(ent, CHAN_ITEM, gi.soundindex("items/damage3.wav"), 1, ATTN_NORM, 0);
//==== added (player muzzle) ====
if (!ent->muzzle_ent)
{
if (ent->client->ps.gunindex)
{
ent->muzzle_ent = G_Spawn();
VectorSet(ent->muzzle_ent->s.origin, 40, -12, 0);
VectorCopy(ent->muzzle_ent->s.origin, ent->muzzle_ent->s.old_origin);
ent->muzzle_ent->s.modelindex = gi.modelindex("sprites/s_flash.sp2");
ent->muzzle_ent->s.renderfx = RF_WEAPONMODEL | RF_FULLBRIGHT;
ent->muzzle_ent->s.effects = EF_SPHERETRANS;
ent->muzzle_ent->owner = ent;
gi.linkentity(ent->muzzle_ent);
}
}
//========
fire (ent);
break;
}
}
[...]
</C&NBSP;CODE>
At last you have to delete the Muzzleflash. The code I used to
do this is not very nice because it deletes the Muzzle every frame
but it works... and this night is LAN party in town - no time to optimize
the code ;)
add this at the top of
Weapon_Generic:
<C&NBSP;CODE>
void Weapon_Generic (edict_t *ent, int FRAME_ACTIVATE_LAST, int FRAME_FIRE_LAST, int FRAME_IDLE_LAST, int FRAME_DEACTIVATE_LAST, int *pause_frames, int *fire_frames, void (*fire)(edict_t *ent))
{
int n;
//==== added (player muzzle) ====
if (ent->muzzle_ent)
{
G_FreeEdict(ent->muzzle_ent);
ent->muzzle_ent = NULL;
}
//========
if(ent->deadflag || ent->s.modelindex != 255) // VWep animations screw up corpses
{
return;
}
[...]
</C&NBSP;CODE>
Thats it, sorry for the poor discriptions but I have no time and
it seems to me that you guys are waiting for this Muzzle stuff... ;)
- outlaw
|