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