2184 lines
62 KiB
C
2184 lines
62 KiB
C
![]() |
/* KJL 16:23:20 10/25/96 - I'm moved all the weapon stuff to the newly created weapon.c,
|
||
|
so player.c is looking a bit bare at the moment. */
|
||
|
#include "3dc.h"
|
||
|
#include "module.h"
|
||
|
#include "inline.h"
|
||
|
|
||
|
#include "stratdef.h"
|
||
|
#include "gamedef.h"
|
||
|
#include "bh_types.h"
|
||
|
#include "inventry.h"
|
||
|
#include "gameplat.h"
|
||
|
#include "dynblock.h"
|
||
|
#include "dynamics.h"
|
||
|
#include "comp_shp.h"
|
||
|
#include "weapons.h"
|
||
|
#include "vision.h"
|
||
|
#include "pheromon.h"
|
||
|
#include "avpview.h"
|
||
|
#include "particle.h"
|
||
|
#include "scream.h"
|
||
|
#include "savegame.h"
|
||
|
#if SupportWindows95
|
||
|
#include "rebmenus.hpp"
|
||
|
#endif
|
||
|
|
||
|
#define UseLocalAssert Yes
|
||
|
#include "ourasert.h"
|
||
|
|
||
|
#include "psnd.h"
|
||
|
#include "psndplat.h"
|
||
|
|
||
|
/* for win 95 net support */
|
||
|
#if SupportWindows95
|
||
|
#include "pldnet.h"
|
||
|
#include "pldghost.h"
|
||
|
#include "dp_func.h"
|
||
|
#endif
|
||
|
#include "ShowCmds.h"
|
||
|
#include "BonusAbilities.h"
|
||
|
|
||
|
#define PLAYER_HMODEL 0
|
||
|
|
||
|
/*KJL****************************************************************************************
|
||
|
* G L O B A L S *
|
||
|
****************************************************************************************KJL*/
|
||
|
VECTORCH PlayerStartLocation;
|
||
|
MATRIXCH PlayerStartMat;
|
||
|
extern int NormalFrameTime;
|
||
|
extern ACTIVESOUNDSAMPLE ActiveSounds[];
|
||
|
extern int PlayerDamagedOverlayIntensity;
|
||
|
extern int playerNoise;
|
||
|
extern int predHUDSoundHandle;
|
||
|
extern int predOVision_SoundHandle;
|
||
|
|
||
|
extern int AIModuleArraySize;
|
||
|
|
||
|
int GimmeChargeCalls;
|
||
|
int HtoHStrikes;
|
||
|
int CurrentLightAtPlayer;
|
||
|
int TauntSoundPlayed;
|
||
|
|
||
|
int TrickleCharge=9000;
|
||
|
int CloakDrain=12000;
|
||
|
int CloakThreshold=(5*ONE_FIXED);
|
||
|
int CloakPowerOnDrain=(2*ONE_FIXED);
|
||
|
|
||
|
extern DPID myNetworkKillerId;
|
||
|
extern DPID myIgniterId;
|
||
|
extern int MyHitBodyPartId;
|
||
|
extern HMODELCONTROLLER PlayersWeaponHModelController;
|
||
|
extern SECTION_DATA *PWMFSDP; /* PlayersWeaponMuzzleFlashSectionDataPointer */
|
||
|
|
||
|
/*KJL****************************************************************************************
|
||
|
* P R O T O T Y P E S *
|
||
|
****************************************************************************************KJL*/
|
||
|
void InitPlayer(STRATEGYBLOCK* sbPtr, int sb_type);
|
||
|
void MaintainPlayer(void);
|
||
|
void PlayerIsDamaged(STRATEGYBLOCK *sbPtr, DAMAGE_PROFILE *damage, int multiplier,VECTORCH* incoming);
|
||
|
static void PlayerIsDead(DAMAGE_PROFILE *damage,int multiplier,VECTORCH* incoming);
|
||
|
|
||
|
extern int LightIntensityAtPoint(VECTORCH *pointPtr);
|
||
|
extern SECTION * GetNamedHierarchyFromLibrary(const char * rif_name, const char * hier_name);
|
||
|
extern int SlotForThisWeapon(enum WEAPON_ID weaponID);
|
||
|
extern void PointAlert(int level, VECTORCH *point);
|
||
|
extern void RemoveAllThisPlayersDiscs(void);
|
||
|
void ShowAdjacencies(void);
|
||
|
|
||
|
extern int ShowAdj;
|
||
|
|
||
|
/*KJL****************************************************************************************
|
||
|
* F U N C T I O N S *
|
||
|
****************************************************************************************KJL*/
|
||
|
|
||
|
PLAYER_STATUS* PlayerStatusPtr = NULL;
|
||
|
static PLAYER_STATUS PlayerStatusBlock;
|
||
|
int ShowPredoStats=0;
|
||
|
int Observer=0;
|
||
|
|
||
|
/* Patrick 22/8/97------------------------------------------------
|
||
|
Cloaking stuff
|
||
|
------------------------------------------------------------------*/
|
||
|
void InitPlayerCloakingSystem(void);
|
||
|
static void DoPlayerCloakingSystem(void);
|
||
|
|
||
|
void InitPlayer(STRATEGYBLOCK* sbPtr, int sb_type)
|
||
|
{
|
||
|
/*KJL**************************************************************************************
|
||
|
* InitPlayer() was written by me. It attaches the extra player data to the strategy block *
|
||
|
* and fills in some initial values. *
|
||
|
**************************************************************************************KJL*/
|
||
|
|
||
|
SECTION *root_section;
|
||
|
PLAYER_STATUS *psPtr = &PlayerStatusBlock;
|
||
|
GLOBALASSERT(psPtr);
|
||
|
GLOBALASSERT(sbPtr);
|
||
|
|
||
|
// set up our global
|
||
|
|
||
|
PlayerStatusPtr = psPtr;
|
||
|
|
||
|
|
||
|
sbPtr->I_SBtype = sb_type;
|
||
|
sbPtr->SBdataptr = (void*)psPtr;
|
||
|
|
||
|
InitialisePlayersInventory(psPtr);
|
||
|
|
||
|
/* Initialise Player's stats */
|
||
|
{
|
||
|
NPC_DATA *NpcData;
|
||
|
NPC_TYPES PlayerType;
|
||
|
|
||
|
switch(AvP.PlayerType)
|
||
|
{
|
||
|
case(I_Marine):
|
||
|
{
|
||
|
switch (AvP.Difficulty) {
|
||
|
case I_Easy:
|
||
|
PlayerType=I_PC_Marine_Easy;
|
||
|
break;
|
||
|
default:
|
||
|
case I_Medium:
|
||
|
PlayerType=I_PC_Marine_Medium;
|
||
|
break;
|
||
|
case I_Hard:
|
||
|
PlayerType=I_PC_Marine_Hard;
|
||
|
break;
|
||
|
case I_Impossible:
|
||
|
PlayerType=I_PC_Marine_Impossible;
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
#if 0 //this hmodel isn't being set up for the moment - Richard
|
||
|
root_section=GetNamedHierarchyFromLibrary("hnpcmarine","Template");
|
||
|
if (!root_section) {
|
||
|
GLOBALASSERT(0);
|
||
|
/* Sorry, there's just no bouncing back from this one. Fix it. */
|
||
|
return;
|
||
|
}
|
||
|
#if PLAYER_HMODEL
|
||
|
Create_HModel(&psPtr->HModelController,root_section);
|
||
|
InitHModelSequence(&psPtr->HModelController,0,0,ONE_FIXED);
|
||
|
#endif
|
||
|
/* Doesn't matter what the sequence is... */
|
||
|
#endif
|
||
|
break;
|
||
|
}
|
||
|
case(I_Predator):
|
||
|
{
|
||
|
switch (AvP.Difficulty) {
|
||
|
case I_Easy:
|
||
|
PlayerType=I_PC_Predator_Easy;
|
||
|
break;
|
||
|
default:
|
||
|
case I_Medium:
|
||
|
PlayerType=I_PC_Predator_Medium;
|
||
|
break;
|
||
|
case I_Hard:
|
||
|
PlayerType=I_PC_Predator_Hard;
|
||
|
break;
|
||
|
case I_Impossible:
|
||
|
PlayerType=I_PC_Predator_Impossible;
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
#if 0 //this hmodel isn't being set up for the moment - Richard
|
||
|
root_section=GetNamedHierarchyFromLibrary("hnpcpredator","Template");
|
||
|
if (!root_section) {
|
||
|
GLOBALASSERT(0);
|
||
|
/* Sorry, there's just no bouncing back from this one. Fix it. */
|
||
|
return;
|
||
|
}
|
||
|
#if PLAYER_HMODEL
|
||
|
Create_HModel(&psPtr->HModelController,root_section);
|
||
|
InitHModelSequence(&psPtr->HModelController,0,0,ONE_FIXED);
|
||
|
#endif
|
||
|
/* Doesn't matter what the sequence is... */
|
||
|
#endif
|
||
|
break;
|
||
|
}
|
||
|
case(I_Alien):
|
||
|
{
|
||
|
switch (AvP.Difficulty) {
|
||
|
case I_Easy:
|
||
|
PlayerType=I_PC_Alien_Easy;
|
||
|
break;
|
||
|
default:
|
||
|
case I_Medium:
|
||
|
PlayerType=I_PC_Alien_Medium;
|
||
|
break;
|
||
|
case I_Hard:
|
||
|
PlayerType=I_PC_Alien_Hard;
|
||
|
break;
|
||
|
case I_Impossible:
|
||
|
PlayerType=I_PC_Alien_Impossible;
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
#if 0 //this hmodel isn't being set up for the moment - Richard
|
||
|
root_section=GetNamedHierarchyFromLibrary("hnpcalien","alien");
|
||
|
if (!root_section) {
|
||
|
GLOBALASSERT(0);
|
||
|
/* Sorry, there's just no bouncing back from this one. Fix it. */
|
||
|
return;
|
||
|
}
|
||
|
#if PLAYER_HMODEL
|
||
|
Create_HModel(&psPtr->HModelController,root_section);
|
||
|
InitHModelSequence(&psPtr->HModelController,0,0,ONE_FIXED);
|
||
|
#endif
|
||
|
/* Doesn't matter what the sequence is... */
|
||
|
#endif
|
||
|
break;
|
||
|
|
||
|
}
|
||
|
default:
|
||
|
{
|
||
|
LOCALASSERT(1==0);
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
NpcData=GetThisNpcData(PlayerType);
|
||
|
LOCALASSERT(NpcData);
|
||
|
sbPtr->SBDamageBlock.Health=NpcData->StartingStats.Health<<ONE_FIXED_SHIFT;
|
||
|
sbPtr->SBDamageBlock.Armour=NpcData->StartingStats.Armour<<ONE_FIXED_SHIFT;
|
||
|
sbPtr->SBDamageBlock.SB_H_flags=NpcData->StartingStats.SB_H_flags;
|
||
|
sbPtr->SBDamageBlock.IsOnFire=0;
|
||
|
|
||
|
//{
|
||
|
// int *nptr,i;
|
||
|
// nptr=(int *)sbPtr->SBname;
|
||
|
// for (i=0; i<(SB_NAME_LENGTH>>2); i++) {
|
||
|
// *nptr=FastRandom();
|
||
|
// nptr++;
|
||
|
// }
|
||
|
// sbPtr->SBname[SB_NAME_LENGTH-1]=3; /* Just to make sure... */
|
||
|
//}
|
||
|
AssignNewSBName(sbPtr);
|
||
|
}
|
||
|
|
||
|
//psPtr->Health=STARTOFGAME_MARINE_HEALTH;
|
||
|
psPtr->Energy=STARTOFGAME_MARINE_ENERGY;
|
||
|
//psPtr->Armour=STARTOFGAME_MARINE_ARMOUR;
|
||
|
|
||
|
psPtr->Encumberance.MovementMultiple=ONE_FIXED;
|
||
|
psPtr->Encumberance.TurningMultiple=ONE_FIXED;
|
||
|
psPtr->Encumberance.JumpingMultiple=ONE_FIXED;
|
||
|
psPtr->Encumberance.CanCrouch=1;
|
||
|
psPtr->Encumberance.CanRun=1;
|
||
|
|
||
|
psPtr->incidentFlag=0;
|
||
|
psPtr->incidentTimer=0;
|
||
|
|
||
|
/* CDF 16/9/97 Now, those health and armour stats are those of the last cycle. */
|
||
|
|
||
|
psPtr->Health=sbPtr->SBDamageBlock.Health;
|
||
|
psPtr->Armour=sbPtr->SBDamageBlock.Armour;
|
||
|
|
||
|
psPtr->IsAlive = 1;
|
||
|
psPtr->IHaveAPlacedAutogun = 0;
|
||
|
psPtr->MyFaceHugger=NULL;
|
||
|
psPtr->MyCorpse=NULL;
|
||
|
psPtr->tauntTimer=0;
|
||
|
TauntSoundPlayed=0;
|
||
|
psPtr->fireTimer=0;
|
||
|
psPtr->invulnerabilityTimer=0;
|
||
|
/* Better safe than sorry. */
|
||
|
psPtr->soundHandle=SOUND_NOACTIVEINDEX;
|
||
|
psPtr->soundHandle3=SOUND_NOACTIVEINDEX;
|
||
|
psPtr->soundHandle4=SOUND_NOACTIVEINDEX;
|
||
|
psPtr->soundHandle5=SOUND_NOACTIVEINDEX;
|
||
|
psPtr->soundHandleForPredatorCloakDamaged=SOUND_NOACTIVEINDEX;
|
||
|
InitPlayerCloakingSystem();/* Patrick 22/8/97 : Cloaking stuff */
|
||
|
|
||
|
/* KJL 12:06:01 11/14/96 - allocate dynamics block & fill from template */
|
||
|
sbPtr->DynPtr = AllocateDynamicsBlock(DYNAMICS_TEMPLATE_MARINE_PLAYER);
|
||
|
/* for the time being get world position and orientation from the displayblock */
|
||
|
{
|
||
|
DISPLAYBLOCK *dPtr = sbPtr->SBdptr;
|
||
|
DYNAMICSBLOCK *dynPtr = sbPtr->DynPtr;
|
||
|
GLOBALASSERT(dPtr);
|
||
|
GLOBALASSERT(dynPtr);
|
||
|
|
||
|
dynPtr->Position = PlayerStartLocation;
|
||
|
dynPtr->OrientMat = PlayerStartMat;
|
||
|
MatrixToEuler(&dynPtr->OrientMat,&dynPtr->OrientEuler);
|
||
|
//dynPtr->OrientEuler = dPtr->ObEuler;
|
||
|
|
||
|
|
||
|
dynPtr->PrevPosition = dynPtr->Position;
|
||
|
dynPtr->PrevOrientMat = dynPtr->OrientMat;
|
||
|
dynPtr->PrevOrientEuler = dynPtr->OrientEuler;
|
||
|
|
||
|
/* let alien walk on walls & ceiling */
|
||
|
if (AvP.PlayerType == I_Alien)
|
||
|
{
|
||
|
dynPtr->ToppleForce = TOPPLE_FORCE_ALIEN;
|
||
|
}
|
||
|
|
||
|
/* KJL 10:56:57 11/24/97 - set ObRadius to a sensible value */
|
||
|
dPtr->ObRadius = 1200;
|
||
|
|
||
|
/*
|
||
|
if (AvP.PlayerType == I_Alien) sbPtr->I_SBtype = I_BehaviourAlienPlayer;
|
||
|
if (AvP.PlayerType == I_Predator) sbPtr->I_SBtype = I_BehaviourPredatorPlayer;*/
|
||
|
/* KJL 18:30:09 11/11/98 - datum used for falling damage */
|
||
|
{
|
||
|
extern int PlayersMaxHeightWhilstNotInContactWithGround;
|
||
|
PlayersMaxHeightWhilstNotInContactWithGround=dynPtr->Position.vy;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/* zero inertia values */
|
||
|
psPtr->ForwardInertia=0;
|
||
|
psPtr->StrafeInertia=0;
|
||
|
psPtr->TurnInertia=0;
|
||
|
psPtr->IsMovingInWater = 0;
|
||
|
PlayerDamagedOverlayIntensity = 0;
|
||
|
|
||
|
/* a little addition by patrick */
|
||
|
InitPlayerMovementData(sbPtr);
|
||
|
|
||
|
/* security clearance */
|
||
|
psPtr->securityClearances = 0;
|
||
|
|
||
|
/* thou art mortal */
|
||
|
psPtr->IsImmortal = 0;
|
||
|
|
||
|
if (AvP.Network==I_No_Network)
|
||
|
{
|
||
|
SoundSys_FadeIn();
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
SoundSys_ResetFadeLevel();
|
||
|
}
|
||
|
|
||
|
//restore the number of saves allowed
|
||
|
ResetNumberOfSaves();
|
||
|
|
||
|
#if SupportWindows95
|
||
|
//choosing a start position now occurs later on
|
||
|
// if(AvP.Network!=I_No_Network) TeleportNetPlayerToAStartingPosition(sbPtr, 1);
|
||
|
#endif
|
||
|
|
||
|
}
|
||
|
|
||
|
void ChangeToMarine()
|
||
|
{
|
||
|
if(AvP.Network!=I_No_Network)
|
||
|
{
|
||
|
AvP.PlayerType=I_Marine;
|
||
|
NetPlayerRespawn(Player->ObStrategyBlock);
|
||
|
InitPlayerMovementData(Player->ObStrategyBlock);
|
||
|
Player->ObStrategyBlock->DynPtr->ToppleForce=TOPPLE_FORCE_NONE;
|
||
|
netGameData.myCharacterType=netGameData.myNextCharacterType=NGCT_Marine;
|
||
|
|
||
|
//reorient the player
|
||
|
{
|
||
|
EULER e;
|
||
|
MatrixToEuler(&Player->ObStrategyBlock->DynPtr->OrientMat,&e);
|
||
|
e.EulerX=0;
|
||
|
e.EulerZ=0;
|
||
|
|
||
|
CreateEulerMatrix(&e,&Player->ObStrategyBlock->DynPtr->OrientMat);
|
||
|
TransposeMatrixCH(&Player->ObStrategyBlock->DynPtr->OrientMat);
|
||
|
|
||
|
Player->ObStrategyBlock->DynPtr->UseStandardGravity=1;
|
||
|
}
|
||
|
|
||
|
/* CDF 15/3/99, delete all discs... */
|
||
|
RemoveAllThisPlayersDiscs();
|
||
|
|
||
|
}
|
||
|
}
|
||
|
void ChangeToAlien()
|
||
|
{
|
||
|
if(AvP.Network!=I_No_Network)
|
||
|
{
|
||
|
AvP.PlayerType=I_Alien;
|
||
|
NetPlayerRespawn(Player->ObStrategyBlock);
|
||
|
InitPlayerMovementData(Player->ObStrategyBlock);
|
||
|
Player->ObStrategyBlock->DynPtr->ToppleForce=TOPPLE_FORCE_ALIEN;
|
||
|
|
||
|
netGameData.myCharacterType=netGameData.myNextCharacterType=NGCT_Alien;
|
||
|
|
||
|
/* CDF 15/3/99, delete all discs... */
|
||
|
RemoveAllThisPlayersDiscs();
|
||
|
}
|
||
|
}
|
||
|
void ChangeToPredator()
|
||
|
{
|
||
|
if(AvP.Network!=I_No_Network)
|
||
|
{
|
||
|
AvP.PlayerType=I_Predator;
|
||
|
NetPlayerRespawn(Player->ObStrategyBlock);
|
||
|
InitPlayerMovementData(Player->ObStrategyBlock);
|
||
|
Player->ObStrategyBlock->DynPtr->ToppleForce=TOPPLE_FORCE_NONE;
|
||
|
netGameData.myCharacterType=netGameData.myNextCharacterType=NGCT_Predator;
|
||
|
|
||
|
//reorient the player
|
||
|
{
|
||
|
EULER e;
|
||
|
MatrixToEuler(&Player->ObStrategyBlock->DynPtr->OrientMat,&e);
|
||
|
e.EulerX=0;
|
||
|
e.EulerZ=0;
|
||
|
|
||
|
CreateEulerMatrix(&e,&Player->ObStrategyBlock->DynPtr->OrientMat);
|
||
|
TransposeMatrixCH(&Player->ObStrategyBlock->DynPtr->OrientMat);
|
||
|
|
||
|
Player->ObStrategyBlock->DynPtr->UseStandardGravity=1;
|
||
|
}
|
||
|
|
||
|
/* CDF 15/3/99, delete all discs... */
|
||
|
RemoveAllThisPlayersDiscs();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void MaintainPlayer(void)
|
||
|
{
|
||
|
int rand = FastRandom();
|
||
|
PLAYER_STATUS *playerStatusPtr= (PLAYER_STATUS *) (Player->ObStrategyBlock->SBdataptr);
|
||
|
|
||
|
if (playerStatusPtr->IsAlive)
|
||
|
{
|
||
|
MaintainPlayersInventory();
|
||
|
}
|
||
|
|
||
|
if (ShowAdj) {
|
||
|
ShowAdjacencies();
|
||
|
}
|
||
|
|
||
|
/* Set here, as first point. */
|
||
|
playerNoise=0;
|
||
|
|
||
|
/* Incident handling. */
|
||
|
playerStatusPtr->incidentFlag=0;
|
||
|
|
||
|
playerStatusPtr->incidentTimer-=NormalFrameTime;
|
||
|
|
||
|
if (playerStatusPtr->incidentTimer<0) {
|
||
|
playerStatusPtr->incidentFlag=1;
|
||
|
playerStatusPtr->incidentTimer=32767+(FastRandom()&65535);
|
||
|
}
|
||
|
|
||
|
/* CDF 9/6/98 - I can't believe this isn't done!!! */
|
||
|
Player->ObStrategyBlock->containingModule = playerPherModule;
|
||
|
|
||
|
if (Observer) {
|
||
|
textprint("Observer Mode...\n");
|
||
|
}
|
||
|
textprint("HtoH Strikes %d\n",HtoHStrikes);
|
||
|
|
||
|
DoPlayerCloakingSystem();/* Patrick 22/8/97 : Cloaking stuff */
|
||
|
// HandlePredatorVisionModes();
|
||
|
|
||
|
CurrentLightAtPlayer=LightIntensityAtPoint(&Player->ObStrategyBlock->DynPtr->Position);
|
||
|
|
||
|
#if 1
|
||
|
textprint("PlayerLight %d\n",CurrentLightAtPlayer);
|
||
|
#endif
|
||
|
|
||
|
#if SupportWindows95
|
||
|
#if 0//UseRebMenus
|
||
|
if(playerStatusPtr->Mvt_InputRequests.Flags.Rqst_PauseGame)
|
||
|
{
|
||
|
REBMENUS_ProcessPauseRequest();
|
||
|
}
|
||
|
#else
|
||
|
if(AvP.Network==I_No_Network)
|
||
|
{
|
||
|
#if 1
|
||
|
if(playerStatusPtr->Mvt_InputRequests.Flags.Rqst_PauseGame)
|
||
|
{
|
||
|
// go to start menu
|
||
|
AvP.MainLoopRunning = 0;
|
||
|
}
|
||
|
#endif
|
||
|
}
|
||
|
else
|
||
|
if(playerStatusPtr->Mvt_InputRequests.Flags.Rqst_PauseGame)
|
||
|
{
|
||
|
if (AvP.Network == I_Host)
|
||
|
{
|
||
|
TransmitEndOfGameNetMsg();
|
||
|
netGameData.myGameState = NGS_EndGame;
|
||
|
}
|
||
|
else if (AvP.Network == I_Peer)
|
||
|
{
|
||
|
TransmitPlayerLeavingNetMsg();
|
||
|
netGameData.myGameState = NGS_Leaving;
|
||
|
}
|
||
|
// go to start menu
|
||
|
AvP.MainLoopRunning = 0;
|
||
|
}
|
||
|
#endif
|
||
|
#endif
|
||
|
//Update the player's invulnerabilty timer
|
||
|
if(playerStatusPtr->invulnerabilityTimer>0)
|
||
|
{
|
||
|
playerStatusPtr->invulnerabilityTimer-=NormalFrameTime;
|
||
|
|
||
|
if(playerStatusPtr->invulnerabilityTimer<=0)
|
||
|
{
|
||
|
playerStatusPtr->invulnerabilityTimer=0;
|
||
|
}
|
||
|
//lose invulnerability if player is firing
|
||
|
|
||
|
if(playerStatusPtr->Mvt_InputRequests.Flags.Rqst_FirePrimaryWeapon)
|
||
|
{
|
||
|
PLAYER_WEAPON_DATA *weaponPtr = &(playerStatusPtr->WeaponSlot[playerStatusPtr->SelectedWeaponSlot]);
|
||
|
if(weaponPtr->WeaponIDNumber!=WEAPON_PRED_MEDICOMP)
|
||
|
{
|
||
|
playerStatusPtr->invulnerabilityTimer=0;
|
||
|
}
|
||
|
}
|
||
|
if(playerStatusPtr->Mvt_InputRequests.Flags.Rqst_FireSecondaryWeapon)
|
||
|
{
|
||
|
//not many weapons have an offensive secondary fire
|
||
|
PLAYER_WEAPON_DATA *weaponPtr = &(playerStatusPtr->WeaponSlot[playerStatusPtr->SelectedWeaponSlot]);
|
||
|
if(weaponPtr->WeaponIDNumber == WEAPON_PULSERIFLE ||
|
||
|
weaponPtr->WeaponIDNumber == WEAPON_CUDGEL ||
|
||
|
weaponPtr->WeaponIDNumber == WEAPON_MARINE_PISTOL ||
|
||
|
weaponPtr->WeaponIDNumber == WEAPON_TWO_PISTOLS ||
|
||
|
weaponPtr->WeaponIDNumber == WEAPON_PRED_WRISTBLADE ||
|
||
|
weaponPtr->WeaponIDNumber == WEAPON_ALIEN_CLAW)
|
||
|
{
|
||
|
playerStatusPtr->invulnerabilityTimer=0;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
if (AvP.DestructTimer>0) {
|
||
|
extern int NormalFrameTime;
|
||
|
|
||
|
AvP.DestructTimer-=NormalFrameTime;
|
||
|
if (AvP.DestructTimer<0) AvP.DestructTimer=0;
|
||
|
|
||
|
} else if (AvP.DestructTimer==0) {
|
||
|
// ...Destruct?
|
||
|
CauseDamageToObject(Player->ObStrategyBlock,&TemplateAmmo[AMMO_SADAR_TOW].MaxDamage[AvP.Difficulty], 25*ONE_FIXED,NULL);
|
||
|
// That'll learn 'em.
|
||
|
}
|
||
|
|
||
|
/* Take speed sample. */
|
||
|
{
|
||
|
int speed;
|
||
|
|
||
|
speed=Approximate3dMagnitude(&Player->ObStrategyBlock->DynPtr->LinVelocity);
|
||
|
CurrentGameStats_SpeedSample(speed,NormalFrameTime);
|
||
|
}
|
||
|
|
||
|
/* Is the player on fire? */
|
||
|
if (Player->ObStrategyBlock->SBDamageBlock.IsOnFire) {
|
||
|
|
||
|
myNetworkKillerId=myIgniterId;
|
||
|
CauseDamageToObject(Player->ObStrategyBlock,&firedamage,NormalFrameTime,NULL);
|
||
|
myNetworkKillerId=AVPDPNetID;
|
||
|
|
||
|
if (playerStatusPtr->soundHandle3!=SOUND_NOACTIVEINDEX) {
|
||
|
if (ActiveSounds[playerStatusPtr->soundHandle3].soundIndex!=SID_FIRE) {
|
||
|
Sound_Stop(playerStatusPtr->soundHandle3);
|
||
|
Sound_Play(SID_FIRE,"dlev",&(Player->ObStrategyBlock->DynPtr->Position),&playerStatusPtr->soundHandle3,127);
|
||
|
} else {
|
||
|
Sound_Update3d(playerStatusPtr->soundHandle3,&(Player->ObStrategyBlock->DynPtr->Position));
|
||
|
}
|
||
|
} else if (playerStatusPtr->IsAlive) {
|
||
|
Sound_Play(SID_FIRE,"dlev",&(Player->ObStrategyBlock->DynPtr->Position),&playerStatusPtr->soundHandle3,127);
|
||
|
}
|
||
|
|
||
|
/* Put the fire out... */
|
||
|
|
||
|
#if 1
|
||
|
{
|
||
|
int speed;
|
||
|
/* Go out? */
|
||
|
speed=Approximate3dMagnitude(&Player->ObStrategyBlock->DynPtr->LinVelocity);
|
||
|
|
||
|
if (speed>22000) {
|
||
|
/* Jumping alien. */
|
||
|
playerStatusPtr->fireTimer-=(NormalFrameTime*6);
|
||
|
} else if (speed>15000) {
|
||
|
/* Running alien. */
|
||
|
playerStatusPtr->fireTimer-=(NormalFrameTime<<2);
|
||
|
} else {
|
||
|
/* Normal bloke. */
|
||
|
playerStatusPtr->fireTimer-=NormalFrameTime;
|
||
|
}
|
||
|
|
||
|
if(playerStatusPtr->invulnerabilityTimer>0)
|
||
|
{
|
||
|
//player is invulnerable, so put him out.
|
||
|
playerStatusPtr->fireTimer=0;
|
||
|
}
|
||
|
|
||
|
if (playerStatusPtr->fireTimer<=0) {
|
||
|
/* Go out. */
|
||
|
Player->ObStrategyBlock->SBDamageBlock.IsOnFire=0;
|
||
|
playerStatusPtr->fireTimer=0;
|
||
|
}
|
||
|
}
|
||
|
#else
|
||
|
if (playerStatusPtr->incidentFlag) {
|
||
|
int speed;
|
||
|
/* Go out? */
|
||
|
speed=Approximate3dMagnitude(&Player->ObStrategyBlock->DynPtr->LinVelocity);
|
||
|
|
||
|
if (speed>15000) {
|
||
|
/* Running alien. */
|
||
|
if ((FastRandom()&65535)<13107) {
|
||
|
Player->ObStrategyBlock->SBDamageBlock.IsOnFire=0;
|
||
|
}
|
||
|
} else {
|
||
|
/* Normal bloke. */
|
||
|
if ((FastRandom()&65535)<3000) {
|
||
|
Player->ObStrategyBlock->SBDamageBlock.IsOnFire=0;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
#endif
|
||
|
} else {
|
||
|
if (playerStatusPtr->soundHandle3!=SOUND_NOACTIVEINDEX) {
|
||
|
Sound_Stop(playerStatusPtr->soundHandle3);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (playerStatusPtr->IsMovingInWater)
|
||
|
{
|
||
|
#if 0
|
||
|
if (playerStatusPtr->soundHandle4==SOUND_NOACTIVEINDEX) {
|
||
|
switch (rand % 4) {
|
||
|
case 0:
|
||
|
Sound_Play(SID_SPLASH1,"dev",&(Player->ObStrategyBlock->DynPtr->Position),&playerStatusPtr->soundHandle4,127);
|
||
|
break;
|
||
|
case 1:
|
||
|
Sound_Play(SID_SPLASH2,"dev",&(Player->ObStrategyBlock->DynPtr->Position),&playerStatusPtr->soundHandle4,127);
|
||
|
break;
|
||
|
case 2:
|
||
|
Sound_Play(SID_SPLASH3,"dev",&(Player->ObStrategyBlock->DynPtr->Position),&playerStatusPtr->soundHandle4,127);
|
||
|
break;
|
||
|
default:
|
||
|
Sound_Play(SID_SPLASH4,"dev",&(Player->ObStrategyBlock->DynPtr->Position),&playerStatusPtr->soundHandle4,127);
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
#else
|
||
|
/* KJL 19:07:57 25/05/98 - make a noise at most every 1/4 of a sec */
|
||
|
if (playerStatusPtr->soundHandle4<=0)
|
||
|
{
|
||
|
switch (rand&3)
|
||
|
{
|
||
|
case 0:
|
||
|
Sound_Play(SID_SPLASH1,"d",&(Player->ObStrategyBlock->DynPtr->Position));
|
||
|
break;
|
||
|
case 1:
|
||
|
Sound_Play(SID_SPLASH2,"d",&(Player->ObStrategyBlock->DynPtr->Position));
|
||
|
break;
|
||
|
case 2:
|
||
|
Sound_Play(SID_SPLASH3,"d",&(Player->ObStrategyBlock->DynPtr->Position));
|
||
|
break;
|
||
|
default:
|
||
|
Sound_Play(SID_SPLASH4,"d",&(Player->ObStrategyBlock->DynPtr->Position));
|
||
|
break;
|
||
|
|
||
|
}
|
||
|
playerStatusPtr->soundHandle4=16384;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
playerStatusPtr->soundHandle4-=NormalFrameTime;
|
||
|
}
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
|
||
|
/* KJL 14:54:48 25/05/98 - reset water flag to zero for next frame */
|
||
|
playerStatusPtr->IsMovingInWater = 0;
|
||
|
|
||
|
/* Taunt effects. */
|
||
|
if (playerStatusPtr->tauntTimer) {
|
||
|
int ex,ey,ez;
|
||
|
|
||
|
playerNoise=1;
|
||
|
/* An actual noise, too, would probably be good. */
|
||
|
|
||
|
if (AvP.PlayerType==I_Alien) {
|
||
|
|
||
|
//if (playerStatusPtr->tauntTimer>(TAUNT_LENGTH>>1)) {
|
||
|
if (TauntSoundPlayed==0) {
|
||
|
/* That should make sure we don't get more than one. */
|
||
|
if (playerStatusPtr->soundHandle==SOUND_NOACTIVEINDEX) {
|
||
|
#if 0
|
||
|
Sound_Play(SID_ALIEN_SCREAM,"de",&(Player->ObStrategyBlock->DynPtr->Position),&playerStatusPtr->soundHandle);
|
||
|
#else
|
||
|
PlayAlienSound(0,ASC_Taunt,0,&playerStatusPtr->soundHandle,&(Player->ObStrategyBlock->DynPtr->Position));
|
||
|
if(AvP.Network!=I_No_Network) netGameData.myLastScream=ASC_Taunt;
|
||
|
#endif
|
||
|
TauntSoundPlayed=1;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/* Wave the head around? */
|
||
|
ex=0;
|
||
|
ey=0;
|
||
|
ez=0;
|
||
|
|
||
|
ex=MUL_FIXED(64,GetSin(((playerStatusPtr->tauntTimer>>6)&wrap360)));
|
||
|
ey=MUL_FIXED(128,GetSin(((playerStatusPtr->tauntTimer>>5)&wrap360)));
|
||
|
ez=MUL_FIXED(-64,GetSin(((playerStatusPtr->tauntTimer>>5)&wrap360)));
|
||
|
|
||
|
ex&=wrap360;
|
||
|
ey&=wrap360;
|
||
|
ez&=wrap360;
|
||
|
|
||
|
HeadOrientation.EulerX=ex;
|
||
|
HeadOrientation.EulerY=ey;
|
||
|
HeadOrientation.EulerZ=ez;
|
||
|
} else if (AvP.PlayerType==I_Marine) {
|
||
|
if (TauntSoundPlayed==0) {
|
||
|
/* That should make sure we don't get more than one. */
|
||
|
if (playerStatusPtr->soundHandle==SOUND_NOACTIVEINDEX) {
|
||
|
PlayMarineScream(0,SC_Taunt,0,&playerStatusPtr->soundHandle,NULL);
|
||
|
if(AvP.Network!=I_No_Network) netGameData.myLastScream=SC_Taunt;
|
||
|
TauntSoundPlayed=1;
|
||
|
}
|
||
|
}
|
||
|
} else if (AvP.PlayerType==I_Predator) {
|
||
|
if (TauntSoundPlayed==0) {
|
||
|
/* That should make sure we don't get more than one. */
|
||
|
if (playerStatusPtr->soundHandle==SOUND_NOACTIVEINDEX) {
|
||
|
PlayPredatorSound(0,PSC_Taunt,0,&playerStatusPtr->soundHandle,NULL);
|
||
|
if(AvP.Network!=I_No_Network) netGameData.myLastScream=PSC_Taunt;
|
||
|
TauntSoundPlayed=1;
|
||
|
}
|
||
|
}
|
||
|
} else {
|
||
|
GLOBALASSERT(0);
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
/* Decay alien superhealth. */
|
||
|
if (AvP.PlayerType==I_Alien) {
|
||
|
NPC_DATA *NpcData;
|
||
|
|
||
|
switch (AvP.Difficulty) {
|
||
|
case I_Easy:
|
||
|
NpcData=GetThisNpcData(I_PC_Alien_Easy);
|
||
|
break;
|
||
|
default:
|
||
|
case I_Medium:
|
||
|
NpcData=GetThisNpcData(I_PC_Alien_Medium);
|
||
|
break;
|
||
|
case I_Hard:
|
||
|
NpcData=GetThisNpcData(I_PC_Alien_Hard);
|
||
|
break;
|
||
|
case I_Impossible:
|
||
|
NpcData=GetThisNpcData(I_PC_Alien_Impossible);
|
||
|
break;
|
||
|
}
|
||
|
LOCALASSERT(NpcData);
|
||
|
|
||
|
if (Player->ObStrategyBlock->SBDamageBlock.Health>(NpcData->StartingStats.Health<<ONE_FIXED_SHIFT)) {
|
||
|
/* Decay health a bit. */
|
||
|
Player->ObStrategyBlock->SBDamageBlock.Health-=(NormalFrameTime);
|
||
|
if (Player->ObStrategyBlock->SBDamageBlock.Health<(NpcData->StartingStats.Health<<ONE_FIXED_SHIFT)) {
|
||
|
Player->ObStrategyBlock->SBDamageBlock.Health=NpcData->StartingStats.Health<<ONE_FIXED_SHIFT;
|
||
|
}
|
||
|
PlayerStatusPtr->Health=Player->ObStrategyBlock->SBDamageBlock.Health;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void PlayerIsDamaged(STRATEGYBLOCK *sbPtr, DAMAGE_PROFILE *damage, int multiplier,VECTORCH* incoming)
|
||
|
{
|
||
|
int rand = FastRandom();
|
||
|
int pitch = (rand & 255) - 128;
|
||
|
int deltaHealth;
|
||
|
int deltaArmour;
|
||
|
|
||
|
/* access the extra data hanging off the strategy block */
|
||
|
PLAYER_STATUS *playerStatusPtr= (PLAYER_STATUS *) (sbPtr->SBdataptr);
|
||
|
GLOBALASSERT(playerStatusPtr);
|
||
|
|
||
|
deltaHealth=playerStatusPtr->Health-sbPtr->SBDamageBlock.Health;
|
||
|
deltaArmour=playerStatusPtr->Armour-sbPtr->SBDamageBlock.Armour;
|
||
|
|
||
|
CurrentGameStats_DamageTaken(deltaHealth,deltaArmour);
|
||
|
|
||
|
/* Patrick 4/8/97--------------------------------------------------
|
||
|
A little hack-et to make the predator tougher in multiplayer games
|
||
|
------------------------------------------------------------------*/
|
||
|
//if((AvP.Network!=I_No_Network)&&(AvP.PlayerType==I_Predator)) damage>>=1;
|
||
|
/* ChrisF 16/9/97 No, predators are now... wait for it... tough. */
|
||
|
|
||
|
if (playerStatusPtr->IsAlive)
|
||
|
{
|
||
|
#if 0
|
||
|
damage <<= 16;
|
||
|
if (playerStatusPtr->Armour > 0)
|
||
|
{
|
||
|
if (playerStatusPtr->Armour >= damage/2)
|
||
|
{
|
||
|
playerStatusPtr->Armour -= damage/2;
|
||
|
playerStatusPtr->Health -= damage/4;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
damage -= playerStatusPtr->Armour*2;
|
||
|
playerStatusPtr->Health -= playerStatusPtr->Armour/2 + damage;
|
||
|
playerStatusPtr->Armour = 0;
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
playerStatusPtr->Health -= damage;
|
||
|
}
|
||
|
#endif
|
||
|
{
|
||
|
int maxTilt = deltaHealth>>12;
|
||
|
int halfTilt = maxTilt/2;
|
||
|
if (maxTilt)
|
||
|
{
|
||
|
HeadOrientation.EulerX = (FastRandom()%maxTilt)-halfTilt;
|
||
|
HeadOrientation.EulerY = (FastRandom()%maxTilt)-halfTilt;
|
||
|
HeadOrientation.EulerZ = (FastRandom()%maxTilt)-halfTilt;
|
||
|
|
||
|
if (HeadOrientation.EulerX < 0) HeadOrientation.EulerX += 4096;
|
||
|
if (HeadOrientation.EulerY < 0) HeadOrientation.EulerY += 4096;
|
||
|
if (HeadOrientation.EulerZ < 0) HeadOrientation.EulerZ += 4096;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if ((playerStatusPtr->soundHandle==SOUND_NOACTIVEINDEX)&&(deltaHealth||deltaArmour)) {
|
||
|
switch (AvP.PlayerType)
|
||
|
{
|
||
|
case I_Alien:
|
||
|
{
|
||
|
if ((damage->Impact==0)
|
||
|
&&(damage->Cutting==0)
|
||
|
&&(damage->Penetrative==0)
|
||
|
&&(damage->Fire>0)
|
||
|
&&(damage->Electrical==0)
|
||
|
&&(damage->Acid==0)
|
||
|
) {
|
||
|
PlayAlienSound(0,ASC_PC_OnFire,pitch,&playerStatusPtr->soundHandle,NULL);
|
||
|
if(AvP.Network!=I_No_Network) netGameData.myLastScream=ASC_PC_OnFire;
|
||
|
} else {
|
||
|
PlayAlienSound(0,ASC_Scream_Hurt,pitch,&playerStatusPtr->soundHandle,NULL);
|
||
|
if(AvP.Network!=I_No_Network) netGameData.myLastScream=ASC_Scream_Hurt;
|
||
|
}
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
case I_Marine:
|
||
|
{
|
||
|
if (damage->Id==AMMO_FACEHUGGER) {
|
||
|
PlayMarineScream(0,SC_Facehugged,pitch,&playerStatusPtr->soundHandle,NULL);
|
||
|
} else if (damage->Id==AMMO_FALLING_POSTMAX) {
|
||
|
PlayMarineScream(0,SC_Falling,pitch,&playerStatusPtr->soundHandle,NULL);
|
||
|
} else if ((damage->Impact==0)
|
||
|
&&(damage->Cutting==0)
|
||
|
&&(damage->Penetrative==0)
|
||
|
&&(damage->Fire==0)
|
||
|
&&(damage->Electrical==0)
|
||
|
&&(damage->Acid>0)
|
||
|
) {
|
||
|
PlayMarineScream(0,SC_Acid,pitch,&playerStatusPtr->soundHandle,NULL);
|
||
|
if(AvP.Network!=I_No_Network) netGameData.myLastScream=SC_Acid;
|
||
|
} else if ((damage->Impact==0)
|
||
|
&&(damage->Cutting==0)
|
||
|
&&(damage->Penetrative==0)
|
||
|
&&(damage->Fire>0)
|
||
|
&&(damage->Electrical==0)
|
||
|
&&(damage->Acid==0)
|
||
|
) {
|
||
|
PlayMarineScream(0,SC_PC_OnFire,pitch,&playerStatusPtr->soundHandle,NULL);
|
||
|
if(AvP.Network!=I_No_Network) netGameData.myLastScream=SC_PC_OnFire;
|
||
|
} else {
|
||
|
PlayMarineScream(0,SC_Pain,pitch,&playerStatusPtr->soundHandle,NULL);
|
||
|
if(AvP.Network!=I_No_Network) netGameData.myLastScream=SC_Pain;
|
||
|
}
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
case I_Predator:
|
||
|
{
|
||
|
if (damage->Id==AMMO_FACEHUGGER) {
|
||
|
PlayPredatorSound(0,PSC_Facehugged,pitch,&playerStatusPtr->soundHandle,NULL);
|
||
|
} else if ((damage->Impact==0)
|
||
|
&&(damage->Cutting==0)
|
||
|
&&(damage->Penetrative==0)
|
||
|
&&(damage->Fire==0)
|
||
|
&&(damage->Electrical==0)
|
||
|
&&(damage->Acid>0)
|
||
|
) {
|
||
|
PlayPredatorSound(0,PSC_Acid,pitch,&playerStatusPtr->soundHandle,NULL);
|
||
|
if(AvP.Network!=I_No_Network) netGameData.myLastScream=PSC_Acid;
|
||
|
} else if ((damage->Impact==0)
|
||
|
&&(damage->Cutting==0)
|
||
|
&&(damage->Penetrative==0)
|
||
|
&&(damage->Fire>0)
|
||
|
&&(damage->Electrical==0)
|
||
|
&&(damage->Acid==0)
|
||
|
) {
|
||
|
PlayPredatorSound(0,PSC_PC_OnFire,pitch,&playerStatusPtr->soundHandle,NULL);
|
||
|
if(AvP.Network!=I_No_Network) netGameData.myLastScream=PSC_PC_OnFire;
|
||
|
} else {
|
||
|
PlayPredatorSound(0,PSC_Scream_Hurt,pitch,&playerStatusPtr->soundHandle,NULL);
|
||
|
if(AvP.Network!=I_No_Network) netGameData.myLastScream=PSC_Scream_Hurt;
|
||
|
}
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
default:
|
||
|
{
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
playerNoise=1;
|
||
|
/* Alert marines, pretty much whoever you are. */
|
||
|
if (AvP.PlayerType==I_Marine) {
|
||
|
PointAlert(3, &Player->ObStrategyBlock->DynPtr->Position);
|
||
|
} else {
|
||
|
#if 0
|
||
|
PointAlert(2, &Player->ObStrategyBlock->DynPtr->Position);
|
||
|
#endif
|
||
|
}
|
||
|
}
|
||
|
|
||
|
{
|
||
|
NPC_DATA *NpcData;
|
||
|
int scaled_DeltaHealth;
|
||
|
|
||
|
switch (AvP.PlayerType)
|
||
|
{
|
||
|
case I_Marine:
|
||
|
switch (AvP.Difficulty) {
|
||
|
case I_Easy:
|
||
|
NpcData=GetThisNpcData(I_PC_Marine_Easy);
|
||
|
break;
|
||
|
default:
|
||
|
case I_Medium:
|
||
|
NpcData=GetThisNpcData(I_PC_Marine_Medium);
|
||
|
break;
|
||
|
case I_Hard:
|
||
|
NpcData=GetThisNpcData(I_PC_Marine_Hard);
|
||
|
break;
|
||
|
case I_Impossible:
|
||
|
NpcData=GetThisNpcData(I_PC_Marine_Impossible);
|
||
|
break;
|
||
|
}
|
||
|
break;
|
||
|
case I_Alien:
|
||
|
switch (AvP.Difficulty) {
|
||
|
case I_Easy:
|
||
|
NpcData=GetThisNpcData(I_PC_Alien_Easy);
|
||
|
break;
|
||
|
default:
|
||
|
case I_Medium:
|
||
|
NpcData=GetThisNpcData(I_PC_Alien_Medium);
|
||
|
break;
|
||
|
case I_Hard:
|
||
|
NpcData=GetThisNpcData(I_PC_Alien_Hard);
|
||
|
break;
|
||
|
case I_Impossible:
|
||
|
NpcData=GetThisNpcData(I_PC_Alien_Impossible);
|
||
|
break;
|
||
|
}
|
||
|
break;
|
||
|
case I_Predator:
|
||
|
switch (AvP.Difficulty) {
|
||
|
case I_Easy:
|
||
|
NpcData=GetThisNpcData(I_PC_Predator_Easy);
|
||
|
break;
|
||
|
default:
|
||
|
case I_Medium:
|
||
|
NpcData=GetThisNpcData(I_PC_Predator_Medium);
|
||
|
break;
|
||
|
case I_Hard:
|
||
|
NpcData=GetThisNpcData(I_PC_Predator_Hard);
|
||
|
break;
|
||
|
case I_Impossible:
|
||
|
NpcData=GetThisNpcData(I_PC_Predator_Impossible);
|
||
|
break;
|
||
|
}
|
||
|
break;
|
||
|
default:
|
||
|
LOCALASSERT(0);
|
||
|
break;
|
||
|
}
|
||
|
/* Compute scaled deltaHealth... */
|
||
|
scaled_DeltaHealth=MUL_FIXED(deltaHealth,100);
|
||
|
scaled_DeltaHealth=DIV_FIXED(scaled_DeltaHealth,NpcData->StartingStats.Health);
|
||
|
|
||
|
if (scaled_DeltaHealth>PlayerDamagedOverlayIntensity)
|
||
|
{
|
||
|
PlayerDamagedOverlayIntensity=scaled_DeltaHealth;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (deltaHealth>ONE_FIXED)
|
||
|
{
|
||
|
VECTORCH abovePosition = Global_VDB_Ptr->VDB_World;
|
||
|
abovePosition.vy-=1000;
|
||
|
switch (AvP.PlayerType)
|
||
|
{
|
||
|
case I_Alien:
|
||
|
MakeBloodExplosion(&Global_VDB_Ptr->VDB_World, 127, &abovePosition, deltaHealth/ONE_FIXED, PARTICLE_ALIEN_BLOOD);
|
||
|
break;
|
||
|
case I_Marine:
|
||
|
MakeBloodExplosion(&Global_VDB_Ptr->VDB_World, 127, &abovePosition, deltaHealth/ONE_FIXED, PARTICLE_HUMAN_BLOOD);
|
||
|
break;
|
||
|
case I_Predator:
|
||
|
MakeBloodExplosion(&Global_VDB_Ptr->VDB_World, 127, &abovePosition, deltaHealth/ONE_FIXED, PARTICLE_PREDATOR_BLOOD);
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (sbPtr->SBDamageBlock.Health <= 0)
|
||
|
{
|
||
|
if (playerStatusPtr->IsImmortal) sbPtr->SBDamageBlock.Health=0;
|
||
|
else
|
||
|
{
|
||
|
PlayerIsDead(damage,multiplier,incoming);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
playerStatusPtr->Health=sbPtr->SBDamageBlock.Health;
|
||
|
playerStatusPtr->Armour=sbPtr->SBDamageBlock.Armour;
|
||
|
|
||
|
}
|
||
|
}
|
||
|
|
||
|
extern EULER deathTargetOrientation;
|
||
|
extern int deathFadeLevel;
|
||
|
extern int weaponHandle;
|
||
|
|
||
|
static void PlayerIsDead(DAMAGE_PROFILE* damage,int multiplier,VECTORCH* incoming)
|
||
|
{
|
||
|
STRATEGYBLOCK *sbPtr = Player->ObStrategyBlock;
|
||
|
PLAYER_STATUS *playerStatusPtr= (PLAYER_STATUS *) (sbPtr->SBdataptr);
|
||
|
DYNAMICSBLOCK *dynPtr = sbPtr->DynPtr;
|
||
|
|
||
|
/* Stop pred hud sound. */
|
||
|
if(predHUDSoundHandle != SOUND_NOACTIVEINDEX) {
|
||
|
Sound_Stop(predHUDSoundHandle);
|
||
|
}
|
||
|
if(predOVision_SoundHandle != SOUND_NOACTIVEINDEX) {
|
||
|
Sound_Stop(predOVision_SoundHandle);
|
||
|
}
|
||
|
if(weaponHandle != SOUND_NOACTIVEINDEX) {
|
||
|
Sound_Stop(weaponHandle);
|
||
|
}
|
||
|
|
||
|
// Do some death sounds
|
||
|
|
||
|
switch (AvP.PlayerType)
|
||
|
{
|
||
|
case I_Alien:
|
||
|
{
|
||
|
PlayAlienSound(0,ASC_Scream_Dying,0,NULL,NULL);
|
||
|
break;
|
||
|
}
|
||
|
case I_Marine:
|
||
|
{
|
||
|
if (damage->Id==AMMO_FACEHUGGER) {
|
||
|
PlayMarineScream(0,SC_Facehugged,0,NULL,NULL);
|
||
|
} else {
|
||
|
PlayMarineScream(0,SC_Death,0,NULL,NULL);
|
||
|
}
|
||
|
break;
|
||
|
}
|
||
|
case I_Predator:
|
||
|
{
|
||
|
if (damage->Id==AMMO_FACEHUGGER) {
|
||
|
PlayPredatorSound(0,PSC_Facehugged,0,NULL,NULL);
|
||
|
} else {
|
||
|
PlayPredatorSound(0,PSC_Scream_Dying,0,NULL,NULL);
|
||
|
}
|
||
|
|
||
|
{
|
||
|
VECTORCH abovePosition = Global_VDB_Ptr->VDB_World;
|
||
|
abovePosition.vy-=1000;
|
||
|
MakeBloodExplosion(&Global_VDB_Ptr->VDB_World, 127, &abovePosition, 200, PARTICLE_PREDATOR_BLOOD);
|
||
|
}
|
||
|
break;
|
||
|
}
|
||
|
default:
|
||
|
{
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/* Well, it was nice knowing you. */
|
||
|
//playerStatusPtr->Health = 0;
|
||
|
sbPtr->SBDamageBlock.Health=0;
|
||
|
playerStatusPtr->IsAlive = 0;
|
||
|
|
||
|
/* make player fall to the ground */
|
||
|
// Player->ObShape=I_ShapeMarinePlayerLieDown;
|
||
|
// MapBlockInit(Player);
|
||
|
|
||
|
/* give player a little bounce */
|
||
|
dynPtr->Elasticity = 16384;
|
||
|
/* but a lot of friction */
|
||
|
// dynPtr->Friction = 1<<20;
|
||
|
// dynPtr->Mass = 1<<20;
|
||
|
|
||
|
/* cancel any velocity */
|
||
|
dynPtr->LinVelocity.vx = 0;
|
||
|
dynPtr->LinVelocity.vy = 0;
|
||
|
dynPtr->LinVelocity.vz = 0;
|
||
|
|
||
|
deathTargetOrientation.EulerX = 0;//1024-(FastRandom()&255);
|
||
|
deathFadeLevel=65536;
|
||
|
|
||
|
/* if in single player, fade out sound... */
|
||
|
if (AvP.Network==I_No_Network)
|
||
|
{
|
||
|
SoundSys_FadeOut();
|
||
|
}
|
||
|
|
||
|
if (AvP.PlayerType == I_Alien)
|
||
|
{
|
||
|
sbPtr->DynPtr->UseStandardGravity=1;
|
||
|
}
|
||
|
|
||
|
/* network support... */
|
||
|
#if SupportWindows95
|
||
|
if(AvP.Network!=I_No_Network)
|
||
|
{
|
||
|
playerStatusPtr->MyCorpse=MakeNewCorpse();
|
||
|
AddNetMsg_PlayerKilled((*((int *)(&(playerStatusPtr->MyCorpse->SBname[4])))),damage);
|
||
|
|
||
|
/*---------------------------------------------------------**
|
||
|
** handle various special body being torn apart cases **
|
||
|
**---------------------------------------------------------*/
|
||
|
|
||
|
/*Note that we need to apply the damage to the corpse before we can determine a
|
||
|
suitable death anim sequence*/
|
||
|
if(damage)
|
||
|
{
|
||
|
HMODELCONTROLLER* hmodel=playerStatusPtr->MyCorpse->SBdptr->HModelControlBlock;
|
||
|
//was the player killed by a jaw attack?
|
||
|
if(damage->Id==AMMO_ALIEN_BITE_KILLSECTION && AvP.PlayerType!=I_Alien)
|
||
|
{
|
||
|
//knock the head of the corpse
|
||
|
SECTION_DATA *head;
|
||
|
head=GetThisSectionData(playerStatusPtr->MyCorpse->SBdptr->HModelControlBlock->section_data,"head");
|
||
|
//do lots of damage to it
|
||
|
if(head)
|
||
|
{
|
||
|
CauseDamageToHModel(playerStatusPtr->MyCorpse->SBdptr->HModelControlBlock,playerStatusPtr->MyCorpse, &TemplateAmmo[AMMO_ALIEN_BITE_KILLSECTION].MaxDamage[AvP.Difficulty],
|
||
|
ONE_FIXED,head,NULL,NULL,0);
|
||
|
}
|
||
|
//play the head being bitten off sound
|
||
|
Sound_Play(SID_ALIEN_JAW_ATTACK,"d",&(Player->ObStrategyBlock->DynPtr->Position));
|
||
|
|
||
|
}
|
||
|
//chopped by predator disc?
|
||
|
else if(damage->Id==AMMO_PRED_DISC && AvP.PlayerType!=I_Predator)
|
||
|
{
|
||
|
SECTION_DATA *firstSectionPtr;
|
||
|
SECTION_DATA *chest_section=0;
|
||
|
|
||
|
firstSectionPtr=hmodel->section_data;
|
||
|
LOCALASSERT(firstSectionPtr);
|
||
|
LOCALASSERT(firstSectionPtr->flags§ion_data_initialised);
|
||
|
|
||
|
/* look for the object's torso in preference */
|
||
|
chest_section =GetThisSectionData(hmodel->section_data,"chest");
|
||
|
|
||
|
if (chest_section)
|
||
|
{
|
||
|
CauseDamageToHModel(hmodel,playerStatusPtr->MyCorpse,damage, ONE_FIXED, chest_section,incoming,&chest_section->World_Offset,0);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
CauseDamageToObject(playerStatusPtr->MyCorpse,damage, ONE_FIXED,incoming);
|
||
|
}
|
||
|
}
|
||
|
//blown up by shoulder cannon?
|
||
|
else if(damage->Id==AMMO_PLASMACASTER_PCKILL && AvP.PlayerType!=I_Predator)
|
||
|
{
|
||
|
SECTION_DATA *firstSectionPtr;
|
||
|
SECTION_DATA *chest_section=0;
|
||
|
|
||
|
firstSectionPtr=hmodel->section_data;
|
||
|
LOCALASSERT(firstSectionPtr);
|
||
|
LOCALASSERT(firstSectionPtr->flags§ion_data_initialised);
|
||
|
|
||
|
/* look for the object's torso in preference */
|
||
|
chest_section =GetThisSectionData(hmodel->section_data,"chest");
|
||
|
|
||
|
if (chest_section)
|
||
|
{
|
||
|
//spherical blood explosion for aliens
|
||
|
if(AvP.PlayerType==I_Alien)
|
||
|
CauseDamageToHModel(hmodel,playerStatusPtr->MyCorpse,damage, ONE_FIXED, chest_section,NULL,&chest_section->World_Offset,0);
|
||
|
else
|
||
|
CauseDamageToHModel(hmodel,playerStatusPtr->MyCorpse,damage, ONE_FIXED, chest_section,incoming,&chest_section->World_Offset,0);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
CauseDamageToObject(playerStatusPtr->MyCorpse,damage, ONE_FIXED,NULL);
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
SECTION_DATA *section_data=0;
|
||
|
if(MyHitBodyPartId!=-1)
|
||
|
{
|
||
|
//we have the id of the section that was hit when we died
|
||
|
//so try to find the section
|
||
|
section_data=GetThisSectionData_FromID(hmodel->section_data,MyHitBodyPartId);
|
||
|
}
|
||
|
//damage the corpse with the fatal blow
|
||
|
if(section_data)
|
||
|
{
|
||
|
DISPLAYBLOCK *fragged_section=0;
|
||
|
fragged_section=CauseDamageToHModel(hmodel,playerStatusPtr->MyCorpse,damage,
|
||
|
multiplier,section_data,incoming,NULL,0);
|
||
|
|
||
|
if(fragged_section && incoming && damage->Id==AMMO_PRED_RIFLE)
|
||
|
{
|
||
|
//a speargun has fragged off a body part , so we need to create a spear
|
||
|
VECTORCH direction=*incoming;
|
||
|
RotateVector(&direction,&Player->ObMat);
|
||
|
CreateSpearPossiblyWithFragment(fragged_section,&fragged_section->ObWorld,&direction);
|
||
|
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
CauseDamageToObject(playerStatusPtr->MyCorpse,damage,multiplier,incoming);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
/*---------------------------------**
|
||
|
** Choose death anim sequence **
|
||
|
**---------------------------------*/
|
||
|
{
|
||
|
int deathId;
|
||
|
switch(AvP.PlayerType)
|
||
|
{
|
||
|
case I_Marine :
|
||
|
deathId = Deduce_PlayerMarineDeathSequence(playerStatusPtr->MyCorpse,damage,multiplier,incoming);
|
||
|
break;
|
||
|
|
||
|
case I_Alien :
|
||
|
deathId = Deduce_PlayerAlienDeathSequence(playerStatusPtr->MyCorpse,damage,multiplier,incoming);
|
||
|
break;
|
||
|
|
||
|
case I_Predator :
|
||
|
deathId = Deduce_PlayerPredatorDeathSequence(playerStatusPtr->MyCorpse,damage,multiplier,incoming);
|
||
|
break;
|
||
|
}
|
||
|
//apply the animation
|
||
|
ApplyCorpseDeathAnim(playerStatusPtr->MyCorpse,deathId);
|
||
|
//tell everyone else about the chosen death
|
||
|
AddNetMsg_PlayerDeathAnim(deathId,*(int*)&playerStatusPtr->MyCorpse->SBname[4]);
|
||
|
|
||
|
}
|
||
|
|
||
|
// if(AvP.Network==I_Host) DoNetScoresForHostDeath();
|
||
|
|
||
|
//does this death require a change in character type?
|
||
|
if(netGameData.gameType==NGT_LastManStanding)
|
||
|
{
|
||
|
//Am I a marine or predator?
|
||
|
if(AvP.PlayerType!=I_Alien)
|
||
|
{
|
||
|
//was I killed by an alien?
|
||
|
if(myNetworkKillerId && myNetworkKillerId!=AVPDPNetID)
|
||
|
{
|
||
|
int killer_index=PlayerIdInPlayerList(myNetworkKillerId);
|
||
|
GLOBALASSERT(killer_index!=NET_IDNOTINPLAYERLIST);
|
||
|
if(netGameData.playerData[killer_index].characterType==NGCT_Alien)
|
||
|
{
|
||
|
//set the next character to be an alien then
|
||
|
netGameData.myNextCharacterType=NGCT_Alien;
|
||
|
}
|
||
|
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
//suicide , so become an alien anyway
|
||
|
netGameData.myNextCharacterType=NGCT_Alien;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
else if(netGameData.gameType==NGT_PredatorTag || netGameData.gameType==NGT_AlienTag)
|
||
|
{
|
||
|
//we may need to change character
|
||
|
extern void SpeciesTag_DetermineMyNextCharacterType();
|
||
|
SpeciesTag_DetermineMyNextCharacterType();
|
||
|
}
|
||
|
}
|
||
|
#endif
|
||
|
if (playerStatusPtr->soundHandle!=SOUND_NOACTIVEINDEX) {
|
||
|
Sound_Stop(playerStatusPtr->soundHandle);
|
||
|
}
|
||
|
if (playerStatusPtr->soundHandle3!=SOUND_NOACTIVEINDEX) {
|
||
|
Sound_Stop(playerStatusPtr->soundHandle3);
|
||
|
}
|
||
|
|
||
|
/* KJL 15:36:41 10/09/98 - don't hang around on my behalf */
|
||
|
DisengageGrapplingHook();
|
||
|
|
||
|
}
|
||
|
|
||
|
void ActivateSelfDestructSequence (int seconds)
|
||
|
{
|
||
|
// Currently does nothing, called when sequence is activated
|
||
|
|
||
|
if (AvP.DestructTimer==-1) {
|
||
|
AvP.DestructTimer=ONE_FIXED*seconds; //2 1/2 mins.
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void DeInitialisePlayer(void) {
|
||
|
/* I thought it would be logical to put it here... */
|
||
|
|
||
|
int slot = MAX_NO_OF_WEAPON_SLOTS;
|
||
|
PLAYER_STATUS *playerStatusPtr= (PLAYER_STATUS *) (Player->ObStrategyBlock->SBdataptr);
|
||
|
|
||
|
do {
|
||
|
TXACTRLBLK *txactrl,*txactrl_next;
|
||
|
PLAYER_WEAPON_DATA *wdPtr = &PlayerStatusBlock.WeaponSlot[--slot];
|
||
|
|
||
|
txactrl_next = wdPtr->TxAnimCtrl;
|
||
|
|
||
|
while(txactrl_next)
|
||
|
{
|
||
|
txactrl = txactrl_next;
|
||
|
txactrl_next = txactrl->tac_next;
|
||
|
DeallocateMem((void*)txactrl);
|
||
|
}
|
||
|
|
||
|
wdPtr->TxAnimCtrl=NULL;
|
||
|
} while(slot);
|
||
|
|
||
|
#if 0 //this hmodel isn't being set up for the moment - Richard
|
||
|
Dispel_HModel(&playerStatusPtr->HModelController);
|
||
|
#endif
|
||
|
|
||
|
}
|
||
|
|
||
|
static int cloakDebounce = 1;
|
||
|
|
||
|
void InitPlayerCloakingSystem(void)
|
||
|
{
|
||
|
PLAYER_STATUS *playerStatusPtr= (PLAYER_STATUS *) (Player->ObStrategyBlock->SBdataptr);
|
||
|
LOCALASSERT(playerStatusPtr);
|
||
|
|
||
|
playerStatusPtr->cloakOn = 0;
|
||
|
playerStatusPtr->cloakPositionGivenAway = 0;
|
||
|
playerStatusPtr->CloakingEffectiveness = 0;
|
||
|
|
||
|
playerStatusPtr->FieldCharge = PLAYERCLOAK_MAXENERGY;
|
||
|
playerStatusPtr->cloakPositionGivenAwayTimer = 0;
|
||
|
playerStatusPtr->PlasmaCasterCharge=0;
|
||
|
|
||
|
GimmeChargeCalls=0;
|
||
|
HtoHStrikes=0;
|
||
|
CurrentLightAtPlayer=0;
|
||
|
}
|
||
|
|
||
|
static void DoPlayerCloakingSystem(void)
|
||
|
{
|
||
|
extern int NormalFrameTime;
|
||
|
PLAYER_STATUS *playerStatusPtr= (PLAYER_STATUS *) (Player->ObStrategyBlock->SBdataptr);
|
||
|
LOCALASSERT(playerStatusPtr);
|
||
|
|
||
|
if(AvP.PlayerType!=I_Predator) return;
|
||
|
if(!(playerStatusPtr->IsAlive)) return;
|
||
|
|
||
|
/* Handle controls. */
|
||
|
if (playerStatusPtr->Mvt_InputRequests.Flags.Rqst_ChangeVision)
|
||
|
{
|
||
|
if (cloakDebounce)
|
||
|
{
|
||
|
cloakDebounce = 0;
|
||
|
if (playerStatusPtr->cloakOn)
|
||
|
{
|
||
|
Sound_Play(SID_PRED_CLOAKOFF,"h");
|
||
|
playerStatusPtr->cloakOn = 0;
|
||
|
//playerNoise=1;
|
||
|
} else {
|
||
|
/* Check validity. */
|
||
|
if ((playerStatusPtr->FieldCharge>CloakThreshold)
|
||
|
&&(playerStatusPtr->FieldCharge>CloakPowerOnDrain)) {
|
||
|
|
||
|
PLAYER_WEAPON_DATA *weaponPtr;
|
||
|
TEMPLATE_WEAPON_DATA *twPtr;
|
||
|
|
||
|
weaponPtr = &(playerStatusPtr->WeaponSlot[playerStatusPtr->SelectedWeaponSlot]);
|
||
|
twPtr = &TemplateWeapon[weaponPtr->WeaponIDNumber];
|
||
|
if (!(((weaponPtr->CurrentState==WEAPONSTATE_FIRING_PRIMARY)||(weaponPtr->CurrentState==WEAPONSTATE_FIRING_SECONDARY))
|
||
|
&&(twPtr->FireWhenCloaked==0)))
|
||
|
{
|
||
|
playerStatusPtr->FieldCharge-=CloakPowerOnDrain;
|
||
|
CurrentGameStats_ChargeUsed(CloakPowerOnDrain);
|
||
|
playerStatusPtr->cloakOn = 1;
|
||
|
playerStatusPtr->CloakingEffectiveness = 0;
|
||
|
Sound_Play(SID_PRED_CLOAKON,"h");
|
||
|
//playerNoise=1;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
cloakDebounce = 1;
|
||
|
|
||
|
if (playerStatusPtr->cloakOn)
|
||
|
{
|
||
|
int maxPossibleEffectiveness;
|
||
|
VECTORCH velocity;
|
||
|
DYNAMICSBLOCK *dynPtr=Player->ObStrategyBlock->DynPtr;
|
||
|
|
||
|
velocity.vx = dynPtr->Position.vx - dynPtr->PrevPosition.vx;
|
||
|
velocity.vy = dynPtr->Position.vy - dynPtr->PrevPosition.vy;
|
||
|
velocity.vz = dynPtr->Position.vz - dynPtr->PrevPosition.vz;
|
||
|
|
||
|
if (playerStatusPtr->IsMovingInWater)
|
||
|
{
|
||
|
maxPossibleEffectiveness = 0;
|
||
|
if(playerStatusPtr->soundHandleForPredatorCloakDamaged==SOUND_NOACTIVEINDEX)
|
||
|
Sound_Play(SID_PREDATOR_CLOAKING_DAMAGED,"el",playerStatusPtr->soundHandleForPredatorCloakDamaged);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
if(playerStatusPtr->soundHandleForPredatorCloakDamaged!=SOUND_NOACTIVEINDEX)
|
||
|
Sound_Stop(playerStatusPtr->soundHandleForPredatorCloakDamaged);
|
||
|
|
||
|
maxPossibleEffectiveness = ONE_FIXED - DIV_FIXED(Magnitude(&velocity)*2,NormalFrameTime);
|
||
|
if (maxPossibleEffectiveness<0) maxPossibleEffectiveness = 0;
|
||
|
}
|
||
|
|
||
|
playerStatusPtr->CloakingEffectiveness += NormalFrameTime;
|
||
|
if (playerStatusPtr->CloakingEffectiveness>maxPossibleEffectiveness)
|
||
|
{
|
||
|
playerStatusPtr->CloakingEffectiveness = maxPossibleEffectiveness;
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
playerStatusPtr->CloakingEffectiveness -= NormalFrameTime;
|
||
|
if (playerStatusPtr->CloakingEffectiveness<0)
|
||
|
{
|
||
|
playerStatusPtr->CloakingEffectiveness=0;
|
||
|
}
|
||
|
if(playerStatusPtr->soundHandleForPredatorCloakDamaged!=SOUND_NOACTIVEINDEX)
|
||
|
Sound_Stop(playerStatusPtr->soundHandleForPredatorCloakDamaged);
|
||
|
}
|
||
|
|
||
|
}
|
||
|
#if 1
|
||
|
|
||
|
/* position-given-away-timer runs whatever state the cloak is in */
|
||
|
if(playerStatusPtr->cloakPositionGivenAway)
|
||
|
{
|
||
|
playerStatusPtr->cloakPositionGivenAwayTimer-=NormalFrameTime;
|
||
|
if(playerStatusPtr->cloakPositionGivenAwayTimer<=0)
|
||
|
{
|
||
|
playerStatusPtr->cloakPositionGivenAwayTimer = 0;
|
||
|
playerStatusPtr->cloakPositionGivenAway = 0;
|
||
|
playerStatusPtr->CloakingEffectiveness = 0;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/* now sort out energy discharge/recharge */
|
||
|
if(playerStatusPtr->cloakOn)
|
||
|
{
|
||
|
int chargeUsed;
|
||
|
|
||
|
chargeUsed=MUL_FIXED(NormalFrameTime,CloakDrain);
|
||
|
|
||
|
if (playerStatusPtr->IsMovingInWater) {
|
||
|
chargeUsed<<=2;
|
||
|
}
|
||
|
|
||
|
if (chargeUsed>playerStatusPtr->FieldCharge) {
|
||
|
chargeUsed=playerStatusPtr->FieldCharge;
|
||
|
}
|
||
|
playerStatusPtr->FieldCharge -= chargeUsed;
|
||
|
CurrentGameStats_ChargeUsed(chargeUsed);
|
||
|
if(playerStatusPtr->FieldCharge <= 0)
|
||
|
{
|
||
|
playerStatusPtr->FieldCharge = 0;
|
||
|
playerStatusPtr->cloakOn = 0;
|
||
|
playerStatusPtr->Mvt_InputRequests.Flags.Rqst_ChangeVision = 1;
|
||
|
Sound_Play(SID_PRED_CLOAKOFF,"h");
|
||
|
//playerNoise=1;
|
||
|
}
|
||
|
|
||
|
/* TrickleCharge Difficulty Variation! */
|
||
|
if ((AvP.Difficulty==I_Hard)||(AvP.Difficulty==I_Impossible)) {
|
||
|
playerStatusPtr->FieldCharge += MUL_FIXED(NormalFrameTime,(TrickleCharge>>1));
|
||
|
} else {
|
||
|
playerStatusPtr->FieldCharge += MUL_FIXED(NormalFrameTime,TrickleCharge);
|
||
|
}
|
||
|
|
||
|
if(playerStatusPtr->FieldCharge > PLAYERCLOAK_MAXENERGY) {
|
||
|
playerStatusPtr->FieldCharge = PLAYERCLOAK_MAXENERGY;
|
||
|
}
|
||
|
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
if(playerStatusPtr->FieldCharge < PLAYERCLOAK_MAXENERGY)
|
||
|
{
|
||
|
|
||
|
/* TrickleCharge Difficulty Variation! */
|
||
|
if ((AvP.Difficulty==I_Hard)||(AvP.Difficulty==I_Impossible)) {
|
||
|
playerStatusPtr->FieldCharge += MUL_FIXED(NormalFrameTime,(TrickleCharge>>1));
|
||
|
} else {
|
||
|
playerStatusPtr->FieldCharge += MUL_FIXED(NormalFrameTime,TrickleCharge);
|
||
|
}
|
||
|
|
||
|
if(playerStatusPtr->FieldCharge > PLAYERCLOAK_MAXENERGY) {
|
||
|
playerStatusPtr->FieldCharge = PLAYERCLOAK_MAXENERGY;
|
||
|
}
|
||
|
|
||
|
#if 0
|
||
|
/* Infinite field charge? */
|
||
|
playerStatusPtr->FieldCharge = PLAYERCLOAK_MAXENERGY;
|
||
|
#endif
|
||
|
}
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
if (ShowPredoStats) {
|
||
|
/* for testing */
|
||
|
PrintDebuggingText("Cloak on: %d \n",playerStatusPtr->cloakOn);
|
||
|
PrintDebuggingText("Field Charge: %d \n",playerStatusPtr->FieldCharge);
|
||
|
{
|
||
|
int a;
|
||
|
/* Speargun ammo count */
|
||
|
a=SlotForThisWeapon(WEAPON_PRED_RIFLE);
|
||
|
if (a!=-1) {
|
||
|
PrintDebuggingText("Speargun Rounds: %d Clips: %d\n",(playerStatusPtr->WeaponSlot[a].PrimaryRoundsRemaining>>ONE_FIXED_SHIFT),playerStatusPtr->WeaponSlot[a].PrimaryMagazinesRemaining);
|
||
|
} else {
|
||
|
PrintDebuggingText("Speargun not possessed.\n");
|
||
|
}
|
||
|
|
||
|
}
|
||
|
PrintDebuggingText("Cloak given away: %d \n", playerStatusPtr->cloakPositionGivenAway);
|
||
|
PrintDebuggingText("Cloak given away timer: %d \n", playerStatusPtr->cloakPositionGivenAwayTimer);
|
||
|
PrintDebuggingText("Cloaking Effectiveness: %d \n", playerStatusPtr->CloakingEffectiveness);
|
||
|
PrintDebuggingText("Gimme_Charge Calls: %d \n",GimmeChargeCalls);
|
||
|
}
|
||
|
#if 1
|
||
|
/* now, if we are cloaked, lets see if we have given away our position...
|
||
|
if we have already given away our position, we may do so again */
|
||
|
if(playerStatusPtr->cloakOn)
|
||
|
{
|
||
|
PLAYER_WEAPON_DATA *weaponPtr;
|
||
|
TEMPLATE_WEAPON_DATA *twPtr;
|
||
|
|
||
|
weaponPtr = &(playerStatusPtr->WeaponSlot[playerStatusPtr->SelectedWeaponSlot]);
|
||
|
twPtr = &TemplateWeapon[weaponPtr->WeaponIDNumber];
|
||
|
|
||
|
/* weapon fire ?*/
|
||
|
if(((PlayerStatusPtr->WeaponSlot[PlayerStatusPtr->SelectedWeaponSlot].CurrentState==WEAPONSTATE_FIRING_PRIMARY)&&(!twPtr->PrimaryIsMeleeWeapon))||
|
||
|
((PlayerStatusPtr->WeaponSlot[PlayerStatusPtr->SelectedWeaponSlot].CurrentState==WEAPONSTATE_FIRING_SECONDARY)&&(!twPtr->SecondaryIsMeleeWeapon)))
|
||
|
{
|
||
|
playerStatusPtr->cloakPositionGivenAway = 1;
|
||
|
playerStatusPtr->cloakPositionGivenAwayTimer = PLAYERCLOAK_POSTIONGIVENAWAYTIME;
|
||
|
}
|
||
|
/* collision with npc ?*/
|
||
|
{
|
||
|
struct collisionreport *nextReport;
|
||
|
LOCALASSERT(Player->ObStrategyBlock->DynPtr);
|
||
|
nextReport = Player->ObStrategyBlock->DynPtr->CollisionReportPtr;
|
||
|
|
||
|
while(nextReport)
|
||
|
{
|
||
|
if(nextReport->ObstacleSBPtr)
|
||
|
{
|
||
|
if((nextReport->ObstacleSBPtr->I_SBtype==I_BehaviourAlien)||
|
||
|
(nextReport->ObstacleSBPtr->I_SBtype==I_BehaviourMarine)||
|
||
|
(nextReport->ObstacleSBPtr->I_SBtype==I_BehaviourXenoborg)||
|
||
|
(nextReport->ObstacleSBPtr->I_SBtype==I_BehaviourPredatorAlien)||
|
||
|
(nextReport->ObstacleSBPtr->I_SBtype==I_BehaviourQueenAlien)||
|
||
|
(nextReport->ObstacleSBPtr->I_SBtype==I_BehaviourFaceHugger)||
|
||
|
(nextReport->ObstacleSBPtr->I_SBtype==I_BehaviourSeal))
|
||
|
{
|
||
|
playerStatusPtr->cloakPositionGivenAway = 1;
|
||
|
playerStatusPtr->cloakPositionGivenAwayTimer = PLAYERCLOAK_POSTIONGIVENAWAYTIME;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
nextReport = nextReport->NextCollisionReportPtr;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
if (playerStatusPtr->cloakOn) {
|
||
|
CurrentGameStats_CloakOn();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void GimmeCharge(void) {
|
||
|
|
||
|
PLAYER_STATUS *playerStatusPtr= (PLAYER_STATUS *) (Player->ObStrategyBlock->SBdataptr);
|
||
|
LOCALASSERT(playerStatusPtr);
|
||
|
|
||
|
if(AvP.PlayerType!=I_Predator) return;
|
||
|
|
||
|
playerStatusPtr->FieldCharge = PLAYERCLOAK_MAXENERGY;
|
||
|
|
||
|
GimmeChargeCalls++;
|
||
|
|
||
|
}
|
||
|
|
||
|
#define AUTOSPOT_RANGE (1000)
|
||
|
|
||
|
int AlienPCIsCurrentlyVisible(int checktime,STRATEGYBLOCK *sbPtr) {
|
||
|
|
||
|
PLAYER_WEAPON_DATA *weaponPtr;
|
||
|
int range;
|
||
|
DYNAMICSBLOCK *dynPtr=(Player->ObStrategyBlock->DynPtr);
|
||
|
PLAYER_STATUS *playerStatusPtr= (PLAYER_STATUS *) (Player->ObStrategyBlock->SBdataptr);
|
||
|
LOCALASSERT(playerStatusPtr);
|
||
|
/* sbPtr is the viewer. */
|
||
|
|
||
|
if (AvP.PlayerType!=I_Alien) {
|
||
|
/* Just to be sure. */
|
||
|
return(1);
|
||
|
}
|
||
|
|
||
|
weaponPtr = &(playerStatusPtr->WeaponSlot[playerStatusPtr->SelectedWeaponSlot]);
|
||
|
|
||
|
/* Set a default range? */
|
||
|
range=-1;
|
||
|
/* Maybe we also need an autospot range. */
|
||
|
if (sbPtr) {
|
||
|
VECTORCH offset;
|
||
|
|
||
|
offset.vx=dynPtr->Position.vx-sbPtr->DynPtr->Position.vx;
|
||
|
offset.vy=dynPtr->Position.vy-sbPtr->DynPtr->Position.vy;
|
||
|
offset.vz=dynPtr->Position.vz-sbPtr->DynPtr->Position.vz;
|
||
|
|
||
|
range=Approximate3dMagnitude(&offset);
|
||
|
|
||
|
/* In fact, let's turn this around... */
|
||
|
|
||
|
if (playerStatusPtr->ShapeState==PMph_Standing) {
|
||
|
if (range>=(CurrentLightAtPlayer)+AUTOSPOT_RANGE) {
|
||
|
return(0);
|
||
|
}
|
||
|
} else {
|
||
|
if (range>=(CurrentLightAtPlayer>>1)+AUTOSPOT_RANGE) {
|
||
|
/* Half that range if crouching? */
|
||
|
return(0);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/* I guess, if we're in _pitch_ darkness... see nothing outside that range? */
|
||
|
if (CurrentLightAtPlayer<=2560) {
|
||
|
if (playerStatusPtr->ShapeState==PMph_Standing) {
|
||
|
if (range<=(CurrentLightAtPlayer)+AUTOSPOT_RANGE) {
|
||
|
return(1);
|
||
|
}
|
||
|
} else {
|
||
|
if (range<=(CurrentLightAtPlayer>>1)+AUTOSPOT_RANGE) {
|
||
|
/* Half that range if crouching? */
|
||
|
return(1);
|
||
|
}
|
||
|
}
|
||
|
return(0);
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
|
||
|
if (playerStatusPtr->ShapeState==PMph_Standing) {
|
||
|
/* Default to visible, unless stationary and in near darkness. */
|
||
|
if (weaponPtr->CurrentState!=WEAPONSTATE_IDLE) {
|
||
|
/* Don't even breathe. */
|
||
|
return(1);
|
||
|
}
|
||
|
if ((dynPtr->Position.vx!=dynPtr->PrevPosition.vx)||
|
||
|
(dynPtr->Position.vy!=dynPtr->PrevPosition.vy)||
|
||
|
(dynPtr->Position.vz!=dynPtr->PrevPosition.vz)) {
|
||
|
/* Stand perfectly still. */
|
||
|
return(1);
|
||
|
}
|
||
|
if (checktime) {
|
||
|
int chance;
|
||
|
/* There is a chance of being seen regardless. */
|
||
|
chance=32767; /* Lets say. */
|
||
|
if ((FastRandom()&65535)<chance) {
|
||
|
return(1);
|
||
|
}
|
||
|
}
|
||
|
if (CurrentLightAtPlayer<5000) {
|
||
|
return(0);
|
||
|
}
|
||
|
return(1);
|
||
|
} else {
|
||
|
int speed;
|
||
|
|
||
|
/* Crouching. Default to cloaked, unless they get 'lucky'. */
|
||
|
if (weaponPtr->CurrentState==WEAPONSTATE_FIRING_PRIMARY) {
|
||
|
/* Just don't claw. */
|
||
|
return(1);
|
||
|
}
|
||
|
|
||
|
if (CurrentLightAtPlayer>17000) {
|
||
|
/* It's too bright, mere crouching won't save you. */
|
||
|
return(1);
|
||
|
}
|
||
|
#if 0
|
||
|
if ((dynPtr->Position.vx!=dynPtr->PrevPosition.vx)||
|
||
|
(dynPtr->Position.vy!=dynPtr->PrevPosition.vy)||
|
||
|
(dynPtr->Position.vz!=dynPtr->PrevPosition.vz)) {
|
||
|
/* Stand perfectly still? */
|
||
|
return(1);
|
||
|
}
|
||
|
#else
|
||
|
speed=Approximate3dMagnitude(&Player->ObStrategyBlock->DynPtr->LinVelocity);
|
||
|
/* Speed: < 5000 = standing. > 22000 = jumping.
|
||
|
In practice, walk/fall = 18000 ish, jump = 27000 ish. */
|
||
|
if (speed>22000) {
|
||
|
/* Not getting away with that, mate. */
|
||
|
return(1);
|
||
|
}
|
||
|
speed-=5000;
|
||
|
if (speed<0) {
|
||
|
speed=0;
|
||
|
}
|
||
|
/* Now should be 0->17000 ish. */
|
||
|
speed<<=1;
|
||
|
#endif
|
||
|
if (checktime) {
|
||
|
int chance;
|
||
|
/* There is a chance of being seen. */
|
||
|
chance=CurrentLightAtPlayer-5000;
|
||
|
#if 1
|
||
|
chance+=speed;
|
||
|
#endif
|
||
|
if ((FastRandom()&65535)<chance) {
|
||
|
return(1);
|
||
|
}
|
||
|
}
|
||
|
return(0);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
#if 0
|
||
|
static void HandlePredatorVisionModes(void)
|
||
|
{
|
||
|
extern unsigned char DebouncedKeyboardInput[];
|
||
|
|
||
|
if (DebouncedKeyboardInput[KEY_K])
|
||
|
{
|
||
|
ChangePredatorVisionMode();
|
||
|
}
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
void ShowAdjacencies(void) {
|
||
|
|
||
|
int moduleCounter;
|
||
|
AIMODULE **AdjModuleRefPtr;
|
||
|
AIMODULE *thisModule;
|
||
|
AIMODULE *ModuleListPointer;
|
||
|
|
||
|
/* Utility function... */
|
||
|
PrintDebuggingText("Adjacencies FROM Player's Module (%s):\n",
|
||
|
(*(playerPherModule->m_aimodule->m_module_ptrs))->name);
|
||
|
|
||
|
thisModule=playerPherModule->m_aimodule;
|
||
|
|
||
|
AdjModuleRefPtr = thisModule->m_link_ptrs;
|
||
|
|
||
|
if(AdjModuleRefPtr) /* check that there is a list of adjacent modules */
|
||
|
{
|
||
|
while(*AdjModuleRefPtr != 0)
|
||
|
{
|
||
|
/* Probably want some validity test for the link. */
|
||
|
if (AIModuleIsPhysical(*AdjModuleRefPtr)) {
|
||
|
/* Probably a valid link... */
|
||
|
if (CheckAdjacencyValidity((*AdjModuleRefPtr),thisModule,0)) {
|
||
|
PrintDebuggingText("--AI Module of %s, general.\n",(*((*AdjModuleRefPtr)->m_module_ptrs))->name);
|
||
|
} else if (CheckAdjacencyValidity((*AdjModuleRefPtr),thisModule,1)) {
|
||
|
PrintDebuggingText("--AI Module of %s, alien only.\n",(*((*AdjModuleRefPtr)->m_module_ptrs))->name);
|
||
|
} else {
|
||
|
PrintDebuggingText("--AI Module of %s, fails validity test!\n",(*((*AdjModuleRefPtr)->m_module_ptrs))->name);
|
||
|
}
|
||
|
}
|
||
|
/* next adjacent module reference pointer */
|
||
|
AdjModuleRefPtr++;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
PrintDebuggingText("Adjacencies TO Player's Module:\n");
|
||
|
|
||
|
{
|
||
|
extern AIMODULE *AIModuleArray;
|
||
|
|
||
|
ModuleListPointer = AIModuleArray;
|
||
|
}
|
||
|
|
||
|
/* go through each aimodule in the environment */
|
||
|
for(moduleCounter = 0; moduleCounter < AIModuleArraySize; moduleCounter++)
|
||
|
{
|
||
|
|
||
|
/* get a pointer to the next current module */
|
||
|
thisModule = &(ModuleListPointer[moduleCounter]);
|
||
|
LOCALASSERT(thisModule);
|
||
|
|
||
|
AdjModuleRefPtr = thisModule->m_link_ptrs;
|
||
|
|
||
|
if(AdjModuleRefPtr) /* check that there is a list of adjacent modules */
|
||
|
{
|
||
|
while(*AdjModuleRefPtr != 0)
|
||
|
{
|
||
|
/* Probably want some validity test for the link. */
|
||
|
if (AIModuleIsPhysical(*AdjModuleRefPtr)) {
|
||
|
/* Is this the target? */
|
||
|
if ((*AdjModuleRefPtr)==(playerPherModule->m_aimodule)) {
|
||
|
|
||
|
/* Probably a valid link... */
|
||
|
if (CheckAdjacencyValidity((*AdjModuleRefPtr),thisModule,0)) {
|
||
|
PrintDebuggingText("--AI Module of %s, general.\n",(*(thisModule->m_module_ptrs))->name);
|
||
|
} else if (CheckAdjacencyValidity((*AdjModuleRefPtr),thisModule,1)) {
|
||
|
PrintDebuggingText("--AI Module of %s, alien only.\n",(*(thisModule->m_module_ptrs))->name);
|
||
|
} else {
|
||
|
PrintDebuggingText("--AI Module of %s, fails validity test!\n",(*(thisModule->m_module_ptrs))->name);
|
||
|
}
|
||
|
|
||
|
}
|
||
|
}
|
||
|
/* next adjacent module reference pointer */
|
||
|
AdjModuleRefPtr++;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
/*---------------------------**
|
||
|
** Loading and saving player **
|
||
|
**---------------------------*/
|
||
|
|
||
|
|
||
|
typedef struct player_save_block
|
||
|
{
|
||
|
SAVE_BLOCK_STRATEGY_HEADER header;
|
||
|
|
||
|
//behaviour block things
|
||
|
PLAYER_WEAPON_DATA WeaponSlot[MAX_NO_OF_WEAPON_SLOTS];
|
||
|
|
||
|
enum WEAPON_SLOT SelectedWeaponSlot;
|
||
|
enum WEAPON_SLOT SwapToWeaponSlot;
|
||
|
enum WEAPON_SLOT PreviouslySelectedWeaponSlot;
|
||
|
|
||
|
int Health; /* in 16.16 */
|
||
|
int Energy; /* in 16.16 */
|
||
|
int Armour; /* in 16.16 */
|
||
|
|
||
|
|
||
|
enum player_morph_state ShapeState; /* for controlling morphing */
|
||
|
|
||
|
signed int ForwardInertia;
|
||
|
signed int StrafeInertia;
|
||
|
signed int TurnInertia;
|
||
|
|
||
|
int ViewPanX; /* the looking up/down value that used to be in displayblock */
|
||
|
|
||
|
unsigned int securityClearances;
|
||
|
|
||
|
unsigned int IsAlive :1;
|
||
|
unsigned int IsImmortal :1;
|
||
|
unsigned int Mvt_AnalogueTurning :1;
|
||
|
unsigned int Mvt_AnaloguePitching :1;
|
||
|
unsigned int Absolute_Pitching :1;
|
||
|
unsigned int SwappingIsDebounced :1;
|
||
|
unsigned int DemoMode :1;
|
||
|
unsigned int IHaveAPlacedAutogun :1;
|
||
|
unsigned int IsMovingInWater :1;
|
||
|
unsigned int JetpackEnabled :1;
|
||
|
unsigned int GrapplingHookEnabled :1;
|
||
|
|
||
|
unsigned int MTrackerType;
|
||
|
|
||
|
unsigned int cloakOn :1;
|
||
|
unsigned int cloakPositionGivenAway :1;
|
||
|
int FieldCharge;
|
||
|
int cloakPositionGivenAwayTimer;
|
||
|
int PlasmaCasterCharge;
|
||
|
|
||
|
int CloakingEffectiveness;
|
||
|
|
||
|
ENCUMBERANCE_STATE Encumberance;
|
||
|
int tauntTimer;
|
||
|
|
||
|
int incidentFlag;
|
||
|
int incidentTimer;
|
||
|
int fireTimer;
|
||
|
|
||
|
//some stuff for the weapon displayblock
|
||
|
VECTORCH Weapon_World;
|
||
|
EULER Weapon_Euler;
|
||
|
MATRIXCH Weapon_Matrix;
|
||
|
|
||
|
|
||
|
//and globals
|
||
|
enum VISION_MODE_ID CurrentVisionMode;
|
||
|
SMARTGUN_MODES SmartgunMode;
|
||
|
GRENADE_LAUNCHER_DATA GrenadeLauncherData;
|
||
|
|
||
|
|
||
|
//strategy block stuff
|
||
|
DYNAMICSBLOCK dynamics;
|
||
|
int integrity;
|
||
|
DAMAGEBLOCK SBDamageBlock;
|
||
|
|
||
|
}PLAYER_SAVE_BLOCK;
|
||
|
|
||
|
//defines for load/save macros
|
||
|
#define SAVELOAD_BLOCK block
|
||
|
#define SAVELOAD_BEHAV playerStatusPtr
|
||
|
|
||
|
|
||
|
void SaveStrategy_Player(STRATEGYBLOCK* sbPtr)
|
||
|
{
|
||
|
PLAYER_STATUS *playerStatusPtr= (PLAYER_STATUS *) (sbPtr->SBdataptr);
|
||
|
PLAYER_SAVE_BLOCK* block;
|
||
|
int i;
|
||
|
|
||
|
GET_STRATEGY_SAVE_BLOCK(block,sbPtr);
|
||
|
|
||
|
|
||
|
COPYELEMENT_SAVE(SelectedWeaponSlot)
|
||
|
COPYELEMENT_SAVE(SwapToWeaponSlot)
|
||
|
COPYELEMENT_SAVE(PreviouslySelectedWeaponSlot)
|
||
|
|
||
|
COPYELEMENT_SAVE(Health) /* in 16.16 */
|
||
|
COPYELEMENT_SAVE(Energy) /* in 16.16 */
|
||
|
COPYELEMENT_SAVE(Armour) /* in 16.16 */
|
||
|
|
||
|
|
||
|
COPYELEMENT_SAVE(ShapeState) /* for controlling morphing */
|
||
|
|
||
|
COPYELEMENT_SAVE(ForwardInertia)
|
||
|
COPYELEMENT_SAVE(StrafeInertia)
|
||
|
COPYELEMENT_SAVE(TurnInertia)
|
||
|
|
||
|
COPYELEMENT_SAVE(ViewPanX) /* the looking up/down value that used to be in displayblock */
|
||
|
|
||
|
COPYELEMENT_SAVE(securityClearances)
|
||
|
|
||
|
COPYELEMENT_SAVE(IsAlive)
|
||
|
COPYELEMENT_SAVE(IsImmortal)
|
||
|
COPYELEMENT_SAVE(Mvt_AnalogueTurning)
|
||
|
COPYELEMENT_SAVE(Mvt_AnaloguePitching)
|
||
|
COPYELEMENT_SAVE(Absolute_Pitching)
|
||
|
COPYELEMENT_SAVE(SwappingIsDebounced)
|
||
|
COPYELEMENT_SAVE(DemoMode)
|
||
|
COPYELEMENT_SAVE(IHaveAPlacedAutogun)
|
||
|
COPYELEMENT_SAVE(IsMovingInWater)
|
||
|
COPYELEMENT_SAVE(JetpackEnabled)
|
||
|
COPYELEMENT_SAVE(GrapplingHookEnabled )
|
||
|
|
||
|
COPYELEMENT_SAVE(MTrackerType)
|
||
|
|
||
|
COPYELEMENT_SAVE(cloakOn)
|
||
|
COPYELEMENT_SAVE(cloakPositionGivenAway)
|
||
|
COPYELEMENT_SAVE(FieldCharge)
|
||
|
COPYELEMENT_SAVE(cloakPositionGivenAwayTimer)
|
||
|
COPYELEMENT_SAVE(PlasmaCasterCharge)
|
||
|
COPYELEMENT_SAVE(CloakingEffectiveness)
|
||
|
COPYELEMENT_SAVE(Encumberance)
|
||
|
COPYELEMENT_SAVE(tauntTimer)
|
||
|
|
||
|
COPYELEMENT_SAVE(incidentFlag)
|
||
|
COPYELEMENT_SAVE(incidentTimer)
|
||
|
COPYELEMENT_SAVE(fireTimer)
|
||
|
|
||
|
for(i=0;i<MAX_NO_OF_WEAPON_SLOTS;i++)
|
||
|
{
|
||
|
block->WeaponSlot[i].WeaponIDNumber = playerStatusPtr->WeaponSlot[i].WeaponIDNumber;
|
||
|
block->WeaponSlot[i].CurrentState = playerStatusPtr->WeaponSlot[i].CurrentState;
|
||
|
block->WeaponSlot[i].StateTimeOutCounter = playerStatusPtr->WeaponSlot[i].StateTimeOutCounter;
|
||
|
block->WeaponSlot[i].PrimaryRoundsRemaining = playerStatusPtr->WeaponSlot[i].PrimaryRoundsRemaining;
|
||
|
block->WeaponSlot[i].SecondaryRoundsRemaining = playerStatusPtr->WeaponSlot[i].SecondaryRoundsRemaining;
|
||
|
block->WeaponSlot[i].PrimaryMagazinesRemaining = playerStatusPtr->WeaponSlot[i].PrimaryMagazinesRemaining;
|
||
|
block->WeaponSlot[i].SecondaryMagazinesRemaining = playerStatusPtr->WeaponSlot[i].SecondaryMagazinesRemaining;
|
||
|
block->WeaponSlot[i].PositionOffset = playerStatusPtr->WeaponSlot[i].PositionOffset;
|
||
|
block->WeaponSlot[i].DirectionOffset = playerStatusPtr->WeaponSlot[i].DirectionOffset;
|
||
|
block->WeaponSlot[i].Possessed = playerStatusPtr->WeaponSlot[i].Possessed;
|
||
|
}
|
||
|
|
||
|
//some stuff for the weapon displayblock
|
||
|
block->Weapon_World = PlayersWeapon.ObWorld;
|
||
|
block->Weapon_Euler = PlayersWeapon.ObEuler;
|
||
|
block->Weapon_Matrix = PlayersWeapon.ObMat;
|
||
|
|
||
|
//global
|
||
|
block->CurrentVisionMode = CurrentVisionMode;
|
||
|
block->SmartgunMode = SmartgunMode;
|
||
|
block->GrenadeLauncherData = GrenadeLauncherData;
|
||
|
|
||
|
//strategy block stuff
|
||
|
|
||
|
block->integrity = sbPtr->integrity;
|
||
|
block->SBDamageBlock = sbPtr->SBDamageBlock;
|
||
|
|
||
|
block->dynamics = *sbPtr->DynPtr;
|
||
|
block->dynamics.CollisionReportPtr=0;
|
||
|
|
||
|
//save the weapon hierarchy
|
||
|
SaveHierarchy(&PlayersWeaponHModelController);
|
||
|
|
||
|
|
||
|
Save_SoundState(&playerStatusPtr->soundHandle);
|
||
|
Save_SoundState(&playerStatusPtr->soundHandle3);
|
||
|
Save_SoundState(&playerStatusPtr->soundHandle5);
|
||
|
Save_SoundState(&playerStatusPtr->soundHandleForPredatorCloakDamaged);
|
||
|
}
|
||
|
|
||
|
void LoadStrategy_Player(SAVE_BLOCK_STRATEGY_HEADER* header)
|
||
|
{
|
||
|
PLAYER_SAVE_BLOCK* block = (PLAYER_SAVE_BLOCK*) header;
|
||
|
STRATEGYBLOCK* sbPtr = Player->ObStrategyBlock;
|
||
|
PLAYER_STATUS *playerStatusPtr= (PLAYER_STATUS *) (sbPtr->SBdataptr);
|
||
|
int i;
|
||
|
|
||
|
if(block->header.size != sizeof(*block)) return;
|
||
|
|
||
|
COPY_NAME(sbPtr->SBname,header->SBname);
|
||
|
|
||
|
|
||
|
|
||
|
COPYELEMENT_LOAD(SelectedWeaponSlot)
|
||
|
COPYELEMENT_LOAD(SwapToWeaponSlot)
|
||
|
COPYELEMENT_LOAD(PreviouslySelectedWeaponSlot)
|
||
|
|
||
|
COPYELEMENT_LOAD(Health) /* in 16.16 */
|
||
|
COPYELEMENT_LOAD(Energy) /* in 16.16 */
|
||
|
COPYELEMENT_LOAD(Armour) /* in 16.16 */
|
||
|
|
||
|
|
||
|
COPYELEMENT_LOAD(ShapeState) /* for controlling morphing */
|
||
|
|
||
|
COPYELEMENT_LOAD(ForwardInertia)
|
||
|
COPYELEMENT_LOAD(StrafeInertia)
|
||
|
COPYELEMENT_LOAD(TurnInertia)
|
||
|
|
||
|
COPYELEMENT_LOAD(ViewPanX) /* the looking up/down value that used to be in displayblock */
|
||
|
|
||
|
COPYELEMENT_LOAD(securityClearances)
|
||
|
|
||
|
COPYELEMENT_LOAD(IsAlive)
|
||
|
COPYELEMENT_LOAD(IsImmortal)
|
||
|
COPYELEMENT_LOAD(Mvt_AnalogueTurning)
|
||
|
COPYELEMENT_LOAD(Mvt_AnaloguePitching)
|
||
|
COPYELEMENT_LOAD(Absolute_Pitching)
|
||
|
COPYELEMENT_LOAD(SwappingIsDebounced)
|
||
|
COPYELEMENT_LOAD(DemoMode)
|
||
|
COPYELEMENT_LOAD(IHaveAPlacedAutogun)
|
||
|
COPYELEMENT_LOAD(IsMovingInWater)
|
||
|
COPYELEMENT_LOAD(JetpackEnabled)
|
||
|
COPYELEMENT_LOAD(GrapplingHookEnabled )
|
||
|
|
||
|
COPYELEMENT_LOAD(MTrackerType)
|
||
|
|
||
|
COPYELEMENT_LOAD(cloakOn)
|
||
|
COPYELEMENT_LOAD(cloakPositionGivenAway)
|
||
|
COPYELEMENT_LOAD(FieldCharge)
|
||
|
COPYELEMENT_LOAD(cloakPositionGivenAwayTimer)
|
||
|
COPYELEMENT_LOAD(PlasmaCasterCharge)
|
||
|
COPYELEMENT_LOAD(CloakingEffectiveness)
|
||
|
COPYELEMENT_LOAD(Encumberance)
|
||
|
COPYELEMENT_LOAD(tauntTimer)
|
||
|
|
||
|
COPYELEMENT_LOAD(incidentFlag)
|
||
|
COPYELEMENT_LOAD(incidentTimer)
|
||
|
COPYELEMENT_LOAD(fireTimer)
|
||
|
|
||
|
// playerStatusPtr->SwapToWeaponSlot = block->SelectedWeaponSlot;
|
||
|
|
||
|
|
||
|
|
||
|
for(i=0;i<MAX_NO_OF_WEAPON_SLOTS;i++)
|
||
|
{
|
||
|
playerStatusPtr->WeaponSlot[i].WeaponIDNumber = block->WeaponSlot[i].WeaponIDNumber;
|
||
|
playerStatusPtr->WeaponSlot[i].CurrentState = block->WeaponSlot[i].CurrentState;
|
||
|
playerStatusPtr->WeaponSlot[i].StateTimeOutCounter = block->WeaponSlot[i].StateTimeOutCounter;
|
||
|
playerStatusPtr->WeaponSlot[i].PrimaryRoundsRemaining = block->WeaponSlot[i].PrimaryRoundsRemaining;
|
||
|
playerStatusPtr->WeaponSlot[i].SecondaryRoundsRemaining = block->WeaponSlot[i].SecondaryRoundsRemaining;
|
||
|
playerStatusPtr->WeaponSlot[i].PrimaryMagazinesRemaining = block->WeaponSlot[i].PrimaryMagazinesRemaining;
|
||
|
playerStatusPtr->WeaponSlot[i].SecondaryMagazinesRemaining = block->WeaponSlot[i].SecondaryMagazinesRemaining;
|
||
|
playerStatusPtr->WeaponSlot[i].PositionOffset = block->WeaponSlot[i].PositionOffset;
|
||
|
playerStatusPtr->WeaponSlot[i].DirectionOffset = block->WeaponSlot[i].DirectionOffset;
|
||
|
playerStatusPtr->WeaponSlot[i].Possessed = block->WeaponSlot[i].Possessed;
|
||
|
}
|
||
|
|
||
|
//some stuff for the weapon displayblock
|
||
|
PlayersWeapon.ObWorld = block->Weapon_World;
|
||
|
PlayersWeapon.ObEuler = block->Weapon_Euler;
|
||
|
PlayersWeapon.ObMat = block->Weapon_Matrix;
|
||
|
|
||
|
//global
|
||
|
CurrentVisionMode = block->CurrentVisionMode;
|
||
|
SmartgunMode = block->SmartgunMode;
|
||
|
GrenadeLauncherData = block->GrenadeLauncherData;
|
||
|
|
||
|
//strategy block stuff
|
||
|
*sbPtr->DynPtr = block->dynamics;
|
||
|
sbPtr->integrity = block->integrity;
|
||
|
sbPtr->SBDamageBlock = block->SBDamageBlock;
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
{
|
||
|
extern VIEWDESCRIPTORBLOCK* Global_VDB_Ptr;
|
||
|
sbPtr->containingModule = ModuleFromPosition(&(sbPtr->DynPtr->Position), (MODULE*)0);
|
||
|
Global_VDB_Ptr->VDB_World = sbPtr->DynPtr->Position;
|
||
|
}
|
||
|
|
||
|
|
||
|
//load the weapon hierarchy
|
||
|
{
|
||
|
SAVE_BLOCK_HEADER* hier_header = GetNextBlockIfOfType(SaveBlock_Hierarchy);
|
||
|
if(hier_header)
|
||
|
{
|
||
|
LoadHierarchy(hier_header,&PlayersWeaponHModelController);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
Dispel_HModel(&PlayersWeaponHModelController);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
PlayersWeapon.HModelControlBlock = &PlayersWeaponHModelController;
|
||
|
|
||
|
//get the section data pointers
|
||
|
PWMFSDP=GetThisSectionData(PlayersWeaponHModelController.section_data,"dum flash");
|
||
|
if (PWMFSDP==NULL) {
|
||
|
PWMFSDP=GetThisSectionData(PlayersWeaponHModelController.section_data,"Dum flash");
|
||
|
}
|
||
|
|
||
|
Load_SoundState(&playerStatusPtr->soundHandle);
|
||
|
Load_SoundState(&playerStatusPtr->soundHandle3);
|
||
|
Load_SoundState(&playerStatusPtr->soundHandle5);
|
||
|
Load_SoundState(&playerStatusPtr->soundHandleForPredatorCloakDamaged);
|
||
|
|
||
|
}
|
||
|
|