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