| | 1 | #include "npc_common.h" |
| | 2 | #include "dynamics.h" |
| | 3 | #include "prototyp.h" |
| | 4 | #include "switchdoor.h" |
| | 5 | #include "liftdoor.h" |
| | 6 | #include "platformlift.h" |
| | 7 | #include "weaponbehaviour.h" |
| | 8 | #include "debris.h" |
| | 9 | #include "lighting.h" |
| | 10 | #include "linkswitch.h" |
| | 11 | #include "binaryswitch.h" |
| | 12 | #include "npc_xenoborg.h" |
| | 13 | #include "npc_queen.h" |
| | 14 | #include "npc_sentrygun.h" |
| | 15 | #include "npc_dummy.h" |
| | 16 | #include "npc_facehugger.h" |
| | 17 | #include "lift.h" |
| | 18 | #include "bh_spcl.h" |
| | 19 | #include "bh_ltfx.h" |
| | 20 | #include "bh_snds.h" |
| | 21 | #include "placedhierarchy.h" |
| | 22 | #include "bh_light.h" |
| | 23 | #include "bh_cable.h" |
| | 24 | #include "bh_deathvol.h" |
| | 25 | #include "bh_selfdest.h" |
| | 26 | #include "mission.h" |
| | 27 | #include "fan.h" |
| | 28 | #include "particlegenerator.h" |
| | 29 | #include "particle.h" |
| | 30 | #include "videoscreen.h" |
| | 31 | #include "savegame.h" |
| | 32 | #include <stdlib.h> |
| | 33 | #include <string.h> |
| | 34 | |
| | 35 | extern int GlobalFrameCounter; |
| | 36 | extern SCENEMODULE MainScene; |
| | 37 | |
| | 38 | extern void MaintainPlayersInventory(STRATEGYBLOCK *collidedWith); |
| | 39 | extern void UpdateMorphing(MORPHCTRL *mcptr); |
| | 40 | extern void GrapplingHookBehaviour(STRATEGYBLOCK *sbPtr); |
| | 41 | extern void InitXenoMorphRoom (void * bhdata, STRATEGYBLOCK * sbptr); |
| | 42 | extern void XenoMorphRoomBehaviour (STRATEGYBLOCK * sbptr); |
| | 43 | extern void HierarchicalFragmentBehaviour(STRATEGYBLOCK *sptr); |
| | 44 | extern void Xeno_Enter_PowerUp_State(STRATEGYBLOCK *sbPtr); |
| | 45 | extern void Xeno_Enter_PowerDown_State(STRATEGYBLOCK *sbPtr); |
| | 46 | |
| | 47 | #define ObjectRequest_AdjustIntegrity 0x00000001 |
| | 48 | #define PLAYER_PICKUP_OBJECT_RADIUS 1600 |
| | 49 | |
| | 50 | const NPC_DATA NpcDataList[I_NPC_End] = |
| | 51 | { |
| | 52 | { |
| | 53 | I_NPC_Civilian, |
| | 54 | { |
| | 55 | 50, /* Health */ |
| | 56 | 0, /* Armour */ |
| | 57 | 0, /* IsOnFire */ |
| | 58 | 0, /* Acid Resistant */ |
| | 59 | 0, /* Fire Resistant */ |
| | 60 | 0, /* Electric Resistant */ |
| | 61 | 0, /* Perfect Armour */ |
| | 62 | 0, /* Electric Sensitive */ |
| | 63 | 1, /* Combustability */ |
| | 64 | 0 /* Indestructable */ |
| | 65 | }, |
| | 66 | }, |
| | 67 | { |
| | 68 | I_NPC_FaceHugger, |
| | 69 | { |
| | 70 | 10, /* Health */ |
| | 71 | 0, /* Armour */ |
| | 72 | 0, /* IsOnFire */ |
| | 73 | 1, /* Acid Resistant */ |
| | 74 | 0, /* Fire Resistant */ |
| | 75 | 0, /* Electric Resistant */ |
| | 76 | 0, /* Perfect Armour */ |
| | 77 | 1, /* Electric Sensitive */ |
| | 78 | 0, /* Combustability */ |
| | 79 | 0 /* Indestructable */ |
| | 80 | }, |
| | 81 | }, |
| | 82 | { |
| | 83 | I_NPC_Alien, |
| | 84 | { |
| | 85 | 300, /* Health */ |
| | 86 | 100, /* Armour */ |
| | 87 | 0, /* IsOnFire */ |
| | 88 | 1, /* Acid Resistant */ |
| | 89 | 1, /* Fire Resistant */ |
| | 90 | 0, /* Electric Resistant */ |
| | 91 | 1, /* Perfect Armour */ |
| | 92 | 1, /* Electric Sensitive */ |
| | 93 | 0, /* Combustability */ |
| | 94 | 0 /* Indestructable */ |
| | 95 | }, |
| | 96 | }, |
| | 97 | { |
| | 98 | I_NPC_Xenoborg, |
| | 99 | { |
| | 100 | 750, /* Health */ |
| | 101 | 120, /* Armour */ |
| | 102 | 0, /* IsOnFire */ |
| | 103 | 1, /* Acid Resistant */ |
| | 104 | 0, /* Fire Resistant */ |
| | 105 | 0, /* Electric Resistant */ |
| | 106 | 0, /* Perfect Armour */ |
| | 107 | 1, /* Electric Sensitive */ |
| | 108 | 0, /* Combustability */ |
| | 109 | 0 /* Indestructable */ |
| | 110 | }, |
| | 111 | }, |
| | 112 | { |
| | 113 | I_NPC_Marine, |
| | 114 | { |
| | 115 | 80, /* Health */ |
| | 116 | 50, /* Armour */ |
| | 117 | 0, /* IsOnFire */ |
| | 118 | 0, /* Acid Resistant */ |
| | 119 | 0, /* Fire Resistant */ |
| | 120 | 0, /* Electric Resistant */ |
| | 121 | 0, /* Perfect Armour */ |
| | 122 | 0, /* Electric Sensitive */ |
| | 123 | 1, /* Combustability */ |
| | 124 | 0 /* Indestructable */ |
| | 125 | }, |
| | 126 | }, |
| | 127 | { |
| | 128 | I_NPC_PredatorAlien, |
| | 129 | { |
| | 130 | 400, /* Health */ |
| | 131 | 150, /* Armour */ |
| | 132 | 0, /* IsOnFire */ |
| | 133 | 1, /* Acid Resistant */ |
| | 134 | 0, /* Fire Resistant */ |
| | 135 | 0, /* Electric Resistant */ |
| | 136 | 0, /* Perfect Armour */ |
| | 137 | 0, /* Electric Sensitive */ |
| | 138 | 1, /* Combustability */ |
| | 139 | 0 /* Indestructable */ |
| | 140 | }, |
| | 141 | }, |
| | 142 | { |
| | 143 | I_NPC_Predator, |
| | 144 | { |
| | 145 | 350, /* Health */ |
| | 146 | 200, /* Armour */ |
| | 147 | 0, /* IsOnFire */ |
| | 148 | 0, /* Acid Resistant */ |
| | 149 | 0, /* Fire Resistant */ |
| | 150 | 0, /* Electric Resistant */ |
| | 151 | 0, /* Perfect Armour */ |
| | 152 | 0, /* Electric Sensitive */ |
| | 153 | 1, /* Combustability */ |
| | 154 | 0 /* Indestructable */ |
| | 155 | }, |
| | 156 | }, |
| | 157 | { |
| | 158 | I_NPC_PraetorianGuard, |
| | 159 | { |
| | 160 | 1000, /* Health */ |
| | 161 | 400, /* Armour */ |
| | 162 | 0, /* IsOnFire */ |
| | 163 | 1, /* Acid Resistant */ |
| | 164 | 1, /* Fire Resistant */ |
| | 165 | 0, /* Electric Resistant */ |
| | 166 | 1, /* Perfect Armour */ |
| | 167 | 1, /* Electric Sensitive */ |
| | 168 | 0, /* Combustability */ |
| | 169 | 0 /* Indestructable */ |
| | 170 | }, |
| | 171 | }, |
| | 172 | { |
| | 173 | I_NPC_AlienQueen, |
| | 174 | { |
| | 175 | 4000, /* Health */ |
| | 176 | 1000, /* Armour */ |
| | 177 | 0, /* IsOnFire */ |
| | 178 | 1, /* Acid Resistant */ |
| | 179 | 1, /* Fire Resistant */ |
| | 180 | 0, /* Electric Resistant */ |
| | 181 | 1, /* Perfect Armour */ |
| | 182 | 0, /* Electric Sensitive */ |
| | 183 | 0, /* Combustability */ |
| | 184 | 0 /* Indestructable */ |
| | 185 | }, |
| | 186 | }, |
| | 187 | { |
| | 188 | I_NPC_DefaultInanimate, |
| | 189 | { |
| | 190 | 15, /* Health */ |
| | 191 | 4, /* Armour */ |
| | 192 | 0, /* IsOnFire */ |
| | 193 | 0, /* Acid Resistant */ |
| | 194 | 0, /* Fire Resistant */ |
| | 195 | 0, /* Electric Resistant */ |
| | 196 | 0, /* Perfect Armour */ |
| | 197 | 0, /* Electric Sensitive */ |
| | 198 | 1, /* Combustability */ |
| | 199 | 0 /* Indestructable */ |
| | 200 | }, |
| | 201 | }, |
| | 202 | { |
| | 203 | I_PC_Alien_MaxStats, |
| | 204 | { |
| | 205 | 180, /* Health */ |
| | 206 | 30, /* Armour (was 6) */ |
| | 207 | 0, /* IsOnFire */ |
| | 208 | 1, /* Acid Resistant */ |
| | 209 | 0, /* Fire Resistant */ |
| | 210 | 0, /* Electric Resistant */ |
| | 211 | 0, /* Perfect Armour */ /* Disabled, CDF 28/7/98 */ |
| | 212 | 0, /* Electric Sensitive */ |
| | 213 | 0, /* Combustability */ |
| | 214 | 0 /* Indestructable */ |
| | 215 | }, |
| | 216 | }, |
| | 217 | { |
| | 218 | I_NPC_SentryGun, |
| | 219 | { |
| | 220 | 500, /* Health */ |
| | 221 | 400, /* Armour */ |
| | 222 | 0, /* IsOnFire */ |
| | 223 | 0, /* Acid Resistant */ |
| | 224 | 1, /* Fire Resistant */ |
| | 225 | 0, /* Electric Resistant */ |
| | 226 | 0, /* Perfect Armour */ |
| | 227 | 1, /* Electric Sensitive */ |
| | 228 | 0, /* Combustability */ |
| | 229 | 0 /* Indestructable */ |
| | 230 | }, |
| | 231 | }, |
| | 232 | { |
| | 233 | I_NPC_Android, |
| | 234 | { |
| | 235 | 200, /* Health */ |
| | 236 | 200, /* Armour */ |
| | 237 | 0, /* IsOnFire */ |
| | 238 | 0, /* Acid Resistant */ |
| | 239 | 0, /* Fire Resistant */ |
| | 240 | 0, /* Electric Resistant */ |
| | 241 | 0, /* Perfect Armour */ |
| | 242 | 1, /* Electric Sensitive */ |
| | 243 | 1, /* Combustability */ |
| | 244 | 0 /* Indestructable */ |
| | 245 | }, |
| | 246 | } |
| | 247 | }; |
| | 248 | |
| | 249 | void RemoveBehaviourStrategy(STRATEGYBLOCK* sbptr) |
| | 250 | { |
| | 251 | assert(sbptr); |
| | 252 | |
| | 253 | /* Andy 16/8/97 - Updated to cope with partially allocated strategy blocks |
| | 254 | We need to check that each allocation has been completed before |
| | 255 | trying to deallocate */ |
| | 256 | |
| | 257 | /* CDF 12/11/96 - Destroys ANY strategyblock. * |
| | 258 | * Please maintain... */ |
| | 259 | |
| | 260 | // this notifies the game flow system that an object has been destroyed |
| | 261 | switch(sbptr->type) |
| | 262 | { |
| | 263 | case I_BehaviourFragment: // this happens a lot |
| | 264 | break; |
| | 265 | case I_BehaviourHierarchicalFragment: |
| | 266 | { |
| | 267 | HDEBRIS_BEHAV_BLOCK *hdbblk = (HDEBRIS_BEHAV_BLOCK *)sbptr->dataptr; |
| | 268 | |
| | 269 | Dispel_HModel(&hdbblk->HModelController); |
| | 270 | } |
| | 271 | break; |
| | 272 | case I_BehaviourCorpse: |
| | 273 | { |
| | 274 | CORPSEDATABLOCK *corpseData = (CORPSEDATABLOCK *)(sbptr->dataptr); |
| | 275 | |
| | 276 | if(corpseData) |
| | 277 | { |
| | 278 | if(corpseData->SoundHandle != SOUND_NOACTIVEINDEX) |
| | 279 | Sound_Stop(corpseData->SoundHandle); |
| | 280 | |
| | 281 | Dispel_HModel(&corpseData->HModelController); |
| | 282 | } |
| | 283 | } |
| | 284 | break; |
| | 285 | case I_BehaviourInanimateObject: |
| | 286 | { |
| | 287 | INANIMATEOBJECT_STATUSBLOCK* objectstatusptr = (INANIMATEOBJECT_STATUSBLOCK*)sbptr->dataptr; |
| | 288 | |
| | 289 | if (objectstatusptr) |
| | 290 | { |
| | 291 | if(objectstatusptr->event_target) |
| | 292 | free(objectstatusptr->event_target); |
| | 293 | |
| | 294 | if(!objectstatusptr->inan_tac) |
| | 295 | { |
| | 296 | TXACTRLBLK *txactrl_next = objectstatusptr->inan_tac; |
| | 297 | |
| | 298 | while(txactrl_next) |
| | 299 | { |
| | 300 | TXACTRLBLK *txactrl = txactrl_next; |
| | 301 | txactrl_next = txactrl->tac_next; |
| | 302 | free((void*)txactrl); |
| | 303 | } |
| | 304 | } |
| | 305 | } |
| | 306 | } |
| | 307 | break; |
| | 308 | case I_BehaviourVideoScreen: |
| | 309 | { |
| | 310 | VIDEO_SCREEN_BEHAV_BLOCK* videoScreen = (VIDEO_SCREEN_BEHAV_BLOCK*)sbptr->dataptr; |
| | 311 | |
| | 312 | if (videoScreen && videoScreen->inan_tac) |
| | 313 | { |
| | 314 | TXACTRLBLK *txactrl_next = videoScreen->inan_tac; |
| | 315 | |
| | 316 | while(txactrl_next) |
| | 317 | { |
| | 318 | TXACTRLBLK *txactrl = txactrl_next; |
| | 319 | txactrl_next = txactrl->tac_next; |
| | 320 | free((void*)txactrl); |
| | 321 | } |
| | 322 | } |
| | 323 | } |
| | 324 | break; |
| | 325 | case I_BehaviourPlacedLight: |
| | 326 | { |
| | 327 | PLACED_LIGHT_BEHAV_BLOCK* pl_bhv=(PLACED_LIGHT_BEHAV_BLOCK*)sbptr->dataptr; |
| | 328 | |
| | 329 | if (pl_bhv) |
| | 330 | { |
| | 331 | //set num lights to zero so it doesn't attempt to deallocate the light |
| | 332 | if(sbptr->DisplayBlock) |
| | 333 | sbptr->DisplayBlock->ObNumLights = 0; |
| | 334 | |
| | 335 | //reset vaules in lightblock |
| | 336 | pl_bhv->light->LightBright = pl_bhv->light->LightBrightStore; |
| | 337 | pl_bhv->light->RedScale = pl_bhv->colour_red; |
| | 338 | pl_bhv->light->GreenScale = pl_bhv->colour_green; |
| | 339 | pl_bhv->light->BlueScale = pl_bhv->colour_blue; |
| | 340 | |
| | 341 | if(!pl_bhv->inan_tac) |
| | 342 | break; |
| | 343 | |
| | 344 | TXACTRLBLK *txactrl_next = pl_bhv->inan_tac; |
| | 345 | |
| | 346 | while(txactrl_next) |
| | 347 | { |
| | 348 | TXACTRLBLK *txactrl = txactrl_next; |
| | 349 | txactrl_next = txactrl->tac_next; |
| | 350 | free((void*)txactrl); |
| | 351 | } |
| | 352 | } |
| | 353 | } |
| | 354 | break; |
| | 355 | case I_BehaviourLightFX: |
| | 356 | { |
| | 357 | LIGHT_FX_BEHAV_BLOCK * lfxbb = (LIGHT_FX_BEHAV_BLOCK *)sbptr->dataptr; |
| | 358 | |
| | 359 | if(lfxbb) |
| | 360 | { |
| | 361 | TXACTRLBLK *txactrl_next = lfxbb->anim_control; |
| | 362 | |
| | 363 | while(txactrl_next) |
| | 364 | { |
| | 365 | TXACTRLBLK *txactrl = txactrl_next; |
| | 366 | txactrl_next = txactrl->tac_next; |
| | 367 | free((void*)txactrl); |
| | 368 | } |
| | 369 | } |
| | 370 | } |
| | 371 | break; |
| | 372 | case I_BehaviourPredatorDisc_SeekTrack: |
| | 373 | { |
| | 374 | PC_PRED_DISC_BEHAV_BLOCK *bblk = (PC_PRED_DISC_BEHAV_BLOCK *)(sbptr->dataptr); |
| | 375 | |
| | 376 | if(bblk) |
| | 377 | { |
| | 378 | if (bblk->soundHandle != SOUND_NOACTIVEINDEX) |
| | 379 | Sound_Stop(bblk->soundHandle); |
| | 380 | |
| | 381 | Dispel_HModel(&bblk->HModelController); |
| | 382 | } |
| | 383 | } |
| | 384 | break; |
| | 385 | case I_BehaviourPredatorEnergyBolt: |
| | 386 | case I_BehaviourFrisbeeEnergyBolt: |
| | 387 | { |
| | 388 | CASTER_BOLT_BEHAV_BLOCK *bblk = (CASTER_BOLT_BEHAV_BLOCK *)(sbptr->dataptr); |
| | 389 | |
| | 390 | if(bblk) |
| | 391 | { |
| | 392 | if (bblk->soundHandle != SOUND_NOACTIVEINDEX) |
| | 393 | Sound_Stop(bblk->soundHandle); |
| | 394 | } |
| | 395 | } |
| | 396 | break; |
| | 397 | case I_BehaviourFrisbee: |
| | 398 | { |
| | 399 | FRISBEE_BEHAV_BLOCK *fblk = (FRISBEE_BEHAV_BLOCK *)(sbptr->dataptr); |
| | 400 | |
| | 401 | if(fblk) |
| | 402 | { |
| | 403 | if (fblk->soundHandle != SOUND_NOACTIVEINDEX) |
| | 404 | Sound_Stop(fblk->soundHandle); |
| | 405 | |
| | 406 | Dispel_HModel(&fblk->HModelController); |
| | 407 | } |
| | 408 | } |
| | 409 | break; |
| | 410 | case I_BehaviourFaceHugger: |
| | 411 | { |
| | 412 | FACEHUGGER_STATUS_BLOCK *fhugStatusPointer = (FACEHUGGER_STATUS_BLOCK *)(sbptr->dataptr); |
| | 413 | |
| | 414 | if(fhugStatusPointer) |
| | 415 | { |
| | 416 | if (fhugStatusPointer->soundHandle_fire != SOUND_NOACTIVEINDEX) |
| | 417 | Sound_Stop(fhugStatusPointer->soundHandle_fire); |
| | 418 | |
| | 419 | Dispel_HModel(&fhugStatusPointer->HModelController); |
| | 420 | } |
| | 421 | } |
| | 422 | break; |
| | 423 | case I_BehaviourXenoborg: |
| | 424 | { |
| | 425 | /* need to get rid of the animations...*/ |
| | 426 | XENO_STATUS_BLOCK *xenoStatus = (XENO_STATUS_BLOCK*)(sbptr->dataptr); |
| | 427 | |
| | 428 | if(xenoStatus) |
| | 429 | { |
| | 430 | Dispel_HModel(&xenoStatus->HModelController); |
| | 431 | /* Zounds! */ |
| | 432 | if(xenoStatus->soundHandle1 != SOUND_NOACTIVEINDEX) |
| | 433 | Sound_Stop(xenoStatus->soundHandle1); |
| | 434 | |
| | 435 | if(xenoStatus->soundHandle2 != SOUND_NOACTIVEINDEX) |
| | 436 | Sound_Stop(xenoStatus->soundHandle2); |
| | 437 | |
| | 438 | if(xenoStatus->head_whirr!= SOUND_NOACTIVEINDEX) |
| | 439 | Sound_Stop(xenoStatus->head_whirr); |
| | 440 | |
| | 441 | if(xenoStatus->left_arm_whirr != SOUND_NOACTIVEINDEX) |
| | 442 | Sound_Stop(xenoStatus->left_arm_whirr); |
| | 443 | |
| | 444 | if(xenoStatus->right_arm_whirr != SOUND_NOACTIVEINDEX) |
| | 445 | Sound_Stop(xenoStatus->right_arm_whirr); |
| | 446 | |
| | 447 | if(xenoStatus->torso_whirr != SOUND_NOACTIVEINDEX) |
| | 448 | Sound_Stop(xenoStatus->torso_whirr); |
| | 449 | } |
| | 450 | } |
| | 451 | break; |
| | 452 | case I_BehaviourAlien: |
| | 453 | { |
| | 454 | ALIEN_STATUS_BLOCK *asb = (ALIEN_STATUS_BLOCK *)(sbptr->dataptr); |
| | 455 | Dispel_HModel(&asb->HModelController); |
| | 456 | } |
| | 457 | break; |
| | 458 | case I_BehaviourMarine: |
| | 459 | { |
| | 460 | MARINE_STATUS_BLOCK *marineStatusPointer = (MARINE_STATUS_BLOCK *)(sbptr->dataptr); |
| | 461 | |
| | 462 | if(marineStatusPointer) |
| | 463 | { |
| | 464 | Dispel_HModel(&marineStatusPointer->HModelController); |
| | 465 | |
| | 466 | if(marineStatusPointer->myGunFlash) |
| | 467 | DestroyActiveObject(&marineStatusPointer->myGunFlash); |
| | 468 | |
| | 469 | if(marineStatusPointer->soundHandle != SOUND_NOACTIVEINDEX) |
| | 470 | Sound_Stop(marineStatusPointer->soundHandle); |
| | 471 | } |
| | 472 | } |
| | 473 | break; |
| | 474 | case I_BehaviourPredator: |
| | 475 | { |
| | 476 | PREDATOR_STATUS_BLOCK *predatorStatusPointer = (PREDATOR_STATUS_BLOCK *)(sbptr->dataptr); |
| | 477 | |
| | 478 | if(predatorStatusPointer) |
| | 479 | { |
| | 480 | if(predatorStatusPointer->soundHandle != SOUND_NOACTIVEINDEX) |
| | 481 | Sound_Stop(predatorStatusPointer->soundHandle); |
| | 482 | |
| | 483 | Dispel_HModel(&predatorStatusPointer->HModelController); |
| | 484 | } |
| | 485 | } |
| | 486 | break; |
| | 487 | case I_BehaviourQueenAlien: |
| | 488 | { |
| | 489 | QUEEN_STATUS_BLOCK *queenStatusPointer = (QUEEN_STATUS_BLOCK *)(sbptr->dataptr); |
| | 490 | |
| | 491 | if(queenStatusPointer) |
| | 492 | { |
| | 493 | Dispel_HModel(&queenStatusPointer->HModelController); |
| | 494 | |
| | 495 | //stop any sound the queen is making |
| | 496 | if(queenStatusPointer->soundHandle != SOUND_NOACTIVEINDEX) |
| | 497 | Sound_Stop(queenStatusPointer->soundHandle); |
| | 498 | } |
| | 499 | } |
| | 500 | break; |
| | 501 | case I_BehaviourNetGhost: |
| | 502 | { |
| | 503 | NETGHOSTDATABLOCK *ghostData = (NETGHOSTDATABLOCK *)(sbptr->dataptr); |
| | 504 | |
| | 505 | if(ghostData) |
| | 506 | { |
| | 507 | if(ghostData->myGunFlash) |
| | 508 | DestroyActiveObject(&ghostData->myGunFlash); |
| | 509 | |
| | 510 | if(ghostData->SoundHandle != SOUND_NOACTIVEINDEX) |
| | 511 | Sound_Stop(ghostData->SoundHandle); |
| | 512 | |
| | 513 | if(ghostData->SoundHandle2 != SOUND_NOACTIVEINDEX) |
| | 514 | Sound_Stop(ghostData->SoundHandle2); |
| | 515 | |
| | 516 | if(ghostData->SoundHandle3 != SOUND_NOACTIVEINDEX) |
| | 517 | Sound_Stop(ghostData->SoundHandle3); |
| | 518 | |
| | 519 | Dispel_HModel(&ghostData->HModelController); |
| | 520 | } |
| | 521 | } |
| | 522 | break; |
| | 523 | case I_BehaviourXenoborgMorphRoom: |
| | 524 | { |
| | 525 | XENO_MORPH_ROOM_DATA * xmrd = (XENO_MORPH_ROOM_DATA *)sbptr->dataptr; |
| | 526 | |
| | 527 | if(xmrd) |
| | 528 | { |
| | 529 | if (sbptr->morphctrl && sbptr->morphctrl->ObMorphHeader && sbptr->morphctrl->ObMorphHeader->mph_frames) |
| | 530 | { |
| | 531 | free(sbptr->morphctrl->ObMorphHeader->mph_frames); |
| | 532 | free(sbptr->morphctrl->ObMorphHeader); |
| | 533 | free(sbptr->morphctrl); |
| | 534 | } |
| | 535 | |
| | 536 | if (xmrd->tacb) |
| | 537 | { |
| | 538 | TXACTRLBLK *txactrl_next = xmrd->tacb; |
| | 539 | |
| | 540 | while(txactrl_next) |
| | 541 | { |
| | 542 | TXACTRLBLK *txactrl = txactrl_next; |
| | 543 | txactrl_next = txactrl->tac_next; |
| | 544 | free((void*)txactrl); |
| | 545 | } |
| | 546 | } |
| | 547 | } |
| | 548 | } |
| | 549 | break; |
| | 550 | case I_BehaviourSpeargunBolt: |
| | 551 | { |
| | 552 | SPEAR_BEHAV_BLOCK *sbblk = (SPEAR_BEHAV_BLOCK *)sbptr->dataptr; |
| | 553 | |
| | 554 | /* There's a hierarchy to dispel. */ |
| | 555 | if (sbblk->SpearThroughFragment) |
| | 556 | Dispel_HModel(&sbblk->HierarchicalFragment); |
| | 557 | } |
| | 558 | break; |
| | 559 | case I_BehaviourFan: |
| | 560 | { |
| | 561 | FAN_BEHAV_BLOCK* f_bhv = (FAN_BEHAV_BLOCK*)sbptr->dataptr; |
| | 562 | |
| | 563 | if(f_bhv->track) |
| | 564 | Reset_Track(f_bhv->track); |
| | 565 | } |
| | 566 | break; |
| | 567 | case I_BehaviourAutoGun: |
| | 568 | { |
| | 569 | AUTOGUN_STATUS_BLOCK *ag_bhv = (AUTOGUN_STATUS_BLOCK*)(sbptr->dataptr); |
| | 570 | |
| | 571 | if (ag_bhv) |
| | 572 | { |
| | 573 | /* patrick 7/7/97*/ |
| | 574 | if(ag_bhv->soundHandle != SOUND_NOACTIVEINDEX) |
| | 575 | Sound_Stop(ag_bhv->soundHandle); |
| | 576 | |
| | 577 | Dispel_HModel(&ag_bhv->HModelController); |
| | 578 | } |
| | 579 | } |
| | 580 | break; |
| | 581 | case I_BehaviourDummy: |
| | 582 | { |
| | 583 | DUMMY_STATUS_BLOCK *dummyStatusPointer = (DUMMY_STATUS_BLOCK *)(sbptr->dataptr); |
| | 584 | |
| | 585 | if(dummyStatusPointer) |
| | 586 | Dispel_HModel(&dummyStatusPointer->HModelController); |
| | 587 | } |
| | 588 | break; |
| | 589 | case I_BehaviourPlacedSound: |
| | 590 | { |
| | 591 | SOUND_BEHAV_BLOCK * sbb = (SOUND_BEHAV_BLOCK*)sbptr->dataptr; |
| | 592 | |
| | 593 | if (sbb->activ_no != SOUND_NOACTIVEINDEX) |
| | 594 | Sound_Stop(sbb->activ_no); |
| | 595 | |
| | 596 | if (sbb->wav_name) |
| | 597 | free (sbb->wav_name); |
| | 598 | } |
| | 599 | break; |
| | 600 | case I_BehaviourMissionComplete: |
| | 601 | { |
| | 602 | MISSION_COMPLETE_BEHAV_BLOCK *mc_bhv = (MISSION_COMPLETE_BEHAV_BLOCK*)sbptr->dataptr; |
| | 603 | if(mc_bhv) |
| | 604 | { |
| | 605 | assert((mc_bhv->bhvr_type == I_BehaviourMissionComplete)); |
| | 606 | ResetMission(mc_bhv->mission_objective_ptr); |
| | 607 | } |
| | 608 | } |
| | 609 | break; |
| | 610 | case I_BehaviourTrackObject: |
| | 611 | { |
| | 612 | TRACK_OBJECT_BEHAV_BLOCK *to_bhv = (TRACK_OBJECT_BEHAV_BLOCK*)(sbptr->dataptr); |
| | 613 | |
| | 614 | if (to_bhv) |
| | 615 | { |
| | 616 | assert(to_bhv->bhvr_type == I_BehaviourTrackObject); |
| | 617 | |
| | 618 | if(to_bhv->to_track) |
| | 619 | Reset_Track(to_bhv->to_track); |
| | 620 | |
| | 621 | TXACTRLBLK *txactrl_next = to_bhv->to_tac; |
| | 622 | |
| | 623 | while(txactrl_next) |
| | 624 | { |
| | 625 | TXACTRLBLK *txactrl = txactrl_next; |
| | 626 | txactrl_next = txactrl->tac_next; |
| | 627 | free((void*)txactrl); |
| | 628 | } |
| | 629 | } |
| | 630 | } |
| | 631 | break; |
| | 632 | case I_BehaviourPlacedHierarchy: |
| | 633 | { |
| | 634 | PLACED_HIERARCHY_BEHAV_BLOCK *ph_bhv = (PLACED_HIERARCHY_BEHAV_BLOCK*)(sbptr->dataptr); |
| | 635 | assert(ph_bhv->bhvr_type == I_BehaviourPlacedHierarchy); |
| | 636 | |
| | 637 | if (ph_bhv) |
| | 638 | DeletePlacedHierarchy(ph_bhv); |
| | 639 | } |
| | 640 | break; |
| | 641 | case I_BehaviourParticleGenerator: |
| | 642 | { |
| | 643 | PARTICLE_GENERATOR_BEHAV_BLOCK* pargen = (PARTICLE_GENERATOR_BEHAV_BLOCK*)sbptr->dataptr; |
| | 644 | |
| | 645 | if(pargen->sound) |
| | 646 | Stop_Track_Sound(pargen->sound); |
| | 647 | } |
| | 648 | break; |
| | 649 | case I_BehaviourPlatform: |
| | 650 | { |
| | 651 | PLATFORMLIFT_BEHAVIOUR_BLOCK* pl_bhv = (PLATFORMLIFT_BEHAVIOUR_BLOCK*)sbptr->dataptr; |
| | 652 | |
| | 653 | if(pl_bhv->sound) |
| | 654 | Stop_Track_Sound(pl_bhv->sound); |
| | 655 | |
| | 656 | if(pl_bhv->start_sound) |
| | 657 | Stop_Track_Sound(pl_bhv->start_sound); |
| | 658 | |
| | 659 | if(pl_bhv->end_sound) |
| | 660 | Stop_Track_Sound(pl_bhv->end_sound); |
| | 661 | } |
| | 662 | break; |
| | 663 | case I_BehaviourProximityDoor: |
| | 664 | { |
| | 665 | /* patrick 7/7/97: remove sound handle, if we have one*/ |
| | 666 | PROXDOOR_BEHAV_BLOCK *doorbhv = (PROXDOOR_BEHAV_BLOCK *)(sbptr->dataptr); |
| | 667 | |
| | 668 | if(doorbhv) |
| | 669 | { |
| | 670 | if(doorbhv->SoundHandle != SOUND_NOACTIVEINDEX) |
| | 671 | Sound_Stop(doorbhv->SoundHandle); |
| | 672 | |
| | 673 | if (sbptr->morphctrl && sbptr->morphctrl->ObMorphHeader && sbptr->morphctrl->ObMorphHeader->mph_frames) |
| | 674 | { |
| | 675 | free(sbptr->morphctrl->ObMorphHeader->mph_frames); |
| | 676 | free(sbptr->morphctrl->ObMorphHeader); |
| | 677 | free(sbptr->morphctrl); |
| | 678 | } |
| | 679 | } |
| | 680 | } |
| | 681 | break; |
| | 682 | case I_BehaviourLiftDoor: |
| | 683 | { |
| | 684 | // Deallocater for the doors hack |
| | 685 | /* patrick 7/7/97: remove sound handle, if we have one*/ |
| | 686 | LIFT_DOOR_BEHAV_BLOCK *doorbhv = (LIFT_DOOR_BEHAV_BLOCK *)(sbptr->dataptr); |
| | 687 | |
| | 688 | if(doorbhv) |
| | 689 | { |
| | 690 | if(doorbhv->SoundHandle != SOUND_NOACTIVEINDEX) |
| | 691 | Sound_Stop(doorbhv->SoundHandle); |
| | 692 | |
| | 693 | if (sbptr->morphctrl && sbptr->morphctrl->ObMorphHeader && sbptr->morphctrl->ObMorphHeader->mph_frames) |
| | 694 | { |
| | 695 | free(sbptr->morphctrl->ObMorphHeader->mph_frames); |
| | 696 | free(sbptr->morphctrl->ObMorphHeader); |
| | 697 | free(sbptr->morphctrl); |
| | 698 | } |
| | 699 | } |
| | 700 | } |
| | 701 | break; |
| | 702 | case I_BehaviourSwitchDoor: |
| | 703 | { |
| | 704 | /* patrick 7/7/97: remove sound handle, if we have one*/ |
| | 705 | SWITCH_DOOR_BEHAV_BLOCK *doorbhv = (SWITCH_DOOR_BEHAV_BLOCK *)(sbptr->dataptr); |
| | 706 | |
| | 707 | if(doorbhv) |
| | 708 | { |
| | 709 | if(doorbhv->SoundHandle != SOUND_NOACTIVEINDEX) |
| | 710 | Sound_Stop(doorbhv->SoundHandle); |
| | 711 | |
| | 712 | if (sbptr->morphctrl && sbptr->morphctrl->ObMorphHeader && sbptr->morphctrl->ObMorphHeader->mph_frames) |
| | 713 | { |
| | 714 | free(sbptr->morphctrl->ObMorphHeader->mph_frames); |
| | 715 | free(sbptr->morphctrl->ObMorphHeader); |
| | 716 | free(sbptr->morphctrl); |
| | 717 | } |
| | 718 | } |
| | 719 | } |
| | 720 | break; |
| | 721 | case I_BehaviourSimpleAnimation: |
| | 722 | { |
| | 723 | SIMPLE_ANIM_BEHAV_BLOCK *sanimbhv = (SIMPLE_ANIM_BEHAV_BLOCK*)(sbptr->dataptr); |
| | 724 | |
| | 725 | if (sanimbhv) |
| | 726 | { |
| | 727 | assert(sanimbhv->bhvr_type == I_BehaviourSimpleAnimation); |
| | 728 | |
| | 729 | TXACTRLBLK *txactrl_next = sanimbhv->tacbSimple; |
| | 730 | |
| | 731 | while(txactrl_next) |
| | 732 | { |
| | 733 | TXACTRLBLK *txactrl = txactrl_next; |
| | 734 | txactrl_next = txactrl->tac_next; |
| | 735 | free((void*)txactrl); |
| | 736 | } |
| | 737 | } |
| | 738 | } |
| | 739 | break; |
| | 740 | case I_BehaviourBinarySwitch: |
| | 741 | { |
| | 742 | BINARY_SWITCH_BEHAV_BLOCK *bs_bhv = (BINARY_SWITCH_BEHAV_BLOCK*)(sbptr->dataptr); |
| | 743 | |
| | 744 | if (bs_bhv) |
| | 745 | { |
| | 746 | assert(bs_bhv->bhvr_type == I_BehaviourBinarySwitch); |
| | 747 | |
| | 748 | /* Andy 20/8/97: remove sound handle, if we have one*/ |
| | 749 | if(bs_bhv->soundHandle != SOUND_NOACTIVEINDEX) |
| | 750 | Sound_Stop(bs_bhv->soundHandle); |
| | 751 | |
| | 752 | if(bs_bhv->bs_track) |
| | 753 | Reset_Track(bs_bhv->bs_track); |
| | 754 | |
| | 755 | TXACTRLBLK *txactrl_next = bs_bhv->bs_tac; |
| | 756 | |
| | 757 | while(txactrl_next) |
| | 758 | { |
| | 759 | TXACTRLBLK *txactrl = txactrl_next; |
| | 760 | txactrl_next = txactrl->tac_next; |
| | 761 | free((void*)txactrl); |
| | 762 | } |
| | 763 | |
| | 764 | if(bs_bhv->num_targets) |
| | 765 | { |
| | 766 | if (bs_bhv->target_names) |
| | 767 | free (bs_bhv->target_names); |
| | 768 | |
| | 769 | if (bs_bhv->bs_targets) |
| | 770 | free (bs_bhv->bs_targets); |
| | 771 | |
| | 772 | if (bs_bhv->request_messages) |
| | 773 | free(bs_bhv->request_messages); |
| | 774 | } |
| | 775 | } |
| | 776 | } |
| | 777 | break; |
| | 778 | case I_BehaviourLinkSwitch: |
| | 779 | { |
| | 780 | LINK_SWITCH_BEHAV_BLOCK *bs_bhv = (LINK_SWITCH_BEHAV_BLOCK*)(sbptr->dataptr); |
| | 781 | |
| | 782 | if (bs_bhv) |
| | 783 | { |
| | 784 | assert(bs_bhv->bhvr_type == I_BehaviourLinkSwitch); |
| | 785 | |
| | 786 | /* Andy 20/8/97: remove sound handle, if we have one*/ |
| | 787 | if(bs_bhv->soundHandle != SOUND_NOACTIVEINDEX) |
| | 788 | Sound_Stop(bs_bhv->soundHandle); |
| | 789 | |
| | 790 | if(bs_bhv->ls_track) |
| | 791 | Reset_Track(bs_bhv->ls_track); |
| | 792 | |
| | 793 | TXACTRLBLK *txactrl_next = bs_bhv->ls_tac; |
| | 794 | |
| | 795 | while(txactrl_next) |
| | 796 | { |
| | 797 | TXACTRLBLK *txactrl = txactrl_next; |
| | 798 | txactrl_next = txactrl->tac_next; |
| | 799 | free((void*)txactrl); |
| | 800 | } |
| | 801 | |
| | 802 | if (bs_bhv->ls_targets) |
| | 803 | free ((void *)bs_bhv->ls_targets); |
| | 804 | |
| | 805 | if (bs_bhv->lswitch_list) |
| | 806 | free ((void *)bs_bhv->lswitch_list); |
| | 807 | } |
| | 808 | } |
| | 809 | break; |
| | 810 | case I_BehaviourLift: |
| | 811 | { |
| | 812 | LIFT_BEHAV_BLOCK *lift_bhv = (LIFT_BEHAV_BLOCK*)(sbptr->dataptr); |
| | 813 | |
| | 814 | if (lift_bhv && lift_bhv->controller) |
| | 815 | { |
| | 816 | if(lift_bhv->lift_control->SoundHandle != SOUND_NOACTIVEINDEX) |
| | 817 | Sound_Stop(lift_bhv->lift_control->SoundHandle); |
| | 818 | |
| | 819 | if (lift_bhv->lift_control) |
| | 820 | { |
| | 821 | free(lift_bhv->lift_control); |
| | 822 | |
| | 823 | if (lift_bhv->lift_control->lift_stations) |
| | 824 | free(lift_bhv->lift_control->lift_stations); |
| | 825 | } |
| | 826 | } |
| | 827 | } |
| | 828 | break; |
| | 829 | case I_BehaviourMarinePlayer: |
| | 830 | case I_BehaviourAlienPlayer: |
| | 831 | case I_BehaviourPredatorPlayer: |
| | 832 | Dispel_HModel(sbptr->DisplayBlock->HModelControlBlock); |
| | 833 | DestroyActiveObject(&sbptr->DisplayBlock); |
| | 834 | DeallocateDynamicsBlock(sbptr->DynPtr); |
| | 835 | DestroyActiveStrategyBlock(sbptr); |
| | 836 | return; |
| | 837 | default: |
| | 838 | break; |
| | 839 | } |
| | 840 | |
| | 841 | free(sbptr->dataptr); |
| | 842 | sbptr->dataptr = NULL; |
| | 843 | |
| | 844 | if (sbptr->DisplayBlock) |
| | 845 | DestroyActiveObject(&sbptr->DisplayBlock); |
| | 846 | |
| | 847 | if (sbptr->DynPtr) |
| | 848 | DeallocateDynamicsBlock(sbptr->DynPtr); |
| | 849 | |
| | 850 | DestroyActiveStrategyBlock(sbptr); |
| | 851 | } |
| | 852 | |
| | 853 | static void DoorProxBehaveInit(void* bhdata, STRATEGYBLOCK* sbptr) |
| | 854 | { |
| | 855 | MODULE * my_mod; |
| | 856 | |
| | 857 | PROXDOOR_BEHAV_BLOCK *doorbhv = sbptr->dataptr = malloc(sizeof(PROXDOOR_BEHAV_BLOCK)); |
| | 858 | MORPHCTRL* morphctrl = malloc(sizeof(MORPHCTRL)); |
| | 859 | MORPHHEADER* morphheader = malloc(sizeof(MORPHHEADER)); |
| | 860 | MORPHFRAME* morphframe = malloc(sizeof(MORPHFRAME)); |
| | 861 | |
| | 862 | if((NULL == doorbhv) || (NULL == morphctrl) || (NULL == morphheader) || (NULL == morphframe)) |
| | 863 | { |
| | 864 | free(morphctrl); |
| | 865 | free(morphheader); |
| | 866 | free(morphframe); |
| | 867 | RemoveBehaviourStrategy(sbptr); |
| | 868 | return; |
| | 869 | } |
| | 870 | |
| | 871 | doorbhv->bhvr_type = I_BehaviourProximityDoor; |
| | 872 | |
| | 873 | PROX_DOOR_TOOLS_TEMPLATE *doortt = (PROX_DOOR_TOOLS_TEMPLATE*)bhdata; |
| | 874 | |
| | 875 | morphframe->mf_shape1 = doortt->shape_open; |
| | 876 | morphframe->mf_shape2 = doortt->shape_closed; |
| | 877 | |
| | 878 | morphheader->mph_numframes = 1; |
| | 879 | morphheader->mph_maxframes = ONE_FIXED; |
| | 880 | morphheader->mph_frames = morphframe; |
| | 881 | |
| | 882 | morphctrl->ObMorphCurrFrame = 0; |
| | 883 | morphctrl->ObMorphFlags = 0; |
| | 884 | morphctrl->ObMorphSpeed = 0; |
| | 885 | morphctrl->ObMorphHeader = morphheader; |
| | 886 | |
| | 887 | // Copy the name over |
| | 888 | COPY_NAME (sbptr->SBname, doortt->nameID); |
| | 889 | |
| | 890 | // Setup module ref |
| | 891 | { |
| | 892 | MREF mref = doortt->my_module; |
| | 893 | ConvertModuleNameToPointer (&mref, MainScene.sm_marray); |
| | 894 | my_mod = mref.mref_ptr; |
| | 895 | } |
| | 896 | assert (my_mod); |
| | 897 | |
| | 898 | my_mod->m_sbptr = sbptr; |
| | 899 | sbptr->moptr = my_mod; |
| | 900 | |
| | 901 | doorbhv->PDmctrl = morphctrl; |
| | 902 | doorbhv->lockable_door = doortt->has_lock_target; |
| | 903 | |
| | 904 | doorbhv->door_opening_speed = doortt->door_opening_speed; |
| | 905 | doorbhv->door_closing_speed = doortt->door_closing_speed; |
| | 906 | |
| | 907 | if(doortt->has_lock_target) |
| | 908 | { |
| | 909 | COPY_NAME(doorbhv->target_name, doortt->target_name); |
| | 910 | } |
| | 911 | |
| | 912 | sbptr->morphctrl = doorbhv->PDmctrl; |
| | 913 | sbptr->morphctrl->ObMorphCurrFrame = 1; /* this should be closed*/ |
| | 914 | |
| | 915 | doorbhv->door_state = I_door_closed; |
| | 916 | CloseDoor(sbptr->morphctrl, DOOR_CLOSEFASTSPEED); |
| | 917 | |
| | 918 | //sbptr->moptr->m_flags |= m_flag_open; |
| | 919 | //sbptr->moptr->m_flags &= ~m_flag_open; |
| | 920 | |
| | 921 | /*-----------Patrick 9/12/96-------------- |
| | 922 | a little addition... |
| | 923 | -----------------------------------------*/ |
| | 924 | doorbhv->alienTrigger = 0; |
| | 925 | doorbhv->marineTrigger = 0; |
| | 926 | doorbhv->Timer = 0; |
| | 927 | doorbhv->door_locked = doortt->door_is_locked; |
| | 928 | doorbhv->SoundHandle = SOUND_NOACTIVEINDEX; |
| | 929 | |
| | 930 | { |
| | 931 | // Work out the door sound pitch |
| | 932 | |
| | 933 | int maxX = mainshapelist[morphframe->mf_shape2]->shapemaxx; |
| | 934 | int maxY = mainshapelist[morphframe->mf_shape2]->shapemaxy; |
| | 935 | int maxZ = mainshapelist[morphframe->mf_shape2]->shapemaxz; |
| | 936 | |
| | 937 | int doorSize = maxX + maxY + maxZ; |
| | 938 | |
| | 939 | if (doorSize < 3000) |
| | 940 | doorSize = 3000; |
| | 941 | else if (doorSize > 8000) |
| | 942 | doorSize = 8000; |
| | 943 | |
| | 944 | doorbhv->doorType = (3000 - doorSize) >> 4; |
| | 945 | } |
| | 946 | } |
| | 947 | |
| | 948 | static void SimpleAnimationBehaveInit(void* bhdata, STRATEGYBLOCK* sbptr) |
| | 949 | { |
| | 950 | /**RWH 10/12/96 *************************************** |
| | 951 | |
| | 952 | Simple Animation intialistation. This will set up an array |
| | 953 | of texture control blocks. Each textures controlblock will animate only |
| | 954 | one sequence per polygon. |
| | 955 | |
| | 956 | ***********************************************************/ |
| | 957 | |
| | 958 | int item_num; |
| | 959 | SIMPLE_ANIM_TOOLS_TEMPLATE * satt = (SIMPLE_ANIM_TOOLS_TEMPLATE *)bhdata; |
| | 960 | struct shapeheader* shptr = mainshapelist[sbptr->shapeIndex]; |
| | 961 | MODULE * my_mod; |
| | 962 | |
| | 963 | assert(shptr); |
| | 964 | assert(shptr->numitems > 0); |
| | 965 | |
| | 966 | SIMPLE_ANIM_BEHAV_BLOCK *sabhv = malloc(sizeof(SIMPLE_ANIM_BEHAV_BLOCK)); |
| | 967 | |
| | 968 | if(!sabhv) |
| | 969 | { |
| | 970 | RemoveBehaviourStrategy(sbptr); |
| | 971 | return; |
| | 972 | } |
| | 973 | |
| | 974 | sbptr->dataptr = sabhv; |
| | 975 | |
| | 976 | sabhv->bhvr_type = I_BehaviourSimpleAnimation; |
| | 977 | |
| | 978 | // Copy the name over |
| | 979 | COPY_NAME (sbptr->SBname, satt->nameID); |
| | 980 | |
| | 981 | // Setup module ref |
| | 982 | |
| | 983 | if ('\0' != satt->my_module.mref_name[0]) |
| | 984 | { |
| | 985 | MREF mref = satt->my_module; |
| | 986 | ConvertModuleNameToPointer(&mref, MainScene.sm_marray); |
| | 987 | my_mod = mref.mref_ptr; |
| | 988 | |
| | 989 | assert (my_mod); |
| | 990 | |
| | 991 | my_mod->m_sbptr = sbptr; |
| | 992 | sbptr->moptr = my_mod; |
| | 993 | } |
| | 994 | |
| | 995 | /* |
| | 996 | we need to reserve the address of where we |
| | 997 | are going to place the new animation ctrl block. |
| | 998 | |
| | 999 | this is so that we can call the texture animation builder |
| | 1000 | in the below loop |
| | 1001 | */ |
| | 1002 | |
| | 1003 | TXACTRLBLK **pptxactrlblk = &sabhv->tacbSimple; |
| | 1004 | |
| | 1005 | /* |
| | 1006 | the bhdata is a ptr to the struct shapeheader each |
| | 1007 | animating polygon has an array of sequences, in |
| | 1008 | this case thers is only onr sequence per array |
| | 1009 | */ |
| | 1010 | |
| | 1011 | for(item_num = 0; item_num < shptr->numitems; item_num ++) |
| | 1012 | { |
| | 1013 | POLYHEADER *poly = (POLYHEADER*)(shptr->items[item_num]); |
| | 1014 | assert(poly); |
| | 1015 | |
| | 1016 | if(poly->PolyFlags & iflag_txanim) |
| | 1017 | { |
| | 1018 | TXACTRLBLK *pnew_txactrlblk = malloc(sizeof(TXACTRLBLK)); |
| | 1019 | |
| | 1020 | if (pnew_txactrlblk) |
| | 1021 | { |
| | 1022 | pnew_txactrlblk->tac_flags = 0; |
| | 1023 | pnew_txactrlblk->tac_item = item_num; |
| | 1024 | pnew_txactrlblk->tac_sequence = 0; |
| | 1025 | pnew_txactrlblk->tac_node = 0; |
| | 1026 | pnew_txactrlblk->tac_txarray = GetTxAnimArrayZ(sbptr->shapeIndex, item_num); |
| | 1027 | pnew_txactrlblk->tac_txah_s = GetTxAnimHeaderFromShape(pnew_txactrlblk, sbptr->shapeIndex); |
| | 1028 | |
| | 1029 | /* set the flags in the animation header */ |
| | 1030 | |
| | 1031 | /* KJL 17:00:38 04/04/97 - ChrisF complained about the next line, so |
| | 1032 | I've turned it off to see if anything happens. */ |
| | 1033 | /*pnew_txactrlblk->tac_txah.txa_flags = txa_flag_play; */ |
| | 1034 | |
| | 1035 | /* |
| | 1036 | change the value held in pptxactrlblk |
| | 1037 | which point to the previous structures "next" pointer |
| | 1038 | */ |
| | 1039 | |
| | 1040 | *pptxactrlblk = pnew_txactrlblk; |
| | 1041 | pptxactrlblk = &pnew_txactrlblk->tac_next; |
| | 1042 | } |
| | 1043 | else |
| | 1044 | { |
| | 1045 | memoryInitialisationFailure = 1; |
| | 1046 | } |
| | 1047 | } |
| | 1048 | } |
| | 1049 | |
| | 1050 | *pptxactrlblk = 0; |
| | 1051 | } |
| | 1052 | |
| | 1053 | /*-----------------------Patrick 16/1/97--------------------------- |
| | 1054 | Inanimate object initialisation and behaviour and functions. |
| | 1055 | -------------------------------------------------------------------*/ |
| | 1056 | static void InitInanimateObject(void* bhdata, STRATEGYBLOCK *sbPtr) |
| | 1057 | { |
| | 1058 | TOOLS_DATA_INANIMATEOBJECT *toolsData = (TOOLS_DATA_INANIMATEOBJECT *)bhdata; |
| | 1059 | INANIMATEOBJECT_STATUSBLOCK* objectstatusptr = sbPtr->dataptr = malloc(sizeof(INANIMATEOBJECT_STATUSBLOCK)); |
| | 1060 | DYNAMICSBLOCK *dynPtr = sbPtr->DynPtr = AllocateDynamicsBlock(DYNAMICS_TEMPLATE_STATIC); |
| | 1061 | int i; |
| | 1062 | |
| | 1063 | if((NULL == dynPtr) || (NULL == objectstatusptr)) |
| | 1064 | { |
| | 1065 | RemoveBehaviourStrategy(sbPtr); |
| | 1066 | return; |
| | 1067 | } |
| | 1068 | |
| | 1069 | sbPtr->maintainVisibility = 1; |
| | 1070 | objectstatusptr->respawnTimer = 0; |
| | 1071 | objectstatusptr->lifespanTimer = 0; |
| | 1072 | objectstatusptr->explosionTimer = 0; |
| | 1073 | |
| | 1074 | /* these should be loaded */ |
| | 1075 | objectstatusptr->typeId = toolsData->typeId; |
| | 1076 | objectstatusptr->subType = toolsData->subType; |
| | 1077 | objectstatusptr->ghosted_object = 0; |
| | 1078 | objectstatusptr->event_target = NULL; |
| | 1079 | |
| | 1080 | { |
| | 1081 | const NPC_DATA *NpcData = &NpcDataList[I_NPC_DefaultInanimate]; |
| | 1082 | |
| | 1083 | sbPtr->DamageBlock = NpcData->StartingStats; |
| | 1084 | sbPtr->DamageBlock.Health = NpcData->StartingStats.Health << ONE_FIXED_SHIFT; |
| | 1085 | sbPtr->DamageBlock.Armour = NpcData->StartingStats.Armour << ONE_FIXED_SHIFT; |
| | 1086 | } |
| | 1087 | |
| | 1088 | sbPtr->DamageBlock.Health *= toolsData->integrity; |
| | 1089 | sbPtr->DamageBlock.Indestructable = (toolsData->integrity > 20); |
| | 1090 | |
| | 1091 | if(toolsData->triggering_event) |
| | 1092 | { |
| | 1093 | objectstatusptr->event_target = malloc(sizeof(OBJECT_EVENT_TARGET)); |
| | 1094 | objectstatusptr->event_target->triggering_event = toolsData->triggering_event; |
| | 1095 | objectstatusptr->event_target->request = toolsData->event_request; |
| | 1096 | objectstatusptr->event_target->event_target_sbptr = 0; |
| | 1097 | |
| | 1098 | for(i=0; i < SB_NAME_LENGTH; i++) |
| | 1099 | objectstatusptr->event_target->event_target_ID[i] = toolsData->event_target_ID[i]; |
| | 1100 | } |
| | 1101 | |
| | 1102 | objectstatusptr->explosionType = toolsData->explosionType; |
| | 1103 | |
| | 1104 | dynPtr->IsStatic = 0; |
| | 1105 | dynPtr->PrevPosition = dynPtr->Position = toolsData->position; |
| | 1106 | dynPtr->OrientEuler = toolsData->orientation; |
| | 1107 | |
| | 1108 | CreateEulerMatrix(&dynPtr->OrientEuler, &dynPtr->OrientMat); |
| | 1109 | TransposeMatrixCH(&dynPtr->OrientMat); |
| | 1110 | sbPtr->containingModule = ModuleFromPosition(&dynPtr->Position, NULL); |
| | 1111 | |
| | 1112 | if(NULL == sbPtr->containingModule) |
| | 1113 | { |
| | 1114 | printf("no containing module for %d\n", sbPtr->type); |
| | 1115 | RemoveBehaviourStrategy(sbPtr); |
| | 1116 | return; |
| | 1117 | } |
| | 1118 | |
| | 1119 | switch(objectstatusptr->typeId) |
| | 1120 | { |
| | 1121 | case IOT_Static: |
| | 1122 | { |
| | 1123 | if(NULL != sbPtr->name) |
| | 1124 | { |
| | 1125 | if(!strncmp(sbPtr->name, "switch", 6)) |
| | 1126 | { |
| | 1127 | dynPtr->IsStatic = 1; |
| | 1128 | } |
| | 1129 | else if(!strncmp(sbPtr->name, "Shelf", 5)) |
| | 1130 | { |
| | 1131 | sbPtr->DamageBlock.Indestructable = 0; |
| | 1132 | dynPtr->GravityOn = 0; |
| | 1133 | dynPtr->IsNetGhost = 1; |
| | 1134 | } |
| | 1135 | else |
| | 1136 | { |
| | 1137 | dynPtr->GravityOn = 0; |
| | 1138 | } |
| | 1139 | } |
| | 1140 | else |
| | 1141 | { |
| | 1142 | dynPtr->IsNetGhost = 1; |
| | 1143 | } |
| | 1144 | } // no break; |
| | 1145 | case IOT_HitMeAndIllDestroyBase: |
| | 1146 | { |
| | 1147 | sbPtr->DynPtr->Mass = toolsData->mass; |
| | 1148 | } |
| | 1149 | break; |
| | 1150 | case IOT_Furniture: |
| | 1151 | { |
| | 1152 | dynPtr->Elasticity = 16384; |
| | 1153 | dynPtr->IsStatic = 0; |
| | 1154 | //dynPtr->IsInanimate = 1; |
| | 1155 | dynPtr->Mass = toolsData->mass; |
| | 1156 | dynPtr->Mass = 10; |
| | 1157 | } |
| | 1158 | break; |
| | 1159 | case IOT_Weapon: |
| | 1160 | { |
| | 1161 | dynPtr->Elasticity = 16384; |
| | 1162 | dynPtr->Mass = 10; |
| | 1163 | dynPtr->ToppleForce = TOPPLE_FORCE_FULL; |
| | 1164 | dynPtr->GravityOn = 0; |
| | 1165 | dynPtr->IsStatic = 0; |
| | 1166 | dynPtr->IsPickupObject = 1; |
| | 1167 | |
| | 1168 | //flamethrowers explode using a molotov explosion |
| | 1169 | //if(objectstatusptr->subType == WEAPON_FLAMETHROWER) |
| | 1170 | // need to be smartgun since WEAPON_AUTOSHOTGUN and WEAPON_PLASMAGUN was removed |
| | 1171 | if(objectstatusptr->subType == WEAPON_SADAR) // is really WEAPON_FLAMETHROWER |
| | 1172 | objectstatusptr->explosionType = 3; |
| | 1173 | } |
| | 1174 | break; |
| | 1175 | case IOT_Ammo: |
| | 1176 | { |
| | 1177 | dynPtr->Elasticity = 16384; |
| | 1178 | dynPtr->Mass = 10; |
| | 1179 | dynPtr->ToppleForce = TOPPLE_FORCE_FULL; |
| | 1180 | dynPtr->GravityOn = 0; |
| | 1181 | dynPtr->IsStatic = 0; |
| | 1182 | dynPtr->IsPickupObject = 1; |
| | 1183 | |
| | 1184 | //flamethrowers explode using a molotov explosion |
| | 1185 | if(objectstatusptr->subType == AMMO_FLAMETHROWER) |
| | 1186 | objectstatusptr->explosionType = 3; |
| | 1187 | } |
| | 1188 | break; |
| | 1189 | case IOT_Health: |
| | 1190 | case IOT_Armour: |
| | 1191 | case IOT_FieldCharge: |
| | 1192 | case IOT_SpecialPickupObject: |
| | 1193 | case IOT_Key: |
| | 1194 | { |
| | 1195 | dynPtr->Elasticity = 16384; |
| | 1196 | dynPtr->Mass = 3; |
| | 1197 | dynPtr->ToppleForce = TOPPLE_FORCE_FULL; |
| | 1198 | dynPtr->GravityOn = 0; |
| | 1199 | dynPtr->IsStatic = 0; |
| | 1200 | dynPtr->IsPickupObject = 1; |
| | 1201 | } |
| | 1202 | default: |
| | 1203 | break; |
| | 1204 | } |
| | 1205 | |
| | 1206 | /*check to see if object is animated.*/ |
| | 1207 | { |
| | 1208 | int item_num = 0; |
| | 1209 | struct shapeheader* shptr = mainshapelist[sbPtr->shapeIndex]; |
| | 1210 | TXACTRLBLK **pptxactrlblk = &objectstatusptr->inan_tac; |
| | 1211 | |
| | 1212 | for(; item_num < shptr->numitems; item_num++) |
| | 1213 | { |
| | 1214 | POLYHEADER *poly = (POLYHEADER*)(shptr->items[item_num]); |
| | 1215 | assert(poly); |
| | 1216 | |
| | 1217 | if(poly->PolyFlags & iflag_txanim) |
| | 1218 | { |
| | 1219 | TXACTRLBLK *pnew_txactrlblk = malloc(sizeof(TXACTRLBLK)); |
| | 1220 | |
| | 1221 | if(pnew_txactrlblk) |
| | 1222 | { |
| | 1223 | pnew_txactrlblk->tac_flags = 0; |
| | 1224 | pnew_txactrlblk->tac_item = item_num; |
| | 1225 | pnew_txactrlblk->tac_sequence = 0; |
| | 1226 | pnew_txactrlblk->tac_node = 0; |
| | 1227 | pnew_txactrlblk->tac_txarray = GetTxAnimArrayZ(sbPtr->shapeIndex, item_num); |
| | 1228 | pnew_txactrlblk->tac_txah_s = GetTxAnimHeaderFromShape(pnew_txactrlblk, sbPtr->shapeIndex); |
| | 1229 | |
| | 1230 | *pptxactrlblk = pnew_txactrlblk; |
| | 1231 | pptxactrlblk = &pnew_txactrlblk->tac_next; |
| | 1232 | } |
| | 1233 | else |
| | 1234 | *pptxactrlblk = NULL; |
| | 1235 | } |
| | 1236 | } |
| | 1237 | |
| | 1238 | *pptxactrlblk = NULL; |
| | 1239 | } |
| | 1240 | |
| | 1241 | for(i=0; i < SB_NAME_LENGTH; i++) |
| | 1242 | sbPtr->SBname[i] = toolsData->nameID[i]; |
| | 1243 | |
| | 1244 | if(SinglePlayer != AvP.PlayMode) |
| | 1245 | { |
| | 1246 | /* these must be initialised for respawning objects in multiplayer game */ |
| | 1247 | objectstatusptr->startingHealth = sbPtr->DamageBlock.Health; |
| | 1248 | objectstatusptr->startingArmour = sbPtr->DamageBlock.Armour; |
| | 1249 | int remove = 0; |
| | 1250 | |
| | 1251 | //if in a network game , see if this is an allowable weapon |
| | 1252 | switch(objectstatusptr->typeId) |
| | 1253 | { |
| | 1254 | case IOT_Weapon: |
| | 1255 | { |
| | 1256 | switch(objectstatusptr->subType) |
| | 1257 | { |
| | 1258 | case WEAPON_PULSERIFLE: |
| | 1259 | remove = 1; |
| | 1260 | break; |
| | 1261 | case WEAPON_SMARTGUN: |
| | 1262 | remove = netGameData.allowSmartgun; |
| | 1263 | break; |
| | 1264 | case WEAPON_FLAMETHROWER: |
| | 1265 | remove = netGameData.allowFlamer; |
| | 1266 | break; |
| | 1267 | case WEAPON_SADAR: |
| | 1268 | remove = netGameData.allowSadar; |
| | 1269 | break; |
| | 1270 | case WEAPON_GRENADELAUNCHER: |
| | 1271 | remove = netGameData.allowGrenadeLauncher; |
| | 1272 | break; |
| | 1273 | case WEAPON_FRISBEE_LAUNCHER: |
| | 1274 | remove = netGameData.allowSmartDisc; |
| | 1275 | break; |
| | 1276 | case WEAPON_MINIGUN: |
| | 1277 | remove = netGameData.allowMinigun; |
| | 1278 | break; |
| | 1279 | case WEAPON_MARINE_PISTOL: |
| | 1280 | case WEAPON_TWO_PISTOLS: |
| | 1281 | remove = netGameData.allowPistols; |
| | 1282 | break; |
| | 1283 | default: |
| | 1284 | remove = 0; |
| | 1285 | } |
| | 1286 | |
| | 1287 | if (!remove) |
| | 1288 | RemoveBehaviourStrategy(sbPtr); |
| | 1289 | } |
| | 1290 | break; |
| | 1291 | case IOT_Ammo: |
| | 1292 | { |
| | 1293 | switch(objectstatusptr->subType) |
| | 1294 | { |
| | 1295 | case AMMO_SMARTGUN: |
| | 1296 | remove = netGameData.allowSmartgun; |
| | 1297 | break; |
| | 1298 | case AMMO_FLAMETHROWER: |
| | 1299 | remove = netGameData.allowFlamer; |
| | 1300 | break; |
| | 1301 | case AMMO_SADAR_TOW: |
| | 1302 | remove = netGameData.allowSadar; |
| | 1303 | break; |
| | 1304 | case AMMO_GRENADE: |
| | 1305 | remove = netGameData.allowGrenadeLauncher; |
| | 1306 | break; |
| | 1307 | case AMMO_MARINE_PISTOL: |
| | 1308 | remove = netGameData.allowPistols; |
| | 1309 | break; |
| | 1310 | case AMMO_FRISBEE: |
| | 1311 | remove = netGameData.allowSmartDisc; |
| | 1312 | break; |
| | 1313 | case AMMO_MINIGUN: |
| | 1314 | remove = netGameData.allowMinigun; |
| | 1315 | break; |
| | 1316 | default: |
| | 1317 | remove = 0; |
| | 1318 | } |
| | 1319 | |
| | 1320 | if (!remove) |
| | 1321 | RemoveBehaviourStrategy(sbPtr); |
| | 1322 | } |
| | 1323 | default: |
| | 1324 | break; |
| | 1325 | } |
| | 1326 | } |
| | 1327 | } |
| | 1328 | |
| | 1329 | /*---------------------------------------------------------------------- |
| | 1330 | Use this function to initialise binary loaded objects |
| | 1331 | ----------------------------------------------------------------------*/ |
| | 1332 | |
| | 1333 | void EnableBehaviourType(STRATEGYBLOCK* sbptr, void *bhdata) |
| | 1334 | { |
| | 1335 | switch(sbptr->type) |
| | 1336 | { |
| | 1337 | case I_BehaviourAlien: |
| | 1338 | InitAlienBehaviour(bhdata, sbptr); |
| | 1339 | break; |
| | 1340 | case I_BehaviourMarine: |
| | 1341 | InitMarineBehaviour(bhdata, sbptr); |
| | 1342 | break; |
| | 1343 | case I_BehaviourProximityDoor: |
| | 1344 | sbptr->DamageBlock.Indestructable = 1; |
| | 1345 | DoorProxBehaveInit(bhdata, sbptr); |
| | 1346 | break; |
| | 1347 | case I_BehaviourLiftDoor: |
| | 1348 | LiftDoorBehaveInit(bhdata, sbptr); |
| | 1349 | break; |
| | 1350 | case I_BehaviourSwitchDoor: |
| | 1351 | InitialiseSwitchDoor(bhdata, sbptr); |
| | 1352 | break; |
| | 1353 | case I_BehaviourPlatform: |
| | 1354 | sbptr->DamageBlock.Indestructable = 1; |
| | 1355 | InitialisePlatformLift(bhdata, sbptr); |
| | 1356 | break; |
| | 1357 | case I_BehaviourBinarySwitch: |
| | 1358 | sbptr->DamageBlock.Indestructable = 1; |
| | 1359 | BinarySwitchBehaveInit(bhdata, sbptr); |
| | 1360 | break; |
| | 1361 | case I_BehaviourLinkSwitch: |
| | 1362 | LinkSwitchBehaveInit(bhdata, sbptr); |
| | 1363 | break; |
| | 1364 | case I_BehaviourLift: |
| | 1365 | sbptr->DamageBlock.Indestructable = 1; |
| | 1366 | LiftBehaveInit(bhdata, sbptr); |
| | 1367 | break; |
| | 1368 | case I_BehaviourSimpleAnimation: |
| | 1369 | SimpleAnimationBehaveInit(bhdata, sbptr); |
| | 1370 | break; |
| | 1371 | case I_BehaviourGenerator: |
| | 1372 | InitGenerator(bhdata, sbptr); |
| | 1373 | break; |
| | 1374 | case I_BehaviourInanimateObject: |
| | 1375 | InitInanimateObject(bhdata, sbptr); |
| | 1376 | break; |
| | 1377 | case I_BehaviourLightFX: |
| | 1378 | LightFXBehaveInit (bhdata, sbptr); |
| | 1379 | break; |
| | 1380 | case I_BehaviourPlacedSound: |
| | 1381 | SoundBehaveInit(bhdata, sbptr); |
| | 1382 | break; |
| | 1383 | case I_BehaviourMissionComplete: |
| | 1384 | MissionCompleteBehaveInit (bhdata, sbptr); |
| | 1385 | break; |
| | 1386 | case I_BehaviourMessage: |
| | 1387 | MessageBehaveInit (bhdata, sbptr); |
| | 1388 | break; |
| | 1389 | case I_BehaviourTrackObject: |
| | 1390 | //sbptr->DamageBlock.Indestructable = 1; |
| | 1391 | TrackObjectBehaveInit(bhdata, sbptr); |
| | 1392 | break; |
| | 1393 | case I_BehaviourFan: |
| | 1394 | sbptr->DamageBlock.Indestructable = 1; |
| | 1395 | FanBehaveInit(bhdata, sbptr); |
| | 1396 | break; |
| | 1397 | case I_BehaviourPlacedHierarchy: |
| | 1398 | //sbptr->DamageBlock.Indestructable = 1; |
| | 1399 | PlacedHierarchyBehaveInit(bhdata, sbptr); |
| | 1400 | break; |
| | 1401 | case I_BehaviourPlacedLight: |
| | 1402 | InitPlacedLight(bhdata, sbptr); |
| | 1403 | break; |
| | 1404 | case I_BehaviourVideoScreen: |
| | 1405 | InitVideoScreen(bhdata, sbptr); |
| | 1406 | break; |
| | 1407 | case I_BehaviourPowerCable: |
| | 1408 | PowerCableBehaveInit(bhdata, sbptr); |
| | 1409 | break; |
| | 1410 | case I_BehaviourDeathVolume: |
| | 1411 | sbptr->DamageBlock.Indestructable = 1; |
| | 1412 | DeathVolumeBehaveInit(bhdata, sbptr); |
| | 1413 | break; |
| | 1414 | case I_BehaviourSelfDestruct: |
| | 1415 | SelfDestructBehaveInit(bhdata, sbptr); |
| | 1416 | break; |
| | 1417 | case I_BehaviourParticleGenerator: |
| | 1418 | ParticleGeneratorBehaveInit(bhdata, sbptr); |
| | 1419 | break; |
| | 1420 | case I_BehaviourAutoGun: |
| | 1421 | AutoGunBehaveInit(bhdata, sbptr); |
| | 1422 | break; |
| | 1423 | case I_BehaviourFaceHugger: |
| | 1424 | InitFacehuggerBehaviour(bhdata, sbptr); |
| | 1425 | break; |
| | 1426 | case I_BehaviourPredator: |
| | 1427 | InitPredatorBehaviour(bhdata, sbptr); |
| | 1428 | break; |
| | 1429 | case I_BehaviourXenoborg: |
| | 1430 | InitXenoborgBehaviour(bhdata, sbptr); |
| | 1431 | break; |
| | 1432 | case I_BehaviourQueenAlien: |
| | 1433 | InitQueenBehaviour(bhdata, sbptr); |
| | 1434 | break; |
| | 1435 | case I_BehaviourXenoborgMorphRoom: |
| | 1436 | InitXenoMorphRoom (bhdata, sbptr); |
| | 1437 | break; |
| | 1438 | case I_BehaviourDormantPredator: |
| | 1439 | InitDormantPredatorBehaviour(bhdata, sbptr); |
| | 1440 | default: |
| | 1441 | break; |
| | 1442 | } |
| | 1443 | } |
| | 1444 | |
| | 1445 | void AssignAllSBNames() |
| | 1446 | { |
| | 1447 | int stratblock = NumActiveStBlocks; |
| | 1448 | assert(stratblock >= 0); |
| | 1449 | |
| | 1450 | while(--stratblock > 0) |
| | 1451 | { |
| | 1452 | STRATEGYBLOCK* sbptr = ActiveStBlockList[stratblock]; |
| | 1453 | assert(sbptr); |
| | 1454 | |
| | 1455 | switch (sbptr->type) |
| | 1456 | { |
| | 1457 | case I_BehaviourBinarySwitch: |
| | 1458 | { |
| | 1459 | int i = 0; |
| | 1460 | BINARY_SWITCH_BEHAV_BLOCK *bs_bhv = (BINARY_SWITCH_BEHAV_BLOCK*)sbptr->dataptr; |
| | 1461 | assert((bs_bhv->bhvr_type == I_BehaviourBinarySwitch)); |
| | 1462 | |
| | 1463 | for (; i < bs_bhv->num_targets; i++) |
| | 1464 | bs_bhv->bs_targets[i] = FindSBWithName(bs_bhv->target_names[i].name); |
| | 1465 | } |
| | 1466 | break; |
| | 1467 | case I_BehaviourLinkSwitch: |
| | 1468 | { |
| | 1469 | int i=0; |
| | 1470 | LINK_SWITCH_BEHAV_BLOCK *ls_bhv = (LINK_SWITCH_BEHAV_BLOCK*)sbptr->dataptr; |
| | 1471 | assert((ls_bhv->bhvr_type == I_BehaviourLinkSwitch)); |
| | 1472 | |
| | 1473 | for(i=0; i < ls_bhv->num_linked_switches;i++) |
| | 1474 | ls_bhv->lswitch_list[i].bswitch = FindSBWithName(ls_bhv->lswitch_list[i].bs_name); |
| | 1475 | |
| | 1476 | for(i=0;i < ls_bhv->num_targets; i++) |
| | 1477 | ls_bhv->ls_targets[i].sbptr=FindSBWithName(ls_bhv->ls_targets[i].name); |
| | 1478 | } |
| | 1479 | break; |
| | 1480 | case I_BehaviourSwitchDoor: |
| | 1481 | { |
| | 1482 | SWITCH_DOOR_BEHAV_BLOCK *switchDoorBehaviourPtr = (SWITCH_DOOR_BEHAV_BLOCK *)sbptr->dataptr; |
| | 1483 | if(*((int *)switchDoorBehaviourPtr->linkedDoorName) + *( ((int *)switchDoorBehaviourPtr->linkedDoorName)+1 ) ) |
| | 1484 | switchDoorBehaviourPtr->linkedDoorPtr = FindSBWithName(switchDoorBehaviourPtr->linkedDoorName); |
| | 1485 | |
| | 1486 | /* may or may not be linked to another door */ |
| | 1487 | #if DEBUG |
| | 1488 | if(switchDoorBehaviourPtr->linkedDoorPtr) |
| | 1489 | { |
| | 1490 | assert(switchDoorBehaviourPtr->linkedDoorPtr->type == I_BehaviourSwitchDoor); |
| | 1491 | } |
| | 1492 | #endif |
| | 1493 | } |
| | 1494 | break; |
| | 1495 | case I_BehaviourProximityDoor: |
| | 1496 | { |
| | 1497 | PROXDOOR_BEHAV_BLOCK *doorbhv = (PROXDOOR_BEHAV_BLOCK*)sbptr->dataptr; |
| | 1498 | assert((doorbhv->bhvr_type == I_BehaviourProximityDoor)); |
| | 1499 | |
| | 1500 | if(doorbhv->lockable_door) |
| | 1501 | doorbhv->door_lock_target = FindSBWithName(doorbhv->target_name); |
| | 1502 | } |
| | 1503 | break; |
| | 1504 | case I_BehaviourLift: |
| | 1505 | { |
| | 1506 | LIFT_BEHAV_BLOCK *lift_bhv = (LIFT_BEHAV_BLOCK*)sbptr->dataptr; |
| | 1507 | assert((lift_bhv->bhvr_type == I_BehaviourLift)); |
| | 1508 | |
| | 1509 | LIFT_STATION *curr_stn = &lift_bhv->lift_station; |
| | 1510 | assert(curr_stn); |
| | 1511 | |
| | 1512 | curr_stn->lift_call_switch = FindSBWithName(curr_stn->lift_call_switch_name); |
| | 1513 | |
| | 1514 | if((*(int*)&curr_stn->lift_floor_switch_name[0]) || (*(int*)&curr_stn->lift_floor_switch_name[4])) |
| | 1515 | curr_stn->lift_floor_switch = FindSBWithName(curr_stn->lift_floor_switch_name); //lifts with switches that don't teleport,don't know about their
floor switches |
| | 1516 | |
| | 1517 | curr_stn->lift_door = FindSBWithName(curr_stn->lift_door_name); |
| | 1518 | |
| | 1519 | // find my module pointer |
| | 1520 | { |
| | 1521 | STRATEGYBLOCK *my_sb = FindSBWithName(curr_stn->my_sb_name); |
| | 1522 | |
| | 1523 | if (my_sb) |
| | 1524 | curr_stn->lift_module = my_sb->moptr; |
| | 1525 | } |
| | 1526 | |
| | 1527 | // find the controlling lift behave block |
| | 1528 | lift_bhv->control_sb = FindSBWithName(lift_bhv->control_sb_name); |
| | 1529 | |
| | 1530 | assert(lift_bhv->control_sb); |
| | 1531 | /* |
| | 1532 | { |
| | 1533 | //LIFT_STATION **lift_array; |
| | 1534 | LIFT_BEHAV_BLOCK *cont_bhv = lift_bhv->control_sb->dataptr; |
| | 1535 | lift_bhv->lift_control = cont_bhv->lift_control; |
| | 1536 | //lift_array = cont_bhv->lift_control->lift_stations; |
| | 1537 | //lift_array[curr_stn->num_floor] = curr_stn; |
| | 1538 | } |
| | 1539 | */ |
| | 1540 | lift_bhv->lift_control = lift_bhv->control_sb->dataptr; //??? |
| | 1541 | |
| | 1542 | if(curr_stn->starting_station) |
| | 1543 | { |
| | 1544 | // the door on this floor is open |
| | 1545 | // therefore, since we are all perfect |
| | 1546 | // i can say |
| | 1547 | |
| | 1548 | assert(lift_bhv->lift_control->curr_station == -1); |
| | 1549 | |
| | 1550 | lift_bhv->lift_control->curr_station = curr_stn->num_floor; |
| | 1551 | |
| | 1552 | if(curr_stn->lift_call_switch) |
| | 1553 | { |
| | 1554 | // turn on the floor lights |
| | 1555 | RequestState(curr_stn->lift_call_switch, 1, 0); |
| | 1556 | if((*(int*)&curr_stn->lift_floor_switch_name[0]) || (*(int*)&curr_stn->lift_floor_switch_name[4])) |
| | 1557 | RequestState(curr_stn->lift_floor_switch, 1, 0); |
| | 1558 | } |
| | 1559 | } |
| | 1560 | } |
| | 1561 | break; |
| | 1562 | case I_BehaviourXenoborgMorphRoom: |
| | 1563 | { |
| | 1564 | XENO_MORPH_ROOM_DATA * xmrd = (XENO_MORPH_ROOM_DATA *)sbptr->dataptr; |
| | 1565 | |
| | 1566 | assert (xmrd->bhvr_type == I_BehaviourXenoborgMorphRoom); |
| | 1567 | |
| | 1568 | xmrd->DoorToRoom = FindSBWithName(xmrd->doorID); |
| | 1569 | } |
| | 1570 | break; |
| | 1571 | case I_BehaviourAlien: |
| | 1572 | { |
| | 1573 | ALIEN_STATUS_BLOCK *alienStatus = (ALIEN_STATUS_BLOCK *)sbptr->dataptr; |
| | 1574 | alienStatus->death_target_sbptr = FindSBWithName(alienStatus->death_target_ID); |
| | 1575 | } |
| | 1576 | break; |
| | 1577 | case I_BehaviourMarine: |
| | 1578 | { |
| | 1579 | MARINE_STATUS_BLOCK *marineStatus = (MARINE_STATUS_BLOCK *)sbptr->dataptr; |
| | 1580 | marineStatus->death_target_sbptr = FindSBWithName(marineStatus->death_target_ID); |
| | 1581 | } |
| | 1582 | break; |
| | 1583 | case I_BehaviourPredator: |
| | 1584 | { |
| | 1585 | PREDATOR_STATUS_BLOCK *predatorStatus = (PREDATOR_STATUS_BLOCK *)sbptr->dataptr; |
| | 1586 | predatorStatus->death_target_sbptr = FindSBWithName(predatorStatus->death_target_ID); |
| | 1587 | } |
| | 1588 | break; |
| | 1589 | case I_BehaviourXenoborg: |
| | 1590 | { |
| | 1591 | XENO_STATUS_BLOCK *xenoStatus = (XENO_STATUS_BLOCK *)sbptr->dataptr; |
| | 1592 | xenoStatus->death_target_sbptr = FindSBWithName(xenoStatus->death_target_ID); |
| | 1593 | } |
| | 1594 | break; |
| | 1595 | case I_BehaviourAutoGun: |
| | 1596 | { |
| | 1597 | AUTOGUN_STATUS_BLOCK *agunStatus = (AUTOGUN_STATUS_BLOCK *)sbptr->dataptr; |
| | 1598 | agunStatus->death_target_sbptr = FindSBWithName(agunStatus->death_target_ID); |
| | 1599 | } |
| | 1600 | break; |
| | 1601 | case I_BehaviourQueenAlien: |
| | 1602 | { |
| | 1603 | QUEEN_STATUS_BLOCK *queenStatus = (QUEEN_STATUS_BLOCK *)sbptr->dataptr; |
| | 1604 | queenStatus->death_target_sbptr = FindSBWithName(queenStatus->death_target_ID); |
| | 1605 | } |
| | 1606 | break; |
| | 1607 | case I_BehaviourFaceHugger: |
| | 1608 | { |
| | 1609 | FACEHUGGER_STATUS_BLOCK *facehuggerStatus = (FACEHUGGER_STATUS_BLOCK *)sbptr->dataptr; |
| | 1610 | facehuggerStatus->death_target_sbptr = FindSBWithName(facehuggerStatus->death_target_ID); |
| | 1611 | } |
| | 1612 | break; |
| | 1613 | case I_BehaviourTrackObject: |
| | 1614 | { |
| | 1615 | int i=0; |
| | 1616 | TRACK_OBJECT_BEHAV_BLOCK *to_bhv = (TRACK_OBJECT_BEHAV_BLOCK *)sbptr->dataptr; |
| | 1617 | |
| | 1618 | for(; i < to_bhv->num_special_track_points; i++) |
| | 1619 | { |
| | 1620 | int j=0; |
| | 1621 | SPECIAL_TRACK_POINT* stp = &to_bhv->special_track_points[i]; |
| | 1622 | |
| | 1623 | for(; j < stp->num_targets; j++) |
| | 1624 | stp->targets[j].target_sbptr = FindSBWithName(stp->targets[j].target_name); |
| | 1625 | } |
| | 1626 | |
| | 1627 | to_bhv->destruct_target_sbptr = FindSBWithName(to_bhv->destruct_target_ID); |
| | 1628 | } |
| | 1629 | break; |
| | 1630 | case I_BehaviourPlacedHierarchy: |
| | 1631 | { |
| | 1632 | int i = 0; |
| | 1633 | PLACED_HIERARCHY_BEHAV_BLOCK *ph_bhv = (PLACED_HIERARCHY_BEHAV_BLOCK *)sbptr->dataptr; |
| | 1634 | |
| | 1635 | for(; i < ph_bhv->num_special_track_points; i++) |
| | 1636 | { |
| | 1637 | int j = 0; |
| | 1638 | SPECIAL_TRACK_POINT* stp = &ph_bhv->special_track_points[i]; |
| | 1639 | |
| | 1640 | for(; j < stp->num_targets; j++) |
| | 1641 | stp->targets[j].target_sbptr = FindSBWithName(stp->targets[j].target_name); |
| | 1642 | } |
| | 1643 | } |
| | 1644 | break; |
| | 1645 | case I_BehaviourInanimateObject: |
| | 1646 | { |
| | 1647 | INANIMATEOBJECT_STATUSBLOCK* objectstatusptr=(INANIMATEOBJECT_STATUSBLOCK*)sbptr->dataptr; |
| | 1648 | |
| | 1649 | if(objectstatusptr) |
| | 1650 | { |
| | 1651 | if(objectstatusptr->event_target) |
| | 1652 | objectstatusptr->event_target->event_target_sbptr = FindSBWithName(objectstatusptr->event_target->event_target_ID); |
| | 1653 | } |
| | 1654 | } |
| | 1655 | break; |
| | 1656 | case I_BehaviourPlacedLight: |
| | 1657 | { |
| | 1658 | PLACED_LIGHT_BEHAV_BLOCK* pl_bhv = (PLACED_LIGHT_BEHAV_BLOCK*)sbptr->dataptr; |
| | 1659 | |
| | 1660 | if(pl_bhv) |
| | 1661 | pl_bhv->destruct_target_sbptr = FindSBWithName(pl_bhv->destruct_target_ID); |
| | 1662 | } |
| | 1663 | break; |
| | 1664 | case I_BehaviourVideoScreen: |
| | 1665 | { |
| | 1666 | VIDEO_SCREEN_BEHAV_BLOCK* videoScreen = (VIDEO_SCREEN_BEHAV_BLOCK*)sbptr->dataptr; |
| | 1667 | |
| | 1668 | if(videoScreen) |
| | 1669 | videoScreen->destruct_target_sbptr = FindSBWithName(videoScreen->destruct_target_ID); |
| | 1670 | } |
| | 1671 | default: |
| | 1672 | break; |
| | 1673 | } |
| | 1674 | } |
| | 1675 | } |
| | 1676 | |
| | 1677 | #define DOOR_OPENDISTANCE (3000) /* mm */ |
| | 1678 | |
| | 1679 | /*---------------Patrick 6/1/97------------------- |
| | 1680 | Sorry, but I can't think of anything better than |
| | 1681 | searching the entire sb list for any object that |
| | 1682 | might trigger a door.... |
| | 1683 | ------------------------------------------------*/ |
| | 1684 | static int AnythingNearProxDoor(MODULE *doorModulePtr, PROXDOOR_BEHAV_BLOCK *doorbhv) |
| | 1685 | { |
| | 1686 | /* KJL 18:06:59 19/02/98 - I've rewritten this check so that it can cope with very tall doors. */ |
| | 1687 | |
| | 1688 | int i, maxY, minY, maxX, minX, maxZ, minZ; |
| | 1689 | |
| | 1690 | if (doorModulePtr->m_flags & MODULEFLAG_HORIZONTALDOOR) |
| | 1691 | { |
| | 1692 | maxY = doorModulePtr->m_world.vy + DOOR_OPENDISTANCE; |
| | 1693 | minY = doorModulePtr->m_world.vy - DOOR_OPENDISTANCE; |
| | 1694 | maxX = doorModulePtr->m_world.vx + doorModulePtr->m_maxx + DOOR_OPENDISTANCE/2; |
| | 1695 | minX = doorModulePtr->m_world.vx + doorModulePtr->m_minx - DOOR_OPENDISTANCE/2; |
| | 1696 | maxZ = doorModulePtr->m_world.vz + doorModulePtr->m_maxz + DOOR_OPENDISTANCE/2; |
| | 1697 | minZ = doorModulePtr->m_world.vz + doorModulePtr->m_minz - DOOR_OPENDISTANCE/2; |
| | 1698 | } |
| | 1699 | else |
| | 1700 | { |
| | 1701 | maxY = doorModulePtr->m_world.vy + doorModulePtr->m_maxy; |
| | 1702 | minY = doorModulePtr->m_world.vy + doorModulePtr->m_miny; |
| | 1703 | maxX = doorModulePtr->m_world.vx + DOOR_OPENDISTANCE; |
| | 1704 | minX = doorModulePtr->m_world.vx - DOOR_OPENDISTANCE; |
| | 1705 | maxZ = doorModulePtr->m_world.vz + DOOR_OPENDISTANCE; |
| | 1706 | minZ = doorModulePtr->m_world.vz - DOOR_OPENDISTANCE; |
| | 1707 | } |
| | 1708 | |
| | 1709 | /* loop thro' the strategy block list... |
| | 1710 | looking for triggerable objects (please feel free to add any |
| | 1711 | sensible object types) */ |
| | 1712 | int return_value = 0; |
| | 1713 | |
| | 1714 | for(i = 0; i < NumActiveStBlocks; i++) |
| | 1715 | { |
| | 1716 | STRATEGYBLOCK *sbPtr = ActiveStBlockList[i]; |
| | 1717 | |
| | 1718 | if(NULL != sbPtr->DisplayBlock) |
| | 1719 | { |
| | 1720 | switch(sbPtr->type) |
| | 1721 | { |
| | 1722 | case I_BehaviourPlatform: |
| | 1723 | { |
| | 1724 | DYNAMICSBLOCK *dynPtr = sbPtr->DynPtr; |
| | 1725 | |
| | 1726 | if ((dynPtr->Position.vy > minY && dynPtr->Position.vy < maxY) |
| | 1727 | && |
| | 1728 | (dynPtr->Position.vx > minX && dynPtr->Position.vx < maxX) |
| | 1729 | && |
| | 1730 | (dynPtr->Position.vz > minZ && dynPtr->Position.vz < maxZ)) |
| | 1731 | { |
| | 1732 | PLATFORMLIFT_BEHAVIOUR_BLOCK *platformliftdata = (PLATFORMLIFT_BEHAVIOUR_BLOCK *)sbPtr->dataptr; |
| | 1733 | if(PLBS_AtRest != platformliftdata->state) |
| | 1734 | { |
| | 1735 | doorbhv->door_locked = 2; |
| | 1736 | return 0; |
| | 1737 | } |
| | 1738 | else if(2 == doorbhv->door_locked) |
| | 1739 | { |
| | 1740 | doorbhv->door_locked = 0; |
| | 1741 | return 1; |
| | 1742 | } |
| | 1743 | } |
| | 1744 | } |
| | 1745 | case I_BehaviourAlien: |
| | 1746 | case I_BehaviourMarine: |
| | 1747 | case I_BehaviourMarinePlayer: |
| | 1748 | case I_BehaviourPredatorPlayer: |
| | 1749 | case I_BehaviourAlienPlayer: |
| | 1750 | case I_BehaviourPredator: |
| | 1751 | case I_BehaviourXenoborg: |
| | 1752 | case I_BehaviourQueenAlien: |
| | 1753 | case I_BehaviourNetGhost: |
| | 1754 | case I_BehaviourCorpse: |
| | 1755 | //case I_BehaviourHierarchicalFragment: |
| | 1756 | { |
| | 1757 | DYNAMICSBLOCK *dynPtr = sbPtr->DynPtr; |
| | 1758 | |
| | 1759 | if ((dynPtr->Position.vy > minY && dynPtr->Position.vy < maxY) |
| | 1760 | && |
| | 1761 | (dynPtr->Position.vx > minX && dynPtr->Position.vx < maxX) |
| | 1762 | && |
| | 1763 | (dynPtr->Position.vz > minZ && dynPtr->Position.vz < maxZ)) |
| | 1764 | { |
| | 1765 | if (sbPtr->type == I_BehaviourMarine) |
| | 1766 | doorbhv->marineTrigger = 1; |
| | 1767 | |
| | 1768 | return_value = 1; |
| | 1769 | } |
| | 1770 | } |
| | 1771 | default: |
| | 1772 | break; |
| | 1773 | } |
| | 1774 | } |
| | 1775 | } |
| | 1776 | |
| | 1777 | return return_value; |
| | 1778 | } |
| | 1779 | |
| | 1780 | void OpenDoor(MORPHCTRL *mctrl, int speed) |
| | 1781 | { |
| | 1782 | assert(mctrl); |
| | 1783 | |
| | 1784 | mctrl->ObMorphFlags = mph_flag_play | mph_flag_noloop | mph_flag_reverse; |
| | 1785 | mctrl->ObMorphSpeed = speed; |
| | 1786 | } |
| | 1787 | |
| | 1788 | void CloseDoor(MORPHCTRL *mctrl, int speed) |
| | 1789 | { |
| | 1790 | assert(mctrl); |
| | 1791 | |
| | 1792 | mctrl->ObMorphFlags = mph_flag_play | mph_flag_noloop; |
| | 1793 | mctrl->ObMorphFlags &= ~mph_flag_reverse; |
| | 1794 | mctrl->ObMorphSpeed = speed; |
| | 1795 | } |
| | 1796 | |
| | 1797 | static void DoorProxBehaveFun(STRATEGYBLOCK* sbptr) |
| | 1798 | { |
| | 1799 | int open_door = 0; |
| | 1800 | |
| | 1801 | PROXDOOR_BEHAV_BLOCK *doorbhv = (PROXDOOR_BEHAV_BLOCK*)sbptr->dataptr; |
| | 1802 | assert((doorbhv->bhvr_type == I_BehaviourProximityDoor)); |
| | 1803 | MORPHCTRL *mctrl = doorbhv->PDmctrl; |
| | 1804 | assert(mctrl); |
| | 1805 | MODULE *mptr = sbptr->moptr; |
| | 1806 | assert(mptr); |
| | 1807 | DISPLAYBLOCK* dptr = sbptr->DisplayBlock; |
| | 1808 | |
| | 1809 | UpdateMorphing(mctrl); |
| | 1810 | |
| | 1811 | if (!(1 == doorbhv->door_locked) && (I_door_opening != doorbhv->door_state)) |
| | 1812 | { |
| | 1813 | /* if door is visible check for proximity of player, aliens, and whatever... */ |
| | 1814 | /* check for an alien trigger: NB Door could be either visible or not when triggered */ |
| | 1815 | |
| | 1816 | if (doorbhv->alienTrigger || doorbhv->marineTrigger) |
| | 1817 | { |
| | 1818 | open_door = 1; |
| | 1819 | |
| | 1820 | doorbhv->Timer = DOOR_FAROPENTIME; |
| | 1821 | doorbhv->alienTrigger = 0; |
| | 1822 | } |
| | 1823 | else if((SinglePlayer != AvP.PlayMode) || dptr) |
| | 1824 | { |
| | 1825 | /*-----------------Patrick 29/4/97------------------------- |
| | 1826 | Little patch for networking: doors should run the |
| | 1827 | AnythingNearProxDoor() test even when they are not visible |
| | 1828 | ----------------------------------------------------------*/ |
| | 1829 | open_door = AnythingNearProxDoor(mptr, doorbhv); |
| | 1830 | } |
| | 1831 | } |
| | 1832 | |
| | 1833 | switch(doorbhv->door_state) |
| | 1834 | { |
| | 1835 | case I_door_opening: |
| | 1836 | { |
| | 1837 | mptr->m_flags |= m_flag_open; |
| | 1838 | |
| | 1839 | if(mctrl->ObMorphFlags & mph_flag_finished) |
| | 1840 | { |
| | 1841 | if (doorbhv->SoundHandle != SOUND_NOACTIVEINDEX) |
| | 1842 | { |
| | 1843 | Sound_Play(SID_DOOREND, (doorbhv->marineTrigger ? "dpm" : "dp"), &mptr->m_world, doorbhv->doorType); |
| | 1844 | Sound_Stop(doorbhv->SoundHandle); |
| | 1845 | } |
| | 1846 | |
| | 1847 | doorbhv->door_state = I_door_open; |
| | 1848 | doorbhv->Timer = DOOR_FAROPENTIME; |
| | 1849 | } |
| | 1850 | } |
| | 1851 | break; |
| | 1852 | case I_door_closing: |
| | 1853 | { |
| | 1854 | if(open_door) |
| | 1855 | { |
| | 1856 | if(dptr) |
| | 1857 | { |
| | 1858 | OpenDoor(mctrl, doorbhv->door_opening_speed); |
| | 1859 | |
| | 1860 | if (doorbhv->SoundHandle == SOUND_NOACTIVEINDEX) |
| | 1861 | { |
| | 1862 | if (doorbhv->marineTrigger) |
| | 1863 | { |
| | 1864 | Sound_Play(SID_DOORSTART, "dpm", &mptr->m_world, doorbhv->doorType); |
| | 1865 | Sound_Play(SID_DOORMID, "delpm", &mptr->m_world, &doorbhv->SoundHandle, doorbhv->doorType); |
| | 1866 | } |
| | 1867 | else |
| | 1868 | { |
| | 1869 | Sound_Play(SID_DOORSTART, "dp", &mptr->m_world, doorbhv->doorType); |
| | 1870 | Sound_Play(SID_DOORMID, "delp", &mptr->m_world, &doorbhv->SoundHandle, doorbhv->doorType); |
| | 1871 | } |
| | 1872 | } |
| | 1873 | } |
| | 1874 | else |
| | 1875 | { |
| | 1876 | OpenDoor(mctrl, DOOR_OPENFASTSPEED); |
| | 1877 | } |
| | 1878 | |
| | 1879 | doorbhv->door_state = I_door_opening; |
| | 1880 | } |
| | 1881 | else if(mctrl->ObMorphFlags & mph_flag_finished) |
| | 1882 | { |
| | 1883 | if (doorbhv->SoundHandle != SOUND_NOACTIVEINDEX) |
| | 1884 | { |
| | 1885 | Sound_Play(SID_DOOREND, (doorbhv->marineTrigger ? "dpm" : "dp"), &mptr->m_world, doorbhv->doorType); |
| | 1886 | Sound_Stop(doorbhv->SoundHandle); |
| | 1887 | } |
| | 1888 | |
| | 1889 | doorbhv->door_state = I_door_closed; |
| | 1890 | mptr->m_flags &= ~m_flag_open; |
| | 1891 | } |
| | 1892 | } |
| | 1893 | break; |
| | 1894 | case I_door_open: |
| | 1895 | { |
| | 1896 | mptr->m_flags |= m_flag_open; |
| | 1897 | |
| | 1898 | if(!open_door) |
| | 1899 | { |
| | 1900 | if(doorbhv->Timer < 0) |
| | 1901 | { |
| | 1902 | CloseDoor(mctrl, (dptr ? doorbhv->door_closing_speed : DOOR_CLOSEFASTSPEED)); |
| | 1903 | doorbhv->door_state = I_door_closing; |
| | 1904 | |
| | 1905 | if(dptr) |
| | 1906 | { |
| | 1907 | if (doorbhv->marineTrigger) |
| | 1908 | { |
| | 1909 | Sound_Play(SID_DOORSTART, "dpm", &mptr->m_world, doorbhv->doorType); |
| | 1910 | Sound_Play(SID_DOORMID, "delpm", &mptr->m_world, &doorbhv->SoundHandle, doorbhv->doorType); |
| | 1911 | } |
| | 1912 | else |
| | 1913 | { |
| | 1914 | Sound_Play(SID_DOORSTART, "dp", &mptr->m_world, doorbhv->doorType); |
| | 1915 | Sound_Play(SID_DOORMID, "delp", &mptr->m_world, &doorbhv->SoundHandle, doorbhv->doorType); |
| | 1916 | } |
| | 1917 | } |
| | 1918 | } |
| | 1919 | else |
| | 1920 | { |
| | 1921 | doorbhv->Timer -= NormalFrameTime; |
| | 1922 | } |
| | 1923 | } |
| | 1924 | } |
| | 1925 | break; |
| | 1926 | case I_door_closed: |
| | 1927 | { |
| | 1928 | mptr->m_flags &= ~m_flag_open; |
| | 1929 | |
| | 1930 | if(open_door) |
| | 1931 | { |
| | 1932 | if(dptr) |
| | 1933 | { |
| | 1934 | if (doorbhv->marineTrigger) |
| | 1935 | { |
| | 1936 | Sound_Play(SID_DOORSTART, "dpm", &mptr->m_world, doorbhv->doorType); |
| | 1937 | Sound_Play(SID_DOORMID, "delpm", &mptr->m_world, &doorbhv->SoundHandle, doorbhv->doorType); |
| | 1938 | } |
| | 1939 | else |
| | 1940 | { |
| | 1941 | Sound_Play(SID_DOORSTART, "dp", &mptr->m_world, doorbhv->doorType); |
| | 1942 | Sound_Play(SID_DOORMID, "delp", &mptr->m_world, &doorbhv->SoundHandle, doorbhv->doorType); |
| | 1943 | } |
| | 1944 | |
| | 1945 | OpenDoor(mctrl, doorbhv->door_opening_speed); |
| | 1946 | } |
| | 1947 | else |
| | 1948 | { |
| | 1949 | OpenDoor(mctrl, DOOR_OPENFASTSPEED); |
| | 1950 | } |
| | 1951 | |
| | 1952 | doorbhv->door_state = I_door_opening; |
| | 1953 | mptr->m_flags |= m_flag_open; |
| | 1954 | } |
| | 1955 | else |
| | 1956 | { |
| | 1957 | doorbhv->Timer = DOOR_FAROPENTIME; |
| | 1958 | } |
| | 1959 | } |
| | 1960 | break; |
| | 1961 | default: |
| | 1962 | assert(1==0); |
| | 1963 | break; |
| | 1964 | } |
| | 1965 | |
| | 1966 | doorbhv->marineTrigger = 0; |
| | 1967 | } |
| | 1968 | |
| | 1969 | static void SimpleAnimBehaveFun(STRATEGYBLOCK* sbptr) |
| | 1970 | { |
| | 1971 | /* this just copie the SB taccontrol into the |
| | 1972 | display bloxk if it didnt already have one*/ |
| | 1973 | |
| | 1974 | SIMPLE_ANIM_BEHAV_BLOCK *sanimbhv = (SIMPLE_ANIM_BEHAV_BLOCK*)(sbptr->dataptr); |
| | 1975 | |
| | 1976 | assert(sanimbhv->bhvr_type == I_BehaviourSimpleAnimation); |
| | 1977 | |
| | 1978 | DISPLAYBLOCK* dptr = sbptr->DisplayBlock; |
| | 1979 | |
| | 1980 | if(dptr && !dptr->ObTxAnimCtrlBlks) |
| | 1981 | dptr->ObTxAnimCtrlBlks = sanimbhv->tacbSimple; |
| | 1982 | } |
| | 1983 | |
| | 1984 | static void MakeObjectNear(STRATEGYBLOCK *sbPtr) |
| | 1985 | { |
| | 1986 | DISPLAYBLOCK *dPtr = AllocateNewObject(sbPtr->shapeIndex); |
| | 1987 | |
| | 1988 | if(NULL != dPtr) |
| | 1989 | { |
| | 1990 | DYNAMICSBLOCK *dynPtr = sbPtr->DynPtr; |
| | 1991 | sbPtr->DisplayBlock = dPtr; |
| | 1992 | dPtr->ObStrategyBlock = sbPtr; |
| | 1993 | |
| | 1994 | /* also need to initialise positional information in the new display |
| | 1995 | block from the existing dynamics block: this necessary because this |
| | 1996 | function is (usually) called between the dynamics and rendering systems |
| | 1997 | so it is not initialised by the dynamics system the first time it is |
| | 1998 | drawn. */ |
| | 1999 | dPtr->ObWorld = dynPtr->Position; |
| | 2000 | dPtr->ObEuler = dynPtr->OrientEuler; |
| | 2001 | dPtr->ObMat = dynPtr->OrientMat; |
| | 2002 | } |
| | 2003 | /*else cannot create displayblock, so leave object "far" */ |
| | 2004 | } |
| | 2005 | |
| | 2006 | void RespawnInanimateObject(STRATEGYBLOCK *sbPtr) |
| | 2007 | { |
| | 2008 | INANIMATEOBJECT_STATUSBLOCK* objectstatusptr = sbPtr->dataptr; |
| | 2009 | assert(objectstatusptr); |
| | 2010 | |
| | 2011 | sbPtr->maintainVisibility = 1; |
| | 2012 | |
| | 2013 | /* must respawn health too... */ |
| | 2014 | sbPtr->DamageBlock.Health = objectstatusptr->startingHealth; |
| | 2015 | sbPtr->DamageBlock.Armour = objectstatusptr->startingArmour; |
| | 2016 | } |
| | 2017 | |
| | 2018 | void KillFragmentalObjectForRespawn(STRATEGYBLOCK *sbPtr) |
| | 2019 | { |
| | 2020 | INANIMATEOBJECT_STATUSBLOCK* objectstatusptr = sbPtr->dataptr; |
| | 2021 | assert(objectstatusptr); |
| | 2022 | |
| | 2023 | /* make the object invisible, and remove it from visibility management */ |
| | 2024 | sbPtr->maintainVisibility = 0; |
| | 2025 | |
| | 2026 | DestroyActiveObject(&sbPtr->DisplayBlock); |
| | 2027 | |
| | 2028 | /* KJL 12:44:23 24/05/98 - |
| | 2029 | Set the respawn counter to be the max allowable, so that if all the |
| | 2030 | respawn counters are set to zero, it forces all the objects that have been |
| | 2031 | destroyed (eg. glass) to respawn simultaneously. |
| | 2032 | Not a perfect solution: the object will respawn in 9.1 hours on its own. |
| | 2033 | */ |
| | 2034 | |
| | 2035 | objectstatusptr->respawnTimer = OBJECT_RESPAWN_NO_RESPAWN; |
| | 2036 | } |
| | 2037 | |
| | 2038 | void KillInanimateObjectForRespawn(STRATEGYBLOCK *sbPtr) |
| | 2039 | { |
| | 2040 | INANIMATEOBJECT_STATUSBLOCK* objectstatusptr = sbPtr->dataptr; |
| | 2041 | assert(objectstatusptr); |
| | 2042 | |
| | 2043 | /* make the object invisible, and remove it from visibility management */ |
| | 2044 | if(!objectstatusptr->lifespanTimer) |
| | 2045 | { |
| | 2046 | sbPtr->maintainVisibility = 0; |
| | 2047 | |
| | 2048 | DestroyActiveObject(&sbPtr->DisplayBlock); |
| | 2049 | |
| | 2050 | if(netGameData.timeForRespawn>0) |
| | 2051 | objectstatusptr->respawnTimer = netGameData.timeForRespawn*ONE_FIXED; |
| | 2052 | else |
| | 2053 | objectstatusptr->respawnTimer = OBJECT_RESPAWN_NO_RESPAWN; |
| | 2054 | } |
| | 2055 | else |
| | 2056 | { |
| | 2057 | //get rid of this object permanently |
| | 2058 | sbPtr->please_destroy_me = 1; |
| | 2059 | } |
| | 2060 | } |
| | 2061 | |
| | 2062 | /* this global flag is used to distinguish between messages from the host, and locally caused damage */ |
| | 2063 | int InanimateDamageFromNetHost = 0; |
| | 2064 | extern SOUND3DDATA Explosion_SoundData; |
| | 2065 | |
| | 2066 | void InanimateObjectIsDamaged(STRATEGYBLOCK *sbPtr, const DAMAGE_PROFILE *damage, int multiple) |
| | 2067 | { |
| | 2068 | INANIMATEOBJECT_STATUSBLOCK* objectstatusptr = sbPtr->dataptr; |
| | 2069 | |
| | 2070 | switch(AvP.PlayMode) |
| | 2071 | { |
| | 2072 | case NetworkPeer: |
| | 2073 | if(!InanimateDamageFromNetHost) |
| | 2074 | { |
| | 2075 | /* this means that the damage was generated locally in a net-game: |
| | 2076 | in this case, just send a damage message to the host */ |
| | 2077 | AddNetMsg_InanimateObjectDamaged(sbPtr, damage, multiple); |
| | 2078 | return; |
| | 2079 | } |
| | 2080 | break; |
| | 2081 | case NetworkHost: |
| | 2082 | /* if we're the host, inform everyone that the object is dead */ |
| | 2083 | if(sbPtr->DamageBlock.Health <= 0) |
| | 2084 | AddNetMsg_InanimateObjectDestroyed(sbPtr); |
| | 2085 | default: |
| | 2086 | break; |
| | 2087 | } |
| | 2088 | |
| | 2089 | //if object has been destroyed , see if it has a target that it needs to notify |
| | 2090 | if((objectstatusptr->event_target) && (sbPtr->DamageBlock.Health <= 0) && (objectstatusptr->event_target->triggering_event
& ObjectEventFlag_Destroyed)) |
| | 2091 | { |
| | 2092 | RequestState(objectstatusptr->event_target->event_target_sbptr, objectstatusptr->event_target->request, 0); |
| | 2093 | } |
| | 2094 | |
| | 2095 | sbPtr->DynPtr->GravityOn = 1; |
| | 2096 | |
| | 2097 | if(sbPtr->DamageBlock.Health <= 0) |
| | 2098 | { |
| | 2099 | if (objectstatusptr->explosionType && !objectstatusptr->explosionTimer) |
| | 2100 | { |
| | 2101 | //start explosion timer |
| | 2102 | //this gives a slight time delay for object destruction, to allow for chain reactions |
| | 2103 | //(rather than all explosive objects going up in one frame) |
| | 2104 | objectstatusptr->explosionTimer = ONE_FIXED/10; |
| | 2105 | objectstatusptr->explosionStartFrame = GlobalFrameCounter; |
| | 2106 | return; |
| | 2107 | } |
| | 2108 | |
| | 2109 | switch(objectstatusptr->typeId) |
| | 2110 | { |
| | 2111 | case IOT_Weapon: |
| | 2112 | case IOT_Health: |
| | 2113 | case IOT_Armour: |
| | 2114 | case IOT_FieldCharge: |
| | 2115 | case IOT_Ammo: |
| | 2116 | case IOT_SpecialPickupObject: |
| | 2117 | { |
| | 2118 | MakeFragments(sbPtr); |
| | 2119 | |
| | 2120 | if(SinglePlayer == AvP.PlayMode) |
| | 2121 | sbPtr->please_destroy_me = 1; |
| | 2122 | else |
| | 2123 | KillInanimateObjectForRespawn(sbPtr); |
| | 2124 | } |
| | 2125 | break; |
| | 2126 | case IOT_Furniture: |
| | 2127 | { |
| | 2128 | MakeFragments(sbPtr); |
| | 2129 | |
| | 2130 | sbPtr->please_destroy_me = 1; |
| | 2131 | } |
| | 2132 | break; |
| | 2133 | case IOT_Static: |
| | 2134 | { |
| | 2135 | MakeFragments(sbPtr); |
| | 2136 | |
| | 2137 | if(SinglePlayer == AvP.PlayMode) |
| | 2138 | sbPtr->please_destroy_me = 1; |
| | 2139 | else |
| | 2140 | KillFragmentalObjectForRespawn(sbPtr); |
| | 2141 | } |
| | 2142 | break; |
| | 2143 | case IOT_BoxedSentryGun: |
| | 2144 | { |
| | 2145 | if(SinglePlayer == AvP.PlayMode) |
| | 2146 | sbPtr->please_destroy_me = 1; |
| | 2147 | else |
| | 2148 | KillInanimateObjectForRespawn(sbPtr); |
| | 2149 | } |
| | 2150 | break; |
| | 2151 | default: |
| | 2152 | { |
| | 2153 | assert(1==0); |
| | 2154 | break; |
| | 2155 | } |
| | 2156 | } |
| | 2157 | } |
| | 2158 | } |
| | 2159 | |
| | 2160 | static void InanimateObjectBehaviour(STRATEGYBLOCK *sbPtr) |
| | 2161 | { |
| | 2162 | /* handle respawn timer here */ |
| | 2163 | INANIMATEOBJECT_STATUSBLOCK* objectstatusptr = sbPtr->dataptr; |
| | 2164 | assert(objectstatusptr); |
| | 2165 | assert(!(objectstatusptr->respawnTimer < 0)); /* this should never happen */ |
| | 2166 | |
| | 2167 | if(objectstatusptr->inan_tac) |
| | 2168 | { |
| | 2169 | DISPLAYBLOCK* dptr = sbPtr->DisplayBlock; |
| | 2170 | |
| | 2171 | /*deal with texture animation*/ |
| | 2172 | if(dptr && !dptr->ObTxAnimCtrlBlks) |
| | 2173 | dptr->ObTxAnimCtrlBlks = objectstatusptr->inan_tac; |
| | 2174 | } |
| | 2175 | |
| | 2176 | if(DynamicObjectIsMoving(sbPtr->DynPtr)) //??? |
| | 2177 | sbPtr->DynPtr->GravityOn = 1; |
| | 2178 | |
| | 2179 | if(objectstatusptr->explosionTimer) |
| | 2180 | { |
| | 2181 | if(objectstatusptr->explosionStartFrame == GlobalFrameCounter) |
| | 2182 | { |
| | 2183 | //the explosion was triggered earlier this frame |
| | 2184 | //therefore don't bother altering the timer until next frame |
| | 2185 | return; |
| | 2186 | } |
| | 2187 | |
| | 2188 | objectstatusptr->explosionTimer -= NormalFrameTime; |
| | 2189 | |
| | 2190 | if(objectstatusptr->explosionTimer <= 0) |
| | 2191 | { |
| | 2192 | //MakeFragments(sbPtr); ??? |
| | 2193 | //do explosion effect , without the damage? |
| | 2194 | switch(objectstatusptr->explosionType) |
| | 2195 | { |
| | 2196 | case 1: |
| | 2197 | { |
| | 2198 | MakeVolumetricExplosionAt(&sbPtr->DynPtr->Position, (InanimateDamageFromNetHost ? EXPLOSION_SMALL_NOCOLLISIONS :
EXPLOSION_PULSEGRENADE)); |
| | 2199 | Explosion_SoundData.position = sbPtr->DynPtr->Position; |
| | 2200 | Sound_Play(SID_NADEEXPLODE, "n", &Explosion_SoundData); |
| | 2201 | } |
| | 2202 | break; |
| | 2203 | case 2: |
| | 2204 | { |
| | 2205 | MakeVolumetricExplosionAt(&sbPtr->DynPtr->Position, (InanimateDamageFromNetHost ? EXPLOSION_GRENADE_NOCOLLISIONS :
EXPLOSION_GRENADE_BLAST)); |
| | 2206 | Explosion_SoundData.position = sbPtr->DynPtr->Position; |
| | 2207 | Sound_Play(SID_NICE_EXPLOSION, "n", &Explosion_SoundData); |
| | 2208 | } |
| | 2209 | break; |
| | 2210 | case 3: |
| | 2211 | { |
| | 2212 | MakeMolotovExplosionAt(&sbPtr->DynPtr->Position); |
| | 2213 | Explosion_SoundData.position = sbPtr->DynPtr->Position; |
| | 2214 | Sound_Play(SID_NADEEXPLODE, "n", &Explosion_SoundData); |
| | 2215 | } |
| | 2216 | } |
| | 2217 | |
| | 2218 | sbPtr->please_destroy_me = 1; |
| | 2219 | return; |
| | 2220 | } |
| | 2221 | } |
| | 2222 | |
| | 2223 | if(sbPtr->DamageBlock.IsOnFire) |
| | 2224 | CauseDamageToObject(sbPtr, &damage_profiles[FIREDAMAGE], NormalFrameTime, NULL); |
| | 2225 | |
| | 2226 | if(sbPtr->containingModule == PlayerStatus.sbptr->containingModule) |
| | 2227 | { |
| | 2228 | if(AvP.PlayerType != I_Alien) |
| | 2229 | { |
| | 2230 | if(objectstatusptr->typeId == IOT_Static) |
| | 2231 | { |
| | 2232 | if(sbPtr->name && !strncmp(sbPtr->name, "egg", 3)) |
| | 2233 | { |
| | 2234 | if (!(FastRandom() % 300)) |
| | 2235 | { |
| | 2236 | CreateFacehuggerBot(&sbPtr->DisplayBlock->ObWorld); |
| | 2237 | MakeFragments(sbPtr); |
| | 2238 | sbPtr->please_destroy_me = 1; |
| | 2239 | } |
| | 2240 | } |
| | 2241 | } |
| | 2242 | |
| | 2243 | if(sbPtr->DynPtr && sbPtr->DynPtr->IsPickupObject) |
| | 2244 | { |
| | 2245 | DYNAMICSBLOCK *dynPtr = PlayerStatus.sbptr->DynPtr; |
| | 2246 | VECTORCH disp; |
| | 2247 | |
| | 2248 | disp.vx = dynPtr->Position.vx - sbPtr->DynPtr->Position.vx; |
| | 2249 | disp.vy = dynPtr->Position.vy - sbPtr->DynPtr->Position.vy; |
| | 2250 | disp.vz = dynPtr->Position.vz - sbPtr->DynPtr->Position.vz; |
| | 2251 | |
| | 2252 | if (Approximate3dMagnitude(&disp) < PLAYER_PICKUP_OBJECT_RADIUS) |
| | 2253 | MaintainPlayersInventory(sbPtr); |
| | 2254 | } |
| | 2255 | } |
| | 2256 | } |
| | 2257 | |
| | 2258 | if(SinglePlayer != AvP.PlayMode) |
| | 2259 | { |
| | 2260 | //see if dropped weapons have timed out |
| | 2261 | if(objectstatusptr->lifespanTimer > 0) |
| | 2262 | { |
| | 2263 | objectstatusptr->lifespanTimer -= NormalFrameTime; |
| | 2264 | |
| | 2265 | if(objectstatusptr->lifespanTimer <= 0) |
| | 2266 | { |
| | 2267 | MakeFragments(sbPtr); |
| | 2268 | sbPtr->please_destroy_me = 1; |
| | 2269 | } |
| | 2270 | return; |
| | 2271 | } |
| | 2272 | |
| | 2273 | /* do nothing if the timer is zero */ |
| | 2274 | if(!objectstatusptr->respawnTimer || objectstatusptr->respawnTimer == OBJECT_RESPAWN_NO_RESPAWN) |
| | 2275 | return; |
| | 2276 | |
| | 2277 | /* printf("RESPAWN TIMER %d \n", objectstatusptr->respawnTimer); */ |
| | 2278 | /* If we get here, the object is in a respawn state: this should only happen in a net-game */ |
| | 2279 | assert(!sbPtr->maintainVisibility); |
| | 2280 | |
| | 2281 | objectstatusptr->respawnTimer -= NormalFrameTime; |
| | 2282 | |
| | 2283 | if(objectstatusptr->respawnTimer <= 0) |
| | 2284 | { |
| | 2285 | /* time to respawn, then */ |
| | 2286 | RespawnInanimateObject(sbPtr); |
| | 2287 | objectstatusptr->respawnTimer = 0; |
| | 2288 | } |
| | 2289 | } |
| | 2290 | } |
| | 2291 | |
| | 2292 | void IdentifyObject(STRATEGYBLOCK *sbPtr) |
| | 2293 | { |
| | 2294 | if (sbPtr == NULL) |
| | 2295 | { |
| | 2296 | printf("Object is NULL!\n"); |
| | 2297 | return; |
| | 2298 | } |
| | 2299 | |
| | 2300 | switch(sbPtr->type) |
| | 2301 | { |
| | 2302 | case I_BehaviourInanimateObject: |
| | 2303 | { |
| | 2304 | INANIMATEOBJECT_STATUSBLOCK* objStatPtr = sbPtr->dataptr; |
| | 2305 | |
| | 2306 | switch(objStatPtr->typeId) |
| | 2307 | { |
| | 2308 | case(IOT_Weapon): |
| | 2309 | { |
| | 2310 | switch(objStatPtr->subType) |
| | 2311 | { |
| | 2312 | case WEAPON_PULSERIFLE: |
| | 2313 | { |
| | 2314 | printf("Object is a Pulse Rifle.\n"); |
| | 2315 | return; |
| | 2316 | } |
| | 2317 | case WEAPON_SMARTGUN: |
| | 2318 | { |
| | 2319 | printf("Object is a Smartgun.\n"); |
| | 2320 | return; |
| | 2321 | } |
| | 2322 | case WEAPON_FLAMETHROWER: |
| | 2323 | { |
| | 2324 | printf("Object is a Flamethrower.\n"); |
| | 2325 | return; |
| | 2326 | } |
| | 2327 | case WEAPON_SADAR: |
| | 2328 | { |
| | 2329 | printf("Object is a Sadar.\n"); |
| | 2330 | return; |
| | 2331 | } |
| | 2332 | case WEAPON_GRENADELAUNCHER: |
| | 2333 | { |
| | 2334 | printf("Object is a Grenade Launcher.\n"); |
| | 2335 | return; |
| | 2336 | } |
| | 2337 | case WEAPON_MINIGUN: |
| | 2338 | { |
| | 2339 | printf("Object is a Minigun.\n"); |
| | 2340 | return; |
| | 2341 | } |
| | 2342 | |
| | 2343 | default: |
| | 2344 | printf("Object is unknown weapon (subtype %d).\n",(int)objStatPtr->subType); |
| | 2345 | break; |
| | 2346 | } |
| | 2347 | } |
| | 2348 | break; |
| | 2349 | case IOT_Ammo: |
| | 2350 | { |
| | 2351 | switch(objStatPtr->subType) |
| | 2352 | { |
| | 2353 | case AMMO_10MM_CULW: |
| | 2354 | { |
| | 2355 | printf("Object is Pulse Rifle ammo.\n"); |
| | 2356 | break; |
| | 2357 | } |
| | 2358 | case AMMO_SHOTGUN: |
| | 2359 | { |
| | 2360 | printf("Object is Shotgun ammo.\n"); |
| | 2361 | break; |
| | 2362 | } |
| | 2363 | case AMMO_SMARTGUN: |
| | 2364 | { |
| | 2365 | printf("Object is Smartgun ammo.\n"); |
| | 2366 | break; |
| | 2367 | } |
| | 2368 | case AMMO_FLAMETHROWER: |
| | 2369 | { |
| | 2370 | printf("Object is Flamethrower ammo.\n"); |
| | 2371 | break; |
| | 2372 | } |
| | 2373 | case AMMO_SADAR_TOW: |
| | 2374 | { |
| | 2375 | printf("Object is Sadar ammo.\n"); |
| | 2376 | break; |
| | 2377 | } |
| | 2378 | case AMMO_GRENADE: |
| | 2379 | { |
| | 2380 | printf("Object is Grenade Launcher ammo.\n"); |
| | 2381 | break; |
| | 2382 | } |
| | 2383 | case AMMO_MINIGUN: |
| | 2384 | { |
| | 2385 | printf("Object is Minigun ammo.\n"); |
| | 2386 | break; |
| | 2387 | } |
| | 2388 | default: |
| | 2389 | printf("Object is unlisted ammo (subtype %d).\n",(int)objStatPtr->subType); |
| | 2390 | break; |
| | 2391 | } |
| | 2392 | } |
| | 2393 | break; |
| | 2394 | case IOT_Health: |
| | 2395 | { |
| | 2396 | printf("Object is health.\n"); |
| | 2397 | break; |
| | 2398 | } |
| | 2399 | case IOT_Armour: |
| | 2400 | { |
| | 2401 | printf("Object is armour.\n"); |
| | 2402 | break; |
| | 2403 | } |
| | 2404 | case IOT_FieldCharge: |
| | 2405 | { |
| | 2406 | printf("Object is field charge powerup.\n"); |
| | 2407 | break; |
| | 2408 | } |
| | 2409 | default: |
| | 2410 | { |
| | 2411 | printf("Object is unlisted subtype (%d).\n",(int)objStatPtr->subType); |
| | 2412 | } |
| | 2413 | } |
| | 2414 | } |
| | 2415 | break; |
| | 2416 | case I_BehaviourMarine: |
| | 2417 | { |
| | 2418 | printf("Object is a marine.\n"); |
| | 2419 | printf("Marine is in %s\n",sbPtr->containingModule->name); |
| | 2420 | } |
| | 2421 | break; |
| | 2422 | case I_BehaviourAlien: |
| | 2423 | { |
| | 2424 | printf("Object is an alien.\n"); |
| | 2425 | } |
| | 2426 | break; |
| | 2427 | case I_BehaviourPredator: |
| | 2428 | { |
| | 2429 | printf("Object is a predator.\n"); |
| | 2430 | } |
| | 2431 | break; |
| | 2432 | default: |
| | 2433 | { |
| | 2434 | printf("Object is not supported - change PVisible.c for expanded diagnostics!\n"); |
| | 2435 | } |
| | 2436 | } |
| | 2437 | |
| | 2438 | if (!sbPtr->DynPtr) |
| | 2439 | printf("Object has no dynamics block!\n"); |
| | 2440 | else |
| | 2441 | printf("Object world co-ords: %d %d %d\n",sbPtr->DynPtr->Position.vx,sbPtr->DynPtr->Position.vy,sbPtr->DynPtr->Position.vz); |
| | 2442 | } |
| | 2443 | |
| | 2444 | #include "pfarlocs.h" |
| | 2445 | |
| | 2446 | static void EmergencyPlaceObjectInModule(STRATEGYBLOCK *sbPtr, AIMODULE* targetModule) |
| | 2447 | { |
| | 2448 | printf("Calling EmergencyPlaceObjectInModule!\n"); |
| | 2449 | |
| | 2450 | /* first off, assert a few pre-conditions */ |
| | 2451 | assert(AIModuleIsPhysical(targetModule)); |
| | 2452 | assert(sbPtr->maintainVisibility); |
| | 2453 | assert(FALLP_EntryPoints); |
| | 2454 | |
| | 2455 | assert(FALLP_EntryPoints[(targetModule->m_index)].numEntryPoints); |
| | 2456 | |
| | 2457 | FARENTRYPOINT *entryPointsList = FALLP_EntryPoints[(targetModule->m_index)].entryPointsList; |
| | 2458 | |
| | 2459 | |
| | 2460 | /* just use the first entry point */ |
| | 2461 | VECTORCH newPosition = entryPointsList[0].position; |
| | 2462 | |
| | 2463 | /* now set the object's new position and current module. |
| | 2464 | NB this is world position + a little extra in y to make sure */ |
| | 2465 | { |
| | 2466 | DYNAMICSBLOCK *dynPtr = sbPtr->DynPtr; |
| | 2467 | dynPtr->Position = newPosition; |
| | 2468 | |
| | 2469 | dynPtr->Position.vx += targetModule->m_world.vx; |
| | 2470 | dynPtr->Position.vy += targetModule->m_world.vy; |
| | 2471 | dynPtr->Position.vz += targetModule->m_world.vz; |
| | 2472 | |
| | 2473 | dynPtr->PrevPosition = dynPtr->Position; |
| | 2474 | } |
| | 2475 | |
| | 2476 | /* finally, update the sb's module */ |
| | 2477 | sbPtr->containingModule = ModuleFromPosition(&sbPtr->DynPtr->Position, NULL); |
| | 2478 | } |
| | 2479 | |
| | 2480 | /*----------------------Patrick 15/1/97----------------------------- |
| | 2481 | This function relocates an object back into the environment: |
| | 2482 | this may be an npc, inanimate object, etc. |
| | 2483 | It is called if the visibility system fails to find a |
| | 2484 | containing module for the object, which may happen for a number |
| | 2485 | of reasons, eg: an object is blown out of the visible part of the |
| | 2486 | environment, or an npc falls out... |
| | 2487 | NB returns 0 if relocation failed. |
| | 2488 | --------------------------------------------------------------------*/ |
| | 2489 | |
| | 2490 | int EmergencyRelocateObject(STRATEGYBLOCK *sbPtr) |
| | 2491 | { |
| | 2492 | switch(sbPtr->type) |
| | 2493 | { |
| | 2494 | case I_BehaviourNetGhost: |
| | 2495 | case I_BehaviourPlatform: |
| | 2496 | return 1; |
| | 2497 | default: |
| | 2498 | break; |
| | 2499 | } |
| | 2500 | |
| | 2501 | /* first, try to reset the object's position: if it has a valid 'containingModule', |
| | 2502 | this means that it's last position was in that module, so we can use that as a reset |
| | 2503 | position. |
| | 2504 | NB this means that NPC's will be unable to 'run away' into an invisible module. |
| | 2505 | */ |
| | 2506 | |
| | 2507 | if(NULL != sbPtr->containingModule) |
| | 2508 | { |
| | 2509 | /* Nooo, this doesn't work! CDF 3/12/97 Hack. */ |
| | 2510 | |
| | 2511 | if ((sbPtr->type != I_BehaviourAlien) && (sbPtr->type != I_BehaviourMarine)) |
| | 2512 | { |
| | 2513 | if(DynamicObjectIsMoving(sbPtr->DynPtr)) |
| | 2514 | { |
| | 2515 | printf("Valid containingModule.\n"); |
| | 2516 | sbPtr->DynPtr->Position = sbPtr->DynPtr->PrevPosition; |
| | 2517 | return 1; |
| | 2518 | } |
| | 2519 | } |
| | 2520 | } |
| | 2521 | |
| | 2522 | /* |
| | 2523 | so, we don't have a previous module... then search the environment for the |
| | 2524 | nearest invisible module that has entry point locations, and relocate to one of |
| | 2525 | these locations. |
| | 2526 | */ |
| | 2527 | |
| | 2528 | { |
| | 2529 | AIMODULE *targetModule = NULL; |
| | 2530 | int targetModuleDistance = 0; |
| | 2531 | int moduleCounter = 0; |
| | 2532 | |
| | 2533 | AIMODULE *moduleListPointer = AIModuleArray; |
| | 2534 | |
| | 2535 | for(; moduleCounter < AIModuleArraySize; moduleCounter++) |
| | 2536 | { |
| | 2537 | AIMODULE *thisModule = &moduleListPointer[moduleCounter]; |
| | 2538 | |
| | 2539 | if(!ModuleCurrVisArray[thisModule->m_index] && FALLP_EntryPoints[thisModule->m_index].numEntryPoints) |
| | 2540 | { |
| | 2541 | /* a candidate */ |
| | 2542 | int thisModuleDistance = VectorDistance(&thisModule->m_world, &sbPtr->DynPtr->Position); |
| | 2543 | |
| | 2544 | if(!targetModule || (thisModuleDistance < targetModuleDistance)) |
| | 2545 | { |
| | 2546 | targetModule = thisModule; |
| | 2547 | targetModuleDistance = thisModuleDistance; |
| | 2548 | } |
| | 2549 | } |
| | 2550 | } |
| | 2551 | |
| | 2552 | if(!targetModule) |
| | 2553 | { |
| | 2554 | /* this condition shouldn't happen, but since I'm paranoid... */ |
| | 2555 | //This can happen on the skirmish levels (where the whole level is visible at once) |
| | 2556 | //Therefore if the object has a previous containing module , use it. |
| | 2557 | //Otherwise get rid of it. |
| | 2558 | |
| | 2559 | if(sbPtr->containingModule) |
| | 2560 | { |
| | 2561 | /* Nooo, this doesn't work! CDF 3/12/97 Hack. */ |
| | 2562 | |
| | 2563 | printf("Valid containingModule.\n"); |
| | 2564 | sbPtr->DynPtr->Position = sbPtr->DynPtr->PrevPosition; |
| | 2565 | return 1; |
| | 2566 | } |
| | 2567 | |
| | 2568 | sbPtr->please_destroy_me = 1; |
| | 2569 | return 0; |
| | 2570 | } |
| | 2571 | |
| | 2572 | EmergencyPlaceObjectInModule(sbPtr, targetModule); |
| | 2573 | |
| | 2574 | #if DEBUG |
| | 2575 | if (!sbPtr->containingModule) |
| | 2576 | printf("WARNING!! EmgcyPlcObInMod failed\n"); |
| | 2577 | #endif |
| | 2578 | |
| | 2579 | return sbPtr->containingModule != NULL; |
| | 2580 | } |
| | 2581 | } |
| | 2582 | |
| | 2583 | static void DoObjectVisibility(STRATEGYBLOCK *sbPtr) |
| | 2584 | { |
| | 2585 | if(NULL == sbPtr->DisplayBlock) |
| | 2586 | { |
| | 2587 | /* Note that we don't call modulefromposition() for far objects, as they mostly don't |
| | 2588 | move, and those that do (eg AIs) move to precalculated positions in modules. Thus |
| | 2589 | invisible objects are responsible for looking after their own containingModule field. |
| | 2590 | This should always be ok: we should always have a correct and valid containing |
| | 2591 | module. However, we will do a paranoia check for a null containingModule... */ |
| | 2592 | |
| | 2593 | if(NULL == sbPtr->containingModule) |
| | 2594 | { |
| | 2595 | printf("Calling Far EmergencyRelocateObject, On object %p, type %d!\n", (void*)sbPtr, sbPtr->type); |
| | 2596 | |
| | 2597 | IdentifyObject(sbPtr); |
| | 2598 | |
| | 2599 | if(!EmergencyRelocateObject(sbPtr)) |
| | 2600 | { |
| | 2601 | printf("Relocate failed!\n"); |
| | 2602 | return; |
| | 2603 | } |
| | 2604 | } |
| | 2605 | |
| | 2606 | /* Now do the visibility check: the object has no display block, so check if |
| | 2607 | it's module is visible. If so, make the object visibile too. */ |
| | 2608 | |
| | 2609 | switch(sbPtr->type) |
| | 2610 | { |
| | 2611 | case I_BehaviourPlacedLight: |
| | 2612 | { |
| | 2613 | if (ThisObjectIsInAModuleVisibleFromCurrentlyVisibleModules(sbPtr)) |
| | 2614 | MakePlacedLightNear(sbPtr); |
| | 2615 | } |
| | 2616 | return; |
| | 2617 | case I_BehaviourNetGhost: |
| | 2618 | { |
| | 2619 | NETGHOSTDATABLOCK *ghostDataPtr = (NETGHOSTDATABLOCK *)sbPtr->dataptr; |
| | 2620 | |
| | 2621 | if (ghostDataPtr && ghostDataPtr->type == I_BehaviourFlare) |
| | 2622 | { |
| | 2623 | if(ThisObjectIsInAModuleVisibleFromCurrentlyVisibleModules(sbPtr)) |
| | 2624 | { |
| | 2625 | MakeGhostNear(sbPtr); |
| | 2626 | return; |
| | 2627 | } |
| | 2628 | } |
| | 2629 | } |
| | 2630 | break; |
| | 2631 | case I_BehaviourPlatform: |
| | 2632 | { |
| | 2633 | PLATFORMLIFT_BEHAVIOUR_BLOCK *platformliftdata = (PLATFORMLIFT_BEHAVIOUR_BLOCK *)sbPtr->dataptr; |
| | 2634 | //platform lift needs to be made near if its module near or if it is moving |
| | 2635 | |
| | 2636 | switch(platformliftdata->state) |
| | 2637 | { |
| | 2638 | default: |
| | 2639 | { |
| | 2640 | if(!ModuleCurrVisArray[sbPtr->containingModule->m_index]) |
| | 2641 | break; |
| | 2642 | } |
| | 2643 | case PLBS_GoingUp: |
| | 2644 | case PLBS_GoingDown: |
| | 2645 | MakeObjectNear(sbPtr); |
| | 2646 | } |
| | 2647 | return; |
| | 2648 | } |
| | 2649 | default: |
| | 2650 | break; |
| | 2651 | } |
| | 2652 | |
| | 2653 | if(ModuleCurrVisArray[sbPtr->containingModule->m_index] > 1) |
| | 2654 | { |
| | 2655 | /* module is visible, so make object visible too */ |
| | 2656 | switch(sbPtr->type) |
| | 2657 | { |
| | 2658 | case I_BehaviourAlien: |
| | 2659 | MakeAlienNear(sbPtr); |
| | 2660 | break; |
| | 2661 | case I_BehaviourVideoScreen: |
| | 2662 | { |
| | 2663 | DISPLAYBLOCK *dPtr = AllocateNewObject(sbPtr->shapeIndex); |
| | 2664 | |
| | 2665 | if(NULL != dPtr) |
| | 2666 | { |
| | 2667 | sbPtr->DisplayBlock = dPtr; |
| | 2668 | dPtr->ObStrategyBlock = sbPtr; |
| | 2669 | DYNAMICSBLOCK *dynPtr = sbPtr->DynPtr; |
| | 2670 | |
| | 2671 | /* also need to initialise positional information in the new display |
| | 2672 | block from the existing dynamics block: this necessary because this |
| | 2673 | function is (usually) called between the dynamics and rendering systems |
| | 2674 | so it is not initialised by the dynamics system the first time it is |
| | 2675 | drawn. */ |
| | 2676 | dPtr->ObWorld = dynPtr->Position; |
| | 2677 | dPtr->ObEuler = dynPtr->OrientEuler; |
| | 2678 | dPtr->ObMat = dynPtr->OrientMat; |
| | 2679 | AddLightingEffectToObject(sbPtr->DisplayBlock, LFX_FLARE); |
| | 2680 | } |
| | 2681 | /*else cannot create displayblock, so leave object "far" */ |
| | 2682 | } |
| | 2683 | break; |
| | 2684 | case I_BehaviourHierarchicalFragment: |
| | 2685 | case I_BehaviourFragment: |
| | 2686 | case I_BehaviourRocket: |
| | 2687 | case I_BehaviourPPPlasmaBolt: |
| | 2688 | case I_BehaviourSpeargunBolt: |
| | 2689 | case I_BehaviourPredatorDisc_SeekTrack: |
| | 2690 | case I_BehaviourPredatorEnergyBolt: |
| | 2691 | case I_BehaviourFlare: |
| | 2692 | case I_BehaviourPulseGrenade: |
| | 2693 | case I_BehaviourGrenade: |
| | 2694 | case I_BehaviourFragmentationGrenade: |
| | 2695 | case I_BehaviourProximityGrenade: |
| | 2696 | case I_BehaviourMolotov: |
| | 2697 | case I_BehaviourDeathVolume: |
| | 2698 | case I_BehaviourFrisbee: |
| | 2699 | case I_BehaviourFrisbeeEnergyBolt: |
| | 2700 | //sbPtr->DisplayBlock->ObFlags & ObFlag_NotVis; |
| | 2701 | //break; |
| | 2702 | |
| | 2703 | case I_BehaviourInanimateObject: |
| | 2704 | case I_BehaviourBinarySwitch: |
| | 2705 | case I_BehaviourLinkSwitch: |
| | 2706 | case I_BehaviourFan: |
| | 2707 | case I_BehaviourTrackObject: |
| | 2708 | MakeObjectNear(sbPtr); |
| | 2709 | break; |
| | 2710 | case I_BehaviourMarine: |
| | 2711 | MakeMarineNear(sbPtr); |
| | 2712 | break; |
| | 2713 | case I_BehaviourPredator: |
| | 2714 | MakePredatorNear(sbPtr); |
| | 2715 | break; |
| | 2716 | case I_BehaviourFaceHugger: |
| | 2717 | MakeFacehuggerNear(sbPtr); |
| | 2718 | break; |
| | 2719 | case I_BehaviourNetGhost: |
| | 2720 | { |
| | 2721 | NETGHOSTDATABLOCK *ghostDataPtr = (NETGHOSTDATABLOCK *)sbPtr->dataptr; |
| | 2722 | |
| | 2723 | /* KJL 16:42:40 23/01/99 - near behaviour is triggered differently for lightsources such as flares */ |
| | 2724 | if (ghostDataPtr && ghostDataPtr->type != I_BehaviourFlare) |
| | 2725 | MakeGhostNear(sbPtr); |
| | 2726 | } |
| | 2727 | break; |
| | 2728 | case I_BehaviourCorpse: |
| | 2729 | MakeCorpseNear(sbPtr); |
| | 2730 | break; |
| | 2731 | case I_BehaviourPlacedHierarchy: |
| | 2732 | MakePlacedHierarchyNear(sbPtr); |
| | 2733 | break; |
| | 2734 | case I_BehaviourAutoGun: |
| | 2735 | MakeSentrygunNear(sbPtr); |
| | 2736 | break; |
| | 2737 | case I_BehaviourXenoborg: |
| | 2738 | MakeXenoborgNear(sbPtr); |
| | 2739 | break; |
| | 2740 | case I_BehaviourQueenAlien: |
| | 2741 | MakeQueenNear(sbPtr); |
| | 2742 | break; |
| | 2743 | case I_BehaviourDummy: |
| | 2744 | MakeDummyNear(sbPtr); |
| | 2745 | break; |
| | 2746 | default: |
| | 2747 | { |
| | 2748 | /* only the above object types should get here */ |
| | 2749 | assert(1==0); |
| | 2750 | } |
| | 2751 | } |
| | 2752 | } |
| | 2753 | } |
| | 2754 | else |
| | 2755 | { |
| | 2756 | if (sbPtr->type == I_BehaviourPlacedLight) |
| | 2757 | { |
| | 2758 | if(!ThisObjectIsInAModuleVisibleFromCurrentlyVisibleModules(sbPtr)) |
| | 2759 | DestroyActiveObject(&sbPtr->DisplayBlock); |
| | 2760 | } |
| | 2761 | else |
| | 2762 | { |
| | 2763 | if(!ModuleCurrVisArray[sbPtr->containingModule->m_index]) |
| | 2764 | { |
| | 2765 | /* module is invisible, so make object invisible too */ |
| | 2766 | switch(sbPtr->type) |
| | 2767 | { |
| | 2768 | case I_BehaviourAlien: |
| | 2769 | MakeAlienFar(sbPtr); |
| | 2770 | break; |
| | 2771 | case I_BehaviourHierarchicalFragment: |
| | 2772 | case I_BehaviourFragment: |
| | 2773 | case I_BehaviourRocket: |
| | 2774 | case I_BehaviourPPPlasmaBolt: |
| | 2775 | case I_BehaviourSpeargunBolt: |
| | 2776 | case I_BehaviourPredatorDisc_SeekTrack: |
| | 2777 | case I_BehaviourPredatorEnergyBolt: |
| | 2778 | case I_BehaviourFlare: |
| | 2779 | case I_BehaviourPulseGrenade: |
| | 2780 | case I_BehaviourGrenade: |
| | 2781 | case I_BehaviourFragmentationGrenade: |
| | 2782 | case I_BehaviourProximityGrenade: |
| | 2783 | case I_BehaviourMolotov: |
| | 2784 | case I_BehaviourDeathVolume: |
| | 2785 | case I_BehaviourFrisbee: |
| | 2786 | case I_BehaviourFrisbeeEnergyBolt: |
| | 2787 | //break; |
| | 2788 | case I_BehaviourInanimateObject: |
| | 2789 | case I_BehaviourVideoScreen: |
| | 2790 | case I_BehaviourBinarySwitch: |
| | 2791 | case I_BehaviourLinkSwitch: |
| | 2792 | case I_BehaviourPlacedHierarchy: |
| | 2793 | case I_BehaviourTrackObject: |
| | 2794 | case I_BehaviourCorpse: |
| | 2795 | case I_BehaviourFan: |
| | 2796 | case I_BehaviourNetGhost: |
| | 2797 | DestroyActiveObject(&sbPtr->DisplayBlock); |
| | 2798 | break; |
| | 2799 | case I_BehaviourMarine: |
| | 2800 | MakeMarineFar(sbPtr); |
| | 2801 | break; |
| | 2802 | case I_BehaviourPlatform: |
| | 2803 | { |
| | 2804 | PLATFORMLIFT_BEHAVIOUR_BLOCK *platformliftdata = (PLATFORMLIFT_BEHAVIOUR_BLOCK *)sbPtr->dataptr; |
| | 2805 | //don't make platform lift far if it is currently moving |
| | 2806 | //(otherwise the lift won't be able to move) |
| | 2807 | |
| | 2808 | switch(platformliftdata->state) |
| | 2809 | { |
| | 2810 | case PLBS_GoingUp: |
| | 2811 | case PLBS_GoingDown: |
| | 2812 | break; |
| | 2813 | default: |
| | 2814 | DestroyActiveObject(&sbPtr->DisplayBlock); |
| | 2815 | } |
| | 2816 | } |
| | 2817 | break; |
| | 2818 | case I_BehaviourFaceHugger: |
| | 2819 | MakeFacehuggerFar(sbPtr); |
| | 2820 | break; |
| | 2821 | case I_BehaviourPredator: |
| | 2822 | MakePredatorFar(sbPtr); |
| | 2823 | break; |
| | 2824 | case I_BehaviourXenoborg: |
| | 2825 | MakeXenoborgFar(sbPtr); |
| | 2826 | break; |
| | 2827 | case I_BehaviourQueenAlien: |
| | 2828 | MakeQueenFar(sbPtr); |
| | 2829 | break; |
| | 2830 | case I_BehaviourAutoGun: |
| | 2831 | MakeSentrygunFar(sbPtr); |
| | 2832 | break; |
| | 2833 | case I_BehaviourDummy: |
| | 2834 | MakeDummyFar(sbPtr); |
| | 2835 | break; |
| | 2836 | default: |
| | 2837 | { |
| | 2838 | /* only the above object types should get here */ |
| | 2839 | assert(1==0); |
| | 2840 | } |
| | 2841 | } |
| | 2842 | } |
| | 2843 | } |
| | 2844 | } |
| | 2845 | } |
| | 2846 | |
| | 2847 | static void FragmentBehaviour(STRATEGYBLOCK *sptr) |
| | 2848 | { |
| | 2849 | ONE_SHOT_BEHAV_BLOCK *osbhv = (ONE_SHOT_BEHAV_BLOCK * )sptr->dataptr; |
| | 2850 | |
| | 2851 | if (osbhv->counter < 0) |
| | 2852 | { |
| | 2853 | sptr->please_destroy_me = 1; |
| | 2854 | } |
| | 2855 | else |
| | 2856 | { |
| | 2857 | osbhv->counter -= NormalFrameTime; |
| | 2858 | |
| | 2859 | if (!sptr->DynPtr->IsInContactWithFloor && DynamicObjectIsMoving(sptr->DynPtr)) |
| | 2860 | DynamicallyRotateObject(sptr->DynPtr); |
| | 2861 | |
| | 2862 | if (sptr->DisplayBlock) |
| | 2863 | { |
| | 2864 | sptr->DisplayBlock->SpecialFXFlags |= SFXFLAG_MELTINGINTOGROUND; |
| | 2865 | sptr->DisplayBlock->ObFlags2 = osbhv->counter / 2; |
| | 2866 | } |
| | 2867 | } |
| | 2868 | } |
| | 2869 | |
| | 2870 | void ExecuteBehaviour() |
| | 2871 | { |
| | 2872 | int i; // player is 0 and is done in PlayerBehaviour |
| | 2873 | |
| | 2874 | for (i=1; i < NumActiveStBlocks; i++) |
| | 2875 | { |
| | 2876 | STRATEGYBLOCK *sbptr = ActiveStBlockList[i]; |
| | 2877 | |
| | 2878 | if(sbptr->please_destroy_me) |
| | 2879 | continue; |
| | 2880 | else if(sbptr->maintainVisibility) |
| | 2881 | DoObjectVisibility(sbptr); |
| | 2882 | |
| | 2883 | switch(sbptr->type) |
| | 2884 | { |
| | 2885 | case I_BehaviourPlacedLight: |
| | 2886 | PlacedLightBehaviour(sbptr); |
| | 2887 | break; |
| | 2888 | case I_BehaviourLightFX: |
| | 2889 | LightFXBehaveFun(sbptr); |
| | 2890 | break; |
| | 2891 | case I_BehaviourPlacedSound: |
| | 2892 | SoundBehaveFun(sbptr); |
| | 2893 | break; |
| | 2894 | case I_BehaviourAlien: |
| | 2895 | if(sbptr->containingModule) |
| | 2896 | AlienBehaviour(sbptr); |
| | 2897 | else |
| | 2898 | sbptr->please_destroy_me = 1; // aliens sometimes climb out of the environment, remove and relocate. Note to myself fix this |
| | 2899 | break; |
| | 2900 | case I_BehaviourHierarchicalFragment: |
| | 2901 | HierarchicalFragmentBehaviour(sbptr); |
| | 2902 | break; |
| | 2903 | case I_BehaviourFragment: |
| | 2904 | FragmentBehaviour(sbptr); |
| | 2905 | break; |
| | 2906 | case I_BehaviourCorpse: |
| | 2907 | CorpseBehaveFun(sbptr); |
| | 2908 | break; |
| | 2909 | case I_BehaviourMarine: |
| | 2910 | if(sbptr->containingModule) |
| | 2911 | MarineBehaviour(sbptr); |
| | 2912 | else |
| | 2913 | sbptr->please_destroy_me = 1; |
| | 2914 | break; |
| | 2915 | case I_BehaviourGenerator: |
| | 2916 | GeneratorBehaviour(sbptr); |
| | 2917 | break; |
| | 2918 | case I_BehaviourParticleGenerator: |
| | 2919 | ParticleGeneratorBehaveFun(sbptr); |
| | 2920 | break; |
| | 2921 | case I_BehaviourInanimateObject: |
| | 2922 | InanimateObjectBehaviour(sbptr); |
| | 2923 | break; |
| | 2924 | case I_BehaviourVideoScreen: |
| | 2925 | VideoScreenBehaviour(sbptr); |
| | 2926 | break; |
| | 2927 | case I_BehaviourFlare: |
| | 2928 | FlareBehaviour(sbptr); |
| | 2929 | break; |
| | 2930 | case I_BehaviourPulseGrenade: |
| | 2931 | PulseGrenadeBehaviour(sbptr); |
| | 2932 | break; |
| | 2933 | case I_BehaviourRocket: |
| | 2934 | RocketBehaviour(sbptr); |
| | 2935 | break; |
| | 2936 | case I_BehaviourGrenade: |
| | 2937 | GrenadeBehaviour(sbptr); |
| | 2938 | break; |
| | 2939 | case I_BehaviourFragmentationGrenade: |
| | 2940 | FragGrenadeBehaviour(sbptr); |
| | 2941 | break; |
| | 2942 | case I_BehaviourProximityGrenade: |
| | 2943 | ProximityGrenadeBehaviour(sbptr); |
| | 2944 | break; |
| | 2945 | case I_BehaviourProximityDoor: |
| | 2946 | DoorProxBehaveFun(sbptr); |
| | 2947 | break; |
| | 2948 | case I_BehaviourBinarySwitch: |
| | 2949 | BinarySwitchBehaveFun(sbptr); |
| | 2950 | break; |
| | 2951 | case I_BehaviourLiftDoor: |
| | 2952 | LiftDoorBehaveFun(sbptr); |
| | 2953 | break; |
| | 2954 | case I_BehaviourLift: |
| | 2955 | LiftBehaveFun(sbptr); |
| | 2956 | break; |
| | 2957 | case I_BehaviourSwitchDoor: |
| | 2958 | SwitchDoorBehaviour(sbptr); |
| | 2959 | break; |
| | 2960 | case I_BehaviourLinkSwitch: |
| | 2961 | LinkSwitchBehaveFun(sbptr); |
| | 2962 | break; |
| | 2963 | case I_BehaviourPlatform: |
| | 2964 | PlatformLiftBehaviour(sbptr); |
| | 2965 | break; |
| | 2966 | case I_BehaviourSimpleAnimation: |
| | 2967 | SimpleAnimBehaveFun(sbptr); |
| | 2968 | break; |
| | 2969 | case I_BehaviourAutoGun: |
| | 2970 | AutoGunBehaveFun(sbptr); |
| | 2971 | break; |
| | 2972 | case I_BehaviourMolotov: |
| | 2973 | MolotovBehaviour(sbptr); |
| | 2974 | break; |
| | 2975 | case I_BehaviourFrisbee: |
| | 2976 | FrisbeeBehaviour(sbptr); |
| | 2977 | break; |
| | 2978 | case I_BehaviourFaceHugger: |
| | 2979 | if(sbptr->containingModule) |
| | 2980 | FacehuggerBehaviour(sbptr); |
| | 2981 | else |
| | 2982 | sbptr->please_destroy_me = 1; // just to make sure |
| | 2983 | break; |
| | 2984 | case I_BehaviourPredator: |
| | 2985 | if(sbptr->containingModule) |
| | 2986 | PredatorBehaviour(sbptr); |
| | 2987 | else |
| | 2988 | sbptr->please_destroy_me = 1; // just to make sure |
| | 2989 | break; |
| | 2990 | case I_BehaviourPPPlasmaBolt: |
| | 2991 | PPPlasmaBoltBehaviour(sbptr); |
| | 2992 | break; |
| | 2993 | case I_BehaviourSpeargunBolt: |
| | 2994 | SpeargunBoltBehaviour(sbptr); |
| | 2995 | break; |
| | 2996 | case I_BehaviourPredatorEnergyBolt: |
| | 2997 | PredatorEnergyBoltBehaviour(sbptr); |
| | 2998 | break; |
| | 2999 | case I_BehaviourFrisbeeEnergyBolt: |
| | 3000 | FrisbeeEnergyBoltBehaviour(sbptr); |
| | 3001 | break; |
| | 3002 | case I_BehaviourPredatorDisc_SeekTrack: |
| | 3003 | DiscBehaviour_SeekTrack(sbptr); |
| | 3004 | break; |
| | 3005 | case I_BehaviourNetGhost: |
| | 3006 | NetGhostBehaviour(sbptr); |
| | 3007 | break; |
| | 3008 | case I_BehaviourTrackObject: |
| | 3009 | TrackObjectBehaveFun(sbptr); |
| | 3010 | break; |
| | 3011 | case I_BehaviourFan: |
| | 3012 | FanBehaveFun(sbptr); |
| | 3013 | break; |
| | 3014 | case I_BehaviourGrapplingHook: |
| | 3015 | GrapplingHookBehaviour(sbptr); |
| | 3016 | break; |
| | 3017 | case I_BehaviourPlacedHierarchy: |
| | 3018 | PlacedHierarchyBehaveFun(sbptr); |
| | 3019 | break; |
| | 3020 | case I_BehaviourPowerCable: |
| | 3021 | PowerCableBehaveFun(sbptr); |
| | 3022 | break; |
| | 3023 | case I_BehaviourDeathVolume: |
| | 3024 | DeathVolumeBehaveFun(sbptr); |
| | 3025 | break; |
| | 3026 | case I_BehaviourXenoborg: |
| | 3027 | XenoborgBehaviour(sbptr); |
| | 3028 | break; |
| | 3029 | case I_BehaviourQueenAlien: |
| | 3030 | QueenBehaviour(sbptr); |
| | 3031 | break; |
| | 3032 | case I_BehaviourXenoborgMorphRoom: |
| | 3033 | XenoMorphRoomBehaviour(sbptr); |
| | 3034 | break; |
| | 3035 | case I_BehaviourSelfDestruct: |
| | 3036 | SelfDestructBehaveFun(sbptr); |
| | 3037 | break; |
| | 3038 | case I_BehaviourDummy: |
| | 3039 | DummyBehaviour(sbptr); |
| | 3040 | default: |
| | 3041 | break; |
| | 3042 | } |
| | 3043 | } |
| | 3044 | |
| | 3045 | // RWH 5/6/97 these next two functions were 1, changed and 2, added |
| | 3046 | // to deal with deallocating stblocks at the end of behaviours |
| | 3047 | // this stops problems with accessing defunct strategy blocks |
| | 3048 | // via collision reports |
| | 3049 | |
| | 3050 | /* |
| | 3051 | Go backwards through the strategy block. |
| | 3052 | This should prevent any strategy blocks from being skipped when they |
| | 3053 | get shuffled down from the end of the array. |
| | 3054 | */ |
| | 3055 | |
| | 3056 | while(i--) |
| | 3057 | { |
| | 3058 | STRATEGYBLOCK* sbptr = ActiveStBlockList[i]; |
| | 3059 | |
| | 3060 | if(sbptr->please_destroy_me) |
| | 3061 | RemoveBehaviourStrategy(sbptr); |
| | 3062 | } |
| | 3063 | } |
| | 3064 | |
| | 3065 | static void SendRequestToInanimateObject(STRATEGYBLOCK* sbptr, int state, int extended_data) |
| | 3066 | { |
| | 3067 | if(state && (extended_data & ObjectRequest_AdjustIntegrity)) |
| | 3068 | { |
| | 3069 | int new_integrity = (extended_data >> 7) & 0xff; |
| | 3070 | sbptr->DamageBlock.Indestructable = (new_integrity > 20); |
| | 3071 | sbptr->DamageBlock.Health = (10 << ONE_FIXED_SHIFT) * new_integrity; |
| | 3072 | |
| | 3073 | if(!new_integrity) |
| | 3074 | InanimateObjectIsDamaged(sbptr, &damage_profiles[CERTAINDEATH], ONE_FIXED); |
| | 3075 | } |
| | 3076 | } |
| | 3077 | |
| | 3078 | /********************* SUPPORT FUNCTION ***********************/ |
| | 3079 | /* |
| | 3080 | these set the reqest state in a strategy block |
| | 3081 | */ |
| | 3082 | |
| | 3083 | void RequestState(STRATEGYBLOCK* sbptr, int message, STRATEGYBLOCK * SBRequester) |
| | 3084 | { |
| | 3085 | //lowest bit of message corresponds to old on/off state |
| | 3086 | //the rest is extended information ,the interpretation of which depends on the receiving strategy |
| | 3087 | int state = message & 1; |
| | 3088 | |
| | 3089 | if(!sbptr) |
| | 3090 | return; |
| | 3091 | |
| | 3092 | if(sbptr->destroyed_but_preserved) |
| | 3093 | return; //target doesn't exist anymore so ignore request. |
| | 3094 | |
| | 3095 | #if DEBUG |
| | 3096 | { |
| | 3097 | extern int GlobalFrameCounter; |
| | 3098 | //add details of request to logfile |
| | 3099 | const char* name1=0; |
| | 3100 | const char* name2 = "ANON"; |
| | 3101 | |
| | 3102 | if(sbptr) |
| | 3103 | name1 = sbptr->name; |
| | 3104 | |
| | 3105 | if(SBRequester) |
| | 3106 | name2 = SBRequester->name; |
| | 3107 | |
| | 3108 | printf("Frame %d : %s sent %s message to %s%s",GlobalFrameCounter,name2, state ? "'on'" :
"'off'",name1,(message>>1)? " with extra message data" : ""); |
| | 3109 | } |
| | 3110 | #endif |
| | 3111 | |
| | 3112 | switch (sbptr->type) |
| | 3113 | { |
| | 3114 | case I_BehaviourCorpse: |
| | 3115 | /* Ulp... */ |
| | 3116 | break; |
| | 3117 | case I_BehaviourBinarySwitch: |
| | 3118 | { |
| | 3119 | // 0 = rest state |
| | 3120 | // 1 = unusual state |
| | 3121 | |
| | 3122 | BINARY_SWITCH_BEHAV_BLOCK *bs_bhv = (BINARY_SWITCH_BEHAV_BLOCK*)sbptr->dataptr; |
| | 3123 | |
| | 3124 | assert((bs_bhv->bhvr_type == I_BehaviourBinarySwitch)); |
| | 3125 | |
| | 3126 | bs_bhv->request = state ? I_request_on : I_request_off; |
| | 3127 | } |
| | 3128 | break; |
| | 3129 | case I_BehaviourLinkSwitch: |
| | 3130 | { |
| | 3131 | // 0 = rest state |
| | 3132 | // 1 = unusual state |
| | 3133 | LINK_SWITCH_BEHAV_BLOCK *bs_bhv = (LINK_SWITCH_BEHAV_BLOCK*)sbptr->dataptr; |
| | 3134 | |
| | 3135 | assert((bs_bhv->bhvr_type == I_BehaviourLinkSwitch)); |
| | 3136 | |
| | 3137 | if (SBRequester) |
| | 3138 | if (SBRequester->type == I_BehaviourBinarySwitch || SBRequester->type == I_BehaviourLinkSwitch) |
| | 3139 | { |
| | 3140 | //if the request has come from one of the linked switches , ignore it |
| | 3141 | int i = 0; |
| | 3142 | |
| | 3143 | for(; i < bs_bhv->num_linked_switches; i++) |
| | 3144 | { |
| | 3145 | if(bs_bhv->lswitch_list[i].bswitch == SBRequester) |
| | 3146 | break; |
| | 3147 | } |
| | 3148 | |
| | 3149 | if( i < bs_bhv->num_linked_switches) |
| | 3150 | break; |
| | 3151 | } |
| | 3152 | |
| | 3153 | bs_bhv->request = state ? I_request_on : I_request_off; |
| | 3154 | } |
| | 3155 | break; |
| | 3156 | case I_BehaviourProximityDoor: |
| | 3157 | { |
| | 3158 | PROXDOOR_BEHAV_BLOCK *door_bhv = (PROXDOOR_BEHAV_BLOCK*)sbptr->dataptr; |
| | 3159 | assert((door_bhv->bhvr_type == I_BehaviourProximityDoor)); |
| | 3160 | |
| | 3161 | //request previously open and closed door.Now it locks or unlocks it. |
| | 3162 | |
| | 3163 | door_bhv->door_locked = (state == 1) ? 0 : 1; |
| | 3164 | } |
| | 3165 | break; |
| | 3166 | case I_BehaviourLiftDoor: |
| | 3167 | { |
| | 3168 | LIFT_DOOR_BEHAV_BLOCK *door_bhv = (LIFT_DOOR_BEHAV_BLOCK*)sbptr->dataptr; |
| | 3169 | assert((door_bhv->bhvr_type == I_BehaviourLiftDoor)); |
| | 3170 | |
| | 3171 | door_bhv->request_state = (state == 1) ? I_door_open : I_door_closed; |
| | 3172 | } |
| | 3173 | break; |
| | 3174 | case I_BehaviourSwitchDoor: |
| | 3175 | { |
| | 3176 | SWITCH_DOOR_BEHAV_BLOCK *door_bhv = (SWITCH_DOOR_BEHAV_BLOCK*)sbptr->dataptr; |
| | 3177 | assert((door_bhv->myBehaviourType == I_BehaviourSwitchDoor)); |
| | 3178 | |
| | 3179 | if(state == 1) |
| | 3180 | door_bhv->requestOpen = 1; |
| | 3181 | else |
| | 3182 | door_bhv->requestClose = 1; |
| | 3183 | } |
| | 3184 | break; |
| | 3185 | case I_BehaviourLift: |
| | 3186 | { |
| | 3187 | assert(sbptr); |
| | 3188 | LIFT_BEHAV_BLOCK *lift_bhv = (LIFT_BEHAV_BLOCK*)sbptr->dataptr; |
| | 3189 | assert((lift_bhv->bhvr_type == I_BehaviourLift)); |
| | 3190 | LIFT_STATION *lift_stn = &lift_bhv->lift_station; |
| | 3191 | assert(lift_stn); |
| | 3192 | |
| | 3193 | lift_stn->called = (state == 1) ? 1 : 0; |
| | 3194 | } |
| | 3195 | break; |
| | 3196 | case I_BehaviourPlatform: |
| | 3197 | { |
| | 3198 | ((PLATFORMLIFT_BEHAVIOUR_BLOCK*)sbptr->dataptr)->Enabled = state; |
| | 3199 | } |
| | 3200 | break; |
| | 3201 | case I_BehaviourAutoGun: |
| | 3202 | { |
| | 3203 | AUTOGUN_STATUS_BLOCK *agunStatusPointer = (AUTOGUN_STATUS_BLOCK*)sbptr->dataptr; |
| | 3204 | |
| | 3205 | if ((agunStatusPointer->behaviourState == I_inactive) && (state == 1)) |
| | 3206 | { |
| | 3207 | agunStatusPointer->behaviourState = I_tracking; |
| | 3208 | } |
| | 3209 | else if ((agunStatusPointer->behaviourState == I_tracking) && !state) |
| | 3210 | { |
| | 3211 | agunStatusPointer->behaviourState = I_inactive; |
| | 3212 | Sound_Play(SID_SENTRYGUN_SHUTDOWN, "d", &sbptr->DynPtr->Position); |
| | 3213 | } |
| | 3214 | } |
| | 3215 | break; |
| | 3216 | case I_BehaviourGenerator: |
| | 3217 | { |
| | 3218 | ((GENERATOR_BLOCK*)sbptr->dataptr)->Active = state; |
| | 3219 | break; |
| | 3220 | } |
| | 3221 | case I_BehaviourLightFX: |
| | 3222 | { |
| | 3223 | LIGHT_FX_BEHAV_BLOCK * lfxbb = (LIGHT_FX_BEHAV_BLOCK *)sbptr->dataptr; |
| | 3224 | |
| | 3225 | if (lfxbb->type == LFX_Switch) |
| | 3226 | { |
| | 3227 | switch (lfxbb->current_state) |
| | 3228 | { |
| | 3229 | case LFXS_LightOn: |
| | 3230 | { |
| | 3231 | if(!state) |
| | 3232 | { |
| | 3233 | lfxbb->current_state = LFXS_LightFadingDown; |
| | 3234 | lfxbb->timer = 0; |
| | 3235 | } |
| | 3236 | } |
| | 3237 | break; |
| | 3238 | case LFXS_LightOff: |
| | 3239 | { |
| | 3240 | if(state == 1) |
| | 3241 | { |
| | 3242 | lfxbb->current_state = LFXS_LightFadingUp; |
| | 3243 | lfxbb->timer = 0; |
| | 3244 | } |
| | 3245 | } |
| | 3246 | break; |
| | 3247 | case LFXS_LightFadingUp: |
| | 3248 | { |
| | 3249 | if(!state) |
| | 3250 | { |
| | 3251 | lfxbb->timer = ONE_FIXED - lfxbb->timer; |
| | 3252 | lfxbb->current_state = LFXS_LightFadingDown; |
| | 3253 | } |
| | 3254 | } |
| | 3255 | break; |
| | 3256 | case LFXS_LightFadingDown: |
| | 3257 | { |
| | 3258 | if(state == 1) |
| | 3259 | { |
| | 3260 | lfxbb->timer = ONE_FIXED - lfxbb->timer; |
| | 3261 | lfxbb->current_state = LFXS_LightFadingUp; |
| | 3262 | } |
| | 3263 | } |
| | 3264 | break; |
| | 3265 | default: |
| | 3266 | { |
| | 3267 | assert (0 == "Light FX state not supported"); |
| | 3268 | break; |
| | 3269 | } |
| | 3270 | } |
| | 3271 | } |
| | 3272 | else if (lfxbb->type == LFX_FlickySwitch) |
| | 3273 | { |
| | 3274 | switch (lfxbb->current_state) |
| | 3275 | { |
| | 3276 | case LFXS_LightOn: |
| | 3277 | { |
| | 3278 | if(!state) |
| | 3279 | { |
| | 3280 | lfxbb->current_state = LFXS_LightFadingDown; |
| | 3281 | lfxbb->timer = 0; |
| | 3282 | } |
| | 3283 | } |
| | 3284 | break; |
| | 3285 | case LFXS_LightOff: |
| | 3286 | { |
| | 3287 | if(state == 1) |
| | 3288 | { |
| | 3289 | lfxbb->current_state = LFXS_LightFadingUp; |
| | 3290 | lfxbb->timer = 0; |
| | 3291 | } |
| | 3292 | break; |
| | 3293 | } |
| | 3294 | case LFXS_LightFadingUp: |
| | 3295 | { |
| | 3296 | if(!state) |
| | 3297 | { |
| | 3298 | lfxbb->multiplier = lfxbb->timer; |
| | 3299 | lfxbb->timer = ONE_FIXED - lfxbb->timer; |
| | 3300 | lfxbb->current_state = LFXS_LightFadingDown; |
| | 3301 | } |
| | 3302 | } |
| | 3303 | break; |
| | 3304 | case LFXS_LightFadingDown: |
| | 3305 | { |
| | 3306 | if(state == 1) |
| | 3307 | { |
| | 3308 | lfxbb->timer = ONE_FIXED - lfxbb->timer; |
| | 3309 | lfxbb->current_state = LFXS_LightFadingUp; |
| | 3310 | } |
| | 3311 | break; |
| | 3312 | } |
| | 3313 | default: |
| | 3314 | { |
| | 3315 | assert (0 == "Light FX state not supported"); |
| | 3316 | break; |
| | 3317 | } |
| | 3318 | } |
| | 3319 | } |
| | 3320 | else if(lfxbb->type == LFX_RandomFlicker) |
| | 3321 | { |
| | 3322 | switch (lfxbb->current_state) |
| | 3323 | { |
| | 3324 | case LFXS_Flicking: |
| | 3325 | case LFXS_NotFlicking: |
| | 3326 | if(!state) |
| | 3327 | { |
| | 3328 | //switch light off |
| | 3329 | lfxbb->current_state = LFXS_LightOff; |
| | 3330 | } |
| | 3331 | break; |
| | 3332 | case LFXS_LightOff : |
| | 3333 | if(state == 1) |
| | 3334 | { |
| | 3335 | //switch light on |
| | 3336 | lfxbb->current_state = LFXS_Flicking; |
| | 3337 | } |
| | 3338 | break; |
| | 3339 | default:; |
| | 3340 | } |
| | 3341 | } |
| | 3342 | } |
| | 3343 | break; |
| | 3344 | case I_BehaviourMissionComplete: |
| | 3345 | SendRequestToMissionStrategy(sbptr, state, message >> 1); |
| | 3346 | break; |
| | 3347 | case I_BehaviourMessage: |
| | 3348 | SendRequestToMessageStrategy(sbptr, state, message >> 1); |
| | 3349 | break; |
| | 3350 | case I_BehaviourTrackObject: |
| | 3351 | { |
| | 3352 | TRACK_OBJECT_BEHAV_BLOCK *to_bhv = (TRACK_OBJECT_BEHAV_BLOCK*)sbptr->dataptr; |
| | 3353 | assert((to_bhv->bhvr_type == I_BehaviourTrackObject)); |
| | 3354 | |
| | 3355 | if(state) |
| | 3356 | { |
| | 3357 | switch(message >> 1) |
| | 3358 | { |
| | 3359 | case 0: |
| | 3360 | to_bhv->request = track_request_start; |
| | 3361 | break; |
| | 3362 | case 1: |
| | 3363 | to_bhv->request = track_request_startforward; |
| | 3364 | break; |
| | 3365 | case 2: |
| | 3366 | to_bhv->request = track_request_startbackward; |
| | 3367 | break; |
| | 3368 | } |
| | 3369 | } |
| | 3370 | else |
| | 3371 | { |
| | 3372 | to_bhv->request = track_request_stop; |
| | 3373 | } |
| | 3374 | } |
| | 3375 | break; |
| | 3376 | case I_BehaviourFan: |
| | 3377 | { |
| | 3378 | FAN_BEHAV_BLOCK *f_bhv = (FAN_BEHAV_BLOCK*)sbptr->dataptr; |
| | 3379 | |
| | 3380 | assert((f_bhv->bhvr_type == I_BehaviourFan)); |
| | 3381 | |
| | 3382 | f_bhv->spinning = state; |
| | 3383 | } |
| | 3384 | break; |
| | 3385 | case I_BehaviourPlacedSound: |
| | 3386 | { |
| | 3387 | if(state) |
| | 3388 | StartPlacedSoundPlaying(sbptr); |
| | 3389 | else |
| | 3390 | StopPlacedSoundPlaying(sbptr); |
| | 3391 | } |
| | 3392 | break; |
| | 3393 | case I_BehaviourInanimateObject: |
| | 3394 | SendRequestToInanimateObject(sbptr, state, message >> 1); |
| | 3395 | break; |
| | 3396 | case I_BehaviourPlacedHierarchy : |
| | 3397 | SendRequestToPlacedHierarchy(sbptr, state, message >> 1); |
| | 3398 | break; |
| | 3399 | case I_BehaviourPlacedLight: |
| | 3400 | SendRequestToPlacedLight(sbptr, state,message >> 1); |
| | 3401 | break; |
| | 3402 | case I_BehaviourAlien: |
| | 3403 | { |
| | 3404 | ALIEN_STATUS_BLOCK *alienStatusPointer = (ALIEN_STATUS_BLOCK*)sbptr->dataptr; |
| | 3405 | |
| | 3406 | if (alienStatusPointer->BehaviourState == ABS_Dormant) |
| | 3407 | Alien_Awaken(sbptr); |
| | 3408 | } |
| | 3409 | break; |
| | 3410 | case I_BehaviourFaceHugger: |
| | 3411 | { |
| | 3412 | FACEHUGGER_STATUS_BLOCK *facehuggerStatusPointer = (FACEHUGGER_STATUS_BLOCK *)(sbptr->dataptr); |
| | 3413 | |
| | 3414 | if (facehuggerStatusPointer->nearBehaviourState == FHNS_Floating) |
| | 3415 | { |
| | 3416 | facehuggerStatusPointer->nearBehaviourState = FHNS_Approach; |
| | 3417 | sbptr->DynPtr->GravityOn = 1; |
| | 3418 | } |
| | 3419 | } |
| | 3420 | break; |
| | 3421 | case I_BehaviourXenoborg: |
| | 3422 | { |
| | 3423 | XENO_STATUS_BLOCK *xenoStatusPointer = (XENO_STATUS_BLOCK*)sbptr->dataptr; |
| | 3424 | |
| | 3425 | if (state) |
| | 3426 | { |
| | 3427 | if (xenoStatusPointer->behaviourState == XS_Inactive) |
| | 3428 | Xeno_Enter_PowerUp_State(sbptr); |
| | 3429 | } |
| | 3430 | else |
| | 3431 | { |
| | 3432 | if (xenoStatusPointer->behaviourState != XS_Inactive) |
| | 3433 | Xeno_Enter_PowerDown_State(sbptr); |
| | 3434 | } |
| | 3435 | } |
| | 3436 | break; |
| | 3437 | case I_BehaviourDormantPredator: |
| | 3438 | { |
| | 3439 | if(state) |
| | 3440 | ActivateDormantPredator(sbptr); |
| | 3441 | } |
| | 3442 | break; |
| | 3443 | case I_BehaviourPredator: |
| | 3444 | //do nothing |
| | 3445 | //can't assert for this one since it might previously have been a dormant predator |
| | 3446 | break; |
| | 3447 | case I_BehaviourMarine: |
| | 3448 | SendRequestToMarine(sbptr, state,message >> 1); |
| | 3449 | break; |
| | 3450 | case I_BehaviourDeathVolume: |
| | 3451 | { |
| | 3452 | DEATH_VOLUME_BEHAV_BLOCK *dv_bhv = (DEATH_VOLUME_BEHAV_BLOCK*)sbptr->dataptr; |
| | 3453 | assert((dv_bhv->bhvr_type == I_BehaviourDeathVolume)); |
| | 3454 | |
| | 3455 | dv_bhv->active = state; |
| | 3456 | } |
| | 3457 | break; |
| | 3458 | case I_BehaviourSelfDestruct: |
| | 3459 | { |
| | 3460 | SELF_DESTRUCT_BEHAV_BLOCK *sd_bhv = (SELF_DESTRUCT_BEHAV_BLOCK*)sbptr->dataptr; |
| | 3461 | assert((sd_bhv->bhvr_type == I_BehaviourSelfDestruct)); |
| | 3462 | |
| | 3463 | sd_bhv->active = state; |
| | 3464 | } |
| | 3465 | break; |
| | 3466 | case I_BehaviourParticleGenerator: |
| | 3467 | SendRequestToParticleGenerator(sbptr, state); |
| | 3468 | break; |
| | 3469 | default: |
| | 3470 | { |
| | 3471 | assert(2 < 1); |
| | 3472 | } |
| | 3473 | } |
| | 3474 | } |
| | 3475 | |
| | 3476 | int GetState(STRATEGYBLOCK* sbptr) |
| | 3477 | { |
| | 3478 | assert(sbptr); |
| | 3479 | |
| | 3480 | switch (sbptr->type) |
| | 3481 | { |
| | 3482 | case I_BehaviourBinarySwitch: |
| | 3483 | { |
| | 3484 | // 0 = rest state |
| | 3485 | // 1 = unusual state |
| | 3486 | |
| | 3487 | BINARY_SWITCH_BEHAV_BLOCK *bs_bhv = (BINARY_SWITCH_BEHAV_BLOCK*)sbptr->dataptr; |
| | 3488 | assert((bs_bhv->bhvr_type == I_BehaviourBinarySwitch)); |
| | 3489 | |
| | 3490 | return((int)bs_bhv->state); |
| | 3491 | } |
| | 3492 | case I_BehaviourLinkSwitch: |
| | 3493 | { |
| | 3494 | // 0 = rest state |
| | 3495 | // 1 = unusual state |
| | 3496 | |
| | 3497 | LINK_SWITCH_BEHAV_BLOCK *bs_bhv = (LINK_SWITCH_BEHAV_BLOCK*)sbptr->dataptr; |
| | 3498 | assert((bs_bhv->bhvr_type == I_BehaviourLinkSwitch)); |
| | 3499 | |
| | 3500 | return((int)bs_bhv->state); |
| | 3501 | } |
| | 3502 | case I_BehaviourProximityDoor: |
| | 3503 | { |
| | 3504 | PROXDOOR_BEHAV_BLOCK *door_bhv = (PROXDOOR_BEHAV_BLOCK*)sbptr->dataptr; |
| | 3505 | assert((door_bhv->bhvr_type == I_BehaviourProximityDoor)); |
| | 3506 | |
| | 3507 | // returns true only when fully open |
| | 3508 | |
| | 3509 | return (door_bhv->door_state == I_door_open); |
| | 3510 | } |
| | 3511 | case I_BehaviourSwitchDoor: |
| | 3512 | { |
| | 3513 | /* returns true if fully open (DO NOT CHANGE THIS) */ |
| | 3514 | SWITCH_DOOR_BEHAV_BLOCK *door_bhv = (SWITCH_DOOR_BEHAV_BLOCK*)sbptr->dataptr; |
| | 3515 | assert(door_bhv->myBehaviourType == I_BehaviourSwitchDoor); |
| | 3516 | |
| | 3517 | return (door_bhv->doorState == I_door_open); |
| | 3518 | } |
| | 3519 | case I_BehaviourLiftDoor: |
| | 3520 | { |
| | 3521 | LIFT_DOOR_BEHAV_BLOCK *door_bhv = (LIFT_DOOR_BEHAV_BLOCK*)sbptr->dataptr; |
| | 3522 | assert((door_bhv->bhvr_type == I_BehaviourLiftDoor)); |
| | 3523 | |
| | 3524 | // returns true only when fully open so that the lift |
| | 3525 | // dosn't start to move when we can still see out |
| | 3526 | |
| | 3527 | return !(door_bhv->door_state == I_door_closed); |
| | 3528 | } |
| | 3529 | case I_BehaviourLift: |
| | 3530 | { |
| | 3531 | LIFT_BEHAV_BLOCK *lift_bhv = (LIFT_BEHAV_BLOCK*)sbptr->dataptr; |
| | 3532 | assert((lift_bhv->bhvr_type == I_BehaviourLift)); |
| | 3533 | LIFT_STATION *lift_stn = &lift_bhv->lift_station; |
| | 3534 | assert(lift_stn); |
| | 3535 | |
| | 3536 | return(lift_stn->called); |
| | 3537 | } |
| | 3538 | default: |
| | 3539 | { |
| | 3540 | assert(2 < 1); |
| | 3541 | return 0; |
| | 3542 | } |
| | 3543 | } |
| | 3544 | } |