| | 1 | /*------------------------Patrick 14/1/97----------------------------- |
| | 2 | This source file contains all the functions for the object visibility |
| | 3 | management system (which controls visibility for aliens, objects, |
| | 4 | pickups, autoguns, etc....) |
| | 5 | It also contains initialisation and behaviour functions for |
| | 6 | inanimate objects (like chairs, weapons, etc...). |
| | 7 | --------------------------------------------------------------------*/ |
| | 8 | #include <string.h> |
| | 9 | #include <stdlib.h> |
| | 10 | #include <stdio.h> |
| | 11 | #include <assert.h> |
| | 12 | #include "system.h" |
| | 13 | #include "stratdef.h" |
| | 14 | #include "bh_types.h" |
| | 15 | #include "npc_alien.h" |
| | 16 | #include "npc_xenoborg.h" |
| | 17 | #include "npc_queen.h" |
| | 18 | #include "npc_marine.h" |
| | 19 | #include "npc_facehugger.h" |
| | 20 | #include "debris.h" |
| | 21 | #include "placedhierarchy.h" |
| | 22 | #include "lighting.h" |
| | 23 | #include "npc_dummy.h" |
| | 24 | #include "platformlift.h" |
| | 25 | #include "bh_light.h" |
| | 26 | #include "weapons.h" |
| | 27 | #include "npc_sentrygun.h" |
| | 28 | #include "corpse.h" |
| | 29 | #include "pfarlocs.h" |
| | 30 | #include "pldghost.h" |
| | 31 | #include "generator.h" |
| | 32 | |
| | 33 | size_t ModuleArraySize = 0; |
| | 34 | |
| | 35 | extern int GlobalFrameCounter; |
| | 36 | extern SCENEMODULE MainScene; |
| | 37 | |
| | 38 | extern SECTION * GetNamedHierarchyFromLibrary(const char * rif_name, const char * hier_name); |
| | 39 | |
| | 40 | /* this is a default map used in visibility management |
| | 41 | NB If you use this, you MUST set the shapeIndex field appropriately*/ |
| | 42 | |
| | 43 | #define ModuleFromPositionTolerance 50 |
| | 44 | |
| | 45 | static int WorldPointIsInModule_WithTolerance(MODULE* thisModule, VECTORCH* thisPoint) |
| | 46 | { |
| | 47 | VECTORCH localpoint = *thisPoint; |
| | 48 | localpoint.vx -= thisModule->m_world.vx; |
| | 49 | localpoint.vy -= thisModule->m_world.vy; |
| | 50 | localpoint.vz -= thisModule->m_world.vz; |
| | 51 | |
| | 52 | return |
| | 53 | ( |
| | 54 | (localpoint.vx <= thisModule->m_maxx + ModuleFromPositionTolerance) |
| | 55 | && |
| | 56 | (localpoint.vx >= thisModule->m_minx - ModuleFromPositionTolerance) |
| | 57 | && |
| | 58 | (localpoint.vy <= thisModule->m_maxy + ModuleFromPositionTolerance) |
| | 59 | && |
| | 60 | (localpoint.vy >= thisModule->m_miny - ModuleFromPositionTolerance) |
| | 61 | && |
| | 62 | (localpoint.vz <= thisModule->m_maxz + ModuleFromPositionTolerance) |
| | 63 | && |
| | 64 | (localpoint.vz >= thisModule->m_minz - ModuleFromPositionTolerance) |
| | 65 | ); |
| | 66 | } |
| | 67 | |
| | 68 | static int WorldPointIsInModule(MODULE* thisModule, VECTORCH* thisPoint) |
| | 69 | { |
| | 70 | VECTORCH localpoint = *thisPoint; |
| | 71 | localpoint.vx -= thisModule->m_world.vx; |
| | 72 | localpoint.vy -= thisModule->m_world.vy; |
| | 73 | localpoint.vz -= thisModule->m_world.vz; |
| | 74 | |
| | 75 | return |
| | 76 | ( |
| | 77 | (localpoint.vx <= thisModule->m_maxx) |
| | 78 | && |
| | 79 | (localpoint.vx >= thisModule->m_minx) |
| | 80 | && |
| | 81 | (localpoint.vy <= thisModule->m_maxy) |
| | 82 | && |
| | 83 | (localpoint.vy >= thisModule->m_miny) |
| | 84 | && |
| | 85 | (localpoint.vz <= thisModule->m_maxz) |
| | 86 | && |
| | 87 | (localpoint.vz >= thisModule->m_minz) |
| | 88 | ); |
| | 89 | } |
| | 90 | |
| | 91 | /*------------------------Patrick 14/1/97----------------------------- |
| | 92 | This function returns the module in which a given world-space |
| | 93 | position is located. A starting point for the search may also be |
| | 94 | passed, so that the following search pattern is used: |
| | 95 | 1. is the location in the indicated starting module. |
| | 96 | 2. is the location in any of the starting module's visible-links. |
| | 97 | 3. finally, all modules in the environment are searched until |
| | 98 | a containing module is found. |
| | 99 | |
| | 100 | If no module is found, a null module pointer is returned. |
| | 101 | NB only 'physical' modules are returned, ie infinite and |
| | 102 | terminator modules are ignored. |
| | 103 | |
| | 104 | The function is designed to be used for objects which move over small |
| | 105 | distances, and for which a recently containing module is known (eg |
| | 106 | avp aliens).... so that the first stage of the search will be successful |
| | 107 | in the majority of cases, and the third stage rarely used. |
| | 108 | Note that the fn returns the first module which contains the given |
| | 109 | point, so problems may arise if the point exists in more than one |
| | 110 | module. This should be ok for environments like avp, where v-linking |
| | 111 | is not used. |
| | 112 | --------------------------------------------------------------------*/ |
| | 113 | |
| | 114 | static MODULE* ModuleFromPosition_WithTolerance(VECTORCH *position, MODULE* startingModule) |
| | 115 | { |
| | 116 | if(startingModule && ModuleIsPhysical(startingModule)) |
| | 117 | { |
| | 118 | /* first test for the most trivial, and most likely case */ |
| | 119 | if(WorldPointIsInModule_WithTolerance(startingModule, position)) |
| | 120 | return startingModule; |
| | 121 | |
| | 122 | /* now test visible-linked modules (If there are any) */ |
| | 123 | { |
| | 124 | VMODULE *vlPtr = startingModule->m_vmptr; |
| | 125 | |
| | 126 | if(vlPtr) |
| | 127 | { |
| | 128 | while(!vlPtr->end_module) |
| | 129 | { |
| | 130 | MODULE *mPtr = vlPtr->vmod_mref.mref_ptr; |
| | 131 | |
| | 132 | if(mPtr && ModuleIsPhysical(mPtr) && WorldPointIsInModule_WithTolerance(mPtr, position)) |
| | 133 | { |
| | 134 | return mPtr; |
| | 135 | } |
| | 136 | |
| | 137 | vlPtr++; |
| | 138 | } |
| | 139 | } |
| | 140 | } |
| | 141 | } |
| | 142 | |
| | 143 | /* either there is no starting module; the starting module is not physical; |
| | 144 | we are not in the starting module and it has no visibility-linked modules; |
| | 145 | or we haven't found a module yet: so search the entire module list */ |
| | 146 | { |
| | 147 | int moduleCounter = ModuleArraySize; |
| | 148 | MODULE **moduleListPointer = MainScene.sm_marray; |
| | 149 | |
| | 150 | while(moduleCounter-- > 0) |
| | 151 | { |
| | 152 | MODULE *thisModule = *moduleListPointer++; |
| | 153 | |
| | 154 | if(ModuleIsPhysical(thisModule) && WorldPointIsInModule_WithTolerance(thisModule, position)) |
| | 155 | return thisModule; |
| | 156 | } |
| | 157 | } |
| | 158 | |
| | 159 | /* couldn't find a module */ |
| | 160 | return NULL; |
| | 161 | } |
| | 162 | |
| | 163 | MODULE* ModuleFromPosition(VECTORCH *position, MODULE* startingModule) |
| | 164 | { |
| | 165 | if((NULL != startingModule) && ModuleIsPhysical(startingModule)) |
| | 166 | { |
| | 167 | /* first test for the most trivial, and most likely case */ |
| | 168 | if(WorldPointIsInModule(startingModule, position)) |
| | 169 | return startingModule; |
| | 170 | |
| | 171 | /* now test visible-linked modules (If there are any) */ |
| | 172 | { |
| | 173 | VMODULE *vlPtr = startingModule->m_vmptr; |
| | 174 | |
| | 175 | if(NULL != vlPtr) |
| | 176 | { |
| | 177 | while(!vlPtr->end_module) |
| | 178 | { |
| | 179 | MODULE *mPtr = vlPtr->vmod_mref.mref_ptr; |
| | 180 | |
| | 181 | if((NULL != mPtr) && ModuleIsPhysical(mPtr) && WorldPointIsInModule(mPtr, position)) |
| | 182 | return mPtr; |
| | 183 | |
| | 184 | vlPtr++; |
| | 185 | } |
| | 186 | } |
| | 187 | } |
| | 188 | } |
| | 189 | |
| | 190 | /* either there is no starting module; the starting module is not physical; |
| | 191 | we are not in the starting module and it has no visibility-linked modules; |
| | 192 | or we haven't found a module yet: so search the entire module list */ |
| | 193 | { |
| | 194 | int moduleCounter = ModuleArraySize; |
| | 195 | MODULE **moduleListPointer = MainScene.sm_marray; |
| | 196 | |
| | 197 | while(moduleCounter-- > 0) |
| | 198 | { |
| | 199 | MODULE *thisModule = *moduleListPointer++; |
| | 200 | |
| | 201 | if(ModuleIsPhysical(thisModule) && WorldPointIsInModule(thisModule, position)) |
| | 202 | return thisModule; |
| | 203 | } |
| | 204 | } |
| | 205 | |
| | 206 | /* couldn't find a module */ |
| | 207 | /*Try with slightly larger module bounding boxes*/ |
| | 208 | return ModuleFromPosition_WithTolerance(position, startingModule); |
| | 209 | } |