| | 1 | /* Patrick 14/7/97---------------------------- |
| | 2 | Source for Multi-Player ghost object support header |
| | 3 | ----------------------------------------------------------------------*/ |
| | 4 | #include "system.h" |
| | 5 | #include "prototyp.h" |
| | 6 | #include "stratdef.h" |
| | 7 | #include "bh_types.h" |
| | 8 | #include "npc_alien.h" |
| | 9 | #include "npc_marine.h" |
| | 10 | #include "pldghost.h" |
| | 11 | #include "lighting.h" |
| | 12 | #include "psndplat.h" |
| | 13 | #include "corpse.h" |
| | 14 | #include "weapons.h" |
| | 15 | #include "weaponbehaviour.h" |
| | 16 | #include <stdlib.h> |
| | 17 | #include <assert.h> |
| | 18 | |
| | 19 | #include "projload.hpp" |
| | 20 | extern const SECTION * GetNamedHierarchyFromLibrary(const char * rif_name, const char *); |
| | 21 | |
| | 22 | extern int GlobalFrameCounter; |
| | 23 | extern DEATH_DATA Alien_Deaths[]; |
| | 24 | |
| | 25 | SOUND3DDATA Ghost_Explosion_SoundData = |
| | 26 | { |
| | 27 | {0,0,0,}, |
| | 28 | {0,0,0,}, |
| | 29 | 15000, |
| | 30 | 150000 |
| | 31 | }; |
| | 32 | |
| | 33 | static void SetPlayerGhostAnimationSequence(STRATEGYBLOCK *sbPtr, int sequence, int special) |
| | 34 | { |
| | 35 | DELTA_CONTROLLER *FireLeft,*FireRight; |
| | 36 | |
| | 37 | assert(sbPtr); |
| | 38 | NETGHOSTDATABLOCK *ghostData = (NETGHOSTDATABLOCK *)sbPtr->dataptr; |
| | 39 | assert(ghostData); |
| | 40 | AVP_BEHAVIOUR_TYPE type = ghostData->type; |
| | 41 | |
| | 42 | if(!sbPtr->DisplayBlock) |
| | 43 | { |
| | 44 | /* update the ghost's current sequence: do this even if we don't have a displayblock */ |
| | 45 | ghostData->currentAnimSequence = sequence; |
| | 46 | return; /* no displayblock: can't actually set it */ |
| | 47 | } |
| | 48 | |
| | 49 | switch(type) |
| | 50 | { |
| | 51 | case I_BehaviourMarinePlayer: |
| | 52 | { |
| | 53 | switch((MARINE_SEQUENCE)sequence) |
| | 54 | { |
| | 55 | case MSQ_Walk: |
| | 56 | { |
| | 57 | switch(ghostData->CurrentWeapon) |
| | 58 | { |
| | 59 | case WEAPON_SMARTGUN: |
| | 60 |
InitHModelTweening(&ghostData->HModelController,(ONE_FIXED)>>3,(int)HMSQT_MarineRun,(int)MRSS_Attack_Primary,(ONE_FIXED>>1),1); |
| | 61 | break; |
| | 62 | case WEAPON_MARINE_PISTOL: |
| | 63 |
InitHModelTweening(&ghostData->HModelController,(ONE_FIXED)>>3,(int)HMSQT_MarineRun,(int)MRSS_Attack_Primary,(ONE_FIXED>>1),1); |
| | 64 | break; |
| | 65 | case WEAPON_TWO_PISTOLS: |
| | 66 | { |
| | 67 | /* Oh, no. */ |
| | 68 | if (special) |
| | 69 | { |
| | 70 | if ((ghostData->HModelController.Sequence_Type != (int)HMSQT_MarineRun) || (ghostData->HModelController.Sub_Sequence != MRSS_Fire_From_Hips)) |
| | 71 | InitHModelTweening(&ghostData->HModelController,(ONE_FIXED)>>3,(int)HMSQT_MarineRun,(int)MRSS_Fire_From_Hips,(ONE_FIXED>>1),1); |
| | 72 | } |
| | 73 | else |
| | 74 | { |
| | 75 | if ((ghostData->HModelController.Sequence_Type != (int)HMSQT_MarineRun) || (ghostData->HModelController.Sub_Sequence != MRSS_Standard)) |
| | 76 | InitHModelTweening(&ghostData->HModelController,(ONE_FIXED)>>3,(int)HMSQT_MarineRun,(int)MRSS_Standard,(ONE_FIXED>>1),1); |
| | 77 | } |
| | 78 | } |
| | 79 | break; |
| | 80 | default: |
| | 81 | InitHModelTweening(&ghostData->HModelController,(ONE_FIXED)>>3,(int)HMSQT_MarineRun,(int)MRSS_Standard,(ONE_FIXED>>1),1); |
| | 82 | } |
| | 83 | } |
| | 84 | break; |
| | 85 | case MSQ_Walk_Backwards: |
| | 86 | { |
| | 87 | switch(ghostData->CurrentWeapon) |
| | 88 | { |
| | 89 | case WEAPON_SMARTGUN: |
| | 90 | InitHModelSequence(&ghostData->HModelController,(int)HMSQT_MarineRun,(int)MRSS_Attack_Primary,(ONE_FIXED>>1)); |
| | 91 | break; |
| | 92 | case WEAPON_MARINE_PISTOL: |
| | 93 | InitHModelSequence(&ghostData->HModelController,(int)HMSQT_MarineRun,(int)MRSS_Attack_Primary,(ONE_FIXED>>1)); |
| | 94 | break; |
| | 95 | case WEAPON_TWO_PISTOLS: |
| | 96 | { |
| | 97 | /* Oh, no. */ |
| | 98 | if (special) |
| | 99 | { |
| | 100 | if ((ghostData->HModelController.Sequence_Type!=(int)HMSQT_MarineRun) || (ghostData->HModelController.Sub_Sequence !=
MRSS_Fire_From_Hips)) |
| | 101 |
InitHModelTweening(&ghostData->HModelController,(ONE_FIXED)>>3,(int)HMSQT_MarineRun,(int)MRSS_Fire_From_Hips,(ONE_FIXED>>1),1); |
| | 102 | } |
| | 103 | else |
| | 104 | { |
| | 105 | if ((ghostData->HModelController.Sequence_Type != (int)HMSQT_MarineRun)||(ghostData->HModelController.Sub_Sequence != MRSS_Standard)) |
| | 106 | InitHModelTweening(&ghostData->HModelController,(ONE_FIXED)>>3,(int)HMSQT_MarineRun,(int)MRSS_Standard,(ONE_FIXED>>1),1); |
| | 107 | } |
| | 108 | } |
| | 109 | break; |
| | 110 | default: |
| | 111 | { |
| | 112 | InitHModelSequence(&ghostData->HModelController,(int)HMSQT_MarineRun,(int)MRSS_Standard,(ONE_FIXED>>1)); |
| | 113 | } |
| | 114 | } |
| | 115 | ghostData->HModelController.Reversed = 1; |
| | 116 | } |
| | 117 | break; |
| | 118 | case MSQ_RunningFire: |
| | 119 | { |
| | 120 | switch(ghostData->CurrentWeapon) |
| | 121 | { |
| | 122 | case WEAPON_MARINE_PISTOL: |
| | 123 | InitHModelSequence(&ghostData->HModelController,(int)HMSQT_MarineRun,(int)MRSS_Attack_Primary,(ONE_FIXED>>1)); |
| | 124 | break; |
| | 125 | case WEAPON_TWO_PISTOLS: |
| | 126 | { |
| | 127 | FireRight = Get_Delta_Sequence(&ghostData->HModelController,"FireRight"); |
| | 128 | |
| | 129 | if (FireRight == NULL) |
| | 130 | { |
| | 131 | FireRight =
Add_Delta_Sequence(&ghostData->HModelController,"FireRight",HMSQT_MarineStand,MSSS_Attack_Primary,ONE_FIXED); |
| | 132 | FireRight->Playing = 0; |
| | 133 | FireRight->Active = 0; |
| | 134 | } |
| | 135 | |
| | 136 | FireLeft = Get_Delta_Sequence(&ghostData->HModelController,"FireLeft"); |
| | 137 | |
| | 138 | if (FireLeft == NULL) |
| | 139 | { |
| | 140 | FireLeft =
Add_Delta_Sequence(&ghostData->HModelController,"FireLeft",HMSQT_MarineStand,MSSS_Attack_Secondary,ONE_FIXED); |
| | 141 | FireLeft->Playing = 0; |
| | 142 | FireLeft->Active = 0; |
| | 143 | } |
| | 144 | |
| | 145 | if (special) |
| | 146 | { |
| | 147 | if ((ghostData->HModelController.Sequence_Type != (int)HMSQT_MarineRun) || (ghostData->HModelController.Sub_Sequence !=
MRSS_Fire_From_Hips)) |
| | 148 |
InitHModelTweening(&ghostData->HModelController,(ONE_FIXED)>>3,(int)HMSQT_MarineRun,(int)MRSS_Fire_From_Hips,(ONE_FIXED>>1),1); |
| | 149 | } |
| | 150 | else |
| | 151 | { |
| | 152 | if ((ghostData->HModelController.Sequence_Type != (int)HMSQT_MarineRun) || (ghostData->HModelController.Sub_Sequence != MRSS_Standard)) |
| | 153 | InitHModelTweening(&ghostData->HModelController,(ONE_FIXED)>>3,(int)HMSQT_MarineRun,(int)MRSS_Standard,(ONE_FIXED>>1),1); |
| | 154 | } |
| | 155 | |
| | 156 | Start_Delta_Sequence(FireRight,HMSQT_MarineStand,MSSS_Attack_Primary,-1); |
| | 157 | FireRight->Playing = 1; |
| | 158 | FireRight->Active = 1; |
| | 159 | } |
| | 160 | break; |
| | 161 | default: |
| | 162 | InitHModelSequence(&ghostData->HModelController,(int)HMSQT_MarineRun,(int)MRSS_Attack_Primary,(ONE_FIXED>>1)); |
| | 163 | } |
| | 164 | } |
| | 165 | break; |
| | 166 | case MSQ_RunningFireSecondary: |
| | 167 | { |
| | 168 | switch(ghostData->CurrentWeapon) |
| | 169 | { |
| | 170 | case WEAPON_MARINE_PISTOL: |
| | 171 | InitHModelSequence(&ghostData->HModelController,(int)HMSQT_MarineRun,(int)MRSS_Attack_Primary,(ONE_FIXED>>1)); |
| | 172 | break; |
| | 173 | case WEAPON_TWO_PISTOLS: |
| | 174 | { |
| | 175 | FireRight = Get_Delta_Sequence(&ghostData->HModelController,"FireRight"); |
| | 176 | |
| | 177 | if (FireRight == NULL) |
| | 178 | { |
| | 179 | FireRight =
Add_Delta_Sequence(&ghostData->HModelController,"FireRight",HMSQT_MarineStand,MSSS_Attack_Primary,ONE_FIXED); |
| | 180 | FireRight->Playing = 0; |
| | 181 | FireRight->Active = 0; |
| | 182 | } |
| | 183 | |
| | 184 | FireLeft = Get_Delta_Sequence(&ghostData->HModelController,"FireLeft"); |
| | 185 | |
| | 186 | if (FireLeft == NULL) |
| | 187 | { |
| | 188 | FireLeft =
Add_Delta_Sequence(&ghostData->HModelController,"FireLeft",HMSQT_MarineStand,MSSS_Attack_Secondary,ONE_FIXED); |
| | 189 | FireLeft->Playing = 0; |
| | 190 | FireLeft->Active = 0; |
| | 191 | } |
| | 192 | |
| | 193 | if (special) |
| | 194 | { |
| | 195 | if ((ghostData->HModelController.Sequence_Type != (int)HMSQT_MarineRun) || (ghostData->HModelController.Sub_Sequence != MRSS_Fire_From_Hips)) |
| | 196 |
InitHModelTweening(&ghostData->HModelController,(ONE_FIXED)>>3,(int)HMSQT_MarineRun,(int)MRSS_Fire_From_Hips,(ONE_FIXED>>1),1); |
| | 197 | } |
| | 198 | else |
| | 199 | { |
| | 200 | if ((ghostData->HModelController.Sequence_Type != (int)HMSQT_MarineRun) || (ghostData->HModelController.Sub_Sequence!= MRSS_Standard)) |
| | 201 | InitHModelTweening(&ghostData->HModelController,(ONE_FIXED)>>3,(int)HMSQT_MarineRun,(int)MRSS_Standard,(ONE_FIXED>>1),1); |
| | 202 | } |
| | 203 | |
| | 204 | Start_Delta_Sequence(FireLeft,HMSQT_MarineStand,MSSS_Attack_Secondary,-1); |
| | 205 | FireLeft->Playing = 1; |
| | 206 | FireLeft->Active = 1; |
| | 207 | } |
| | 208 | break; |
| | 209 | default: |
| | 210 | InitHModelSequence(&ghostData->HModelController,(int)HMSQT_MarineRun,(int)MRSS_Attack_Primary,(ONE_FIXED>>1)); |
| | 211 | } |
| | 212 | } |
| | 213 | break; |
| | 214 | case MSQ_RunningFire_Backwards: |
| | 215 | { |
| | 216 | switch(ghostData->CurrentWeapon) |
| | 217 | { |
| | 218 | case WEAPON_MARINE_PISTOL: |
| | 219 | { |
| | 220 | InitHModelSequence(&ghostData->HModelController,(int)HMSQT_MarineRun,(int)MRSS_Attack_Primary,(ONE_FIXED>>1)); |
| | 221 | ghostData->HModelController.Reversed = 1; |
| | 222 | } |
| | 223 | break; |
| | 224 | case WEAPON_TWO_PISTOLS: |
| | 225 | { |
| | 226 | FireRight = Get_Delta_Sequence(&ghostData->HModelController,"FireRight"); |
| | 227 | |
| | 228 | if (FireRight == NULL) |
| | 229 | { |
| | 230 | FireRight =
Add_Delta_Sequence(&ghostData->HModelController,"FireRight",HMSQT_MarineStand,MSSS_Attack_Primary,ONE_FIXED); |
| | 231 | FireRight->Playing = 0; |
| | 232 | FireRight->Active = 0; |
| | 233 | } |
| | 234 | |
| | 235 | FireLeft = Get_Delta_Sequence(&ghostData->HModelController,"FireLeft"); |
| | 236 | |
| | 237 | if (FireLeft == NULL) |
| | 238 | { |
| | 239 | FireLeft =
Add_Delta_Sequence(&ghostData->HModelController,"FireLeft",HMSQT_MarineStand,MSSS_Attack_Secondary,ONE_FIXED); |
| | 240 | FireLeft->Playing = 0; |
| | 241 | FireLeft->Active = 0; |
| | 242 | } |
| | 243 | |
| | 244 | if (special) |
| | 245 | { |
| | 246 | if ((ghostData->HModelController.Sequence_Type != (int)HMSQT_MarineRun) || (ghostData->HModelController.Sub_Sequence !=
MRSS_Fire_From_Hips)) |
| | 247 | { |
| | 248 |
InitHModelTweening(&ghostData->HModelController,(ONE_FIXED)>>3,(int)HMSQT_MarineRun,(int)MRSS_Fire_From_Hips,(ONE_FIXED>>1),1); |
| | 249 | ghostData->HModelController.Reversed = 1; |
| | 250 | } |
| | 251 | } |
| | 252 | else |
| | 253 | { |
| | 254 | if ((ghostData->HModelController.Sequence_Type != (int)HMSQT_MarineRun) || (ghostData->HModelController.Sub_Sequence !=
MRSS_Standard)) |
| | 255 | { |
| | 256 |
InitHModelTweening(&ghostData->HModelController,(ONE_FIXED)>>3,(int)HMSQT_MarineRun,(int)MRSS_Standard,(ONE_FIXED>>1),1); |
| | 257 | ghostData->HModelController.Reversed = 1; |
| | 258 | } |
| | 259 | } |
| | 260 | |
| | 261 | Start_Delta_Sequence(FireRight,HMSQT_MarineStand,MSSS_Attack_Primary,-1); |
| | 262 | FireRight->Playing = 1; |
| | 263 | FireRight->Active = 1; |
| | 264 | } |
| | 265 | break; |
| | 266 | default: |
| | 267 | { |
| | 268 | InitHModelSequence(&ghostData->HModelController,(int)HMSQT_MarineRun,(int)MRSS_Attack_Primary,(ONE_FIXED>>1)); |
| | 269 | ghostData->HModelController.Reversed = 1; |
| | 270 | } |
| | 271 | } |
| | 272 | } |
| | 273 | break; |
| | 274 | case MSQ_RunningFireSecondary_Backwards: |
| | 275 | { |
| | 276 | switch(ghostData->CurrentWeapon) |
| | 277 | { |
| | 278 | case WEAPON_MARINE_PISTOL: |
| | 279 | { |
| | 280 | InitHModelSequence(&ghostData->HModelController,(int)HMSQT_MarineRun,(int)MRSS_Attack_Primary,(ONE_FIXED>>1)); |
| | 281 | ghostData->HModelController.Reversed = 1; |
| | 282 | } |
| | 283 | break; |
| | 284 | case WEAPON_TWO_PISTOLS: |
| | 285 | { |
| | 286 | FireRight = Get_Delta_Sequence(&ghostData->HModelController,"FireRight"); |
| | 287 | |
| | 288 | if (FireRight == NULL) |
| | 289 | { |
| | 290 | FireRight =
Add_Delta_Sequence(&ghostData->HModelController,"FireRight",HMSQT_MarineStand,MSSS_Attack_Primary,ONE_FIXED); |
| | 291 | FireRight->Playing = 0; |
| | 292 | FireRight->Active = 0; |
| | 293 | } |
| | 294 | |
| | 295 | FireLeft = Get_Delta_Sequence(&ghostData->HModelController,"FireLeft"); |
| | 296 | |
| | 297 | if (FireLeft == NULL) |
| | 298 | { |
| | 299 | FireLeft =
Add_Delta_Sequence(&ghostData->HModelController,"FireLeft",HMSQT_MarineStand,MSSS_Attack_Secondary,ONE_FIXED); |
| | 300 | FireLeft->Playing = 0; |
| | 301 | FireLeft->Active = 0; |
| | 302 | } |
| | 303 | |
| | 304 | if (special) |
| | 305 | { |
| | 306 | if ((ghostData->HModelController.Sequence_Type != (int)HMSQT_MarineRun) || (ghostData->HModelController.Sub_Sequence !=
MRSS_Fire_From_Hips)) |
| | 307 | { |
| | 308 |
InitHModelTweening(&ghostData->HModelController,(ONE_FIXED)>>3,(int)HMSQT_MarineRun,(int)MRSS_Fire_From_Hips,(ONE_FIXED>>1),1); |
| | 309 | ghostData->HModelController.Reversed = 1; |
| | 310 | } |
| | 311 | } |
| | 312 | else |
| | 313 | { |
| | 314 | if ((ghostData->HModelController.Sequence_Type != (int)HMSQT_MarineRun) || (ghostData->HModelController.Sub_Sequence !=
MRSS_Standard)) |
| | 315 | { |
| | 316 | InitHModelTweening(&ghostData->HModelController,(ONE_FIXED)>>3,(int)HMSQT_MarineRun,(int)MRSS_Standard,(ONE_FIXED>>1),1); |
| | 317 | ghostData->HModelController.Reversed = 1; |
| | 318 | } |
| | 319 | } |
| | 320 | Start_Delta_Sequence(FireLeft,HMSQT_MarineStand,MSSS_Attack_Secondary,-1); |
| | 321 | FireLeft->Playing = 1; |
| | 322 | FireLeft->Active = 1; |
| | 323 | } |
| | 324 | break; |
| | 325 | default: |
| | 326 | { |
| | 327 | InitHModelSequence(&ghostData->HModelController,(int)HMSQT_MarineRun,(int)MRSS_Attack_Primary,(ONE_FIXED>>1)); |
| | 328 | ghostData->HModelController.Reversed = 1; |
| | 329 | } |
| | 330 | } |
| | 331 | } |
| | 332 | break; |
| | 333 | case MSQ_StandingFire: |
| | 334 | { |
| | 335 | switch(ghostData->CurrentWeapon) |
| | 336 | { |
| | 337 | case WEAPON_TWO_PISTOLS: |
| | 338 | { |
| | 339 | FireRight = Get_Delta_Sequence(&ghostData->HModelController,"FireRight"); |
| | 340 | |
| | 341 | if (FireRight == NULL) |
| | 342 | { |
| | 343 | FireRight =
Add_Delta_Sequence(&ghostData->HModelController,"FireRight",HMSQT_MarineStand,MSSS_Attack_Primary,ONE_FIXED); |
| | 344 | FireRight->Playing = 0; |
| | 345 | FireRight->Active = 0; |
| | 346 | } |
| | 347 | |
| | 348 | FireLeft = Get_Delta_Sequence(&ghostData->HModelController,"FireLeft"); |
| | 349 | |
| | 350 | if (FireLeft == NULL) |
| | 351 | { |
| | 352 | FireLeft =
Add_Delta_Sequence(&ghostData->HModelController,"FireLeft",HMSQT_MarineStand,MSSS_Attack_Secondary,ONE_FIXED); |
| | 353 | FireLeft->Playing = 0; |
| | 354 | FireLeft->Active = 0; |
| | 355 | } |
| | 356 | |
| | 357 | if (special) |
| | 358 | { |
| | 359 | if ((ghostData->HModelController.Sequence_Type != (int)HMSQT_MarineStand) || (ghostData->HModelController.Sub_Sequence !=
MSSS_FireFromHips)) |
| | 360 |
InitHModelTweening(&ghostData->HModelController,(ONE_FIXED)>>3,(int)HMSQT_MarineStand,(int)MSSS_FireFromHips,(ONE_FIXED>>1),1); |
| | 361 | } |
| | 362 | else |
| | 363 | { |
| | 364 | if ((ghostData->HModelController.Sequence_Type != (int)HMSQT_MarineStand) || (ghostData->HModelController.Sub_Sequence != MSSS_Standard)) |
| | 365 | InitHModelTweening(&ghostData->HModelController,(ONE_FIXED)>>3,(int)HMSQT_MarineStand,(int)MSSS_Standard,(ONE_FIXED>>1),1); |
| | 366 | } |
| | 367 | |
| | 368 | Start_Delta_Sequence(FireRight,HMSQT_MarineStand,MSSS_Attack_Primary,-1); |
| | 369 | FireRight->Playing = 1; |
| | 370 | FireRight->Active = 1; |
| | 371 | } |
| | 372 | break; |
| | 373 | default: |
| | 374 | InitHModelSequence(&ghostData->HModelController,(int)HMSQT_MarineStand,(int)MSSS_Attack_Primary,ONE_FIXED); |
| | 375 | } |
| | 376 | } |
| | 377 | break; |
| | 378 | case MSQ_StandingFireSecondary: |
| | 379 | { |
| | 380 | switch(ghostData->CurrentWeapon) |
| | 381 | { |
| | 382 | case WEAPON_TWO_PISTOLS: |
| | 383 | { |
| | 384 | FireRight = Get_Delta_Sequence(&ghostData->HModelController,"FireRight"); |
| | 385 | |
| | 386 | if (FireRight == NULL) |
| | 387 | { |
| | 388 | FireRight =
Add_Delta_Sequence(&ghostData->HModelController,"FireRight",HMSQT_MarineStand,MSSS_Attack_Primary,ONE_FIXED); |
| | 389 | FireRight->Playing = 0; |
| | 390 | FireRight->Active = 0; |
| | 391 | } |
| | 392 | |
| | 393 | FireLeft = Get_Delta_Sequence(&ghostData->HModelController,"FireLeft"); |
| | 394 | |
| | 395 | if (FireLeft == NULL) |
| | 396 | { |
| | 397 | FireLeft =
Add_Delta_Sequence(&ghostData->HModelController,"FireLeft",HMSQT_MarineStand,MSSS_Attack_Secondary,ONE_FIXED); |
| | 398 | FireLeft->Playing = 0; |
| | 399 | FireLeft->Active = 0; |
| | 400 | } |
| | 401 | |
| | 402 | if (special) |
| | 403 | { |
| | 404 | if ((ghostData->HModelController.Sequence_Type != (int)HMSQT_MarineStand) || (ghostData->HModelController.Sub_Sequence !=
MSSS_FireFromHips)) |
| | 405 |
InitHModelTweening(&ghostData->HModelController,(ONE_FIXED)>>3,(int)HMSQT_MarineStand,(int)MSSS_FireFromHips,(ONE_FIXED>>1),1); |
| | 406 | } |
| | 407 | else |
| | 408 | { |
| | 409 | if ((ghostData->HModelController.Sequence_Type != (int)HMSQT_MarineStand) || (ghostData->HModelController.Sub_Sequence != MSSS_Standard)) |
| | 410 | InitHModelTweening(&ghostData->HModelController,(ONE_FIXED)>>3,(int)HMSQT_MarineStand,(int)MSSS_Standard,(ONE_FIXED>>1),1); |
| | 411 | } |
| | 412 | |
| | 413 | Start_Delta_Sequence(FireLeft,HMSQT_MarineStand,MSSS_Attack_Secondary,-1); |
| | 414 | FireLeft->Playing = 1; |
| | 415 | FireLeft->Active = 1; |
| | 416 | } |
| | 417 | break; |
| | 418 | default: |
| | 419 | InitHModelSequence(&ghostData->HModelController,(int)HMSQT_MarineStand,(int)MSSS_Attack_Primary,ONE_FIXED); |
| | 420 | } |
| | 421 | } |
| | 422 | break; |
| | 423 | case MSQ_Stand: |
| | 424 | { |
| | 425 | /* Removed the test for 'standing swipe'... */ |
| | 426 | if(ghostData->currentAnimSequence >= MSQ_BaseOfCudgelAttacks) |
| | 427 | { |
| | 428 | if((ghostData->currentAnimSequence - MSQ_BaseOfCudgelAttacks) % 2 == 1) |
| | 429 | { |
| | 430 | //if currently playing a standing attack allow it to finish first |
| | 431 | if(!HModelAnimation_IsFinished(&ghostData->HModelController)) |
| | 432 | return; |
| | 433 | } |
| | 434 | } |
| | 435 | |
| | 436 | if (ghostData->CurrentWeapon == WEAPON_TWO_PISTOLS) |
| | 437 | { |
| | 438 | if (special) |
| | 439 | { |
| | 440 | if ((ghostData->HModelController.Sequence_Type != (int)HMSQT_MarineStand) || (ghostData->HModelController.Sub_Sequence != MSSS_FireFromHips)) |
| | 441 | InitHModelTweening(&ghostData->HModelController,(ONE_FIXED)>>3,(int)HMSQT_MarineStand,(int)MSSS_FireFromHips,(ONE_FIXED>>1),1); |
| | 442 | } |
| | 443 | else |
| | 444 | { |
| | 445 | if ((ghostData->HModelController.Sequence_Type != (int)HMSQT_MarineStand) || (ghostData->HModelController.Sub_Sequence != MSSS_Standard)) |
| | 446 | InitHModelTweening(&ghostData->HModelController,(ONE_FIXED)>>3,(int)HMSQT_MarineStand,(int)MSSS_Standard,(ONE_FIXED>>1),1); |
| | 447 | } |
| | 448 | } |
| | 449 | else |
| | 450 | { |
| | 451 | InitHModelTweening(&ghostData->HModelController,(ONE_FIXED)>>3,(int)HMSQT_MarineStand,(int)MSSS_Standard,ONE_FIXED,1); |
| | 452 | // InitHModelSequence(&ghostData->HModelController,(int)HMSQT_MarineStand,(int)MSSS_Standard,ONE_FIXED); |
| | 453 | } |
| | 454 | } |
| | 455 | break; |
| | 456 | case MSQ_Crawl: |
| | 457 | { |
| | 458 | if (ghostData->CurrentWeapon == WEAPON_TWO_PISTOLS) |
| | 459 | { |
| | 460 | if (special) |
| | 461 | { |
| | 462 | if ((ghostData->HModelController.Sequence_Type != (int)HMSQT_MarineCrawl) || (ghostData->HModelController.Sub_Sequence != MCSS_FireFromHips)) |
| | 463 | InitHModelTweening(&ghostData->HModelController,(ONE_FIXED)>>3,(int)HMSQT_MarineCrawl,(int)MCSS_FireFromHips,(ONE_FIXED>>1),1); |
| | 464 | } |
| | 465 | else |
| | 466 | { |
| | 467 | if ((ghostData->HModelController.Sequence_Type != (int)HMSQT_MarineCrawl) || (ghostData->HModelController.Sub_Sequence != MCSS_Standard)) |
| | 468 | InitHModelTweening(&ghostData->HModelController,(ONE_FIXED)>>3,(int)HMSQT_MarineCrawl,(int)MCSS_Standard,(ONE_FIXED>>1),1); |
| | 469 | } |
| | 470 | } |
| | 471 | else |
| | 472 | { |
| | 473 |
InitHModelTweening(&ghostData->HModelController,(ONE_FIXED>>3),(int)HMSQT_MarineCrawl,(int)MCSS_Standard,(ONE_FIXED>>1),1); |
| | 474 | } |
| | 475 | } |
| | 476 | break; |
| | 477 | case MSQ_Crawl_Backwards: |
| | 478 | { |
| | 479 | if (ghostData->CurrentWeapon == WEAPON_TWO_PISTOLS) |
| | 480 | { |
| | 481 | if (special) |
| | 482 | { |
| | 483 | if ((ghostData->HModelController.Sequence_Type != (int)HMSQT_MarineCrawl) || (ghostData->HModelController.Sub_Sequence != MCSS_FireFromHips)) |
| | 484 | InitHModelTweening(&ghostData->HModelController,(ONE_FIXED)>>3,(int)HMSQT_MarineCrawl,(int)MCSS_FireFromHips,(ONE_FIXED>>1),1); |
| | 485 | } |
| | 486 | else |
| | 487 | { |
| | 488 | if ((ghostData->HModelController.Sequence_Type != (int)HMSQT_MarineCrawl) || (ghostData->HModelController.Sub_Sequence != MCSS_Standard)) |
| | 489 | InitHModelTweening(&ghostData->HModelController,(ONE_FIXED)>>3,(int)HMSQT_MarineCrawl,(int)MCSS_Standard,(ONE_FIXED>>1),1); |
| | 490 | } |
| | 491 | } |
| | 492 | else |
| | 493 | { |
| | 494 | InitHModelSequence(&ghostData->HModelController,(int)HMSQT_MarineCrawl,(int)MCSS_Standard,(ONE_FIXED>>1)); |
| | 495 | } |
| | 496 | ghostData->HModelController.Reversed = 1; |
| | 497 | } |
| | 498 | break; |
| | 499 | case MSQ_Crouch: |
| | 500 | { |
| | 501 | if(ghostData->currentAnimSequence >= MSQ_BaseOfCudgelAttacks) |
| | 502 | { |
| | 503 | if((ghostData->currentAnimSequence-MSQ_BaseOfCudgelAttacks) % 2 == 0) |
| | 504 | { |
| | 505 | //if currently playing a standing attack allow it to finish first |
| | 506 | if(!HModelAnimation_IsFinished(&ghostData->HModelController)) return; |
| | 507 | } |
| | 508 | } |
| | 509 | |
| | 510 | if (ghostData->CurrentWeapon == WEAPON_TWO_PISTOLS) |
| | 511 | { |
| | 512 | if (special) |
| | 513 | { |
| | 514 | if ((ghostData->HModelController.Sequence_Type != (int)HMSQT_MarineCrouch) || (ghostData->HModelController.Sub_Sequence !=
MCrSS_FireFromHips)) |
| | 515 | InitHModelTweening(&ghostData->HModelController,(ONE_FIXED)>>3,(int)HMSQT_MarineCrouch,(int)MCrSS_FireFromHips,(ONE_FIXED>>1),1); |
| | 516 | } |
| | 517 | else |
| | 518 | { |
| | 519 | if ((ghostData->HModelController.Sequence_Type != (int)HMSQT_MarineCrouch) || (ghostData->HModelController.Sub_Sequence != MCrSS_Standard)) |
| | 520 | InitHModelTweening(&ghostData->HModelController,(ONE_FIXED)>>3,(int)HMSQT_MarineCrouch,(int)MCrSS_Standard,(ONE_FIXED>>1),1); |
| | 521 | } |
| | 522 | } |
| | 523 | else |
| | 524 | { |
| | 525 | InitHModelTweening(&ghostData->HModelController,(ONE_FIXED>>3),(int)HMSQT_MarineCrouch,(int)MCrSS_Standard,ONE_FIXED,1); |
| | 526 | } |
| | 527 | } |
| | 528 | break; |
| | 529 | case MSQ_Jump: |
| | 530 | { |
| | 531 | if (HModelSequence_Exists(&ghostData->HModelController,(int)HMSQT_MarineStand,(int)MSSS_Jump)) |
| | 532 | InitHModelTweening(&ghostData->HModelController,(ONE_FIXED>>3),(int)HMSQT_MarineStand,(int)MSSS_Jump,(ONE_FIXED),0); |
| | 533 | else |
| | 534 | InitHModelTweening(&ghostData->HModelController,(ONE_FIXED)>>3,(int)HMSQT_MarineStand,(int)MSSS_Standard,ONE_FIXED,1); |
| | 535 | } |
| | 536 | break; |
| | 537 | case MSQ_Taunt: |
| | 538 | { |
| | 539 | if (HModelSequence_Exists(&ghostData->HModelController,(int)HMSQT_MarineStand,(int)MSSS_Taunt_One)) |
| | 540 | { |
| | 541 | if ((ghostData->HModelController.Sequence_Type != (int)HMSQT_MarineStand) || (ghostData->HModelController.Sub_Sequence != MSSS_Taunt_One)) |
| | 542 |
InitHModelTweening(&ghostData->HModelController,(ONE_FIXED>>3),(int)HMSQT_MarineStand,(int)MSSS_Taunt_One,(TAUNT_LENGTH-(ONE_FIXED>>3)),0); |
| | 543 | } |
| | 544 | else |
| | 545 | { |
| | 546 | /* Default. */ |
| | 547 | InitHModelTweening(&ghostData->HModelController,(ONE_FIXED)>>3,(int)HMSQT_MarineStand,(int)MSSS_Standard,ONE_FIXED,1); |
| | 548 | } |
| | 549 | } |
| | 550 | break; |
| | 551 | case MSQ_StandDieFront: |
| | 552 | case MSQ_CrouchDie: |
| | 553 | break; |
| | 554 | default: |
| | 555 | { |
| | 556 | int attack; |
| | 557 | /* Now includes cudgel attacks... */ |
| | 558 | if ((int)sequence >= (int)MSQ_BaseOfCudgelAttacks) |
| | 559 | { |
| | 560 | attack = (int)sequence - (int)MSQ_BaseOfCudgelAttacks; |
| | 561 | |
| | 562 | if(ghostData->currentAnimSequence >= MSQ_BaseOfCudgelAttacks) |
| | 563 | { |
| | 564 | //already playing some form of attack |
| | 565 | if(!HModelAnimation_IsFinished(&ghostData->HModelController)) |
| | 566 | return; |
| | 567 | } |
| | 568 | |
| | 569 | switch (attack) |
| | 570 | { |
| | 571 | case 0: |
| | 572 | /* Crouching Primary Fire. */ |
| | 573 | InitHModelTweening(&ghostData->HModelController,(ONE_FIXED>>4),(int)HMSQT_MarineCrouch,(int)MCrSS_Attack_Primary,-1,0); |
| | 574 | break; |
| | 575 | case 1: |
| | 576 | /* Standing Primary Fire. */ |
| | 577 | InitHModelTweening(&ghostData->HModelController,(ONE_FIXED>>4),(int)HMSQT_MarineStand,(int)MSSS_Attack_Primary,-1,0); |
| | 578 | break; |
| | 579 | case 2: |
| | 580 | /* Crouching Secondary Fire. */ |
| | 581 | InitHModelTweening(&ghostData->HModelController,(ONE_FIXED>>4),(int)HMSQT_MarineCrouch,(int)MCrSS_Attack_Secondary,-1,0); |
| | 582 | break; |
| | 583 | case 3: |
| | 584 | /* Standing Secondary Fire. */ |
| | 585 | InitHModelTweening(&ghostData->HModelController,(ONE_FIXED>>4),(int)HMSQT_MarineStand,(int)MSSS_Attack_Secondary,-1,0); |
| | 586 | break; |
| | 587 | default: |
| | 588 | /* KJL 16:56:15 26/11/98 - hmm. Any 'unknown' attacks will be replaced with a fast jab */ |
| | 589 | { |
| | 590 | if (attack & 1) |
| | 591 | { |
| | 592 | /* Standing Fast Jab. */ |
| | 593 | InitHModelTweening(&ghostData->HModelController,(ONE_FIXED>>4),(int)HMSQT_MarineStand,(int)MSSS_Attack_Primary,-1,0); |
| | 594 | } |
| | 595 | else |
| | 596 | { |
| | 597 | /* Crouching Fast Jab. */ |
| | 598 | InitHModelTweening(&ghostData->HModelController,(ONE_FIXED>>4),(int)HMSQT_MarineCrouch,(int)MCrSS_Attack_Primary,-1,0); |
| | 599 | } |
| | 600 | } |
| | 601 | } |
| | 602 | } |
| | 603 | else |
| | 604 | { |
| | 605 | attack = (int)sequence - (int)MSQ_BaseOfCudgelAttacks; |
| | 606 | |
| | 607 | if (attack) |
| | 608 | InitHModelTweening(&ghostData->HModelController,(ONE_FIXED>>3),(int)HMSQT_PredatorCrouch,(int)PCrSS_Attack_Primary,-1,0); |
| | 609 | else |
| | 610 | InitHModelTweening(&ghostData->HModelController,(ONE_FIXED>>3),(int)HMSQT_PredatorStand,(int)PSSS_Attack_Primary,-1,0); |
| | 611 | } |
| | 612 | } |
| | 613 | } |
| | 614 | } |
| | 615 | break; |
| | 616 | case I_BehaviourAlienPlayer: |
| | 617 | case I_BehaviourAlien: |
| | 618 | { |
| | 619 | switch((ALIEN_SEQUENCE)sequence) |
| | 620 | { |
| | 621 | case ASQ_Stand: |
| | 622 | case ASQ_StandingTailPoise: |
| | 623 | { |
| | 624 | switch(ghostData->currentAnimSequence) |
| | 625 | { |
| | 626 | case ASQ_StandingAttack_Claw: |
| | 627 | case ASQ_StandingTailStrike: |
| | 628 | case ASQ_Eat: |
| | 629 | { |
| | 630 | //if currently playing a standing attack allow it to finish first |
| | 631 | if(!HModelAnimation_IsFinished(&ghostData->HModelController)) |
| | 632 | return; |
| | 633 | } |
| | 634 | default: |
| | 635 | break; |
| | 636 | } |
| | 637 | |
| | 638 | InitHModelTweening(&ghostData->HModelController,(ONE_FIXED>>3),(int)HMSQT_AlienStand,(int)ASSS_Standard,ONE_FIXED,1); |
| | 639 | break; |
| | 640 | } |
| | 641 | case ASQ_StandingAttack_Claw: |
| | 642 | { |
| | 643 | int chosenSequence; |
| | 644 | |
| | 645 | switch(ghostData->currentAnimSequence) |
| | 646 | { |
| | 647 | case ASQ_StandingAttack_Claw: |
| | 648 | case ASQ_StandingTailStrike: |
| | 649 | case ASQ_Eat: |
| | 650 | { |
| | 651 | //if already playing a standing attack allow it to finish first |
| | 652 | if(!HModelAnimation_IsFinished(&ghostData->HModelController)) |
| | 653 | return; |
| | 654 | } |
| | 655 | default: |
| | 656 | break; |
| | 657 | } |
| | 658 | |
| | 659 | /*Pick a random claw attack*/ |
| | 660 | switch(FastRandom() % 6) |
| | 661 | { |
| | 662 | case 0: |
| | 663 | chosenSequence = ASSS_Attack_Right_Swipe_In; |
| | 664 | break; |
| | 665 | case 1: |
| | 666 | chosenSequence = ASSS_Attack_Left_Swipe_In; |
| | 667 | break; |
| | 668 | case 2: |
| | 669 | chosenSequence = ASSS_Attack_Both_In; |
| | 670 | break; |
| | 671 | case 3: |
| | 672 | chosenSequence = ASSS_Attack_Both_Down; |
| | 673 | break; |
| | 674 | case 4: |
| | 675 | chosenSequence = ASSS_Attack_Low_Left_Swipe; |
| | 676 | break; |
| | 677 | case 5: |
| | 678 | chosenSequence = ASSS_Attack_Low_Right_Swipe; |
| | 679 | break; |
| | 680 | } |
| | 681 | |
| | 682 | InitHModelTweening(&ghostData->HModelController,(ONE_FIXED>>3),(int)HMSQT_AlienStand,chosenSequence,-1/*(ONE_FIXED/6)*/,0); |
| | 683 | } |
| | 684 | break; |
| | 685 | case ASQ_StandingTailStrike: |
| | 686 | { |
| | 687 | switch(ghostData->currentAnimSequence) |
| | 688 | { |
| | 689 | case ASQ_StandingAttack_Claw: |
| | 690 | case ASQ_StandingTailStrike: |
| | 691 | case ASQ_Eat: |
| | 692 | { |
| | 693 | //if already playing a standing attack allow it to finish first |
| | 694 | if(!HModelAnimation_IsFinished(&ghostData->HModelController)) |
| | 695 | return; |
| | 696 | } |
| | 697 | default: |
| | 698 | break; |
| | 699 | } |
| | 700 | |
| | 701 |
InitHModelTweening(&ghostData->HModelController,(ONE_FIXED>>3),(int)HMSQT_AlienStand,(int)ASSS_Attack_Tail,-1/*(ONE_FIXED/6)*/,0); |
| | 702 | } |
| | 703 | break; |
| | 704 | case ASQ_Eat: |
| | 705 | { |
| | 706 | switch(ghostData->currentAnimSequence) |
| | 707 | { |
| | 708 | case ASQ_StandingAttack_Claw: |
| | 709 | case ASQ_StandingTailStrike: |
| | 710 | case ASQ_Eat: |
| | 711 | { |
| | 712 | //if already playing a standing attack allow it to finish first |
| | 713 | if(!HModelAnimation_IsFinished(&ghostData->HModelController)) |
| | 714 | return; |
| | 715 | } |
| | 716 | default: |
| | 717 | break; |
| | 718 | } |
| | 719 | |
| | 720 | InitHModelTweening(&ghostData->HModelController,(ONE_FIXED>>3),(int)HMSQT_AlienStand,(int)ASSS_Attack_Bite,-1,0); |
| | 721 | break; |
| | 722 | } |
| | 723 | case ASQ_Run: |
| | 724 | case ASQ_RunningTailPoise: |
| | 725 | { |
| | 726 | switch(ghostData->currentAnimSequence) |
| | 727 | { |
| | 728 | case ASQ_RunningAttack_Claw: |
| | 729 | case ASQ_RunningTailStrike: |
| | 730 | { |
| | 731 | if(!HModelAnimation_IsFinished(&ghostData->HModelController)) |
| | 732 | { |
| | 733 | ghostData->HModelController.Looped=0; |
| | 734 | ghostData->HModelController.LoopAfterTweening=0; |
| | 735 | return; |
| | 736 | } |
| | 737 | } |
| | 738 | default: |
| | 739 | break; |
| | 740 | } |
| | 741 | |
| | 742 | InitHModelTweening(&ghostData->HModelController,(ONE_FIXED>>3),(int)HMSQT_AlienRun,(int)ARSS_Standard,ONE_FIXED,1); |
| | 743 | } |
| | 744 | break; |
| | 745 | case ASQ_Run_Backwards: |
| | 746 | case ASQ_RunningTailPoise_Backwards: |
| | 747 | { |
| | 748 | switch(ghostData->currentAnimSequence) |
| | 749 | { |
| | 750 | case ASQ_RunningAttack_Claw_Backwards: |
| | 751 | case ASQ_RunningTailStrike_Backwards: |
| | 752 | { |
| | 753 | if(!HModelAnimation_IsFinished(&ghostData->HModelController)) |
| | 754 | { |
| | 755 | ghostData->HModelController.Looped = 0; |
| | 756 | ghostData->HModelController.LoopAfterTweening = 0; |
| | 757 | return; |
| | 758 | } |
| | 759 | } |
| | 760 | default: |
| | 761 | break; |
| | 762 | } |
| | 763 | InitHModelSequence(&ghostData->HModelController,(int)HMSQT_AlienRun,(int)ARSS_Standard,ONE_FIXED); |
| | 764 | ghostData->HModelController.Reversed = 1; |
| | 765 | } |
| | 766 | break; |
| | 767 | case ASQ_RunningAttack_Claw: |
| | 768 | case ASQ_RunningTailStrike: |
| | 769 |
InitHModelTweening(&ghostData->HModelController,(ONE_FIXED>>3),(int)HMSQT_AlienRun,(int)ARSS_Attack_Swipe,ONE_FIXED/*(ONE_FIXED/6)*/,1); |
| | 770 | break; |
| | 771 | case ASQ_RunningAttack_Claw_Backwards: |
| | 772 | case ASQ_RunningTailStrike_Backwards: |
| | 773 | InitHModelSequence(&ghostData->HModelController,(int)HMSQT_AlienRun,(int)ARSS_Attack_Swipe,ONE_FIXED/*(ONE_FIXED/6)*/); |
| | 774 | ghostData->HModelController.Reversed = 1; |
| | 775 | ghostData->HModelController.Looped = 1; |
| | 776 | break; |
| | 777 | case ASQ_Crawl: |
| | 778 | case ASQ_CrawlingTailPoise: |
| | 779 | { |
| | 780 | switch(ghostData->currentAnimSequence) |
| | 781 | { |
| | 782 | case ASQ_CrawlingAttack_Claw: |
| | 783 | case ASQ_CrawlingTailStrike: |
| | 784 | { |
| | 785 | if(!HModelAnimation_IsFinished(&ghostData->HModelController)) |
| | 786 | { |
| | 787 | ghostData->HModelController.Looped = 0; |
| | 788 | ghostData->HModelController.LoopAfterTweening = 0; |
| | 789 | return; |
| | 790 | } |
| | 791 | } |
| | 792 | default: |
| | 793 | break; |
| | 794 | } |
| | 795 | |
| | 796 | InitHModelTweening(&ghostData->HModelController,(ONE_FIXED>>3),(int)HMSQT_AlienCrawl,(int)ACSS_Standard,ONE_FIXED,1); |
| | 797 | } |
| | 798 | break; |
| | 799 | case ASQ_Scamper: |
| | 800 | { |
| | 801 | switch(ghostData->currentAnimSequence) |
| | 802 | { |
| | 803 | case ASQ_CrawlingAttack_Claw: |
| | 804 | case ASQ_CrawlingTailStrike: |
| | 805 | { |
| | 806 | if(!HModelAnimation_IsFinished(&ghostData->HModelController)) |
| | 807 | { |
| | 808 | ghostData->HModelController.Looped = 0; |
| | 809 | ghostData->HModelController.LoopAfterTweening = 0; |
| | 810 | return; |
| | 811 | } |
| | 812 | } |
| | 813 | default: |
| | 814 | break; |
| | 815 | } |
| | 816 | |
| | 817 | InitHModelTweening(&ghostData->HModelController,(ONE_FIXED>>3),(int)HMSQT_AlienCrawl,(int)ACSS_Scamper,ONE_FIXED,1); |
| | 818 | } |
| | 819 | break; |
| | 820 | case ASQ_Crawl_Backwards: |
| | 821 | case ASQ_CrawlingTailPoise_Backwards: |
| | 822 | { |
| | 823 | switch(ghostData->currentAnimSequence) |
| | 824 | { |
| | 825 | case ASQ_CrawlingAttack_Claw_Backwards: |
| | 826 | case ASQ_CrawlingTailStrike_Backwards: |
| | 827 | { |
| | 828 | if(!HModelAnimation_IsFinished(&ghostData->HModelController)) |
| | 829 | { |
| | 830 | ghostData->HModelController.Looped = 0; |
| | 831 | ghostData->HModelController.LoopAfterTweening = 0; |
| | 832 | return; |
| | 833 | } |
| | 834 | } |
| | 835 | default: |
| | 836 | break; |
| | 837 | } |
| | 838 | |
| | 839 | InitHModelSequence(&ghostData->HModelController,(int)HMSQT_AlienCrawl,(int)ACSS_Standard,ONE_FIXED); |
| | 840 | ghostData->HModelController.Reversed = 1; |
| | 841 | } |
| | 842 | break; |
| | 843 | case ASQ_Scamper_Backwards: |
| | 844 | { |
| | 845 | switch(ghostData->currentAnimSequence) |
| | 846 | { |
| | 847 | case ASQ_CrawlingAttack_Claw_Backwards: |
| | 848 | case ASQ_CrawlingTailStrike_Backwards: |
| | 849 | { |
| | 850 | if(!HModelAnimation_IsFinished(&ghostData->HModelController)) |
| | 851 | { |
| | 852 | ghostData->HModelController.Looped = 0; |
| | 853 | ghostData->HModelController.LoopAfterTweening = 0; |
| | 854 | return; |
| | 855 | } |
| | 856 | } |
| | 857 | default: |
| | 858 | break; |
| | 859 | } |
| | 860 | |
| | 861 | InitHModelSequence(&ghostData->HModelController,(int)HMSQT_AlienCrawl,(int)ACSS_Scamper,ONE_FIXED); |
| | 862 | ghostData->HModelController.Reversed = 1; |
| | 863 | } |
| | 864 | break; |
| | 865 | case ASQ_CrawlingAttack_Claw: |
| | 866 | case ASQ_CrawlingTailStrike: |
| | 867 |
InitHModelTweening(&ghostData->HModelController,(ONE_FIXED>>3),(int)HMSQT_AlienCrouch,(int)ACrSS_Attack_Swipe,ONE_FIXED/*(ONE_FIXED/6)*/,1); |
| | 868 | break; |
| | 869 | case ASQ_CrawlingAttack_Claw_Backwards: |
| | 870 | case ASQ_CrawlingTailStrike_Backwards: |
| | 871 | InitHModelSequence(&ghostData->HModelController,(int)HMSQT_AlienCrouch,(int)ACrSS_Attack_Swipe,ONE_FIXED/*(ONE_FIXED/6)*/); |
| | 872 | ghostData->HModelController.Reversed = 1; |
| | 873 | ghostData->HModelController.Looped = 1; |
| | 874 | break; |
| | 875 | case ASQ_Crouch: |
| | 876 | case ASQ_CrouchedTailPoise: |
| | 877 | { |
| | 878 | switch(ghostData->currentAnimSequence) |
| | 879 | { |
| | 880 | case ASQ_CrouchedAttack_Claw: |
| | 881 | case ASQ_CrouchEat: |
| | 882 | case ASQ_CrouchedTailStrike: |
| | 883 | { |
| | 884 | if(!HModelAnimation_IsFinished(&ghostData->HModelController)) |
| | 885 | return; |
| | 886 | } |
| | 887 | default: |
| | 888 | break; |
| | 889 | } |
| | 890 | InitHModelTweening(&ghostData->HModelController,(ONE_FIXED>>3),(int)HMSQT_AlienCrouch,(int)ACSS_Standard,ONE_FIXED,1); |
| | 891 | } |
| | 892 | break; |
| | 893 | case ASQ_CrouchedAttack_Claw: |
| | 894 | { |
| | 895 | switch(ghostData->currentAnimSequence) |
| | 896 | { |
| | 897 | case ASQ_CrouchedAttack_Claw: |
| | 898 | case ASQ_CrouchedTailStrike: |
| | 899 | case ASQ_CrouchEat: |
| | 900 | { |
| | 901 | //if already playing a crouched attack allow it to finish first |
| | 902 | if(!HModelAnimation_IsFinished(&ghostData->HModelController)) |
| | 903 | return; |
| | 904 | } |
| | 905 | default: |
| | 906 | break; |
| | 907 | } |
| | 908 |
InitHModelTweening(&ghostData->HModelController,(ONE_FIXED>>3),(int)HMSQT_AlienCrouch,(int)ACrSS_Attack_Swipe,-1/*(ONE_FIXED/6)*/,0); |
| | 909 | } |
| | 910 | break; |
| | 911 | case ASQ_CrouchedTailStrike: |
| | 912 | { |
| | 913 | switch(ghostData->currentAnimSequence) |
| | 914 | { |
| | 915 | case ASQ_CrouchedAttack_Claw: |
| | 916 | case ASQ_CrouchedTailStrike: |
| | 917 | case ASQ_CrouchEat: |
| | 918 | { |
| | 919 | //if already playing a crouched attack allow it to finish first |
| | 920 | if(!HModelAnimation_IsFinished(&ghostData->HModelController)) return; |
| | 921 | } |
| | 922 | default: |
| | 923 | break; |
| | 924 | } |
| | 925 | |
| | 926 |
InitHModelTweening(&ghostData->HModelController,(ONE_FIXED>>3),(int)HMSQT_AlienCrouch,(int)ACrSS_Attack_Tail,-1/*(ONE_FIXED/6)*/,0); |
| | 927 | } |
| | 928 | break; |
| | 929 | case ASQ_CrouchEat: |
| | 930 | { |
| | 931 | switch(ghostData->currentAnimSequence) |
| | 932 | { |
| | 933 | case ASQ_CrouchedAttack_Claw: |
| | 934 | case ASQ_CrouchedTailStrike: |
| | 935 | case ASQ_CrouchEat: |
| | 936 | { |
| | 937 | //if already playing a crouched attack allow it to finish first |
| | 938 | if(!HModelAnimation_IsFinished(&ghostData->HModelController)) |
| | 939 | return; |
| | 940 | } |
| | 941 | default: |
| | 942 | break; |
| | 943 | } |
| | 944 | |
| | 945 | InitHModelTweening(&ghostData->HModelController,(ONE_FIXED>>3),(int)HMSQT_AlienCrouch,(int)ACrSS_Attack_Bite,-1,0); |
| | 946 | } |
| | 947 | break; |
| | 948 | case ASQ_Jump: |
| | 949 | case ASQ_Pounce: |
| | 950 | case ASQ_JumpingTailPoise: |
| | 951 | case ASQ_JumpingTailStrike: |
| | 952 | InitHModelTweening(&ghostData->HModelController,(ONE_FIXED>>3),(int)HMSQT_AlienRun,(int)ARSS_Jump,ONE_FIXED,1); |
| | 953 | break; |
| | 954 | case ASQ_Taunt: |
| | 955 | if (HModelSequence_Exists(&ghostData->HModelController,(int)HMSQT_AlienStand,(int)ASSS_Taunt)) |
| | 956 |
InitHModelTweening(&ghostData->HModelController,(ONE_FIXED>>3),(int)HMSQT_AlienStand,(int)ASSS_Taunt,(TAUNT_LENGTH-(ONE_FIXED>>3)),0); |
| | 957 | else /* Default. */ |
| | 958 | InitHModelTweening(&ghostData->HModelController,(ONE_FIXED)>>3,(int)HMSQT_AlienStand,(int)ASSS_Standard,ONE_FIXED,1); |
| | 959 | break; |
| | 960 | default: |
| | 961 | { |
| | 962 | /* no other sequences should be set */ |
| | 963 | assert("Unknown Alien anim sequence"==0); |
| | 964 | break; |
| | 965 | } |
| | 966 | } |
| | 967 | } |
| | 968 | break; |
| | 969 | case I_BehaviourPredatorPlayer: |
| | 970 | { |
| | 971 | switch((PREDATOR_SEQUENCE)sequence) |
| | 972 | { |
| | 973 | case PredSQ_Stand: |
| | 974 | { |
| | 975 | if(ghostData->currentAnimSequence == PredSQ_StandingSwipe) |
| | 976 | { |
| | 977 | //if currently playing a standing attack allow it to finish first |
| | 978 | if(!HModelAnimation_IsFinished(&ghostData->HModelController)) |
| | 979 | return; |
| | 980 | } |
| | 981 | else if(ghostData->currentAnimSequence >= PredSQ_BaseOfWristbladeAttacks) |
| | 982 | { |
| | 983 | if((ghostData->currentAnimSequence - PredSQ_BaseOfWristbladeAttacks) % 2 == 1) |
| | 984 | { |
| | 985 | //if currently playing a standing attack allow it to finish first |
| | 986 | if(!HModelAnimation_IsFinished(&ghostData->HModelController)) |
| | 987 | return; |
| | 988 | } |
| | 989 | } |
| | 990 | |
| | 991 | InitHModelTweening(&ghostData->HModelController,(ONE_FIXED>>3),(int)HMSQT_PredatorStand,(int)PSSS_Standard,ONE_FIXED,1); |
| | 992 | } |
| | 993 | break; |
| | 994 | case PredSQ_StandingSwipe: |
| | 995 | InitHModelTweening(&ghostData->HModelController,(ONE_FIXED>>3),(int)HMSQT_PredatorStand,(int)PSSS_Attack_Primary,-1,0); |
| | 996 | break; |
| | 997 | case PredSQ_RunningSwipe: |
| | 998 | InitHModelSequence(&ghostData->HModelController,(int)HMSQT_PredatorRun,(int)PRSS_Attack_Primary,(ONE_FIXED>>1)); |
| | 999 | ghostData->HModelController.Looped = 0; |
| | 1000 | break; |
| | 1001 | case PredSQ_RunningSwipe_Backwards: |
| | 1002 | InitHModelSequence(&ghostData->HModelController,(int)HMSQT_PredatorRun,(int)PRSS_Attack_Primary,(ONE_FIXED>>1)); |
| | 1003 | ghostData->HModelController.Looped = 0; |
| | 1004 | ghostData->HModelController.Reversed = 1; |
| | 1005 | break; |
| | 1006 | case PredSQ_Run: |
| | 1007 | { |
| | 1008 | if(ghostData->currentAnimSequence == PredSQ_RunningSwipe) |
| | 1009 | { |
| | 1010 | if(!HModelAnimation_IsFinished(&ghostData->HModelController)) |
| | 1011 | { |
| | 1012 | ghostData->HModelController.Looped = 0; |
| | 1013 | ghostData->HModelController.LoopAfterTweening = 0; |
| | 1014 | return; |
| | 1015 | } |
| | 1016 | } |
| | 1017 | |
| | 1018 |
InitHModelTweening(&ghostData->HModelController,(ONE_FIXED>>3),(int)HMSQT_PredatorRun,(int)PSSS_Standard,(ONE_FIXED>>1),1); |
| | 1019 | } |
| | 1020 | break; |
| | 1021 | case PredSQ_Run_Backwards: |
| | 1022 | { |
| | 1023 | if(ghostData->currentAnimSequence == PredSQ_RunningSwipe_Backwards) |
| | 1024 | { |
| | 1025 | if(!HModelAnimation_IsFinished(&ghostData->HModelController)) |
| | 1026 | { |
| | 1027 | ghostData->HModelController.Looped = 0; |
| | 1028 | ghostData->HModelController.LoopAfterTweening = 0; |
| | 1029 | return; |
| | 1030 | } |
| | 1031 | } |
| | 1032 | |
| | 1033 | InitHModelSequence(&ghostData->HModelController,(int)HMSQT_PredatorRun,(int)PSSS_Standard,(ONE_FIXED>>1)); |
| | 1034 | ghostData->HModelController.Reversed = 1; |
| | 1035 | } |
| | 1036 | break; |
| | 1037 | case PredSQ_Crawl: |
| | 1038 | { |
| | 1039 | if(ghostData->currentAnimSequence == PredSQ_CrawlingSwipe) |
| | 1040 | { |
| | 1041 | if(!HModelAnimation_IsFinished(&ghostData->HModelController)) |
| | 1042 | { |
| | 1043 | ghostData->HModelController.Looped = 0; |
| | 1044 | ghostData->HModelController.LoopAfterTweening = 0; |
| | 1045 | return; |
| | 1046 | } |
| | 1047 | } |
| | 1048 | |
| | 1049 |
InitHModelTweening(&ghostData->HModelController,(ONE_FIXED>>3),(int)HMSQT_PredatorCrawl,(int)PCSS_Standard,(ONE_FIXED>>1),1); |
| | 1050 | } |
| | 1051 | break; |
| | 1052 | case PredSQ_Crawl_Backwards: |
| | 1053 | { |
| | 1054 | if(ghostData->currentAnimSequence == PredSQ_CrawlingSwipe_Backwards) |
| | 1055 | { |
| | 1056 | if(!HModelAnimation_IsFinished(&ghostData->HModelController)) |
| | 1057 | { |
| | 1058 | ghostData->HModelController.Looped = 0; |
| | 1059 | ghostData->HModelController.LoopAfterTweening = 0; |
| | 1060 | return; |
| | 1061 | } |
| | 1062 | } |
| | 1063 | |
| | 1064 | InitHModelSequence(&ghostData->HModelController,(int)HMSQT_PredatorCrawl,(int)PCSS_Standard,(ONE_FIXED>>1)); |
| | 1065 | ghostData->HModelController.Reversed = 1; |
| | 1066 | } |
| | 1067 | break; |
| | 1068 | case PredSQ_Crouch: |
| | 1069 | { |
| | 1070 | int crouched_attack = 0; |
| | 1071 | if(ghostData->currentAnimSequence == PredSQ_CrouchedSwipe) |
| | 1072 | { |
| | 1073 | crouched_attack = 1; |
| | 1074 | } |
| | 1075 | else if(ghostData->currentAnimSequence >= PredSQ_BaseOfWristbladeAttacks) |
| | 1076 | { |
| | 1077 | if((ghostData->currentAnimSequence - PredSQ_BaseOfWristbladeAttacks) %2 == 0) |
| | 1078 | crouched_attack = 1; |
| | 1079 | } |
| | 1080 | |
| | 1081 | if(crouched_attack) |
| | 1082 | { |
| | 1083 | //if currently playing a standing attack allow it to finish first |
| | 1084 | if(!HModelAnimation_IsFinished(&ghostData->HModelController)) |
| | 1085 | return; |
| | 1086 | } |
| | 1087 | |
| | 1088 | if(ghostData->currentAnimSequence == PredSQ_CrouchedSwipe) |
| | 1089 | { |
| | 1090 | if(!HModelAnimation_IsFinished(&ghostData->HModelController)) |
| | 1091 | return; |
| | 1092 | } |
| | 1093 | |
| | 1094 | InitHModelTweening(&ghostData->HModelController,(ONE_FIXED>>3),(int)HMSQT_PredatorCrouch,(int)PCrSS_Standard,ONE_FIXED,1); |
| | 1095 | } |
| | 1096 | break; |
| | 1097 | case PredSQ_CrouchedSwipe: |
| | 1098 | InitHModelTweening(&ghostData->HModelController,(ONE_FIXED>>3),(int)HMSQT_PredatorCrouch,(int)PCrSS_Attack_Primary,-1,0); |
| | 1099 | break; |
| | 1100 | case PredSQ_CrawlingSwipe: |
| | 1101 | InitHModelSequence(&ghostData->HModelController,(int)HMSQT_PredatorCrawl,(int)PCSS_Attack_Primary,(ONE_FIXED>>1)); |
| | 1102 | ghostData->HModelController.Looped = 0; |
| | 1103 | break; |
| | 1104 | case PredSQ_CrawlingSwipe_Backwards: |
| | 1105 | InitHModelSequence(&ghostData->HModelController,(int)HMSQT_PredatorCrawl,(int)PCSS_Attack_Primary,(ONE_FIXED>>1)); |
| | 1106 | ghostData->HModelController.Looped = 0; |
| | 1107 | ghostData->HModelController.Reversed = 1; |
| | 1108 | break; |
| | 1109 | case PredSQ_Jump: |
| | 1110 | { |
| | 1111 | if (HModelSequence_Exists(&ghostData->HModelController,(int)HMSQT_PredatorStand,(int)PSSS_Jump)) |
| | 1112 | InitHModelTweening(&ghostData->HModelController,(ONE_FIXED>>3),(int)HMSQT_PredatorStand,(int)PSSS_Jump,(ONE_FIXED),0); |
| | 1113 | else |
| | 1114 | InitHModelTweening(&ghostData->HModelController,(ONE_FIXED)>>3,(int)HMSQT_PredatorStand,(int)PSSS_Standard,ONE_FIXED,1); |
| | 1115 | break; |
| | 1116 | } |
| | 1117 | case PredSQ_Taunt: |
| | 1118 | { |
| | 1119 | if (HModelSequence_Exists(&ghostData->HModelController,(int)HMSQT_PredatorStand,(int)PSSS_Taunt_One)) |
| | 1120 |
InitHModelTweening(&ghostData->HModelController,(ONE_FIXED>>3),(int)HMSQT_PredatorStand,(int)PSSS_Taunt_One,(TAUNT_LENGTH-(ONE_FIXED>>3)),0); |
| | 1121 | else |
| | 1122 | InitHModelTweening(&ghostData->HModelController,(ONE_FIXED)>>3,(int)HMSQT_PredatorStand,(int)PSSS_Standard,ONE_FIXED,1); /*
Default. */ |
| | 1123 | break; |
| | 1124 | } |
| | 1125 | case PredSQ_StandDie: |
| | 1126 | case PredSQ_CrouchDie: |
| | 1127 | break; |
| | 1128 | default: |
| | 1129 | { |
| | 1130 | int attack; |
| | 1131 | /* Must cover STAFF ATTACKS, and WRISTBLADE ATTACKS! */ |
| | 1132 | if ((int)sequence >= (int)PredSQ_BaseOfWristbladeAttacks) |
| | 1133 | { |
| | 1134 | attack = (int)sequence-(int)PredSQ_BaseOfWristbladeAttacks; |
| | 1135 | |
| | 1136 | if(ghostData->currentAnimSequence >= PredSQ_BaseOfWristbladeAttacks) |
| | 1137 | { |
| | 1138 | //already playing some form of attack |
| | 1139 | if(!HModelAnimation_IsFinished(&ghostData->HModelController)) |
| | 1140 | return; |
| | 1141 | } |
| | 1142 | |
| | 1143 | switch (attack) |
| | 1144 | { |
| | 1145 | case 0: |
| | 1146 | /* Crouching Fast Jab. */ |
| | 1147 | InitHModelTweening(&ghostData->HModelController,(ONE_FIXED>>4),(int)HMSQT_PredatorCrouch,(int)PCrSS_Attack_Primary,-1,0); |
| | 1148 | break; |
| | 1149 | case 1: |
| | 1150 | /* Standing Fast Jab. */ |
| | 1151 | InitHModelTweening(&ghostData->HModelController,(ONE_FIXED>>4),(int)HMSQT_PredatorStand,(int)PSSS_Attack_Quick_Jab,-1,0); |
| | 1152 | break; |
| | 1153 | case 2: |
| | 1154 | /* Crouching Slow Jab. */ |
| | 1155 | InitHModelTweening(&ghostData->HModelController,(ONE_FIXED>>4),(int)HMSQT_PredatorCrouch,(int)PCrSS_Attack_Primary,-1,0); |
| | 1156 | break; |
| | 1157 | case 3: |
| | 1158 | /* Standing Slow Jab. */ |
| | 1159 | InitHModelTweening(&ghostData->HModelController,(ONE_FIXED>>4),(int)HMSQT_PredatorStand,(int)PSSS_Attack_Primary,-1,0); |
| | 1160 | break; |
| | 1161 | case 4: |
| | 1162 | /* Crouching Uppercut. */ |
| | 1163 | InitHModelTweening(&ghostData->HModelController,(ONE_FIXED>>4),(int)HMSQT_PredatorCrouch,(int)PCrSS_Attack_Primary,-1,0); |
| | 1164 | break; |
| | 1165 | case 5: |
| | 1166 | /* Standing Uppercut. */ |
| | 1167 | InitHModelTweening(&ghostData->HModelController,(ONE_FIXED>>4),(int)HMSQT_PredatorStand,(int)PSSS_Attack_Uppercut,-1,0); |
| | 1168 | break; |
| | 1169 | default: |
| | 1170 | /* KJL 16:56:15 26/11/98 - hmm. Any 'unknown' attacks will be replaced with a fast jab */ |
| | 1171 | { |
| | 1172 | if (attack & 1) // Standing Fast Jab. |
| | 1173 | InitHModelTweening(&ghostData->HModelController,(ONE_FIXED>>4),(int)HMSQT_PredatorStand,(int)PSSS_Attack_Quick_Jab,-1,0); |
| | 1174 | else // Crouching Fast Jab. |
| | 1175 | InitHModelTweening(&ghostData->HModelController,(ONE_FIXED>>4),(int)HMSQT_PredatorCrouch,(int)PCrSS_Attack_Primary,-1,0); |
| | 1176 | break; |
| | 1177 | } |
| | 1178 | } |
| | 1179 | } |
| | 1180 | else |
| | 1181 | { |
| | 1182 | attack = (int)sequence-(int)PredSQ_BaseOfStaffAttacks; |
| | 1183 | |
| | 1184 | if (attack) |
| | 1185 | InitHModelTweening(&ghostData->HModelController,(ONE_FIXED>>3),(int)HMSQT_PredatorCrouch,(int)PCrSS_Attack_Primary,-1,0); |
| | 1186 | else |
| | 1187 | InitHModelTweening(&ghostData->HModelController,(ONE_FIXED>>3),(int)HMSQT_PredatorStand,(int)PSSS_Attack_Primary,-1,0); |
| | 1188 | } |
| | 1189 | } |
| | 1190 | } |
| | 1191 | } |
| | 1192 | break; |
| | 1193 | default: |
| | 1194 | { |
| | 1195 | assert(1==0); |
| | 1196 | break; |
| | 1197 | } |
| | 1198 | } |
| | 1199 | /* update the ghost's current sequence*/ |
| | 1200 | ghostData->currentAnimSequence = sequence; |
| | 1201 | } |
| | 1202 | |
| | 1203 | /* Patrick 14/7/97 ----------------------------------------------------------- |
| | 1204 | Shape animation control functions for player ghosts: |
| | 1205 | |
| | 1206 | Init initilaises the character sequence, and should only be called when a new |
| | 1207 | player ghost is created, after the sb and datablock have been set up. |
| | 1208 | |
| | 1209 | Update changes the sequence if appropriate (and calls set if the sbPtr has a dptr) |
| | 1210 | |
| | 1211 | Set selects the correct sequence/type, infers the speed and follow-on sequences, |
| | 1212 | etc, and sets it. |
| | 1213 | ------------------------------------------------------------------------------*/ |
| | 1214 | |
| | 1215 | static void UpdatePlayerGhostAnimSequence(STRATEGYBLOCK *sbPtr, int sequence, int special) |
| | 1216 | { |
| | 1217 | assert(sbPtr); |
| | 1218 | NETGHOSTDATABLOCK *ghostData = (NETGHOSTDATABLOCK *)sbPtr->dataptr; |
| | 1219 | assert(ghostData); |
| | 1220 | |
| | 1221 | switch(ghostData->type) |
| | 1222 | { |
| | 1223 | case I_BehaviourMarinePlayer: |
| | 1224 | { |
| | 1225 | /* if the current sequence is the same as the new sequence, do nothing */ |
| | 1226 | |
| | 1227 | if ( (MARINE_SEQUENCE)ghostData->currentAnimSequence == (MARINE_SEQUENCE)sequence) |
| | 1228 | { |
| | 1229 | switch(ghostData->CurrentWeapon) |
| | 1230 | { |
| | 1231 | case WEAPON_TWO_PISTOLS: |
| | 1232 | break; |
| | 1233 | case WEAPON_MARINE_PISTOL: |
| | 1234 | if (special) |
| | 1235 | break; |
| | 1236 | default: |
| | 1237 | return; |
| | 1238 | } |
| | 1239 | } |
| | 1240 | |
| | 1241 | /* if we're dead, and passed dying, do nothing */ |
| | 1242 | if(((MARINE_SEQUENCE)ghostData->currentAnimSequence == MSQ_StandDeadFront) && ((MARINE_SEQUENCE)sequence == MSQ_StandDieFront)) |
| | 1243 | return; |
| | 1244 | |
| | 1245 | if(((MARINE_SEQUENCE)ghostData->currentAnimSequence == MSQ_CrouchDead) && ((MARINE_SEQUENCE)sequence == MSQ_CrouchDie)) |
| | 1246 | return; |
| | 1247 | /* need to update the anim sequence, then*/ |
| | 1248 | SetPlayerGhostAnimationSequence(sbPtr, sequence, special); |
| | 1249 | } |
| | 1250 | break; |
| | 1251 | case I_BehaviourAlienPlayer: |
| | 1252 | { |
| | 1253 | /* if the current sequence is the same as the new sequence, do nothing */ |
| | 1254 | if(!HModelAnimation_IsFinished(&ghostData->HModelController)) |
| | 1255 | { |
| | 1256 | if((ALIEN_SEQUENCE)ghostData->currentAnimSequence == (ALIEN_SEQUENCE)sequence) |
| | 1257 | { |
| | 1258 | switch(ghostData->currentAnimSequence) |
| | 1259 | { |
| | 1260 | case ASQ_RunningAttack_Claw: |
| | 1261 | case ASQ_RunningTailStrike: |
| | 1262 | case ASQ_RunningAttack_Claw_Backwards: |
| | 1263 | case ASQ_RunningTailStrike_Backwards: |
| | 1264 | case ASQ_CrawlingAttack_Claw: |
| | 1265 | case ASQ_CrawlingAttack_Claw_Backwards: |
| | 1266 | case ASQ_CrawlingTailStrike: |
| | 1267 | case ASQ_CrawlingTailStrike_Backwards: |
| | 1268 | ghostData->HModelController.Looped = 1; |
| | 1269 | ghostData->HModelController.LoopAfterTweening = 1; |
| | 1270 | default: |
| | 1271 | break; |
| | 1272 | } |
| | 1273 | return; |
| | 1274 | } |
| | 1275 | } |
| | 1276 | /* need to update the anim sequence, then*/ |
| | 1277 | SetPlayerGhostAnimationSequence(sbPtr, sequence, special); |
| | 1278 | } |
| | 1279 | break; |
| | 1280 | case I_BehaviourPredatorPlayer: |
| | 1281 | { |
| | 1282 | /* if the current sequence is the same as the new sequence, do nothing */ |
| | 1283 | if(!HModelAnimation_IsFinished(&ghostData->HModelController)) |
| | 1284 | { |
| | 1285 | if(ghostData->currentAnimSequence == sequence) |
| | 1286 | { |
| | 1287 | switch(ghostData->currentAnimSequence) |
| | 1288 | { |
| | 1289 | case PredSQ_RunningSwipe: |
| | 1290 | case PredSQ_RunningSwipe_Backwards: |
| | 1291 | case PredSQ_CrawlingSwipe: |
| | 1292 | case PredSQ_CrawlingSwipe_Backwards: |
| | 1293 | ghostData->HModelController.Looped = 1; |
| | 1294 | ghostData->HModelController.LoopAfterTweening = 1; |
| | 1295 | default: |
| | 1296 | break; |
| | 1297 | } |
| | 1298 | return; |
| | 1299 | } |
| | 1300 | } |
| | 1301 | /* if we're dead, and passed dying, do nothing */ |
| | 1302 | if(((PREDATOR_SEQUENCE)ghostData->currentAnimSequence == PredSQ_StandDead)&& |
| | 1303 | ((PREDATOR_SEQUENCE)sequence == PredSQ_StandDie)) |
| | 1304 | return; |
| | 1305 | |
| | 1306 | if(((PREDATOR_SEQUENCE)ghostData->currentAnimSequence == PredSQ_CrouchDead)&& |
| | 1307 | ((PREDATOR_SEQUENCE)sequence == PredSQ_CrouchDie)) |
| | 1308 | return; |
| | 1309 | |
| | 1310 | /* need to update the anim sequence, then*/ |
| | 1311 | SetPlayerGhostAnimationSequence(sbPtr, sequence, special); |
| | 1312 | } |
| | 1313 | break; |
| | 1314 | case I_BehaviourAlien: |
| | 1315 | { |
| | 1316 | /* if the current sequence is the same as the new sequence, do nothing */ |
| | 1317 | |
| | 1318 | if(ghostData->currentAnimSequence == sequence) |
| | 1319 | return; |
| | 1320 | |
| | 1321 | /* need to update the anim sequence, then*/ |
| | 1322 | SetPlayerGhostAnimationSequence(sbPtr, sequence, special); |
| | 1323 | break; |
| | 1324 | } |
| | 1325 | default: |
| | 1326 | { |
| | 1327 | assert(1==0); |
| | 1328 | break; |
| | 1329 | } |
| | 1330 | } |
| | 1331 | } |
| | 1332 | |
| | 1333 | static void UpdateObjectTrails(STRATEGYBLOCK *sbPtr) |
| | 1334 | { |
| | 1335 | NETGHOSTDATABLOCK *ghostDataPtr = (NETGHOSTDATABLOCK *)sbPtr->dataptr; |
| | 1336 | |
| | 1337 | switch(ghostDataPtr->type) |
| | 1338 | { |
| | 1339 | case I_BehaviourPulseGrenade: |
| | 1340 | case I_BehaviourRocket: |
| | 1341 | MakeRocketTrailParticles(&sbPtr->DynPtr->PrevPosition, &sbPtr->DynPtr->Position); |
| | 1342 | break; |
| | 1343 | case I_BehaviourPredatorEnergyBolt: |
| | 1344 | MakePlasmaTrailParticles(sbPtr->DynPtr, 32); |
| | 1345 | break; |
| | 1346 | case I_BehaviourFrisbeeEnergyBolt: |
| | 1347 | MakeDewlineTrailParticles(sbPtr->DynPtr, 32); |
| | 1348 | break; |
| | 1349 | case I_BehaviourFrisbee: |
| | 1350 | { |
| | 1351 | int l = 0; |
| | 1352 | for (; l < 4; l++) |
| | 1353 | MakeFlareParticle(sbPtr->DynPtr); |
| | 1354 | } |
| | 1355 | break; |
| | 1356 | case I_BehaviourGrenade: |
| | 1357 | case I_BehaviourProximityGrenade: |
| | 1358 | MakeGrenadeTrailParticles(&sbPtr->DynPtr->PrevPosition, &sbPtr->DynPtr->Position); |
| | 1359 | default: |
| | 1360 | break; |
| | 1361 | } |
| | 1362 | } |
| | 1363 | |
| | 1364 | /* updates an existing ghost's position and orientation: Before calling this |
| | 1365 | need to use FindGhost to locate the ghost (which confirms it's existance) */ |
| | 1366 | void UpdateGhost(STRATEGYBLOCK *sbPtr,VECTORCH *position,EULER *orientation,int sequence, int special) |
| | 1367 | { |
| | 1368 | assert(sbPtr); |
| | 1369 | NETGHOSTDATABLOCK *ghostData = (NETGHOSTDATABLOCK *)sbPtr->dataptr; |
| | 1370 | |
| | 1371 | /* for visibility support: as ghosts can be moved when invisible, we need to work out |
| | 1372 | which module they're in whenever we update them. We must be carefull, however, not |
| | 1373 | to set the containingModule to NULL if the object has moved outside the env, as |
| | 1374 | the visibility system expects that we at least know what module any object WAS in, |
| | 1375 | even if we do not now... thus, if we cannot find a containing module, we abort the update */ |
| | 1376 | |
| | 1377 | /* KJL 21:01:09 23/05/98 - I've put this test here because the player's image in a mirror goes |
| | 1378 | throught this code, and it's obviously going to be outside the environment */ |
| | 1379 | |
| | 1380 | if (sbPtr->type == I_BehaviourNetGhost) |
| | 1381 | { |
| | 1382 | MODULE *myContainingModule = ModuleFromPosition(position, (sbPtr->containingModule)); |
| | 1383 | |
| | 1384 | if(myContainingModule == NULL) |
| | 1385 | { |
| | 1386 | //Not in any module , so don't try updating ghost, |
| | 1387 | //except for various projectiles which can be shot |
| | 1388 | //out of the environment semi-legitamately |
| | 1389 | switch(ghostData->type) |
| | 1390 | { |
| | 1391 | case I_BehaviourGrenade: |
| | 1392 | case I_BehaviourRocket: |
| | 1393 | case I_BehaviourPPPlasmaBolt: |
| | 1394 | case I_BehaviourSpeargunBolt: |
| | 1395 | case I_BehaviourPredatorDisc_SeekTrack: |
| | 1396 | case I_BehaviourPredatorEnergyBolt: |
| | 1397 | case I_BehaviourPulseGrenade: |
| | 1398 | case I_BehaviourFlare: |
| | 1399 | case I_BehaviourFragmentationGrenade: |
| | 1400 | case I_BehaviourFrisbeeEnergyBolt: |
| | 1401 | case I_BehaviourProximityGrenade: |
| | 1402 | break; |
| | 1403 | default: |
| | 1404 | return; |
| | 1405 | } |
| | 1406 | } |
| | 1407 | else |
| | 1408 | { |
| | 1409 | sbPtr->containingModule = myContainingModule; |
| | 1410 | } |
| | 1411 | } |
| | 1412 | |
| | 1413 | /* CDF 29/7/98 I'll assume that stationary discs are stuck. */ |
| | 1414 | if (ghostData->type == I_BehaviourPredatorDisc_SeekTrack) |
| | 1415 | { |
| | 1416 | DYNAMICSBLOCK *dynPtr = sbPtr->DynPtr; |
| | 1417 | |
| | 1418 | if(!DynamicObjectIsMoving(sbPtr->DynPtr)) |
| | 1419 | { |
| | 1420 | ghostData->HModelController.Playing = 0; |
| | 1421 | } |
| | 1422 | else |
| | 1423 | { |
| | 1424 | ghostData->HModelController.Playing = 1; |
| | 1425 | //draw the disc's trail |
| | 1426 | NewTrailPoint(dynPtr); |
| | 1427 | |
| | 1428 | //update sound for disc |
| | 1429 | if(ghostData->SoundHandle!=SOUND_NOACTIVEINDEX) |
| | 1430 | Sound_Update3d(ghostData->SoundHandle, &sbPtr->DynPtr->Position); |
| | 1431 | else |
| | 1432 | Sound_Play(SID_PREDATOR_DISK_FLYING, "del", &sbPtr->DynPtr->Position, &ghostData->SoundHandle); |
| | 1433 | } |
| | 1434 | } |
| | 1435 | |
| | 1436 | if (ghostData->type == I_BehaviourFrisbee) |
| | 1437 | { |
| | 1438 | //update sound for disc |
| | 1439 | if(ghostData->SoundHandle != SOUND_NOACTIVEINDEX) |
| | 1440 | Sound_Update3d(ghostData->SoundHandle, &sbPtr->DynPtr->Position); |
| | 1441 | } |
| | 1442 | |
| | 1443 | /* update the dynamics block */ |
| | 1444 | { |
| | 1445 | DYNAMICSBLOCK *dynPtr = sbPtr->DynPtr; |
| | 1446 | // dynPtr->Position = dynPtr->PrevPosition = *position; |
| | 1447 | dynPtr->PrevPosition = dynPtr->Position; |
| | 1448 | dynPtr->PrevOrientMat = dynPtr->OrientMat; |
| | 1449 | dynPtr->Position = *position; |
| | 1450 | dynPtr->OrientEuler = *orientation; |
| | 1451 | CreateEulerMatrix(&dynPtr->OrientEuler,&dynPtr->OrientMat); |
| | 1452 | TransposeMatrixCH(&dynPtr->OrientMat); |
| | 1453 | } |
| | 1454 | |
| | 1455 | UpdateObjectTrails(sbPtr); |
| | 1456 | |
| | 1457 | /* if we're a player type, update the animation sequence */ |
| | 1458 | switch(ghostData->type) |
| | 1459 | { |
| | 1460 | case I_BehaviourMarinePlayer: |
| | 1461 | case I_BehaviourAlienPlayer: |
| | 1462 | case I_BehaviourPredatorPlayer: |
| | 1463 | if(sequence != -1) |
| | 1464 | UpdatePlayerGhostAnimSequence(sbPtr,sequence, special); |
| | 1465 | break; |
| | 1466 | case I_BehaviourMarine: |
| | 1467 | case I_BehaviourAlien: |
| | 1468 | case I_BehaviourPredator: |
| | 1469 | /* KJL 16:58:04 17/06/98 - we want to update anims differently for NPCS */ |
| | 1470 | UpdatePlayerGhostAnimSequence(sbPtr,sequence, special); |
| | 1471 | default: |
| | 1472 | break; |
| | 1473 | } |
| | 1474 | |
| | 1475 | /* refresh integrity */ |
| | 1476 | ghostData->integrity = GHOST_INTEGRITY; |
| | 1477 | } |
| | 1478 | |
| | 1479 | void RemoveGhost(STRATEGYBLOCK *sbPtr) |
| | 1480 | { |
| | 1481 | assert(sbPtr); |
| | 1482 | NETGHOSTDATABLOCK *ghostData = (NETGHOSTDATABLOCK *)sbPtr->dataptr; |
| | 1483 | assert(ghostData); |
| | 1484 | |
| | 1485 | /* this is where we add fragmentation and explosion effects to destroyed ghosts */ |
| | 1486 | switch(ghostData->type) |
| | 1487 | { |
| | 1488 | case I_BehaviourAlienPlayer: |
| | 1489 | case I_BehaviourMarinePlayer: |
| | 1490 | case I_BehaviourPredatorPlayer: |
| | 1491 | //Extreme_Gibbing(sbPtr,ghostData->HModelController.section_data,ONE_FIXED); // jadda |
| | 1492 | break; |
| | 1493 | case I_BehaviourGrenade: |
| | 1494 | if (sbPtr->containingModule) |
| | 1495 | { |
| | 1496 | Ghost_Explosion_SoundData.position=sbPtr->DynPtr->Position; |
| | 1497 | Sound_Play(SID_GRENADE_EXPLOSION, "n", &Ghost_Explosion_SoundData); |
| | 1498 | } |
| | 1499 | break; |
| | 1500 | case I_BehaviourRocket: |
| | 1501 | if (sbPtr->containingModule) |
| | 1502 | { |
| | 1503 | Ghost_Explosion_SoundData.position=sbPtr->DynPtr->Position; |
| | 1504 | Sound_Play(SID_NICE_EXPLOSION, "n", &Ghost_Explosion_SoundData); |
| | 1505 | } |
| | 1506 | break; |
| | 1507 | case I_BehaviourProximityGrenade: |
| | 1508 | if (sbPtr->containingModule) |
| | 1509 | { |
| | 1510 | Ghost_Explosion_SoundData.position=sbPtr->DynPtr->Position; |
| | 1511 | Sound_Play(SID_GRENADE_PROXEXPLOSION, "n", &Ghost_Explosion_SoundData); |
| | 1512 | } |
| | 1513 | break; |
| | 1514 | case I_BehaviourFragmentationGrenade: |
| | 1515 | if (sbPtr->containingModule) |
| | 1516 | { |
| | 1517 | Ghost_Explosion_SoundData.position=sbPtr->DynPtr->Position; |
| | 1518 | Sound_Play(SID_NADEEXPLODE, "n", &Ghost_Explosion_SoundData); |
| | 1519 | } |
| | 1520 | break; |
| | 1521 | case I_BehaviourPulseGrenade: |
| | 1522 | if (sbPtr->containingModule) |
| | 1523 | { |
| | 1524 | Ghost_Explosion_SoundData.position=sbPtr->DynPtr->Position; |
| | 1525 | Sound_Play(SID_NADEEXPLODE, "n", &Ghost_Explosion_SoundData); |
| | 1526 | } |
| | 1527 | break; |
| | 1528 | case I_BehaviourPredatorDisc_SeekTrack: |
| | 1529 | /* MakeAnExplosion... ? */ |
| | 1530 | Sound_Play(SID_NADEEXPLODE, "d", &sbPtr->DynPtr->Position); |
| | 1531 | break; |
| | 1532 | case I_BehaviourFrisbee: |
| | 1533 | //Ghost_Explosion_SoundData.position = sbPtr->DynPtr->Position; |
| | 1534 | //Sound_Play(SID_NICE_EXPLOSION, "n", &Ghost_Explosion_SoundData); |
| | 1535 | case I_BehaviourPPPlasmaBolt: |
| | 1536 | case I_BehaviourCorpse: |
| | 1537 | default: |
| | 1538 | { |
| | 1539 | /* do absolutely bugger all, probably: |
| | 1540 | remaining cases are: predator energy bolt;flame;predator disc;flare; |
| | 1541 | and AUTOGUN */ |
| | 1542 | break; |
| | 1543 | } |
| | 1544 | } |
| | 1545 | |
| | 1546 | /* see if we've got a sound... */ |
| | 1547 | if(ghostData->SoundHandle != SOUND_NOACTIVEINDEX) |
| | 1548 | Sound_Stop(ghostData->SoundHandle); |
| | 1549 | |
| | 1550 | if(ghostData->SoundHandle2 != SOUND_NOACTIVEINDEX) |
| | 1551 | Sound_Stop(ghostData->SoundHandle2); |
| | 1552 | |
| | 1553 | if(ghostData->SoundHandle3 != SOUND_NOACTIVEINDEX) |
| | 1554 | Sound_Stop(ghostData->SoundHandle3); |
| | 1555 | |
| | 1556 | if(ghostData->SoundHandle4 != SOUND_NOACTIVEINDEX) |
| | 1557 | Sound_Stop(ghostData->SoundHandle4); |
| | 1558 | |
| | 1559 | DestroyActiveObject(&ghostData->myGunFlash); |
| | 1560 | |
| | 1561 | sbPtr->please_destroy_me = 1; |
| | 1562 | } |
| | 1563 | |
| | 1564 | /* removes a given player's ghost, and all associated ghosts, eg when a player |
| | 1565 | leaves the game... */ |
| | 1566 | void RemovePlayersGhosts(int id) |
| | 1567 | { |
| | 1568 | int sbIndex = 0; |
| | 1569 | |
| | 1570 | while(sbIndex < NumActiveStBlocks) |
| | 1571 | { |
| | 1572 | STRATEGYBLOCK *sbPtr = ActiveStBlockList[sbIndex++]; |
| | 1573 | |
| | 1574 | if(sbPtr->type == I_BehaviourNetGhost) |
| | 1575 | { |
| | 1576 | NETGHOSTDATABLOCK *ghostData = (NETGHOSTDATABLOCK *)sbPtr->dataptr; |
| | 1577 | assert(ghostData); |
| | 1578 | if(ghostData->playerId == id) |
| | 1579 | RemoveGhost(sbPtr); |
| | 1580 | } |
| | 1581 | } |
| | 1582 | } |
| | 1583 | |
| | 1584 | /* locates a ghost from Id and ObId */ |
| | 1585 | STRATEGYBLOCK *FindGhost(int Id, int obId) |
| | 1586 | { |
| | 1587 | int sbIndex = 0; |
| | 1588 | |
| | 1589 | while(sbIndex < NumActiveStBlocks) |
| | 1590 | { |
| | 1591 | STRATEGYBLOCK *sbPtr = ActiveStBlockList[sbIndex++]; |
| | 1592 | |
| | 1593 | if(sbPtr->type == I_BehaviourNetGhost) |
| | 1594 | { |
| | 1595 | NETGHOSTDATABLOCK *ghostData = (NETGHOSTDATABLOCK *)sbPtr->dataptr; |
| | 1596 | assert(ghostData); |
| | 1597 | |
| | 1598 | if((ghostData->playerId == Id) && (ghostData->playerObjectId == obId)) |
| | 1599 | return sbPtr; |
| | 1600 | } |
| | 1601 | } |
| | 1602 | |
| | 1603 | return NULL; |
| | 1604 | } |
| | 1605 | |
| | 1606 | extern HIERARCHY_VARIANT_DATA* GetHierarchyAlternateShapeSetCollectionFromLibrary(const char* rif_name,int index); |
| | 1607 | void ChangeGhostMarineAccoutrementSet(HMODELCONTROLLER *HModelController,int playerId) |
| | 1608 | { |
| | 1609 | int index = 0; |
| | 1610 | |
| | 1611 | assert(HModelController); |
| | 1612 | |
| | 1613 | //find the index for this player |
| | 1614 | if(playerId) |
| | 1615 | { |
| | 1616 | for(; index < NET_MAXPLAYERS; index++) |
| | 1617 | { |
| | 1618 | if(netGameData.playerData[index].playerId == playerId) |
| | 1619 | break; |
| | 1620 | } |
| | 1621 | } |
| | 1622 | |
| | 1623 | HIERARCHY_VARIANT_DATA* variant_data = GetHierarchyAlternateShapeSetCollectionFromLibrary("hnpcmarine", index + 1); |
| | 1624 | |
| | 1625 | if (variant_data == NULL) |
| | 1626 | return; |
| | 1627 | |
| | 1628 | HIERARCHY_SHAPE_REPLACEMENT* replacement_array = (HIERARCHY_SHAPE_REPLACEMENT*)variant_data->replacements; |
| | 1629 | |
| | 1630 | if (replacement_array == NULL) |
| | 1631 | return; |
| | 1632 | |
| | 1633 | int a = 0; |
| | 1634 | |
| | 1635 | while (replacement_array[a].replaced_section_name != NULL) |
| | 1636 | { |
| | 1637 | SECTION_DATA *target_section = GetThisSectionData(HModelController->section_data, |
| | 1638 | |
| | 1639 | replacement_array[a].replaced_section_name); |
| | 1640 | |
| | 1641 | if (target_section) |
| | 1642 | { |
| | 1643 | target_section->Shape = replacement_array[a].replacement_shape; |
| | 1644 | target_section->ShapeNum = replacement_array[a].replacement_shape_index; |
| | 1645 | Setup_Texture_Animation_For_Section(target_section); |
| | 1646 | } |
| | 1647 | a++; |
| | 1648 | } |
| | 1649 | } |
| | 1650 | |
| | 1651 | static void CreateMarineHModel(NETGHOSTDATABLOCK *ghostDataPtr, int weapon) |
| | 1652 | { |
| | 1653 | const SECTION *root_section; |
| | 1654 | |
| | 1655 | /* KJL 11:09:14 27/01/98 - pick which model to create based on the character's weapon */ |
| | 1656 | switch (weapon) |
| | 1657 | { |
| | 1658 | default: |
| | 1659 | case WEAPON_PULSERIFLE: |
| | 1660 | root_section = GetNamedHierarchyFromLibrary("hnpcmarine","marine with pulse rifle"); |
| | 1661 | break; |
| | 1662 | case WEAPON_TWO_PISTOLS: |
| | 1663 | root_section = GetNamedHierarchyFromLibrary("hnpcmarine","Two Pistol"); |
| | 1664 | break; |
| | 1665 | case WEAPON_MARINE_PISTOL: |
| | 1666 | root_section = GetNamedHierarchyFromLibrary("hnpcmarine","PISTOL"); |
| | 1667 | break; |
| | 1668 | case WEAPON_FLAMETHROWER: |
| | 1669 | root_section = GetNamedHierarchyFromLibrary("hnpcmarine","marine with flame thrower"); |
| | 1670 | break; |
| | 1671 | case WEAPON_SMARTGUN: |
| | 1672 | root_section = GetNamedHierarchyFromLibrary("hnpcmarine","marine with smart gun"); |
| | 1673 | break; |
| | 1674 | case WEAPON_MINIGUN: |
| | 1675 | root_section = GetNamedHierarchyFromLibrary("hnpcmarine","Marine with Mini Gun"); |
| | 1676 | break; |
| | 1677 | case WEAPON_SADAR: |
| | 1678 | root_section = GetNamedHierarchyFromLibrary("hnpcmarine","marine with SADAR"); |
| | 1679 | break; |
| | 1680 | case WEAPON_GRENADELAUNCHER: |
| | 1681 | root_section = GetNamedHierarchyFromLibrary("hnpcmarine","marine + grenade launcher"); |
| | 1682 | break; |
| | 1683 | case WEAPON_CUDGEL: |
| | 1684 | root_section = GetNamedHierarchyFromLibrary("hnpcmarine","Cudgel"); |
| | 1685 | break; |
| | 1686 | case WEAPON_FRISBEE_LAUNCHER: |
| | 1687 | root_section = GetNamedHierarchyFromLibrary("hnpcmarine","skeeter"); |
| | 1688 | } |
| | 1689 | |
| | 1690 | Create_HModel(&ghostDataPtr->HModelController, root_section); |
| | 1691 | ghostDataPtr->CurrentWeapon = weapon; |
| | 1692 | |
| | 1693 | ChangeGhostMarineAccoutrementSet(&ghostDataPtr->HModelController, ghostDataPtr->playerId); |
| | 1694 | |
| | 1695 | /* KJL 11:09:38 27/01/98 - set a default anim sequence to use */ |
| | 1696 | ghostDataPtr->currentAnimSequence = MSQ_Stand; |
| | 1697 | InitHModelSequence(&ghostDataPtr->HModelController, (int)HMSQT_MarineStand, (int)MSSS_Standard,ONE_FIXED); |
| | 1698 | |
| | 1699 | /* KJL 11:09:52 27/01/98 - find the section which hold the muzzle flash data */ |
| | 1700 | ghostDataPtr->GunflashSectionPtr = GetThisSectionData(ghostDataPtr->HModelController.section_data, "dum flash"); |
| | 1701 | assert(ghostDataPtr->GunflashSectionPtr); |
| | 1702 | |
| | 1703 | /* CDF 8/4/98 Elevation Delta Sequence. */ |
| | 1704 | { |
| | 1705 | DELTA_CONTROLLER *delta = Add_Delta_Sequence(&ghostDataPtr->HModelController,"Elevation",(int)HMSQT_MarineStand,(int)MSSS_Elevation,0); |
| | 1706 | assert(delta); |
| | 1707 | delta->timer = 32767; |
| | 1708 | } |
| | 1709 | //add hit delta |
| | 1710 | if (HModelSequence_Exists(&ghostDataPtr->HModelController,(int)HMSQT_MarineStand,(int)MSSS_HitChestFront)) |
| | 1711 | { |
| | 1712 | DELTA_CONTROLLER *delta = Add_Delta_Sequence(&ghostDataPtr->HModelController, "HitDelta", (int)HMSQT_MarineStand,
(int)MSSS_HitChestFront, (ONE_FIXED>>2)); |
| | 1713 | assert(delta); |
| | 1714 | delta->Playing = 0; |
| | 1715 | } |
| | 1716 | |
| | 1717 | ghostDataPtr->hltable = (HITLOCATIONTABLE*)GetThisHitLocationTable("marine with pulse rifle"); |
| | 1718 | } |
| | 1719 | |
| | 1720 | static void CreateAlienHModel(NETGHOSTDATABLOCK *ghostDataPtr,int alienType) |
| | 1721 | { |
| | 1722 | const SECTION *root_section; |
| | 1723 | |
| | 1724 | switch(alienType) |
| | 1725 | { |
| | 1726 | case Predalien : |
| | 1727 | root_section = GetNamedHierarchyFromLibrary("hnpcpred_alien","TEMPLATE"); |
| | 1728 | ghostDataPtr->hltable = GetThisHitLocationTable("predalien"); |
| | 1729 | break; |
| | 1730 | case Praetorian : |
| | 1731 | root_section = GetNamedHierarchyFromLibrary("hnpcpretorian","Template"); |
| | 1732 | ghostDataPtr->hltable = GetThisHitLocationTable("praetorian"); |
| | 1733 | break; |
| | 1734 | default: |
| | 1735 | root_section = GetNamedHierarchyFromLibrary("hnpcalien","alien"); |
| | 1736 | ghostDataPtr->hltable = GetThisHitLocationTable("alien"); |
| | 1737 | } |
| | 1738 | |
| | 1739 | Create_HModel(&ghostDataPtr->HModelController,root_section); |
| | 1740 | ghostDataPtr->currentAnimSequence = ASQ_Stand; |
| | 1741 | InitHModelSequence(&ghostDataPtr->HModelController,(int)HMSQT_AlienStand,(int)ASSS_Standard,ONE_FIXED); |
| | 1742 | |
| | 1743 | ghostDataPtr->CurrentWeapon = 0; |
| | 1744 | |
| | 1745 | /* CDF 12/4/98 Elevation Delta Sequence. */ |
| | 1746 | { |
| | 1747 | DELTA_CONTROLLER *delta =
Add_Delta_Sequence(&ghostDataPtr->HModelController,"Elevation",(int)HMSQT_AlienStand,(int)ASSS_Standard_Elevation,0); |
| | 1748 | assert(delta); |
| | 1749 | delta->timer = 32767; |
| | 1750 | |
| | 1751 | delta->Active = 0; /* Default for predator. */ |
| | 1752 | } |
| | 1753 | } |
| | 1754 | |
| | 1755 | static void CreatePredatorHModel(NETGHOSTDATABLOCK *ghostDataPtr, int weapon) |
| | 1756 | { |
| | 1757 | const SECTION *root_section; |
| | 1758 | /* KJL 11:09:14 27/01/98 - pick which model to create based on the character's weapon */ |
| | 1759 | switch (weapon) |
| | 1760 | { |
| | 1761 | default: |
| | 1762 | case WEAPON_PRED_WRISTBLADE: |
| | 1763 | root_section = GetNamedHierarchyFromLibrary("hnpcpredator","pred with wristblade"); |
| | 1764 | break; |
| | 1765 | /* |
| | 1766 | case WEAPON_PRED_STAFF: |
| | 1767 | root_section = GetNamedHierarchyFromLibrary("hnpcpredator","pred with staff"); |
| | 1768 | break; |
| | 1769 | */ |
| | 1770 | case WEAPON_PRED_RIFLE: |
| | 1771 | root_section = GetNamedHierarchyFromLibrary("hnpcpredator","Speargun"); |
| | 1772 | break; |
| | 1773 | case WEAPON_PRED_PISTOL: |
| | 1774 | root_section = GetNamedHierarchyFromLibrary("hnpcpredator","pred + pistol"); |
| | 1775 | break; |
| | 1776 | case WEAPON_PRED_SHOULDERCANNON: |
| | 1777 | root_section = GetNamedHierarchyFromLibrary("hnpcpredator","pred with Plasma Caster"); |
| | 1778 | break; |
| | 1779 | case WEAPON_PRED_DISC: |
| | 1780 | root_section = GetNamedHierarchyFromLibrary("hnpcpredator","pred with disk"); |
| | 1781 | break; |
| | 1782 | case WEAPON_PRED_MEDICOMP: |
| | 1783 | root_section = GetNamedHierarchyFromLibrary("hnpcpredator","medicomp"); |
| | 1784 | break; |
| | 1785 | } |
| | 1786 | |
| | 1787 | Create_HModel(&ghostDataPtr->HModelController,root_section); |
| | 1788 | ghostDataPtr->CurrentWeapon = weapon; |
| | 1789 | |
| | 1790 | assert(ghostDataPtr->HModelController.Root_Section==root_section); |
| | 1791 | |
| | 1792 | InitHModelSequence(&ghostDataPtr->HModelController,(int)HMSQT_PredatorStand,(int)PSSS_Standard,ONE_FIXED); |
| | 1793 | ghostDataPtr->currentAnimSequence = PredSQ_Stand; |
| | 1794 | |
| | 1795 | // ghostDataPtr->GunflashSectionPtr=GetThisSectionData(ghostDataPtr->HModelController.section_data,"dum flash"); |
| | 1796 | // assert(ghostDataPtr->GunflashSectionPtr); |
| | 1797 | |
| | 1798 | /* CDF 11/4/98 Elevation Delta Sequence. */ |
| | 1799 | { |
| | 1800 | DELTA_CONTROLLER *delta =
Add_Delta_Sequence(&ghostDataPtr->HModelController,"Elevation",(int)HMSQT_PredatorStand,(int)PSSS_Elevation,0); |
| | 1801 | assert(delta); |
| | 1802 | delta->timer = 32767; |
| | 1803 | delta->Active = 0; /* Default for predator. */ |
| | 1804 | } |
| | 1805 | |
| | 1806 | if (HModelSequence_Exists(&ghostDataPtr->HModelController,(int)HMSQT_PredatorStand,(int)PSSS_HitChestFront)) |
| | 1807 | { |
| | 1808 | DELTA_CONTROLLER *delta =
Add_Delta_Sequence(&ghostDataPtr->HModelController,"HitDelta",(int)HMSQT_PredatorStand,(int)PSSS_HitChestFront,-1); |
| | 1809 | assert(delta); |
| | 1810 | delta->Playing = 0; |
| | 1811 | } |
| | 1812 | |
| | 1813 | ghostDataPtr->hltable = GetThisHitLocationTable("predator"); |
| | 1814 | } |
| | 1815 | |
| | 1816 | /* create a new ghost: doesn't do shape animation stuff: this is performed using a seperate set of functions */ |
| | 1817 | |
| | 1818 | STRATEGYBLOCK *CreateNetGhost(int playerId, int objectId, VECTORCH *position, EULER* orientation, AVP_BEHAVIOUR_TYPE type, uint8_t IOType, uint8_t subtype) |
| | 1819 | { |
| | 1820 | int i; |
| | 1821 | |
| | 1822 | /* first check that the position we've been passed is in a module */ |
| | 1823 | MODULE *myContainingModule = ModuleFromPosition(position, NULL); |
| | 1824 | |
| | 1825 | if(myContainingModule == NULL) |
| | 1826 | return NULL; |
| | 1827 | |
| | 1828 | /* create a strategy block */ |
| | 1829 | STRATEGYBLOCK *sbPtr = CreateActiveStrategyBlock(I_BehaviourNetGhost); |
| | 1830 | |
| | 1831 | if(!sbPtr) |
| | 1832 | return NULL; |
| | 1833 | |
| | 1834 | for(i = 0; i < SB_NAME_LENGTH; i++) sbPtr->SBname[i] = '\0'; |
| | 1835 | AssignNewSBName(sbPtr); |
| | 1836 | |
| | 1837 | /* dynamics block */ |
| | 1838 | { |
| | 1839 | /* need different templates for objects and sprites */ |
| | 1840 | #if EXTRAPOLATION_TEST |
| | 1841 | DYNAMICSBLOCK *dynPtr; |
| | 1842 | switch(type) |
| | 1843 | { |
| | 1844 | case I_BehaviourMarinePlayer: |
| | 1845 | dynPtr = AllocateDynamicsBlock(DYNAMICS_TEMPLATE_DEFAULT); |
| | 1846 | break; |
| | 1847 | case I_BehaviourPredatorPlayer: |
| | 1848 | dynPtr = AllocateDynamicsBlock(DYNAMICS_TEMPLATE_DEFAULT); |
| | 1849 | dynPtr->Mass = 180; |
| | 1850 | break; |
| | 1851 | case I_BehaviourAlienPlayer: |
| | 1852 | case I_BehaviourAlien: |
| | 1853 | dynPtr = AllocateDynamicsBlock(DYNAMICS_TEMPLATE_DEFAULT); |
| | 1854 | dynPtr->ToppleForce = TOPPLE_FORCE_ALIEN; |
| | 1855 | dynPtr->Mass = 160; |
| | 1856 | break; |
| | 1857 | default: |
| | 1858 | dynPtr = AllocateDynamicsBlock(DYNAMICS_TEMPLATE_STATIC); |
| | 1859 | } |
| | 1860 | #else |
| | 1861 | DYNAMICSBLOCK *dynPtr = AllocateDynamicsBlock(DYNAMICS_TEMPLATE_STATIC); |
| | 1862 | #endif |
| | 1863 | if(!dynPtr) |
| | 1864 | { |
| | 1865 | /* allocation failed */ |
| | 1866 | RemoveBehaviourStrategy(sbPtr); |
| | 1867 | return NULL; |
| | 1868 | } |
| | 1869 | |
| | 1870 | sbPtr->DynPtr = dynPtr; |
| | 1871 | dynPtr->GravityOn = 0; |
| | 1872 | dynPtr->IsStatic = 0; |
| | 1873 | dynPtr->IsNetGhost = 1; |
| | 1874 | dynPtr->Position = dynPtr->PrevPosition = *position; |
| | 1875 | dynPtr->OrientEuler = *orientation; |
| | 1876 | CreateEulerMatrix(&dynPtr->OrientEuler, &dynPtr->OrientMat); |
| | 1877 | TransposeMatrixCH(&dynPtr->OrientMat); |
| | 1878 | } |
| | 1879 | |
| | 1880 | /* data block */ |
| | 1881 | { |
| | 1882 | NETGHOSTDATABLOCK *ghostData = malloc(sizeof(NETGHOSTDATABLOCK)); |
| | 1883 | |
| | 1884 | if(!ghostData) |
| | 1885 | { |
| | 1886 | /* allocation failed */ |
| | 1887 | RemoveBehaviourStrategy(sbPtr); |
| | 1888 | return NULL; |
| | 1889 | } |
| | 1890 | |
| | 1891 | sbPtr->dataptr = (void *)ghostData; |
| | 1892 | ghostData->playerId = playerId; |
| | 1893 | ghostData->playerObjectId = objectId; |
| | 1894 | ghostData->type = type; |
| | 1895 | ghostData->IOType = (INANIMATEOBJECT_TYPE)IOType; |
| | 1896 | ghostData->subtype = (int)subtype; |
| | 1897 | ghostData->myGunFlash = NULL; |
| | 1898 | ghostData->GunFlashFrameStamp = GlobalFrameCounter; |
| | 1899 | ghostData->SoundHandle = SOUND_NOACTIVEINDEX; |
| | 1900 | ghostData->SoundHandle2 = SOUND_NOACTIVEINDEX; |
| | 1901 | ghostData->SoundHandle3 = SOUND_NOACTIVEINDEX; |
| | 1902 | ghostData->SoundHandle4 = SOUND_NOACTIVEINDEX; |
| | 1903 | ghostData->currentAnimSequence = 0; |
| | 1904 | ghostData->timer = 0; |
| | 1905 | ghostData->CloakingEffectiveness = 0; |
| | 1906 | ghostData->IgnitionHandshaking = 0; |
| | 1907 | ghostData->soundStartFlag = 0; |
| | 1908 | ghostData->FlameHitCount = 0; |
| | 1909 | ghostData->FlechetteHitCount = 0; |
| | 1910 | ghostData->invulnerable = 0; |
| | 1911 | ghostData->onlyValidFar = 0; |
| | 1912 | |
| | 1913 | #if EXTRAPOLATION_TEST |
| | 1914 | ghostData->velocity.vx = 0; |
| | 1915 | ghostData->velocity.vy = 0; |
| | 1916 | ghostData->velocity.vz = 0; |
| | 1917 | ghostData->extrapTimerLast = 0; |
| | 1918 | ghostData->extrapTimer = 0; |
| | 1919 | #endif |
| | 1920 | |
| | 1921 | /* Clear HModelController. */ |
| | 1922 | ghostData->HModelController.Seconds_For_Sequence = 0; |
| | 1923 | ghostData->HModelController.timer_increment = 0; |
| | 1924 | ghostData->HModelController.Sequence_Type = 0; |
| | 1925 | ghostData->HModelController.Sub_Sequence = 0; |
| | 1926 | ghostData->HModelController.sequence_timer = 0; |
| | 1927 | ghostData->HModelController.FrameStamp = 0; |
| | 1928 | ghostData->HModelController.keyframe_flags = 0; |
| | 1929 | ghostData->HModelController.Deltas = NULL; |
| | 1930 | ghostData->HModelController.Root_Section = NULL; |
| | 1931 | ghostData->HModelController.section_data = NULL; |
| | 1932 | ghostData->HModelController.After_Tweening_Sequence_Type = 0; |
| | 1933 | ghostData->HModelController.After_Tweening_Sub_Sequence = 0; |
| | 1934 | ghostData->HModelController.AT_seconds_for_sequence = 0; |
| | 1935 | ghostData->HModelController.Playing = 0; |
| | 1936 | ghostData->HModelController.Reversed = 0; |
| | 1937 | ghostData->HModelController.Looped = 0; |
| | 1938 | ghostData->HModelController.Tweening = 0; |
| | 1939 | ghostData->HModelController.LoopAfterTweening = 0; |
| | 1940 | ghostData->HModelController.ElevationTweening = 0; |
| | 1941 | /* Whew. */ |
| | 1942 | ghostData->hltable = 0; |
| | 1943 | /* init the integrity */ |
| | 1944 | ghostData->integrity = GHOST_INTEGRITY; |
| | 1945 | |
| | 1946 | /* set the shape */ |
| | 1947 | switch(type) |
| | 1948 | { |
| | 1949 | case I_BehaviourMarinePlayer: |
| | 1950 | CreateMarineHModel(ghostData,WEAPON_PULSERIFLE); |
| | 1951 | ProveHModel_Far(&ghostData->HModelController,sbPtr); |
| | 1952 | break; |
| | 1953 | case I_BehaviourAlienPlayer: |
| | 1954 | CreateAlienHModel(ghostData,0); |
| | 1955 | ProveHModel_Far(&ghostData->HModelController,sbPtr); |
| | 1956 | break; |
| | 1957 | case I_BehaviourPredatorPlayer: |
| | 1958 | CreatePredatorHModel(ghostData,WEAPON_PRED_WRISTBLADE); |
| | 1959 | ProveHModel_Far(&ghostData->HModelController,sbPtr); |
| | 1960 | break; |
| | 1961 | /* KJL 16:57:14 17/06/98 - NPC characters */ |
| | 1962 | case I_BehaviourAlien: |
| | 1963 | CreateAlienHModel(ghostData,subtype); |
| | 1964 | |
| | 1965 | ProveHModel_Far(&ghostData->HModelController,sbPtr); |
| | 1966 | break; |
| | 1967 | case I_BehaviourGrenade: |
| | 1968 | case I_BehaviourPulseGrenade: |
| | 1969 | sbPtr->shapeIndex = GetLoadedShapeMSL("Shell"); |
| | 1970 | break; |
| | 1971 | case I_BehaviourFragmentationGrenade: |
| | 1972 | sbPtr->shapeIndex = GetLoadedShapeMSL("Cluster"); |
| | 1973 | break; |
| | 1974 | case I_BehaviourRocket: |
| | 1975 | sbPtr->shapeIndex = GetLoadedShapeMSL("missile"); |
| | 1976 | break; |
| | 1977 | case I_BehaviourPredatorEnergyBolt: |
| | 1978 | sbPtr->shapeIndex = 0; // uses a special effect |
| | 1979 | //need to play the energy bolt being fired sound |
| | 1980 | Sound_Play(SID_PRED_LAUNCHER, "hpd", (FastRandom()&255)-128, &sbPtr->DynPtr->Position); |
| | 1981 | break; |
| | 1982 | case I_BehaviourFrisbeeEnergyBolt: |
| | 1983 | sbPtr->shapeIndex = 0; // uses a special effect |
| | 1984 | //need to play the energy bolt being fired sound |
| | 1985 | Sound_Play(SID_PRED_LAUNCHER, "hpd", (FastRandom()&255)-128, &sbPtr->DynPtr->Position); |
| | 1986 | break; |
| | 1987 | case I_BehaviourPPPlasmaBolt: |
| | 1988 | sbPtr->shapeIndex = 0; // uses a special effect |
| | 1989 | break; |
| | 1990 | case I_BehaviourPredatorDisc_SeekTrack: |
| | 1991 | { |
| | 1992 | const SECTION *root_section = GetNamedHierarchyFromLibrary("disk","Disk"); |
| | 1993 | |
| | 1994 | assert(root_section); |
| | 1995 | |
| | 1996 | Create_HModel(&ghostData->HModelController,root_section); |
| | 1997 | InitHModelSequence(&ghostData->HModelController,HMSQT_MarineStand,MSSS_Minigun_Delta,ONE_FIXED); |
| | 1998 | ProveHModel_Far(&ghostData->HModelController,sbPtr); |
| | 1999 | |
| | 2000 | /* Just to make sure. */ |
| | 2001 | sbPtr->shapeIndex = GetLoadedShapeMSL("Shell"); |
| | 2002 | } |
| | 2003 | break; |
| | 2004 | case I_BehaviourFrisbee: |
| | 2005 | { |
| | 2006 | const SECTION *root_section = GetNamedHierarchyFromLibrary("mdisk","Mdisk"); |
| | 2007 | |
| | 2008 | assert(root_section); |
| | 2009 | |
| | 2010 | Create_HModel(&ghostData->HModelController,root_section); |
| | 2011 | InitHModelSequence(&ghostData->HModelController,HMSQT_MarineStand,MSSS_Minigun_Delta,(ONE_FIXED>>1)); |
| | 2012 | ProveHModel_Far(&ghostData->HModelController,sbPtr); |
| | 2013 | |
| | 2014 | /* Just to make sure. */ |
| | 2015 | sbPtr->shapeIndex = GetLoadedShapeMSL("Shell"); |
| | 2016 | |
| | 2017 | //Sound_Play(SID_ED_SKEETERLAUNCH, "hd", &sbPtr->DynPtr->Position); |
| | 2018 | } |
| | 2019 | break; |
| | 2020 | case I_BehaviourInanimateObject: |
| | 2021 | /* That *should* only happen for pred discs at this stage */ |
| | 2022 | //Now there are also weapons that appear when players die |
| | 2023 | if(IOType==IOT_Weapon) |
| | 2024 | { |
| | 2025 | switch(subtype) |
| | 2026 | { |
| | 2027 | case WEAPON_MARINE_PISTOL: |
| | 2028 | case WEAPON_PULSERIFLE: |
| | 2029 | sbPtr->shapeIndex = GetLoadedShapeMSL("pulse"); |
| | 2030 | break; |
| | 2031 | case WEAPON_SMARTGUN: |
| | 2032 | sbPtr->shapeIndex = GetLoadedShapeMSL("smart"); |
| | 2033 | break; |
| | 2034 | case WEAPON_FLAMETHROWER: |
| | 2035 | sbPtr->shapeIndex = GetLoadedShapeMSL("flame"); |
| | 2036 | break; |
| | 2037 | case WEAPON_SADAR: |
| | 2038 | sbPtr->shapeIndex = GetLoadedShapeMSL("sadar"); |
| | 2039 | break; |
| | 2040 | case WEAPON_GRENADELAUNCHER: |
| | 2041 | sbPtr->shapeIndex = GetLoadedShapeMSL("grenade"); |
| | 2042 | break; |
| | 2043 | case WEAPON_MINIGUN: |
| | 2044 | sbPtr->shapeIndex = GetLoadedShapeMSL("minigun"); |
| | 2045 | break; |
| | 2046 | case WEAPON_FRISBEE_LAUNCHER: |
| | 2047 | sbPtr->shapeIndex = GetLoadedShapeMSL("sadar"); |
| | 2048 | break; |
| | 2049 | default: |
| | 2050 | { |
| | 2051 | assert(0=="Unexpected weapon type"); |
| | 2052 | } |
| | 2053 | } |
| | 2054 | |
| | 2055 | sbPtr->DynPtr->IsPickupObject = 1; |
| | 2056 | assert(sbPtr->shapeIndex != -1); |
| | 2057 | } |
| | 2058 | else |
| | 2059 | { |
| | 2060 | const SECTION *root_section = GetNamedHierarchyFromLibrary("disk","Disk"); |
| | 2061 | |
| | 2062 | assert(IOType == IOT_Ammo); |
| | 2063 | assert(subtype == AMMO_PRED_DISC); |
| | 2064 | assert(root_section); |
| | 2065 | |
| | 2066 | /* Now it's not hierarchical! */ |
| | 2067 | const SECTION *disc_section = GetThisSection(root_section, "disk"); |
| | 2068 | assert(disc_section); |
| | 2069 | |
| | 2070 | sbPtr->shapeIndex = disc_section->ShapeNum; |
| | 2071 | } |
| | 2072 | break; |
| | 2073 | case I_BehaviourFlare: |
| | 2074 | sbPtr->shapeIndex = GetLoadedShapeMSL("Flare"); |
| | 2075 | ghostData->timer = FLARE_LIFETIME*ONE_FIXED; |
| | 2076 | break; |
| | 2077 | case I_BehaviourProximityGrenade: |
| | 2078 | sbPtr->shapeIndex = GetLoadedShapeMSL("Proxmine"); |
| | 2079 | ghostData->timer = PROX_GRENADE_LIFETIME*ONE_FIXED*2; |
| | 2080 | break; |
| | 2081 | case I_BehaviourAutoGun: |
| | 2082 | sbPtr->shapeIndex = GetLoadedShapeMSL("Sentry01"); |
| | 2083 | break; |
| | 2084 | case I_BehaviourSpeargunBolt: |
| | 2085 | sbPtr->shapeIndex = GetLoadedShapeMSL("spear"); |
| | 2086 | //speargun bolt won't get any location updates , so set integrity |
| | 2087 | //to be the standard speargun timeout time. |
| | 2088 | ghostData->integrity = 20*ONE_FIXED; |
| | 2089 | |
| | 2090 | //play the sound for the bolt as well |
| | 2091 | Sound_Play(SID_SPEARGUN_HITTING_WALL, "d", &sbPtr->DynPtr->Position); |
| | 2092 | //and make the sparks |
| | 2093 | { |
| | 2094 | VECTORCH pos = sbPtr->DynPtr->Position; |
| | 2095 | pos.vx += sbPtr->DynPtr->OrientMat.mat31; |
| | 2096 | pos.vy += sbPtr->DynPtr->OrientMat.mat32; |
| | 2097 | pos.vz += sbPtr->DynPtr->OrientMat.mat33; |
| | 2098 | MakeFocusedExplosion(&(sbPtr->DynPtr->Position), &pos, 20, PARTICLE_SPARK); |
| | 2099 | } |
| | 2100 | default: |
| | 2101 | break; |
| | 2102 | } |
| | 2103 | |
| | 2104 | assert(sbPtr->shapeIndex != -1); |
| | 2105 | } |
| | 2106 | |
| | 2107 | /* strategy block initialisation, after dynamics block creation */ |
| | 2108 | sbPtr->maintainVisibility = 1; |
| | 2109 | sbPtr->containingModule = myContainingModule; |
| | 2110 | |
| | 2111 | return sbPtr; |
| | 2112 | } |
| | 2113 | |
| | 2114 | #if EXTRAPOLATION_TEST |
| | 2115 | int UseExtrapolation = 1; |
| | 2116 | void PlayerGhostExtrapolation() |
| | 2117 | { |
| | 2118 | int sbIndex = 0; |
| | 2119 | |
| | 2120 | //search for all ghosts of players |
| | 2121 | while(sbIndex < NumActiveStBlocks) |
| | 2122 | { |
| | 2123 | STRATEGYBLOCK *sbPtr = ActiveStBlockList[sbIndex++]; |
| | 2124 | |
| | 2125 | if(sbPtr->type == I_BehaviourNetGhost) |
| | 2126 | { |
| | 2127 | NETGHOSTDATABLOCK *ghostData = (NETGHOSTDATABLOCK *)sbPtr->dataptr; |
| | 2128 | |
| | 2129 | switch(ghostData->type) |
| | 2130 | { |
| | 2131 | case I_BehaviourMarinePlayer: |
| | 2132 | case I_BehaviourAlienPlayer: |
| | 2133 | case I_BehaviourAlien: |
| | 2134 | case I_BehaviourPredatorPlayer: |
| | 2135 | { |
| | 2136 | int time; |
| | 2137 | DYNAMICSBLOCK* dynPtr= sbPtr->DynPtr; |
| | 2138 | if(ghostData->onlyValidFar) |
| | 2139 | continue; |
| | 2140 | |
| | 2141 | if(UseExtrapolation) |
| | 2142 | { |
| | 2143 | dynPtr->LinVelocity.vx = 0; |
| | 2144 | dynPtr->LinVelocity.vy = 0; |
| | 2145 | dynPtr->LinVelocity.vz = 0; |
| | 2146 | |
| | 2147 | dynPtr->IsNetGhost = 0; |
| | 2148 | |
| | 2149 | ghostData->extrapTimer += NormalFrameTime; |
| | 2150 | if(ghostData->extrapTimer < 0) |
| | 2151 | ghostData->extrapTimer=0; |
| | 2152 | |
| | 2153 | if(ghostData->extrapTimer > ONE_FIXED/2) |
| | 2154 | ghostData->extrapTimer=ONE_FIXED/2; |
| | 2155 | |
| | 2156 | time = ghostData->extrapTimer - ghostData->extrapTimerLast; |
| | 2157 | ghostData->extrapTimerLast = ghostData->extrapTimer; |
| | 2158 | |
| | 2159 | if(!ghostData->velocity.vx && !ghostData->velocity.vy && !ghostData->velocity.vz) |
| | 2160 | { |
| | 2161 | /* |
| | 2162 | Not moving , so alter the dynamics block settings to match those of a non-extrapolated |
| | 2163 | net ghost. |
| | 2164 | */ |
| | 2165 | dynPtr->LinImpulse.vx = dynPtr->LinImpulse.vy = dynPtr->LinImpulse.vz = 0; |
| | 2166 | |
| | 2167 | ghostData->extrapTimerLast = ghostData->extrapTimer = 0; |
| | 2168 | dynPtr->IsNetGhost = 1; |
| | 2169 | dynPtr->UseStandardGravity = 1; |
| | 2170 | sbPtr->DynPtr->ToppleForce = TOPPLE_FORCE_NONE; |
| | 2171 | } |
| | 2172 | else if(time > 0) |
| | 2173 | { |
| | 2174 | dynPtr->LinVelocity = ghostData->velocity; |
| | 2175 | |
| | 2176 | if(time != NormalFrameTime) |
| | 2177 | { |
| | 2178 | //only doing interpolation for a fraction of a frame |
| | 2179 | //so we need to scale the velocity accordingly |
| | 2180 | dynPtr->LinVelocity.vx = WideMulNarrowDiv(dynPtr->LinVelocity.vx,time,NormalFrameTime); |
| | 2181 | dynPtr->LinVelocity.vy = WideMulNarrowDiv(dynPtr->LinVelocity.vy,time,NormalFrameTime); |
| | 2182 | dynPtr->LinVelocity.vz = WideMulNarrowDiv(dynPtr->LinVelocity.vz,time,NormalFrameTime); |
| | 2183 | } |
| | 2184 | } |
| | 2185 | |
| | 2186 | /* |
| | 2187 | if(sbPtr->DisplayBlock) |
| | 2188 | sbPtr->DisplayBlock->ObRadius=1200; |
| | 2189 | */ |
| | 2190 | } |
| | 2191 | else |
| | 2192 | { |
| | 2193 | //not using extrapolation , so make sure dynamics block |
| | 2194 | //contains normal ghost settings |
| | 2195 | dynPtr->LinImpulse.vx = 0; |
| | 2196 | dynPtr->LinImpulse.vy = 0; |
| | 2197 | dynPtr->LinImpulse.vz = 0; |
| | 2198 | dynPtr->LinVelocity.vx = 0; |
| | 2199 | dynPtr->LinVelocity.vy = 0; |
| | 2200 | dynPtr->LinVelocity.vz = 0; |
| | 2201 | dynPtr->UseStandardGravity = 1; |
| | 2202 | dynPtr->IsNetGhost = 1; |
| | 2203 | sbPtr->DynPtr->ToppleForce = TOPPLE_FORCE_NONE; |
| | 2204 | } |
| | 2205 | } |
| | 2206 | default: |
| | 2207 | break; |
| | 2208 | } |
| | 2209 | } |
| | 2210 | } |
| | 2211 | } |
| | 2212 | |
| | 2213 | static DISPLAYBLOCK* AddNPCGunFlashEffect(VECTORCH *position, MATRIXCH* orientation, enum SFX_ID sfxID) |
| | 2214 | { |
| | 2215 | DISPLAYBLOCK *dPtr = CreateSFXObject(sfxID); |
| | 2216 | |
| | 2217 | if(dPtr) |
| | 2218 | { |
| | 2219 | dPtr->ObWorld = *position; |
| | 2220 | dPtr->ObMat = *orientation; |
| | 2221 | AddLightingEffectToObject(dPtr, LFX_MUZZLEFLASH); |
| | 2222 | dPtr->SfxPtr->EffectDrawnLastFrame = 0; |
| | 2223 | } |
| | 2224 | |
| | 2225 | return dPtr; |
| | 2226 | } |
| | 2227 | |
| | 2228 | /* This function maintains a player ghost's gunflash effect, and is called from |
| | 2229 | processmsg_playerstate(). It maintains the ghost given by index, and takes as a |
| | 2230 | parameter the state of the net-player's muzzle flash, as indicated in the last |
| | 2231 | network message. It */ |
| | 2232 | void HandleGhostGunFlashEffect(STRATEGYBLOCK *sbPtr, int gunFlashOn) |
| | 2233 | { |
| | 2234 | assert(sbPtr); |
| | 2235 | NETGHOSTDATABLOCK *ghostData = (NETGHOSTDATABLOCK *)sbPtr->dataptr; |
| | 2236 | assert(ghostData); |
| | 2237 | |
| | 2238 | /* aliens shouldn't have gun flashes */ |
| | 2239 | switch(ghostData->type) |
| | 2240 | { |
| | 2241 | case I_BehaviourAlienPlayer: |
| | 2242 | case I_BehaviourPredatorPlayer: |
| | 2243 | ghostData->myGunFlash = NULL; |
| | 2244 | return; |
| | 2245 | case I_BehaviourMarinePlayer: |
| | 2246 | { |
| | 2247 | if (gunFlashOn == 2) |
| | 2248 | { |
| | 2249 | ghostData->GunflashSectionPtr=GetThisSectionData(ghostData->HModelController.section_data,"dum L flash"); |
| | 2250 | |
| | 2251 | if (ghostData->GunflashSectionPtr == NULL) |
| | 2252 | ghostData->GunflashSectionPtr = GetThisSectionData(ghostData->HModelController.section_data,"dum flash"); |
| | 2253 | } |
| | 2254 | else if (gunFlashOn == 1) |
| | 2255 | { |
| | 2256 | ghostData->GunflashSectionPtr=GetThisSectionData(ghostData->HModelController.section_data,"dum flash"); |
| | 2257 | } |
| | 2258 | /* |
| | 2259 | else if (gunFlashOn == 3) |
| | 2260 | { |
| | 2261 | // Extrapolation. |
| | 2262 | } |
| | 2263 | */ |
| | 2264 | } |
| | 2265 | default: |
| | 2266 | break; |
| | 2267 | } |
| | 2268 | |
| | 2269 | //assert((ghostData->type == I_BehaviourMarinePlayer)|| (ghostData->type == I_BehaviourPredatorPlayer)); |
| | 2270 | |
| | 2271 | /* Handle two pistols? */ |
| | 2272 | |
| | 2273 | if(ghostData->myGunFlash) |
| | 2274 | { |
| | 2275 | /* I've already got a gun flash... */ |
| | 2276 | if(gunFlashOn) |
| | 2277 | { |
| | 2278 | /* Maintain existing gun flash */ |
| | 2279 | assert(ghostData->GunflashSectionPtr); |
| | 2280 | |
| | 2281 | if (sbPtr->DisplayBlock) |
| | 2282 | { |
| | 2283 | ProveHModel(&ghostData->HModelController,sbPtr->DisplayBlock); |
| | 2284 | ghostData->myGunFlash->ObWorld = ghostData->GunflashSectionPtr->World_Offset; |
| | 2285 | ghostData->myGunFlash->ObMat = ghostData->GunflashSectionPtr->SecMat; |
| | 2286 | AddLightingEffectToObject(ghostData->myGunFlash, LFX_MUZZLEFLASH); |
| | 2287 | } |
| | 2288 | } |
| | 2289 | else |
| | 2290 | { |
| | 2291 | if (ghostData->GunFlashFrameStamp != GlobalFrameCounter) |
| | 2292 | { |
| | 2293 | /* Maintain for at least one frame. */ |
| | 2294 | DestroyActiveObject(&ghostData->myGunFlash); |
| | 2295 | } |
| | 2296 | } |
| | 2297 | } |
| | 2298 | else |
| | 2299 | { |
| | 2300 | if(gunFlashOn) |
| | 2301 | { |
| | 2302 | /* new flash */ |
| | 2303 | assert(ghostData->GunflashSectionPtr); |
| | 2304 | ghostData->GunFlashFrameStamp = GlobalFrameCounter; |
| | 2305 | |
| | 2306 | if (sbPtr->DisplayBlock) |
| | 2307 | { |
| | 2308 | ProveHModel(&ghostData->HModelController,sbPtr->DisplayBlock); |
| | 2309 | |
| | 2310 | switch(ghostData->CurrentWeapon) |
| | 2311 | { |
| | 2312 | case WEAPON_SMARTGUN: |
| | 2313 | { |
| | 2314 | ghostData->myGunFlash = AddNPCGunFlashEffect |
| | 2315 | ( |
| | 2316 | &ghostData->GunflashSectionPtr->World_Offset, |
| | 2317 | &ghostData->GunflashSectionPtr->SecMat, |
| | 2318 | SFX_MUZZLE_FLASH_SMARTGUN |
| | 2319 | ); |
| | 2320 | } |
| | 2321 | break; |
| | 2322 | case WEAPON_FRISBEE_LAUNCHER: |
| | 2323 | { |
| | 2324 | ghostData->myGunFlash = AddNPCGunFlashEffect |
| | 2325 | ( |
| | 2326 | &ghostData->GunflashSectionPtr->World_Offset, |
| | 2327 | &ghostData->GunflashSectionPtr->SecMat, |
| | 2328 | SFX_MUZZLE_FLASH_SKEETER |
| | 2329 | ); |
| | 2330 | } |
| | 2331 | break; |
| | 2332 | default: |
| | 2333 | { |
| | 2334 | ghostData->myGunFlash = AddNPCGunFlashEffect |
| | 2335 | ( |
| | 2336 | &ghostData->GunflashSectionPtr->World_Offset, |
| | 2337 | &ghostData->GunflashSectionPtr->SecMat, |
| | 2338 | SFX_MUZZLE_FLASH_AMORPHOUS |
| | 2339 | ); |
| | 2340 | } |
| | 2341 | } |
| | 2342 | } |
| | 2343 | } |
| | 2344 | } |
| | 2345 | } |
| | 2346 | |
| | 2347 | #endif //EXTRAPOLATION_TEST |
| | 2348 | |
| | 2349 | /* these functions are called directly by the visibility management system */ |
| | 2350 | void MakeGhostNear(STRATEGYBLOCK *sbPtr) |
| | 2351 | { |
| | 2352 | NETGHOSTDATABLOCK *ghostData = (NETGHOSTDATABLOCK *)sbPtr->dataptr; |
| | 2353 | DYNAMICSBLOCK *dynPtr = sbPtr->DynPtr; |
| | 2354 | SFXBLOCK *sfxPtr = NULL; |
| | 2355 | |
| | 2356 | assert(ghostData); |
| | 2357 | |
| | 2358 | /* KJL 11:56:09 08/05/98 - if shape doesn't exist, use a sfx */ |
| | 2359 | |
| | 2360 | switch(ghostData->type) |
| | 2361 | { |
| | 2362 | case I_BehaviourPredatorEnergyBolt: |
| | 2363 | case I_BehaviourFrisbeeEnergyBolt: |
| | 2364 | case I_BehaviourPPPlasmaBolt: |
| | 2365 | { |
| | 2366 | sfxPtr = AllocateSfxBlock(); |
| | 2367 | // if we haven't got a free sfx block, return */ |
| | 2368 | if (!sfxPtr) |
| | 2369 | return; |
| | 2370 | } |
| | 2371 | default: |
| | 2372 | break; |
| | 2373 | } |
| | 2374 | |
| | 2375 | if(ghostData->onlyValidFar) |
| | 2376 | return; //Far alien ai , don't have enough information to make it near |
| | 2377 | |
| | 2378 | assert(dynPtr); |
| | 2379 | assert(sbPtr->DisplayBlock == NULL); |
| | 2380 | |
| | 2381 | DISPLAYBLOCK *dPtr = AllocateNewObject(sbPtr->shapeIndex); |
| | 2382 | |
| | 2383 | if(dPtr == NULL) |
| | 2384 | return; /* cannot create displayblock, so leave object "far" */ |
| | 2385 | |
| | 2386 | sbPtr->DisplayBlock = dPtr; |
| | 2387 | dPtr->ObStrategyBlock = sbPtr; |
| | 2388 | |
| | 2389 | /* set the animation sequence, if we're a player ghost */ |
| | 2390 | if(ghostData->playerObjectId == GHOST_PLAYEROBJECTID) |
| | 2391 | { |
| | 2392 | assert((ghostData->type == I_BehaviourMarinePlayer)|| |
| | 2393 | (ghostData->type == I_BehaviourPredatorPlayer)|| |
| | 2394 | (ghostData->type == I_BehaviourAlienPlayer)); |
| | 2395 | |
| | 2396 | dPtr->HModelControlBlock = &ghostData->HModelController; |
| | 2397 | ProveHModel(dPtr->HModelControlBlock, dPtr); |
| | 2398 | } |
| | 2399 | else |
| | 2400 | { |
| | 2401 | switch(ghostData->type) |
| | 2402 | { |
| | 2403 | case I_BehaviourAlien: |
| | 2404 | case I_BehaviourPredatorDisc_SeekTrack: |
| | 2405 | case I_BehaviourFrisbee: |
| | 2406 | case I_BehaviourCorpse: |
| | 2407 | dPtr->HModelControlBlock = &ghostData->HModelController; |
| | 2408 | ProveHModel(dPtr->HModelControlBlock, dPtr); |
| | 2409 | default: |
| | 2410 | break; |
| | 2411 | } |
| | 2412 | } |
| | 2413 | |
| | 2414 | /* need to initialise positional information in the new display block */ |
| | 2415 | dPtr->ObWorld = dynPtr->Position; |
| | 2416 | dPtr->ObEuler = dynPtr->OrientEuler; |
| | 2417 | dPtr->ObMat = dynPtr->OrientMat; |
| | 2418 | dPtr->SfxPtr = sfxPtr; |
| | 2419 | |
| | 2420 | /* finally, need to add lighting effects to the displayblock */ |
| | 2421 | switch(ghostData->type) |
| | 2422 | { |
| | 2423 | case I_BehaviourPulseGrenade: |
| | 2424 | case I_BehaviourRocket: |
| | 2425 | AddLightingEffectToObject(dPtr,LFX_ROCKETJET); |
| | 2426 | break; |
| | 2427 | case I_BehaviourPredatorEnergyBolt: |
| | 2428 | sfxPtr->SfxID = SFX_PREDATOR_PLASMA_BOLT; |
| | 2429 | AddLightingEffectToObject(dPtr,LFX_PLASMA_BOLT); |
| | 2430 | break; |
| | 2431 | case I_BehaviourFrisbeeEnergyBolt: |
| | 2432 | sfxPtr->SfxID = SFX_FRISBEE_PLASMA_BOLT; |
| | 2433 | AddLightingEffectToObject(dPtr,LFX_PLASMA_BOLT); |
| | 2434 | break; |
| | 2435 | case I_BehaviourPPPlasmaBolt: |
| | 2436 | sfxPtr->SfxID = SFX_SMALL_PREDATOR_PLASMA_BOLT; |
| | 2437 | AddLightingEffectToObject(dPtr,LFX_PLASMA_BOLT); |
| | 2438 | break; |
| | 2439 | case I_BehaviourFlare: |
| | 2440 | AddLightingEffectToObject(dPtr,LFX_FLARE); |
| | 2441 | default: |
| | 2442 | break; |
| | 2443 | } |
| | 2444 | } |
| | 2445 | |
| | 2446 | /* this function handles damage to a netghost object: |
| | 2447 | basically, it just sends a network message, which should be picked up by the owning object */ |
| | 2448 | void DamageNetworkGhost(STRATEGYBLOCK *sbPtr, const DAMAGE_PROFILE *damage, int multiple, SECTION_DATA *section,VECTORCH* incoming) |
| | 2449 | { |
| | 2450 | int delta_seq = -1; |
| | 2451 | int delta_sub_seq = -1; |
| | 2452 | |
| | 2453 | assert(AvP.Network != I_No_Network); |
| | 2454 | |
| | 2455 | if(section) |
| | 2456 | { |
| | 2457 | //get the appropriate delta sequence |
| | 2458 | int frontback = 1; |
| | 2459 | |
| | 2460 | if (incoming && incoming->vz >= 0) |
| | 2461 | frontback = 0; |
| | 2462 | |
| | 2463 | NETGHOSTDATABLOCK *ghostData = (NETGHOSTDATABLOCK *)sbPtr->dataptr; |
| | 2464 | |
| | 2465 | switch(ghostData->type) |
| | 2466 | { |
| | 2467 | case I_BehaviourMarinePlayer: |
| | 2468 | { |
| | 2469 | int CrouchSubSequence; |
| | 2470 | int StandSubSequence; |
| | 2471 | |
| | 2472 | if (section == NULL) |
| | 2473 | { |
| | 2474 | if (!frontback) |
| | 2475 | { |
| | 2476 | CrouchSubSequence = MCrSS_HitChestBack; |
| | 2477 | StandSubSequence = MSSS_HitChestBack; |
| | 2478 | } |
| | 2479 | else |
| | 2480 | { |
| | 2481 | CrouchSubSequence = MCrSS_HitChestFront; |
| | 2482 | StandSubSequence = MSSS_HitChestFront; |
| | 2483 | } |
| | 2484 | } |
| | 2485 | else if (section->sempai->flags & section_flag_head) |
| | 2486 | { |
| | 2487 | if (!frontback) |
| | 2488 | { |
| | 2489 | CrouchSubSequence = MCrSS_HitHeadBack; |
| | 2490 | StandSubSequence = MSSS_HitHeadBack; |
| | 2491 | } |
| | 2492 | else |
| | 2493 | { |
| | 2494 | CrouchSubSequence = MCrSS_HitHeadFront; |
| | 2495 | StandSubSequence = MSSS_HitHeadFront; |
| | 2496 | } |
| | 2497 | } |
| | 2498 | else if ((section->sempai->flags & section_flag_left_arm) |
| | 2499 | ||(section->sempai->flags & section_flag_left_hand)) |
| | 2500 | { |
| | 2501 | if (!frontback) |
| | 2502 | { |
| | 2503 | CrouchSubSequence = MCrSS_HitRightArm; |
| | 2504 | StandSubSequence = MSSS_HitRightArm; |
| | 2505 | } |
| | 2506 | else |
| | 2507 | { |
| | 2508 | CrouchSubSequence = MCrSS_HitLeftArm; |
| | 2509 | StandSubSequence = MSSS_HitLeftArm; |
| | 2510 | } |
| | 2511 | } |
| | 2512 | else if ((section->sempai->flags & section_flag_right_arm) |
| | 2513 | ||(section->sempai->flags & section_flag_right_hand)) |
| | 2514 | { |
| | 2515 | if (!frontback) |
| | 2516 | { |
| | 2517 | CrouchSubSequence = MCrSS_HitLeftArm; |
| | 2518 | StandSubSequence = MSSS_HitLeftArm; |
| | 2519 | } |
| | 2520 | else |
| | 2521 | { |
| | 2522 | CrouchSubSequence = MCrSS_HitRightArm; |
| | 2523 | StandSubSequence = MSSS_HitRightArm; |
| | 2524 | } |
| | 2525 | } |
| | 2526 | else if ((section->sempai->flags & section_flag_left_leg) |
| | 2527 | ||(section->sempai->flags & section_flag_left_foot)) |
| | 2528 | { |
| | 2529 | CrouchSubSequence = MCrSS_HitLeftLeg; |
| | 2530 | StandSubSequence = MSSS_HitLeftLeg; |
| | 2531 | } |
| | 2532 | else if ((section->sempai->flags & section_flag_right_leg) |
| | 2533 | ||(section->sempai->flags & section_flag_right_foot)) |
| | 2534 | { |
| | 2535 | CrouchSubSequence = MCrSS_HitRightLeg; |
| | 2536 | StandSubSequence = MSSS_HitRightLeg; |
| | 2537 | } |
| | 2538 | else |
| | 2539 | { |
| | 2540 | /* Chest or misc. hit. */ |
| | 2541 | if (!frontback) |
| | 2542 | { |
| | 2543 | CrouchSubSequence = MCrSS_HitChestBack; |
| | 2544 | StandSubSequence = MSSS_HitChestBack; |
| | 2545 | } |
| | 2546 | else |
| | 2547 | { |
| | 2548 | CrouchSubSequence = MCrSS_HitChestFront; |
| | 2549 | StandSubSequence= MSSS_HitChestFront; |
| | 2550 | } |
| | 2551 | } |
| | 2552 | |
| | 2553 | switch(ghostData->currentAnimSequence) |
| | 2554 | { |
| | 2555 | case MSQ_Crawl: |
| | 2556 | case MSQ_Crawl_Backwards: |
| | 2557 | case MSQ_Crouch: |
| | 2558 | delta_seq = (int)HMSQT_MarineCrouch; |
| | 2559 | delta_sub_seq = (int)CrouchSubSequence; |
| | 2560 | break; |
| | 2561 | default: |
| | 2562 | delta_seq = (int)HMSQT_MarineStand; |
| | 2563 | delta_sub_seq = (int)StandSubSequence; |
| | 2564 | } |
| | 2565 | |
| | 2566 | PlayHitDeltaOnGhost(sbPtr,delta_seq,delta_sub_seq); |
| | 2567 | } |
| | 2568 | break; |
| | 2569 | case I_BehaviourPredatorPlayer: |
| | 2570 | { |
| | 2571 | int CrouchSubSequence; |
| | 2572 | int StandSubSequence; |
| | 2573 | |
| | 2574 | if (section == NULL) |
| | 2575 | { |
| | 2576 | if (!frontback) |
| | 2577 | { |
| | 2578 | CrouchSubSequence = PCrSS_HitChestBack; |
| | 2579 | StandSubSequence = PSSS_HitChestBack; |
| | 2580 | } |
| | 2581 | else |
| | 2582 | { |
| | 2583 | CrouchSubSequence = PCrSS_HitChestFront; |
| | 2584 | StandSubSequence = PSSS_HitChestFront; |
| | 2585 | } |
| | 2586 | } |
| | 2587 | else if (section->sempai->flags & section_flag_head) |
| | 2588 | { |
| | 2589 | if (!frontback) |
| | 2590 | { |
| | 2591 | CrouchSubSequence = PCrSS_HitHeadBack; |
| | 2592 | StandSubSequence = PSSS_HitHeadBack; |
| | 2593 | } |
| | 2594 | else |
| | 2595 | { |
| | 2596 | CrouchSubSequence = PCrSS_HitHeadFront; |
| | 2597 | StandSubSequence = PSSS_HitHeadFront; |
| | 2598 | } |
| | 2599 | } |
| | 2600 | else if ((section->sempai->flags & section_flag_left_arm) |
| | 2601 | ||(section->sempai->flags & section_flag_left_hand)) |
| | 2602 | { |
| | 2603 | if (!frontback) |
| | 2604 | { |
| | 2605 | CrouchSubSequence = PCrSS_HitRightArm; |
| | 2606 | StandSubSequence = PSSS_HitRightArm; |
| | 2607 | } |
| | 2608 | else |
| | 2609 | { |
| | 2610 | CrouchSubSequence = PCrSS_HitLeftArm; |
| | 2611 | StandSubSequence = PSSS_HitLeftArm; |
| | 2612 | } |
| | 2613 | } |
| | 2614 | else if ((section->sempai->flags & section_flag_right_arm) |
| | 2615 | ||(section->sempai->flags & section_flag_right_hand)) |
| | 2616 | { |
| | 2617 | if (!frontback) |
| | 2618 | { |
| | 2619 | CrouchSubSequence = PCrSS_HitLeftArm; |
| | 2620 | StandSubSequence = PSSS_HitLeftArm; |
| | 2621 | } |
| | 2622 | else |
| | 2623 | { |
| | 2624 | CrouchSubSequence = PCrSS_HitRightArm; |
| | 2625 | StandSubSequence = PSSS_HitRightArm; |
| | 2626 | } |
| | 2627 | } |
| | 2628 | else if ((section->sempai->flags & section_flag_left_leg) |
| | 2629 | ||(section->sempai->flags & section_flag_left_foot)) |
| | 2630 | { |
| | 2631 | CrouchSubSequence = PCrSS_HitLeftLeg; |
| | 2632 | StandSubSequence = PSSS_HitLeftLeg; |
| | 2633 | |
| | 2634 | } |
| | 2635 | else if ((section->sempai->flags & section_flag_right_leg) |
| | 2636 | ||(section->sempai->flags & section_flag_right_foot)) |
| | 2637 | { |
| | 2638 | CrouchSubSequence = PCrSS_HitRightLeg; |
| | 2639 | StandSubSequence = PSSS_HitRightLeg; |
| | 2640 | } |
| | 2641 | else |
| | 2642 | { |
| | 2643 | /* Chest or misc. hit. */ |
| | 2644 | if (!frontback) |
| | 2645 | { |
| | 2646 | CrouchSubSequence = PCrSS_HitChestBack; |
| | 2647 | StandSubSequence = PSSS_HitChestBack; |
| | 2648 | } |
| | 2649 | else |
| | 2650 | { |
| | 2651 | CrouchSubSequence = PCrSS_HitChestFront; |
| | 2652 | StandSubSequence = PSSS_HitChestFront; |
| | 2653 | } |
| | 2654 | } |
| | 2655 | |
| | 2656 | switch(ghostData->currentAnimSequence) |
| | 2657 | { |
| | 2658 | case PredSQ_Crawl: |
| | 2659 | case PredSQ_Crawl_Backwards: |
| | 2660 | case PredSQ_Crouch: |
| | 2661 | case PredSQ_CrouchedSwipe: |
| | 2662 | case PredSQ_CrawlingSwipe: |
| | 2663 | case PredSQ_CrawlingSwipe_Backwards: |
| | 2664 | delta_seq = (int)HMSQT_PredatorCrouch; |
| | 2665 | delta_sub_seq = (int)CrouchSubSequence; |
| | 2666 | break; |
| | 2667 | default: |
| | 2668 | delta_seq = (int)HMSQT_PredatorStand; |
| | 2669 | delta_sub_seq = (int)StandSubSequence; |
| | 2670 | } |
| | 2671 | |
| | 2672 | PlayHitDeltaOnGhost(sbPtr,delta_seq,delta_sub_seq); |
| | 2673 | } |
| | 2674 | default: |
| | 2675 | break; |
| | 2676 | } |
| | 2677 | } |
| | 2678 | |
| | 2679 | { |
| | 2680 | int sectionID; |
| | 2681 | if (section) |
| | 2682 | sectionID = section->sempai->IDnumber; |
| | 2683 | else |
| | 2684 | sectionID = -1; |
| | 2685 | |
| | 2686 | AddNetMsg_LocalObjectDamaged(sbPtr, damage, multiple,sectionID,delta_seq,delta_sub_seq,incoming); |
| | 2687 | } |
| | 2688 | } |
| | 2689 | |
| | 2690 | /* Patrick 5/8/97 -------------------------------------------------- |
| | 2691 | Handles the player's weapon sound effects... this should be called |
| | 2692 | after update ghost/create ghost has been called for player ghost |
| | 2693 | in processnetmsg_playerstate(). |
| | 2694 | ---------------------------------------------------------------------*/ |
| | 2695 | void HandlePlayerGhostWeaponSound(STRATEGYBLOCK *sbPtr, int weapon, int firingPrimary, int firingSecondary) |
| | 2696 | { |
| | 2697 | assert(sbPtr); |
| | 2698 | assert(sbPtr->DynPtr); |
| | 2699 | assert(weapon>=0); |
| | 2700 | |
| | 2701 | NETGHOSTDATABLOCK *ghostData = (NETGHOSTDATABLOCK *)sbPtr->dataptr; |
| | 2702 | assert(ghostData); |
| | 2703 | |
| | 2704 | switch((enum WEAPON_ID)weapon) |
| | 2705 | { |
| | 2706 | case NULL_WEAPON: |
| | 2707 | /* stop sound if we've got it */ |
| | 2708 | if(ghostData->SoundHandle != SOUND_NOACTIVEINDEX) |
| | 2709 | Sound_Stop(ghostData->SoundHandle); |
| | 2710 | break; |
| | 2711 | case WEAPON_CUDGEL: |
| | 2712 | //no sound for the moment. |
| | 2713 | if(ghostData->SoundHandle != SOUND_NOACTIVEINDEX) |
| | 2714 | Sound_Stop(ghostData->SoundHandle); |
| | 2715 | break; |
| | 2716 | case WEAPON_PULSERIFLE: |
| | 2717 | assert(ghostData->type == I_BehaviourMarinePlayer); |
| | 2718 | |
| | 2719 | if(firingPrimary) |
| | 2720 | { |
| | 2721 | if(ghostData->SoundHandle == SOUND_NOACTIVEINDEX) |
| | 2722 | Sound_Play(SID_PULSE_LOOP, "elhd", &ghostData->SoundHandle, &sbPtr->DynPtr->Position); |
| | 2723 | else |
| | 2724 | Sound_Update3d(ghostData->SoundHandle, &(sbPtr->DynPtr->Position)); |
| | 2725 | } |
| | 2726 | else |
| | 2727 | { |
| | 2728 | if(ghostData->SoundHandle != SOUND_NOACTIVEINDEX) |
| | 2729 | { |
| | 2730 | Sound_Stop(ghostData->SoundHandle); |
| | 2731 | Sound_Play(SID_PULSE_END, "hd", &sbPtr->DynPtr->Position); |
| | 2732 | } |
| | 2733 | |
| | 2734 | if(firingSecondary) |
| | 2735 | Sound_Play(SID_PULSEGRENADELAUNCH, "hd", &sbPtr->DynPtr->Position); |
| | 2736 | } |
| | 2737 | break; |
| | 2738 | case WEAPON_TWO_PISTOLS: |
| | 2739 | case WEAPON_MARINE_PISTOL: |
| | 2740 | assert(ghostData->type == I_BehaviourMarinePlayer); |
| | 2741 | /* stop sound if we've got it */ |
| | 2742 | |
| | 2743 | if(ghostData->SoundHandle != SOUND_NOACTIVEINDEX) |
| | 2744 | Sound_Stop(ghostData->SoundHandle); |
| | 2745 | |
| | 2746 | if (firingPrimary || firingSecondary) |
| | 2747 | Sound_Play(SID_SHOTGUN, "hd", &sbPtr->DynPtr->Position); |
| | 2748 | break; |
| | 2749 | case WEAPON_SMARTGUN: |
| | 2750 | assert(ghostData->type == I_BehaviourMarinePlayer); |
| | 2751 | if(firingPrimary) |
| | 2752 | { |
| | 2753 | if(ghostData->SoundHandle == SOUND_NOACTIVEINDEX) |
| | 2754 | { |
| | 2755 | switch (FastRandom() % 3) |
| | 2756 | { |
| | 2757 | case 0: |
| | 2758 | Sound_Play(SID_SMART1, "ehpd", &ghostData->SoundHandle, ((FastRandom()&255)-128),
&sbPtr->DynPtr->Position); |
| | 2759 | break; |
| | 2760 | case 1: |
| | 2761 | Sound_Play(SID_SMART2, "ehpd", &ghostData->SoundHandle, ((FastRandom()&255)-128),
&sbPtr->DynPtr->Position); |
| | 2762 | break; |
| | 2763 | case 2: |
| | 2764 | Sound_Play(SID_SMART3, "ehpd", &ghostData->SoundHandle, ((FastRandom()&255)-128),
&sbPtr->DynPtr->Position); |
| | 2765 | default: |
| | 2766 | break; |
| | 2767 | } |
| | 2768 | } |
| | 2769 | else |
| | 2770 | { |
| | 2771 | Sound_Update3d(ghostData->SoundHandle, &(sbPtr->DynPtr->Position)); |
| | 2772 | } |
| | 2773 | } |
| | 2774 | else |
| | 2775 | { |
| | 2776 | if(ghostData->SoundHandle != SOUND_NOACTIVEINDEX) |
| | 2777 | Sound_Stop(ghostData->SoundHandle); |
| | 2778 | } |
| | 2779 | break; |
| | 2780 | case WEAPON_FLAMETHROWER: |
| | 2781 | assert(ghostData->type == I_BehaviourMarinePlayer); |
| | 2782 | |
| | 2783 | if(firingPrimary) |
| | 2784 | { |
| | 2785 | if(ghostData->SoundHandle == SOUND_NOACTIVEINDEX) |
| | 2786 | Sound_Play(SID_INCIN_LOOP, "elhd", &ghostData->SoundHandle, &sbPtr->DynPtr->Position); |
| | 2787 | else |
| | 2788 | Sound_Update3d(ghostData->SoundHandle, &(sbPtr->DynPtr->Position)); |
| | 2789 | |
| | 2790 | if (sbPtr->DisplayBlock) |
| | 2791 | { |
| | 2792 | ProveHModel(&ghostData->HModelController,sbPtr->DisplayBlock); |
| | 2793 | FireNetGhostFlameThrower |
| | 2794 | ( |
| | 2795 | &ghostData->GunflashSectionPtr->World_Offset, |
| | 2796 | &ghostData->GunflashSectionPtr->SecMat |
| | 2797 | ); |
| | 2798 | |
| | 2799 | /* Lighting? */ |
| | 2800 | if (sbPtr->DisplayBlock) |
| | 2801 | AddLightingEffectToObject(sbPtr->DisplayBlock,LFX_MUZZLEFLASH); |
| | 2802 | } |
| | 2803 | } |
| | 2804 | else |
| | 2805 | { |
| | 2806 | if(ghostData->SoundHandle != SOUND_NOACTIVEINDEX) |
| | 2807 | Sound_Stop(ghostData->SoundHandle); |
| | 2808 | } |
| | 2809 | break; |
| | 2810 | case WEAPON_SADAR: |
| | 2811 | assert(ghostData->type == I_BehaviourMarinePlayer); |
| | 2812 | /* stop sound if we've got it */ |
| | 2813 | if(ghostData->SoundHandle != SOUND_NOACTIVEINDEX) |
| | 2814 | Sound_Stop(ghostData->SoundHandle); |
| | 2815 | |
| | 2816 | if(firingPrimary) |
| | 2817 | Sound_Play(SID_SADAR_FIRE, "hd", &sbPtr->DynPtr->Position); |
| | 2818 | break; |
| | 2819 | case WEAPON_GRENADELAUNCHER: |
| | 2820 | assert(ghostData->type == I_BehaviourMarinePlayer); |
| | 2821 | /* stop sound if we've got it */ |
| | 2822 | if(ghostData->SoundHandle != SOUND_NOACTIVEINDEX) |
| | 2823 | Sound_Stop(ghostData->SoundHandle); |
| | 2824 | |
| | 2825 | if(firingPrimary) |
| | 2826 | Sound_Play(SID_GRENADE_LAUNCH, "hd", &sbPtr->DynPtr->Position); |
| | 2827 | break; |
| | 2828 | case WEAPON_MINIGUN: |
| | 2829 | assert(ghostData->type == I_BehaviourMarinePlayer); |
| | 2830 | if(firingPrimary) |
| | 2831 | { |
| | 2832 | if(ghostData->SoundHandle == SOUND_NOACTIVEINDEX) |
| | 2833 | Sound_Play(SID_MINIGUN_LOOP, "elhd", &ghostData->SoundHandle, &sbPtr->DynPtr->Position); |
| | 2834 | else |
| | 2835 | Sound_Update3d(ghostData->SoundHandle, &(sbPtr->DynPtr->Position)); |
| | 2836 | } |
| | 2837 | else |
| | 2838 | { |
| | 2839 | if(ghostData->SoundHandle != SOUND_NOACTIVEINDEX) |
| | 2840 | { |
| | 2841 | Sound_Stop(ghostData->SoundHandle); |
| | 2842 | Sound_Play(SID_MINIGUN_END, "hd", &sbPtr->DynPtr->Position); |
| | 2843 | } |
| | 2844 | } |
| | 2845 | break; |
| | 2846 | case WEAPON_FRISBEE_LAUNCHER: |
| | 2847 | { |
| | 2848 | assert(ghostData->type == I_BehaviourMarinePlayer); |
| | 2849 | /* stop sound if we've got it */ |
| | 2850 | if (firingPrimary) |
| | 2851 | { |
| | 2852 | // if (ghostData->SoundHandle != SOUND_NOACTIVEINDEX) |
| | 2853 | // { |
| | 2854 | //if (ActiveSounds[ghostData->SoundHandle].soundIndex != SID_ED_SKEETERCHARGE) |
| | 2855 | // Sound_Stop(ghostData->SoundHandle); |
| | 2856 | // } |
| | 2857 | if (ghostData->SoundHandle == SOUND_NOACTIVEINDEX) |
| | 2858 | { |
| | 2859 | if (!ghostData->soundStartFlag) |
| | 2860 | { |
| | 2861 | //Sound_Play(SID_ED_SKEETERCHARGE, "ehd", &ghostData->SoundHandle, &sbPtr->DynPtr->Position); |
| | 2862 | ghostData->soundStartFlag = 1; |
| | 2863 | } |
| | 2864 | } |
| | 2865 | } |
| | 2866 | else |
| | 2867 | { |
| | 2868 | ghostData->soundStartFlag = 0; |
| | 2869 | if (ghostData->SoundHandle != SOUND_NOACTIVEINDEX) |
| | 2870 | Sound_Stop(ghostData->SoundHandle); |
| | 2871 | } |
| | 2872 | break; |
| | 2873 | } |
| | 2874 | case WEAPON_PRED_WRISTBLADE: |
| | 2875 | assert(ghostData->type == I_BehaviourPredatorPlayer); |
| | 2876 | /* stop sound if we've got it */ |
| | 2877 | //use the sounds connected to the hierarchy |
| | 2878 | break; |
| | 2879 | case WEAPON_PRED_PISTOL: |
| | 2880 | assert(ghostData->type == I_BehaviourPredatorPlayer); |
| | 2881 | if(firingPrimary) |
| | 2882 | { |
| | 2883 | if(ghostData->SoundHandle == SOUND_NOACTIVEINDEX) |
| | 2884 | Sound_Play(SID_PRED_PISTOL, "hd", &sbPtr->DynPtr->Position); |
| | 2885 | } |
| | 2886 | //else |
| | 2887 | //{ |
| | 2888 | //if(ghostData->SoundHandle != SOUND_NOACTIVEINDEX) |
| | 2889 | //{ |
| | 2890 | // Sound_Stop(ghostData->SoundHandle); |
| | 2891 | // Sound_Play(SID_PULSE_END, "hd", &sbPtr->DynPtr->Position); |
| | 2892 | //} |
| | 2893 | //} |
| | 2894 | break; |
| | 2895 | case WEAPON_PRED_RIFLE: |
| | 2896 | assert(ghostData->type == I_BehaviourPredatorPlayer); |
| | 2897 | /* stop sound if we've got it */ |
| | 2898 | |
| | 2899 | if(ghostData->SoundHandle != SOUND_NOACTIVEINDEX) |
| | 2900 | Sound_Stop(ghostData->SoundHandle); |
| | 2901 | |
| | 2902 | if(firingPrimary) |
| | 2903 | Sound_Play(SID_PRED_LASER, "hd", &sbPtr->DynPtr->Position); |
| | 2904 | break; |
| | 2905 | case WEAPON_PRED_SHOULDERCANNON: |
| | 2906 | assert(ghostData->type == I_BehaviourPredatorPlayer); |
| | 2907 | /* stop sound if we've got it */ |
| | 2908 | if(ghostData->SoundHandle != SOUND_NOACTIVEINDEX) |
| | 2909 | Sound_Stop(ghostData->SoundHandle); |
| | 2910 | |
| | 2911 | //sound is caused by energy bolt creation |
| | 2912 | break; |
| | 2913 | case WEAPON_PRED_DISC: |
| | 2914 | assert(ghostData->type == I_BehaviourPredatorPlayer); |
| | 2915 | /* stop sound if we've got it */ |
| | 2916 | if(ghostData->SoundHandle != SOUND_NOACTIVEINDEX) |
| | 2917 | Sound_Stop(ghostData->SoundHandle); |
| | 2918 | /* currently no sound for this */ |
| | 2919 | break; |
| | 2920 | case WEAPON_ALIEN_CLAW: |
| | 2921 | //appropriate sounds should be triggered by the animation |
| | 2922 | break; |
| | 2923 | case(WEAPON_PRED_MEDICOMP): |
| | 2924 | if(ghostData->SoundHandle != SOUND_NOACTIVEINDEX) |
| | 2925 | Sound_Stop(ghostData->SoundHandle); |
| | 2926 | break; |
| | 2927 | default: |
| | 2928 | assert(1==0); |
| | 2929 | /* stop sound if we've got it */ |
| | 2930 | if(ghostData->SoundHandle != SOUND_NOACTIVEINDEX) |
| | 2931 | Sound_Stop(ghostData->SoundHandle); |
| | 2932 | break; |
| | 2933 | } |
| | 2934 | } |
| | 2935 | |
| | 2936 | int ExtractTimerFromElevation(int elevation) |
| | 2937 | { |
| | 2938 | int fake_timer,angle1; |
| | 2939 | |
| | 2940 | if (elevation > 1024) |
| | 2941 | elevation -= 4096; |
| | 2942 | |
| | 2943 | angle1 = -elevation; |
| | 2944 | |
| | 2945 | assert(angle1 >= -1024); |
| | 2946 | assert(angle1 <= 1024); |
| | 2947 | |
| | 2948 | fake_timer = 1024 - angle1; |
| | 2949 | fake_timer <<= 5; |
| | 2950 | |
| | 2951 | if (fake_timer > 65536) |
| | 2952 | fake_timer = 65535; |
| | 2953 | |
| | 2954 | assert(fake_timer >= 0); |
| | 2955 | assert(fake_timer < 65536); |
| | 2956 | |
| | 2957 | return fake_timer; |
| | 2958 | } |
| | 2959 | |
| | 2960 | /* KJL 17:11:43 26/01/98 - weapon elevation */ |
| | 2961 | void HandleWeaponElevation(STRATEGYBLOCK *sbPtr, int elevation, int weapon) |
| | 2962 | { |
| | 2963 | DELTA_CONTROLLER *elevation_controller; |
| | 2964 | assert(sbPtr); |
| | 2965 | NETGHOSTDATABLOCK *ghostDataPtr = (NETGHOSTDATABLOCK *)sbPtr->dataptr; |
| | 2966 | assert(ghostDataPtr); |
| | 2967 | assert(elevation >= 0); |
| | 2968 | assert(elevation < 4096); |
| | 2969 | |
| | 2970 | if (ghostDataPtr->type == I_BehaviourMarinePlayer) |
| | 2971 | { |
| | 2972 | if (weapon != ghostDataPtr->CurrentWeapon) |
| | 2973 | { |
| | 2974 | Dispel_HModel(&ghostDataPtr->HModelController); |
| | 2975 | CreateMarineHModel(ghostDataPtr, weapon); |
| | 2976 | ProveHModel_Far(&ghostDataPtr->HModelController,sbPtr); |
| | 2977 | } |
| | 2978 | |
| | 2979 | elevation_controller = Get_Delta_Sequence(&ghostDataPtr->HModelController,"Elevation"); |
| | 2980 | /* Deal with elevation sequence. */ |
| | 2981 | assert(elevation_controller); |
| | 2982 | elevation_controller->Active = 1; |
| | 2983 | |
| | 2984 | switch(ghostDataPtr->currentAnimSequence) |
| | 2985 | { |
| | 2986 | case MSQ_StandDieFront: |
| | 2987 | case MSQ_StandDieBack: |
| | 2988 | case MSQ_StandDeadFront: |
| | 2989 | case MSQ_StandDeadBack: |
| | 2990 | case MSQ_CrouchDie: |
| | 2991 | case MSQ_CrouchDead: |
| | 2992 | case MSQ_Taunt: |
| | 2993 | { |
| | 2994 | /* Force no elevation. */ |
| | 2995 | elevation_controller->Active=0; |
| | 2996 | break; |
| | 2997 | } |
| | 2998 | case MSQ_RunningFire: |
| | 2999 | case MSQ_RunningFire_Backwards: |
| | 3000 | if (ghostDataPtr->CurrentWeapon == WEAPON_GRENADELAUNCHER) |
| | 3001 | { |
| | 3002 | elevation_controller->Active = 0; |
| | 3003 | ghostDataPtr->HModelController.Looped = 0; |
| | 3004 | break; |
| | 3005 | } |
| | 3006 | else if (ghostDataPtr->CurrentWeapon == WEAPON_TWO_PISTOLS) |
| | 3007 | { |
| | 3008 | if (ghostDataPtr->HModelController.Sub_Sequence == MRSS_Fire_From_Hips) |
| | 3009 | { |
| | 3010 | elevation_controller->sequence_type = HMSQT_MarineStand; |
| | 3011 | elevation_controller->sub_sequence = (int)MSSS_Hip_Fire_Elevation; |
| | 3012 | } |
| | 3013 | else |
| | 3014 | { |
| | 3015 | if (HModelSequence_Exists(&ghostDataPtr->HModelController, HMSQT_MarineRun,(int)MRSS_Elevation)) |
| | 3016 | { |
| | 3017 | elevation_controller->sequence_type = HMSQT_MarineRun; |
| | 3018 | elevation_controller->sub_sequence = (int)MRSS_Elevation; |
| | 3019 | } |
| | 3020 | else |
| | 3021 | { |
| | 3022 | elevation_controller->sequence_type = HMSQT_MarineStand; |
| | 3023 | elevation_controller->sub_sequence = (int)MSSS_Elevation; |
| | 3024 | } |
| | 3025 | } |
| | 3026 | elevation_controller->timer = ExtractTimerFromElevation(elevation); |
| | 3027 | } |
| | 3028 | else |
| | 3029 | { |
| | 3030 | if (HModelSequence_Exists(&ghostDataPtr->HModelController, HMSQT_MarineRun,(int)MRSS_Elevation)) |
| | 3031 | { |
| | 3032 | elevation_controller->sequence_type = HMSQT_MarineRun; |
| | 3033 | elevation_controller->sub_sequence = (int)MRSS_Elevation; |
| | 3034 | } |
| | 3035 | else |
| | 3036 | { |
| | 3037 | elevation_controller->sequence_type = HMSQT_MarineStand; |
| | 3038 | elevation_controller->sub_sequence = (int)MSSS_Elevation; |
| | 3039 | } |
| | 3040 | elevation_controller->timer = ExtractTimerFromElevation(elevation); |
| | 3041 | break; |
| | 3042 | } |
| | 3043 | case MSQ_StandingFire: |
| | 3044 | if (ghostDataPtr->CurrentWeapon == WEAPON_GRENADELAUNCHER) |
| | 3045 | { |
| | 3046 | elevation_controller->Active = 0; |
| | 3047 | ghostDataPtr->HModelController.Looped = 0; |
| | 3048 | break; |
| | 3049 | } |
| | 3050 | else if (ghostDataPtr->CurrentWeapon == WEAPON_TWO_PISTOLS) |
| | 3051 | { |
| | 3052 | if (ghostDataPtr->HModelController.Sub_Sequence == MSSS_FireFromHips) |
| | 3053 | { |
| | 3054 | elevation_controller->sequence_type= HMSQT_MarineStand; |
| | 3055 | elevation_controller->sub_sequence = (int)MSSS_Hip_Fire_Elevation; |
| | 3056 | } |
| | 3057 | else |
| | 3058 | { |
| | 3059 | elevation_controller->sequence_type = HMSQT_MarineStand; |
| | 3060 | elevation_controller->sub_sequence = (int)MSSS_Elevation; |
| | 3061 | } |
| | 3062 | |
| | 3063 | elevation_controller->timer = ExtractTimerFromElevation(elevation); |
| | 3064 | } |
| | 3065 | else |
| | 3066 | { |
| | 3067 | elevation_controller->sequence_type = HMSQT_MarineStand; |
| | 3068 | elevation_controller->sub_sequence = (int)MSSS_Elevation; |
| | 3069 | elevation_controller->timer = ExtractTimerFromElevation(elevation); |
| | 3070 | break; |
| | 3071 | } |
| | 3072 | case MSQ_Walk: |
| | 3073 | case MSQ_Walk_Backwards: |
| | 3074 | if (ghostDataPtr->CurrentWeapon == WEAPON_TWO_PISTOLS) |
| | 3075 | { |
| | 3076 | if (ghostDataPtr->HModelController.Sub_Sequence == MRSS_Fire_From_Hips) |
| | 3077 | { |
| | 3078 | elevation_controller->sequence_type = HMSQT_MarineStand; |
| | 3079 | elevation_controller->sub_sequence = (int)MSSS_Hip_Fire_Elevation; |
| | 3080 | } |
| | 3081 | else |
| | 3082 | { |
| | 3083 | if (HModelSequence_Exists(&ghostDataPtr->HModelController, HMSQT_MarineRun,(int)MRSS_Elevation)) |
| | 3084 | { |
| | 3085 | elevation_controller->sequence_type = HMSQT_MarineRun; |
| | 3086 | elevation_controller->sub_sequence = (int)MRSS_Elevation; |
| | 3087 | } |
| | 3088 | else |
| | 3089 | { |
| | 3090 | elevation_controller->sequence_type = HMSQT_MarineStand; |
| | 3091 | elevation_controller->sub_sequence = (int)MSSS_Elevation; |
| | 3092 | } |
| | 3093 | } |
| | 3094 | elevation_controller->timer = ExtractTimerFromElevation(elevation); |
| | 3095 | } |
| | 3096 | else |
| | 3097 | { |
| | 3098 | if (HModelSequence_Exists(&ghostDataPtr->HModelController, HMSQT_MarineRun,(int)MRSS_Elevation)) |
| | 3099 | { |
| | 3100 | elevation_controller->sequence_type = HMSQT_MarineRun; |
| | 3101 | elevation_controller->sub_sequence = (int)MRSS_Elevation; |
| | 3102 | } |
| | 3103 | else |
| | 3104 | { |
| | 3105 | elevation_controller->sequence_type = HMSQT_MarineStand; |
| | 3106 | elevation_controller->sub_sequence = (int)MSSS_Elevation; |
| | 3107 | } |
| | 3108 | |
| | 3109 | elevation_controller->timer = ExtractTimerFromElevation(elevation); |
| | 3110 | } |
| | 3111 | break; |
| | 3112 | case MSQ_Crawl: |
| | 3113 | case MSQ_Crawl_Backwards: |
| | 3114 | if (ghostDataPtr->CurrentWeapon == WEAPON_TWO_PISTOLS) |
| | 3115 | { |
| | 3116 | if (ghostDataPtr->HModelController.Sub_Sequence == MCSS_FireFromHips) |
| | 3117 | { |
| | 3118 | elevation_controller->sequence_type = HMSQT_MarineCrouch; |
| | 3119 | elevation_controller->sub_sequence = (int)MCrSS_Hip_Fire_Elevation; |
| | 3120 | } |
| | 3121 | else |
| | 3122 | { |
| | 3123 | if (HModelSequence_Exists(&ghostDataPtr->HModelController, HMSQT_MarineCrawl,(int)MCSS_Elevation)) |
| | 3124 | { |
| | 3125 | elevation_controller->sequence_type = HMSQT_MarineCrawl; |
| | 3126 | elevation_controller->sub_sequence = (int)MCSS_Elevation; |
| | 3127 | } |
| | 3128 | else |
| | 3129 | { |
| | 3130 | elevation_controller->sequence_type = HMSQT_MarineCrouch; |
| | 3131 | elevation_controller->sub_sequence = (int)MCrSS_Elevation; |
| | 3132 | } |
| | 3133 | } |
| | 3134 | } |
| | 3135 | else |
| | 3136 | { |
| | 3137 | if (HModelSequence_Exists(&ghostDataPtr->HModelController, HMSQT_MarineCrawl,(int)MCSS_Elevation)) |
| | 3138 | { |
| | 3139 | elevation_controller->sequence_type = HMSQT_MarineCrawl; |
| | 3140 | elevation_controller->sub_sequence = (int)MCSS_Elevation; |
| | 3141 | } |
| | 3142 | else |
| | 3143 | { |
| | 3144 | elevation_controller->sequence_type = HMSQT_MarineCrouch; |
| | 3145 | elevation_controller->sub_sequence = (int)MCrSS_Elevation; |
| | 3146 | } |
| | 3147 | } |
| | 3148 | elevation_controller->timer = ExtractTimerFromElevation(elevation); |
| | 3149 | break; |
| | 3150 | case MSQ_Crouch: |
| | 3151 | if (ghostDataPtr->CurrentWeapon == WEAPON_TWO_PISTOLS) |
| | 3152 | { |
| | 3153 | if (ghostDataPtr->HModelController.Sub_Sequence == MCrSS_FireFromHips) |
| | 3154 | { |
| | 3155 | elevation_controller->sequence_type = HMSQT_MarineCrouch; |
| | 3156 | elevation_controller->sub_sequence = (int)MCrSS_Hip_Fire_Elevation; |
| | 3157 | } |
| | 3158 | else |
| | 3159 | { |
| | 3160 | elevation_controller->sequence_type = HMSQT_MarineCrouch; |
| | 3161 | elevation_controller->sub_sequence = (int)MCrSS_Elevation; |
| | 3162 | } |
| | 3163 | } |
| | 3164 | else |
| | 3165 | { |
| | 3166 | elevation_controller->sequence_type = HMSQT_MarineCrouch; |
| | 3167 | elevation_controller->sub_sequence = (int)MCrSS_Elevation; |
| | 3168 | } |
| | 3169 | elevation_controller->timer = ExtractTimerFromElevation(elevation); |
| | 3170 | break; |
| | 3171 | case MSQ_Stand: |
| | 3172 | case MSQ_Jump: |
| | 3173 | default: |
| | 3174 | if (ghostDataPtr->CurrentWeapon == WEAPON_TWO_PISTOLS) |
| | 3175 | { |
| | 3176 | if (ghostDataPtr->HModelController.Sub_Sequence == MSSS_FireFromHips) |
| | 3177 | { |
| | 3178 | elevation_controller->sequence_type = HMSQT_MarineStand; |
| | 3179 | elevation_controller->sub_sequence = (int)MSSS_Hip_Fire_Elevation; |
| | 3180 | } |
| | 3181 | else |
| | 3182 | { |
| | 3183 | elevation_controller->sequence_type = HMSQT_MarineStand; |
| | 3184 | elevation_controller->sub_sequence = (int)MSSS_Elevation; |
| | 3185 | } |
| | 3186 | } |
| | 3187 | else |
| | 3188 | { |
| | 3189 | elevation_controller->sequence_type = HMSQT_MarineStand; |
| | 3190 | elevation_controller->sub_sequence = (int)MSSS_Elevation; |
| | 3191 | } |
| | 3192 | elevation_controller->timer = ExtractTimerFromElevation(elevation); |
| | 3193 | } |
| | 3194 | |
| | 3195 | if ((HModelSequence_Exists(&ghostDataPtr->HModelController,elevation_controller->sequence_type,elevation_controller->sub_sequence))
&& elevation_controller->Active) |
| | 3196 | { |
| | 3197 | elevation_controller->Active = 1; |
| | 3198 | // printf("Using elevation delta.\n"); |
| | 3199 | } |
| | 3200 | else |
| | 3201 | { |
| | 3202 | elevation_controller->Active = 0; |
| | 3203 | } |
| | 3204 | } |
| | 3205 | else if (ghostDataPtr->type == I_BehaviourPredatorPlayer) |
| | 3206 | { |
| | 3207 | if (weapon != ghostDataPtr->CurrentWeapon) |
| | 3208 | { |
| | 3209 | Dispel_HModel(&ghostDataPtr->HModelController); |
| | 3210 | CreatePredatorHModel(ghostDataPtr, weapon); |
| | 3211 | ProveHModel_Far(&ghostDataPtr->HModelController,sbPtr); |
| | 3212 | } |
| | 3213 | elevation_controller = Get_Delta_Sequence(&ghostDataPtr->HModelController,"Elevation"); |
| | 3214 | /* Deal with elevation sequence. */ |
| | 3215 | assert(elevation_controller); |
| | 3216 | elevation_controller->Active = 1; /* enabled? */ |
| | 3217 | |
| | 3218 | switch(ghostDataPtr->currentAnimSequence) |
| | 3219 | { |
| | 3220 | case PredSQ_Taunt: |
| | 3221 | case PredSQ_StandDie: |
| | 3222 | case PredSQ_StandDead: |
| | 3223 | case PredSQ_CrouchDie: |
| | 3224 | case PredSQ_CrouchDead: |
| | 3225 | elevation_controller->Active = 0; |
| | 3226 | /* Force no elevation. */ |
| | 3227 | break; |
| | 3228 | case PredSQ_Run: |
| | 3229 | case PredSQ_Run_Backwards: |
| | 3230 | case PredSQ_RunningSwipe: |
| | 3231 | case PredSQ_RunningSwipe_Backwards: |
| | 3232 | elevation_controller->sequence_type = HMSQT_PredatorStand; |
| | 3233 | elevation_controller->sub_sequence = (int)PSSS_Elevation; |
| | 3234 | elevation_controller->timer = ExtractTimerFromElevation(elevation); |
| | 3235 | break; |
| | 3236 | case PredSQ_Crouch: |
| | 3237 | case PredSQ_CrouchedSwipe: |
| | 3238 | elevation_controller->sequence_type = HMSQT_PredatorCrouch; |
| | 3239 | elevation_controller->sub_sequence = (int)PCrSS_Elevation; |
| | 3240 | elevation_controller->timer = ExtractTimerFromElevation(elevation); |
| | 3241 | break; |
| | 3242 | case PredSQ_Crawl: |
| | 3243 | case PredSQ_CrawlingSwipe: |
| | 3244 | case PredSQ_Crawl_Backwards: |
| | 3245 | case PredSQ_CrawlingSwipe_Backwards: |
| | 3246 | elevation_controller->sequence_type = HMSQT_PredatorCrouch; |
| | 3247 | elevation_controller->sub_sequence = (int)PCrSS_Elevation; |
| | 3248 | elevation_controller->timer = ExtractTimerFromElevation(elevation); |
| | 3249 | break; |
| | 3250 | case PredSQ_Jump: |
| | 3251 | case PredSQ_Stand: |
| | 3252 | case PredSQ_StandingSwipe: |
| | 3253 | default: |
| | 3254 | elevation_controller->sequence_type = HMSQT_PredatorStand; |
| | 3255 | elevation_controller->sub_sequence = (int)PSSS_Elevation; |
| | 3256 | elevation_controller->timer = ExtractTimerFromElevation(elevation); |
| | 3257 | } |
| | 3258 | |
| | 3259 | if ((HModelSequence_Exists(&ghostDataPtr->HModelController,elevation_controller->sequence_type,elevation_controller->sub_sequence)) |
| | 3260 | && (elevation_controller->Active)) |
| | 3261 | { |
| | 3262 | elevation_controller->Active = 1; |
| | 3263 | } |
| | 3264 | else |
| | 3265 | { |
| | 3266 | elevation_controller->Active = 0; |
| | 3267 | } |
| | 3268 | } |
| | 3269 | else if (ghostDataPtr->type == I_BehaviourAlienPlayer) |
| | 3270 | { |
| | 3271 | if (ghostDataPtr->CurrentWeapon == -1) |
| | 3272 | { |
| | 3273 | //this only happens for aliens , if a player changes character |
| | 3274 | Dispel_HModel(&ghostDataPtr->HModelController); |
| | 3275 | CreateAlienHModel(ghostDataPtr,0); |
| | 3276 | ProveHModel_Far(&ghostDataPtr->HModelController,sbPtr); |
| | 3277 | } |
| | 3278 | |
| | 3279 | elevation_controller = Get_Delta_Sequence(&ghostDataPtr->HModelController,"Elevation"); |
| | 3280 | /* Deal with elevation sequence. */ |
| | 3281 | assert(elevation_controller); |
| | 3282 | elevation_controller->Active = 1; /* enabled? */ |
| | 3283 | |
| | 3284 | switch(ghostDataPtr->currentAnimSequence) |
| | 3285 | { |
| | 3286 | case ASQ_Pain: |
| | 3287 | case ASQ_Jump: |
| | 3288 | case ASQ_Eat: |
| | 3289 | case ASQ_Pounce: |
| | 3290 | case ASQ_JumpingTailPoise: |
| | 3291 | case ASQ_JumpingTailStrike: |
| | 3292 | case ASQ_Taunt: |
| | 3293 | elevation_controller->Active = 0; |
| | 3294 | /* Force no elevation. */ |
| | 3295 | break; |
| | 3296 | case ASQ_Crouch: |
| | 3297 | case ASQ_CrouchedAttack_Claw: |
| | 3298 | case ASQ_CrouchedTailPoise: |
| | 3299 | case ASQ_CrouchedTailStrike: |
| | 3300 | case ASQ_Crawl: |
| | 3301 | case ASQ_CrawlingAttack_Claw: |
| | 3302 | case ASQ_CrawlingTailPoise: |
| | 3303 | case ASQ_CrawlingTailStrike: |
| | 3304 | case ASQ_Crawl_Backwards: |
| | 3305 | case ASQ_CrawlingTailPoise_Backwards: |
| | 3306 | case ASQ_CrawlingTailStrike_Backwards: |
| | 3307 | case ASQ_CrawlingAttack_Claw_Backwards: |
| | 3308 | case ASQ_Scamper: |
| | 3309 | case ASQ_Scamper_Backwards: |
| | 3310 | case ASQ_CrouchEat : |
| | 3311 | elevation_controller->sequence_type = HMSQT_AlienCrouch; |
| | 3312 | elevation_controller->sub_sequence = (int)ACrSS_Standard_Elevation; |
| | 3313 | elevation_controller->timer = ExtractTimerFromElevation(elevation); |
| | 3314 | break; |
| | 3315 | case ASQ_Run: |
| | 3316 | case ASQ_RunningAttack_Claw: |
| | 3317 | case ASQ_RunningTailPoise: |
| | 3318 | case ASQ_RunningTailStrike: |
| | 3319 | case ASQ_Run_Backwards: |
| | 3320 | case ASQ_RunningAttack_Claw_Backwards: |
| | 3321 | case ASQ_RunningTailPoise_Backwards: |
| | 3322 | case ASQ_RunningTailStrike_Backwards: |
| | 3323 | case ASQ_Stand: |
| | 3324 | case ASQ_StandingAttack_Claw: |
| | 3325 | case ASQ_StandingTailPoise: |
| | 3326 | case ASQ_StandingTailStrike: |
| | 3327 | elevation_controller->sequence_type = HMSQT_AlienStand; |
| | 3328 | elevation_controller->sub_sequence = (int)ASSS_Standard_Elevation; |
| | 3329 | elevation_controller->timer = ExtractTimerFromElevation(elevation); |
| | 3330 | break; |
| | 3331 | default: |
| | 3332 | elevation_controller->sequence_type = HMSQT_AlienStand; |
| | 3333 | elevation_controller->sub_sequence = (int)ASSS_Standard_Elevation; |
| | 3334 | elevation_controller->timer = ExtractTimerFromElevation(elevation); |
| | 3335 | } |
| | 3336 | |
| | 3337 | if ((HModelSequence_Exists(&ghostDataPtr->HModelController,elevation_controller->sequence_type,elevation_controller->sub_sequence)) |
| | 3338 | && (elevation_controller->Active)) |
| | 3339 | { |
| | 3340 | elevation_controller->Active=1; |
| | 3341 | } |
| | 3342 | else |
| | 3343 | { |
| | 3344 | elevation_controller->Active=0; |
| | 3345 | } |
| | 3346 | } |
| | 3347 | } |
| | 3348 | |
| | 3349 | /* Patrick 15/7/97 -------------------------------------------------- |
| | 3350 | Manages the ghost's integrities |
| | 3351 | ---------------------------------------------------------------------*/ |
| | 3352 | void MaintainGhosts() |
| | 3353 | { |
| | 3354 | int sbIndex = 0; |
| | 3355 | |
| | 3356 | /* only do this when we're playing */ |
| | 3357 | if(netGameData.myGameState!=NGS_Playing) return; |
| | 3358 | |
| | 3359 | while(sbIndex < NumActiveStBlocks) |
| | 3360 | { |
| | 3361 | STRATEGYBLOCK *sbPtr = ActiveStBlockList[sbIndex++]; |
| | 3362 | |
| | 3363 | if(sbPtr->type == I_BehaviourNetGhost) |
| | 3364 | { |
| | 3365 | NETGHOSTDATABLOCK *ghostData = (NETGHOSTDATABLOCK *)sbPtr->dataptr; |
| | 3366 | assert(ghostData); |
| | 3367 | ghostData->integrity -= NormalFrameTime; |
| | 3368 | |
| | 3369 | if(ghostData->integrity < 0) |
| | 3370 | { |
| | 3371 | RemoveGhost(sbPtr); |
| | 3372 | } |
| | 3373 | |
| | 3374 | else |
| | 3375 | switch (ghostData->type) |
| | 3376 | { |
| | 3377 | case I_BehaviourFlare: |
| | 3378 | { |
| | 3379 | if (ghostData->timer > ONE_FIXED*4) |
| | 3380 | ghostData->currentAnimSequence += NormalFrameTime; |
| | 3381 | else |
| | 3382 | ghostData->currentAnimSequence += MUL_FIXED(NormalFrameTime,ghostData->timer)/4; |
| | 3383 | |
| | 3384 | while (ghostData->currentAnimSequence >= FLARE_PARTICLE_GENERATION_TIME) |
| | 3385 | { |
| | 3386 | ghostData->currentAnimSequence -= FLARE_PARTICLE_GENERATION_TIME; |
| | 3387 | MakeFlareParticle(sbPtr->DynPtr); |
| | 3388 | } |
| | 3389 | |
| | 3390 | /* add lighting effect if near */ |
| | 3391 | if (sbPtr->DisplayBlock) |
| | 3392 | { |
| | 3393 | LIGHTBLOCK *lightPtr = sbPtr->DisplayBlock->ObLights[0]; |
| | 3394 | assert(sbPtr->DisplayBlock->ObNumLights==1); |
| | 3395 | assert(lightPtr); |
| | 3396 | lightPtr->LightBright = 1 + MUL_FIXED((ONE_FIXED*4-(FastRandom()&32767)), ghostData->timer/FLARE_LIFETIME); |
| | 3397 | } |
| | 3398 | ghostData->timer -= NormalFrameTime; |
| | 3399 | |
| | 3400 | //Stop flare from disappearing from lack of update messages. |
| | 3401 | //This is so the number of meessages sent can be reduced when the flare has stopped moving. |
| | 3402 | ghostData->integrity = ghostData->timer; |
| | 3403 | |
| | 3404 | } |
| | 3405 | break; |
| | 3406 | case I_BehaviourProximityGrenade: |
| | 3407 | { |
| | 3408 | DYNAMICSBLOCK *dynPtr = sbPtr->DynPtr; |
| | 3409 | assert(dynPtr); |
| | 3410 | if (ghostData->timer <= PROX_GRENADE_LIFETIME*ONE_FIXED) |
| | 3411 | { |
| | 3412 | { |
| | 3413 | int scale = ONE_FIXED-ghostData->timer/PROX_GRENADE_LIFETIME; |
| | 3414 | scale = MUL_FIXED(scale,scale); |
| | 3415 | scale = MUL_FIXED(scale,scale)*8; |
| | 3416 | |
| | 3417 | ghostData->currentAnimSequence += NormalFrameTime + MUL_FIXED(NormalFrameTime,scale); |
| | 3418 | } |
| | 3419 | |
| | 3420 | while (ghostData->currentAnimSequence >= PROX_GRENADE_SOUND_GENERATION_TIME) |
| | 3421 | { |
| | 3422 | ghostData->currentAnimSequence -= PROX_GRENADE_SOUND_GENERATION_TIME; |
| | 3423 | Sound_Play(SID_PROX_GRENADE_ACTIVE, "d", &dynPtr->Position); |
| | 3424 | } |
| | 3425 | |
| | 3426 | ghostData->timer -= NormalFrameTime; |
| | 3427 | |
| | 3428 | if (ghostData->timer <= PROX_GRENADE_TRIGGER_TIME && ghostData->SoundHandle == SOUND_NOACTIVEINDEX) |
| | 3429 | Sound_Play(SID_PROX_GRENADE_READYTOBLOW, "de", &dynPtr->Position, &ghostData->SoundHandle); |
| | 3430 | |
| | 3431 | //Stop flare from disappearing from lack of update messages. |
| | 3432 | //This is so the number of meessages sent can be reduced when the flare has stopped moving. |
| | 3433 | } |
| | 3434 | else |
| | 3435 | { |
| | 3436 | if(!DynamicObjectIsMoving(dynPtr)) |
| | 3437 | ghostData->timer = PROX_GRENADE_LIFETIME * ONE_FIXED; |
| | 3438 | } |
| | 3439 | |
| | 3440 | if(ValidTargetForProxMine(sbPtr)) |
| | 3441 | { |
| | 3442 | if(ghostData->SoundHandle != SOUND_NOACTIVEINDEX) |
| | 3443 | { |
| | 3444 | if (ActiveSounds[ghostData->SoundHandle].soundIndex != SID_PROX_GRENADE_READYTOBLOW) |
| | 3445 | Sound_Stop(ghostData->SoundHandle); |
| | 3446 | |
| | 3447 | Sound_Play(SID_PROX_GRENADE_READYTOBLOW, "de", &dynPtr->Position, &ghostData->SoundHandle); |
| | 3448 | } |
| | 3449 | } |
| | 3450 | |
| | 3451 | ghostData->integrity = ghostData->timer; |
| | 3452 | break; |
| | 3453 | } |
| | 3454 | default: |
| | 3455 | break; |
| | 3456 | } |
| | 3457 | } |
| | 3458 | } |
| | 3459 | } |
| | 3460 | |
| | 3461 | #define AGUNGHOST_FIRINGPOINT_INFRONT 500 |
| | 3462 | #define AGUNGHOST_FIRINGPOINT_ACROSS 0 |
| | 3463 | #define AGUNGHOST_FIRINGPOINT_UP 200 |
| | 3464 | |
| | 3465 | static void CalculatePosnForGhostAutoGunMuzzleFlash(STRATEGYBLOCK *sbPtr,VECTORCH *position, EULER *orientation) |
| | 3466 | { |
| | 3467 | VECTORCH upNormal = {0,-65536,0}; |
| | 3468 | VECTORCH inFrontVec = {0,0,0}; |
| | 3469 | VECTORCH toSideVec = {0,0,0}; |
| | 3470 | EULER firingOrient = {0,0,0}; |
| | 3471 | |
| | 3472 | /* orientation is easy */ |
| | 3473 | firingOrient.EulerY = sbPtr->DynPtr->OrientEuler.EulerY; |
| | 3474 | *orientation = firingOrient; |
| | 3475 | |
| | 3476 | /* vector in front */ |
| | 3477 | inFrontVec.vx = sine[firingOrient.EulerY]; |
| | 3478 | inFrontVec.vz = cosine[firingOrient.EulerY]; |
| | 3479 | Normalise(&inFrontVec); |
| | 3480 | |
| | 3481 | /* vectors in front, to side, and up */ |
| | 3482 | CrossProduct(&inFrontVec,&upNormal,&toSideVec); |
| | 3483 | assert(toSideVec.vy == 0); |
| | 3484 | inFrontVec.vx = MUL_FIXED(inFrontVec.vx,AGUNGHOST_FIRINGPOINT_INFRONT); |
| | 3485 | inFrontVec.vz = MUL_FIXED(inFrontVec.vz,AGUNGHOST_FIRINGPOINT_INFRONT); |
| | 3486 | toSideVec.vx = MUL_FIXED(toSideVec.vx,AGUNGHOST_FIRINGPOINT_ACROSS); |
| | 3487 | toSideVec.vz = MUL_FIXED(toSideVec.vz,AGUNGHOST_FIRINGPOINT_ACROSS); |
| | 3488 | |
| | 3489 | position->vx = sbPtr->DynPtr->Position.vx + inFrontVec.vx + toSideVec.vx; |
| | 3490 | position->vy = sbPtr->DynPtr->Position.vy - AGUNGHOST_FIRINGPOINT_UP; |
| | 3491 | position->vz = sbPtr->DynPtr->Position.vz + inFrontVec.vz + toSideVec.vz; |
| | 3492 | } |
| | 3493 | |
| | 3494 | void HandleGhostAutoGunMuzzleFlash(STRATEGYBLOCK *sbPtr, int firing) |
| | 3495 | { |
| | 3496 | assert(sbPtr); |
| | 3497 | NETGHOSTDATABLOCK *ghostData = (NETGHOSTDATABLOCK *)sbPtr->dataptr; |
| | 3498 | assert(ghostData); |
| | 3499 | assert(ghostData->type == I_BehaviourAutoGun); |
| | 3500 | |
| | 3501 | if(ghostData->myGunFlash) |
| | 3502 | { |
| | 3503 | /* I've already got a gun flash... */ |
| | 3504 | if(firing) |
| | 3505 | { |
| | 3506 | /* Maintain existing gun flash */ |
| | 3507 | VECTORCH position; |
| | 3508 | EULER orientation; |
| | 3509 | MATRIXCH mat; |
| | 3510 | CalculatePosnForGhostAutoGunMuzzleFlash(sbPtr, &position, &orientation); |
| | 3511 | |
| | 3512 | CreateEulerMatrix(&orientation, &mat); |
| | 3513 | TransposeMatrixCH(&mat); |
| | 3514 | |
| | 3515 | ghostData->myGunFlash->ObWorld = position; |
| | 3516 | ghostData->myGunFlash->ObMat = mat; |
| | 3517 | AddLightingEffectToObject(ghostData->myGunFlash, LFX_MUZZLEFLASH); |
| | 3518 | } |
| | 3519 | else |
| | 3520 | { |
| | 3521 | DestroyActiveObject(&ghostData->myGunFlash); |
| | 3522 | } |
| | 3523 | } |
| | 3524 | else if(firing) |
| | 3525 | { |
| | 3526 | /* Need a new gun flash */ |
| | 3527 | VECTORCH position; |
| | 3528 | EULER orientation; |
| | 3529 | MATRIXCH mat; |
| | 3530 | CalculatePosnForGhostAutoGunMuzzleFlash(sbPtr, &position, &orientation); |
| | 3531 | CreateEulerMatrix(&orientation, &mat); |
| | 3532 | TransposeMatrixCH(&mat); |
| | 3533 | ghostData->myGunFlash = AddNPCGunFlashEffect(&position, &mat, SFX_MUZZLE_FLASH_AMORPHOUS); |
| | 3534 | } |
| | 3535 | } |
| | 3536 | |
| | 3537 | void HandleGhostAutoGunSound(STRATEGYBLOCK *sbPtr, int firing) |
| | 3538 | { |
| | 3539 | NETGHOSTDATABLOCK *ghostData = (NETGHOSTDATABLOCK *)sbPtr->dataptr; |
| | 3540 | |
| | 3541 | if(firing) |
| | 3542 | { |
| | 3543 | if(ghostData->SoundHandle == SOUND_NOACTIVEINDEX) |
| | 3544 | Sound_Play(SID_SENTRY_GUN, "eld", &ghostData->SoundHandle, &sbPtr->DynPtr->Position); |
| | 3545 | /* don't need sound update, as autoguns don't move */ |
| | 3546 | } |
| | 3547 | else if(ghostData->SoundHandle != SOUND_NOACTIVEINDEX) |
| | 3548 | { |
| | 3549 | Sound_Stop(ghostData->SoundHandle); |
| | 3550 | Sound_Play(SID_SENTRY_END, "hd", &sbPtr->DynPtr->Position); |
| | 3551 | } |
| | 3552 | } |
| | 3553 | |
| | 3554 | /* patrick 14/10/97 : added to support cloaked predators in net game */ |
| | 3555 | void MaintainGhostCloakingStatus(STRATEGYBLOCK *sbPtr, int IsCloaked) |
| | 3556 | { |
| | 3557 | assert(sbPtr); |
| | 3558 | NETGHOSTDATABLOCK *ghostData = (NETGHOSTDATABLOCK *)sbPtr->dataptr; |
| | 3559 | assert(ghostData); |
| | 3560 | AVP_BEHAVIOUR_TYPE type = ghostData->type; |
| | 3561 | |
| | 3562 | if(type != I_BehaviourPredatorPlayer) |
| | 3563 | { |
| | 3564 | ghostData->CloakingEffectiveness = 0; |
| | 3565 | return; |
| | 3566 | } |
| | 3567 | |
| | 3568 | /* Handle sound playing. */ |
| | 3569 | if (ghostData->CloakingEffectiveness) |
| | 3570 | { |
| | 3571 | if (!IsCloaked) |
| | 3572 | { |
| | 3573 | /* Cloak turns off. */ |
| | 3574 | Sound_Play(SID_PRED_CLOAKOFF, "hd", &sbPtr->DynPtr->Position); |
| | 3575 | } |
| | 3576 | } |
| | 3577 | else |
| | 3578 | { |
| | 3579 | if (IsCloaked) |
| | 3580 | { |
| | 3581 | /* Cloak turns on. */ |
| | 3582 | Sound_Play(SID_PRED_CLOAKON, "hd", &sbPtr->DynPtr->Position); |
| | 3583 | } |
| | 3584 | } |
| | 3585 | |
| | 3586 | ghostData->CloakingEffectiveness = IsCloaked; |
| | 3587 | } |
| | 3588 | |
| | 3589 | /* KJL 14:18:32 27/01/98 - object behaviour for network ghosts */ |
| | 3590 | void NetGhostBehaviour(STRATEGYBLOCK *sbPtr) |
| | 3591 | { |
| | 3592 | assert(sbPtr); |
| | 3593 | |
| | 3594 | NETGHOSTDATABLOCK *ghostDataPtr = (NETGHOSTDATABLOCK *)sbPtr->dataptr; |
| | 3595 | assert(ghostDataPtr); |
| | 3596 | |
| | 3597 | switch(ghostDataPtr->type) |
| | 3598 | { |
| | 3599 | case I_BehaviourCorpse: |
| | 3600 | { |
| | 3601 | /* A copy of the fn. for real ones, minus existance. */ |
| | 3602 | DISPLAYBLOCK *dispPtr = sbPtr->DisplayBlock; |
| | 3603 | |
| | 3604 | /* do we have a displayblock? */ |
| | 3605 | if (dispPtr) |
| | 3606 | { |
| | 3607 | dispPtr->SpecialFXFlags |= SFXFLAG_MELTINGINTOGROUND; |
| | 3608 | dispPtr->ObFlags2 = ghostDataPtr->timer/2; |
| | 3609 | } |
| | 3610 | |
| | 3611 | /* Does the corpse that falls when not visible make no sound? */ |
| | 3612 | ProveHModel_Far(&ghostDataPtr->HModelController,sbPtr); |
| | 3613 | ghostDataPtr->timer -= NormalFrameTime; |
| | 3614 | } |
| | 3615 | default: |
| | 3616 | break; |
| | 3617 | } |
| | 3618 | |
| | 3619 | if (sbPtr->DisplayBlock) |
| | 3620 | { |
| | 3621 | if (sbPtr->DisplayBlock->HModelControlBlock) |
| | 3622 | { |
| | 3623 | /* Fire sound code. */ |
| | 3624 | if(ghostDataPtr->SoundHandle3 != SOUND_NOACTIVEINDEX) |
| | 3625 | Sound_Update3d(ghostDataPtr->SoundHandle3,&(sbPtr->DynPtr->Position)); |
| | 3626 | |
| | 3627 | if(ghostDataPtr->SoundHandle4 != SOUND_NOACTIVEINDEX) |
| | 3628 | Sound_Update3d(ghostDataPtr->SoundHandle4,&(sbPtr->DynPtr->Position)); |
| | 3629 | |
| | 3630 | if (sbPtr->DamageBlock.IsOnFire) |
| | 3631 | { |
| | 3632 | if (!ghostDataPtr->IgnitionHandshaking) |
| | 3633 | AddNetMsg_LocalObjectOnFire(sbPtr); |
| | 3634 | |
| | 3635 | if (ghostDataPtr->SoundHandle3 != SOUND_NOACTIVEINDEX) |
| | 3636 | { |
| | 3637 | if (ActiveSounds[ghostDataPtr->SoundHandle3].soundIndex != SID_FIRE) |
| | 3638 | { |
| | 3639 | Sound_Stop(ghostDataPtr->SoundHandle3); |
| | 3640 | Sound_Play(SID_FIRE, "dle", &sbPtr->DynPtr->Position, &ghostDataPtr->SoundHandle3); |
| | 3641 | } |
| | 3642 | } |
| | 3643 | else |
| | 3644 | { |
| | 3645 | Sound_Play(SID_FIRE, "dle", &sbPtr->DynPtr->Position, &ghostDataPtr->SoundHandle3); |
| | 3646 | } |
| | 3647 | } |
| | 3648 | else |
| | 3649 | { |
| | 3650 | if (ghostDataPtr->SoundHandle3 != SOUND_NOACTIVEINDEX) |
| | 3651 | Sound_Stop(ghostDataPtr->SoundHandle3); |
| | 3652 | } |
| | 3653 | } |
| | 3654 | } |
| | 3655 | |
| | 3656 | if(ghostDataPtr->FlameHitCount) |
| | 3657 | { |
| | 3658 | //send a damage message for all the flame particles that have hit |
| | 3659 | CauseDamageToObject(sbPtr,&TemplateAmmo[AMMO_FLAMETHROWER].MaxDamage, (ONE_FIXED/400)*ghostDataPtr->FlameHitCount,NULL); |
| | 3660 | ghostDataPtr->FlameHitCount = 0; |
| | 3661 | |
| | 3662 | } |
| | 3663 | |
| | 3664 | if(ghostDataPtr->FlechetteHitCount) |
| | 3665 | { |
| | 3666 | //send a damage message for all the flechette particles that have hit |
| | 3667 | CauseDamageToObject(sbPtr, &damage_profiles[FLECHETTEDAMAGE], ONE_FIXED*ghostDataPtr->FlechetteHitCount, NULL); |
| | 3668 | ghostDataPtr->FlechetteHitCount = 0; |
| | 3669 | } |
| | 3670 | } |
| | 3671 | |
| | 3672 | void MaintainGhostFireStatus(STRATEGYBLOCK *sbPtr, int IsOnFire) |
| | 3673 | { |
| | 3674 | assert(sbPtr); |
| | 3675 | NETGHOSTDATABLOCK *ghostData = (NETGHOSTDATABLOCK *)sbPtr->dataptr; |
| | 3676 | assert(ghostData); |
| | 3677 | |
| | 3678 | if (IsOnFire) |
| | 3679 | { |
| | 3680 | if (!ghostData->IgnitionHandshaking) |
| | 3681 | { |
| | 3682 | /* Recieved confirmation. */ |
| | 3683 | ghostData->IgnitionHandshaking = 1; |
| | 3684 | if (!sbPtr->DamageBlock.IsOnFire) |
| | 3685 | { |
| | 3686 | /* Set alight by something else? */ |
| | 3687 | sbPtr->DamageBlock.IsOnFire = 1; |
| | 3688 | } |
| | 3689 | } |
| | 3690 | /* |
| | 3691 | else |
| | 3692 | Corroberated - do nothing. |
| | 3693 | */ |
| | 3694 | } |
| | 3695 | else |
| | 3696 | { |
| | 3697 | if (ghostData->IgnitionHandshaking) |
| | 3698 | { |
| | 3699 | /* Fire gone out? */ |
| | 3700 | ghostData->IgnitionHandshaking = 0; |
| | 3701 | sbPtr->DamageBlock.IsOnFire = 0; |
| | 3702 | } |
| | 3703 | /* |
| | 3704 | else |
| | 3705 | Corroberated - do nothing. |
| | 3706 | */ |
| | 3707 | } |
| | 3708 | } |
| | 3709 | |
| | 3710 | /* Kills a ghost, to leave a corpse */ |
| | 3711 | void KillGhost(STRATEGYBLOCK *sbPtr,int objectId) |
| | 3712 | { |
| | 3713 | assert(sbPtr); |
| | 3714 | NETGHOSTDATABLOCK *ghostData = (NETGHOSTDATABLOCK *)sbPtr->dataptr; |
| | 3715 | assert(ghostData); |
| | 3716 | |
| | 3717 | /* this is where we add fragmentation and explosion effects to destroyed ghosts */ |
| | 3718 | switch(ghostData->type) |
| | 3719 | { |
| | 3720 | case I_BehaviourAlienPlayer: |
| | 3721 | case I_BehaviourMarinePlayer: |
| | 3722 | case I_BehaviourPredatorPlayer: |
| | 3723 | /* Drop through, for the moment. */ |
| | 3724 | #if EXTRAPOLATION_TEST |
| | 3725 | sbPtr->DynPtr->LinImpulse.vx = 0; |
| | 3726 | sbPtr->DynPtr->LinImpulse.vy = 0; |
| | 3727 | sbPtr->DynPtr->LinImpulse.vz = 0; |
| | 3728 | sbPtr->DynPtr->LinVelocity.vx = 0; |
| | 3729 | sbPtr->DynPtr->LinVelocity.vy = 0; |
| | 3730 | sbPtr->DynPtr->LinVelocity.vz = 0; |
| | 3731 | sbPtr->DynPtr->UseStandardGravity = 1; |
| | 3732 | sbPtr->DynPtr->IsNetGhost = 1; |
| | 3733 | sbPtr->DynPtr->ToppleForce = TOPPLE_FORCE_NONE; |
| | 3734 | #endif |
| | 3735 | break; |
| | 3736 | case I_BehaviourGrenade: |
| | 3737 | case I_BehaviourRocket: |
| | 3738 | case I_BehaviourProximityGrenade: |
| | 3739 | case I_BehaviourFragmentationGrenade: |
| | 3740 | case I_BehaviourPulseGrenade: |
| | 3741 | case I_BehaviourPredatorDisc_SeekTrack: |
| | 3742 | case I_BehaviourInanimateObject: |
| | 3743 | default: |
| | 3744 | { |
| | 3745 | /* Default to something else. */ |
| | 3746 | RemoveGhost(sbPtr); |
| | 3747 | return; |
| | 3748 | break; |
| | 3749 | } |
| | 3750 | } |
| | 3751 | |
| | 3752 | /* see if we've got a sound... */ |
| | 3753 | if(ghostData->SoundHandle != SOUND_NOACTIVEINDEX) Sound_Stop(ghostData->SoundHandle); |
| | 3754 | if(ghostData->SoundHandle2 != SOUND_NOACTIVEINDEX) Sound_Stop(ghostData->SoundHandle2); |
| | 3755 | if(ghostData->SoundHandle3 != SOUND_NOACTIVEINDEX) Sound_Stop(ghostData->SoundHandle3); |
| | 3756 | if(ghostData->SoundHandle4 != SOUND_NOACTIVEINDEX) Sound_Stop(ghostData->SoundHandle4); |
| | 3757 | |
| | 3758 | DestroyActiveObject(&ghostData->myGunFlash); |
| | 3759 | |
| | 3760 | /* Now.. you're a ghost. Of a corpse. */ |
| | 3761 | |
| | 3762 | /*--------------------------------------------------------------------** |
| | 3763 | ** The animation sequence we should use will come in a later message ** |
| | 3764 | **--------------------------------------------------------------------*/ |
| | 3765 | |
| | 3766 | ghostData->subtype = ghostData->type; |
| | 3767 | ghostData->type = I_BehaviourCorpse; |
| | 3768 | ghostData->IOType = IOT_Non; |
| | 3769 | ghostData->playerObjectId = objectId; |
| | 3770 | ghostData->timer = CORPSE_EXPIRY_TIME; /* Arbitrarily */ |
| | 3771 | |
| | 3772 | if (ghostData->HModelController.Deltas) |
| | 3773 | RemoveAllDeltas(&ghostData->HModelController); |
| | 3774 | |
| | 3775 | sbPtr->DynPtr->OnlyCollideWithEnvironment = 1; |
| | 3776 | |
| | 3777 | //allow the corpse to fall to the floor |
| | 3778 | sbPtr->DynPtr->GravityOn = 1; |
| | 3779 | } |
| | 3780 | |
| | 3781 | void ApplyGhostCorpseDeathAnim(STRATEGYBLOCK *sbPtr,int deathId) |
| | 3782 | { |
| | 3783 | extern DEATH_DATA Marine_Deaths[]; |
| | 3784 | extern DEATH_DATA Predator_Deaths[]; |
| | 3785 | DEATH_DATA* this_death; |
| | 3786 | |
| | 3787 | assert(sbPtr); |
| | 3788 | NETGHOSTDATABLOCK *ghostData = (NETGHOSTDATABLOCK *)sbPtr->dataptr; |
| | 3789 | assert(ghostData); |
| | 3790 | |
| | 3791 | if(ghostData->type != I_BehaviourCorpse) |
| | 3792 | return; |
| | 3793 | |
| | 3794 | switch(ghostData->subtype) |
| | 3795 | { |
| | 3796 | case I_BehaviourMarinePlayer: |
| | 3797 | { |
| | 3798 | this_death = GetThisDeath_FromCode(&Marine_Deaths[0],deathId); |
| | 3799 | if (this_death->Template) |
| | 3800 | { |
| | 3801 | const SECTION* template_root = GetNamedHierarchyFromLibrary("hnpcmarine","Template"); |
| | 3802 | assert(template_root); |
| | 3803 | /* Convert to template. */ |
| | 3804 | Transmogrify_HModels(sbPtr,&ghostData->HModelController, template_root, 0, 0,0); |
| | 3805 | } |
| | 3806 | else |
| | 3807 | { |
| | 3808 | const SECTION* template_root = GetNamedHierarchyFromLibrary("hnpcmarine","Template"); |
| | 3809 | assert(template_root); |
| | 3810 | /* Convert to template. */ |
| | 3811 | TrimToTemplate(sbPtr, &ghostData->HModelController, template_root, 0); |
| | 3812 | } |
| | 3813 | } |
| | 3814 | break; |
| | 3815 | case I_BehaviourPredatorPlayer: |
| | 3816 | { |
| | 3817 | this_death = GetThisDeath_FromCode(&Predator_Deaths[0],deathId); |
| | 3818 | if (this_death->Template) |
| | 3819 | { |
| | 3820 | const SECTION* template_root = GetNamedHierarchyFromLibrary("hnpcpredator","Template"); |
| | 3821 | assert(template_root); |
| | 3822 | /* Convert to template. */ |
| | 3823 | Transmogrify_HModels(sbPtr,&ghostData->HModelController, template_root, 1, 0,0); |
| | 3824 | } |
| | 3825 | } |
| | 3826 | break; |
| | 3827 | case I_BehaviourAlienPlayer : |
| | 3828 | this_death = GetThisDeath_FromCode(&Alien_Deaths[0],deathId); |
| | 3829 | break; |
| | 3830 | default : |
| | 3831 | return; |
| | 3832 | } |
| | 3833 | |
| | 3834 | if(this_death->TweeningTime <= 0) |
| | 3835 | InitHModelSequence(&ghostData->HModelController,this_death->Sequence_Type,this_death->Sub_Sequence,this_death->Sequence_Length); |
| | 3836 | else |
| | 3837 | InitHModelTweening(&ghostData->HModelController,
this_death->TweeningTime,this_death->Sequence_Type,this_death->Sub_Sequence,this_death->Sequence_Length,0); |
| | 3838 | |
| | 3839 | /* Electric death sound? */ |
| | 3840 | if (this_death->Electrical) |
| | 3841 | Sound_Play(SID_ELEC_DEATH, "de", &sbPtr->DynPtr->Position, &ghostData->SoundHandle4); |
| | 3842 | } |
| | 3843 | |
| | 3844 | void ApplyCorpseDeathAnim(STRATEGYBLOCK *sbPtr,int deathId) |
| | 3845 | { |
| | 3846 | extern DEATH_DATA Marine_Deaths[]; |
| | 3847 | extern DEATH_DATA Predator_Deaths[]; |
| | 3848 | DEATH_DATA* this_death; |
| | 3849 | |
| | 3850 | CORPSEDATABLOCK *corpseDataPtr = (CORPSEDATABLOCK *)sbPtr->dataptr; |
| | 3851 | |
| | 3852 | switch(corpseDataPtr->Type) |
| | 3853 | { |
| | 3854 | case I_BehaviourMarinePlayer: |
| | 3855 | { |
| | 3856 | this_death = GetThisDeath_FromCode(&Marine_Deaths[0],deathId); |
| | 3857 | if (this_death->Template) |
| | 3858 | { |
| | 3859 | const SECTION* template_root = GetNamedHierarchyFromLibrary("hnpcmarine","Template"); |
| | 3860 | assert(template_root); |
| | 3861 | /* Convert to template. */ |
| | 3862 | Transmogrify_HModels(sbPtr, &corpseDataPtr->HModelController, template_root, 0, 0, 0); |
| | 3863 | } |
| | 3864 | else |
| | 3865 | { |
| | 3866 | const SECTION* template_root = GetNamedHierarchyFromLibrary("hnpcmarine","Template"); |
| | 3867 | assert(template_root); |
| | 3868 | /* Convert to template. */ |
| | 3869 | TrimToTemplate(sbPtr,&corpseDataPtr->HModelController, template_root, 0); |
| | 3870 | } |
| | 3871 | } |
| | 3872 | break; |
| | 3873 | case I_BehaviourPredatorPlayer: |
| | 3874 | { |
| | 3875 | this_death = GetThisDeath_FromCode(&Predator_Deaths[0],deathId); |
| | 3876 | if (this_death->Template) |
| | 3877 | { |
| | 3878 | const SECTION* template_root = GetNamedHierarchyFromLibrary("hnpcpredator","Template"); |
| | 3879 | assert(template_root); |
| | 3880 | /* Convert to template. */ |
| | 3881 | Transmogrify_HModels(sbPtr,&corpseDataPtr->HModelController, template_root, 1, 0,0); |
| | 3882 | } |
| | 3883 | } |
| | 3884 | break; |
| | 3885 | case I_BehaviourAlienPlayer: |
| | 3886 | this_death = GetThisDeath_FromCode(&Alien_Deaths[0],deathId); |
| | 3887 | break; |
| | 3888 | default : |
| | 3889 | return; |
| | 3890 | } |
| | 3891 | |
| | 3892 | if(this_death->TweeningTime <= 0) |
| | 3893 | InitHModelSequence(&corpseDataPtr->HModelController,this_death->Sequence_Type,this_death->Sub_Sequence,this_death->Sequence_Length); |
| | 3894 | else |
| | 3895 | InitHModelTweening(&corpseDataPtr->HModelController,
this_death->TweeningTime,this_death->Sequence_Type,this_death->Sub_Sequence,this_death->Sequence_Length,0); |
| | 3896 | |
| | 3897 | corpseDataPtr->This_Death = this_death; |
| | 3898 | |
| | 3899 | /* Electric death sound? */ |
| | 3900 | if (this_death->Electrical) |
| | 3901 | Sound_Play(SID_ELEC_DEATH, "de", &sbPtr->DynPtr->Position, &corpseDataPtr->SoundHandle4); |
| | 3902 | } |
| | 3903 | |
| | 3904 | void UpdateAlienAIGhostAnimSequence(STRATEGYBLOCK *sbPtr,HMODEL_SEQUENCE_TYPES type, int subtype, int length, int tweeningtime) |
| | 3905 | { |
| | 3906 | assert(sbPtr); |
| | 3907 | NETGHOSTDATABLOCK *ghostData = (NETGHOSTDATABLOCK *)sbPtr->dataptr; |
| | 3908 | |
| | 3909 | assert(length != 0); |
| | 3910 | |
| | 3911 | /* Are we already playing this one? */ |
| | 3912 | if ((ghostData->HModelController.Sequence_Type == type) && (ghostData->HModelController.Sub_Sequence == subtype)) |
| | 3913 | { |
| | 3914 | /* Yes, but... */ |
| | 3915 | /*I think we only want to change speed if we're not tweening*/ |
| | 3916 | if (tweeningtime <= 0) |
| | 3917 | { |
| | 3918 | if (length != ghostData->HModelController.Seconds_For_Sequence) |
| | 3919 | HModel_ChangeSpeed(&ghostData->HModelController,length); |
| | 3920 | } |
| | 3921 | |
| | 3922 | } |
| | 3923 | else if (tweeningtime <= 0) |
| | 3924 | { |
| | 3925 | InitHModelSequence(&ghostData->HModelController,(int)type,subtype,length); |
| | 3926 | } |
| | 3927 | else |
| | 3928 | { |
| | 3929 | InitHModelTweening(&ghostData->HModelController, tweeningtime, (int)type,subtype,length, 1); |
| | 3930 | } |
| | 3931 | |
| | 3932 | ghostData->HModelController.Playing=1; |
| | 3933 | /* Might be unset... */ |
| | 3934 | } |
| | 3935 | |
| | 3936 | void KillAlienAIGhost(STRATEGYBLOCK *sbPtr,int death_code,int death_time,int GibbFactor) |
| | 3937 | { |
| | 3938 | DEATH_DATA *this_death; |
| | 3939 | |
| | 3940 | assert(sbPtr); |
| | 3941 | NETGHOSTDATABLOCK *ghostData = (NETGHOSTDATABLOCK *)sbPtr->dataptr; |
| | 3942 | assert(ghostData); |
| | 3943 | |
| | 3944 | /* To ensure we know what we're doing... */ |
| | 3945 | #if DEBUG |
| | 3946 | if (ghostData->type != I_BehaviourAlien) |
| | 3947 | { |
| | 3948 | assert(0); |
| | 3949 | } |
| | 3950 | #endif |
| | 3951 | |
| | 3952 | if(ghostData->onlyValidFar) |
| | 3953 | { |
| | 3954 | RemoveGhost(sbPtr); |
| | 3955 | return; |
| | 3956 | } |
| | 3957 | |
| | 3958 | this_death = GetThisDeath_FromCode(Alien_Deaths, death_code); |
| | 3959 | assert(this_death); |
| | 3960 | |
| | 3961 | /* see if we've got a sound... */ |
| | 3962 | if(ghostData->SoundHandle != SOUND_NOACTIVEINDEX) Sound_Stop(ghostData->SoundHandle); |
| | 3963 | if(ghostData->SoundHandle2 != SOUND_NOACTIVEINDEX) Sound_Stop(ghostData->SoundHandle2); |
| | 3964 | if(ghostData->SoundHandle3 != SOUND_NOACTIVEINDEX) Sound_Stop(ghostData->SoundHandle3); |
| | 3965 | if(ghostData->SoundHandle4 != SOUND_NOACTIVEINDEX) Sound_Stop(ghostData->SoundHandle4); |
| | 3966 | |
| | 3967 | DestroyActiveObject(&ghostData->myGunFlash); |
| | 3968 | |
| | 3969 | /* Convert that sucker. */ |
| | 3970 | ghostData->type = I_BehaviourCorpse; |
| | 3971 | /* |
| | 3972 | Alien subtype (alien/predalien/praetorian) gets shuffled down into IOType. |
| | 3973 | Not entirely appropriate , but it will do... |
| | 3974 | */ |
| | 3975 | ghostData->IOType = ghostData->subtype; |
| | 3976 | ghostData->subtype = I_BehaviourAlien; |
| | 3977 | ghostData->timer = death_time; |
| | 3978 | |
| | 3979 | if (ghostData->HModelController.Deltas) |
| | 3980 | RemoveAllDeltas(&ghostData->HModelController); |
| | 3981 | |
| | 3982 | /* Now let's do the sequence. */ |
| | 3983 | UpdateAlienAIGhostAnimSequence(sbPtr,this_death->Sequence_Type,this_death->Sub_Sequence, this_death->Sequence_Length,this_death->TweeningTime); |
| | 3984 | ghostData->HModelController.LoopAfterTweening = 0; |
| | 3985 | |
| | 3986 | //Allow players to walk through the corpse |
| | 3987 | sbPtr->DynPtr->OnlyCollideWithEnvironment = 1; |
| | 3988 | |
| | 3989 | #if EXTRAPOLATION_TEST |
| | 3990 | sbPtr->DynPtr->LinImpulse.vx = 0; |
| | 3991 | sbPtr->DynPtr->LinImpulse.vy = 0; |
| | 3992 | sbPtr->DynPtr->LinImpulse.vz = 0; |
| | 3993 | sbPtr->DynPtr->LinVelocity.vx = 0; |
| | 3994 | sbPtr->DynPtr->LinVelocity.vy = 0; |
| | 3995 | sbPtr->DynPtr->LinVelocity.vz = 0; |
| | 3996 | sbPtr->DynPtr->UseStandardGravity = 1; |
| | 3997 | sbPtr->DynPtr->IsNetGhost = 1; |
| | 3998 | sbPtr->DynPtr->ToppleForce = TOPPLE_FORCE_NONE; |
| | 3999 | #endif |
| | 4000 | //allow the corpse to fall to the floor |
| | 4001 | sbPtr->DynPtr->GravityOn = 1; |
| | 4002 | |
| | 4003 | //if (GibbFactor) Extreme_Gibbing(sbPtr,ghostData->HModelController.section_data,GibbFactor); // jadda |
| | 4004 | |
| | 4005 | /* Electric death sound? */ |
| | 4006 | if (this_death->Electrical) |
| | 4007 | Sound_Play(SID_ELEC_DEATH, "de", &sbPtr->DynPtr->Position, &ghostData->SoundHandle4); |
| | 4008 | } |
| | 4009 | |
| | 4010 | int Deduce_PlayerMarineDeathSequence(const HMODELCONTROLLER *controller, const DAMAGE_PROFILE* damage, int multiple, VECTORCH* incoming) |
| | 4011 | { |
| | 4012 | int deathtype = 0,gibbFactor = 0; |
| | 4013 | |
| | 4014 | /* Set GibbFactor and death type*/ |
| | 4015 | { |
| | 4016 | int tkd = TotalKineticDamage(damage); |
| | 4017 | |
| | 4018 | if (damage->ExplosivePower == 1) |
| | 4019 | { |
| | 4020 | if (MUL_FIXED(tkd,(multiple&((ONE_FIXED<<1)-1)))>20) |
| | 4021 | { |
| | 4022 | /* Okay, you can gibb now. */ |
| | 4023 | gibbFactor = ONE_FIXED >> 1; |
| | 4024 | deathtype = 2; |
| | 4025 | } |
| | 4026 | } |
| | 4027 | else if ((tkd > 60) && ((multiple>>16) > 1)) |
| | 4028 | { |
| | 4029 | int newmult = DIV_FIXED(multiple,NormalFrameTime); |
| | 4030 | |
| | 4031 | if (MUL_FIXED(tkd,newmult) > 500) |
| | 4032 | { |
| | 4033 | /* Loadsabullets! */ |
| | 4034 | gibbFactor = -(ONE_FIXED >> 2); |
| | 4035 | deathtype = 2; |
| | 4036 | } |
| | 4037 | } |
| | 4038 | |
| | 4039 | if ((damage->ExplosivePower == 2) || (damage->ExplosivePower == 6)) |
| | 4040 | { |
| | 4041 | /* Basically SADARS only. */ |
| | 4042 | gibbFactor = ONE_FIXED; |
| | 4043 | deathtype = 3; |
| | 4044 | } |
| | 4045 | } |
| | 4046 | |
| | 4047 | if (damage->ForceBoom) |
| | 4048 | deathtype += damage->ForceBoom; |
| | 4049 | |
| | 4050 | { |
| | 4051 | SECTION_DATA *chest = GetThisSectionData(controller->section_data,"chest"); |
| | 4052 | |
| | 4053 | if (chest == NULL) |
| | 4054 | { |
| | 4055 | /* I'm impressed. */ |
| | 4056 | deathtype += 2; |
| | 4057 | } |
| | 4058 | else if ((chest->flags & section_data_notreal) && (chest->flags & section_data_terminate_here)) |
| | 4059 | { |
| | 4060 | /* That's gotta hurt. */ |
| | 4061 | deathtype++; |
| | 4062 | } |
| | 4063 | } |
| | 4064 | |
| | 4065 | /* Now final stage. */ |
| | 4066 | { |
| | 4067 | HIT_FACING facing = { 0,0,0,0 }; |
| | 4068 | int burning = 0,electrical = 0; |
| | 4069 | |
| | 4070 | const SECTION *root = GetNamedHierarchyFromLibrary("hnpcmarine","Template"); |
| | 4071 | |
| | 4072 | if (incoming) |
| | 4073 | { |
| | 4074 | if (incoming->vz > 0) |
| | 4075 | facing.Back = 1; |
| | 4076 | else |
| | 4077 | facing.Front = 1; |
| | 4078 | |
| | 4079 | if (incoming->vx > 0) |
| | 4080 | facing.Right = 1; |
| | 4081 | else |
| | 4082 | facing.Left = 1; |
| | 4083 | } |
| | 4084 | |
| | 4085 | if ( !damage->Impact && !damage->Cutting && !damage->Penetrative && !damage->Acid) |
| | 4086 | { |
| | 4087 | if(damage->Electrical) |
| | 4088 | { |
| | 4089 | if (!damage->Fire) |
| | 4090 | electrical = 1; |
| | 4091 | } |
| | 4092 | else if (damage->Fire && PlayerStatus.sbptr->DamageBlock.IsOnFire) |
| | 4093 | { |
| | 4094 | burning = 1; |
| | 4095 | } |
| | 4096 | } |
| | 4097 | |
| | 4098 | const DEATH_DATA *this_death = GetMarineDeathSequence(controller, root, 0, 0, deathtype, &facing, burning, PlayerStatus.Crouching, electrical); |
| | 4099 | |
| | 4100 | assert(this_death); |
| | 4101 | |
| | 4102 | return this_death->Multiplayer_Code; |
| | 4103 | } |
| | 4104 | } |
| | 4105 | |
| | 4106 | int Deduce_PlayerAlienDeathSequence(const HMODELCONTROLLER *controller, const DAMAGE_PROFILE* damage, int multiple, VECTORCH* incoming) |
| | 4107 | { |
| | 4108 | /* Get death type. */ |
| | 4109 | int tkd = TotalKineticDamage(damage); |
| | 4110 | int deathtype = 0; |
| | 4111 | |
| | 4112 | if (damage->ExplosivePower == 1) |
| | 4113 | { |
| | 4114 | /* Explosion case. */ |
| | 4115 | if (MUL_FIXED(tkd, (multiple&((ONE_FIXED<<1)-1))) > 20) |
| | 4116 | { |
| | 4117 | /* Okay, you can gibb now. */ |
| | 4118 | deathtype = 2; |
| | 4119 | } |
| | 4120 | } |
| | 4121 | else if ((tkd < 40) && ((multiple >> 16) > 1)) |
| | 4122 | { |
| | 4123 | int temp = MUL_FIXED(tkd, DIV_FIXED(multiple,NormalFrameTime)); |
| | 4124 | |
| | 4125 | if (temp > 700) |
| | 4126 | { |
| | 4127 | /* Excessive bullets case 1. */ |
| | 4128 | deathtype = 2; |
| | 4129 | } |
| | 4130 | else if (temp > 250) |
| | 4131 | { |
| | 4132 | /* Excessive bullets case 2. */ |
| | 4133 | deathtype = 1; |
| | 4134 | } |
| | 4135 | } |
| | 4136 | |
| | 4137 | if ((damage->ExplosivePower == 2) || (damage->ExplosivePower == 6)) |
| | 4138 | deathtype = 3; // Basically SADARS only. |
| | 4139 | |
| | 4140 | if (damage->ForceBoom) |
| | 4141 | deathtype += damage->ForceBoom; |
| | 4142 | |
| | 4143 | { |
| | 4144 | SECTION_DATA *chest=GetThisSectionData(controller->section_data, "chest"); |
| | 4145 | |
| | 4146 | if (chest == NULL) |
| | 4147 | { |
| | 4148 | /* I'm impressed. */ |
| | 4149 | deathtype += 2; |
| | 4150 | } |
| | 4151 | else if ((chest->flags & section_data_notreal) && (chest->flags & section_data_terminate_here)) |
| | 4152 | { |
| | 4153 | /* That's gotta hurt. */ |
| | 4154 | deathtype++; |
| | 4155 | } |
| | 4156 | } |
| | 4157 | |
| | 4158 | { |
| | 4159 | HIT_FACING facing = { 0,0,0,0 }; |
| | 4160 | |
| | 4161 | if (incoming) |
| | 4162 | { |
| | 4163 | if (incoming->vz > 0) |
| | 4164 | facing.Back = 1; |
| | 4165 | else |
| | 4166 | facing.Front = 1; |
| | 4167 | |
| | 4168 | if (incoming->vx > 0) |
| | 4169 | facing.Right = 1; |
| | 4170 | else |
| | 4171 | facing.Left = 1; |
| | 4172 | } |
| | 4173 | |
| | 4174 | DEATH_DATA *this_death = GetAlienDeathSequence(controller, NULL, 0, 0, deathtype, &facing, 0, PlayerStatus.Crouching, 0); |
| | 4175 | |
| | 4176 | return this_death->Multiplayer_Code; |
| | 4177 | } |
| | 4178 | } |
| | 4179 | |
| | 4180 | int Deduce_PlayerPredatorDeathSequence(const HMODELCONTROLLER *controller, const DAMAGE_PROFILE* damage, int multiple, VECTORCH* incoming) |
| | 4181 | { |
| | 4182 | int deathtype = 0; |
| | 4183 | int tkd = TotalKineticDamage(damage); |
| | 4184 | |
| | 4185 | if (damage->ExplosivePower == 1) |
| | 4186 | { |
| | 4187 | if (MUL_FIXED(tkd,(multiple&((ONE_FIXED<<1)-1))) > 20) |
| | 4188 | { |
| | 4189 | /* Okay, you can... splat now. */ |
| | 4190 | deathtype = 2; |
| | 4191 | } |
| | 4192 | } |
| | 4193 | else if ((tkd < 40) && ((multiple >> 16) > 1)) |
| | 4194 | { |
| | 4195 | int newmult = DIV_FIXED(multiple,NormalFrameTime); |
| | 4196 | |
| | 4197 | if (MUL_FIXED(tkd, newmult) > 500) |
| | 4198 | deathtype = 2; |
| | 4199 | } |
| | 4200 | |
| | 4201 | if ((damage->ExplosivePower == 2) || (damage->ExplosivePower == 6)) |
| | 4202 | { |
| | 4203 | /* Basically SADARS only. */ |
| | 4204 | deathtype = 3; |
| | 4205 | } |
| | 4206 | |
| | 4207 | if (damage->ForceBoom) |
| | 4208 | deathtype += damage->ForceBoom; |
| | 4209 | |
| | 4210 | { |
| | 4211 | SECTION_DATA *chest = GetThisSectionData(controller->section_data, "chest"); |
| | 4212 | |
| | 4213 | if (chest == NULL) |
| | 4214 | { |
| | 4215 | /* I'm impressed. */ |
| | 4216 | deathtype += 2; |
| | 4217 | } |
| | 4218 | else if ((chest->flags & section_data_notreal) && (chest->flags & section_data_terminate_here)) |
| | 4219 | { |
| | 4220 | /* That's gotta hurt. */ |
| | 4221 | deathtype++; |
| | 4222 | } |
| | 4223 | } |
| | 4224 | |
| | 4225 | { |
| | 4226 | HIT_FACING facing = { 0,0,0,0 }; |
| | 4227 | int burning = 0; |
| | 4228 | const SECTION *root = GetNamedHierarchyFromLibrary("hnpcpredator", "Template"); |
| | 4229 | |
| | 4230 | if (incoming) |
| | 4231 | { |
| | 4232 | if (incoming->vz > 0) |
| | 4233 | facing.Back = 1; |
| | 4234 | else |
| | 4235 | facing.Front = 1; |
| | 4236 | |
| | 4237 | if (incoming->vx > 0) |
| | 4238 | facing.Right = 1; |
| | 4239 | else |
| | 4240 | facing.Left = 1; |
| | 4241 | } |
| | 4242 | |
| | 4243 | if (!damage->Impact |
| | 4244 | && !damage->Cutting |
| | 4245 | && !damage->Penetrative |
| | 4246 | && damage->Fire |
| | 4247 | && !damage->Electrical |
| | 4248 | && !damage->Acid) |
| | 4249 | { |
| | 4250 | burning = 1; |
| | 4251 | } |
| | 4252 | |
| | 4253 | const DEATH_DATA *this_death = GetPredatorDeathSequence(controller, root, 0, 0, deathtype, &facing, burning, PlayerStatus.Crouching, 0); |
| | 4254 | |
| | 4255 | assert(this_death); |
| | 4256 | |
| | 4257 | return this_death->Multiplayer_Code; |
| | 4258 | } |
| | 4259 | } |
| | 4260 | |
| | 4261 | /* This a copy of UpdateGhost, with extra parameters. */ |
| | 4262 | void UpdateAlienAIGhost(STRATEGYBLOCK *sbPtr,VECTORCH *position,EULER *orientation,int sequence_type,int sub_sequence, int sequence_length) |
| | 4263 | { |
| | 4264 | assert(sbPtr); |
| | 4265 | NETGHOSTDATABLOCK *ghostData = (NETGHOSTDATABLOCK *)sbPtr->dataptr; |
| | 4266 | |
| | 4267 | /* for visibility support: as ghosts can be moved when invisible, we need to work out |
| | 4268 | which module they're in whenever we update them. We must be carefull, however, not |
| | 4269 | to set the containingModule to NULL if the object has moved outside the env, as |
| | 4270 | the visibility system expects that we at least know what module any object WAS in, |
| | 4271 | even if we do not now... thus, if we cannot find a containing module, we abort the update */ |
| | 4272 | |
| | 4273 | /* KJL 21:01:09 23/05/98 - I've put this test here because the player's image in a mirror goes |
| | 4274 | throught this code, and it's obviously going to be outside the environment */ |
| | 4275 | |
| | 4276 | if (sbPtr->type == I_BehaviourNetGhost) |
| | 4277 | { |
| | 4278 | MODULE *myContainingModule = ModuleFromPosition(position, (sbPtr->containingModule)); |
| | 4279 | |
| | 4280 | if(myContainingModule == NULL) |
| | 4281 | return; |
| | 4282 | |
| | 4283 | sbPtr->containingModule = myContainingModule; |
| | 4284 | } |
| | 4285 | |
| | 4286 | #if DEBUG |
| | 4287 | if (ghostData->type != I_BehaviourAlien) |
| | 4288 | { |
| | 4289 | assert(0); |
| | 4290 | } |
| | 4291 | #endif |
| | 4292 | |
| | 4293 | //We have enough information to be able to make this alien near (should we want to) |
| | 4294 | ghostData->onlyValidFar = 0; |
| | 4295 | |
| | 4296 | /* update the dynamics block */ |
| | 4297 | { |
| | 4298 | DYNAMICSBLOCK *dynPtr = sbPtr->DynPtr; |
| | 4299 | |
| | 4300 | dynPtr->PrevPosition = dynPtr->Position; |
| | 4301 | dynPtr->PrevOrientMat = dynPtr->OrientMat; |
| | 4302 | dynPtr->Position = *position; |
| | 4303 | dynPtr->OrientEuler = *orientation; |
| | 4304 | CreateEulerMatrix(&dynPtr->OrientEuler,&dynPtr->OrientMat); |
| | 4305 | TransposeMatrixCH(&dynPtr->OrientMat); |
| | 4306 | } |
| | 4307 | |
| | 4308 | /* KJL 16:58:04 17/06/98 - we want to update anims differently for NPCS */ |
| | 4309 | if ((sequence_type != -1) && (sub_sequence != -1)) |
| | 4310 | { |
| | 4311 | /* Not tweening! */ |
| | 4312 | UpdateAlienAIGhostAnimSequence(sbPtr,sequence_type,sub_sequence,sequence_length,(ONE_FIXED>>2)); |
| | 4313 | } |
| | 4314 | |
| | 4315 | /* refresh integrity */ |
| | 4316 | ghostData->integrity = GHOST_INTEGRITY; |
| | 4317 | } |
| | 4318 | |
| | 4319 | void Convert_DiscGhost_To_PickupGhost(STRATEGYBLOCK *sbPtr) |
| | 4320 | { |
| | 4321 | DYNAMICSBLOCK *dynPtr = sbPtr->DynPtr; |
| | 4322 | NETGHOSTDATABLOCK *ghostData= (NETGHOSTDATABLOCK * ) sbPtr->dataptr; |
| | 4323 | /* Transmogrify a disc ghost behaviour to a disc ammo pickup! */ |
| | 4324 | |
| | 4325 | /* Sort out dynamics block */ |
| | 4326 | dynPtr->LinVelocity.vx = dynPtr->LinVelocity.vy = dynPtr->LinVelocity.vz = 0; |
| | 4327 | dynPtr->LinImpulse.vx = dynPtr->LinImpulse.vy = dynPtr->LinImpulse.vz = 0; |
| | 4328 | |
| | 4329 | ghostData->type = I_BehaviourInanimateObject; |
| | 4330 | ghostData->IOType = IOT_Ammo; |
| | 4331 | ghostData->subtype = AMMO_PRED_DISC; |
| | 4332 | |
| | 4333 | ghostData->HModelController.Playing = 0; |
| | 4334 | /* Deal with flip up case? */ |
| | 4335 | |
| | 4336 | /* The final shape is NOT hierarchical. */ |
| | 4337 | { |
| | 4338 | SECTION_DATA *disc_section = GetThisSectionData(ghostData->HModelController.section_data, "disk"); |
| | 4339 | assert(disc_section); |
| | 4340 | |
| | 4341 | sbPtr->shapeIndex = disc_section->sempai->ShapeNum; |
| | 4342 | |
| | 4343 | Dispel_HModel(&ghostData->HModelController); |
| | 4344 | |
| | 4345 | if (sbPtr->DisplayBlock) |
| | 4346 | { |
| | 4347 | sbPtr->DisplayBlock->ObShape = disc_section->sempai->ShapeNum; |
| | 4348 | sbPtr->DisplayBlock->ShapeData = disc_section->sempai->Shape; |
| | 4349 | sbPtr->DisplayBlock->HModelControlBlock = NULL; |
| | 4350 | } |
| | 4351 | } |
| | 4352 | |
| | 4353 | if(ghostData->SoundHandle != SOUND_NOACTIVEINDEX) |
| | 4354 | Sound_Stop(ghostData->SoundHandle); |
| | 4355 | |
| | 4356 | Sound_Play(SID_DISC_STICKSINWALL, "dp", &sbPtr->DynPtr->Position, ((FastRandom()&511)-255)); |
| | 4357 | } |
| | 4358 | |
| | 4359 | void PlayHitDeltaOnGhost(STRATEGYBLOCK *sbPtr,char delta_seq,char delta_sub_seq) |
| | 4360 | { |
| | 4361 | assert(sbPtr); |
| | 4362 | NETGHOSTDATABLOCK *ghostData = (NETGHOSTDATABLOCK *)sbPtr->dataptr; |
| | 4363 | |
| | 4364 | //only play hit deltas on marine and predator players |
| | 4365 | switch(ghostData->type) |
| | 4366 | { |
| | 4367 | case I_BehaviourMarinePlayer: |
| | 4368 | case I_BehaviourPredatorPlayer: |
| | 4369 | break; |
| | 4370 | default: |
| | 4371 | return; |
| | 4372 | } |
| | 4373 | |
| | 4374 | DELTA_CONTROLLER *hitdelta = Get_Delta_Sequence(&ghostData->HModelController,"HitDelta"); |
| | 4375 | |
| | 4376 | if(hitdelta) |
| | 4377 | { |
| | 4378 | if (HModelSequence_Exists(&ghostData->HModelController,(int)delta_seq,(int)delta_sub_seq)) |
| | 4379 | { |
| | 4380 | Start_Delta_Sequence(hitdelta,(int)delta_seq,(int) delta_sub_seq,ONE_FIXED/2); |
| | 4381 | hitdelta->Playing = 1; |
| | 4382 | } |
| | 4383 | } |
| | 4384 | } |
| | 4385 | |
| | 4386 | void PlayOtherSound(enum soundindex SoundIndex, VECTORCH *position, int explosion) |
| | 4387 | { |
| | 4388 | if (explosion) |
| | 4389 | { |
| | 4390 | Ghost_Explosion_SoundData.position = *position; |
| | 4391 | Sound_Play(SoundIndex, "n", &Ghost_Explosion_SoundData); |
| | 4392 | } |
| | 4393 | else |
| | 4394 | { |
| | 4395 | Sound_Play(SoundIndex, "d", position); |
| | 4396 | } |
| | 4397 | } |