| | 1 | #include "system.h" |
| | 2 | #include "stratdef.h" |
| | 3 | #include "bh_spcl.h" |
| | 4 | #include <assert.h> |
| | 5 | #include <stdlib.h> |
| | 6 | |
| | 7 | extern void UpdateMorphing(MORPHCTRL *mcptr); |
| | 8 | signed int RequestFadeToBlackLevel = 0; |
| | 9 | extern SCENEMODULE MainScene; |
| | 10 | |
| | 11 | void InitXenoMorphRoom(void * bhdata, STRATEGYBLOCK * sbptr) |
| | 12 | { |
| | 13 | MODULE * my_mod; |
| | 14 | assert(sbptr); |
| | 15 | |
| | 16 | XENO_MORPH_ROOM_DATA * xmrd = malloc(sizeof(XENO_MORPH_ROOM_DATA)); |
| | 17 | sbptr->dataptr = xmrd; |
| | 18 | |
| | 19 | if (!xmrd) |
| | 20 | { |
| | 21 | RemoveBehaviourStrategy(sbptr); |
| | 22 | return; |
| | 23 | } |
| | 24 | |
| | 25 | xmrd->bhvr_type = I_BehaviourXenoborgMorphRoom; |
| | 26 | |
| | 27 | XENO_MORPH_ROOM_TOOLS_TEMPLATE * xmrtt = (XENO_MORPH_ROOM_TOOLS_TEMPLATE *)bhdata; |
| | 28 | |
| | 29 | xmrd->MainShape = xmrtt->MainShape; |
| | 30 | xmrd->ShutShape = xmrtt->ShutShape; |
| | 31 | xmrd->WallsOutShape = xmrtt->WallsOutShape; |
| | 32 | xmrd->ProbesInShape = xmrtt->ProbesInShape; |
| | 33 | |
| | 34 | MORPHCTRL* morphctrl = malloc(sizeof(MORPHCTRL)); |
| | 35 | |
| | 36 | if (!morphctrl) |
| | 37 | { |
| | 38 | RemoveBehaviourStrategy(sbptr); |
| | 39 | return; |
| | 40 | } |
| | 41 | |
| | 42 | MORPHHEADER* morphheader = malloc(sizeof(MORPHHEADER)); |
| | 43 | |
| | 44 | if (!morphheader) |
| | 45 | { |
| | 46 | free(morphctrl); |
| | 47 | RemoveBehaviourStrategy(sbptr); |
| | 48 | return; |
| | 49 | } |
| | 50 | |
| | 51 | MORPHFRAME* morphframe = malloc(sizeof(MORPHFRAME)); |
| | 52 | |
| | 53 | if (!morphframe) |
| | 54 | { |
| | 55 | free(morphctrl); |
| | 56 | free(morphheader); |
| | 57 | RemoveBehaviourStrategy(sbptr); |
| | 58 | return; |
| | 59 | } |
| | 60 | |
| | 61 | morphframe->mf_shape1 = xmrd->MainShape; |
| | 62 | morphframe->mf_shape2 = xmrd->ShutShape; |
| | 63 | |
| | 64 | morphheader->mph_numframes = 1; |
| | 65 | morphheader->mph_maxframes = ONE_FIXED; |
| | 66 | morphheader->mph_frames = morphframe; |
| | 67 | |
| | 68 | morphctrl->ObMorphCurrFrame = 0; |
| | 69 | morphctrl->ObMorphFlags = 0; |
| | 70 | morphctrl->ObMorphSpeed = 0; |
| | 71 | morphctrl->ObMorphHeader = morphheader; |
| | 72 | |
| | 73 | // Copy the names over |
| | 74 | COPY_NAME (sbptr->SBname, xmrtt->nameID); |
| | 75 | COPY_NAME (xmrd->doorID, xmrtt->doorID); |
| | 76 | |
| | 77 | // Setup module ref |
| | 78 | ConvertModuleNameToPointer(&xmrtt->my_module, MainScene.sm_marray); |
| | 79 | my_mod = xmrtt->my_module.mref_ptr; |
| | 80 | |
| | 81 | assert (my_mod); |
| | 82 | |
| | 83 | my_mod->m_sbptr = sbptr; |
| | 84 | sbptr->moptr = my_mod; |
| | 85 | sbptr->shapeIndex = my_mod->m_mapptr->MapShape; |
| | 86 | |
| | 87 | xmrd->XMR_Mctrl = morphctrl; |
| | 88 | xmrd->XMR_State = XMRS_Idle; |
| | 89 | xmrd->DoorToRoom = 0; |
| | 90 | |
| | 91 | sbptr->morphctrl = xmrd->XMR_Mctrl; |
| | 92 | sbptr->morphctrl->ObMorphCurrFrame = 0; |
| | 93 | |
| | 94 | // set up the animation control |
| | 95 | { |
| | 96 | int item_num = 0; |
| | 97 | int shape_num = my_mod->m_mapptr->MapShape; |
| | 98 | struct shapeheader* shptr = GetShapeData(shape_num); |
| | 99 | TXACTRLBLK **pptxactrlblk = &xmrd->tacb; |
| | 100 | |
| | 101 | for(; item_num < shptr->numitems; item_num ++) |
| | 102 | { |
| | 103 | POLYHEADER *poly = (POLYHEADER*)(shptr->items[item_num]); |
| | 104 | assert(poly); |
| | 105 | |
| | 106 | if(poly->PolyFlags & iflag_txanim) |
| | 107 | { |
| | 108 | int num_seq = 0; |
| | 109 | TXACTRLBLK *pnew_txactrlblk = malloc(sizeof(TXACTRLBLK)); |
| | 110 | |
| | 111 | if (pnew_txactrlblk) |
| | 112 | { |
| | 113 | pnew_txactrlblk->tac_flags = 0; |
| | 114 | pnew_txactrlblk->tac_item = item_num; |
| | 115 | pnew_txactrlblk->tac_sequence = 0; |
| | 116 | pnew_txactrlblk->tac_node = 0; |
| | 117 | pnew_txactrlblk->tac_txarray = GetTxAnimArrayZ(shape_num, item_num); |
| | 118 | pnew_txactrlblk->tac_txah_s = GetTxAnimHeaderFromShape(pnew_txactrlblk, shape_num); |
| | 119 | |
| | 120 | while(pnew_txactrlblk->tac_txarray[num_seq+1]) |
| | 121 | num_seq++; |
| | 122 | |
| | 123 | /* set the flags in the animation header */ |
| | 124 | // we only ever have one frame of animation per sequence - |
| | 125 | // nb this can change talk to richard - one sequence with two frames |
| | 126 | // or mutliple sequences??? |
| | 127 | |
| | 128 | // pnew_txactrlblk->tac_txah.txa_flags |= txa_flag_play; |
| | 129 | |
| | 130 | /* change the value held in pptxactrlblk |
| | 131 | which point to the previous structures "next" |
| | 132 | pointer*/ |
| | 133 | |
| | 134 | *pptxactrlblk = pnew_txactrlblk; |
| | 135 | pptxactrlblk = &pnew_txactrlblk->tac_next; |
| | 136 | } |
| | 137 | else |
| | 138 | { |
| | 139 | memoryInitialisationFailure = 1; |
| | 140 | } |
| | 141 | } |
| | 142 | } |
| | 143 | |
| | 144 | *pptxactrlblk = NULL; |
| | 145 | } |
| | 146 | |
| | 147 | RequestFadeToBlackLevel = 0; |
| | 148 | } |
| | 149 | |
| | 150 | void XenoMorphRoomBehaviour (STRATEGYBLOCK * sbptr) |
| | 151 | { |
| | 152 | XENO_MORPH_ROOM_DATA * xmrd = (XENO_MORPH_ROOM_DATA *)sbptr->dataptr; |
| | 153 | MORPHCTRL * mctrl = xmrd->XMR_Mctrl; |
| | 154 | |
| | 155 | assert (mctrl); |
| | 156 | assert (mctrl->ObMorphHeader); |
| | 157 | assert (mctrl->ObMorphHeader->mph_frames); |
| | 158 | |
| | 159 | switch (xmrd->XMR_State) |
| | 160 | { |
| | 161 | case XMRS_Idle: |
| | 162 | { |
| | 163 | if (sbptr->moptr->m_dptr) |
| | 164 | { |
| | 165 | if (PlayerStatus.sbptr->containingModule == sbptr->moptr) |
| | 166 | { |
| | 167 | VECTORCH diff; |
| | 168 | diff.vx = PlayerStatus.DisplayBlock->ObWorld.vx - sbptr->moptr->m_dptr->ObWorld.vx; |
| | 169 | diff.vy = PlayerStatus.DisplayBlock->ObWorld.vy - sbptr->moptr->m_dptr->ObWorld.vy; |
| | 170 | diff.vz = PlayerStatus.DisplayBlock->ObWorld.vz - sbptr->moptr->m_dptr->ObWorld.vz; |
| | 171 | |
| | 172 | if (diff.vx * diff.vx + diff.vz * diff.vz < 200000) |
| | 173 | xmrd->XMR_State = XMRS_SafetyChecks; |
| | 174 | } |
| | 175 | } |
| | 176 | } |
| | 177 | break; |
| | 178 | case XMRS_SafetyChecks: |
| | 179 | { |
| | 180 | int can_continue = 1; |
| | 181 | int i; |
| | 182 | // waits to make sure everything is OK before it shuts the walls |
| | 183 | |
| | 184 | if (xmrd->DoorToRoom) |
| | 185 | { |
| | 186 | PROXDOOR_BEHAV_BLOCK * doorbhv = (PROXDOOR_BEHAV_BLOCK*)xmrd->DoorToRoom->dataptr; |
| | 187 | |
| | 188 | doorbhv->door_locked = 1; |
| | 189 | |
| | 190 | if (doorbhv->door_state != I_door_closed) |
| | 191 | can_continue = 0; |
| | 192 | } |
| | 193 | |
| | 194 | for (i=0; i < NumActiveStBlocks; i++) |
| | 195 | { |
| | 196 | if (ActiveStBlockList[i]->type == I_BehaviourMarine) |
| | 197 | { |
| | 198 | if (ActiveStBlockList[i]->containingModule == sbptr->moptr) |
| | 199 | { |
| | 200 | can_continue = 0; |
| | 201 | break; |
| | 202 | } |
| | 203 | } |
| | 204 | } |
| | 205 | |
| | 206 | if (sbptr->moptr->m_dptr) |
| | 207 | { |
| | 208 | if (PlayerStatus.sbptr->containingModule == sbptr->moptr) |
| | 209 | { |
| | 210 | VECTORCH diff; |
| | 211 | diff.vx = PlayerStatus.DisplayBlock->ObWorld.vx - sbptr->moptr->m_dptr->ObWorld.vx; |
| | 212 | diff.vy = PlayerStatus.DisplayBlock->ObWorld.vy - sbptr->moptr->m_dptr->ObWorld.vy; |
| | 213 | diff.vz = PlayerStatus.DisplayBlock->ObWorld.vz - sbptr->moptr->m_dptr->ObWorld.vz; |
| | 214 | |
| | 215 | if (diff.vx * diff.vx + diff.vz * diff.vz > 200000) |
| | 216 | can_continue = 0; |
| | 217 | |
| | 218 | if(DynamicObjectIsMoving(PlayerStatus.sbptr->DynPtr)) |
| | 219 | can_continue = 0; |
| | 220 | } |
| | 221 | else |
| | 222 | { |
| | 223 | can_continue = 0; |
| | 224 | } |
| | 225 | } |
| | 226 | else |
| | 227 | { |
| | 228 | can_continue = 0; |
| | 229 | xmrd->XMR_State = XMRS_Idle; |
| | 230 | } |
| | 231 | |
| | 232 | if (can_continue) |
| | 233 | { |
| | 234 | // closes in player |
| | 235 | mctrl->ObMorphHeader->mph_frames->mf_shape1 = xmrd->MainShape; |
| | 236 | mctrl->ObMorphHeader->mph_frames->mf_shape2 = xmrd->ShutShape; |
| | 237 | |
| | 238 | mctrl->ObMorphCurrFrame = 0; |
| | 239 | mctrl->ObMorphFlags = mph_flag_play; |
| | 240 | mctrl->ObMorphFlags |= mph_flag_noloop; |
| | 241 | mctrl->ObMorphFlags &= ~mph_flag_reverse; |
| | 242 | mctrl->ObMorphFlags &= ~mph_flag_finished; |
| | 243 | mctrl->ObMorphSpeed = 1 << 18; |
| | 244 | |
| | 245 | xmrd->XMR_State = XMRS_EnclosingPlayer; |
| | 246 | } |
| | 247 | } |
| | 248 | break; |
| | 249 | case XMRS_EnclosingPlayer: |
| | 250 | { |
| | 251 | UpdateMorphing(mctrl); |
| | 252 | |
| | 253 | if(mctrl->ObMorphFlags & mph_flag_finished) |
| | 254 | { |
| | 255 | mctrl->ObMorphHeader->mph_frames->mf_shape1 = xmrd->ShutShape; |
| | 256 | mctrl->ObMorphHeader->mph_frames->mf_shape2 = xmrd->WallsOutShape; |
| | 257 | |
| | 258 | mctrl->ObMorphCurrFrame = 0; |
| | 259 | |
| | 260 | mctrl->ObMorphFlags = mph_flag_play; |
| | 261 | mctrl->ObMorphFlags |= mph_flag_noloop; |
| | 262 | mctrl->ObMorphFlags &= ~mph_flag_reverse; |
| | 263 | mctrl->ObMorphFlags &= ~mph_flag_finished; |
| | 264 | mctrl->ObMorphSpeed = 1 << 13; |
| | 265 | |
| | 266 | xmrd->XMR_State = XMRS_WallsOut; |
| | 267 | } |
| | 268 | } |
| | 269 | break; |
| | 270 | case XMRS_WallsOut: |
| | 271 | { |
| | 272 | UpdateMorphing(mctrl); |
| | 273 | |
| | 274 | if(mctrl->ObMorphFlags & mph_flag_finished) |
| | 275 | { |
| | 276 | mctrl->ObMorphHeader->mph_frames->mf_shape1 = xmrd->WallsOutShape; |
| | 277 | mctrl->ObMorphHeader->mph_frames->mf_shape2 = xmrd->ProbesInShape; |
| | 278 | |
| | 279 | mctrl->ObMorphCurrFrame = 0; |
| | 280 | |
| | 281 | mctrl->ObMorphFlags = mph_flag_play; |
| | 282 | mctrl->ObMorphFlags |= mph_flag_noloop; |
| | 283 | mctrl->ObMorphFlags &= ~mph_flag_reverse; |
| | 284 | mctrl->ObMorphFlags &= ~mph_flag_finished; |
| | 285 | mctrl->ObMorphSpeed = 1 << 13; |
| | 286 | |
| | 287 | xmrd->XMR_State = XMRS_ProbesIn; |
| | 288 | } |
| | 289 | } |
| | 290 | break; |
| | 291 | case XMRS_ProbesIn: |
| | 292 | { |
| | 293 | UpdateMorphing(mctrl); |
| | 294 | |
| | 295 | if(mctrl->ObMorphFlags & mph_flag_finished) |
| | 296 | xmrd->XMR_State = XMRS_FadeToBlack; |
| | 297 | } |
| | 298 | break; |
| | 299 | case XMRS_FadeToBlack: |
| | 300 | { |
| | 301 | RequestFadeToBlackLevel += (NormalFrameTime >> 1); |
| | 302 | |
| | 303 | if (RequestFadeToBlackLevel > (ONE_FIXED)) |
| | 304 | { |
| | 305 | RequestFadeToBlackLevel = ONE_FIXED; |
| | 306 | xmrd->timer = 0; |
| | 307 | xmrd->XMR_State = XMRS_Process; |
| | 308 | } |
| | 309 | } |
| | 310 | break; |
| | 311 | case XMRS_Process: |
| | 312 | { |
| | 313 | xmrd->timer += NormalFrameTime; |
| | 314 | |
| | 315 | if (xmrd->timer > (ONE_FIXED << 3)) |
| | 316 | { |
| | 317 | if(sbptr->DisplayBlock) |
| | 318 | { |
| | 319 | struct shapeheader* pis = GetShapeData(xmrd->ProbesInShape); |
| | 320 | struct shapeheader* ms = GetShapeData(xmrd->MainShape); |
| | 321 | |
| | 322 | sbptr->DisplayBlock->ObMorphCtrl = 0; |
| | 323 | |
| | 324 | xmrd->pis_items_str = pis->items; |
| | 325 | xmrd->pis_sht_str = pis->sh_textures; |
| | 326 | |
| | 327 | pis->items = ms->items; |
| | 328 | pis->sh_textures = ms->sh_textures; |
| | 329 | pis->sh_instruction[4].sh_instr_data = ms->sh_instruction[4].sh_instr_data; |
| | 330 | |
| | 331 | sbptr->DisplayBlock->ObTxAnimCtrlBlks = xmrd->tacb; |
| | 332 | sbptr->DisplayBlock->ObShape = xmrd->ProbesInShape; |
| | 333 | sbptr->DisplayBlock->ShapeData = GetShapeData(xmrd->ProbesInShape); |
| | 334 | |
| | 335 | // This moves the player to the required location |
| | 336 | |
| | 337 | PlayerStatus.sbptr->DynPtr->Position = sbptr->DisplayBlock->ObWorld; |
| | 338 | PlayerStatus.sbptr->DynPtr->Position.vy += 1472; |
| | 339 | PlayerStatus.sbptr->DynPtr->Position.vx -= 900; |
| | 340 | PlayerStatus.sbptr->DynPtr->PrevPosition = PlayerStatus.sbptr->DynPtr->Position; |
| | 341 | PlayerStatus.sbptr->DynPtr->OrientEuler.EulerX = 0; |
| | 342 | PlayerStatus.sbptr->DynPtr->OrientEuler.EulerY = 1024; |
| | 343 | PlayerStatus.sbptr->DynPtr->OrientEuler.EulerZ = 0; |
| | 344 | PlayerStatus.sbptr->DynPtr->PrevOrientEuler = PlayerStatus.sbptr->DynPtr->OrientEuler; |
| | 345 | |
| | 346 | CreateEulerMatrix (&PlayerStatus.sbptr->DynPtr->OrientEuler, &PlayerStatus.sbptr->DynPtr->OrientMat); |
| | 347 | |
| | 348 | TransposeMatrixCH(&PlayerStatus.sbptr->DynPtr->OrientMat); |
| | 349 | |
| | 350 | PlayerStatus.sbptr->DynPtr->PrevOrientMat = PlayerStatus.sbptr->DynPtr->OrientMat; |
| | 351 | |
| | 352 | xmrd->XMR_State = XMRS_Return; |
| | 353 | } |
| | 354 | } |
| | 355 | } |
| | 356 | break; |
| | 357 | case XMRS_Return: |
| | 358 | { |
| | 359 | RequestFadeToBlackLevel -= (NormalFrameTime >> 1); |
| | 360 | |
| | 361 | if (RequestFadeToBlackLevel <= 0) |
| | 362 | { |
| | 363 | RequestFadeToBlackLevel = 0; |
| | 364 | |
| | 365 | xmrd->timer = 0; |
| | 366 | xmrd->XMR_State = XMRS_ReleasePlayer; |
| | 367 | } |
| | 368 | } |
| | 369 | break; |
| | 370 | case XMRS_ReleasePlayer: |
| | 371 | { |
| | 372 | xmrd->timer += NormalFrameTime; |
| | 373 | |
| | 374 | if (xmrd->timer > (ONE_FIXED << 2)) |
| | 375 | { |
| | 376 | sbptr->DisplayBlock->ObShape = xmrd->MainShape; |
| | 377 | sbptr->DisplayBlock->ShapeData = GetShapeData(xmrd->MainShape); |
| | 378 | sbptr->DisplayBlock->ObMorphCtrl = mctrl; |
| | 379 | mctrl->ObMorphHeader->mph_frames->mf_shape1 = xmrd->ProbesInShape; |
| | 380 | mctrl->ObMorphHeader->mph_frames->mf_shape2 = xmrd->MainShape; |
| | 381 | mctrl->ObMorphCurrFrame = 0; |
| | 382 | mctrl->ObMorphFlags = mph_flag_play; |
| | 383 | mctrl->ObMorphFlags |= mph_flag_noloop; |
| | 384 | mctrl->ObMorphFlags &= ~mph_flag_reverse; |
| | 385 | mctrl->ObMorphFlags &= ~mph_flag_finished; |
| | 386 | mctrl->ObMorphSpeed = 1 << 15; |
| | 387 | |
| | 388 | xmrd->XMR_State = XMRS_Finished; |
| | 389 | } |
| | 390 | } |
| | 391 | break; |
| | 392 | case XMRS_Finished: |
| | 393 | { |
| | 394 | if(!(mctrl->ObMorphFlags & mph_flag_finished)) |
| | 395 | { |
| | 396 | UpdateMorphing(mctrl); |
| | 397 | } |
| | 398 | else |
| | 399 | { |
| | 400 | struct shapeheader* pis = GetShapeData(xmrd->ProbesInShape); |
| | 401 | sbptr->DisplayBlock->ObTxAnimCtrlBlks = 0; |
| | 402 | pis->items = xmrd->pis_items_str; |
| | 403 | pis->sh_textures = xmrd->pis_sht_str; |
| | 404 | |
| | 405 | pis->sh_instruction[4].sh_instr_data = xmrd->pis_items_str; |
| | 406 | xmrd->XMR_State = XMRS_Idle; |
| | 407 | } |
| | 408 | } |
| | 409 | break; |
| | 410 | default : |
| | 411 | assert (0 == "Shouldn't be here"); |
| | 412 | break; |
| | 413 | } |
| | 414 | } |