4b825dc642cb6eb9a060e54bf8d69288fbee490494a6641b73026d662261604d7d192beae70b11dc
 
 
1
/*------------------------Patrick 13/12/96-----------------------------
 
 
2
  Source file for FAR AI alien module locations, as used by far alien
 
 
3
  behaviours....
 
 
4
  --------------------------------------------------------------------*/
 
 
5
 
 
 
6
#include "system.h"
 
 
7
#include "prototyp.h"
 
 
8
#include "stratdef.h"
 
 
9
#include "dynamics.h"
 
 
10
#include "pfarlocs.h"
 
 
11
#include <stdlib.h>
 
 
12
#include <assert.h>
 
 
13
 
 
 
14
/* external global variables used in this file */
 
 
15
extern int ModuleArraySize;
 
 
16
extern int memoryInitialisationFailure;
 
 
17
 
 
 
18
/* globals for this file */
 
 
19
FARENTRYPOINTSHEADER *FALLP_EntryPoints = NULL;
 
 
20
FARLOCATIONSHEADER *FALLP_AuxLocs = NULL;
 
 
21
 
 
 
22
int AIModuleArraySize = 0;
 
 
23
AIMODULE *AIModuleArray = NULL;
 
 
24
 
 
 
25
/* static globals for this file */
 
 
26
static FARVALIDATEDLOCATION *auxLocsGrid = NULL;
 
 
27
 
 
 
28
static int FL_TotalNumAuxLocs = 0;
 
 
29
static VECTORCH    *FL_AuxData = NULL;
 
 
30
 
 
 
31
/* a define for logging location data */
 
 
32
#define logFarLocData    0
 
 
33
#if logFarLocData
 
 
34
static FILE *logfile;
 
 
35
#endif
 
 
36
 
 
 
37
#define logFarLocPositions    0
 
 
38
#if logFarLocPositions
 
 
39
static FILE *logfile2;
 
 
40
#endif
 
 
41
 
 
 
42
/*------------------ Patrick 3/12/96 ----------------------
 
 
43
  This function determines whether an x/z position lies
 
 
44
  within the x/z projection of a polygon.
 
 
45
 
 
 
46
  NB is not entirely accurate for concave polygons.
 
 
47
  ---------------------------------------------------------*/
 
 
48
static int IsXZinPoly(VECTORCH* location, struct ColPolyTag *polygonData)
 
 
49
{
 
 
50
    int x = location->vx;
 
 
51
    int z = location->vz;
 
 
52
    int xa,za,xb,zb;
 
 
53
    int intersections = 0;
 
 
54
    int intersectMinz, intersectMaxz;
 
 
55
    int linesToTest;
 
 
56
    int nextLine;
 
 
57
 
 
 
58
    linesToTest = polygonData->NumberOfVertices;
 
 
59
 
 
 
60
    if(linesToTest == 3)
 
 
61
    {
 
 
62
        xa = polygonData->PolyPoint[2].vx;
 
 
63
        za = polygonData->PolyPoint[2].vz;
 
 
64
    }
 
 
65
    else
 
 
66
    {
 
 
67
        assert(linesToTest == 4);
 
 
68
        xa = polygonData->PolyPoint[3].vx;
 
 
69
        za = polygonData->PolyPoint[3].vz;
 
 
70
    }
 
 
71
 
 
 
72
    nextLine = 0;
 
 
73
 
 
 
74
    while(nextLine < linesToTest)
 
 
75
    {
 
 
76
        /* copy last first point to next last point (?) */
 
 
77
        xb = xa;
 
 
78
        zb = za;
 
 
79
 
 
 
80
        /* get next first point */
 
 
81
        xa = polygonData->PolyPoint[nextLine].vx;
 
 
82
        za = polygonData->PolyPoint[nextLine].vz;
 
 
83
 
 
 
84
        if(((x >= xb) && (x <= xa)) || ((x < xb) && (x >= xa)))
 
 
85
        {
 
 
86
              /* intesection ! */
 
 
87
            intersections++;
 
 
88
 
 
 
89
            if(!(intersections < 4))
 
 
90
                return 0;
 
 
91
 
 
 
92
            {
 
 
93
                int zPosn;
 
 
94
 
 
 
95
                if(xb == xa)
 
 
96
                    zPosn = za;
 
 
97
                else
 
 
98
                    zPosn = zb + WideMulNarrowDiv((za-zb),(x-xb),(xa-xb));
 
 
99
 
 
 
100
                if(intersections == 1)
 
 
101
                    intersectMinz = intersectMaxz = zPosn;
 
 
102
                else
 
 
103
                {
 
 
104
                    if(zPosn < intersectMinz)
 
 
105
                        intersectMinz = zPosn;
 
 
106
                    else if(zPosn > intersectMaxz)
 
 
107
                        intersectMaxz = zPosn;
 
 
108
                }
 
 
109
            }
 
 
110
        }
 
 
111
      nextLine++;
 
 
112
    }
 
 
113
 
 
 
114
    if(intersections == 0)
 
 
115
        return 0;
 
 
116
 
 
 
117
    if(intersections == 1)
 
 
118
        return (z == intersectMinz);    
 
 
119
    else 
 
 
120
        return ((z >= intersectMinz)&&(z <= intersectMaxz));
 
 
121
}
 
 
122
 
 
 
123
/*----------------------Patrick 1/12/96--------------------------
 
 
124
  Given an x/z position for the shape, this function returns a 
 
 
125
  height value, by examining upwards facing polygons....
 
 
126
  To validate the height, there must also be a downwards facing
 
 
127
  polgon above the upwards facing polygon (so that we know that
 
 
128
  the location iiiiis inside the shape): if there is no up &
 
 
129
  down polygon, the location is invalidated, and an error code
 
 
130
  returned (either no up poly, no down poly, no up-or-down poly)
 
 
131
 
 
 
132
  ----------------------------------------------------------------*/
 
 
133
 
 
 
134
static void GetFarLocHeight(FARVALIDATEDLOCATION *location, MODULE *thisModule)
 
 
135
{
 
 
136
    int heightOfUpPoly = thisModule->m_maxy; /* init to lowest module extent */
 
 
137
    int heightOfDownPoly = thisModule->m_miny; /* init to heighest module extent */
 
 
138
    int polyCounter    = SetupPolygonAccessFromShapeIndex(thisModule->m_mapptr->MapShape);
 
 
139
    int upPolyFound = 0;
 
 
140
    int downPolyFound = 0;
 
 
141
    struct ColPolyTag polygonData;
 
 
142
 
 
 
143
    /* loop through the item list, then ... */
 
 
144
    while(polyCounter > 0)
 
 
145
    {
 
 
146
        {
 
 
147
            int *itemPtr = *(ItemArrayPtr++);
 
 
148
            PolyheaderPtr = (POLYHEADER *) itemPtr;
 
 
149
        }
 
 
150
 
 
 
151
        GetPolygonVertices(&polygonData);
 
 
152
        GetPolygonNormal(&polygonData);
 
 
153
 
 
 
154
        /* first test if poly is vertical */
 
 
155
        if((polygonData.PolyNormal.vy > FAR_MIN_INCLINE)||(polygonData.PolyNormal.vy < -FAR_MIN_INCLINE))
 
 
156
        {
 
 
157
        int XZcontainment = IsXZinPoly(&(location->position), &polygonData);
 
 
158
 
 
 
159
            if(XZcontainment)
 
 
160
            {                
 
 
161
                if(polygonData.PolyNormal.vy > 0) /* downwards facing */
 
 
162
                {
 
 
163
                    downPolyFound++;
 
 
164
                    {
 
 
165
                        /* find height of this poly: height of lowest vertex */
 
 
166
                        int tmpHeight = polygonData.PolyPoint[0].vy;
 
 
167
 
 
 
168
                        if(polygonData.PolyPoint[1].vy > tmpHeight)
 
 
169
                            tmpHeight = polygonData.PolyPoint[1].vy;
 
 
170
 
 
 
171
                        if(polygonData.PolyPoint[2].vy > tmpHeight)
 
 
172
                            tmpHeight = polygonData.PolyPoint[2].vy;
 
 
173
 
 
 
174
                        if(polygonData.NumberOfVertices == 4)
 
 
175
                        {
 
 
176
                            if(polygonData.PolyPoint[3].vy > tmpHeight)
 
 
177
                                tmpHeight = polygonData.PolyPoint[2].vy;
 
 
178
                        }
 
 
179
 
 
 
180
                        /* record height of lowest downward facing poly */
 
 
181
                        if(tmpHeight > heightOfDownPoly)
 
 
182
                            heightOfDownPoly = tmpHeight;                        
 
 
183
                    }
 
 
184
                }
 
 
185
                else /* upwards facing */
 
 
186
                {
 
 
187
                    upPolyFound++;
 
 
188
                    {
 
 
189
                        /* find height of this poly: height of highest vertex */
 
 
190
                        int tmpHeight = polygonData.PolyPoint[0].vy;
 
 
191
 
 
 
192
                        if(polygonData.PolyPoint[1].vy < tmpHeight)
 
 
193
                                tmpHeight = polygonData.PolyPoint[1].vy;
 
 
194
 
 
 
195
                        if(polygonData.PolyPoint[2].vy < tmpHeight)
 
 
196
                                tmpHeight = polygonData.PolyPoint[2].vy;
 
 
197
 
 
 
198
                        if(polygonData.NumberOfVertices == 4)
 
 
199
                        {
 
 
200
                            if(polygonData.PolyPoint[3].vy < tmpHeight)
 
 
201
                                tmpHeight = polygonData.PolyPoint[2].vy;
 
 
202
                        }
 
 
203
 
 
 
204
                        /* record height of heighest upward facing poly */
 
 
205
                        if(tmpHeight < heightOfUpPoly)
 
 
206
                            heightOfUpPoly = tmpHeight;                        
 
 
207
                    }
 
 
208
                }
 
 
209
            }
 
 
210
        }
 
 
211
    polyCounter--;
 
 
212
    }
 
 
213
 
 
 
214
    /* if up & down polys exist check their heights:
 
 
215
    if there is not enough clearance bewteen the lowest down poly and the heighest up poly, 
 
 
216
    invalidate the location.*/
 
 
217
 
 
 
218
    if((upPolyFound != 0) && (downPolyFound != 0))
 
 
219
    {
 
 
220
        int minclearance = FAR_BB_HEIGHT;
 
 
221
        if(thisModule->m_flags & MODULEFLAG_AIRDUCT)
 
 
222
            minclearance >>= 1;
 
 
223
 
 
 
224
        if((heightOfUpPoly-heightOfDownPoly) >= minclearance)
 
 
225
        {
 
 
226
            //position the aux location slightly above the polygon
 
 
227
            location->position.vy = heightOfUpPoly - 10;
 
 
228
        }
 
 
229
        else
 
 
230
            location->valid = 0;
 
 
231
    }
 
 
232
    else
 
 
233
        location->valid = 0;
 
 
234
}
 
 
235
 
 
 
236
/*--------------------Patrick 4/12/96--------------------
 
 
237
  This function checks a potential location for impinging
 
 
238
  downward or sideways facing polygons (ie ceiling or floor).  
 
 
239
  This is done using a bounding box containment test.  If 
 
 
240
  the test fails, it invalidates the location.
 
 
241
  -------------------------------------------------------*/
 
 
242
 
 
 
243
static int farbbox_maxx;
 
 
244
static int farbbox_minx;
 
 
245
static int farbbox_maxy;
 
 
246
static int farbbox_miny;
 
 
247
static int farbbox_maxz;
 
 
248
static int farbbox_minz;
 
 
249
static struct ColPolyTag farbbox_polygonData;
 
 
250
 
 
 
251
/*--------------------Patrick 5/12/96----------------------------------
 
 
252
 This does a bounding box extent test for a polygon.
 
 
253
 NB returns false if the poly definitely isn't in the bbox, and returns 
 
 
254
 true if the poly is in the bbox, and for unresolved cases.
 
 
255
 ----------------------------------------------------------------------*/
 
 
256
static int FarBoxContainsPolygon()
 
 
257
{
 
 
258
    if(farbbox_polygonData.NumberOfVertices == 3)
 
 
259
    {
 
 
260
        if(    (farbbox_polygonData.PolyPoint[0].vy<=farbbox_miny)&&
 
 
261
            (farbbox_polygonData.PolyPoint[1].vy<=farbbox_miny)&&
 
 
262
            (farbbox_polygonData.PolyPoint[2].vy<=farbbox_miny))    return 0;
 
 
263
 
 
 
264
        if(    (farbbox_polygonData.PolyPoint[0].vx<=farbbox_minx)&&
 
 
265
            (farbbox_polygonData.PolyPoint[1].vx<=farbbox_minx)&&
 
 
266
            (farbbox_polygonData.PolyPoint[2].vx<=farbbox_minx))    return 0;    
 
 
267
 
 
 
268
        if( (farbbox_polygonData.PolyPoint[0].vz<=farbbox_minz)&&
 
 
269
            (farbbox_polygonData.PolyPoint[1].vz<=farbbox_minz)&&
 
 
270
            (farbbox_polygonData.PolyPoint[2].vz<=farbbox_minz))    return 0;
 
 
271
 
 
 
272
        if( (farbbox_polygonData.PolyPoint[0].vz>=farbbox_maxz)&&
 
 
273
            (farbbox_polygonData.PolyPoint[1].vz>=farbbox_maxz)&&
 
 
274
            (farbbox_polygonData.PolyPoint[2].vz>=farbbox_maxz))    return 0;
 
 
275
 
 
 
276
        if( (farbbox_polygonData.PolyPoint[0].vx>=farbbox_maxx)&&
 
 
277
            (farbbox_polygonData.PolyPoint[1].vx>=farbbox_maxx)&&
 
 
278
            (farbbox_polygonData.PolyPoint[2].vx>=farbbox_maxx))    return 0;
 
 
279
 
 
 
280
        if( (farbbox_polygonData.PolyPoint[0].vy>=farbbox_maxy)&&
 
 
281
            (farbbox_polygonData.PolyPoint[1].vy>=farbbox_maxy)&&
 
 
282
            (farbbox_polygonData.PolyPoint[2].vy>=farbbox_maxy))    return 0;
 
 
283
    }
 
 
284
    else
 
 
285
    {
 
 
286
        if(    (farbbox_polygonData.PolyPoint[0].vy<=farbbox_miny)&&
 
 
287
            (farbbox_polygonData.PolyPoint[1].vy<=farbbox_miny)&&
 
 
288
            (farbbox_polygonData.PolyPoint[2].vy<=farbbox_miny)&&
 
 
289
            (farbbox_polygonData.PolyPoint[3].vy<=farbbox_miny))    return 0;
 
 
290
 
 
 
291
        if(    (farbbox_polygonData.PolyPoint[0].vx<=farbbox_minx)&&
 
 
292
            (farbbox_polygonData.PolyPoint[1].vx<=farbbox_minx)&&
 
 
293
            (farbbox_polygonData.PolyPoint[2].vx<=farbbox_minx)&&
 
 
294
            (farbbox_polygonData.PolyPoint[3].vx<=farbbox_minx))    return 0;    
 
 
295
 
 
 
296
        if( (farbbox_polygonData.PolyPoint[0].vz<=farbbox_minz)&&
 
 
297
            (farbbox_polygonData.PolyPoint[1].vz<=farbbox_minz)&&
 
 
298
            (farbbox_polygonData.PolyPoint[2].vz<=farbbox_minz)&&
 
 
299
            (farbbox_polygonData.PolyPoint[3].vz<=farbbox_minz))    return 0;
 
 
300
 
 
 
301
        if( (farbbox_polygonData.PolyPoint[0].vz>=farbbox_maxz)&&
 
 
302
            (farbbox_polygonData.PolyPoint[1].vz>=farbbox_maxz)&&
 
 
303
            (farbbox_polygonData.PolyPoint[2].vz>=farbbox_maxz)&&
 
 
304
            (farbbox_polygonData.PolyPoint[3].vz>=farbbox_maxz))    return 0;
 
 
305
 
 
 
306
        if( (farbbox_polygonData.PolyPoint[0].vx>=farbbox_maxx)&&
 
 
307
            (farbbox_polygonData.PolyPoint[1].vx>=farbbox_maxx)&&
 
 
308
            (farbbox_polygonData.PolyPoint[2].vx>=farbbox_maxx)&&
 
 
309
            (farbbox_polygonData.PolyPoint[3].vx>=farbbox_maxx))    return 0;
 
 
310
 
 
 
311
        if( (farbbox_polygonData.PolyPoint[0].vy>=farbbox_maxy)&&
 
 
312
            (farbbox_polygonData.PolyPoint[1].vy>=farbbox_maxy)&&
 
 
313
            (farbbox_polygonData.PolyPoint[2].vy>=farbbox_maxy)&&
 
 
314
            (farbbox_polygonData.PolyPoint[3].vy>=farbbox_maxy))    return 0;
 
 
315
    }    
 
 
316
    return 1;
 
 
317
}
 
 
318
 
 
 
319
static void FarLocVolumeTest(FARVALIDATEDLOCATION *location, MODULE *thisModule)
 
 
320
{
 
 
321
    int polyCounter;
 
 
322
    int containmentFailure = 0;
 
 
323
 
 
 
324
    assert(location->valid);
 
 
325
 
 
 
326
    /* the location is provided as an x,y,z:
 
 
327
    the x and z indicate the centre, and the y indicates the bottom.
 
 
328
    translate these into bounding box extents.... */
 
 
329
 
 
 
330
    /* 10/7/97: this test has been modified: the bbox is moved up slightly, and any
 
 
331
    impinging ploygon invalidates the location */
 
 
332
 
 
 
333
    farbbox_maxx = location->position.vx + (FAR_BB_WIDTH>>1);
 
 
334
    farbbox_minx = location->position.vx - (FAR_BB_WIDTH>>1);
 
 
335
    farbbox_maxz = location->position.vz + (FAR_BB_WIDTH>>1);
 
 
336
    farbbox_minz = location->position.vz - (FAR_BB_WIDTH>>1);
 
 
337
    farbbox_maxy = location->position.vy - 10;
 
 
338
 
 
 
339
    /* patrick 4/7/97: a little adittion for airducts: npc should be crouched in them */
 
 
340
    if(thisModule->m_flags & MODULEFLAG_AIRDUCT)
 
 
341
        farbbox_miny = location->position.vy - (FAR_BB_HEIGHT >> 1) - 10;    
 
 
342
    else
 
 
343
        farbbox_miny = location->position.vy - FAR_BB_HEIGHT - 10;
 
 
344
 
 
 
345
    /* now just run through the polygons in the shape. If a polygon is 
 
 
346
    inside (actually, not definitely outside) the bbox, invalidate the location */        
 
 
347
 
 
 
348
     polyCounter = SetupPolygonAccessFromShapeIndex(thisModule->m_mapptr->MapShape);
 
 
349
 
 
 
350
    while((polyCounter > 0) && (!containmentFailure))
 
 
351
    {
 
 
352
        {
 
 
353
            int *itemPtr = *(ItemArrayPtr++);
 
 
354
            PolyheaderPtr = (POLYHEADER *) itemPtr;
 
 
355
        }
 
 
356
 
 
 
357
        GetPolygonVertices(&farbbox_polygonData);
 
 
358
        containmentFailure = FarBoxContainsPolygon();                    
 
 
359
        polyCounter--;
 
 
360
    }
 
 
361
 
 
 
362
    /* so, if there    has been a containmentFailure, invalidate the location */
 
 
363
    if(containmentFailure)
 
 
364
        location->valid = 0;
 
 
365
}
 
 
366
 
 
 
367
/*--------------------- Patrick 26/11/96 --------------------------
 
 
368
  This function attempts to construct a series of valid 
 
 
369
  auxilary locations inside the module (provided it has entry points)    
 
 
370
  -----------------------------------------------------------------*/
 
 
371
static void BuildFM_AuxilaryLocs(MODULE *thisModule)
 
 
372
{
 
 
373
    int gridStartX, gridStartZ, gridExtentX, gridExtentZ, XIndex, ZIndex;
 
 
374
    int NumLocsValid = 0;
 
 
375
    int NumLocsHeightFailed = 0;
 
 
376
    int NumLocsVolFailed = 0;
 
 
377
    int ThisModuleIndex;
 
 
378
    AIMODULE* aimodule = thisModule->m_aimodule;
 
 
379
 
 
 
380
    /* get the module index */
 
 
381
    assert(aimodule);
 
 
382
    ThisModuleIndex = aimodule->m_index;
 
 
383
    assert(ThisModuleIndex >= 0);
 
 
384
    assert(ThisModuleIndex < ModuleArraySize);    
 
 
385
 
 
 
386
    gridStartX = thisModule->m_minx + (FAR_BB_WIDTH>>1);
 
 
387
    gridStartZ = thisModule->m_minz + (FAR_BB_WIDTH>>1);
 
 
388
    gridExtentX = thisModule->m_maxx - thisModule->m_minx - FAR_BB_WIDTH;
 
 
389
    gridExtentZ = thisModule->m_maxz - thisModule->m_minz - FAR_BB_WIDTH;
 
 
390
 
 
 
391
    if(gridExtentX<=0 || gridExtentZ<=0)
 
 
392
    {
 
 
393
        //module is too narrow for auxilary locations
 
 
394
        return;
 
 
395
    }
 
 
396
 
 
 
397
    assert(gridStartX > thisModule->m_minx);
 
 
398
 
 
 
399
    /* step through each grid (index) location */
 
 
400
    for(XIndex = FAR_GRID_SIZE; XIndex > 0; XIndex--)
 
 
401
    {
 
 
402
        for(ZIndex = FAR_GRID_SIZE; ZIndex > 0; ZIndex--)
 
 
403
        {
 
 
404
            int locationsIndex = (XIndex-1)*FAR_GRID_SIZE + (ZIndex-1);
 
 
405
 
 
 
406
            auxLocsGrid[locationsIndex].position.vx = gridStartX + (gridExtentX*(XIndex-1))/(FAR_GRID_SIZE-1);
 
 
407
            auxLocsGrid[locationsIndex].position.vz = gridStartZ + (gridExtentZ*(ZIndex-1))/(FAR_GRID_SIZE-1);
 
 
408
            auxLocsGrid[locationsIndex].position.vy = 0;
 
 
409
            auxLocsGrid[locationsIndex].valid = 1; /* validated by default */
 
 
410
 
 
 
411
            /* get the floor height for this location.
 
 
412
            If no valid height is found, the location is set to
 
 
413
            minx,minz,miny, ie. outside of the grid, and abandoned */
 
 
414
 
 
 
415
            GetFarLocHeight(&auxLocsGrid[locationsIndex], thisModule);
 
 
416
 
 
 
417
            /* if there's a valid floor height, check the volume around the location
 
 
418
            for impinging polygons.  If volume is impinged, the location is set to 
 
 
419
            minx,minz,miny, ie. outside of the grid, and abandoned */
 
 
420
 
 
 
421
            if(auxLocsGrid[locationsIndex].valid)
 
 
422
            {
 
 
423
                FarLocVolumeTest(&auxLocsGrid[locationsIndex], thisModule); 
 
 
424
 
 
 
425
                if(auxLocsGrid[locationsIndex].valid)
 
 
426
                {
 
 
427
                    auxLocsGrid[locationsIndex].position.vx += thisModule->m_world.vx;
 
 
428
                    auxLocsGrid[locationsIndex].position.vy += thisModule->m_world.vy;
 
 
429
                    auxLocsGrid[locationsIndex].position.vz += thisModule->m_world.vz;
 
 
430
 
 
 
431
                    auxLocsGrid[locationsIndex].position.vx -= aimodule->m_world.vx;
 
 
432
                    auxLocsGrid[locationsIndex].position.vy -= aimodule->m_world.vy;
 
 
433
                    auxLocsGrid[locationsIndex].position.vz -= aimodule->m_world.vz;
 
 
434
 
 
 
435
                    NumLocsValid++;
 
 
436
                }
 
 
437
                else
 
 
438
                {
 
 
439
                    NumLocsVolFailed++;
 
 
440
                }
 
 
441
            }
 
 
442
            else
 
 
443
                NumLocsHeightFailed++;
 
 
444
        }
 
 
445
    }
 
 
446
 
 
 
447
    #if logFarLocData
 
 
448
    fprintf(logfile, "Num valid locs: %d \n", NumLocsValid);
 
 
449
    fprintf(logfile, "Num Height failed: %d \n", NumLocsHeightFailed);
 
 
450
    fprintf(logfile, "Num Vol failed: %d \n \n", NumLocsVolFailed);
 
 
451
    #endif
 
 
452
 
 
 
453
    /* now have a full list of locations.... 
 
 
454
    Those that are zero are invalid: hopefully some have survived */
 
 
455
    assert((NumLocsHeightFailed+NumLocsVolFailed+NumLocsValid) == (FAR_GRID_SIZE*FAR_GRID_SIZE));
 
 
456
 
 
 
457
    /* If there are any valid locations remaining, store them in the locations list */
 
 
458
    if(NumLocsValid > 0) 
 
 
459
    {
 
 
460
        /* Build a final and definitive list of valid locations for the module:
 
 
461
        look at the number of valid locations. If there are more than the maximum 
 
 
462
        number, take a reasonably distributed sample. Otherwise just put them all in.
 
 
463
 
 
 
464
        NB this wil be a list of Local Space coordinates.
 
 
465
        */               
 
 
466
 
 
 
467
        if(NumLocsValid > FAR_MAX_LOCS) 
 
 
468
        {
 
 
469
            VECTORCH *destinationPtr;
 
 
470
            int locationsIndex = 0;
 
 
471
 
 
 
472
            int numTaken = 0;
 
 
473
            int numFound = 0;
 
 
474
            int nextToTake = 0; 
 
 
475
 
 
 
476
            /* fill out the header (space is preallocated) */
 
 
477
            destinationPtr = &FALLP_AuxLocs[ThisModuleIndex].locationsList[FALLP_AuxLocs[ThisModuleIndex].numLocations];
 
 
478
            FALLP_AuxLocs[ThisModuleIndex].numLocations += FAR_MAX_LOCS;
 
 
479
 
 
 
480
            nextToTake = NumLocsValid / FAR_MAX_LOCS;                    
 
 
481
 
 
 
482
            while(numTaken < FAR_MAX_LOCS)
 
 
483
            {
 
 
484
                assert(nextToTake <= NumLocsValid);
 
 
485
                assert(locationsIndex < (FAR_GRID_SIZE*FAR_GRID_SIZE));            
 
 
486
 
 
 
487
                while(auxLocsGrid[locationsIndex].valid == 0)
 
 
488
                    locationsIndex++;
 
 
489
 
 
 
490
                assert(locationsIndex < (FAR_GRID_SIZE*FAR_GRID_SIZE));            
 
 
491
                numFound++;
 
 
492
                assert(numFound <= NumLocsValid);
 
 
493
 
 
 
494
                if(numFound == nextToTake)
 
 
495
                {
 
 
496
                    *destinationPtr++ = auxLocsGrid[locationsIndex].position;
 
 
497
                    numTaken++;
 
 
498
                    /* calc index of the next one to take */
 
 
499
                    nextToTake = ((numTaken + 1) * NumLocsValid) / FAR_MAX_LOCS;
 
 
500
                }
 
 
501
 
 
 
502
            /* move to next location */
 
 
503
            locationsIndex++;
 
 
504
            }
 
 
505
        }
 
 
506
        else
 
 
507
        {    
 
 
508
            VECTORCH *destinationPtr;
 
 
509
            int locationsIndex;
 
 
510
            int checkCount = 0; 
 
 
511
 
 
 
512
            /* fill out the header (space is preallocated) */
 
 
513
            destinationPtr = &FALLP_AuxLocs[ThisModuleIndex].locationsList[FALLP_AuxLocs[ThisModuleIndex].numLocations];
 
 
514
            FALLP_AuxLocs[ThisModuleIndex].numLocations += NumLocsValid;
 
 
515
 
 
 
516
            /* fill up the list with what we've got */
 
 
517
            locationsIndex = (FAR_GRID_SIZE*FAR_GRID_SIZE) - 1;
 
 
518
 
 
 
519
            do
 
 
520
            {
 
 
521
                if(auxLocsGrid[locationsIndex].valid)
 
 
522
                {
 
 
523
                    /* found a valid location: copy it into the list */
 
 
524
                    *(destinationPtr++) = auxLocsGrid[locationsIndex].position;
 
 
525
                    checkCount++;
 
 
526
                }            
 
 
527
 
 
 
528
            } while(locationsIndex--);
 
 
529
 
 
 
530
            assert(checkCount == NumLocsValid);
 
 
531
        }
 
 
532
 
 
 
533
        #if logFarLocData
 
 
534
        {
 
 
535
            /* log the final list */
 
 
536
            VECTORCH *tmpPtr;
 
 
537
            int tmpCounter;
 
 
538
            fprintf(logfile, "Locations list: \n");
 
 
539
 
 
 
540
            tmpCounter = FALLP_AuxLocs[ThisModuleIndex].numLocations;
 
 
541
            tmpPtr = FALLP_AuxLocs[ThisModuleIndex].locationsList;
 
 
542
 
 
 
543
            while(tmpCounter > 0)
 
 
544
            {
 
 
545
                fprintf(logfile, "%d %d %d \n", tmpPtr->vx, tmpPtr->vz, tmpPtr->vy);
 
 
546
                tmpPtr++;
 
 
547
                tmpCounter--;    
 
 
548
            }
 
 
549
 
 
 
550
            fprintf(logfile,"\n");
 
 
551
 
 
 
552
        }
 
 
553
        #endif
 
 
554
    }
 
 
555
    #if logFarLocData
 
 
556
    else
 
 
557
    {
 
 
558
        /* No valid locations */
 
 
559
        {
 
 
560
            /* log an error */
 
 
561
            fprintf(logfile,"All auxilary locations FAILED \n");
 
 
562
        }
 
 
563
    }                                    
 
 
564
    #endif    
 
 
565
}
 
 
566
 
 
 
567
/*-----------------------Patrick 20/12/96---------------------------
 
 
568
Returns TRUE if a module is a physical part of the environment,
 
 
569
ie is not infinite or a terminator, etc...
 
 
570
-------------------------------------------------------------------*/
 
 
571
int ModuleIsPhysical(MODULE* target)
 
 
572
{
 
 
573
    if(target->m_flags & m_flag_infinite)
 
 
574
        return 0;
 
 
575
 
 
 
576
    return !target->end_module;
 
 
577
}
 
 
578
 
 
 
579
int AIModuleIsPhysical(AIMODULE* target)
 
 
580
{
 
 
581
    return (NULL != target) ? (target->m_module_ptrs != NULL) : 0;
 
 
582
}
 
 
583
 
 
 
584
/*-----------------------Patrick 20/12/96---------------------------
 
 
585
Takes 2 modules, and returns TRUE if the centre of the target module
 
 
586
is within the bounding box of the source;
 
 
587
-------------------------------------------------------------------*/
 
 
588
int ModuleInModule(MODULE* source, MODULE* target)
 
 
589
{
 
 
590
    if(target->m_world.vx < (source->m_world.vx + source->m_minx)) return 0;
 
 
591
    if(target->m_world.vx > (source->m_world.vx + source->m_maxx)) return 0;
 
 
592
 
 
 
593
    if(target->m_world.vy < (source->m_world.vy + source->m_miny)) return 0;
 
 
594
    if(target->m_world.vy > (source->m_world.vy + source->m_maxy)) return 0;
 
 
595
 
 
 
596
    if(target->m_world.vz < (source->m_world.vz + source->m_minz)) return 0;
 
 
597
    if(target->m_world.vz > (source->m_world.vz + source->m_maxz)) return 0;
 
 
598
 
 
 
599
return 1;
 
 
600
}
 
 
601
 
 
 
602
/*-----------------------Patrick 20/12/96---------------------------
 
 
603
Returns the number of entries in a given module's adjacency list
 
 
604
If there is no adjacency list, return 0.
 
 
605
-------------------------------------------------------------------*/
 
 
606
int NumAdjacentModules(AIMODULE* target)
 
 
607
{
 
 
608
    AIMODULE **AdjAIModulePtr = (target->m_link_ptrs);
 
 
609
    int counter = 0;
 
 
610
 
 
 
611
    if(AdjAIModulePtr)    
 
 
612
    {
 
 
613
        while(*AdjAIModulePtr)
 
 
614
        {
 
 
615
            counter++;
 
 
616
            AdjAIModulePtr++;
 
 
617
        }
 
 
618
    }
 
 
619
    else
 
 
620
        return 0;
 
 
621
 
 
 
622
return counter;
 
 
623
}
 
 
624
 
 
 
625
 
 
 
626
/* allocates and initialises primitive data areas */
 
 
627
static void InitFarLocDataAreas(MODULE **moduleList, int numModules)
 
 
628
{
 
 
629
    int moduleCounter;
 
 
630
 
 
 
631
    /* first, the lists of data headers */    
 
 
632
    assert(numModules > 0);
 
 
633
    FALLP_AuxLocs = malloc(numModules*sizeof(FARLOCATIONSHEADER));
 
 
634
 
 
 
635
    if(!FALLP_AuxLocs) 
 
 
636
    {
 
 
637
        memoryInitialisationFailure = 1;
 
 
638
        return;
 
 
639
    }
 
 
640
 
 
 
641
    FL_TotalNumAuxLocs = 0;
 
 
642
    FL_AuxData = NULL;
 
 
643
 
 
 
644
    /* work out the number of adjacent modules/auxilary locations for each module, and add them up */
 
 
645
 
 
 
646
    for(moduleCounter=0; moduleCounter < numModules; moduleCounter++)
 
 
647
    {
 
 
648
        int thisModuleIndex;
 
 
649
        MODULE *thisModule = moduleList[moduleCounter]; 
 
 
650
 
 
 
651
        assert(thisModule);
 
 
652
        thisModuleIndex = thisModule->m_index;
 
 
653
        assert(thisModuleIndex >= 0);
 
 
654
        assert(thisModuleIndex < ModuleArraySize);
 
 
655
 
 
 
656
        if(ModuleIsPhysical(thisModule))
 
 
657
        {
 
 
658
            FL_TotalNumAuxLocs += FAR_MAX_LOCS;
 
 
659
        }    
 
 
660
    }
 
 
661
 
 
 
662
    /* allocate base data areas */
 
 
663
    assert(FL_TotalNumAuxLocs > 0);
 
 
664
    FL_AuxData = malloc(FL_TotalNumAuxLocs * sizeof(VECTORCH));;
 
 
665
 
 
 
666
    if(!FL_AuxData) 
 
 
667
    {
 
 
668
        memoryInitialisationFailure = 1;
 
 
669
        return;
 
 
670
    }
 
 
671
 
 
 
672
    /* init header lists */
 
 
673
    {
 
 
674
        VECTORCH *auxDataPtr = FL_AuxData;
 
 
675
 
 
 
676
        for(moduleCounter=0; moduleCounter < AIModuleArraySize; moduleCounter++)
 
 
677
        {
 
 
678
            AIMODULE* thisAIModule = &AIModuleArray[moduleCounter]; 
 
 
679
            int thisModuleIndex = thisAIModule->m_index;
 
 
680
            /* NB these pointers and indexes have been validated above */
 
 
681
 
 
 
682
            FALLP_AuxLocs[thisModuleIndex].numLocations = 0;
 
 
683
            FALLP_AuxLocs[thisModuleIndex].locationsList = NULL;
 
 
684
 
 
 
685
            {
 
 
686
                MODULE** modulearray = thisAIModule->m_module_ptrs;
 
 
687
 
 
 
688
                if(modulearray)
 
 
689
                {
 
 
690
                    FALLP_AuxLocs[thisModuleIndex].locationsList = auxDataPtr;
 
 
691
 
 
 
692
                    while(*modulearray)
 
 
693
                    {
 
 
694
                        modulearray++;
 
 
695
                        auxDataPtr += FAR_MAX_LOCS;
 
 
696
                    }
 
 
697
                }
 
 
698
            }
 
 
699
        }
 
 
700
 
 
 
701
        /* we can now validate this process... */
 
 
702
        assert(auxDataPtr == (FL_AuxData+FL_TotalNumAuxLocs));    
 
 
703
    }
 
 
704
}
 
 
705
 
 
 
706
/*----------------------Patrick 16/12/96------------------------
 
 
707
  This function builds a list of entry points and auxilary
 
 
708
  locations for    each module.
 
 
709
 
 
 
710
  NB this cannot be called until the module system has been 
 
 
711
  initialised for this environment.
 
 
712
----------------------------------------------------------------*/
 
 
713
 
 
 
714
void BuildFarModuleLocs()
 
 
715
{
 
 
716
    extern SCENEMODULE MainScene;
 
 
717
    /* now get a pointer to the list of modules in this environment. */ 
 
 
718
    int moduleCounter;
 
 
719
 
 
 
720
    assert(ModuleArraySize);
 
 
721
 
 
 
722
    #if logFarLocData
 
 
723
    logfile = fopen("E:/3DC/FARLOCS.TXT","w");
 
 
724
    fprintf(logfile, "MODULE FAR LOCATIONS DATA \n");
 
 
725
    fprintf(logfile, "LevelName: %s \n", LevelName);
 
 
726
    fprintf(logfile, "************************* \n");
 
 
727
    fprintf(logfile, "number of modules: %d \n", ModuleArraySize);
 
 
728
    fprintf(logfile, "grid size: %d \n", FAR_GRID_SIZE);
 
 
729
    fprintf(logfile, "max locs stored per module: %d \n \n", FAR_MAX_LOCS);
 
 
730
    fprintf(logfile, "alien box height: %d \n", FAR_BB_HEIGHT);
 
 
731
    fprintf(logfile, "alien box width: %d \n", FAR_BB_WIDTH);
 
 
732
    fprintf(logfile, "************************* \n \n");    
 
 
733
    #endif
 
 
734
 
 
 
735
    /* allocate some temporary work spaces..*/
 
 
736
    auxLocsGrid = malloc(FAR_GRID_SIZE*FAR_GRID_SIZE*sizeof(FARVALIDATEDLOCATION));
 
 
737
 
 
 
738
    if(!auxLocsGrid) 
 
 
739
    {
 
 
740
        memoryInitialisationFailure = 1;
 
 
741
        return;
 
 
742
    }
 
 
743
 
 
 
744
    /* Initialise the entry point list and auxilary location list.
 
 
745
    NB entry points are are pre-allocated, since they are evaluated in pairs.*/
 
 
746
    InitFarLocDataAreas(MainScene.sm_marray, ModuleArraySize);
 
 
747
 
 
 
748
    #if logFarLocData
 
 
749
    fprintf(logfile, "********************************* \n");
 
 
750
    fprintf(logfile, "STARTING ENTRY POINTS.... \n");
 
 
751
    fprintf(logfile, "********************************* \n \n");
 
 
752
    #endif
 
 
753
 
 
 
754
    /* Now go through the module list, and calculate entry points. This step should
 
 
755
    be done before auxilary locations, to be absolutely sure everything works out */
 
 
756
 
 
 
757
    #if logFarLocData
 
 
758
    fprintf(logfile, "********************************* \n");
 
 
759
    fprintf(logfile, "STARTING AUXILARY LOCATIONS.... \n");
 
 
760
    fprintf(logfile, "********************************* \n \n");
 
 
761
    #endif
 
 
762
 
 
 
763
    /* now go thro' each module calculating auxilary locations */
 
 
764
    for(moduleCounter = 0; moduleCounter < ModuleArraySize; moduleCounter++)
 
 
765
    {
 
 
766
        int ThisModuleIndex;    
 
 
767
        MODULE *thisModule = MainScene.sm_marray[moduleCounter]; 
 
 
768
 
 
 
769
         /* get a pointer to the next module, and it's index */
 
 
770
        assert(thisModule);
 
 
771
        ThisModuleIndex = thisModule->m_index;
 
 
772
        assert(ThisModuleIndex >= 0);
 
 
773
        assert(ThisModuleIndex < ModuleArraySize);
 
 
774
 
 
 
775
        #if logFarLocData
 
 
776
        fprintf(logfile, "********************************* \n");
 
 
777
        fprintf(logfile, "Module Index: %d \n", ThisModuleIndex);
 
 
778
        fprintf(logfile, "Module X range: %d %d \n", thisModule->m_minx, thisModule->m_maxx);
 
 
779
        fprintf(logfile, "Module Z range: %d %d \n \n", thisModule->m_minz, thisModule->m_maxz);
 
 
780
        #endif
 
 
781
 
 
 
782
        /* check for entry points into this module if there    aren't any,
 
 
783
        don't bother with auxilary locations */
 
 
784
 
 
 
785
        if(thisModule->m_aimodule)
 
 
786
            BuildFM_AuxilaryLocs(thisModule);
 
 
787
        /*
 
 
788
        else
 
 
789
        {    
 
 
790
            #if logFarLocData
 
 
791
            fprintf(logfile, "NO AUXILARY LOCS COMPUTED: NO EPS \n \n");
 
 
792
            #endif
 
 
793
        } 
 
 
794
        */ 
 
 
795
    }
 
 
796
 
 
 
797
    /* deallocate the temporary work spaces */
 
 
798
    if (auxLocsGrid)
 
 
799
        free(auxLocsGrid);
 
 
800
 
 
 
801
    #if logFarLocData
 
 
802
    fprintf(logfile, "************************************* \n");
 
 
803
    fprintf(logfile, "FINISHED ! \n");
 
 
804
    //fprintf(logfile, "NUM INFINITE MODULES/TERMINATORS: %d \n", numInfiniteModules);
 
 
805
    fprintf(logfile, "************************************* \n");
 
 
806
    fclose(logfile);
 
 
807
    #endif
 
 
808
 
 
 
809
    #if logFarLocPositions && 0 //this log will need to updated for the ai modules.
 
 
810
    logfile2 = fopen("D:/PATRICK/FARLOCS2.TXT","w");
 
 
811
    fprintf(logfile2, "MODULE EPs AND AUXILARY LOCATIONS \n");
 
 
812
    fprintf(logfile2, "LeveName: %s \n", LevelName);
 
 
813
    fprintf(logfile2, "************************* \n \n");
 
 
814
 
 
 
815
    for(moduleCounter = 0; moduleCounter < ModuleArraySize; moduleCounter++)
 
 
816
    {
 
 
817
        int i;
 
 
818
        fprintf(logfile2, "MODULE INDEX: %d \n",moduleCounter);
 
 
819
        fprintf(logfile2, "  EPs: \n");
 
 
820
 
 
 
821
        for(i=0; i < FALLP_EntryPoints[moduleCounter].numEntryPoints; i++)
 
 
822
        {
 
 
823
            VECTORCH posn = (FALLP_EntryPoints[moduleCounter].entryPointsList)[i].position;
 
 
824
            int index = (FALLP_EntryPoints[moduleCounter].entryPointsList)[i].donorIndex; 
 
 
825
            fprintf(logfile2, "  %d %d %d FROM %d \n", posn.vx, posn.vy, posn.vz, index);
 
 
826
        }
 
 
827
 
 
 
828
        fprintf(logfile2, "  AUX: \n");
 
 
829
 
 
 
830
        for(i=0; i < FALLP_AuxLocs[moduleCounter].numLocations; i++)
 
 
831
        {
 
 
832
            VECTORCH posn = (FALLP_AuxLocs[moduleCounter].locationsList)[i];
 
 
833
            fprintf(logfile2, "  %d %d %d \n", posn.vx, posn.vy, posn.vz);
 
 
834
        }
 
 
835
        fprintf(logfile2, "\n");
 
 
836
    }
 
 
837
    fprintf(logfile2, "************************* \n");
 
 
838
    fprintf(logfile2, "END \n ");
 
 
839
    fclose(logfile2);
 
 
840
    #endif
 
 
841
}
 
 
842
 
 
 
843
/*-----------------------Patrick 28/11/96---------------------------
 
 
844
This function deallocates the location lists for each module,
 
 
845
and must be called at some point before the environment re-load
 
 
846
-------------------------------------------------------------------*/
 
 
847
void KillFarModuleLocs()
 
 
848
{    
 
 
849
    /* don't do this for a net game */
 
 
850
    //in fact do do it in net game
 
 
851
    //if(AvP.Network != I_No_Network)    return;
 
 
852
 
 
 
853
    assert(ModuleArraySize);
 
 
854
    assert(AIModuleArraySize);
 
 
855
    assert(FALLP_EntryPoints);
 
 
856
    assert(FALLP_AuxLocs);
 
 
857
    assert(FL_TotalNumAuxLocs>0);
 
 
858
    assert(FL_AuxData);
 
 
859
 
 
 
860
    /* deallocate the base data area in one go, and re-init globals */
 
 
861
    if (FL_AuxData)
 
 
862
        free(FL_AuxData);
 
 
863
 
 
 
864
    FL_TotalNumAuxLocs = 0;
 
 
865
    FL_AuxData = NULL;
 
 
866
 
 
 
867
    /* deallocate the list headers, and re-init globals */
 
 
868
    if (FALLP_AuxLocs)
 
 
869
        free(FALLP_AuxLocs);
 
 
870
 
 
 
871
    FALLP_AuxLocs = NULL;
 
 
872
 
 
 
873
    if (FALLP_EntryPoints) 
 
 
874
    {
 
 
875
        int i = 0;
 
 
876
        for(; i < AIModuleArraySize; i++)
 
 
877
        {
 
 
878
            if(FALLP_EntryPoints[i].entryPointsList)
 
 
879
            {
 
 
880
                free(FALLP_EntryPoints[i].entryPointsList);
 
 
881
            }
 
 
882
        }
 
 
883
 
 
 
884
    free(FALLP_EntryPoints);
 
 
885
    }
 
 
886
 
 
 
887
    FALLP_EntryPoints = NULL;
 
 
888
}
 
 
889
 
 
 
890
/*-----------------------Patrick 20/12/96---------------------------
 
 
891
THE FOLLOWING ARE SOME GENERIC FUNCTIONS FOR ANALYSING MODULE
 
 
892
STATES. THEY MAY BE USED IN ANY SOURCE FILE.
 
 
893
-------------------------------------------------------------------*/
 
 
894
 
 
 
895
/*-----------------------Patrick 20/12/96---------------------------
 
 
896
This function takes a module and returns whether it is a door,
 
 
897
and if so, what kind of door it is from an alien perspective.
 
 
898
-------------------------------------------------------------------*/
 
 
899
MODULEDOORTYPE ModuleIsADoor(MODULE* target)
 
 
900
{
 
 
901
    if((target->m_sbptr) && (target->m_sbptr->type == I_BehaviourProximityDoor))
 
 
902
        return MDT_ProxDoor;
 
 
903
 
 
 
904
    if((target->m_sbptr) && (target->m_sbptr->type == I_BehaviourLiftDoor))    
 
 
905
        return MDT_LiftDoor;
 
 
906
 
 
 
907
    if((target->m_sbptr) && (target->m_sbptr->type == I_BehaviourSwitchDoor))    
 
 
908
        return MDT_SecurityDoor;
 
 
909
 
 
 
910
return MDT_NotADoor;
 
 
911
}
 
 
912
 
 
 
913
MODULEDOORTYPE AIModuleIsADoor(AIMODULE* target)
 
 
914
{
 
 
915
    /* A bit rough and ready at this point. */
 
 
916
    MODULE **renderModule = target->m_module_ptrs;
 
 
917
    assert(target->m_module_ptrs);
 
 
918
 
 
 
919
    while ((*renderModule) != NULL)
 
 
920
    {
 
 
921
        if((*renderModule)->m_sbptr)
 
 
922
        {
 
 
923
            switch((*renderModule)->m_sbptr->type)
 
 
924
            {
 
 
925
                case I_BehaviourProximityDoor:
 
 
926
                    return MDT_ProxDoor;
 
 
927
                case I_BehaviourLiftDoor:
 
 
928
                    return MDT_LiftDoor;
 
 
929
                case I_BehaviourSwitchDoor:
 
 
930
                    return MDT_SecurityDoor;
 
 
931
                default:
 
 
932
                break;
 
 
933
            }
 
 
934
        }
 
 
935
 
 
 
936
        renderModule++;
 
 
937
    }
 
 
938
 
 
 
939
return MDT_NotADoor;
 
 
940
}
 
 
941
/*-----------------------Patrick 20/12/96---------------------------
 
 
942
Returns a pointer to an entry point in thisModule from fromModule,
 
 
943
or 0 if there isn't one.
 
 
944
-------------------------------------------------------------------*/
 
 
945
FARENTRYPOINT *GetModuleEP(MODULE* thisModule, MODULE*fromModule)
 
 
946
{
 
 
947
    FARENTRYPOINT *thisEp = NULL;
 
 
948
    int tmIndex = fromModule->m_index;
 
 
949
    int numEps = FALLP_EntryPoints[thisModule->m_index].numEntryPoints;
 
 
950
    FARENTRYPOINT *epList = FALLP_EntryPoints[thisModule->m_index].entryPointsList;
 
 
951
 
 
 
952
    while((numEps > 0) && (thisEp == NULL) )
 
 
953
    {
 
 
954
        if(epList->donorIndex == tmIndex)
 
 
955
            thisEp = epList;
 
 
956
 
 
 
957
    epList++;
 
 
958
    numEps--;
 
 
959
    }
 
 
960
 
 
 
961
return thisEp;
 
 
962
}
 
 
963
 
 
 
964
FARENTRYPOINT *GetAIModuleEP(AIMODULE* thisModule, AIMODULE*fromModule)
 
 
965
{
 
 
966
    FARENTRYPOINT *thisEp = NULL;
 
 
967
    int tmIndex = fromModule->m_index;
 
 
968
    int numEps = FALLP_EntryPoints[thisModule->m_index].numEntryPoints;
 
 
969
    FARENTRYPOINT *epList = FALLP_EntryPoints[thisModule->m_index].entryPointsList;
 
 
970
 
 
 
971
    while((numEps > 0) && (thisEp == NULL))
 
 
972
    {
 
 
973
        if(epList->donorIndex == tmIndex)
 
 
974
            thisEp = epList;
 
 
975
    epList++;
 
 
976
    numEps--;
 
 
977
    }
 
 
978
 
 
 
979
return thisEp;
 
 
980
}