
Quake DeveLS - Advanced Thinking
Author: Kieren
Johnstone a.k.a. -X'BuG-
Difficulty: Easy
Hi, it's me again...I
recently thought up a way of making Quake2 programming much easier! Using this
tutorial, we will be able to have two different "think" and
"nextthink" functions!
This means that, for example, you could have a rocket that dropped a grenade
every second, but exploded after 3 seconds!
Hey - that's a great idea! I'll show you the grenade rocket trick!
First, we need to implement the new think function. Go to g_local.h at
the very bottom of the file, and add this:
// add for advanced thinking: float nextthink2; void (*think2)(edict_t *self); // end of add}
Then we have to make it so that the game recognises this and runs think2
when the time is right. Open g_phys.c, and go to the function called
SV_RunThink. Replace it with this:
/*=============SV_RunThink Runs thinking code for this frame if necessary=============*/qboolean SV_RunThink (edict_t *ent){ float thinktime; float thinktime2; thinktime = ent->nextthink; if (thinktime <= 0) return true; if (thinktime > level.time+0.001) return true; ent->nextthink = 0; if (!ent->think) gi.error ("NULL ent->think"); ent->think (ent); // added for advanced thinking: thinktime2 = ent->nextthink2; if (thinktime2 <= 0) return true; if (thinktime2 > level.time+0.001) return true; ent->nextthink2 = 0; if (!ent->think2) gi.error ("NULL ent->think2"); ent->think2 (ent); // end of add return false;}
As I said, this basically checks if it's time to run the think2 function (i.e.
if the time is nextthink2).
Right, that's that done - now you can do whatever the hell you want with your
new think2 ideas! Now to explore my idea.
We want a rocket to drop a grenade every second, but explode after 3 seconds!
Let's go!
Open g_weapon.c and look for the fire_rocket function. Replace it
with this:
void fire_rocket (edict_t *self, vec3_t start, vec3_t dir, int damage, int speed, float damage_radius, int radius_damage){ edict_t *rocket; speed /= 2; // go slower rocket = G_Spawn(); VectorCopy (start, rocket->s.origin); VectorCopy (dir, rocket->movedir); vectoangles (dir, rocket->s.angles); VectorScale (dir, speed, rocket->velocity); rocket->movetype = MOVETYPE_FLYMISSILE; rocket->clipmask = MASK_SHOT; rocket->solid = SOLID_BBOX; rocket->s.effects |= EF_ROCKET; VectorClear (rocket->mins); VectorClear (rocket->maxs); rocket->s.modelindex = gi.modelindex ("models/objects/rocket/tris.md2"); rocket->owner = self; rocket->touch = rocket_touch; rocket->nextthink = level.time + 3; // changed to 3 rocket->think = G_FreeEdict; // added: rocket->nextthink2 = level.time + 1; // every second, rocket->think2 = rocket_drop_grenade; // drop a grenade // end of add rocket->dmg = damage; rocket->radius_dmg = radius_damage; rocket->dmg_radius = damage_radius; rocket->s.sound = gi.soundindex ("weapons/rockfly.wav"); rocket->classname = "rocket"; if (self->client) check_dodge (self, rocket->s.origin, dir, speed); gi.linkentity (rocket);}
And to
finish it off, we need a function to drop those grenades! Put it before
fire_rocket, or you'll have to prototype it (put void
rocket_drop_grenade(edict_t *ent) before fire_rocket).
Here it is:
void rocket_drop_grenade (edict_t *ent){ // new function to // drop a grenade from a rocket // // (similar to fire_grenade) // edict_t *grenade; grenade = G_Spawn(); VectorCopy (ent->s.origin,grenade->s.origin); grenade->s.origin[2] -= ent->maxs[2] + 1; grenade->velocity[2] += 20; VectorSet (grenade->avelocity, 300, 300, 300); grenade->movetype = MOVETYPE_BOUNCE; grenade->clipmask = MASK_SHOT; grenade->solid = SOLID_BBOX; grenade->s.effects |= EF_GRENADE; VectorClear (grenade->mins); VectorClear (grenade->maxs); grenade->s.modelindex = gi.modelindex ("models/objects/grenade2/tris.md2"); grenade->owner = ent->owner; grenade->touch = Grenade_Touch; grenade->nextthink = level.time + 1; grenade->think = Grenade_Explode; grenade->dmg = 30; grenade->dmg_radius = 200; grenade->classname = "hgrenade"; if (held) grenade->spawnflags = 3; else grenade->spawnflags = 1; grenade->s.sound = gi.soundindex("weapons/hgrenc1b.wav"); gi.sound (self, CHAN_WEAPON, gi.soundindex ("weapons/hgrent1a.wav"), 1, ATTN_NORM, 0); gi.linkentity (grenade);}
Tada! All done, it should work fine! If it doesn't please e-mail and tell me, I
don't like to give a bad impression! Although slightly unrealistic, the grenade
rocket launcher is a good example. Think of something good and maybe send it in
as a tutorial!
Tutorial by Kieren
Johnstone, author of forthcoming mod CLOT.
|
This site, and all
content and graphics displayed on it, |