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