1 // Emacs style mode select -*- C++ -*-
2 //-----------------------------------------------------------------------------
3 //
4 // $Id: p_user.cpp 4542 2014-02-09 17:39:42Z dr_sean $
5 //
6 // Copyright (C) 1993-1996 by id Software, Inc.
7 // Copyright (C) 2006-2014 by The Odamex Team.
8 //
9 // This program is free software; you can redistribute it and/or
10 // modify it under the terms of the GNU General Public License
11 // as published by the Free Software Foundation; either version 2
12 // of the License, or (at your option) any later version.
13 //
14 // This program is distributed in the hope that it will be useful,
15 // but WITHOUT ANY WARRANTY; without even the implied warranty of
16 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 // GNU General Public License for more details.
18 //
19 // DESCRIPTION:
20 // Player related stuff.
21 // Bobbing POV/weapon, movement.
22 // Pending weapon.
23 //
24 //-----------------------------------------------------------------------------
25
26 #include "cmdlib.h"
27 #include "doomdef.h"
28 #include "d_event.h"
29 #include "p_local.h"
30 #include "doomstat.h"
31 #include "s_sound.h"
32 #include "i_system.h"
33 #include "i_net.h"
34 #include "gi.h"
35
36 #include "p_snapshot.h"
37
38 // Index of the special effects (INVUL inverse) map.
39 #define INVERSECOLORMAP 32
40
41 //
42 // Movement.
43 //
44
45 // 16 pixels of bob
46 #define MAXBOB 0x100000
47
48 EXTERN_CVAR (sv_allowjump)
49 EXTERN_CVAR (cl_mouselook)
50 EXTERN_CVAR (sv_freelook)
51 EXTERN_CVAR (co_zdoomphys)
52 EXTERN_CVAR (cl_deathcam)
53 EXTERN_CVAR (sv_forcerespawn)
54 EXTERN_CVAR (sv_forcerespawntime)
55 EXTERN_CVAR (sv_spawndelaytime)
56
57 extern bool predicting, step_mode;
58
59 static player_t nullplayer; // used to indicate 'player not found' when searching
60 EXTERN_CVAR (sv_allowmovebob)
EXTERN_CVAR(cl_movebob)61 EXTERN_CVAR (cl_movebob)
62
63 player_t &idplayer(byte id)
64 {
65 // Put a cached lookup mechanism in here.
66
67 // full search
68 for (Players::iterator it = players.begin();it != players.end();++it)
69 {
70 // Add to the cache while we search
71 if (it->id == id)
72 return *it;
73 }
74
75 return nullplayer;
76 }
77
78 /**
79 * Find player by netname. Note that this search is case-insensitive.
80 *
81 * @param netname Name of player to look for.
82 * @return Player reference of found player, or nullplayer.
83 */
nameplayer(const std::string & netname)84 player_t &nameplayer(const std::string &netname)
85 {
86 for (Players::iterator it = players.begin();it != players.end();++it)
87 {
88 if (iequals(netname, it->userinfo.netname))
89 return *it;
90 }
91
92 return nullplayer;
93 }
94
validplayer(player_t & ref)95 bool validplayer(player_t &ref)
96 {
97 if (&ref == &nullplayer)
98 return false;
99
100 if (players.empty())
101 return false;
102
103 return true;
104 }
105
106 //
107 // P_NumPlayersInGame()
108 //
109 // Returns the number of players who are active in the current game. This does
110 // not include spectators or downloaders.
111 //
P_NumPlayersInGame()112 size_t P_NumPlayersInGame()
113 {
114 size_t num_players = 0;
115
116 for (Players::const_iterator it = players.begin();it != players.end();++it)
117 {
118 if (!(it->spectator) && it->ingame())
119 num_players += 1;
120 }
121
122 return num_players;
123 }
124
125 //
126 // P_NumReadyPlayersInGame()
127 //
128 // Returns the number of players who are marked ready in the current game.
129 // This does not include spectators or downloaders.
130 //
P_NumReadyPlayersInGame()131 size_t P_NumReadyPlayersInGame()
132 {
133 size_t num_players = 0;
134
135 for (Players::const_iterator it = players.begin();it != players.end();++it)
136 {
137 if (!(it->spectator) && it->ingame() && it->ready)
138 num_players += 1;
139 }
140
141 return num_players;
142 }
143
144 // P_NumPlayersOnTeam()
145 //
146 // Returns the number of active players on a team. No specs or downloaders.
P_NumPlayersOnTeam(team_t team)147 size_t P_NumPlayersOnTeam(team_t team)
148 {
149 size_t num_players = 0;
150
151 for (Players::const_iterator it = players.begin();it != players.end();++it)
152 {
153 if (!(it->spectator) && it->ingame() && it->userinfo.team == team)
154 num_players += 1;
155 }
156
157 return num_players;
158 }
159
160 //
161 // P_Thrust
162 // Moves the given origin along a given angle.
163 //
P_SideThrust(player_t * player,angle_t angle,fixed_t move)164 void P_SideThrust (player_t *player, angle_t angle, fixed_t move)
165 {
166 angle = (angle - ANG90) >> ANGLETOFINESHIFT;
167
168 player->mo->momx += FixedMul (move, finecosine[angle]);
169 player->mo->momy += FixedMul (move, finesine[angle]);
170 }
171
P_ForwardThrust(player_t * player,angle_t angle,fixed_t move)172 void P_ForwardThrust (player_t *player, angle_t angle, fixed_t move)
173 {
174 angle >>= ANGLETOFINESHIFT;
175
176 if ((player->mo->waterlevel || (player->mo->flags2 & MF2_FLY))
177 && player->mo->pitch != 0)
178 {
179 angle_t pitch = (angle_t)player->mo->pitch >> ANGLETOFINESHIFT;
180 fixed_t zpush = FixedMul (move, finesine[pitch]);
181 if (player->mo->waterlevel && player->mo->waterlevel < 2 && zpush < 0)
182 zpush = 0;
183 player->mo->momz -= zpush;
184 move = FixedMul (move, finecosine[pitch]);
185 }
186 player->mo->momx += FixedMul (move, finecosine[angle]);
187 player->mo->momy += FixedMul (move, finesine[angle]);
188 }
189
190 //
191 // P_CalcHeight
192 // Calculate the walking / running height adjustment
193 //
P_CalcHeight(player_t * player)194 void P_CalcHeight (player_t *player)
195 {
196 int angle;
197 fixed_t bob;
198
199 // Regular movement bobbing
200 // (needs to be calculated for gun swing even if not on ground)
201 // OPTIMIZE: tablify angle
202
203 // killough 10/98: Make bobbing depend only on player-applied motion.
204 //
205 // Note: don't reduce bobbing here if on ice: if you reduce bobbing here,
206 // it causes bobbing jerkiness when the player moves from ice to non-ice,
207 // and vice-versa.
208
209 if ((player->mo->flags2 & MF2_FLY) && !player->mo->onground)
210 {
211 player->bob = FRACUNIT / 2;
212 }
213
214 if ((serverside || !predicting) && !player->spectator)
215 {
216 player->bob = FixedMul (player->mo->momx, player->mo->momx)
217 + FixedMul (player->mo->momy, player->mo->momy);
218 player->bob >>= 2;
219
220 if (player->bob > MAXBOB)
221 player->bob = MAXBOB;
222 }
223
224 if (player->cheats & CF_NOMOMENTUM || (!co_zdoomphys && !player->mo->onground))
225 {
226 player->viewz = player->mo->z + VIEWHEIGHT;
227
228 if (player->viewz > player->mo->ceilingz-4*FRACUNIT)
229 player->viewz = player->mo->ceilingz-4*FRACUNIT;
230
231 return;
232 }
233
234 angle = (FINEANGLES/20*level.time) & FINEMASK;
235 if (!player->spectator)
236 bob = FixedMul (player->bob>>(player->mo->waterlevel > 1 ? 2 : 1), finesine[angle]);
237 else
238 bob = 0;
239
240 // move viewheight
241 if (player->playerstate == PST_LIVE)
242 {
243 player->viewheight += player->deltaviewheight;
244
245 if (player->viewheight > VIEWHEIGHT)
246 {
247 player->viewheight = VIEWHEIGHT;
248 player->deltaviewheight = 0;
249 }
250 else if (player->viewheight < VIEWHEIGHT/2)
251 {
252 player->viewheight = VIEWHEIGHT/2;
253 if (player->deltaviewheight <= 0)
254 player->deltaviewheight = 1;
255 }
256
257 if (player->deltaviewheight)
258 {
259 player->deltaviewheight += FRACUNIT/4;
260 if (!player->deltaviewheight)
261 player->deltaviewheight = 1;
262 }
263 }
264
265 // [SL] Scale view-bobbing based on user's preference (if the server allows)
266 if (sv_allowmovebob)
267 bob *= cl_movebob;
268
269 player->viewz = player->mo->z + player->viewheight + bob;
270
271 if (player->viewz > player->mo->ceilingz-4*FRACUNIT)
272 player->viewz = player->mo->ceilingz-4*FRACUNIT;
273 if (player->viewz < player->mo->floorz + 4*FRACUNIT)
274 player->viewz = player->mo->floorz + 4*FRACUNIT;
275 }
276
277 //
278 // P_PlayerLookUpDown
279 //
P_PlayerLookUpDown(player_t * p)280 void P_PlayerLookUpDown (player_t *p)
281 {
282 // [RH] Look up/down stuff
283 if (!sv_freelook)
284 {
285 p->mo->pitch = 0;
286 }
287 else
288 {
289 int look = p->cmd.pitch << 16;
290
291 // The player's view pitch is clamped between -32 and +56 degrees,
292 // which translates to about half a screen height up and (more than)
293 // one full screen height down from straight ahead when view panning
294 // is used.
295 if (look)
296 {
297 if (look == -32768 << 16)
298 { // center view
299 p->mo->pitch = 0;
300 }
301 else if (look > 0)
302 { // look up
303 p->mo->pitch -= look;
304 if (p->mo->pitch < -ANG(32))
305 p->mo->pitch = -ANG(32);
306 }
307 else
308 { // look down
309 p->mo->pitch -= look;
310 if (p->mo->pitch > ANG(56))
311 p->mo->pitch = ANG(56);
312 }
313 }
314 }
315 }
316
CVAR_FUNC_IMPL(sv_aircontrol)317 CVAR_FUNC_IMPL (sv_aircontrol)
318 {
319 level.aircontrol = (fixed_t)((float)var * 65536.f);
320 G_AirControlChanged ();
321 }
322
323 //
324 // P_MovePlayer
325 //
P_MovePlayer(player_t * player)326 void P_MovePlayer (player_t *player)
327 {
328 if (!player || !player->mo || player->playerstate == PST_DEAD)
329 return;
330
331 AActor *mo = player->mo;
332
333 mo->onground = (mo->z <= mo->floorz) || (mo->flags2 & MF2_ONMOBJ);
334
335 // [RH] Don't let frozen players move
336 if (player->cheats & CF_FROZEN)
337 return;
338
339 // Move around.
340 // Reactiontime is used to prevent movement
341 // for a bit after a teleport.
342 if (player->mo->reactiontime)
343 {
344 player->mo->reactiontime--;
345 return;
346 }
347
348 if (player->cmd.upmove == -32768)
349 {
350 // Only land if in the air
351 if ((player->mo->flags2 & MF2_FLY) && player->mo->waterlevel < 2)
352 {
353 player->mo->flags2 &= ~MF2_FLY;
354 player->mo->flags &= ~MF_NOGRAVITY;
355 }
356 }
357 else if (player->cmd.upmove != 0)
358 {
359 if (player->mo->waterlevel >= 2 || player->mo->flags2 & MF2_FLY)
360 {
361 player->mo->momz = player->cmd.upmove << 9;
362
363 if (player->mo->waterlevel < 2 && !(player->mo->flags2 & MF2_FLY))
364 {
365 player->mo->flags2 |= MF2_FLY;
366 player->mo->flags |= MF_NOGRAVITY;
367 if (player->mo->momz <= -39*FRACUNIT)
368 S_StopSound(player->mo, CHAN_VOICE); // Stop falling scream
369 }
370 }
371 }
372
373 // Look left/right
374 if(clientside || step_mode)
375 {
376 mo->angle += player->cmd.yaw << 16;
377
378 // Look up/down stuff
379 P_PlayerLookUpDown(player);
380 }
381
382 // killough 10/98:
383 //
384 // We must apply thrust to the player and bobbing separately, to avoid
385 // anomalies. The thrust applied to bobbing is always the same strength on
386 // ice, because the player still "works just as hard" to move, while the
387 // thrust applied to the movement varies with 'movefactor'.
388
389 if (player->cmd.forwardmove | player->cmd.sidemove)
390 {
391 fixed_t forwardmove, sidemove;
392 int bobfactor;
393 int friction, movefactor;
394
395 movefactor = P_GetMoveFactor (mo, &friction);
396 bobfactor = friction < ORIG_FRICTION ? movefactor : ORIG_FRICTION_FACTOR;
397 if (!mo->onground && !(mo->flags2 & MF2_FLY) && !mo->waterlevel)
398 {
399 // [RH] allow very limited movement if not on ground.
400 if (co_zdoomphys)
401 {
402 movefactor = FixedMul (movefactor, level.aircontrol);
403 bobfactor = FixedMul (bobfactor, level.aircontrol);
404 }
405 else
406 {
407 movefactor >>= 8;
408 bobfactor >>= 8;
409 }
410 }
411 forwardmove = (player->cmd.forwardmove * movefactor) >> 8;
412 sidemove = (player->cmd.sidemove * movefactor) >> 8;
413
414 // [ML] Check for these conditions unless advanced physics is on
415 if(co_zdoomphys ||
416 (!co_zdoomphys && (mo->onground || (mo->flags2 & MF2_FLY) || mo->waterlevel)))
417 {
418 if (forwardmove)
419 {
420 P_ForwardThrust (player, mo->angle, forwardmove);
421 }
422 if (sidemove)
423 {
424 P_SideThrust (player, mo->angle, sidemove);
425 }
426 }
427
428 if (mo->state == &states[S_PLAY])
429 {
430 // denis - fixme - this function might destoy player->mo without setting it to 0
431 P_SetMobjState (player->mo, S_PLAY_RUN1);
432 }
433
434 if (player->cheats & CF_REVERTPLEASE)
435 {
436 player->cheats &= ~CF_REVERTPLEASE;
437 player->camera = player->mo;
438 }
439 }
440
441 // [RH] check for jump
442 if (player->jumpTics)
443 player->jumpTics--;
444
445 if ((player->cmd.buttons & BT_JUMP) == BT_JUMP)
446 {
447 if (player->mo->waterlevel >= 2)
448 {
449 player->mo->momz = 4*FRACUNIT;
450 }
451 else if (player->mo->flags2 & MF2_FLY)
452 {
453 player->mo->momz = 3*FRACUNIT;
454 }
455 else if (sv_allowjump && player->mo->onground && !player->jumpTics)
456 {
457 player->mo->momz += 8*FRACUNIT;
458 if(!player->spectator)
459 UV_SoundAvoidPlayer(player->mo, CHAN_VOICE, "player/male/jump1", ATTN_NORM);
460
461 player->mo->flags2 &= ~MF2_ONMOBJ;
462 player->jumpTics = 18;
463 }
464 }
465 }
466
467 // [RH] (Adapted from Q2)
468 // P_FallingDamage
469 //
P_FallingDamage(AActor * ent)470 void P_FallingDamage (AActor *ent)
471 {
472 float delta;
473 int damage;
474
475 if (!ent->player)
476 return; // not a player
477
478 if (ent->flags & MF_NOCLIP)
479 return;
480
481 if ((ent->player->oldvelocity[2] < 0)
482 && (ent->momz > ent->player->oldvelocity[2])
483 && (!(ent->flags2 & MF2_ONMOBJ)
484 || !(ent->z <= ent->floorz)))
485 {
486 delta = (float)ent->player->oldvelocity[2];
487 }
488 else
489 {
490 if (!(ent->flags2 & MF2_ONMOBJ))
491 return;
492 delta = (float)(ent->momz - ent->player->oldvelocity[2]);
493 }
494 delta = delta*delta * 2.03904313e-11f;
495
496 if (delta < 1)
497 return;
498
499 if (delta < 15)
500 {
501 //ent->s.event = EV_FOOTSTEP;
502 return;
503 }
504
505 if (delta > 30)
506 {
507 damage = (int)((delta-30)/2);
508 if (damage < 1)
509 damage = 1;
510
511 if (0)
512 P_DamageMobj (ent, NULL, NULL, damage, MOD_FALLING);
513 }
514 else
515 {
516 //ent->s.event = EV_FALLSHORT;
517 return;
518 }
519 }
520
521 //
522 // P_DeathThink
523 // Fall on your face when dying.
524 // Decrease POV height to floor height.
525 //
526 #define ANG5 (ANG90/18)
527
P_DeathThink(player_t * player)528 void P_DeathThink (player_t *player)
529 {
530 bool reduce_redness = true;
531
532 P_MovePsprites (player);
533 player->mo->onground = (player->mo->z <= player->mo->floorz);
534
535 // fall to the ground
536 if (player->viewheight > 6*FRACUNIT)
537 player->viewheight -= FRACUNIT;
538
539 if (player->viewheight < 6*FRACUNIT)
540 player->viewheight = 6*FRACUNIT;
541
542 player->deltaviewheight = 0;
543 P_CalcHeight (player);
544
545 // adjust the player's view to follow its attacker
546 if (cl_deathcam && clientside &&
547 player->attacker && player->attacker != player->mo)
548 {
549 angle_t angle = P_PointToAngle (player->mo->x,
550 player->mo->y,
551 player->attacker->x,
552 player->attacker->y);
553
554 angle_t delta = angle - player->mo->angle;
555
556 if (delta < ANG5 || delta > (unsigned)-ANG5)
557 player->mo->angle = angle;
558 else
559 {
560 if (delta < ANG180)
561 player->mo->angle += ANG5;
562 else
563 player->mo->angle -= ANG5;
564
565 // not yet looking at killer so keep the red tinting
566 reduce_redness = false;
567 }
568 }
569
570 if (player->damagecount && reduce_redness && !predicting)
571 player->damagecount--;
572
573 if(serverside)
574 {
575 bool force_respawn = (!clientside && sv_forcerespawn &&
576 level.time >= player->death_time + sv_forcerespawntime * TICRATE);
577
578 // [SL] Can we respawn yet?
579 int respawn_time = player->death_time + sv_spawndelaytime * TICRATE;
580 bool delay_respawn = (!clientside && level.time < respawn_time);
581
582 // [Toke - dmflags] Old location of DF_FORCE_RESPAWN
583 if (player->ingame() && ((player->cmd.buttons & BT_USE && !delay_respawn) || force_respawn))
584 {
585 player->playerstate = PST_REBORN;
586 }
587 }
588 }
589
P_AreTeammates(player_t & a,player_t & b)590 bool P_AreTeammates(player_t &a, player_t &b)
591 {
592 // not your own teammate (at least for friendly fire, etc)
593 if (a.id == b.id)
594 return false;
595
596 return (sv_gametype == GM_COOP) ||
597 ((a.userinfo.team == b.userinfo.team) &&
598 (sv_gametype == GM_TEAMDM || sv_gametype == GM_CTF));
599 }
600
P_CanSpy(player_t & viewer,player_t & other)601 bool P_CanSpy(player_t &viewer, player_t &other)
602 {
603 if (other.spectator || !other.mo)
604 return false;
605
606 return (viewer.spectator || P_AreTeammates(viewer, other) || demoplayback);
607 }
608
609 void SV_SendPlayerInfo(player_t &);
610
611 //
612 // P_PlayerThink
613 //
P_PlayerThink(player_t * player)614 void P_PlayerThink (player_t *player)
615 {
616 weapontype_t newweapon;
617
618 // [SL] 2011-10-31 - Thinker called before the client has received a message
619 // to spawn a mobj from the server. Just bail from this function and
620 // hope the client receives the spawn message at a later time.
621 if (!player->mo && clientside && multiplayer)
622 {
623 DPrintf("Warning: P_PlayerThink called for player %s without a valid Actor.\n",
624 player->userinfo.netname.c_str());
625 return;
626 }
627 else if (!player->mo)
628 I_Error ("No player %d start\n", player->id);
629
630 player->xviewshift = 0; // [RH] Make sure view is in right place
631 player->prevviewz = player->viewz;
632 player->mo->prevangle = player->mo->angle;
633 player->mo->prevpitch = player->mo->pitch;
634
635 // fixme: do this in the cheat code
636 if (player->cheats & CF_NOCLIP)
637 player->mo->flags |= MF_NOCLIP;
638 else
639 player->mo->flags &= ~MF_NOCLIP;
640
641 if (player->cheats & CF_FLY)
642 player->mo->flags |= MF_NOGRAVITY, player->mo->flags2 |= MF2_FLY;
643 else
644 player->mo->flags &= ~MF_NOGRAVITY, player->mo->flags2 &= ~MF2_FLY;
645
646 // chain saw run forward
647 if (player->mo->flags & MF_JUSTATTACKED)
648 {
649 player->cmd.yaw = 0;
650 player->cmd.forwardmove = 0xc800/2;
651 player->cmd.sidemove = 0;
652 player->mo->flags &= ~MF_JUSTATTACKED;
653 }
654
655 if (player->playerstate == PST_DEAD)
656 {
657 P_DeathThink(player);
658 return;
659 }
660
661 P_MovePlayer (player);
662 P_CalcHeight (player);
663
664 if (player->mo->subsector && (player->mo->subsector->sector->special || player->mo->subsector->sector->damage))
665 P_PlayerInSpecialSector (player);
666
667 // Check for weapon change.
668
669 // A special event has no other buttons.
670 if (player->cmd.buttons & BT_SPECIAL)
671 player->cmd.buttons = 0;
672
673 if ((player->cmd.buttons & BT_CHANGE) || player->cmd.impulse >= 50)
674 {
675 // [RH] Support direct weapon changes
676 if (player->cmd.impulse) {
677 newweapon = (weapontype_t)(player->cmd.impulse - 50);
678 } else {
679 // The actual changing of the weapon is done
680 // when the weapon psprite can do it
681 // (read: not in the middle of an attack).
682 newweapon = (weapontype_t)((player->cmd.buttons&BT_WEAPONMASK)>>BT_WEAPONSHIFT);
683
684 if (newweapon == wp_fist
685 && player->weaponowned[wp_chainsaw]
686 && !(player->readyweapon == wp_chainsaw
687 && player->powers[pw_strength]))
688 {
689 newweapon = wp_chainsaw;
690 }
691
692 if ((gameinfo.flags & GI_MAPxx)
693 && newweapon == wp_shotgun
694 && player->weaponowned[wp_supershotgun]
695 && player->readyweapon != wp_supershotgun)
696 {
697 newweapon = wp_supershotgun;
698 }
699 }
700
701 if ((newweapon >= 0 && newweapon < NUMWEAPONS)
702 && player->weaponowned[newweapon]
703 && newweapon != player->readyweapon)
704 {
705 // NEVER go to plasma or BFG in shareware,
706 if ((newweapon != wp_plasma && newweapon != wp_bfg)
707 || (gamemode != shareware) )
708 {
709 player->pendingweapon = newweapon;
710 }
711 }
712 }
713
714 // check for use
715 if (player->cmd.buttons & BT_USE)
716 {
717 if (!player->usedown)
718 {
719 P_UseLines (player);
720 player->usedown = true;
721 }
722 }
723 else
724 player->usedown = false;
725
726 // cycle psprites
727 P_MovePsprites (player);
728
729 // Counters, time dependent power ups.
730
731 // Strength counts up to diminish fade.
732 if (player->powers[pw_strength])
733 player->powers[pw_strength]++;
734
735 if (player->powers[pw_invulnerability])
736 player->powers[pw_invulnerability]--;
737
738 if (player->powers[pw_invisibility])
739 if (! --player->powers[pw_invisibility] )
740 player->mo->flags &= ~MF_SHADOW;
741
742 if (player->powers[pw_infrared])
743 player->powers[pw_infrared]--;
744
745 if (player->powers[pw_ironfeet])
746 player->powers[pw_ironfeet]--;
747
748 if (player->damagecount)
749 player->damagecount--;
750
751 if (player->bonuscount)
752 player->bonuscount--;
753
754 // Handling colormaps.
755 if (displayplayer().powers[pw_invulnerability])
756 {
757 if (displayplayer().powers[pw_invulnerability] > 4*32
758 || (displayplayer().powers[pw_invulnerability]&8) )
759 displayplayer().fixedcolormap = INVERSECOLORMAP;
760 else
761 displayplayer().fixedcolormap = 0;
762 }
763 else if (player->powers[pw_infrared])
764 {
765 if (player->powers[pw_infrared] > 4*32
766 || (player->powers[pw_infrared]&8) )
767 {
768 // almost full bright
769 player->fixedcolormap = 1;
770 }
771 else
772 player->fixedcolormap = 0;
773 }
774 else
775 player->fixedcolormap = 0;
776
777 // Handle air supply
778 if (player->mo->waterlevel < 3 || player->powers[pw_ironfeet])
779 {
780 player->air_finished = level.time + 10*TICRATE;
781 }
782 else if (player->air_finished <= level.time && !(level.time & 31))
783 {
784 P_DamageMobj (player->mo, NULL, NULL, 2 + 2*((level.time-player->air_finished)/TICRATE), MOD_WATER, DMG_NO_ARMOR);
785 }
786 }
787
Serialize(FArchive & arc)788 void player_s::Serialize (FArchive &arc)
789 {
790 size_t i;
791
792 if (arc.IsStoring ())
793 { // saving to archive
794 arc << id
795 << playerstate
796 << spectator
797 << cmd
798 << userinfo
799 << viewz
800 << viewheight
801 << deltaviewheight
802 << bob
803 << health
804 << armorpoints
805 << armortype
806 << backpack
807 << fragcount
808 << readyweapon
809 << pendingweapon
810 << attackdown
811 << usedown
812 << cheats
813 << refire
814 << killcount
815 << itemcount
816 << secretcount
817 << damagecount
818 << bonuscount
819 << points
820 /*<< attacker->netid*/
821 << extralight
822 << fixedcolormap
823 << xviewshift
824 << jumpTics
825 << death_time
826 << air_finished;
827 for (i = 0; i < NUMPOWERS; i++)
828 arc << powers[i];
829 for (i = 0; i < NUMCARDS; i++)
830 arc << cards[i];
831 for (i = 0; i < NUMWEAPONS; i++)
832 arc << weaponowned[i];
833 for (i = 0; i < NUMAMMO; i++)
834 arc << ammo[i] << maxammo[i];
835 for (i = 0; i < NUMPSPRITES; i++)
836 arc << psprites[i];
837 for (i = 0; i < 3; i++)
838 arc << oldvelocity[i];
839 }
840 else
841 { // Restoring from archive
842 UserInfo dummyuserinfo;
843
844 arc >> id
845 >> playerstate
846 >> spectator
847 >> cmd
848 >> userinfo // Q: Would it be better to restore the userinfo from the archive?
849 >> viewz
850 >> viewheight
851 >> deltaviewheight
852 >> bob
853 >> health
854 >> armorpoints
855 >> armortype
856 >> backpack
857 >> fragcount
858 >> readyweapon
859 >> pendingweapon
860 >> attackdown
861 >> usedown
862 >> cheats
863 >> refire
864 >> killcount
865 >> itemcount
866 >> secretcount
867 >> damagecount
868 >> bonuscount
869 >> points
870 /*>> attacker->netid*/
871 >> extralight
872 >> fixedcolormap
873 >> xviewshift
874 >> jumpTics
875 >> death_time
876 >> air_finished;
877 for (i = 0; i < NUMPOWERS; i++)
878 arc >> powers[i];
879 for (i = 0; i < NUMCARDS; i++)
880 arc >> cards[i];
881 for (i = 0; i < NUMWEAPONS; i++)
882 arc >> weaponowned[i];
883 for (i = 0; i < NUMAMMO; i++)
884 arc >> ammo[i] >> maxammo[i];
885 for (i = 0; i < NUMPSPRITES; i++)
886 arc >> psprites[i];
887 for (i = 0; i < 3; i++)
888 arc >> oldvelocity[i];
889
890 camera = mo;
891
892 // if (&consoleplayer() != this)
893 // userinfo = dummyuserinfo;
894 }
895 }
896
player_s()897 player_s::player_s()
898 {
899 size_t i;
900
901 // GhostlyDeath -- Initialize EVERYTHING
902 id = 0;
903 playerstate = PST_LIVE;
904 mo = AActor::AActorPtr();
905 cmd.clear();
906 fov = 90.0;
907 viewz = 0 << FRACBITS;
908 viewheight = 0 << FRACBITS;
909 deltaviewheight = 0 << FRACBITS;
910 bob = 0 << FRACBITS;
911 health = 0;
912 armorpoints = 0;
913 armortype = 0;
914 for (i = 0; i < NUMPOWERS; i++)
915 powers[i] = 0;
916 for (i = 0; i < NUMCARDS; i++)
917 cards[i] = false;
918 backpack = false;
919 points = 0;
920 for (i = 0; i < NUMFLAGS; i++)
921 flags[i] = false;
922 fragcount = 0;
923 deathcount = 0;
924 killcount = 0;
925 pendingweapon = wp_nochange;
926 readyweapon = wp_nochange;
927 for (i = 0; i < NUMWEAPONS; i++)
928 weaponowned[i] = false;
929 for (i = 0; i < NUMAMMO; i++)
930 {
931 ammo[i] = 0;
932 maxammo[i] = 0;
933 }
934 attackdown = 0;
935 usedown = 0;
936 cheats = 0;
937 refire = 0;
938 damagecount = 0;
939 bonuscount = 0;
940 attacker = AActor::AActorPtr();
941 extralight = 0;
942 fixedcolormap = 0;
943 xviewshift = 0;
944 memset(psprites, 0, sizeof(pspdef_t) * NUMPSPRITES);
945 jumpTics = 0;
946 death_time = 0;
947 memset(oldvelocity, 0, sizeof(oldvelocity));
948 camera = AActor::AActorPtr();
949 air_finished = 0;
950 GameTime = 0;
951 JoinTime = 0;
952 ping = 0;
953 last_received = 0;
954 tic = 0;
955 spying = id;
956 spectator = false;
957
958 joinafterspectatortime = level.time - TICRATE*5;
959 timeout_callvote = 0;
960 timeout_vote = 0;
961
962 ready = false;
963 timeout_ready = 0;
964
965 prefcolor = 0;
966
967 LastMessage.Time = 0;
968 LastMessage.Message = "";
969
970 BlendR = 0;
971 BlendG = 0;
972 BlendB = 0;
973 BlendA = 0;
974
975 memset(netcmds, 0, sizeof(ticcmd_t) * BACKUPTICS);
976 }
977
operator =(const player_s & other)978 player_s &player_s::operator =(const player_s &other)
979 {
980 size_t i;
981
982 id = other.id;
983 playerstate = other.playerstate;
984 mo = other.mo;
985 cmd = other.cmd;
986 cmdqueue = other.cmdqueue;
987 userinfo = other.userinfo;
988 fov = other.fov;
989 viewz = other.viewz;
990 viewheight = other.viewheight;
991 deltaviewheight = other.deltaviewheight;
992 bob = other.bob;
993
994 health = other.health;
995 armorpoints = other.armorpoints;
996 armortype = other.armortype;
997
998 for(i = 0; i < NUMPOWERS; i++)
999 powers[i] = other.powers[i];
1000
1001 for(i = 0; i < NUMCARDS; i++)
1002 cards[i] = other.cards[i];
1003
1004 for(i = 0; i < NUMFLAGS; i++)
1005 flags[i] = other.flags[i];
1006
1007 points = other.points;
1008 backpack = other.backpack;
1009
1010 fragcount = other.fragcount;
1011 deathcount = other.deathcount;
1012 killcount = other.killcount;
1013
1014 pendingweapon = other.pendingweapon;
1015 readyweapon = other.readyweapon;
1016
1017 for(i = 0; i < NUMWEAPONS; i++)
1018 weaponowned[i] = other.weaponowned[i];
1019 for(i = 0; i < NUMAMMO; i++)
1020 ammo[i] = other.ammo[i];
1021 for(i = 0; i < NUMAMMO; i++)
1022 maxammo[i] = other.maxammo[i];
1023
1024 attackdown = other.attackdown;
1025 usedown = other.usedown;
1026
1027 cheats = other.cheats;
1028
1029 refire = other.refire;
1030
1031 damagecount = other.damagecount;
1032 bonuscount = other.bonuscount;
1033
1034 attacker = other.attacker;
1035
1036 extralight = other.extralight;
1037 fixedcolormap = other.fixedcolormap;
1038
1039 xviewshift = other.xviewshift;
1040
1041 for(i = 0; i < NUMPSPRITES; i++)
1042 psprites[i] = other.psprites[i];
1043
1044 jumpTics = other.jumpTics;
1045
1046 death_time = other.death_time;
1047
1048 memcpy(oldvelocity, other.oldvelocity, sizeof(oldvelocity));
1049
1050 camera = other.camera;
1051 air_finished = other.air_finished;
1052
1053 GameTime = other.GameTime;
1054 JoinTime = other.JoinTime;
1055 ping = other.ping;
1056
1057 last_received = other.last_received;
1058
1059 tic = other.tic;
1060 spying = other.spying;
1061 spectator = other.spectator;
1062 joinafterspectatortime = other.joinafterspectatortime;
1063 timeout_callvote = other.timeout_callvote;
1064 timeout_vote = other.timeout_vote;
1065
1066 ready = other.ready;
1067 timeout_ready = other.timeout_ready;
1068
1069 prefcolor = other.prefcolor;
1070
1071 for(i = 0; i < BACKUPTICS; i++)
1072 netcmds[i] = other.netcmds[i];
1073
1074 LastMessage.Time = other.LastMessage.Time;
1075 LastMessage.Message = other.LastMessage.Message;
1076
1077 BlendR = other.BlendR;
1078 BlendG = other.BlendG;
1079 BlendB = other.BlendB;
1080 BlendA = other.BlendA;
1081
1082 client = other.client;
1083
1084 snapshots = other.snapshots;
1085
1086 to_spawn = other.to_spawn;
1087
1088 return *this;
1089 }
1090
~player_s()1091 player_s::~player_s()
1092 {
1093 }
1094
1095 VERSION_CONTROL (p_user_cpp, "$Id: p_user.cpp 4542 2014-02-09 17:39:42Z dr_sean $")
1096
1097