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