|
Title:
Finding FuncPlat Tops and Bottoms
Difficulty: Fairly Difficult
By: Maj.Bitch
Email: peblair@frontier.net
Date: 10-02-99
Note: Please give credit where credit is due.
======================================================
In furtherance of the pathing stuff, it is important to
be able to define the start and stop points (visible)
of any of the func_plats or buttons in the level. I've
put together the following functionality which accomplishes
this. What you end up with (when displaying the pos1 and
pos2 vectors) is a particle entity at the visible bottom
of the func plat and at the visible top of the func plat.
NOTE that buttons have pos1=pos2 and the particles are
displayed right outside the touching part if the button
entity.
Here is the source.
=========================================================
<c code>
int numfuncs=0;
typedef struct {
int type; // CONTENTS_BUTTON, CONTENTS_FUNC
vec3_t pos1; // location of TouchPlatCenter start
vec3_t pos2; // location of final plat end position
} func_t;
func_t *func;
#define CONTENTS_BUTTON 4
#define CONTENTS_FUNC 64
//========================================================
// Make a call to this from the top of ClientThink
//========================================================
void SplashFuncs(void) {
int i;
for (i=0;i<numfuncs;i++) {
G_Spawn_Splash(TE_LASER_SPARKS, 8, 0xd0d1d2d3, func[i].pos1, zvec, func[i].pos1);
if (func[i].type==CONTENTS_BUTTON) continue;
G_Spawn_Splash(TE_LASER_SPARKS, 8, 0xd0d1d2d3, func[i].pos2, zvec, func[i].pos2); }
}
//=====================================================
// Add all func_plats and func_buttons to func[] array
//=====================================================
void SetFuncTable(void) {
edict_t *ent;
int k=0;
numfuncs=0;
// How many func_t structs are we going to have to allocate?
for (ent=&g_edicts[0]; ent<&g_edicts[globals.num_edicts]; ent++)
if (ent && !ent->client && !ent->item && ent->touch)
numfuncs++;
// Allocate all the structs we'll need...
func=(func_t *)gi.TagMalloc(numfuncs*sizeof(func_t),TAG_LEVEL);
// Grab specific ents and calculate pos1 and pos1 for each one.
for (ent=&g_edicts[0]; ent<&g_edicts[globals.num_edicts]; ent++)
if (ent && !ent->client && !ent->item && ent->touch) {
VectorAdd(ent->absmin,ent->absmax,func[k].pos1);
VectorScale(func[k].pos1,0.5,func[k].pos1);
func[k].pos1[2]+=16; // Raise it up a bit
while (!(gi.pointcontents(func[k].pos1) & CONTENTS_SOLID))
func[k].pos1[2]-=4; // Work your way downward
func[k].pos1[2]+=20; // Now, reposition it up again
VectorCopy(func[k].pos1,func[k].pos2); // pos1=pos2 for buttons
func[k].type=(ent->use==button_use)?CONTENTSBUTTONCONTENTS_FUNC;
if (func[k].type==CONTENTS_FUNC)
func[k].pos2[2]+=abs(ent->enemy->absmax[2]-ent->enemy->absmin[2]);
k++; }
gi.dprintf("%d touch entities spawned\n",numfuncs);
}
</c code>
We want to be able to grab all of this information before any of the players
actually join the game. Make a call to SetFuncTable() at the very bottom
of your SpawnEntities() function and, immediately after all the entities are
spawned into the game upon startup, we'll determine which are the ones we
are interested in and grab them right away. A message will be displayed to
the
console as to the number of touch entities which have been found. Then we ADD
these new pos1 and pos2 node locations to our node[] array for A*..
The reason for the two
nodes is this: Say, for example, that the A* algorithm is
working its way merrily along on a lower level. It works its way over to the
node at bottom of the elevator platform (valid node). It adds this node to
the OPEN
array for later searching. When it searches from this node upward, the next
node
will be the one at the top of the func plat which it'll add for later
searching
because its valid. From the node at the top of the func plat it'll start
searching
from there!! This way, it can find valid paths UP and DOWN elevators! And it
can
colorcode the node as some kind of PAUSE action or FREEZE action so that the
bot
doesn't move while at this node location (bottom one) but moves when it gets
to
the top node so it can get off the elevator and continue to the next valid
node.
Maj.Bitch
|