[page=Introduction]
Alright, this tutorial is very easy. Just follow my steps, and you'll be fine.
Again with my little statement. I think you should always make your own files for each function you add, because it makes it easy to edit.
[page=Adding The Command]
First, we'll start by the last thing.. I know it's odd, but incase we forget we might as well do this first.
Find:
else if (Q_stricmp (cmd, "wave") == 0)
Cmd_Wave_f (ent);
Under it, add these two:
// Paril - Added for the Push/Pull
else if (Q_stricmp (cmd, "push") == 0)
Cmd_Push_f (ent);
else if (Q_stricmp (cmd, "pull") == 0)
Cmd_Pull_f (ent);
Good. Now, to the meat and bones of the command: The trace!
[page=Cmd_Push function]
Let's start by adding the Cmd_Push_f function. Find the function Cmd_Wave_f, and when it ends, let's start adding:
/*
=================
Cmd_Push_f
Added by Paril for Push/Pull
=================
*/
void Cmd_Push_f (edict_t *ent)
{
vec3_t start;
vec3_t forward;
vec3_t end;
trace_t tr;
VectorCopy(ent->s.origin, start); // Copy your location
start[2] += ent->viewheight; // vector for start is at your height of view
AngleVectors(ent->client->v_angle, forward, NULL, NULL); // Angles
VectorMA(start, 8192, forward, end); // How far will the line go?
tr = gi.trace(start, NULL, NULL, end, ent, MASK_SHOT); // Trace the line
if ( tr.ent && ((tr.ent->svflags & SVF_MONSTER) || (tr.ent->client)) ) // Trace the line
{
VectorScale(forward, 5000, forward); //Where to hit? Edit 5000 to whatever you like the push to be
VectorAdd(forward, tr.ent->velocity, tr.ent->velocity); // Adding velocity vectors
}
}
Not hard is it? Cmd_Pull_f is the same pretty much. Let's check it out!
[page=Cmd_Pull]
Now, let's pull your enemies into that dazzling lava!
/*
=================
Cmd_Pull_f
Added by Paril for Push/Pull
=================
*/
void Cmd_Pull_f (edict_t *ent)
{
vec3_t start;
vec3_t forward;
vec3_t end;
trace_t tr;
VectorCopy(ent->s.origin, start); // Copy your location
start[2] += ent->viewheight; // vector for start is at your height of view
AngleVectors(ent->client->v_angle, forward, NULL, NULL); // Angles
VectorMA(start, 8192, forward, end); // How far will the line go?
tr = gi.trace(start, NULL, NULL, end, ent, MASK_SHOT); // Trace the line
if ( tr.ent && ((tr.ent->svflags & SVF_MONSTER) || (tr.ent->client)) ) // Trace the line
{
VectorScale(forward, -5000, forward); //Where to hit? Edit -5000 to whatever you like the push to be
VectorAdd(forward, tr.ent->velocity, tr.ent->velocity); // Adding velocity vectors
}
}
It's EXACTLY the same, but pulling -5000 instead of pushing 5000.
Not a hard concept, but can be used for good.
[page=Modifications to the Push and Pull]
You can change the Push/Pull for more of an effect, say if you want it to send a sound for when it's transmitted, add this after the trace of the line (make sure to change both):
gi.sound (ent, CHAN_AUTO, gi.soundindex ("items/damage2.wav"), 1, ATTN_NORM, 0);
Also, this can be altered to spawn a laser when the trace is spawned by adding this after the VectorAdd:
// set origin of laser beam
VectorMA (start, 8192, forward, end);
VectorCopy (ent->s.origin, start);
// trace for end point of laser beam.
// the laser aim is perfect.
tr = gi.trace (from, NULL, NULL, end, self, MASK_SHOT);
// send laser beam temp entity to clients
VectorCopy (tr.endpos, from);
gi.WriteByte (svc_temp_entity);
gi.WriteByte (TE_BFG_LASER);
gi.WritePosition (start);
gi.WritePosition (tr.endpos);
gi.multicast (ent->s.origin, MULTICAST_PHS);
I haven't tested the laser part, but play around with it and see how it works.
Many things can be added, like an ammo requirement for example, by adding this at the beginning:
if (ent->client->pers.inventory[ITEM_INDEX(Finditem ("Cells"))] <= 9) // requires 10 cells
{
gi.cprintf (ent, PRINT_HIGH, "You need 10 cells to use Push or Pull\n"); // Notify them
return; // Stop the command from going
}
Now, after the VectorAdd, add:
ent->client->pers.inventory[ITEM_INDEX(Finditem ("Cells"))] -= 10;
Anyways, this Push/Pull can be the base of a tractor beam weapon if you wanted it to be.
That's all for now..
Paril('s Uber Cool Tutorials) ;)
Careful!
Both of your functions for Push and Pull are named void Cmd_Push_f (edict_t *ent), you just changed the VectorScale value.
error C2084: function 'void __cdecl Cmd_Push_f(struct edict_s *)' already has a body
And, no, your laser code does not work:
tr = gi.trace (from, NULL, NULL, end, self, MASK_SHOT);
error C2065: 'from' : undeclared identifier
error C2065: 'self' : undeclared identifier
error C2109: subscript requires array or pointer type
error C2198: 'gi' : too few actual parameters
As for the ammo requirment:
error C2113: pointer can only be subtracted from another pointer.
So, if you don't add any of the additional modifications, the Push/Pull functions work fine.
farbin
Sorry, that's a very old tutorial.
I'll fix it right now.
As for the ammo requirment:
error C2113: pointer can only be subtracted from another pointer.
Not sure where that came from....
I'll check about the laser.