|
posted 11-22-98 3:49 PM CT (US)
Title: Transformer Gladiator
Difficulty: Moderate
By: Philip (aka Maj.Bitch)
Email: peblair@gv.net
Date: 11-22-98
Note: Please give credit where credit is due.
======================================================
Hey Space Marines, I
was thinking.. I'm sure that you've seen
the single player monster called the 'Gladiator'? It's the bald
headed guy in the big metallic suit who has one arm as a rail gun
and the other is this big two-pronged claw which spins around and
shreds your guts! Well, as a little experiment, I put together
the following transformer routines (which you can expand to any
of the monster types) see: "Putting Monsters in your Source"/
Okay, what is it..
You are getting the
snot beat out of you so, for the cost of
2 frags, you hit your aliased key and a big explosion happens
right at your feet. When the fireball clears up, standing
there is the gladiator!! And you are inside of it looking
out of the gladiator's eyes (actually, slightly above the
head so the graphics don't obscure your view of the fighting)!
Now, the gladiator
has a health of 750 so this baby really can
take some direct hits before going down. Also, it's railgun
is deadly accurate and it's claw will shred anybody within
arm's length. It does all the fraggin for you until destroyed
(and you get all the frags!)
Also, if your
gladiator gets killed, then that player gets 7 frags
for taking this bastard down!
Let your Gladiator
rack up the frags!
GREAT for standing
guard in some area where you'll be under heavy
attack! Transform yourself into one of these babies and get on
with the Killing!!
NOTE: Perhaps code
could be added to control the Gladiator's weapons
and make it move where you want it to go! Another project...
Okay, let's get
started!
============================================================
============================================================
NOTE: I've used these helper routines in many of my previous
tutorials so you may already have them someplace in your source.
If you already do have them, then you don't need them anymore.
Your compiler should warn you that you've already got these
functions previously defined..
Okay, add the
following text to the top of your g_weapons.c file.
------------------
START HERE ------------------------
//======================================================
// True if Ent is valid, has client, and edict_t inuse.
//======================================================
qboolean G_EntExists(edict_t *ent) {
return ((ent) && (ent->client) && (ent->inuse));
}
//======================================================
// True if ent is not DEAD or DEAD or DEAD (and BURIED!)
//======================================================
qboolean G_ClientNotDead(edict_t *ent) {
qboolean b1=ent->client->ps.pmove.pm_type!=PM_DEAD;
qboolean b2=ent->deadflag != DEAD_DEAD;
qboolean b3=ent->health > 0;
return (b3 || b2 || b1);
}
//======================================================
// True if ent is not DEAD and not just did a Respawn.
//======================================================
qboolean G_ClientInGame(edict_t *ent) {
if (!G_EntExists(ent)) return false;
if (!G_ClientNotDead(ent)) return false;
return (ent->client->respawn_time + 5.0 < level.time);
}
//======================================================
void G_Spawn_Explosion(int type, vec3_t start, vec3_t origin ) {
gi.WriteByte(svc_temp_entity);
gi.WriteByte(type);
gi.WritePosition(start);
gi.multicast(origin, MULTICAST_PVS);
}
===============================================================
Okay, we need to add some variables to your edict_s Structure
in your g_local.h file.. Note, you can substitute these edict_t
vars for other ones already present in the structure if you'd
like to save some memory. Just be sure to make all the right
substitutions if you do so..
moveinfo_t moveinfo;
monsterinfo_t monsterinfo;
------- ADD THESE
LINES HERE -----------
edict_t *vehicle; //
Monster 'Gladiator' Vehicle
edict_t *tranformer; // 'Gladiator' Vehicle's Rider..
qboolean is_transformed; // ent is transformed..
-----------------------------------------------
These are the vars which we'll be using globally in the code.
===============================================================
Open up your
g_cmds.c file and go near the bottom of your
ClientCommand() function and add the following as shown
by example..
---------- IF-ELSE
STATEMENTS --------
else if (Q_stricmp(cmd, "decoy") == 0 )
SP_Decoy(ent);
else if (Q_stricmp(cmd, "drone") == 0 )
Cmd_LaserDrone_f(ent);
else if (Q_stricmp(cmd, "teleport") == 0)
Cmd_Teleport_f(ent);
----------- ADD THESE LINES ------
else if (Q_stricmp(cmd, "transform") == 0 )
Cmd_Gladiator_f(ent);
-----------------------------------------
============================================================
Add this prototype
declaration to the top of you g_cmds.c
file:
void
Cmd_Gladiator_f(edict_t *ent);
===========================================================
We don't have to do
anything to the qboolean visible() function
because we've turn the client to SVF_NOCLIENT..
===========================================================
Find your Killed()
function in your g_combat.c file and
add the following lines as shown:
void Killed(......)
{
if (targ->health < -999)
targ->health = -999;
------------- ADD
THESE LINES RIGHT HERE ------------
if
(deathmatch->value)
// Was this the XTransformer which just got shot down?
if (Q_stricmp(targ->classname, "XTransformer")==0)
if (G_EntExists(attacker) && (attacker!=targ->transformer)) {
gi.centerprintf(attacker,"7 Frags for killing a Gladiator!\n");
attacker->client->resp.score += 7; }
-------------------------------------------------------------
This will award the
7 frags to the player who takes out your
Gladiator!!
============================================================
Find your ClientObituary() function and add this code at
the very top..
//
--------------------------------------------------------
// Are we in DM Mode?
if (deathmatch->value)
// Make sure both attacker and self still in game!
if ((G_EntExists(attacker)) && (G_EntExists(self)))
// Was the attacker the XTransformer?
if (Q_stricmp(attacker->classname, "XTransformer")==0)
// XTransformer's transformer still exists?
if (G_EntExists(attacker->transformer)) {
// Assign kills to transformer's score!!
gi.bprintf(PRINT_MEDIUM,"%s was nailed by %s's Gladiator\n",
self->client->pers.netname,
attacker->transformer->client->pers.netname);
attacker->transformer->client->resp.score += 1;
return; }
// --------------------------------------------------------
This will make sure
that the Gladiator's owner gets the frags
for its kills!
============================================================
Okay, now we need to
do some really interesting stuff..
Find your
ClientBeginServerFrame() function and make these
changes as indicated..
void
ClientBeginServerFrame(edict_t *ent)
{
gclient_t *client;
int buttonMask;
if
(level.intermissiontime)
return;
------------ ADD
THESE LINES RIGHT HERE -----------
// Is ent currently a 'Transformer' ?
if (ent->vehicle && ent->is_transformed) {
VectorCopy(ent->vehicle->s.origin, ent->s.origin);
VectorCopy(ent->vehicle->s.angles, ent->s.angles);
AngleVectors(ent->s.angles, NULL, NULL, up);
// Keep ent looking out Gladiator's eyes
VectorMA(ent->s.origin, 25, up, ent->s.origin);
ent->movetype=MOVETYPE_NOCLIP;
ent->svflags=SVF_NOCLIENT;
// No other movement..
return; }
------------------------------------------------------
This will make sure
that the ent moves with the Gladiator.
====================================================
====================================================
====================================================
======================================================================
Okay, now find your void gladiator_die() function in your
m_gladiator.c file and make this change..
void gladiator_die(edict_t *self, edict_t *inflictor, edict_t *attacker, int
damage, vec3_t point)
{
// check for gib
if (self->health <= self->gib_health)
{
------------ ADD THESE LINES HERE ------------
// Make ent no
longer 'Transformed';
self->transformer->vehicle=NULL;
self->transformer->is_transformed=false;
self->transformer->health=self->health;
self->transformer->movetype=MOVETYPE_WALK;
self->transformer->svflags &= ~SVF_NOCLIENT;
---------------------------------------------------
This turn off some
of the owner's special flags..
===========================================================
Now comes the easy part!!
Add all these new
routines to the bottom of your m_gladiator.c
file and you should be okay..
---------------------
START HERE ------------------
//======================================================
//================= GLADIATOR ==========================
//======================================================
//======================================================
void Spawn_Gladiator(edict_t *ent) {
edict_t *gladiator;
vec3_t torigin;
int temp;
G_Spawn_Explosion(TE_EXPLOSION2,
ent->s.origin, ent->s.origin);
VectorCopy(ent->s.origin,
torigin);
// Create basic
entity stuff.
gladiator=G_Spawn();
gladiator->classname = "XTransformer"; // Used for Killed()
gladiator->transformer=ent; // Link back to Owner.
VectorCopy(torigin, gladiator->s.origin);
gi.linkentity(gladiator);
//------------------------------
// Change some Global States
//------------------------------
skill->value=3;
// Toggle Advanced AI.
temp=deathmatch->value; // Temp storage..
deathmatch->value=0; // Must = 0 to bypass quick-exit in Monster Code
//------------------------------
// Activate the gladiator Entity
//------------------------------
SP_monster_gladiator(gladiator);
// Restore to
previous value.
deathmatch->value=temp;
// Reset some stuff
on this Holographic Image
gladiator->monsterinfo.aiflags &= AI_BRUTAL;
ent->is_transformed=true;
ent->vehicle=gladiator; // Link to this Vehicle.
}
//======================================================
void Cmd_Gladiator_f(edict_t *ent) {
// Don't allow
dead/respawning players to have this!
if (!G_ClientInGame(ent)) return;
// Already
transformed?
if (ent->is_transformed) return;
// Try to see if we
can Spawn the gladiator
if (ent->client->resp.score < 2){
gi.centerprintf(ent, "Gladiator costs 2 Frags!\n");
return; }
else {
ent->client->resp.score -= 2;
Spawn_Gladiator(ent); }
}
--------------------- STOP HERE -------------------
===============================================================
Lastly..
Remember to bind a
key in your Autoexec.cfg file as shown
by example below:
bind t
"transform"
That's it!! Now go KILL ALL THOSE BASTARDS!
Have Fun!!
philip
|