1 //
2 // Copyright(C) 1993-1996 Id Software, Inc.
3 // Copyright(C) 2005-2014 Simon Howard
4 //
5 // This program is free software; you can redistribute it and/or
6 // modify it under the terms of the GNU General Public License
7 // as published by the Free Software Foundation; either version 2
8 // of the License, or (at your option) any later version.
9 //
10 // This program is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 // GNU General Public License for more details.
14 //
15 // DESCRIPTION:
16 //	Player related stuff.
17 //	Bobbing POV/weapon, movement.
18 //	Pending weapon.
19 //
20 
21 
22 
23 
24 #include "doomdef.h"
25 #include "d_event.h"
26 
27 #include "p_local.h"
28 
29 #include "doomstat.h"
30 
31 
32 
33 // Index of the special effects (INVUL inverse) map.
34 #define INVERSECOLORMAP		32
35 
36 
37 //
38 // Movement.
39 //
40 
41 // 16 pixels of bob
42 #define MAXBOB	0x100000
43 
44 boolean		onground;
45 
46 
47 //
48 // P_Thrust
49 // Moves the given origin along a given angle.
50 //
51 void
P_Thrust(player_t * player,angle_t angle,fixed_t move)52 P_Thrust
53 ( player_t*	player,
54   angle_t	angle,
55   fixed_t	move )
56 {
57     angle >>= ANGLETOFINESHIFT;
58 
59     player->mo->momx += FixedMul(move,finecosine[angle]);
60     player->mo->momy += FixedMul(move,finesine[angle]);
61 }
62 
63 
64 
65 
66 //
67 // P_CalcHeight
68 // Calculate the walking / running height adjustment
69 //
P_CalcHeight(player_t * player)70 void P_CalcHeight (player_t* player)
71 {
72     int		angle;
73     fixed_t	bob;
74 
75     // Regular movement bobbing
76     // (needs to be calculated for gun swing
77     // even if not on ground)
78     // OPTIMIZE: tablify angle
79     // Note: a LUT allows for effects
80     //  like a ramp with low health.
81     player->bob =
82 	FixedMul (player->mo->momx, player->mo->momx)
83 	+ FixedMul (player->mo->momy,player->mo->momy);
84 
85     player->bob >>= 2;
86 
87     if (player->bob>MAXBOB)
88 	player->bob = MAXBOB;
89 
90     if ((player->cheats & CF_NOMOMENTUM) || !onground)
91     {
92 	player->viewz = player->mo->z + VIEWHEIGHT;
93 
94 	if (player->viewz > player->mo->ceilingz-4*FRACUNIT)
95 	    player->viewz = player->mo->ceilingz-4*FRACUNIT;
96 
97 	player->viewz = player->mo->z + player->viewheight;
98 	return;
99     }
100 
101     angle = (FINEANGLES/20*leveltime)&FINEMASK;
102     bob = FixedMul ( player->bob/2, finesine[angle]);
103 
104 
105     // move viewheight
106     if (player->playerstate == PST_LIVE)
107     {
108 	player->viewheight += player->deltaviewheight;
109 
110 	if (player->viewheight > VIEWHEIGHT)
111 	{
112 	    player->viewheight = VIEWHEIGHT;
113 	    player->deltaviewheight = 0;
114 	}
115 
116 	if (player->viewheight < VIEWHEIGHT/2)
117 	{
118 	    player->viewheight = VIEWHEIGHT/2;
119 	    if (player->deltaviewheight <= 0)
120 		player->deltaviewheight = 1;
121 	}
122 
123 	if (player->deltaviewheight)
124 	{
125 	    player->deltaviewheight += FRACUNIT/4;
126 	    if (!player->deltaviewheight)
127 		player->deltaviewheight = 1;
128 	}
129     }
130     player->viewz = player->mo->z + player->viewheight + bob;
131 
132     if (player->viewz > player->mo->ceilingz-4*FRACUNIT)
133 	player->viewz = player->mo->ceilingz-4*FRACUNIT;
134 }
135 
136 
137 
138 //
139 // P_MovePlayer
140 //
P_MovePlayer(player_t * player)141 void P_MovePlayer (player_t* player)
142 {
143     ticcmd_t*		cmd;
144 
145     cmd = &player->cmd;
146 
147     player->mo->angle += (cmd->angleturn<<FRACBITS);
148 
149     // Do not let the player control movement
150     //  if not onground.
151     onground = (player->mo->z <= player->mo->floorz);
152 
153     if (cmd->forwardmove && onground)
154 	P_Thrust (player, player->mo->angle, cmd->forwardmove*2048);
155 
156     if (cmd->sidemove && onground)
157 	P_Thrust (player, player->mo->angle-ANG90, cmd->sidemove*2048);
158 
159     if ( (cmd->forwardmove || cmd->sidemove)
160 	 && player->mo->state == &states[S_PLAY] )
161     {
162 	P_SetMobjState (player->mo, S_PLAY_RUN1);
163     }
164 }
165 
166 
167 
168 //
169 // P_DeathThink
170 // Fall on your face when dying.
171 // Decrease POV height to floor height.
172 //
173 #define ANG5   	(ANG90/18)
174 
P_DeathThink(player_t * player)175 void P_DeathThink (player_t* player)
176 {
177     angle_t		angle;
178     angle_t		delta;
179 
180     P_MovePsprites (player);
181 
182     // fall to the ground
183     if (player->viewheight > 6*FRACUNIT)
184 	player->viewheight -= FRACUNIT;
185 
186     if (player->viewheight < 6*FRACUNIT)
187 	player->viewheight = 6*FRACUNIT;
188 
189     player->deltaviewheight = 0;
190     onground = (player->mo->z <= player->mo->floorz);
191     P_CalcHeight (player);
192 
193     if (player->attacker && player->attacker != player->mo)
194     {
195 	angle = R_PointToAngle2 (player->mo->x,
196 				 player->mo->y,
197 				 player->attacker->x,
198 				 player->attacker->y);
199 
200 	delta = angle - player->mo->angle;
201 
202 	if (delta < ANG5 || delta > (unsigned)-ANG5)
203 	{
204 	    // Looking at killer,
205 	    //  so fade damage flash down.
206 	    player->mo->angle = angle;
207 
208 	    if (player->damagecount)
209 		player->damagecount--;
210 	}
211 	else if (delta < ANG180)
212 	    player->mo->angle += ANG5;
213 	else
214 	    player->mo->angle -= ANG5;
215     }
216     else if (player->damagecount)
217 	player->damagecount--;
218 
219 
220     if (player->cmd.buttons & BT_USE)
221 	player->playerstate = PST_REBORN;
222 }
223 
224 
225 
226 //
227 // P_PlayerThink
228 //
P_PlayerThink(player_t * player)229 void P_PlayerThink (player_t* player)
230 {
231     ticcmd_t*		cmd;
232     weapontype_t	newweapon;
233 
234     // fixme: do this in the cheat code
235     if (player->cheats & CF_NOCLIP)
236 	player->mo->flags |= MF_NOCLIP;
237     else
238 	player->mo->flags &= ~MF_NOCLIP;
239 
240     // chain saw run forward
241     cmd = &player->cmd;
242     if (player->mo->flags & MF_JUSTATTACKED)
243     {
244 	cmd->angleturn = 0;
245 	cmd->forwardmove = 0xc800/512;
246 	cmd->sidemove = 0;
247 	player->mo->flags &= ~MF_JUSTATTACKED;
248     }
249 
250 
251     if (player->playerstate == PST_DEAD)
252     {
253 	P_DeathThink (player);
254 	return;
255     }
256 
257     // Move around.
258     // Reactiontime is used to prevent movement
259     //  for a bit after a teleport.
260     if (player->mo->reactiontime)
261 	player->mo->reactiontime--;
262     else
263 	P_MovePlayer (player);
264 
265     P_CalcHeight (player);
266 
267     if (player->mo->subsector->sector->special)
268 	P_PlayerInSpecialSector (player);
269 
270     // Check for weapon change.
271 
272     // A special event has no other buttons.
273     if (cmd->buttons & BT_SPECIAL)
274 	cmd->buttons = 0;
275 
276     if (cmd->buttons & BT_CHANGE)
277     {
278 	// The actual changing of the weapon is done
279 	//  when the weapon psprite can do it
280 	//  (read: not in the middle of an attack).
281 	newweapon = (cmd->buttons&BT_WEAPONMASK)>>BT_WEAPONSHIFT;
282 
283 	if (newweapon == wp_fist
284 	    && player->weaponowned[wp_chainsaw]
285 	    && !(player->readyweapon == wp_chainsaw
286 		 && player->powers[pw_strength]))
287 	{
288 	    newweapon = wp_chainsaw;
289 	}
290 
291 	if ( (gamemode == commercial)
292 	    && newweapon == wp_shotgun
293 	    && player->weaponowned[wp_supershotgun]
294 	    && player->readyweapon != wp_supershotgun)
295 	{
296 	    newweapon = wp_supershotgun;
297 	}
298 
299 
300 	if (player->weaponowned[newweapon]
301 	    && newweapon != player->readyweapon)
302 	{
303 	    // Do not go to plasma or BFG in shareware,
304 	    //  even if cheated.
305 	    if ((newweapon != wp_plasma
306 		 && newweapon != wp_bfg)
307 		|| (gamemode != shareware) )
308 	    {
309 		player->pendingweapon = newweapon;
310 	    }
311 	}
312     }
313 
314     // check for use
315     if (cmd->buttons & BT_USE)
316     {
317 	if (!player->usedown)
318 	{
319 	    P_UseLines (player);
320 	    player->usedown = true;
321 	}
322     }
323     else
324 	player->usedown = false;
325 
326     // cycle psprites
327     P_MovePsprites (player);
328 
329     // Counters, time dependend power ups.
330 
331     // Strength counts up to diminish fade.
332     if (player->powers[pw_strength])
333 	player->powers[pw_strength]++;
334 
335     if (player->powers[pw_invulnerability])
336 	player->powers[pw_invulnerability]--;
337 
338     if (player->powers[pw_invisibility])
339 	if (! --player->powers[pw_invisibility] )
340 	    player->mo->flags &= ~MF_SHADOW;
341 
342     if (player->powers[pw_infrared])
343 	player->powers[pw_infrared]--;
344 
345     if (player->powers[pw_ironfeet])
346 	player->powers[pw_ironfeet]--;
347 
348     if (player->damagecount)
349 	player->damagecount--;
350 
351     if (player->bonuscount)
352 	player->bonuscount--;
353 
354 
355     // Handling colormaps.
356     if (player->powers[pw_invulnerability])
357     {
358 	if (player->powers[pw_invulnerability] > 4*32
359 	    || (player->powers[pw_invulnerability]&8) )
360 	    player->fixedcolormap = INVERSECOLORMAP;
361 	else
362 	    player->fixedcolormap = 0;
363     }
364     else if (player->powers[pw_infrared])
365     {
366 	if (player->powers[pw_infrared] > 4*32
367 	    || (player->powers[pw_infrared]&8) )
368 	{
369 	    // almost full bright
370 	    player->fixedcolormap = 1;
371 	}
372 	else
373 	    player->fixedcolormap = 0;
374     }
375     else
376 	player->fixedcolormap = 0;
377 }
378 
379 
380