| | 1 | #include "system.h" |
| | 2 | #include "prototyp.h" |
| | 3 | #include "stratdef.h" |
| | 4 | #include "bh_types.h" |
| | 5 | #include "dynamics.h" |
| | 6 | #include "weapons.h" |
| | 7 | #include "pheromon.h" |
| | 8 | #include "scream.h" |
| | 9 | #include "savegame.h" |
| | 10 | #include "pfarlocs.h" |
| | 11 | #include "bh_ais.h" |
| | 12 | #include "game_statistics.h" |
| | 13 | #include "psndplat.h" |
| | 14 | #include "pldghost.h" |
| | 15 | #include "frustum.h" |
| | 16 | #include <assert.h> |
| | 17 | #include <stdlib.h> |
| | 18 | #include <stdio.h> |
| | 19 | #include "usr_io.h" |
| | 20 | #include "userprofile.h" |
| | 21 | #include "corpse.h" |
| | 22 | #include "sequnces.h" |
| | 23 | #include "extents.h" |
| | 24 | #include "hud.h" |
| | 25 | |
| | 26 | PLAYER_INPUT_CONFIGURATION *primaryInput; |
| | 27 | PLAYER_INPUT_CONFIGURATION *secondaryInput; |
| | 28 | |
| | 29 | extern void InitialiseGrapplingHook(); |
| | 30 | |
| | 31 | extern int Keyboard_input_operate(); |
| | 32 | extern void handle_user_input(); |
| | 33 | extern unsigned int mission_messages_timer; |
| | 34 | extern char * mission_messages; |
| | 35 | extern HMODELCONTROLLER PlayersWeaponHModelController; |
| | 36 | extern int predHUDSoundHandle; |
| | 37 | extern int predOVision_SoundHandle; |
| | 38 | extern int weaponHandle; |
| | 39 | extern int AVPDPNetID; |
| | 40 | extern int myNetworkKillerId; |
| | 41 | extern int MyHitBodyPartId; |
| | 42 | extern int MultiplayerObservedPlayer; |
| | 43 | extern int PlayersMaxHeightWhilstNotInContactWithGround; |
| | 44 | |
| | 45 | const SECTION * GetNamedHierarchyFromLibrary(const char * rif_name, const char *); |
| | 46 | extern int SlotForThisWeapon(enum WEAPON_ID weaponID); |
| | 47 | extern void LoadAllWeapons(); |
| | 48 | extern void DisengageGrapplingHook(); |
| | 49 | extern int LightIntensityAtPoint(VECTORCH *pointPtr); |
| | 50 | extern void PointAlert(int level, VECTORCH *point); |
| | 51 | extern void InitMarineHUD(); |
| | 52 | |
| | 53 | PLAYER_STATUS PlayerStatus; |
| | 54 | int AlienTeethOffset = 0; |
| | 55 | int AlienTongueOffset = 0; |
| | 56 | int deathFadeLevel; |
| | 57 | int CloakingPhase; |
| | 58 | EULER HeadOrientation = {0,0,0}; |
| | 59 | |
| | 60 | extern int TURNSCALE; |
| | 61 | int ALIEN_STRAFESCALE; |
| | 62 | int PREDATOR_STRAFESCALE; |
| | 63 | int MARINE_STRAFESCALE; |
| | 64 | |
| | 65 | static void InitialisePlayersInventory() |
| | 66 | { |
| | 67 | int a; |
| | 68 | |
| | 69 | switch(AvP.PlayerType) |
| | 70 | { |
| | 71 | case I_Marine: |
| | 72 | { |
| | 73 | GrenadeLauncherData.StandardRoundsRemaining = 0; |
| | 74 | GrenadeLauncherData.StandardMagazinesRemaining = 0; |
| | 75 | GrenadeLauncherData.ProximityRoundsRemaining = 0; |
| | 76 | GrenadeLauncherData.ProximityMagazinesRemaining = 0; |
| | 77 | GrenadeLauncherData.FragmentationRoundsRemaining = 0; |
| | 78 | GrenadeLauncherData.FragmentationMagazinesRemaining = 0; |
| | 79 | GrenadeLauncherData.SelectedAmmo = AMMO_GRENADE; |
| | 80 | |
| | 81 | PlayerStatus.JetpackEnabled = PlayerStatus.StartingEquipment.marine_jetpack; |
| | 82 | |
| | 83 | a = SlotForThisWeapon(WEAPON_CUDGEL); |
| | 84 | |
| | 85 | if (a != -1) |
| | 86 | PlayerStatus.WeaponSlot[a].Possessed = 1; |
| | 87 | |
| | 88 | /*if in a multiplayer game , check to see if player is a specialist marine*/ |
| | 89 | if(SinglePlayer != AvP.PlayMode) |
| | 90 | { |
| | 91 | if (netGameData.specialistPistols) |
| | 92 | { |
| | 93 | /* Conditional pistol! */ |
| | 94 | a = SlotForThisWeapon(WEAPON_MARINE_PISTOL); |
| | 95 | |
| | 96 | if (a != -1) |
| | 97 | { |
| | 98 | PlayerStatus.WeaponSlot[a].Possessed = 1; |
| | 99 | PlayerStatus.WeaponSlot[a].MagazinesRemaining = 6; |
| | 100 | } |
| | 101 | } |
| | 102 | |
| | 103 | switch(netGameData.myCharacterSubType) |
| | 104 | { |
| | 105 | case NGSCT_Smartgun: |
| | 106 | a = SlotForThisWeapon(WEAPON_SMARTGUN); |
| | 107 | PlayerStatus.WeaponSlot[a].Possessed = 1; |
| | 108 | |
| | 109 | PlayerStatus.WeaponSlot[a].MagazinesRemaining = 6; |
| | 110 | break; |
| | 111 | case NGSCT_Flamer: |
| | 112 | a = SlotForThisWeapon(WEAPON_FLAMETHROWER); |
| | 113 | PlayerStatus.WeaponSlot[a].Possessed = 1; |
| | 114 | |
| | 115 | PlayerStatus.WeaponSlot[a].MagazinesRemaining = 8; |
| | 116 | break; |
| | 117 | case NGSCT_Sadar: |
| | 118 | a = SlotForThisWeapon(WEAPON_SADAR); |
| | 119 | PlayerStatus.WeaponSlot[a].Possessed = 1; |
| | 120 | |
| | 121 | PlayerStatus.WeaponSlot[a].PrimaryRoundsRemaining = 10; |
| | 122 | break; |
| | 123 | case NGSCT_GrenadeLauncher: |
| | 124 | a = SlotForThisWeapon(WEAPON_GRENADELAUNCHER); |
| | 125 | PlayerStatus.WeaponSlot[a].Possessed = 1; |
| | 126 | |
| | 127 | PlayerStatus.WeaponSlot[a].MagazinesRemaining = 4; |
| | 128 | GrenadeLauncherData.StandardMagazinesRemaining = 4; |
| | 129 | GrenadeLauncherData.ProximityMagazinesRemaining = 4; |
| | 130 | GrenadeLauncherData.FragmentationMagazinesRemaining = 4; |
| | 131 | break; |
| | 132 | case NGSCT_Minigun: |
| | 133 | a = SlotForThisWeapon(WEAPON_MINIGUN); |
| | 134 | PlayerStatus.WeaponSlot[a].Possessed = 1; |
| | 135 | |
| | 136 | PlayerStatus.WeaponSlot[a].MagazinesRemaining = 4; |
| | 137 | break; |
| | 138 | case NGSCT_PulseRifle: |
| | 139 | a = SlotForThisWeapon(WEAPON_PULSERIFLE); |
| | 140 | PlayerStatus.WeaponSlot[a].Possessed = 1; |
| | 141 | |
| | 142 | PlayerStatus.WeaponSlot[a].MagazinesRemaining = 10; |
| | 143 | PlayerStatus.WeaponSlot[a].SecondaryRoundsRemaining = 15; |
| | 144 | break; |
| | 145 | case NGSCT_Frisbee: |
| | 146 | a = SlotForThisWeapon(WEAPON_FRISBEE_LAUNCHER); |
| | 147 | PlayerStatus.WeaponSlot[a].Possessed = 1; |
| | 148 | |
| | 149 | PlayerStatus.WeaponSlot[a].MagazinesRemaining = 5; |
| | 150 | break; |
| | 151 | case NGSCT_Pistols: |
| | 152 | a = SlotForThisWeapon(WEAPON_MARINE_PISTOL); |
| | 153 | |
| | 154 | if (a != -1) |
| | 155 | { |
| | 156 | PlayerStatus.WeaponSlot[a].Possessed = 1; |
| | 157 | PlayerStatus.WeaponSlot[a].MagazinesRemaining = 30; |
| | 158 | } |
| | 159 | |
| | 160 | a = SlotForThisWeapon(WEAPON_TWO_PISTOLS); |
| | 161 | |
| | 162 | if (a != -1) |
| | 163 | { |
| | 164 | PlayerStatus.WeaponSlot[a].Possessed = 1; |
| | 165 | PlayerStatus.WeaponSlot[a].MagazinesRemaining = 30; |
| | 166 | } |
| | 167 | break; |
| | 168 | case NGSCT_General: |
| | 169 | default: |
| | 170 | |
| | 171 | a = SlotForThisWeapon(WEAPON_PULSERIFLE); |
| | 172 | PlayerStatus.WeaponSlot[a].Possessed = 1; |
| | 173 | PlayerStatus.WeaponSlot[a].MagazinesRemaining = 6; |
| | 174 | PlayerStatus.WeaponSlot[a].SecondaryRoundsRemaining = 5; |
| | 175 | } |
| | 176 | } |
| | 177 | else |
| | 178 | { |
| | 179 | a = SlotForThisWeapon(WEAPON_PULSERIFLE); |
| | 180 | PlayerStatus.WeaponSlot[a].Possessed = 1; |
| | 181 | |
| | 182 | if (CHEATMODE_GRENADE == UserProfile.active_bonus) |
| | 183 | { |
| | 184 | PlayerStatus.WeaponSlot[a].MagazinesRemaining = 0; |
| | 185 | PlayerStatus.WeaponSlot[a].SecondaryRoundsRemaining = 99; |
| | 186 | } |
| | 187 | else |
| | 188 | { |
| | 189 | PlayerStatus.WeaponSlot[a].MagazinesRemaining = 4; |
| | 190 | PlayerStatus.WeaponSlot[a].SecondaryRoundsRemaining = 4; |
| | 191 | } |
| | 192 | } |
| | 193 | } |
| | 194 | break; |
| | 195 | case I_Predator: |
| | 196 | { |
| | 197 | PlayerStatus.GrapplingHookEnabled = PlayerStatus.StartingEquipment.predator_grappling_hook; |
| | 198 | |
| | 199 | if(PlayerStatus.StartingEquipment.predator_pistol) |
| | 200 | { |
| | 201 | a = SlotForThisWeapon(WEAPON_PRED_PISTOL); |
| | 202 | PlayerStatus.WeaponSlot[a].Possessed = 1; |
| | 203 | } |
| | 204 | |
| | 205 | if(PlayerStatus.StartingEquipment.predator_num_spears) |
| | 206 | { |
| | 207 | a = SlotForThisWeapon(WEAPON_PRED_RIFLE); |
| | 208 | PlayerStatus.WeaponSlot[a].Possessed = 1; |
| | 209 | PlayerStatus.WeaponSlot[a].PrimaryRoundsRemaining = PlayerStatus.StartingEquipment.predator_num_spears; |
| | 210 | } |
| | 211 | |
| | 212 | if(PlayerStatus.StartingEquipment.predator_plasmacaster) |
| | 213 | { |
| | 214 | a = SlotForThisWeapon(WEAPON_PRED_SHOULDERCANNON); |
| | 215 | PlayerStatus.WeaponSlot[a].Possessed = 1; |
| | 216 | } |
| | 217 | |
| | 218 | if(PlayerStatus.StartingEquipment.predator_disc) |
| | 219 | { |
| | 220 | a = SlotForThisWeapon(WEAPON_PRED_DISC); |
| | 221 | PlayerStatus.WeaponSlot[a].Possessed = 1; |
| | 222 | PlayerStatus.WeaponSlot[a].PrimaryRoundsRemaining = 1; |
| | 223 | } |
| | 224 | |
| | 225 | if(PlayerStatus.StartingEquipment.predator_medicomp) |
| | 226 | { |
| | 227 | a = SlotForThisWeapon(WEAPON_PRED_MEDICOMP); |
| | 228 | PlayerStatus.WeaponSlot[a].Possessed = 1; |
| | 229 | } |
| | 230 | |
| | 231 | a = SlotForThisWeapon(WEAPON_PRED_WRISTBLADE); |
| | 232 | PlayerStatus.WeaponSlot[a].Possessed = 1; |
| | 233 | } |
| | 234 | break; |
| | 235 | case I_Alien: |
| | 236 | { |
| | 237 | a = SlotForThisWeapon(WEAPON_ALIEN_CLAW); |
| | 238 | PlayerStatus.WeaponSlot[a].Possessed = 1; |
| | 239 | PlayerStatus.SelectedWeapon = &PlayerStatus.WeaponSlot[a]; |
| | 240 | return; |
| | 241 | } |
| | 242 | } |
| | 243 | |
| | 244 | PlayerStatus.PreviouslySelectedWeaponSlot = a; |
| | 245 | PlayerStatus.SwapToWeaponSlot = a; |
| | 246 | PlayerStatus.SelectedWeapon = &PlayerStatus.WeaponSlot[a]; |
| | 247 | LoadAllWeapons(); |
| | 248 | } |
| | 249 | |
| | 250 | void create_player_hmodel() |
| | 251 | { |
| | 252 | const SECTION *root_section; |
| | 253 | |
| | 254 | switch(AvP.PlayerType) |
| | 255 | { |
| | 256 | case I_Alien: |
| | 257 | root_section = GetNamedHierarchyFromLibrary("hnpcalien", "alien"); |
| | 258 | //root_section = GetNamedHierarchyFromLibrary("hnpcpred_alien", "TEMPLATE"); |
| | 259 | //root_section = GetNamedHierarchyFromLibrary("hnpcpretorian","Template"); |
| | 260 | break; |
| | 261 | case I_Marine: |
| | 262 | switch (PlayerStatus.SelectedWeapon->WeaponIDNumber) |
| | 263 | { |
| | 264 | default: |
| | 265 | case WEAPON_PULSERIFLE: |
| | 266 | root_section = GetNamedHierarchyFromLibrary("hnpcmarine", "marine with pulse rifle"); |
| | 267 | break; |
| | 268 | case WEAPON_TWO_PISTOLS: |
| | 269 | root_section = GetNamedHierarchyFromLibrary("hnpcmarine", "Two Pistol"); |
| | 270 | break; |
| | 271 | case WEAPON_MARINE_PISTOL: |
| | 272 | root_section = GetNamedHierarchyFromLibrary("hnpcmarine", "PISTOL"); |
| | 273 | break; |
| | 274 | case WEAPON_FLAMETHROWER: |
| | 275 | root_section = GetNamedHierarchyFromLibrary("hnpcmarine", "marine with flame thrower"); |
| | 276 | break; |
| | 277 | case WEAPON_SMARTGUN: |
| | 278 | root_section = GetNamedHierarchyFromLibrary("hnpcmarine", "marine with smart gun"); |
| | 279 | break; |
| | 280 | case WEAPON_MINIGUN: |
| | 281 | root_section = GetNamedHierarchyFromLibrary("hnpcmarine", "Marine with Mini Gun"); |
| | 282 | break; |
| | 283 | case WEAPON_SADAR: |
| | 284 | root_section = GetNamedHierarchyFromLibrary("hnpcmarine", "marine with SADAR"); |
| | 285 | break; |
| | 286 | case WEAPON_GRENADELAUNCHER: |
| | 287 | root_section = GetNamedHierarchyFromLibrary("hnpcmarine", "marine + grenade launcher"); |
| | 288 | break; |
| | 289 | case WEAPON_CUDGEL: |
| | 290 | root_section = GetNamedHierarchyFromLibrary("hnpcmarine", "Cudgel"); |
| | 291 | break; |
| | 292 | case WEAPON_FRISBEE_LAUNCHER: |
| | 293 | root_section = GetNamedHierarchyFromLibrary("hnpcmarine", "skeeter"); |
| | 294 | } |
| | 295 | break; |
| | 296 | case I_Predator: |
| | 297 | switch (PlayerStatus.SelectedWeapon->WeaponIDNumber) |
| | 298 | { |
| | 299 | default: |
| | 300 | case WEAPON_PRED_WRISTBLADE: |
| | 301 | root_section = GetNamedHierarchyFromLibrary("hnpcpredator", "pred with wristblade"); |
| | 302 | break; |
| | 303 | case WEAPON_PRED_RIFLE: |
| | 304 | root_section = GetNamedHierarchyFromLibrary("hnpcpredator", "Speargun"); |
| | 305 | break; |
| | 306 | case WEAPON_PRED_MEDICOMP: |
| | 307 | root_section = GetNamedHierarchyFromLibrary("hnpcpredator", "medicomp"); |
| | 308 | break; |
| | 309 | case WEAPON_PRED_SHOULDERCANNON: |
| | 310 | root_section = GetNamedHierarchyFromLibrary("hnpcpredator", "pred with Plasma Caster"); |
| | 311 | break; |
| | 312 | case WEAPON_PRED_PISTOL: |
| | 313 | root_section = GetNamedHierarchyFromLibrary("hnpcpredator", "pred + pistol"); |
| | 314 | break; |
| | 315 | case WEAPON_PRED_DISC: |
| | 316 | root_section = GetNamedHierarchyFromLibrary("hnpcpredator", "pred with disk"); |
| | 317 | //root_section = GetNamedHierarchyFromLibrary("hnpcpredator", "pred with staff"); |
| | 318 | } |
| | 319 | } |
| | 320 | |
| | 321 | Dispel_HModel(&PlayerStatus.HModelController); |
| | 322 | Create_HModel(&PlayerStatus.HModelController, root_section); |
| | 323 | InitHModelSequence(&PlayerStatus.HModelController, 0, 0, ONE_FIXED); |
| | 324 | //PlayerStatus.HModelController.Playing = 0; |
| | 325 | PlayerStatus.HModelController.Looped = 0; |
| | 326 | ProveHModel_Far(&PlayerStatus.HModelController, PlayerStatus.sbptr); |
| | 327 | } |
| | 328 | |
| | 329 | static void ConfigurePlayer() |
| | 330 | { |
| | 331 | mission_messages = NULL; |
| | 332 | mission_messages_timer = 0; |
| | 333 | mission_messages_clear(); |
| | 334 | |
| | 335 | PlayerStatus.LeanScale = ONE_FIXED; |
| | 336 | |
| | 337 | if (CHEATMODE_MIRROR == UserProfile.active_bonus) |
| | 338 | { |
| | 339 | TURNSCALE = -2000; |
| | 340 | ALIEN_STRAFESCALE = -12000; |
| | 341 | PREDATOR_STRAFESCALE = -8000; |
| | 342 | MARINE_STRAFESCALE = -7000; |
| | 343 | } |
| | 344 | else |
| | 345 | { |
| | 346 | TURNSCALE = 2000; |
| | 347 | ALIEN_STRAFESCALE = 12000; |
| | 348 | PREDATOR_STRAFESCALE = 8000; |
| | 349 | MARINE_STRAFESCALE = 7000; |
| | 350 | } |
| | 351 | |
| | 352 | { |
| | 353 | extern int AllowedLookUpAngle; |
| | 354 | extern int AllowedLookDownAngle; |
| | 355 | extern float CameraZoomScale; |
| | 356 | extern int CameraZoomLevel; |
| | 357 | extern SCREENDESCRIPTORBLOCK ScreenDescriptorBlock; |
| | 358 | |
| | 359 | Global_VDB.VDB_ProjX = ScreenDescriptorBlock.SDB_CentreX; |
| | 360 | Global_VDB.VDB_ProjY = ScreenDescriptorBlock.SDB_CentreY; |
| | 361 | |
| | 362 | const NPC_DATA *NpcData; |
| | 363 | AllowedLookUpAngle = 328; |
| | 364 | AllowedLookDownAngle = 1700; |
| | 365 | HeadOrientation.EulerX = HeadOrientation.EulerY = HeadOrientation.EulerZ = 0; |
| | 366 | PlayerStatus.VisionMode = VISION_MODE_NORMAL; |
| | 367 | CameraZoomScale = 1.0f; |
| | 368 | CameraZoomLevel = 0; |
| | 369 | PredatorVisionChangeCounter = 0; |
| | 370 | enum WEAPON_ID *PlayerWeaponKey; |
| | 371 | |
| | 372 | PlayerStatus.imageintensifier_battery = 0; |
| | 373 | PlayerStatus.FlaresLeft = 20; |
| | 374 | PlayerStatus.sbptr->DamageBlock.Health = 0; |
| | 375 | PlayerStatus.sbptr->DamageBlock.Armour = 0; |
| | 376 | PlayerStatus.sbptr->DamageBlock.AcidResistant = 0; |
| | 377 | PlayerStatus.sbptr->DamageBlock.FireResistant = 0; |
| | 378 | PlayerStatus.sbptr->DamageBlock.ElectricResistant = 0; |
| | 379 | PlayerStatus.sbptr->DamageBlock.PerfectArmour = 0; |
| | 380 | PlayerStatus.sbptr->DamageBlock.ElectricSensitive = 0; |
| | 381 | PlayerStatus.sbptr->DamageBlock.IsOnFire = 0; |
| | 382 | PlayerStatus.sbptr->DamageBlock.Indestructable = 0; |
| | 383 | PlayerStatus.sbptr->DamageBlock.Combustability = 1; |
| | 384 | |
| | 385 | if(!UserProfile.GameOptions.BloodParticles) |
| | 386 | AvP.Difficulty = I_Easy; |
| | 387 | |
| | 388 | switch(AvP.PlayerType) |
| | 389 | { |
| | 390 | case I_Marine: |
| | 391 | switch (AvP.Difficulty) |
| | 392 | { |
| | 393 | default: |
| | 394 | case I_Easy: |
| | 395 | PlayerStatus.sbptr->DamageBlock.AcidResistant = 1; |
| | 396 | case I_Medium: |
| | 397 | PlayerStatus.imageintensifier_battery = FIXED_MINUTE * 3; |
| | 398 | case I_Hard: |
| | 399 | NpcData = &NpcDataList[I_NPC_Marine]; |
| | 400 | } |
| | 401 | PlayerStatus.sbptr->DynPtr->ToppleForce = TOPPLE_FORCE_NONE; |
| | 402 | PlayerStatus.sbptr->DynPtr->Mass = 80; |
| | 403 | PlayerWeaponKey = MarineWeaponKey; |
| | 404 | PlayerStatus.bhvr_type = I_BehaviourMarinePlayer; |
| | 405 | PlayerStatus.sbptr->type = I_BehaviourMarinePlayer; |
| | 406 | SetFrustrumType(FRUSTRUM_TYPE_NORMAL); |
| | 407 | InitMarineHUD(); |
| | 408 | primaryInput = &UserProfile.MarineInputPrimaryConfig; |
| | 409 | secondaryInput = &UserProfile.MarineInputSecondaryConfig; |
| | 410 | PlayerStatus.Hud = marine_hud; |
| | 411 | PlayerStatus.weapon_func = maintain_marine_weapons; |
| | 412 | break; |
| | 413 | case I_Predator: |
| | 414 | switch (AvP.Difficulty) |
| | 415 | { |
| | 416 | default: |
| | 417 | case I_Easy: |
| | 418 | PlayerStatus.sbptr->DamageBlock.AcidResistant = 1; |
| | 419 | case I_Medium: |
| | 420 | case I_Hard: |
| | 421 | NpcData = &NpcDataList[I_NPC_PredatorAlien]; |
| | 422 | } |
| | 423 | PlayerStatus.sbptr->DynPtr->ToppleForce = TOPPLE_FORCE_NONE; |
| | 424 | PlayerStatus.sbptr->DynPtr->Mass = 180; |
| | 425 | PlayerWeaponKey = PredatorWeaponKey; |
| | 426 | PlayerStatus.bhvr_type = I_BehaviourPredatorPlayer; |
| | 427 | PlayerStatus.sbptr->type = I_BehaviourPredatorPlayer; |
| | 428 | SetFrustrumType(FRUSTRUM_TYPE_NORMAL); |
| | 429 | InitialiseGrapplingHook(); |
| | 430 | primaryInput = &UserProfile.PredatorInputPrimaryConfig; |
| | 431 | secondaryInput = &UserProfile.PredatorInputSecondaryConfig; |
| | 432 | predOVision_SoundHandle = SOUND_NOACTIVEINDEX; |
| | 433 | PlayerStatus.Hud = predator_hud; |
| | 434 | PlayerStatus.weapon_func = maintain_predator_weapons; |
| | 435 | break; |
| | 436 | case I_Alien: |
| | 437 | NpcData = &NpcDataList[I_NPC_Alien]; |
| | 438 | PlayerStatus.sbptr->DamageBlock.AcidResistant = 1; |
| | 439 | PlayerStatus.sbptr->DamageBlock.ElectricSensitive = 1; |
| | 440 | PlayerStatus.sbptr->DamageBlock.PerfectArmour = 1; |
| | 441 | PlayerStatus.sbptr->DamageBlock.Combustability = 0; |
| | 442 | PlayerStatus.sbptr->DynPtr->Mass = 160; |
| | 443 | PlayerWeaponKey = AlienWeaponKey; |
| | 444 | PlayerStatus.sbptr->DynPtr->ToppleForce = TOPPLE_FORCE_ALIEN; |
| | 445 | PlayerStatus.bhvr_type = I_BehaviourAlienPlayer; |
| | 446 | PlayerStatus.sbptr->type = I_BehaviourAlienPlayer; |
| | 447 | AlienTeethOffset = 0; |
| | 448 | AlienTongueOffset = 0; |
| | 449 | /* setup wide-angle lens */ |
| | 450 | Global_VDB.VDB_ProjX /= 2; |
| | 451 | Global_VDB.VDB_ProjY /= 2; |
| | 452 | SetFrustrumType(FRUSTRUM_TYPE_WIDE); |
| | 453 | PlayerStatus.LeanScale *= 3; |
| | 454 | primaryInput = &UserProfile.AlienInputPrimaryConfig; |
| | 455 | secondaryInput = &UserProfile.AlienInputSecondaryConfig; |
| | 456 | AllowedLookUpAngle = 0; |
| | 457 | PlayerStatus.Hud = alien_hud; |
| | 458 | PlayerStatus.weapon_func = maintain_alien_weapons; |
| | 459 | } |
| | 460 | |
| | 461 | PlayerStatus.StartingHealth = NpcData->StartingStats.Health; |
| | 462 | PlayerStatus.StartingArmour = NpcData->StartingStats.Armour; |
| | 463 | |
| | 464 | PlayerStatus.sbptr->DamageBlock = NpcData->StartingStats; |
| | 465 | PlayerStatus.sbptr->DamageBlock.Health = PlayerStatus.StartingHealth << ONE_FIXED_SHIFT; |
| | 466 | PlayerStatus.sbptr->DamageBlock.Armour = PlayerStatus.StartingArmour << ONE_FIXED_SHIFT; |
| | 467 | |
| | 468 | PlayerStatus.sbptr->DynPtr->UseStandardGravity = 1; |
| | 469 | |
| | 470 | { |
| | 471 | int slot = MAX_NO_OF_WEAPON_SLOTS; |
| | 472 | |
| | 473 | do |
| | 474 | { |
| | 475 | struct PLAYER_WEAPON_DATA *wdPtr = &PlayerStatus.WeaponSlot[--slot]; |
| | 476 | |
| | 477 | wdPtr->WeaponIDNumber = PlayerWeaponKey[slot]; |
| | 478 | wdPtr->PrimaryRoundsRemaining = 0; |
| | 479 | wdPtr->SecondaryRoundsRemaining = 0; |
| | 480 | wdPtr->MagazinesRemaining = 0; |
| | 481 | wdPtr->LeftOverBullets = 0; |
| | 482 | wdPtr->Possessed = 0; |
| | 483 | |
| | 484 | } while(slot); |
| | 485 | } |
| | 486 | } |
| | 487 | |
| | 488 | PlayerStatus.incidentFlag = 0; |
| | 489 | PlayerStatus.incidentTimer = 0; |
| | 490 | |
| | 491 | PlayerStatus.cloakOn = 0; |
| | 492 | PlayerStatus.muzzle_flash = 0; |
| | 493 | PlayerStatus.Noise = 0; |
| | 494 | PlayerStatus.FirstPersonView = 1; |
| | 495 | PlayerStatus.CloakingEffectiveness = 0; |
| | 496 | PlayerStatus.FieldCharge = PLAYERCLOAK_MAXENERGY; |
| | 497 | PlayerStatus.PlasmaCasterCharge = 0; |
| | 498 | |
| | 499 | /* CDF 16/9/97 Now, those health and armour stats are those of the last cycle. */ |
| | 500 | |
| | 501 | PlayerStatus.Health = PlayerStatus.sbptr->DamageBlock.Health; |
| | 502 | PlayerStatus.Armour = PlayerStatus.sbptr->DamageBlock.Armour; |
| | 503 | |
| | 504 | PlayerStatus.InputRequests.Rqst_FirePrimaryWeapon = 0; |
| | 505 | PlayerStatus.InputRequests.Rqst_FireSecondaryWeapon = 0; |
| | 506 | PlayerStatus.InputRequests.Rqst_Forward = 0; |
| | 507 | PlayerStatus.InputRequests.Rqst_Backward = 0; |
| | 508 | PlayerStatus.InputRequests.Rqst_SideStepLeft = 0; |
| | 509 | PlayerStatus.InputRequests.Rqst_SideStepRight = 0; |
| | 510 | PlayerStatus.InputRequests.Rqst_Strafe = 0; |
| | 511 | PlayerStatus.InputRequests.Rqst_Jump = 0; |
| | 512 | PlayerStatus.InputRequests.Rqst_Walk = 0; |
| | 513 | |
| | 514 | PlayerStatus.Alive = 1; |
| | 515 | PlayerStatus.RequestsToStandUp = 0; |
| | 516 | PlayerStatus.IHaveAPlacedAutogun = 0; |
| | 517 | PlayerStatus.tauntTimer = 0; |
| | 518 | PlayerStatus.invulnerabilityTimer = 0; |
| | 519 | PlayerStatus.ForwardInertia = 0; |
| | 520 | PlayerStatus.StrafeInertia = 0; |
| | 521 | PlayerStatus.TurnInertia = 0; |
| | 522 | PlayerStatus.Crouching = 0; |
| | 523 | PlayerStatus.ViewPanX = 0; |
| | 524 | PlayerStatus.securityClearances = 0; |
| | 525 | PlayerStatus.DamagedOverlayIntensity = 0; |
| | 526 | PlayerStatus.CurrentLightAtPlayer = 0; |
| | 527 | |
| | 528 | /* Better safe than sorry. */ |
| | 529 | PlayerStatus.sound_mouth = SOUND_NOACTIVEINDEX; |
| | 530 | PlayerStatus.soundCracklingFire = SOUND_NOACTIVEINDEX; |
| | 531 | PlayerStatus.sound_watersplash = SOUND_NOACTIVEINDEX; |
| | 532 | PlayerStatus.sound_jetpack = SOUND_NOACTIVEINDEX; |
| | 533 | |
| | 534 | PlayerStatus.WeaponStateTimeOutCounter = 0; |
| | 535 | PlayerStatus.WeaponState = WEAPONSTATE_SWAPPING_IN; |
| | 536 | PlayerStatus.WeaponPositionOffset.vx = 0; |
| | 537 | PlayerStatus.WeaponPositionOffset.vy = 0; |
| | 538 | PlayerStatus.WeaponPositionOffset.vz = 0; |
| | 539 | |
| | 540 | switch(AvP.Difficulty) |
| | 541 | { |
| | 542 | case I_Easy: |
| | 543 | PlayerStatus.saves_left = 4; |
| | 544 | break; |
| | 545 | case I_Medium: |
| | 546 | PlayerStatus.saves_left = 2; |
| | 547 | break; |
| | 548 | case I_Hard: |
| | 549 | default: |
| | 550 | PlayerStatus.saves_left = 1; |
| | 551 | } |
| | 552 | |
| | 553 | InitialisePlayersInventory(); |
| | 554 | GrabWeaponShape(); |
| | 555 | |
| | 556 | if(SinglePlayer == AvP.PlayMode) |
| | 557 | SoundSys_FadeIn(); |
| | 558 | else |
| | 559 | SoundSys_ResetFadeLevel(); |
| | 560 | } |
| | 561 | |
| | 562 | int InitPlayer() |
| | 563 | { |
| | 564 | PlayerStatus.DisplayBlock = CreateActiveObject(); |
| | 565 | PlayerStatus.sbptr = CreateActiveStrategyBlock(I_BehaviourMarinePlayer); |
| | 566 | PlayerStatus.HModelController.Deltas = NULL; |
| | 567 | PlayerStatus.HModelController.Root_Section = NULL; |
| | 568 | PlayerStatus.HModelController.section_data= NULL; |
| | 569 | |
| | 570 | if((NULL != PlayerStatus.sbptr) && (NULL != PlayerStatus.DisplayBlock)) |
| | 571 | { |
| | 572 | PlayerStatus.DisplayBlock->ObStrategyBlock = PlayerStatus.sbptr; |
| | 573 | PlayerStatus.sbptr->DisplayBlock = PlayerStatus.DisplayBlock; |
| | 574 | PlayerStatus.DisplayBlock->HModelControlBlock = &PlayerStatus.HModelController; |
| | 575 | PlayerStatus.DisplayBlock->ObFlags |= ObFlag_NotVis; |
| | 576 | PlayerStatus.sbptr->maintainVisibility = 0; // player is always near; skip DoObjectVisibility. |
| | 577 | |
| | 578 | PlayerStatus.sbptr->dataptr = (void*)&PlayerStatus; |
| | 579 | AssignNewSBName(PlayerStatus.sbptr); |
| | 580 | PlayerStatus.sbptr->DynPtr = AllocateDynamicsBlock(DYNAMICS_TEMPLATE_DEFAULT); |
| | 581 | |
| | 582 | if(NULL != PlayerStatus.sbptr->DynPtr) |
| | 583 | { |
| | 584 | extern const DISPLAYBLOCK Zero_Displayblock; |
| | 585 | DYNAMICSBLOCK *dynPtr = PlayerStatus.sbptr->DynPtr; |
| | 586 | |
| | 587 | dynPtr->PrevPosition = dynPtr->Position = PlayerStatus.DisplayBlock->ObWorld = PlayerStatus.StartLocation; |
| | 588 | dynPtr->PrevOrientMat = dynPtr->OrientMat = PlayerStatus.StartMat; |
| | 589 | MatrixToEuler(&dynPtr->OrientMat, &dynPtr->OrientEuler); |
| | 590 | |
| | 591 | dynPtr->PrevOrientEuler = dynPtr->OrientEuler; |
| | 592 | |
| | 593 | PlayersMaxHeightWhilstNotInContactWithGround = dynPtr->Position.vy; |
| | 594 | |
| | 595 | PlayerStatus.weapon = Zero_Displayblock; |
| | 596 | PlayerStatus.weapon.HModelControlBlock = &PlayersWeaponHModelController; |
| | 597 | |
| | 598 | ConfigurePlayer(); |
| | 599 | return 1; |
| | 600 | } |
| | 601 | } |
| | 602 | |
| | 603 | |
| | 604 | return 0; |
| | 605 | } |
| | 606 | |
| | 607 | static void MakePlayersWeaponPickupVisible() |
| | 608 | { |
| | 609 | int i = NumActiveStBlocks - 1; |
| | 610 | |
| | 611 | /* |
| | 612 | Search through the strategy block list for weapons. |
| | 613 | Any weapons that have a lifespan timer should be made visible. |
| | 614 | There should only be one such object , so we can stop looking once we find it |
| | 615 | */ |
| | 616 | |
| | 617 | for(; i >= 0; i--) |
| | 618 | { |
| | 619 | STRATEGYBLOCK* sbPtr = ActiveStBlockList[i]; |
| | 620 | |
| | 621 | if(sbPtr->type == I_BehaviourInanimateObject && !sbPtr->maintainVisibility) |
| | 622 | { |
| | 623 | INANIMATEOBJECT_STATUSBLOCK* objectstatusptr = (INANIMATEOBJECT_STATUSBLOCK*)sbPtr->dataptr; |
| | 624 | |
| | 625 | if(objectstatusptr->typeId == IOT_Weapon) |
| | 626 | { |
| | 627 | if(objectstatusptr->lifespanTimer > 0) |
| | 628 | { |
| | 629 | //okay we've found the object , so allow it to be visible |
| | 630 | sbPtr->DynPtr->IsPickupObject = 1; |
| | 631 | sbPtr->maintainVisibility = 1; |
| | 632 | return; |
| | 633 | } |
| | 634 | } |
| | 635 | } |
| | 636 | } |
| | 637 | } |
| | 638 | |
| | 639 | static int ObjectIsPlayersDisc(STRATEGYBLOCK *sbPtr) |
| | 640 | { |
| | 641 | switch(sbPtr->type) |
| | 642 | { |
| | 643 | case I_BehaviourInanimateObject: |
| | 644 | { |
| | 645 | INANIMATEOBJECT_STATUSBLOCK* objStatPtr = sbPtr->dataptr; |
| | 646 | |
| | 647 | /* Make sure the object hasn't already been picked up this frame */ |
| | 648 | if(!sbPtr->please_destroy_me && !objStatPtr->respawnTimer) |
| | 649 | { |
| | 650 | if (objStatPtr->typeId == IOT_Ammo) |
| | 651 | { |
| | 652 | if (objStatPtr->subType == AMMO_PRED_DISC) |
| | 653 | return 1; |
| | 654 | } |
| | 655 | } |
| | 656 | } |
| | 657 | break; |
| | 658 | case I_BehaviourPredatorDisc_SeekTrack: |
| | 659 | { |
| | 660 | /* Erm... just return? */ |
| | 661 | return 1; |
| | 662 | } |
| | 663 | default: |
| | 664 | return 0; |
| | 665 | } |
| | 666 | |
| | 667 | return 0; |
| | 668 | } |
| | 669 | |
| | 670 | static void RemoveAllThisPlayersDiscs() |
| | 671 | { |
| | 672 | int a; |
| | 673 | |
| | 674 | /* All discs that are NOT ghosted must 'belong' to this player. */ |
| | 675 | |
| | 676 | for (a=0; a < NumActiveStBlocks; a++) |
| | 677 | { |
| | 678 | STRATEGYBLOCK *candidate = ActiveStBlockList[a]; |
| | 679 | |
| | 680 | if (candidate->DynPtr && ObjectIsPlayersDisc(candidate)) |
| | 681 | { |
| | 682 | /* Are we the right type? */ |
| | 683 | AddNetMsg_LocalObjectDestroyed(candidate); |
| | 684 | candidate->please_destroy_me = 1; |
| | 685 | } |
| | 686 | } |
| | 687 | } |
| | 688 | |
| | 689 | static void NetPlayerRespawn() |
| | 690 | { |
| | 691 | /* When you're going to respawn... you might change */ |
| | 692 | /* character class, after all. */ |
| | 693 | |
| | 694 | if (PlayerStatus.sound_mouth != SOUND_NOACTIVEINDEX) |
| | 695 | Sound_Stop(PlayerStatus.sound_mouth); |
| | 696 | |
| | 697 | if (PlayerStatus.soundCracklingFire != SOUND_NOACTIVEINDEX) |
| | 698 | Sound_Stop(PlayerStatus.soundCracklingFire); |
| | 699 | |
| | 700 | if (weaponHandle != SOUND_NOACTIVEINDEX) |
| | 701 | Sound_Stop(weaponHandle); |
| | 702 | |
| | 703 | if (predHUDSoundHandle != SOUND_NOACTIVEINDEX) |
| | 704 | Sound_Stop(predHUDSoundHandle); |
| | 705 | |
| | 706 | if (predOVision_SoundHandle != SOUND_NOACTIVEINDEX) |
| | 707 | Sound_Stop(predOVision_SoundHandle); |
| | 708 | |
| | 709 | ConfigurePlayer(); |
| | 710 | //reset the player's elasticity (which gets altered upon death) |
| | 711 | PlayerStatus.sbptr->DynPtr->Elasticity = 0; |
| | 712 | |
| | 713 | TurnOffMultiplayerObserveMode(); |
| | 714 | |
| | 715 | //The player's dropped weapon (if there was one) can now be drawn |
| | 716 | MakePlayersWeaponPickupVisible(); |
| | 717 | RemoveAllThisPlayersDiscs(); |
| | 718 | ChooseLightingModel(); |
| | 719 | } |
| | 720 | |
| | 721 | void ChangeToMarine() |
| | 722 | { |
| | 723 | if (I_Marine != AvP.PlayerType) |
| | 724 | { |
| | 725 | AvP.PlayerType = I_Marine; |
| | 726 | NetPlayerRespawn(); |
| | 727 | netGameData.myCharacterType = netGameData.myNextCharacterType = NGCT_Marine; |
| | 728 | |
| | 729 | //reorient the player |
| | 730 | { |
| | 731 | EULER e; |
| | 732 | MatrixToEuler(&PlayerStatus.sbptr->DynPtr->OrientMat, &e); |
| | 733 | e.EulerX = e.EulerZ = 0; |
| | 734 | |
| | 735 | CreateEulerMatrix(&e, &PlayerStatus.sbptr->DynPtr->OrientMat); |
| | 736 | TransposeMatrixCH(&PlayerStatus.sbptr->DynPtr->OrientMat); |
| | 737 | } |
| | 738 | } |
| | 739 | } |
| | 740 | |
| | 741 | void ChangeToAlien() |
| | 742 | { |
| | 743 | if (I_Alien != AvP.PlayerType) |
| | 744 | { |
| | 745 | AvP.PlayerType = I_Alien; |
| | 746 | NetPlayerRespawn(); |
| | 747 | netGameData.myCharacterType = netGameData.myNextCharacterType = NGCT_Alien; |
| | 748 | } |
| | 749 | } |
| | 750 | |
| | 751 | void ChangeToPredator() |
| | 752 | { |
| | 753 | if (I_Predator != AvP.PlayerType) |
| | 754 | { |
| | 755 | AvP.PlayerType = I_Predator; |
| | 756 | NetPlayerRespawn(); |
| | 757 | netGameData.myCharacterType = netGameData.myNextCharacterType = NGCT_Predator; |
| | 758 | |
| | 759 | { |
| | 760 | EULER e; |
| | 761 | MatrixToEuler(&PlayerStatus.sbptr->DynPtr->OrientMat,&e); |
| | 762 | e.EulerX = e.EulerZ = 0; |
| | 763 | |
| | 764 | CreateEulerMatrix(&e, &PlayerStatus.sbptr->DynPtr->OrientMat); |
| | 765 | TransposeMatrixCH(&PlayerStatus.sbptr->DynPtr->OrientMat); |
| | 766 | } |
| | 767 | } |
| | 768 | } |
| | 769 | |
| | 770 | void ShowAdjacencies() |
| | 771 | { |
| | 772 | /* Utility function... */ |
| | 773 | printf("Adjacencies FROM Player's Module (%s):\n", (*(PlayerStatus.sbptr->containingModule->m_aimodule->m_module_ptrs))->name); |
| | 774 | |
| | 775 | AIMODULE *thisModule = PlayerStatus.sbptr->containingModule->m_aimodule; |
| | 776 | AIMODULE **AdjModuleRefPtr = thisModule->m_link_ptrs; |
| | 777 | |
| | 778 | if(AdjModuleRefPtr) /* check that there is a list of adjacent modules */ |
| | 779 | { |
| | 780 | while(*AdjModuleRefPtr != 0) |
| | 781 | { |
| | 782 | /* Probably want some validity test for the link. */ |
| | 783 | if (AIModuleIsPhysical(*AdjModuleRefPtr)) |
| | 784 | { |
| | 785 | /* Probably a valid link... */ |
| | 786 | if (CheckAdjacencyValidity((*AdjModuleRefPtr),thisModule,0)) |
| | 787 | { |
| | 788 | printf("--AI Module of %s, general.\n",(*((*AdjModuleRefPtr)->m_module_ptrs))->name); |
| | 789 | } |
| | 790 | else if (CheckAdjacencyValidity((*AdjModuleRefPtr),thisModule,1)) |
| | 791 | { |
| | 792 | printf("--AI Module of %s, alien only.\n",(*((*AdjModuleRefPtr)->m_module_ptrs))->name); |
| | 793 | } |
| | 794 | else |
| | 795 | { |
| | 796 | printf("--AI Module of %s, fails validity test!\n",(*((*AdjModuleRefPtr)->m_module_ptrs))->name); |
| | 797 | } |
| | 798 | } |
| | 799 | |
| | 800 | /* next adjacent module reference pointer */ |
| | 801 | AdjModuleRefPtr++; |
| | 802 | } |
| | 803 | } |
| | 804 | |
| | 805 | printf("Adjacencies TO Player's Module:\n"); |
| | 806 | |
| | 807 | AIMODULE *ModuleListPointer = AIModuleArray; |
| | 808 | |
| | 809 | /* go through each aimodule in the environment */ |
| | 810 | int moduleCounter = 0; |
| | 811 | for(; moduleCounter < AIModuleArraySize; moduleCounter++) |
| | 812 | { |
| | 813 | /* get a pointer to the next current module */ |
| | 814 | thisModule = &(ModuleListPointer[moduleCounter]); |
| | 815 | assert(thisModule); |
| | 816 | |
| | 817 | AdjModuleRefPtr = thisModule->m_link_ptrs; |
| | 818 | |
| | 819 | if(AdjModuleRefPtr) /* check that there is a list of adjacent modules */ |
| | 820 | { |
| | 821 | while(*AdjModuleRefPtr != 0) |
| | 822 | { |
| | 823 | /* Probably want some validity test for the link. */ |
| | 824 | if (AIModuleIsPhysical(*AdjModuleRefPtr)) |
| | 825 | { |
| | 826 | /* Is this the target? */ |
| | 827 | if ((*AdjModuleRefPtr) == (PlayerStatus.sbptr->containingModule->m_aimodule)) |
| | 828 | { |
| | 829 | /* Probably a valid link... */ |
| | 830 | if (CheckAdjacencyValidity((*AdjModuleRefPtr),thisModule,0)) |
| | 831 | { |
| | 832 | printf("--AI Module of %s, general.\n",(*(thisModule->m_module_ptrs))->name); |
| | 833 | } |
| | 834 | else if (CheckAdjacencyValidity((*AdjModuleRefPtr),thisModule,1)) |
| | 835 | { |
| | 836 | printf("--AI Module of %s, alien only.\n",(*(thisModule->m_module_ptrs))->name); |
| | 837 | } |
| | 838 | else |
| | 839 | { |
| | 840 | printf("--AI Module of %s, fails validity test!\n",(*(thisModule->m_module_ptrs))->name); |
| | 841 | } |
| | 842 | |
| | 843 | } |
| | 844 | } |
| | 845 | |
| | 846 | /* next adjacent module reference pointer */ |
| | 847 | AdjModuleRefPtr++; |
| | 848 | } |
| | 849 | } |
| | 850 | } |
| | 851 | } |
| | 852 | |
| | 853 | void StartPlayerTaunt() |
| | 854 | { |
| | 855 | if (PlayerStatus.tauntTimer) |
| | 856 | return; |
| | 857 | |
| | 858 | PlayerStatus.tauntTimer = -1; /* Cue to start. */ |
| | 859 | |
| | 860 | if(SinglePlayer == AvP.PlayMode) |
| | 861 | PlayerStatus.tauntTimer = TAUNT_LENGTH; |
| | 862 | |
| | 863 | PlayerStatus.Noise = 1; |
| | 864 | /* An actual noise, too, would probably be good. */ |
| | 865 | |
| | 866 | /* That should make sure we don't get more than one. */ |
| | 867 | if (PlayerStatus.sound_mouth == SOUND_NOACTIVEINDEX) |
| | 868 | { |
| | 869 | switch(AvP.PlayerType) |
| | 870 | { |
| | 871 | case I_Alien: |
| | 872 | { |
| | 873 | PlayAlienSound(0, ASC_Taunt, 0, &PlayerStatus.sound_mouth, &PlayerStatus.sbptr->DynPtr->Position); |
| | 874 | |
| | 875 | if(SinglePlayer != AvP.PlayMode) |
| | 876 | netGameData.myLastScream = ASC_Taunt; |
| | 877 | } |
| | 878 | break; |
| | 879 | case I_Marine: |
| | 880 | { |
| | 881 | PlayMarineScream(0, MSC_Taunt, 0, &PlayerStatus.sound_mouth, NULL); |
| | 882 | |
| | 883 | if(SinglePlayer != AvP.PlayMode) |
| | 884 | netGameData.myLastScream = MSC_Taunt; |
| | 885 | } |
| | 886 | break; |
| | 887 | case I_Predator: |
| | 888 | { |
| | 889 | PlayPredatorSound(0, PSC_Taunt, 0, &PlayerStatus.sound_mouth, NULL); |
| | 890 | |
| | 891 | if(SinglePlayer != AvP.PlayMode) |
| | 892 | netGameData.myLastScream = PSC_Taunt; |
| | 893 | } |
| | 894 | } |
| | 895 | } |
| | 896 | } |
| | 897 | |
| | 898 | static STRATEGYBLOCK *MakePlayerCorpse() |
| | 899 | { |
| | 900 | STRATEGYBLOCK *sbPtr = CreateActiveStrategyBlock(I_BehaviourCorpse); |
| | 901 | |
| | 902 | if(NULL != sbPtr) |
| | 903 | { |
| | 904 | AssignNewSBName(sbPtr); |
| | 905 | |
| | 906 | DYNAMICSBLOCK *dynPtr = sbPtr->DynPtr = AllocateDynamicsBlock(DYNAMICS_TEMPLATE_DEFAULT); |
| | 907 | CORPSEDATABLOCK *corpseData = sbPtr->dataptr = make_new_corpse(I_BehaviourCorpse); |
| | 908 | |
| | 909 | if(!dynPtr || !corpseData) |
| | 910 | { |
| | 911 | RemoveBehaviourStrategy(sbPtr); |
| | 912 | return NULL; |
| | 913 | } |
| | 914 | |
| | 915 | dynPtr->CanClimbStairs = 0; |
| | 916 | dynPtr->IgnoreThePlayer = 1; |
| | 917 | |
| | 918 | dynPtr->Position = dynPtr->PrevPosition = PlayerStatus.sbptr->DynPtr->Position; |
| | 919 | dynPtr->OrientEuler = PlayerStatus.sbptr->DynPtr->OrientEuler; |
| | 920 | CreateEulerMatrix(&dynPtr->OrientEuler, &dynPtr->OrientMat); |
| | 921 | TransposeMatrixCH(&dynPtr->OrientMat); |
| | 922 | |
| | 923 | sbPtr->maintainVisibility = 1; |
| | 924 | sbPtr->containingModule = ModuleFromPosition(&sbPtr->DynPtr->Position, NULL); |
| | 925 | Splice_HModels(&corpseData->HModelController, PlayerStatus.HModelController.section_data); |
| | 926 | |
| | 927 | switch(AvP.PlayerType) |
| | 928 | { |
| | 929 | case I_Marine: |
| | 930 | { |
| | 931 | corpseData->Type = I_BehaviourMarinePlayer; |
| | 932 | corpseData->hltable = GetThisHitLocationTable("marine with pulse rifle"); |
| | 933 | /* Select hierarchy from character's selected weapon. */ |
| | 934 | //while we're at it , also deal with creating the pickupable weapon |
| | 935 | { |
| | 936 | STRATEGYBLOCK* weaponSbPtr = CreateMultiplayerWeaponPickup(&PlayerStatus.sbptr->DynPtr->Position,
PlayerStatus.SelectedWeapon->WeaponIDNumber, 0); |
| | 937 | |
| | 938 | //hide the newly created weapon from this player , until the player respawns |
| | 939 | |
| | 940 | if(weaponSbPtr) |
| | 941 | { |
| | 942 | weaponSbPtr->maintainVisibility = 0; |
| | 943 | weaponSbPtr->DynPtr->IsPickupObject = 0; |
| | 944 | } |
| | 945 | } |
| | 946 | } |
| | 947 | break; |
| | 948 | case I_Alien: |
| | 949 | { |
| | 950 | corpseData->Type = I_BehaviourAlienPlayer; |
| | 951 | corpseData->hltable = GetThisHitLocationTable("alien"); |
| | 952 | } |
| | 953 | break; |
| | 954 | case I_Predator: |
| | 955 | { |
| | 956 | corpseData->Type = I_BehaviourPredatorPlayer; |
| | 957 | corpseData->hltable = GetThisHitLocationTable("predator"); |
| | 958 | } |
| | 959 | } |
| | 960 | |
| | 961 | /* Now fix timer. */ |
| | 962 | corpseData->timer = CORPSE_EXPIRY_TIME; /* Arbitrarily */ |
| | 963 | corpseData->validityTimer = CORPSE_VALIDITY_TIME; |
| | 964 | corpseData->HModelController.Looped = 0; |
| | 965 | //ProveHModel_Far(&corpseData->HModelController, sbPtr); |
| | 966 | MakeCorpseNear(sbPtr); |
| | 967 | //sbPtr->DisplayBlock->ObFlags |= ObFlag_NotVis; |
| | 968 | |
| | 969 | if (PlayerStatus.sbptr->DamageBlock.IsOnFire) |
| | 970 | { |
| | 971 | sbPtr->DamageBlock.IsOnFire = 1; |
| | 972 | corpseData->SoundHandle3 = PlayerStatus.soundCracklingFire; |
| | 973 | PlayerStatus.soundCracklingFire = SOUND_NOACTIVEINDEX; |
| | 974 | } |
| | 975 | } |
| | 976 | |
| | 977 | return sbPtr; |
| | 978 | } |
| | 979 | |
| | 980 | static void PlayerIsDead(const DAMAGE_PROFILE* damage, int multiplier, VECTORCH* incoming) |
| | 981 | { |
| | 982 | if(predHUDSoundHandle != SOUND_NOACTIVEINDEX) |
| | 983 | Sound_Stop(predHUDSoundHandle); |
| | 984 | |
| | 985 | if(predOVision_SoundHandle != SOUND_NOACTIVEINDEX) |
| | 986 | Sound_Stop(predOVision_SoundHandle); |
| | 987 | |
| | 988 | if(weaponHandle != SOUND_NOACTIVEINDEX) |
| | 989 | Sound_Stop(weaponHandle); |
| | 990 | |
| | 991 | if (PlayerStatus.sound_mouth != SOUND_NOACTIVEINDEX) |
| | 992 | Sound_Stop(PlayerStatus.sound_mouth); |
| | 993 | |
| | 994 | switch (AvP.PlayerType) |
| | 995 | { |
| | 996 | case I_Alien: |
| | 997 | PlayAlienSound(0, ASC_Scream_Dying, 0, NULL, NULL); |
| | 998 | break; |
| | 999 | case I_Marine: |
| | 1000 | { |
| | 1001 | if (damage->Id == AMMO_FACEHUGGER) |
| | 1002 | PlayMarineScream(0, MSC_Facehugged, 0, NULL, NULL); |
| | 1003 | else |
| | 1004 | PlayMarineScream(0, MSC_Death, 0, NULL, NULL); |
| | 1005 | } |
| | 1006 | break; |
| | 1007 | case I_Predator: |
| | 1008 | { |
| | 1009 | if (damage->Id == AMMO_FACEHUGGER) |
| | 1010 | PlayPredatorSound(0, PSC_Facehugged, 0, NULL, NULL); |
| | 1011 | else |
| | 1012 | PlayPredatorSound(0, PSC_Scream_Dying, 0, NULL, NULL); |
| | 1013 | } |
| | 1014 | } |
| | 1015 | |
| | 1016 | PlayerStatus.Alive = 0; |
| | 1017 | mission_messages = NULL; |
| | 1018 | mission_messages_timer = 0; |
| | 1019 | |
| | 1020 | /* give player a little bounce */ |
| | 1021 | PlayerStatus.sbptr->DynPtr->Elasticity = 16384; |
| | 1022 | /* but a lot of friction */ |
| | 1023 | // PlayerStatus.sbptr->DynPtr->Friction = 1 << 20; |
| | 1024 | // PlayerStatus.sbptr->DynPtr->Mass = 1 << 20; |
| | 1025 | |
| | 1026 | /* cancel any velocity */ |
| | 1027 | PlayerStatus.sbptr->DynPtr->LinVelocity.vx = PlayerStatus.sbptr->DynPtr->LinVelocity.vy = PlayerStatus.sbptr->DynPtr->LinVelocity.vz = 0; |
| | 1028 | |
| | 1029 | deathFadeLevel = ONE_FIXED; |
| | 1030 | |
| | 1031 | PlayerStatus.sbptr->DynPtr->UseStandardGravity = 1; |
| | 1032 | |
| | 1033 | if(SinglePlayer != AvP.PlayMode) |
| | 1034 | { |
| | 1035 | STRATEGYBLOCK *MyCorpse = MakePlayerCorpse(); |
| | 1036 | AddNetMsg_PlayerKilled((*((int *)(&(MyCorpse->SBname[4])))), damage); |
| | 1037 | |
| | 1038 | if(damage) |
| | 1039 | { |
| | 1040 | if (damage->Id == AMMO_ALIEN_BITE_KILLSECTION) |
| | 1041 | Sound_Play(SID_ALIEN_JAW_ATTACK,"d", &PlayerStatus.sbptr->DynPtr->Position); |
| | 1042 | } |
| | 1043 | /*---------------------------------** |
| | 1044 | ** Choose death anim sequence ** |
| | 1045 | **---------------------------------*/ |
| | 1046 | { |
| | 1047 | int deathId; |
| | 1048 | switch(AvP.PlayerType) |
| | 1049 | { |
| | 1050 | case I_Marine: |
| | 1051 | deathId = Deduce_PlayerMarineDeathSequence(&PlayerStatus.HModelController, damage, multiplier, incoming); |
| | 1052 | break; |
| | 1053 | case I_Alien: |
| | 1054 | deathId = Deduce_PlayerAlienDeathSequence(&PlayerStatus.HModelController, damage, multiplier, incoming); |
| | 1055 | break; |
| | 1056 | case I_Predator: |
| | 1057 | deathId = Deduce_PlayerPredatorDeathSequence(&PlayerStatus.HModelController, damage, multiplier ,incoming); |
| | 1058 | } |
| | 1059 | //apply the animation |
| | 1060 | ApplyCorpseDeathAnim(MyCorpse, deathId); |
| | 1061 | //tell everyone else about the chosen death |
| | 1062 | AddNetMsg_PlayerDeathAnim(deathId, *(int*)&MyCorpse->SBname[4]); |
| | 1063 | } |
| | 1064 | |
| | 1065 | //does this death require a change in character type? |
| | 1066 | if(netGameData.gameType == NGT_LastManStanding) |
| | 1067 | { |
| | 1068 | //Am I a marine or predator? |
| | 1069 | if(AvP.PlayerType != I_Alien) |
| | 1070 | { |
| | 1071 | //was I killed by an alien? |
| | 1072 | if(myNetworkKillerId && myNetworkKillerId != AVPDPNetID) |
| | 1073 | { |
| | 1074 | int killer_index = PlayerIdInPlayerList(myNetworkKillerId); |
| | 1075 | |
| | 1076 | assert(killer_index != NET_IDNOTINPLAYERLIST); |
| | 1077 | |
| | 1078 | if(netGameData.playerData[killer_index].characterType == NGCT_Alien) |
| | 1079 | { |
| | 1080 | //set the next character to be an alien then |
| | 1081 | netGameData.myNextCharacterType = NGCT_Alien; |
| | 1082 | } |
| | 1083 | } |
| | 1084 | else |
| | 1085 | { |
| | 1086 | //suicide , so become an alien anyway |
| | 1087 | netGameData.myNextCharacterType = NGCT_Alien; |
| | 1088 | } |
| | 1089 | } |
| | 1090 | } |
| | 1091 | else if(netGameData.gameType == NGT_PredatorTag || netGameData.gameType == NGT_AlienTag) |
| | 1092 | { |
| | 1093 | //we may need to change character |
| | 1094 | extern void SpeciesTag_DetermineMyNextCharacterType(); |
| | 1095 | SpeciesTag_DetermineMyNextCharacterType(); |
| | 1096 | } |
| | 1097 | } |
| | 1098 | else |
| | 1099 | { |
| | 1100 | SoundSys_FadeOut(); |
| | 1101 | } |
| | 1102 | |
| | 1103 | if (PlayerStatus.soundCracklingFire != SOUND_NOACTIVEINDEX) |
| | 1104 | Sound_Stop(PlayerStatus.soundCracklingFire); |
| | 1105 | |
| | 1106 | DisengageGrapplingHook(); |
| | 1107 | } |
| | 1108 | |
| | 1109 | static void ModifyHeadOrientation() |
| | 1110 | { |
| | 1111 | #define TILT_THRESHOLD 128 |
| | 1112 | |
| | 1113 | if (!PlayerStatus.Alive && !MultiplayerObservedPlayer) |
| | 1114 | { |
| | 1115 | int decay = NormalFrameTime >> 6; |
| | 1116 | |
| | 1117 | HeadOrientation.EulerX &= 4095; |
| | 1118 | HeadOrientation.EulerX -= decay; |
| | 1119 | |
| | 1120 | if(HeadOrientation.EulerX < 3072) |
| | 1121 | HeadOrientation.EulerX = 3072; |
| | 1122 | } |
| | 1123 | else |
| | 1124 | { |
| | 1125 | int decay = NormalFrameTime >> 8; |
| | 1126 | |
| | 1127 | if(HeadOrientation.EulerX > 2048) |
| | 1128 | { |
| | 1129 | if (HeadOrientation.EulerX < 4096 - TILT_THRESHOLD) |
| | 1130 | HeadOrientation.EulerX = 4096 - TILT_THRESHOLD; |
| | 1131 | |
| | 1132 | HeadOrientation.EulerX += decay; |
| | 1133 | |
| | 1134 | if(HeadOrientation.EulerX > 4095) |
| | 1135 | HeadOrientation.EulerX = 0; |
| | 1136 | } |
| | 1137 | else |
| | 1138 | { |
| | 1139 | if (HeadOrientation.EulerX > TILT_THRESHOLD) |
| | 1140 | HeadOrientation.EulerX = TILT_THRESHOLD; |
| | 1141 | |
| | 1142 | HeadOrientation.EulerX -= decay; |
| | 1143 | |
| | 1144 | if(HeadOrientation.EulerX < 0) |
| | 1145 | HeadOrientation.EulerX = 0; |
| | 1146 | } |
| | 1147 | |
| | 1148 | if(HeadOrientation.EulerY > 2048) |
| | 1149 | { |
| | 1150 | if (HeadOrientation.EulerY < 4096 - TILT_THRESHOLD) |
| | 1151 | HeadOrientation.EulerY = 4096 - TILT_THRESHOLD; |
| | 1152 | |
| | 1153 | HeadOrientation.EulerY += decay; |
| | 1154 | |
| | 1155 | if(HeadOrientation.EulerY > 4095) |
| | 1156 | HeadOrientation.EulerY = 0; |
| | 1157 | } |
| | 1158 | else |
| | 1159 | { |
| | 1160 | if (HeadOrientation.EulerY > TILT_THRESHOLD) |
| | 1161 | HeadOrientation.EulerY = TILT_THRESHOLD; |
| | 1162 | |
| | 1163 | HeadOrientation.EulerY -= decay; |
| | 1164 | |
| | 1165 | if(HeadOrientation.EulerY < 0) |
| | 1166 | HeadOrientation.EulerY = 0; |
| | 1167 | } |
| | 1168 | |
| | 1169 | if(HeadOrientation.EulerZ > 2048) |
| | 1170 | { |
| | 1171 | if (HeadOrientation.EulerZ < 4096 - TILT_THRESHOLD) |
| | 1172 | HeadOrientation.EulerZ = 4096 - TILT_THRESHOLD; |
| | 1173 | |
| | 1174 | HeadOrientation.EulerZ += decay; |
| | 1175 | |
| | 1176 | if(HeadOrientation.EulerZ > 4095) |
| | 1177 | HeadOrientation.EulerZ = 0; |
| | 1178 | } |
| | 1179 | else |
| | 1180 | { |
| | 1181 | if (HeadOrientation.EulerZ > TILT_THRESHOLD) |
| | 1182 | HeadOrientation.EulerZ = TILT_THRESHOLD; |
| | 1183 | |
| | 1184 | HeadOrientation.EulerZ -= decay; |
| | 1185 | |
| | 1186 | if(HeadOrientation.EulerZ < 0) |
| | 1187 | HeadOrientation.EulerZ = 0; |
| | 1188 | } |
| | 1189 | } |
| | 1190 | } |
| | 1191 | |
| | 1192 | static void InteriorType_Body() |
| | 1193 | { |
| | 1194 | static int verticalSpeed = 0; |
| | 1195 | static int zAxisTilt = 0; |
| | 1196 | |
| | 1197 | { |
| | 1198 | VECTORCH offset = { 0, 0, 0 }; |
| | 1199 | |
| | 1200 | switch(AvP.PlayerType) |
| | 1201 | { |
| | 1202 | case I_Alien: |
| | 1203 | //offset.vy = CollisionExtents[(PlayerStatus.Crouching ? CE_ALIEN_CROUCH : CE_ALIEN)].StandingTop; |
| | 1204 | offset.vy = CollisionExtents[CE_ALIEN].StandingTop; |
| | 1205 | break; |
| | 1206 | case I_Marine: |
| | 1207 | offset.vy = (PlayerStatus.Crouching ? CollisionExtents[CE_MARINE].CrouchingTop : CollisionExtents[CE_MARINE].StandingTop); |
| | 1208 | break; |
| | 1209 | case I_Predator: |
| | 1210 | offset.vy = (PlayerStatus.Crouching ? CollisionExtents[CE_PREDATOR].CrouchingTop : CollisionExtents[CE_PREDATOR].StandingTop); |
| | 1211 | } |
| | 1212 | |
| | 1213 | if(PlayerStatus.FirstPersonView) |
| | 1214 | { |
| | 1215 | ModifyHeadOrientation(); |
| | 1216 | //if (CHEATMODE_LANDOFTHEGIANTS == UserProfile.active_bonus) offset.vy /= 4; |
| | 1217 | } |
| | 1218 | else |
| | 1219 | { |
| | 1220 | if(1) |
| | 1221 | { |
| | 1222 | offset.vz = -CollisionExtents[AvP.PlayerType].CollisionRadius * 3; |
| | 1223 | offset.vy = PlayerStatus.Crouching ? CollisionExtents[AvP.PlayerType].CrouchingTop : CollisionExtents[AvP.PlayerType].StandingTop; |
| | 1224 | offset.vy -= 1500; |
| | 1225 | } |
| | 1226 | else if(1) |
| | 1227 | { |
| | 1228 | offset.vz = -CollisionExtents[AvP.PlayerType].CollisionRadius; |
| | 1229 | offset.vy = PlayerStatus.Crouching ? CollisionExtents[AvP.PlayerType].CrouchingTop : CollisionExtents[AvP.PlayerType].StandingTop; |
| | 1230 | offset.vy -= 50; |
| | 1231 | } |
| | 1232 | else // first person view with model |
| | 1233 | { |
| | 1234 | offset.vz = CollisionExtents[AvP.PlayerType].CollisionRadius; |
| | 1235 | offset.vy = PlayerStatus.Crouching ? CollisionExtents[AvP.PlayerType].CrouchingTop : CollisionExtents[AvP.PlayerType].StandingTop; |
| | 1236 | offset.vy += 100; |
| | 1237 | } |
| | 1238 | } |
| | 1239 | |
| | 1240 | if (!PlayerStatus.Alive && !MultiplayerObservedPlayer) |
| | 1241 | { |
| | 1242 | offset.vy = MUL_FIXED(deathFadeLevel * 4 - 3 * ONE_FIXED, offset.vy); |
| | 1243 | |
| | 1244 | if (offset.vy > -100) |
| | 1245 | offset.vy = -100; |
| | 1246 | } |
| | 1247 | |
| | 1248 | //offset.vy += verticalSpeed / 16+200; |
| | 1249 | |
| | 1250 | RotateVector(&offset, &PlayerStatus.DisplayBlock->ObMat); |
| | 1251 | Global_VDB.VDB_World.vx += offset.vx; |
| | 1252 | Global_VDB.VDB_World.vy += offset.vy; |
| | 1253 | Global_VDB.VDB_World.vz += offset.vz; |
| | 1254 | } |
| | 1255 | |
| | 1256 | { |
| | 1257 | EULER orientation = HeadOrientation; |
| | 1258 | |
| | 1259 | orientation.EulerZ += zAxisTilt >> 8; |
| | 1260 | orientation.EulerZ &= 4095; |
| | 1261 | |
| | 1262 | if (CHEATMODE_NAUSEA == UserProfile.active_bonus) |
| | 1263 | { |
| | 1264 | orientation.EulerZ = (orientation.EulerZ + GetSin((CloakingPhase/2) & 4095) / 256) & 4095; |
| | 1265 | orientation.EulerX = (orientation.EulerX + GetSin((CloakingPhase/2+500) & 4095) / 512) & 4095; |
| | 1266 | orientation.EulerY = (orientation.EulerY + GetSin((CloakingPhase/3+800) & 4095) / 512) & 4095; |
| | 1267 | } |
| | 1268 | // The next test drops the matrix multiply if the orientation is close to zero |
| | 1269 | // There is an inaccuracy problem with the Z angle at this point |
| | 1270 | |
| | 1271 | if (orientation.EulerX || orientation.EulerY || (orientation.EulerZ > 1 && orientation.EulerZ < 4095)) |
| | 1272 | { |
| | 1273 | MATRIXCH matrix; |
| | 1274 | CreateEulerMatrix(&orientation, &matrix); |
| | 1275 | MatrixMultiply(&Global_VDB.VDB_Mat, &matrix, &Global_VDB.VDB_Mat); |
| | 1276 | } |
| | 1277 | } |
| | 1278 | |
| | 1279 | { |
| | 1280 | VECTORCH relativeVelocity; |
| | 1281 | |
| | 1282 | /* get subject's total velocity */ |
| | 1283 | { |
| | 1284 | DYNAMICSBLOCK *dynPtr = PlayerStatus.sbptr->DynPtr; |
| | 1285 | /* make world to local matrix */ |
| | 1286 | MATRIXCH worldToLocalMatrix = PlayerStatus.DisplayBlock->ObMat; |
| | 1287 | |
| | 1288 | TransposeMatrixCH(&worldToLocalMatrix); |
| | 1289 | |
| | 1290 | relativeVelocity.vx = dynPtr->Position.vx - dynPtr->PrevPosition.vx; |
| | 1291 | relativeVelocity.vy = dynPtr->Position.vy - dynPtr->PrevPosition.vy; |
| | 1292 | relativeVelocity.vz = dynPtr->Position.vz - dynPtr->PrevPosition.vz; |
| | 1293 | /* rotate into object space */ |
| | 1294 | |
| | 1295 | RotateVector(&relativeVelocity, &worldToLocalMatrix); |
| | 1296 | } |
| | 1297 | |
| | 1298 | { |
| | 1299 | int targetingSpeed = 10 * NormalFrameTime; |
| | 1300 | |
| | 1301 | /* KJL 14:08:50 09/20/96 - the targeting is FRI, but care has to be taken |
| | 1302 | at very low frame rates to ensure that you can't overshoot */ |
| | 1303 | if (targetingSpeed > 65536) |
| | 1304 | targetingSpeed = 65536; |
| | 1305 | |
| | 1306 | zAxisTilt += MUL_FIXED ( DIV_FIXED ( MUL_FIXED(relativeVelocity.vx, PlayerStatus.LeanScale), NormalFrameTime )-zAxisTilt, targetingSpeed ); |
| | 1307 | |
| | 1308 | { |
| | 1309 | static int previousVerticalSpeed = 0; |
| | 1310 | int difference = 0; |
| | 1311 | |
| | 1312 | if (relativeVelocity.vy >= 0) |
| | 1313 | difference = DIV_FIXED ( previousVerticalSpeed - relativeVelocity.vy, NormalFrameTime ); |
| | 1314 | |
| | 1315 | if (verticalSpeed < difference) |
| | 1316 | verticalSpeed = difference; |
| | 1317 | |
| | 1318 | if(verticalSpeed > 150*16) |
| | 1319 | verticalSpeed = 150*16; |
| | 1320 | |
| | 1321 | verticalSpeed -= NormalFrameTime>>2; |
| | 1322 | |
| | 1323 | if (verticalSpeed < 0) |
| | 1324 | verticalSpeed = 0; |
| | 1325 | |
| | 1326 | previousVerticalSpeed = relativeVelocity.vy; |
| | 1327 | } |
| | 1328 | } |
| | 1329 | } |
| | 1330 | } |
| | 1331 | |
| | 1332 | void PlayerIsDamaged(const DAMAGE_PROFILE *damage, int multiplier, VECTORCH* incoming) |
| | 1333 | { |
| | 1334 | int deltaHealth = PlayerStatus.Health - PlayerStatus.sbptr->DamageBlock.Health; |
| | 1335 | int deltaArmour = PlayerStatus.Armour - PlayerStatus.sbptr->DamageBlock.Armour; |
| | 1336 | |
| | 1337 | if (PlayerStatus.Alive) |
| | 1338 | { |
| | 1339 | CurrentGameStats_DamageTaken(deltaHealth, deltaArmour); |
| | 1340 | |
| | 1341 | { |
| | 1342 | int maxTilt = deltaHealth >> 12; |
| | 1343 | int halfTilt = maxTilt / 2; |
| | 1344 | |
| | 1345 | if (maxTilt) |
| | 1346 | { |
| | 1347 | HeadOrientation.EulerX = (FastRandom()%maxTilt)-halfTilt; |
| | 1348 | HeadOrientation.EulerY = (FastRandom()%maxTilt)-halfTilt; |
| | 1349 | HeadOrientation.EulerZ = (FastRandom()%maxTilt)-halfTilt; |
| | 1350 | |
| | 1351 | if (HeadOrientation.EulerX < 0) HeadOrientation.EulerX += 4096; |
| | 1352 | if (HeadOrientation.EulerY < 0) HeadOrientation.EulerY += 4096; |
| | 1353 | if (HeadOrientation.EulerZ < 0) HeadOrientation.EulerZ += 4096; |
| | 1354 | } |
| | 1355 | } |
| | 1356 | |
| | 1357 | if ((PlayerStatus.sound_mouth == SOUND_NOACTIVEINDEX) && (deltaHealth || deltaArmour)) |
| | 1358 | { |
| | 1359 | int pitch = (FastRandom() & 255) - 128; |
| | 1360 | |
| | 1361 | switch (AvP.PlayerType) |
| | 1362 | { |
| | 1363 | case I_Alien: |
| | 1364 | { |
| | 1365 | if (!damage->Impact && !damage->Cutting && !damage->Penetrative && damage->Fire &&
!damage->Electrical && !damage->Acid) |
| | 1366 | { |
| | 1367 | PlayAlienSound(0, ASC_PC_OnFire, pitch, &PlayerStatus.sound_mouth, NULL); |
| | 1368 | |
| | 1369 | if(SinglePlayer != AvP.PlayMode) |
| | 1370 | netGameData.myLastScream = ASC_PC_OnFire; |
| | 1371 | } |
| | 1372 | else |
| | 1373 | { |
| | 1374 | PlayAlienSound(0, ASC_Scream_Hurt, pitch, &PlayerStatus.sound_mouth, NULL); |
| | 1375 | |
| | 1376 | if(SinglePlayer != AvP.PlayMode) |
| | 1377 | netGameData.myLastScream = ASC_Scream_Hurt; |
| | 1378 | } |
| | 1379 | } |
| | 1380 | break; |
| | 1381 | case I_Marine: |
| | 1382 | { |
| | 1383 | /* Alert marines, pretty much whoever you are. */ |
| | 1384 | PointAlert(3, &PlayerStatus.sbptr->DynPtr->Position); |
| | 1385 | |
| | 1386 | switch(damage->Id) |
| | 1387 | { |
| | 1388 | case AMMO_FACEHUGGER: |
| | 1389 | PlayMarineScream(0, MSC_Facehugged, pitch, &PlayerStatus.sound_mouth, NULL); |
| | 1390 | break; |
| | 1391 | case AMMO_FALLINGDAMAGE: |
| | 1392 | PlayMarineScream(0, MSC_Falling, pitch, &PlayerStatus.sound_mouth, NULL); |
| | 1393 | break; |
| | 1394 | default: |
| | 1395 | { |
| | 1396 | if( !damage->Impact && !damage->Cutting && !damage->Penetrative && !damage->Electrical) |
| | 1397 | { |
| | 1398 | if (damage->Acid) |
| | 1399 | { |
| | 1400 | if (!damage->Fire) |
| | 1401 | { |
| | 1402 | PlayMarineScream(0, MSC_Acid, pitch, &PlayerStatus.sound_mouth, NULL); |
| | 1403 | |
| | 1404 | if(SinglePlayer != AvP.PlayMode) |
| | 1405 | netGameData.myLastScream = MSC_Acid; |
| | 1406 | break; |
| | 1407 | } |
| | 1408 | } |
| | 1409 | else if (damage->Fire) |
| | 1410 | { |
| | 1411 | PlayMarineScream(0, MSC_PC_OnFire, pitch, &PlayerStatus.sound_mouth, NULL); |
| | 1412 | |
| | 1413 | if(SinglePlayer != AvP.PlayMode) |
| | 1414 | netGameData.myLastScream = MSC_PC_OnFire; |
| | 1415 | break; |
| | 1416 | } |
| | 1417 | |
| | 1418 | } |
| | 1419 | |
| | 1420 | PlayMarineScream(0, MSC_Pain, pitch, &PlayerStatus.sound_mouth, NULL); |
| | 1421 | |
| | 1422 | if(SinglePlayer != AvP.PlayMode) |
| | 1423 | netGameData.myLastScream = MSC_Pain; |
| | 1424 | } |
| | 1425 | } |
| | 1426 | } |
| | 1427 | break; |
| | 1428 | case I_Predator: |
| | 1429 | { |
| | 1430 | if (damage->Id == AMMO_FACEHUGGER) |
| | 1431 | { |
| | 1432 | PlayPredatorSound(0, PSC_Facehugged, pitch, &PlayerStatus.sound_mouth, NULL); |
| | 1433 | } |
| | 1434 | else |
| | 1435 | { |
| | 1436 | if (!damage->Impact && !damage->Cutting && !damage->Penetrative && !damage->Electrical) |
| | 1437 | { |
| | 1438 | if (!damage->Fire) |
| | 1439 | { |
| | 1440 | if (damage->Acid) |
| | 1441 | { |
| | 1442 | PlayPredatorSound(0, PSC_Acid, pitch, &PlayerStatus.sound_mouth, NULL); |
| | 1443 | |
| | 1444 | if(SinglePlayer != AvP.PlayMode) |
| | 1445 | netGameData.myLastScream = PSC_Acid; |
| | 1446 | break; |
| | 1447 | } |
| | 1448 | } |
| | 1449 | else if (!damage->Acid) |
| | 1450 | { |
| | 1451 | PlayPredatorSound(0, PSC_PC_OnFire, pitch, &PlayerStatus.sound_mouth, NULL); |
| | 1452 | |
| | 1453 | if(SinglePlayer != AvP.PlayMode) |
| | 1454 | netGameData.myLastScream = PSC_PC_OnFire; |
| | 1455 | break; |
| | 1456 | } |
| | 1457 | } |
| | 1458 | |
| | 1459 | PlayPredatorSound(0, PSC_Scream_Hurt, pitch, &PlayerStatus.sound_mouth, NULL); |
| | 1460 | |
| | 1461 | if(SinglePlayer != AvP.PlayMode) |
| | 1462 | netGameData.myLastScream = PSC_Scream_Hurt; |
| | 1463 | } |
| | 1464 | } |
| | 1465 | default: |
| | 1466 | break; |
| | 1467 | } |
| | 1468 | |
| | 1469 | PlayerStatus.Noise = 1; |
| | 1470 | } |
| | 1471 | |
| | 1472 | { |
| | 1473 | /* Compute scaled deltaHealth... */ |
| | 1474 | int scaled_DeltaHealth = MUL_FIXED(deltaHealth, 100); |
| | 1475 | scaled_DeltaHealth = DIV_FIXED(scaled_DeltaHealth, PlayerStatus.StartingHealth); |
| | 1476 | |
| | 1477 | if (scaled_DeltaHealth > PlayerStatus.DamagedOverlayIntensity) |
| | 1478 | PlayerStatus.DamagedOverlayIntensity = scaled_DeltaHealth; |
| | 1479 | } |
| | 1480 | |
| | 1481 | /* |
| | 1482 | if (deltaHealth > ONE_FIXED) |
| | 1483 | { |
| | 1484 | VECTORCH abovePosition = Global_VDB.VDB_World; |
| | 1485 | abovePosition.vy -= 1000; |
| | 1486 | |
| | 1487 | switch (AvP.PlayerType) |
| | 1488 | { |
| | 1489 | case I_Alien: |
| | 1490 | MakeBloodExplosion(&Global_VDB.VDB_World, 127, &abovePosition, deltaHealth/ONE_FIXED, PARTICLE_ALIEN_BLOOD); |
| | 1491 | break; |
| | 1492 | case I_Marine: |
| | 1493 | MakeBloodExplosion(&Global_VDB.VDB_World, 127, &abovePosition, deltaHealth/ONE_FIXED, PARTICLE_HUMAN_BLOOD); |
| | 1494 | break; |
| | 1495 | case I_Predator: |
| | 1496 | MakeBloodExplosion(&Global_VDB.VDB_World, 127, &abovePosition, deltaHealth/ONE_FIXED, PARTICLE_PREDATOR_BLOOD); |
| | 1497 | } |
| | 1498 | } |
| | 1499 | */ |
| | 1500 | |
| | 1501 | if (PlayerStatus.sbptr->DamageBlock.Health <= 0) |
| | 1502 | PlayerIsDead(damage, multiplier, incoming); |
| | 1503 | |
| | 1504 | PlayerStatus.Health = PlayerStatus.sbptr->DamageBlock.Health; |
| | 1505 | PlayerStatus.Armour = PlayerStatus.sbptr->DamageBlock.Armour; |
| | 1506 | } |
| | 1507 | } |
| | 1508 | |
| | 1509 | static void NetPlayerDeadProcessing() |
| | 1510 | { |
| | 1511 | /* call the read input function so that we can still respawn/quit, etc */ |
| | 1512 | |
| | 1513 | /* check for re-spawn */ |
| | 1514 | if(Keyboard_input_operate()) |
| | 1515 | { |
| | 1516 | if(AreThereAnyLivesLeft()) |
| | 1517 | { |
| | 1518 | //check for change of character |
| | 1519 | if(netGameData.myCharacterType != netGameData.myNextCharacterType) |
| | 1520 | { |
| | 1521 | switch(netGameData.myNextCharacterType) |
| | 1522 | { |
| | 1523 | case NGCT_Marine: |
| | 1524 | ChangeToMarine(); |
| | 1525 | break; |
| | 1526 | case NGCT_Alien: |
| | 1527 | ChangeToAlien(); |
| | 1528 | break; |
| | 1529 | case NGCT_Predator: |
| | 1530 | ChangeToPredator(); |
| | 1531 | break; |
| | 1532 | default: |
| | 1533 | assert("dodgy character type"==0); |
| | 1534 | break; |
| | 1535 | } |
| | 1536 | |
| | 1537 | netGameData.myCharacterType = netGameData.myNextCharacterType; |
| | 1538 | } |
| | 1539 | else |
| | 1540 | { |
| | 1541 | NetPlayerRespawn(); |
| | 1542 | } |
| | 1543 | |
| | 1544 | /* dynamics block stuff... */ |
| | 1545 | { |
| | 1546 | EULER zeroEuler = {0,0,0}; |
| | 1547 | VECTORCH zeroVec = {0,0,0}; |
| | 1548 | DYNAMICSBLOCK *dynPtr = PlayerStatus.sbptr->DynPtr; |
| | 1549 | |
| | 1550 | dynPtr->Position = zeroVec; |
| | 1551 | dynPtr->OrientEuler = zeroEuler; |
| | 1552 | dynPtr->LinVelocity = zeroVec; |
| | 1553 | dynPtr->LinImpulse = zeroVec; |
| | 1554 | |
| | 1555 | CreateEulerMatrix(&dynPtr->OrientEuler, &dynPtr->OrientMat); |
| | 1556 | TransposeMatrixCH(&dynPtr->OrientMat); |
| | 1557 | |
| | 1558 | //Need to get rid of collisions for this frame , so player doesn't pick up |
| | 1559 | //his dropped weapon when he respawns. |
| | 1560 | dynPtr->CollisionReportPtr = 0; |
| | 1561 | } |
| | 1562 | |
| | 1563 | TeleportNetPlayerToAStartingPosition(0); |
| | 1564 | } |
| | 1565 | else |
| | 1566 | { |
| | 1567 | //no lives left , so have to act as an observer |
| | 1568 | GetNextMultiplayerObservedPlayer(); |
| | 1569 | |
| | 1570 | //The player's dropped weapon (if there was one) can now be drawn |
| | 1571 | MakePlayersWeaponPickupVisible(); |
| | 1572 | } |
| | 1573 | } |
| | 1574 | } |
| | 1575 | |
| | 1576 | void PlayerBehaviour() |
| | 1577 | { |
| | 1578 | PlayerStatus.Noise = 0; |
| | 1579 | PlayerStatus.sbptr->containingModule = ModuleFromPosition(&PlayerStatus.DisplayBlock->ObWorld, PlayerStatus.sbptr->containingModule); |
| | 1580 | |
| | 1581 | { |
| | 1582 | int cos = GetCos(PlayerStatus.ViewPanX); |
| | 1583 | int sin = GetSin(PlayerStatus.ViewPanX); |
| | 1584 | MATRIXCH mat = { 0 }; |
| | 1585 | |
| | 1586 | Global_VDB.VDB_World = PlayerStatus.DisplayBlock->ObWorld; |
| | 1587 | |
| | 1588 | mat.mat11 = ONE_FIXED; |
| | 1589 | mat.mat22 = cos; |
| | 1590 | mat.mat23 = -sin; |
| | 1591 | mat.mat32 = sin; |
| | 1592 | mat.mat33 = cos; |
| | 1593 | |
| | 1594 | MatrixMultiply(&PlayerStatus.DisplayBlock->ObMat, &mat, &Global_VDB.VDB_Mat); |
| | 1595 | TransposeMatrixCH(&Global_VDB.VDB_Mat); |
| | 1596 | } |
| | 1597 | |
| | 1598 | InteriorType_Body(); |
| | 1599 | MNormalise(&PlayerStatus.sbptr->DynPtr->OrientMat); |
| | 1600 | |
| | 1601 | /* |
| | 1602 | { |
| | 1603 | extern int GlobalFrameCounter; |
| | 1604 | DYNAMICSBLOCK *dynPtr = PlayerStatus.sbptr->DynPtr; |
| | 1605 | printf("player Impulse at %d,%d,%d\n", dynPtr->LinImpulse.vx, dynPtr->LinImpulse.vy, dynPtr->LinImpulse.vz); |
| | 1606 | |
| | 1607 | printf ( |
| | 1608 | "Dynamics Logging: frame %d\nDL: player's Position %d,%d,%d\nDL: player's Displacement %d,%d,%d\nDL: NormalFrameTime %d\n", |
| | 1609 | GlobalFrameCounter, |
| | 1610 | dynPtr->Position.vx, dynPtr->Position.vy, dynPtr->Position.vz, |
| | 1611 | dynPtr->Displacement.vx, dynPtr->Displacement.vy, dynPtr->Displacement.vz, |
| | 1612 | NormalFrameTime); |
| | 1613 | |
| | 1614 | } |
| | 1615 | */ |
| | 1616 | if (PlayerStatus.Alive) |
| | 1617 | { |
| | 1618 | if (PlayerStatus.tauntTimer) |
| | 1619 | { |
| | 1620 | PlayerStatus.tauntTimer -= NormalFrameTime; |
| | 1621 | |
| | 1622 | if (PlayerStatus.tauntTimer < 0) |
| | 1623 | PlayerStatus.tauntTimer = 0; |
| | 1624 | |
| | 1625 | switch(AvP.PlayerType) |
| | 1626 | { |
| | 1627 | case I_Alien: |
| | 1628 | { |
| | 1629 | extern EULER HeadOrientation; |
| | 1630 | int ex = MUL_FIXED( 64, GetSin(((PlayerStatus.tauntTimer >> 6) & wrap360))); |
| | 1631 | int ey = MUL_FIXED(128, GetSin(((PlayerStatus.tauntTimer >> 5) & wrap360))); |
| | 1632 | int ez = MUL_FIXED(-64, GetSin(((PlayerStatus.tauntTimer >> 5) & wrap360))); |
| | 1633 | |
| | 1634 | ex &= wrap360; |
| | 1635 | ey &= wrap360; |
| | 1636 | ez &= wrap360; |
| | 1637 | |
| | 1638 | HeadOrientation.EulerX = ex; |
| | 1639 | HeadOrientation.EulerY = ey; |
| | 1640 | HeadOrientation.EulerZ = ez; |
| | 1641 | } |
| | 1642 | default: |
| | 1643 | break; |
| | 1644 | } |
| | 1645 | } |
| | 1646 | |
| | 1647 | handle_user_input(); |
| | 1648 | PlayerStatus.weapon_func(); |
| | 1649 | |
| | 1650 | if(SinglePlayer != AvP.PlayMode) |
| | 1651 | { |
| | 1652 | if(PlayerStatus.invulnerabilityTimer) |
| | 1653 | { |
| | 1654 | PlayerStatus.sbptr->DamageBlock.IsOnFire = 0; |
| | 1655 | PlayerStatus.invulnerabilityTimer -= NormalFrameTime; |
| | 1656 | |
| | 1657 | if(PlayerStatus.invulnerabilityTimer < 0) |
| | 1658 | PlayerStatus.invulnerabilityTimer = 0; |
| | 1659 | |
| | 1660 | //lose invulnerability if player is firing |
| | 1661 | |
| | 1662 | if(PlayerStatus.InputRequests.Rqst_FirePrimaryWeapon) |
| | 1663 | { |
| | 1664 | if(WEAPON_PRED_MEDICOMP != PlayerStatus.SelectedWeapon->WeaponIDNumber) |
| | 1665 | PlayerStatus.invulnerabilityTimer = 0; |
| | 1666 | } |
| | 1667 | |
| | 1668 | if(PlayerStatus.InputRequests.Rqst_FireSecondaryWeapon) |
| | 1669 | { |
| | 1670 | //not many weapons have an offensive secondary fire |
| | 1671 | |
| | 1672 | switch(PlayerStatus.SelectedWeapon->WeaponIDNumber) |
| | 1673 | { |
| | 1674 | case WEAPON_PULSERIFLE: |
| | 1675 | case WEAPON_CUDGEL: |
| | 1676 | case WEAPON_MARINE_PISTOL: |
| | 1677 | case WEAPON_TWO_PISTOLS: |
| | 1678 | case WEAPON_PRED_WRISTBLADE: |
| | 1679 | case WEAPON_ALIEN_CLAW: |
| | 1680 | PlayerStatus.invulnerabilityTimer = 0; |
| | 1681 | default: |
| | 1682 | break; |
| | 1683 | } |
| | 1684 | } |
| | 1685 | |
| | 1686 | PlayerStatus.sbptr->DamageBlock.Indestructable = PlayerStatus.invulnerabilityTimer; |
| | 1687 | } |
| | 1688 | } |
| | 1689 | else |
| | 1690 | { |
| | 1691 | CurrentGameStats_VisionMode(PlayerStatus.VisionMode); |
| | 1692 | CurrentGameStats_UsingWeapon(PlayerStatus.SelectedWeaponSlot); |
| | 1693 | CurrentGameStats_SpeedSample(Approximate3dMagnitude(&PlayerStatus.sbptr->DynPtr->LinVelocity), NormalFrameTime); |
| | 1694 | } |
| | 1695 | |
| | 1696 | //printf("PlayerLight %d\n", PlayerStatus.CurrentLightAtPlayer); |
| | 1697 | } |
| | 1698 | else |
| | 1699 | { |
| | 1700 | extern int RealFrameTime; |
| | 1701 | |
| | 1702 | if(SinglePlayer == AvP.PlayMode) |
| | 1703 | { |
| | 1704 | if(deathFadeLevel > ONE_FIXED/2) |
| | 1705 | { |
| | 1706 | deathFadeLevel -= RealFrameTime / 4; |
| | 1707 | //FadeDownScreen(deathFadeLevel, 0); |
| | 1708 | } |
| | 1709 | else |
| | 1710 | { |
| | 1711 | extern SCREENDESCRIPTORBLOCK ScreenDescriptorBlock; |
| | 1712 | //deathFadeLevel = 0; |
| | 1713 | RenderStringCentred("Press operate to restart game", ScreenDescriptorBlock.SDB_CentreX, ScreenDescriptorBlock.SDB_Height-20,
0xffffffff); |
| | 1714 | AvP.MainLoopRunning = !(AvP.RestartLevel = Keyboard_input_operate()); |
| | 1715 | } |
| | 1716 | } |
| | 1717 | else |
| | 1718 | { |
| | 1719 | if(deathFadeLevel > 0) |
| | 1720 | { |
| | 1721 | deathFadeLevel -= RealFrameTime / 2; |
| | 1722 | } |
| | 1723 | else |
| | 1724 | { |
| | 1725 | deathFadeLevel = 0; |
| | 1726 | NetPlayerDeadProcessing(); |
| | 1727 | } |
| | 1728 | } |
| | 1729 | } |
| | 1730 | } |
| | 1731 | |
| | 1732 | /*---------------------------** |
| | 1733 | ** Loading and saving player ** |
| | 1734 | **---------------------------*/ |
| | 1735 | |
| | 1736 | typedef struct player_save_block |
| | 1737 | { |
| | 1738 | SAVE_BLOCK_STRATEGY_HEADER header; |
| | 1739 | |
| | 1740 | //behaviour block things |
| | 1741 | struct PLAYER_WEAPON_DATA WeaponSlot[MAX_NO_OF_WEAPON_SLOTS]; |
| | 1742 | struct PLAYER_WEAPON_DATA *SelectedWeapon; |
| | 1743 | |
| | 1744 | enum WEAPON_SLOT SelectedWeaponSlot; |
| | 1745 | enum WEAPON_SLOT SwapToWeaponSlot; |
| | 1746 | enum WEAPON_SLOT PreviouslySelectedWeaponSlot; |
| | 1747 | enum WEAPON_STATE WeaponState; |
| | 1748 | enum VISION_MODE_ID VisionMode; |
| | 1749 | |
| | 1750 | VECTORCH WeaponPositionOffset; |
| | 1751 | int WeaponStateTimeOutCounter; |
| | 1752 | |
| | 1753 | int Health; /* in 16.16 */ |
| | 1754 | int Armour; /* in 16.16 */ |
| | 1755 | |
| | 1756 | unsigned int Crouching; |
| | 1757 | |
| | 1758 | signed int ForwardInertia; |
| | 1759 | signed int StrafeInertia; |
| | 1760 | signed int TurnInertia; |
| | 1761 | |
| | 1762 | int ViewPanX; /* the looking up/down value that used to be in displayblock */ |
| | 1763 | |
| | 1764 | unsigned int securityClearances; |
| | 1765 | unsigned int IHaveAPlacedAutogun :1; |
| | 1766 | unsigned int JetpackEnabled :1; |
| | 1767 | unsigned int GrapplingHookEnabled :1; |
| | 1768 | unsigned int cloakOn :1; |
| | 1769 | unsigned int muzzle_flash:1; |
| | 1770 | unsigned int FirstPersonView:1; |
| | 1771 | |
| | 1772 | int FieldCharge; |
| | 1773 | int PlasmaCasterCharge; |
| | 1774 | int imageintensifier_battery; |
| | 1775 | int FlaresLeft; |
| | 1776 | int CloakingEffectiveness; |
| | 1777 | int SmartGunMode; |
| | 1778 | int tauntTimer; |
| | 1779 | int incidentFlag; |
| | 1780 | int incidentTimer; |
| | 1781 | |
| | 1782 | //some stuff for the weapon displayblock |
| | 1783 | VECTORCH Weapon_World; |
| | 1784 | EULER Weapon_Euler; |
| | 1785 | MATRIXCH Weapon_Matrix; |
| | 1786 | |
| | 1787 | //and globals |
| | 1788 | GRENADE_LAUNCHER_DATA GrenadeLauncherData; |
| | 1789 | |
| | 1790 | //strategy block stuff |
| | 1791 | DYNAMICSBLOCK dynamics; |
| | 1792 | DAMAGEBLOCK DamageBlock; |
| | 1793 | |
| | 1794 | } PLAYER_SAVE_BLOCK; |
| | 1795 | |
| | 1796 | //defines for load/save macros |
| | 1797 | #define SAVELOAD_BLOCK block |
| | 1798 | #define SAVELOAD_BEHAV playerStatusPtr |
| | 1799 | |
| | 1800 | void SaveStrategy_Player(STRATEGYBLOCK* sbPtr) |
| | 1801 | { |
| | 1802 | PLAYER_SAVE_BLOCK* block; |
| | 1803 | int i; |
| | 1804 | PLAYER_STATUS *playerStatusPtr = &PlayerStatus; |
| | 1805 | |
| | 1806 | GET_STRATEGY_SAVE_BLOCK(block, sbPtr); |
| | 1807 | |
| | 1808 | COPYELEMENT_SAVE(SelectedWeaponSlot) |
| | 1809 | COPYELEMENT_SAVE(SwapToWeaponSlot) |
| | 1810 | COPYELEMENT_SAVE(PreviouslySelectedWeaponSlot) |
| | 1811 | COPYELEMENT_SAVE(WeaponState) |
| | 1812 | COPYELEMENT_SAVE(VisionMode) |
| | 1813 | COPYELEMENT_SAVE(WeaponPositionOffset) |
| | 1814 | COPYELEMENT_SAVE(WeaponStateTimeOutCounter) |
| | 1815 | COPYELEMENT_SAVE(Health) /* in 16.16 */ |
| | 1816 | COPYELEMENT_SAVE(Armour) /* in 16.16 */ |
| | 1817 | COPYELEMENT_SAVE(Crouching) |
| | 1818 | COPYELEMENT_SAVE(ForwardInertia) |
| | 1819 | COPYELEMENT_SAVE(StrafeInertia) |
| | 1820 | COPYELEMENT_SAVE(TurnInertia) |
| | 1821 | COPYELEMENT_SAVE(ViewPanX) /* the looking up/down value that used to be in displayblock */ |
| | 1822 | COPYELEMENT_SAVE(securityClearances) |
| | 1823 | COPYELEMENT_SAVE(IHaveAPlacedAutogun) |
| | 1824 | COPYELEMENT_SAVE(JetpackEnabled) |
| | 1825 | COPYELEMENT_SAVE(GrapplingHookEnabled ) |
| | 1826 | COPYELEMENT_SAVE(cloakOn) |
| | 1827 | COPYELEMENT_SAVE(muzzle_flash) |
| | 1828 | COPYELEMENT_SAVE(FirstPersonView) |
| | 1829 | COPYELEMENT_SAVE(FieldCharge) |
| | 1830 | COPYELEMENT_SAVE(PlasmaCasterCharge) |
| | 1831 | COPYELEMENT_SAVE(imageintensifier_battery) |
| | 1832 | COPYELEMENT_SAVE(FlaresLeft) |
| | 1833 | COPYELEMENT_SAVE(CloakingEffectiveness) |
| | 1834 | COPYELEMENT_SAVE(SmartGunMode) |
| | 1835 | COPYELEMENT_SAVE(tauntTimer) |
| | 1836 | COPYELEMENT_SAVE(incidentFlag) |
| | 1837 | COPYELEMENT_SAVE(incidentTimer) |
| | 1838 | |
| | 1839 | for(i=0; i < MAX_NO_OF_WEAPON_SLOTS; i++) |
| | 1840 | { |
| | 1841 | block->WeaponSlot[i].WeaponIDNumber = PlayerStatus.WeaponSlot[i].WeaponIDNumber; |
| | 1842 | block->WeaponSlot[i].PrimaryRoundsRemaining = PlayerStatus.WeaponSlot[i].PrimaryRoundsRemaining; |
| | 1843 | block->WeaponSlot[i].SecondaryRoundsRemaining = PlayerStatus.WeaponSlot[i].SecondaryRoundsRemaining; |
| | 1844 | block->WeaponSlot[i].MagazinesRemaining = PlayerStatus.WeaponSlot[i].MagazinesRemaining; |
| | 1845 | block->WeaponSlot[i].Possessed = PlayerStatus.WeaponSlot[i].Possessed; |
| | 1846 | } |
| | 1847 | |
| | 1848 | //some stuff for the weapon displayblock |
| | 1849 | block->Weapon_World = PlayerStatus.weapon.ObWorld; |
| | 1850 | block->Weapon_Euler = PlayerStatus.weapon.ObEuler; |
| | 1851 | block->Weapon_Matrix = PlayerStatus.weapon.ObMat; |
| | 1852 | |
| | 1853 | //global |
| | 1854 | block->GrenadeLauncherData = GrenadeLauncherData; |
| | 1855 | |
| | 1856 | //strategy block stuff |
| | 1857 | block->DamageBlock = sbPtr->DamageBlock; |
| | 1858 | block->dynamics = *sbPtr->DynPtr; |
| | 1859 | block->dynamics.CollisionReportPtr = NULL; |
| | 1860 | |
| | 1861 | //save the weapon hierarchy |
| | 1862 | SaveHierarchy(&PlayersWeaponHModelController); |
| | 1863 | |
| | 1864 | Save_SoundState(&PlayerStatus.sound_mouth); |
| | 1865 | Save_SoundState(&PlayerStatus.soundCracklingFire); |
| | 1866 | Save_SoundState(&PlayerStatus.sound_jetpack); |
| | 1867 | } |
| | 1868 | |
| | 1869 | void LoadStrategy_Player(SAVE_BLOCK_STRATEGY_HEADER* header) |
| | 1870 | { |
| | 1871 | PLAYER_SAVE_BLOCK* block = (PLAYER_SAVE_BLOCK*) header; |
| | 1872 | STRATEGYBLOCK* sbPtr = PlayerStatus.sbptr; |
| | 1873 | int i; |
| | 1874 | |
| | 1875 | if(block->header.size != sizeof(*block)) |
| | 1876 | return; |
| | 1877 | |
| | 1878 | COPY_NAME(sbPtr->SBname, header->SBname); |
| | 1879 | |
| | 1880 | PlayerStatus.SelectedWeaponSlot = block->SelectedWeaponSlot; |
| | 1881 | PlayerStatus.SwapToWeaponSlot = block->SwapToWeaponSlot; |
| | 1882 | PlayerStatus.PreviouslySelectedWeaponSlot = block->PreviouslySelectedWeaponSlot; |
| | 1883 | PlayerStatus.WeaponState = block->WeaponState; |
| | 1884 | PlayerStatus.VisionMode = block->VisionMode; |
| | 1885 | PlayerStatus.WeaponPositionOffset = block->WeaponPositionOffset; |
| | 1886 | PlayerStatus.WeaponStateTimeOutCounter = block->WeaponStateTimeOutCounter; |
| | 1887 | PlayerStatus.Health = block->Health; |
| | 1888 | PlayerStatus.Armour = block->Armour; |
| | 1889 | PlayerStatus.Crouching = block->Crouching; |
| | 1890 | PlayerStatus.ForwardInertia = block->ForwardInertia; |
| | 1891 | PlayerStatus.StrafeInertia = block->StrafeInertia; |
| | 1892 | PlayerStatus.TurnInertia = block->TurnInertia; |
| | 1893 | PlayerStatus.ViewPanX = block->ViewPanX; |
| | 1894 | PlayerStatus.securityClearances = block->securityClearances; |
| | 1895 | PlayerStatus.IHaveAPlacedAutogun = block->IHaveAPlacedAutogun; |
| | 1896 | PlayerStatus.JetpackEnabled = block->JetpackEnabled; |
| | 1897 | PlayerStatus.GrapplingHookEnabled = block->GrapplingHookEnabled; |
| | 1898 | PlayerStatus.cloakOn = block->cloakOn; |
| | 1899 | PlayerStatus.muzzle_flash = block->muzzle_flash; |
| | 1900 | PlayerStatus.FirstPersonView = block->FirstPersonView; |
| | 1901 | PlayerStatus.FieldCharge = block->FieldCharge; |
| | 1902 | PlayerStatus.PlasmaCasterCharge = block->PlasmaCasterCharge; |
| | 1903 | PlayerStatus.imageintensifier_battery = block->imageintensifier_battery; |
| | 1904 | PlayerStatus.FlaresLeft = block->FlaresLeft; |
| | 1905 | PlayerStatus.CloakingEffectiveness = block->CloakingEffectiveness; |
| | 1906 | PlayerStatus.SmartGunMode = block->SmartGunMode; |
| | 1907 | PlayerStatus.tauntTimer = block->tauntTimer; |
| | 1908 | PlayerStatus.incidentFlag = block->incidentFlag; |
| | 1909 | PlayerStatus.incidentTimer = block->incidentTimer; |
| | 1910 | |
| | 1911 | for(i=0; i < MAX_NO_OF_WEAPON_SLOTS; i++) |
| | 1912 | { |
| | 1913 | PlayerStatus.WeaponSlot[i].WeaponIDNumber = block->WeaponSlot[i].WeaponIDNumber; |
| | 1914 | PlayerStatus.WeaponSlot[i].PrimaryRoundsRemaining = block->WeaponSlot[i].PrimaryRoundsRemaining; |
| | 1915 | PlayerStatus.WeaponSlot[i].SecondaryRoundsRemaining = block->WeaponSlot[i].SecondaryRoundsRemaining; |
| | 1916 | PlayerStatus.WeaponSlot[i].MagazinesRemaining = block->WeaponSlot[i].MagazinesRemaining; |
| | 1917 | PlayerStatus.WeaponSlot[i].Possessed = block->WeaponSlot[i].Possessed; |
| | 1918 | } |
| | 1919 | |
| | 1920 | PlayerStatus.SelectedWeapon = &PlayerStatus.WeaponSlot[PlayerStatus.SelectedWeaponSlot]; |
| | 1921 | |
| | 1922 | //some stuff for the weapon displayblock |
| | 1923 | PlayerStatus.weapon.ObWorld = block->Weapon_World; |
| | 1924 | PlayerStatus.weapon.ObEuler = block->Weapon_Euler; |
| | 1925 | PlayerStatus.weapon.ObMat = block->Weapon_Matrix; |
| | 1926 | |
| | 1927 | //global |
| | 1928 | GrenadeLauncherData = block->GrenadeLauncherData; |
| | 1929 | |
| | 1930 | //strategy block stuff |
| | 1931 | *sbPtr->DynPtr = block->dynamics; |
| | 1932 | sbPtr->DamageBlock = block->DamageBlock; |
| | 1933 | sbPtr->containingModule = ModuleFromPosition(&sbPtr->DynPtr->Position, NULL); |
| | 1934 | Global_VDB.VDB_World = sbPtr->DynPtr->Position; |
| | 1935 | |
| | 1936 | //load the weapon hierarchy |
| | 1937 | { |
| | 1938 | SAVE_BLOCK_HEADER* hier_header = GetNextBlockIfOfType(SaveBlock_Hierarchy); |
| | 1939 | |
| | 1940 | if(hier_header) |
| | 1941 | LoadHierarchy(hier_header, &PlayersWeaponHModelController); |
| | 1942 | else |
| | 1943 | Dispel_HModel(&PlayersWeaponHModelController); |
| | 1944 | } |
| | 1945 | |
| | 1946 | GrabWeaponShape(); // alien needs this |
| | 1947 | |
| | 1948 | Load_SoundState(&PlayerStatus.sound_mouth); |
| | 1949 | Load_SoundState(&PlayerStatus.soundCracklingFire); |
| | 1950 | Load_SoundState(&PlayerStatus.sound_jetpack); |
| | 1951 | } |