1 // Emacs style mode select -*- C++ -*-
2 //-----------------------------------------------------------------------------
6 // Copyright (C) 1993-1996 by id Software, Inc.
8 // This source is available for distribution and/or modification
9 // only under the terms of the DOOM Source Code License as
10 // published by id Software. All rights reserved.
12 // The source is distributed in the hope that it will be useful,
13 // but WITHOUT ANY WARRANTY; without even the implied warranty of
14 // FITNESS FOR A PARTICULAR PURPOSE. See the DOOM Source Code License
20 // Player related stuff.
21 // Bobbing POV/weapon, movement.
24 //-----------------------------------------------------------------------------
28 rcsid[] = "$Id: p_user.c,v 1.3 1997/01/28 22:08:29 b1 Exp $";
40 // Index of the special effects (INVUL inverse) map.
41 #define INVERSECOLORMAP 32
49 #define MAXBOB 0x100000
56 // Moves the given origin along a given angle.
64 angle >>= ANGLETOFINESHIFT;
66 player->mo->momx += FixedMul(move,finecosine[angle]);
67 player->mo->momy += FixedMul(move,finesine[angle]);
75 // Calculate the walking / running height adjustment
77 void P_CalcHeight (player_t* player)
82 // Regular movement bobbing
83 // (needs to be calculated for gun swing
84 // even if not on ground)
85 // OPTIMIZE: tablify angle
86 // Note: a LUT allows for effects
87 // like a ramp with low health.
89 FixedMul (player->mo->momx, player->mo->momx)
90 + FixedMul (player->mo->momy,player->mo->momy);
94 if (player->bob>MAXBOB)
97 if ((player->cheats & CF_NOMOMENTUM) || !onground)
99 player->viewz = player->mo->z + VIEWHEIGHT;
101 if (player->viewz > player->mo->ceilingz-4*FRACUNIT)
102 player->viewz = player->mo->ceilingz-4*FRACUNIT;
104 player->viewz = player->mo->z + player->viewheight;
108 angle = (FINEANGLES/20*leveltime)&FINEMASK;
109 bob = FixedMul ( player->bob/2, finesine[angle]);
113 if (player->playerstate == PST_LIVE)
115 player->viewheight += player->deltaviewheight;
117 if (player->viewheight > VIEWHEIGHT)
119 player->viewheight = VIEWHEIGHT;
120 player->deltaviewheight = 0;
123 if (player->viewheight < VIEWHEIGHT/2)
125 player->viewheight = VIEWHEIGHT/2;
126 if (player->deltaviewheight <= 0)
127 player->deltaviewheight = 1;
130 if (player->deltaviewheight)
132 player->deltaviewheight += FRACUNIT/4;
133 if (!player->deltaviewheight)
134 player->deltaviewheight = 1;
137 player->viewz = player->mo->z + player->viewheight + bob;
139 if (player->viewz > player->mo->ceilingz-4*FRACUNIT)
140 player->viewz = player->mo->ceilingz-4*FRACUNIT;
148 void P_MovePlayer (player_t* player)
154 player->mo->angle += (cmd->angleturn<<16);
156 // Do not let the player control movement
158 onground = (player->mo->z <= player->mo->floorz);
160 if (cmd->forwardmove && onground)
161 P_Thrust (player, player->mo->angle, cmd->forwardmove*2048);
163 if (cmd->sidemove && onground)
164 P_Thrust (player, player->mo->angle-ANG90, cmd->sidemove*2048);
166 if ( (cmd->forwardmove || cmd->sidemove)
167 && player->mo->state == &states[S_PLAY] )
169 P_SetMobjState (player->mo, S_PLAY_RUN1);
177 // Fall on your face when dying.
178 // Decrease POV height to floor height.
180 #define ANG5 (ANG90/18)
182 void P_DeathThink (player_t* player)
187 P_MovePsprites (player);
189 // fall to the ground
190 if (player->viewheight > 6*FRACUNIT)
191 player->viewheight -= FRACUNIT;
193 if (player->viewheight < 6*FRACUNIT)
194 player->viewheight = 6*FRACUNIT;
196 player->deltaviewheight = 0;
197 onground = (player->mo->z <= player->mo->floorz);
198 P_CalcHeight (player);
200 if (player->attacker && player->attacker != player->mo)
202 angle = R_PointToAngle2 (player->mo->x,
205 player->attacker->y);
207 delta = angle - player->mo->angle;
209 if (delta < ANG5 || delta > (unsigned)-ANG5)
211 // Looking at killer,
212 // so fade damage flash down.
213 player->mo->angle = angle;
215 if (player->damagecount)
216 player->damagecount--;
218 else if (delta < ANG180)
219 player->mo->angle += ANG5;
221 player->mo->angle -= ANG5;
223 else if (player->damagecount)
224 player->damagecount--;
227 if (player->cmd.buttons & BT_USE)
228 player->playerstate = PST_REBORN;
236 void P_PlayerThink (player_t* player)
239 weapontype_t newweapon;
241 // fixme: do this in the cheat code
242 if (player->cheats & CF_NOCLIP)
243 player->mo->flags |= MF_NOCLIP;
245 player->mo->flags &= ~MF_NOCLIP;
247 // chain saw run forward
249 if (player->mo->flags & MF_JUSTATTACKED)
252 cmd->forwardmove = 0xc800/512;
254 player->mo->flags &= ~MF_JUSTATTACKED;
258 if (player->playerstate == PST_DEAD)
260 P_DeathThink (player);
265 // Reactiontime is used to prevent movement
266 // for a bit after a teleport.
267 if (player->mo->reactiontime)
268 player->mo->reactiontime--;
270 P_MovePlayer (player);
272 P_CalcHeight (player);
274 if (player->mo->subsector->sector->special)
275 P_PlayerInSpecialSector (player);
277 // Check for weapon change.
279 // A special event has no other buttons.
280 if (cmd->buttons & BT_SPECIAL)
283 if (cmd->buttons & BT_CHANGE)
285 // The actual changing of the weapon is done
286 // when the weapon psprite can do it
287 // (read: not in the middle of an attack).
288 newweapon = (cmd->buttons&BT_WEAPONMASK)>>BT_WEAPONSHIFT;
290 if (newweapon == wp_fist
291 && player->weaponowned[wp_chainsaw]
292 && !(player->readyweapon == wp_chainsaw
293 && player->powers[pw_strength]))
295 newweapon = wp_chainsaw;
298 if ( (gamemode == commercial)
299 && newweapon == wp_shotgun
300 && player->weaponowned[wp_supershotgun]
301 && player->readyweapon != wp_supershotgun)
303 newweapon = wp_supershotgun;
307 if (player->weaponowned[newweapon]
308 && newweapon != player->readyweapon)
310 // Do not go to plasma or BFG in shareware,
312 if ((newweapon != wp_plasma
313 && newweapon != wp_bfg)
314 || (gamemode != shareware) )
316 player->pendingweapon = newweapon;
322 if (cmd->buttons & BT_USE)
324 if (!player->usedown)
327 player->usedown = true;
331 player->usedown = false;
334 P_MovePsprites (player);
336 // Counters, time dependend power ups.
338 // Strength counts up to diminish fade.
339 if (player->powers[pw_strength])
340 player->powers[pw_strength]++;
342 if (player->powers[pw_invulnerability])
343 player->powers[pw_invulnerability]--;
345 if (player->powers[pw_invisibility])
346 if (! --player->powers[pw_invisibility] )
347 player->mo->flags &= ~MF_SHADOW;
349 if (player->powers[pw_infrared])
350 player->powers[pw_infrared]--;
352 if (player->powers[pw_ironfeet])
353 player->powers[pw_ironfeet]--;
355 if (player->damagecount)
356 player->damagecount--;
358 if (player->bonuscount)
359 player->bonuscount--;
362 // Handling colormaps.
363 if (player->powers[pw_invulnerability])
365 if (player->powers[pw_invulnerability] > 4*32
366 || (player->powers[pw_invulnerability]&8) )
367 player->fixedcolormap = INVERSECOLORMAP;
369 player->fixedcolormap = 0;
371 else if (player->powers[pw_infrared])
373 if (player->powers[pw_infrared] > 4*32
374 || (player->powers[pw_infrared]&8) )
376 // almost full bright
377 player->fixedcolormap = 1;
380 player->fixedcolormap = 0;
383 player->fixedcolormap = 0;