1 /* Emacs style mode select   -*- C++ -*-
2  *-----------------------------------------------------------------------------
3  *
4  *
5  *  PrBoom: a Doom port merged with LxDoom and LSDLDoom
6  *  based on BOOM, a modified and improved DOOM engine
7  *  Copyright (C) 1999 by
8  *  id Software, Chi Hoang, Lee Killough, Jim Flynn, Rand Phares, Ty Halderman
9  *  Copyright (C) 1999-2000 by
10  *  Jess Haas, Nicolas Kalkhof, Colin Phipps, Florian Schulze
11  *  Copyright 2005, 2006 by
12  *  Florian Schulze, Colin Phipps, Neil Stevens, Andrey Budko
13  *
14  *  This program is free software; you can redistribute it and/or
15  *  modify it under the terms of the GNU General Public License
16  *  as published by the Free Software Foundation; either version 2
17  *  of the License, or (at your option) any later version.
18  *
19  *  This program is distributed in the hope that it will be useful,
20  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
21  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
22  *  GNU General Public License for more details.
23  *
24  *  You should have received a copy of the GNU General Public License
25  *  along with this program; if not, write to the Free Software
26  *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
27  *  02111-1307, USA.
28  *
29  * DESCRIPTION:
30  *      Player related stuff.
31  *      Bobbing POV/weapon, movement.
32  *      Pending weapon.
33  *
34  *-----------------------------------------------------------------------------*/
35 
36 #include "doomstat.h"
37 #include "d_event.h"
38 #include "r_main.h"
39 #include "p_map.h"
40 #include "p_spec.h"
41 #include "p_user.h"
42 #include "r_demo.h"
43 #include "r_fps.h"
44 #include "g_game.h"
45 #include "e6y.h"//e6y
46 
47 //
48 // Movement.
49 //
50 
51 // 16 pixels of bob
52 
53 #define MAXBOB  0x100000
54 
55 dboolean onground; // whether player is on ground or in air
56 
57 //
58 // P_Thrust
59 // Moves the given origin along a given angle.
60 //
61 
P_Thrust(player_t * player,angle_t angle,fixed_t move)62 void P_Thrust(player_t* player,angle_t angle,fixed_t move)
63 {
64   angle >>= ANGLETOFINESHIFT;
65   player->mo->momx += FixedMul(move,finecosine[angle]);
66   player->mo->momy += FixedMul(move,finesine[angle]);
67 }
68 
69 
70 /*
71  * P_Bob
72  * Same as P_Thrust, but only affects bobbing.
73  *
74  * killough 10/98: We apply thrust separately between the real physical player
75  * and the part which affects bobbing. This way, bobbing only comes from player
76  * motion, nothing external, avoiding many problems, e.g. bobbing should not
77  * occur on conveyors, unless the player walks on one, and bobbing should be
78  * reduced at a regular rate, even on ice (where the player coasts).
79  */
80 
P_Bob(player_t * player,angle_t angle,fixed_t move)81 static void P_Bob(player_t *player, angle_t angle, fixed_t move)
82 {
83   //e6y
84   if (!mbf_features && !prboom_comp[PC_PRBOOM_FRICTION].state)
85     return;
86 
87   player->momx += FixedMul(move,finecosine[angle >>= ANGLETOFINESHIFT]);
88   player->momy += FixedMul(move,finesine[angle]);
89 }
90 
91 //
92 // P_CalcHeight
93 // Calculate the walking / running height adjustment
94 //
95 
P_CalcHeight(player_t * player)96 void P_CalcHeight (player_t* player)
97 {
98   int     angle;
99   fixed_t bob;
100 
101   // Regular movement bobbing
102   // (needs to be calculated for gun swing
103   // even if not on ground)
104   // OPTIMIZE: tablify angle
105   // Note: a LUT allows for effects
106   //  like a ramp with low health.
107 
108 
109   /* killough 10/98: Make bobbing depend only on player-applied motion.
110    *
111    * Note: don't reduce bobbing here if on ice: if you reduce bobbing here,
112    * it causes bobbing jerkiness when the player moves from ice to non-ice,
113    * and vice-versa.
114    */
115 
116     player->bob = 0;
117     if (mbf_features)
118     {
119       if (player_bobbing)
120       {
121         player->bob = (FixedMul(player->momx, player->momx) +
122           FixedMul(player->momy, player->momy)) >> 2;
123       }
124     }
125     else
126     {
127       if (demo_compatibility || player_bobbing || prboom_comp[PC_FORCE_INCORRECT_BOBBING_IN_BOOM].state)
128       {
129         player->bob = (FixedMul(player->mo->momx, player->mo->momx) +
130           FixedMul(player->mo->momy, player->mo->momy)) >> 2;
131       }
132     }
133 
134     //e6y
135     if (!prboom_comp[PC_PRBOOM_FRICTION].state &&
136         compatibility_level >= boom_202_compatibility &&
137         compatibility_level <= lxdoom_1_compatibility &&
138         player->mo->friction > ORIG_FRICTION) // ice?
139     {
140       if (player->bob > (MAXBOB>>2))
141         player->bob = MAXBOB>>2;
142     }
143     else
144     {
145       if (player->bob > MAXBOB)
146         player->bob = MAXBOB;
147     }
148 
149   if (!onground || player->cheats & CF_NOMOMENTUM)
150     {
151     player->viewz = player->mo->z + VIEWHEIGHT;
152 
153     if (player->viewz > player->mo->ceilingz-4*FRACUNIT)
154       player->viewz = player->mo->ceilingz-4*FRACUNIT;
155 
156 // The following line was in the Id source and appears      // phares 2/25/98
157 // to be a bug. player->viewz is checked in a similar
158 // manner at a different exit below.
159 
160 //  player->viewz = player->mo->z + player->viewheight;
161     return;
162     }
163 
164   angle = (FINEANGLES/20*leveltime)&FINEMASK;
165   bob = FixedMul(player->bob/2,finesine[angle]);
166 
167   // move viewheight
168 
169   if (player->playerstate == PST_LIVE)
170     {
171     player->viewheight += player->deltaviewheight;
172 
173     if (player->viewheight > VIEWHEIGHT)
174       {
175       player->viewheight = VIEWHEIGHT;
176       player->deltaviewheight = 0;
177       }
178 
179     if (player->viewheight < VIEWHEIGHT/2)
180       {
181       player->viewheight = VIEWHEIGHT/2;
182       if (player->deltaviewheight <= 0)
183         player->deltaviewheight = 1;
184       }
185 
186     if (player->deltaviewheight)
187       {
188       player->deltaviewheight += FRACUNIT/4;
189       if (!player->deltaviewheight)
190         player->deltaviewheight = 1;
191       }
192     }
193 
194   player->viewz = player->mo->z + player->viewheight + bob;
195 
196   if (player->viewz > player->mo->ceilingz-4*FRACUNIT)
197     player->viewz = player->mo->ceilingz-4*FRACUNIT;
198 }
199 
200 
201 //
202 // P_SetPitch
203 // Mouse Look Stuff
204 //
P_SetPitch(player_t * player)205 void P_SetPitch(player_t *player)
206 {
207   mobj_t *mo = player->mo;
208 
209 #ifdef GL_DOOM
210   if (V_GetMode() == VID_MODEGL && player == &players[consoleplayer])
211   {
212     if (!(demoplayback || democontinue))
213     {
214       if (GetMouseLook())
215       {
216         if (!mo->reactiontime && (!(automapmode & am_active) || (automapmode & am_overlay)))
217         {
218           mo->pitch += (mlooky << 16);
219           CheckPitch((signed int *)&mo->pitch);
220         }
221       }
222       else
223       {
224         mo->pitch = 0;
225       }
226 
227       R_DemoEx_WriteMLook(mo->pitch);
228     }
229     else
230     {
231       mo->pitch = R_DemoEx_ReadMLook();
232       CheckPitch((signed int *)&mo->pitch);
233     }
234   }
235   else
236   {
237     mo->pitch = 0;
238   }
239 #else // GL_DOOM
240   mo->pitch = 0;
241 #endif // GL_DOOM
242 }
243 
244 //
245 // P_MovePlayer
246 //
247 // Adds momentum if the player is not in the air
248 //
249 // killough 10/98: simplified
250 
P_MovePlayer(player_t * player)251 void P_MovePlayer (player_t* player)
252 {
253   ticcmd_t *cmd = &player->cmd;
254   mobj_t *mo = player->mo;
255 
256   mo->angle += cmd->angleturn << 16;
257 
258   if (demo_smoothturns && player == &players[displayplayer])
259   {
260     R_SmoothPlaying_Add(cmd->angleturn << 16);
261   }
262 
263   onground = mo->z <= mo->floorz;
264 
265   // killough 10/98:
266   //
267   // We must apply thrust to the player and bobbing separately, to avoid
268   // anomalies. The thrust applied to bobbing is always the same strength on
269   // ice, because the player still "works just as hard" to move, while the
270   // thrust applied to the movement varies with 'movefactor'.
271 
272   //e6y
273   if ((!demo_compatibility && !mbf_features && !prboom_comp[PC_PRBOOM_FRICTION].state) ||
274     (cmd->forwardmove | cmd->sidemove)) // killough 10/98
275     {
276       if (onground || mo->flags & MF_BOUNCES) // killough 8/9/98
277       {
278         int friction, movefactor = P_GetMoveFactor(mo, &friction);
279 
280         // killough 11/98:
281         // On sludge, make bobbing depend on efficiency.
282         // On ice, make it depend on effort.
283 
284         int bobfactor =
285           friction < ORIG_FRICTION ? movefactor : ORIG_FRICTION_FACTOR;
286 
287         if (cmd->forwardmove)
288         {
289           P_Bob(player,mo->angle,cmd->forwardmove*bobfactor);
290           P_Thrust(player,mo->angle,cmd->forwardmove*movefactor);
291         }
292 
293         if (cmd->sidemove)
294         {
295           P_Bob(player,mo->angle-ANG90,cmd->sidemove*bobfactor);
296           P_Thrust(player,mo->angle-ANG90,cmd->sidemove*movefactor);
297         }
298       }
299       if (mo->state == states+S_PLAY)
300         P_SetMobjState(mo,S_PLAY_RUN1);
301     }
302 }
303 
304 #define ANG5 (ANG90/18)
305 
306 //
307 // P_DeathThink
308 // Fall on your face when dying.
309 // Decrease POV height to floor height.
310 //
311 
P_DeathThink(player_t * player)312 void P_DeathThink (player_t* player)
313 {
314   angle_t angle;
315   angle_t delta;
316 
317   P_MovePsprites (player);
318 
319   // fall to the ground
320 
321   if (player->viewheight > 6*FRACUNIT)
322     player->viewheight -= FRACUNIT;
323 
324   if (player->viewheight < 6*FRACUNIT)
325     player->viewheight = 6*FRACUNIT;
326 
327   player->deltaviewheight = 0;
328   onground = (player->mo->z <= player->mo->floorz);
329   P_CalcHeight (player);
330 
331   if (player->attacker && player->attacker != player->mo)
332     {
333     angle = R_PointToAngle2 (player->mo->x,
334                              player->mo->y,
335                              player->attacker->x,
336                              player->attacker->y);
337 
338     delta = angle - player->mo->angle;
339 
340     if (delta < ANG5 || delta > (unsigned)-ANG5)
341       {
342       // Looking at killer,
343       //  so fade damage flash down.
344 
345       player->mo->angle = angle;
346 
347       if (player->damagecount)
348         player->damagecount--;
349       }
350     else if (delta < ANG180)
351       player->mo->angle += ANG5;
352     else
353       player->mo->angle -= ANG5;
354     }
355   else if (player->damagecount)
356     player->damagecount--;
357 
358   if (player->cmd.buttons & BT_USE)
359     player->playerstate = PST_REBORN;
360   R_SmoothPlaying_Reset(player); // e6y
361 }
362 
363 
364 //
365 // P_PlayerThink
366 //
367 
P_PlayerThink(player_t * player)368 void P_PlayerThink (player_t* player)
369 {
370   ticcmd_t*    cmd;
371   weapontype_t newweapon;
372 
373   //e6y
374   if (movement_smooth && &players[displayplayer] == player)
375   {
376     player->prev_viewz = player->viewz;
377     player->prev_viewangle = R_SmoothPlaying_Get(player->mo->angle) + viewangleoffset;
378     player->prev_viewpitch = player->mo->pitch;
379 
380     if(walkcamera.type)
381     {
382       P_ResetWalkcam();
383     }
384   }
385 
386   // killough 2/8/98, 3/21/98:
387   if (player->cheats & CF_NOCLIP)
388     player->mo->flags |= MF_NOCLIP;
389   else
390     player->mo->flags &= ~MF_NOCLIP;
391 
392   // chain saw run forward
393 
394   cmd = &player->cmd;
395   if (player->mo->flags & MF_JUSTATTACKED)
396     {
397     cmd->angleturn = 0;
398     cmd->forwardmove = 0xc800/512;
399     cmd->sidemove = 0;
400     player->mo->flags &= ~MF_JUSTATTACKED;
401     }
402 
403   if (player->playerstate == PST_DEAD)
404     {
405     P_DeathThink (player);
406     return;
407     }
408 
409   // Move around.
410   // Reactiontime is used to prevent movement
411   //  for a bit after a teleport.
412 
413   if (player->mo->reactiontime)
414     player->mo->reactiontime--;
415   else
416     P_MovePlayer (player);
417 
418   P_SetPitch(player);
419 
420   P_CalcHeight (player); // Determines view height and bobbing
421 
422   // Determine if there's anything about the sector you're in that's
423   // going to affect you, like painful floors.
424 
425   if (player->mo->subsector->sector->special)
426     P_PlayerInSpecialSector (player);
427 
428   // Check for weapon change.
429 
430   if (cmd->buttons & BT_CHANGE)
431     {
432     // The actual changing of the weapon is done
433     //  when the weapon psprite can do it
434     //  (read: not in the middle of an attack).
435 
436     newweapon = (cmd->buttons & BT_WEAPONMASK)>>BT_WEAPONSHIFT;
437 
438     // killough 3/22/98: For demo compatibility we must perform the fist
439     // and SSG weapons switches here, rather than in G_BuildTiccmd(). For
440     // other games which rely on user preferences, we must use the latter.
441 
442     if (demo_compatibility)
443       { // compatibility mode -- required for old demos -- killough
444       //e6y
445       if (!prboom_comp[PC_ALLOW_SSG_DIRECT].state)
446         newweapon = (cmd->buttons & BT_WEAPONMASK_OLD)>>BT_WEAPONSHIFT;
447 
448       if (newweapon == wp_fist && player->weaponowned[wp_chainsaw] &&
449         (player->readyweapon != wp_chainsaw ||
450          !player->powers[pw_strength]))
451         newweapon = wp_chainsaw;
452       if (gamemode == commercial &&
453         newweapon == wp_shotgun &&
454         player->weaponowned[wp_supershotgun] &&
455         player->readyweapon != wp_supershotgun)
456         newweapon = wp_supershotgun;
457       }
458 
459     // killough 2/8/98, 3/22/98 -- end of weapon selection changes
460 
461     if (player->weaponowned[newweapon] && newweapon != player->readyweapon)
462 
463       // Do not go to plasma or BFG in shareware,
464       //  even if cheated.
465 
466       if ((newweapon != wp_plasma && newweapon != wp_bfg)
467           || (gamemode != shareware) )
468         player->pendingweapon = newweapon;
469     }
470 
471   // check for use
472 
473   if (cmd->buttons & BT_USE)
474     {
475     if (!player->usedown)
476       {
477       P_UseLines (player);
478       player->usedown = true;
479       }
480     }
481   else
482     player->usedown = false;
483 
484   // cycle psprites
485 
486   P_MovePsprites (player);
487 
488   // Counters, time dependent power ups.
489 
490   // Strength counts up to diminish fade.
491 
492   if (player->powers[pw_strength])
493     player->powers[pw_strength]++;
494 
495   // killough 1/98: Make idbeholdx toggle:
496 
497   if (player->powers[pw_invulnerability] > 0) // killough
498     player->powers[pw_invulnerability]--;
499 
500   if (player->powers[pw_invisibility] > 0)    // killough
501     if (! --player->powers[pw_invisibility] )
502       player->mo->flags &= ~MF_SHADOW;
503 
504   if (player->powers[pw_infrared] > 0)        // killough
505     player->powers[pw_infrared]--;
506 
507   if (player->powers[pw_ironfeet] > 0)        // killough
508     player->powers[pw_ironfeet]--;
509 
510   if (player->damagecount)
511     player->damagecount--;
512 
513   if (player->bonuscount)
514     player->bonuscount--;
515 
516   // Handling colormaps.
517   // killough 3/20/98: reformat to terse C syntax
518 
519 //e6y  player->fixedcolormap = player->powers[pw_invulnerability] > 4*32 ||
520 //e6y    player->powers[pw_invulnerability] & 8 ? INVERSECOLORMAP :
521 //e6y    player->powers[pw_infrared] > 4*32 || player->powers[pw_infrared] & 8;
522 //e6y
523   player->fixedcolormap = palette_onpowers &&
524     (player->powers[pw_invulnerability] > 4*32 ||
525     player->powers[pw_invulnerability] & 8) ? INVERSECOLORMAP :
526     player->powers[pw_infrared] > 4*32 || player->powers[pw_infrared] & 8;
527 }
528