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