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