Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
298 | serge | 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 | // Weapon sprite animation, weapon objects. |
||
21 | // Action functions for weapons. |
||
22 | // |
||
23 | //----------------------------------------------------------------------------- |
||
24 | |||
25 | static const char |
||
26 | rcsid[] = "$Id: p_pspr.c,v 1.5 1997/02/03 22:45:12 b1 Exp $"; |
||
27 | |||
28 | #include "doomdef.h" |
||
29 | #include "d_event.h" |
||
30 | |||
31 | |||
32 | #include "m_random.h" |
||
33 | #include "p_local.h" |
||
34 | #include "s_sound.h" |
||
35 | |||
36 | // State. |
||
37 | #include "doomstat.h" |
||
38 | |||
39 | // Data. |
||
40 | #include "sounds.h" |
||
41 | |||
42 | #include "p_pspr.h" |
||
43 | |||
44 | #define LOWERSPEED FRACUNIT*6 |
||
45 | #define RAISESPEED FRACUNIT*6 |
||
46 | |||
47 | #define WEAPONBOTTOM 128*FRACUNIT |
||
48 | #define WEAPONTOP 32*FRACUNIT |
||
49 | |||
50 | |||
51 | // plasma cells for a bfg attack |
||
52 | #define BFGCELLS 40 |
||
53 | |||
54 | |||
55 | // |
||
56 | // P_SetPsprite |
||
57 | // |
||
58 | void |
||
59 | P_SetPsprite |
||
60 | ( player_t* player, |
||
61 | int position, |
||
62 | statenum_t stnum ) |
||
63 | { |
||
64 | pspdef_t* psp; |
||
65 | state_t* state; |
||
66 | |||
67 | psp = &player->psprites[position]; |
||
68 | |||
69 | do |
||
70 | { |
||
71 | if (!stnum) |
||
72 | { |
||
73 | // object removed itself |
||
74 | psp->state = NULL; |
||
75 | break; |
||
76 | } |
||
77 | |||
78 | state = &states[stnum]; |
||
79 | psp->state = state; |
||
80 | psp->tics = state->tics; // could be 0 |
||
81 | |||
82 | if (state->misc1) |
||
83 | { |
||
84 | // coordinate set |
||
85 | psp->sx = state->misc1 << FRACBITS; |
||
86 | psp->sy = state->misc2 << FRACBITS; |
||
87 | } |
||
88 | |||
89 | // Call action routine. |
||
90 | // Modified handling. |
||
91 | if (state->action.acp2) |
||
92 | { |
||
93 | state->action.acp2(player, psp); |
||
94 | if (!psp->state) |
||
95 | break; |
||
96 | } |
||
97 | |||
98 | stnum = psp->state->nextstate; |
||
99 | |||
100 | } while (!psp->tics); |
||
101 | // an initial state of 0 could cycle through |
||
102 | } |
||
103 | |||
104 | |||
105 | |||
106 | // |
||
107 | // P_CalcSwing |
||
108 | // |
||
109 | fixed_t swingx; |
||
110 | fixed_t swingy; |
||
111 | |||
112 | void P_CalcSwing (player_t* player) |
||
113 | { |
||
114 | fixed_t swing; |
||
115 | int angle; |
||
116 | |||
117 | // OPTIMIZE: tablify this. |
||
118 | // A LUT would allow for different modes, |
||
119 | // and add flexibility. |
||
120 | |||
121 | swing = player->bob; |
||
122 | |||
123 | angle = (FINEANGLES/70*leveltime)&FINEMASK; |
||
124 | swingx = FixedMul ( swing, finesine[angle]); |
||
125 | |||
126 | angle = (FINEANGLES/70*leveltime+FINEANGLES/2)&FINEMASK; |
||
127 | swingy = -FixedMul ( swingx, finesine[angle]); |
||
128 | } |
||
129 | |||
130 | |||
131 | |||
132 | // |
||
133 | // P_BringUpWeapon |
||
134 | // Starts bringing the pending weapon up |
||
135 | // from the bottom of the screen. |
||
136 | // Uses player |
||
137 | // |
||
138 | void P_BringUpWeapon (player_t* player) |
||
139 | { |
||
140 | statenum_t newstate; |
||
141 | |||
142 | if (player->pendingweapon == wp_nochange) |
||
143 | player->pendingweapon = player->readyweapon; |
||
144 | |||
145 | if (player->pendingweapon == wp_chainsaw) |
||
146 | S_StartSound (player->mo, sfx_sawup); |
||
147 | |||
148 | newstate = weaponinfo[player->pendingweapon].upstate; |
||
149 | |||
150 | player->pendingweapon = wp_nochange; |
||
151 | player->psprites[ps_weapon].sy = WEAPONBOTTOM; |
||
152 | |||
153 | P_SetPsprite (player, ps_weapon, newstate); |
||
154 | } |
||
155 | |||
156 | // |
||
157 | // P_CheckAmmo |
||
158 | // Returns true if there is enough ammo to shoot. |
||
159 | // If not, selects the next weapon to use. |
||
160 | // |
||
161 | boolean P_CheckAmmo (player_t* player) |
||
162 | { |
||
163 | ammotype_t ammo; |
||
164 | int count; |
||
165 | |||
166 | ammo = weaponinfo[player->readyweapon].ammo; |
||
167 | |||
168 | // Minimal amount for one shot varies. |
||
169 | if (player->readyweapon == wp_bfg) |
||
170 | count = BFGCELLS; |
||
171 | else if (player->readyweapon == wp_supershotgun) |
||
172 | count = 2; // Double barrel. |
||
173 | else |
||
174 | count = 1; // Regular. |
||
175 | |||
176 | // Some do not need ammunition anyway. |
||
177 | // Return if current ammunition sufficient. |
||
178 | if (ammo == am_noammo || player->ammo[ammo] >= count) |
||
179 | return true; |
||
180 | |||
181 | // Out of ammo, pick a weapon to change to. |
||
182 | // Preferences are set here. |
||
183 | do |
||
184 | { |
||
185 | if (player->weaponowned[wp_plasma] |
||
186 | && player->ammo[am_cell] |
||
187 | && (gamemode != shareware) ) |
||
188 | { |
||
189 | player->pendingweapon = wp_plasma; |
||
190 | } |
||
191 | else if (player->weaponowned[wp_supershotgun] |
||
192 | && player->ammo[am_shell]>2 |
||
193 | && (gamemode == commercial) ) |
||
194 | { |
||
195 | player->pendingweapon = wp_supershotgun; |
||
196 | } |
||
197 | else if (player->weaponowned[wp_chaingun] |
||
198 | && player->ammo[am_clip]) |
||
199 | { |
||
200 | player->pendingweapon = wp_chaingun; |
||
201 | } |
||
202 | else if (player->weaponowned[wp_shotgun] |
||
203 | && player->ammo[am_shell]) |
||
204 | { |
||
205 | player->pendingweapon = wp_shotgun; |
||
206 | } |
||
207 | else if (player->ammo[am_clip]) |
||
208 | { |
||
209 | player->pendingweapon = wp_pistol; |
||
210 | } |
||
211 | else if (player->weaponowned[wp_chainsaw]) |
||
212 | { |
||
213 | player->pendingweapon = wp_chainsaw; |
||
214 | } |
||
215 | else if (player->weaponowned[wp_missile] |
||
216 | && player->ammo[am_misl]) |
||
217 | { |
||
218 | player->pendingweapon = wp_missile; |
||
219 | } |
||
220 | else if (player->weaponowned[wp_bfg] |
||
221 | && player->ammo[am_cell]>40 |
||
222 | && (gamemode != shareware) ) |
||
223 | { |
||
224 | player->pendingweapon = wp_bfg; |
||
225 | } |
||
226 | else |
||
227 | { |
||
228 | // If everything fails. |
||
229 | player->pendingweapon = wp_fist; |
||
230 | } |
||
231 | |||
232 | } while (player->pendingweapon == wp_nochange); |
||
233 | |||
234 | // Now set appropriate weapon overlay. |
||
235 | P_SetPsprite (player, |
||
236 | ps_weapon, |
||
237 | weaponinfo[player->readyweapon].downstate); |
||
238 | |||
239 | return false; |
||
240 | } |
||
241 | |||
242 | |||
243 | // |
||
244 | // P_FireWeapon. |
||
245 | // |
||
246 | void P_FireWeapon (player_t* player) |
||
247 | { |
||
248 | statenum_t newstate; |
||
249 | |||
250 | if (!P_CheckAmmo (player)) |
||
251 | return; |
||
252 | |||
253 | P_SetMobjState (player->mo, S_PLAY_ATK1); |
||
254 | newstate = weaponinfo[player->readyweapon].atkstate; |
||
255 | P_SetPsprite (player, ps_weapon, newstate); |
||
256 | P_NoiseAlert (player->mo, player->mo); |
||
257 | } |
||
258 | |||
259 | |||
260 | |||
261 | // |
||
262 | // P_DropWeapon |
||
263 | // Player died, so put the weapon away. |
||
264 | // |
||
265 | void P_DropWeapon (player_t* player) |
||
266 | { |
||
267 | P_SetPsprite (player, |
||
268 | ps_weapon, |
||
269 | weaponinfo[player->readyweapon].downstate); |
||
270 | } |
||
271 | |||
272 | |||
273 | |||
274 | // |
||
275 | // A_WeaponReady |
||
276 | // The player can fire the weapon |
||
277 | // or change to another weapon at this time. |
||
278 | // Follows after getting weapon up, |
||
279 | // or after previous attack/fire sequence. |
||
280 | // |
||
281 | void |
||
282 | A_WeaponReady |
||
283 | ( player_t* player, |
||
284 | pspdef_t* psp ) |
||
285 | { |
||
286 | statenum_t newstate; |
||
287 | int angle; |
||
288 | |||
289 | // get out of attack state |
||
290 | if (player->mo->state == &states[S_PLAY_ATK1] |
||
291 | || player->mo->state == &states[S_PLAY_ATK2] ) |
||
292 | { |
||
293 | P_SetMobjState (player->mo, S_PLAY); |
||
294 | } |
||
295 | |||
296 | if (player->readyweapon == wp_chainsaw |
||
297 | && psp->state == &states[S_SAW]) |
||
298 | { |
||
299 | S_StartSound (player->mo, sfx_sawidl); |
||
300 | } |
||
301 | |||
302 | // check for change |
||
303 | // if player is dead, put the weapon away |
||
304 | if (player->pendingweapon != wp_nochange || !player->health) |
||
305 | { |
||
306 | // change weapon |
||
307 | // (pending weapon should allready be validated) |
||
308 | newstate = weaponinfo[player->readyweapon].downstate; |
||
309 | P_SetPsprite (player, ps_weapon, newstate); |
||
310 | return; |
||
311 | } |
||
312 | |||
313 | // check for fire |
||
314 | // the missile launcher and bfg do not auto fire |
||
315 | if (player->cmd.buttons & BT_ATTACK) |
||
316 | { |
||
317 | if ( !player->attackdown |
||
318 | || (player->readyweapon != wp_missile |
||
319 | && player->readyweapon != wp_bfg) ) |
||
320 | { |
||
321 | player->attackdown = true; |
||
322 | P_FireWeapon (player); |
||
323 | return; |
||
324 | } |
||
325 | } |
||
326 | else |
||
327 | player->attackdown = false; |
||
328 | |||
329 | // bob the weapon based on movement speed |
||
330 | angle = (128*leveltime)&FINEMASK; |
||
331 | psp->sx = FRACUNIT + FixedMul (player->bob, finecosine[angle]); |
||
332 | angle &= FINEANGLES/2-1; |
||
333 | psp->sy = WEAPONTOP + FixedMul (player->bob, finesine[angle]); |
||
334 | } |
||
335 | |||
336 | |||
337 | |||
338 | // |
||
339 | // A_ReFire |
||
340 | // The player can re-fire the weapon |
||
341 | // without lowering it entirely. |
||
342 | // |
||
343 | void A_ReFire |
||
344 | ( player_t* player, |
||
345 | pspdef_t* psp ) |
||
346 | { |
||
347 | |||
348 | // check for fire |
||
349 | // (if a weaponchange is pending, let it go through instead) |
||
350 | if ( (player->cmd.buttons & BT_ATTACK) |
||
351 | && player->pendingweapon == wp_nochange |
||
352 | && player->health) |
||
353 | { |
||
354 | player->refire++; |
||
355 | P_FireWeapon (player); |
||
356 | } |
||
357 | else |
||
358 | { |
||
359 | player->refire = 0; |
||
360 | P_CheckAmmo (player); |
||
361 | } |
||
362 | } |
||
363 | |||
364 | |||
365 | void |
||
366 | A_CheckReload |
||
367 | ( player_t* player, |
||
368 | pspdef_t* psp ) |
||
369 | { |
||
370 | P_CheckAmmo (player); |
||
371 | #if 0 |
||
372 | if (player->ammo[am_shell]<2) |
||
373 | P_SetPsprite (player, ps_weapon, S_DSNR1); |
||
374 | #endif |
||
375 | } |
||
376 | |||
377 | |||
378 | |||
379 | // |
||
380 | // A_Lower |
||
381 | // Lowers current weapon, |
||
382 | // and changes weapon at bottom. |
||
383 | // |
||
384 | void |
||
385 | A_Lower |
||
386 | ( player_t* player, |
||
387 | pspdef_t* psp ) |
||
388 | { |
||
389 | psp->sy += LOWERSPEED; |
||
390 | |||
391 | // Is already down. |
||
392 | if (psp->sy < WEAPONBOTTOM ) |
||
393 | return; |
||
394 | |||
395 | // Player is dead. |
||
396 | if (player->playerstate == PST_DEAD) |
||
397 | { |
||
398 | psp->sy = WEAPONBOTTOM; |
||
399 | |||
400 | // don't bring weapon back up |
||
401 | return; |
||
402 | } |
||
403 | |||
404 | // The old weapon has been lowered off the screen, |
||
405 | // so change the weapon and start raising it |
||
406 | if (!player->health) |
||
407 | { |
||
408 | // Player is dead, so keep the weapon off screen. |
||
409 | P_SetPsprite (player, ps_weapon, S_NULL); |
||
410 | return; |
||
411 | } |
||
412 | |||
413 | player->readyweapon = player->pendingweapon; |
||
414 | |||
415 | P_BringUpWeapon (player); |
||
416 | } |
||
417 | |||
418 | |||
419 | // |
||
420 | // A_Raise |
||
421 | // |
||
422 | void |
||
423 | A_Raise |
||
424 | ( player_t* player, |
||
425 | pspdef_t* psp ) |
||
426 | { |
||
427 | statenum_t newstate; |
||
428 | |||
429 | psp->sy -= RAISESPEED; |
||
430 | |||
431 | if (psp->sy > WEAPONTOP ) |
||
432 | return; |
||
433 | |||
434 | psp->sy = WEAPONTOP; |
||
435 | |||
436 | // The weapon has been raised all the way, |
||
437 | // so change to the ready state. |
||
438 | newstate = weaponinfo[player->readyweapon].readystate; |
||
439 | |||
440 | P_SetPsprite (player, ps_weapon, newstate); |
||
441 | } |
||
442 | |||
443 | |||
444 | |||
445 | // |
||
446 | // A_GunFlash |
||
447 | // |
||
448 | void |
||
449 | A_GunFlash |
||
450 | ( player_t* player, |
||
451 | pspdef_t* psp ) |
||
452 | { |
||
453 | P_SetMobjState (player->mo, S_PLAY_ATK2); |
||
454 | P_SetPsprite (player,ps_flash,weaponinfo[player->readyweapon].flashstate); |
||
455 | } |
||
456 | |||
457 | |||
458 | |||
459 | // |
||
460 | // WEAPON ATTACKS |
||
461 | // |
||
462 | |||
463 | |||
464 | // |
||
465 | // A_Punch |
||
466 | // |
||
467 | void |
||
468 | A_Punch |
||
469 | ( player_t* player, |
||
470 | pspdef_t* psp ) |
||
471 | { |
||
472 | angle_t angle; |
||
473 | int damage; |
||
474 | int slope; |
||
475 | |||
476 | damage = (P_Random ()%10+1)<<1; |
||
477 | |||
478 | if (player->powers[pw_strength]) |
||
479 | damage *= 10; |
||
480 | |||
481 | angle = player->mo->angle; |
||
482 | angle += (P_Random()-P_Random())<<18; |
||
483 | slope = P_AimLineAttack (player->mo, angle, MELEERANGE); |
||
484 | P_LineAttack (player->mo, angle, MELEERANGE, slope, damage); |
||
485 | |||
486 | // turn to face target |
||
487 | if (linetarget) |
||
488 | { |
||
489 | S_StartSound (player->mo, sfx_punch); |
||
490 | player->mo->angle = R_PointToAngle2 (player->mo->x, |
||
491 | player->mo->y, |
||
492 | linetarget->x, |
||
493 | linetarget->y); |
||
494 | } |
||
495 | } |
||
496 | |||
497 | |||
498 | // |
||
499 | // A_Saw |
||
500 | // |
||
501 | void |
||
502 | A_Saw |
||
503 | ( player_t* player, |
||
504 | pspdef_t* psp ) |
||
505 | { |
||
506 | angle_t angle; |
||
507 | int damage; |
||
508 | int slope; |
||
509 | |||
510 | damage = 2*(P_Random ()%10+1); |
||
511 | angle = player->mo->angle; |
||
512 | angle += (P_Random()-P_Random())<<18; |
||
513 | |||
514 | // use meleerange + 1 se the puff doesn't skip the flash |
||
515 | slope = P_AimLineAttack (player->mo, angle, MELEERANGE+1); |
||
516 | P_LineAttack (player->mo, angle, MELEERANGE+1, slope, damage); |
||
517 | |||
518 | if (!linetarget) |
||
519 | { |
||
520 | S_StartSound (player->mo, sfx_sawful); |
||
521 | return; |
||
522 | } |
||
523 | S_StartSound (player->mo, sfx_sawhit); |
||
524 | |||
525 | // turn to face target |
||
526 | angle = R_PointToAngle2 (player->mo->x, player->mo->y, |
||
527 | linetarget->x, linetarget->y); |
||
528 | if (angle - player->mo->angle > ANG180) |
||
529 | { |
||
530 | if (angle - player->mo->angle < -ANG90/20) |
||
531 | player->mo->angle = angle + ANG90/21; |
||
532 | else |
||
533 | player->mo->angle -= ANG90/20; |
||
534 | } |
||
535 | else |
||
536 | { |
||
537 | if (angle - player->mo->angle > ANG90/20) |
||
538 | player->mo->angle = angle - ANG90/21; |
||
539 | else |
||
540 | player->mo->angle += ANG90/20; |
||
541 | } |
||
542 | player->mo->flags |= MF_JUSTATTACKED; |
||
543 | } |
||
544 | |||
545 | |||
546 | |||
547 | // |
||
548 | // A_FireMissile |
||
549 | // |
||
550 | void |
||
551 | A_FireMissile |
||
552 | ( player_t* player, |
||
553 | pspdef_t* psp ) |
||
554 | { |
||
555 | player->ammo[weaponinfo[player->readyweapon].ammo]--; |
||
556 | P_SpawnPlayerMissile (player->mo, MT_ROCKET); |
||
557 | } |
||
558 | |||
559 | |||
560 | // |
||
561 | // A_FireBFG |
||
562 | // |
||
563 | void |
||
564 | A_FireBFG |
||
565 | ( player_t* player, |
||
566 | pspdef_t* psp ) |
||
567 | { |
||
568 | player->ammo[weaponinfo[player->readyweapon].ammo] -= BFGCELLS; |
||
569 | P_SpawnPlayerMissile (player->mo, MT_BFG); |
||
570 | } |
||
571 | |||
572 | |||
573 | |||
574 | // |
||
575 | // A_FirePlasma |
||
576 | // |
||
577 | void |
||
578 | A_FirePlasma |
||
579 | ( player_t* player, |
||
580 | pspdef_t* psp ) |
||
581 | { |
||
582 | player->ammo[weaponinfo[player->readyweapon].ammo]--; |
||
583 | |||
584 | P_SetPsprite (player, |
||
585 | ps_flash, |
||
586 | weaponinfo[player->readyweapon].flashstate+(P_Random ()&1) ); |
||
587 | |||
588 | P_SpawnPlayerMissile (player->mo, MT_PLASMA); |
||
589 | } |
||
590 | |||
591 | |||
592 | |||
593 | // |
||
594 | // P_BulletSlope |
||
595 | // Sets a slope so a near miss is at aproximately |
||
596 | // the height of the intended target |
||
597 | // |
||
598 | fixed_t bulletslope; |
||
599 | |||
600 | |||
601 | void P_BulletSlope (mobj_t* mo) |
||
602 | { |
||
603 | angle_t an; |
||
604 | |||
605 | // see which target is to be aimed at |
||
606 | an = mo->angle; |
||
607 | bulletslope = P_AimLineAttack (mo, an, 16*64*FRACUNIT); |
||
608 | |||
609 | if (!linetarget) |
||
610 | { |
||
611 | an += 1<<26; |
||
612 | bulletslope = P_AimLineAttack (mo, an, 16*64*FRACUNIT); |
||
613 | if (!linetarget) |
||
614 | { |
||
615 | an -= 2<<26; |
||
616 | bulletslope = P_AimLineAttack (mo, an, 16*64*FRACUNIT); |
||
617 | } |
||
618 | } |
||
619 | } |
||
620 | |||
621 | |||
622 | // |
||
623 | // P_GunShot |
||
624 | // |
||
625 | void |
||
626 | P_GunShot |
||
627 | ( mobj_t* mo, |
||
628 | boolean accurate ) |
||
629 | { |
||
630 | angle_t angle; |
||
631 | int damage; |
||
632 | |||
633 | damage = 5*(P_Random ()%3+1); |
||
634 | angle = mo->angle; |
||
635 | |||
636 | if (!accurate) |
||
637 | angle += (P_Random()-P_Random())<<18; |
||
638 | |||
639 | P_LineAttack (mo, angle, MISSILERANGE, bulletslope, damage); |
||
640 | } |
||
641 | |||
642 | |||
643 | // |
||
644 | // A_FirePistol |
||
645 | // |
||
646 | void |
||
647 | A_FirePistol |
||
648 | ( player_t* player, |
||
649 | pspdef_t* psp ) |
||
650 | { |
||
651 | S_StartSound (player->mo, sfx_pistol); |
||
652 | |||
653 | P_SetMobjState (player->mo, S_PLAY_ATK2); |
||
654 | player->ammo[weaponinfo[player->readyweapon].ammo]--; |
||
655 | |||
656 | P_SetPsprite (player, |
||
657 | ps_flash, |
||
658 | weaponinfo[player->readyweapon].flashstate); |
||
659 | |||
660 | P_BulletSlope (player->mo); |
||
661 | P_GunShot (player->mo, !player->refire); |
||
662 | } |
||
663 | |||
664 | |||
665 | // |
||
666 | // A_FireShotgun |
||
667 | // |
||
668 | void |
||
669 | A_FireShotgun |
||
670 | ( player_t* player, |
||
671 | pspdef_t* psp ) |
||
672 | { |
||
673 | int i; |
||
674 | |||
675 | S_StartSound (player->mo, sfx_shotgn); |
||
676 | P_SetMobjState (player->mo, S_PLAY_ATK2); |
||
677 | |||
678 | player->ammo[weaponinfo[player->readyweapon].ammo]--; |
||
679 | |||
680 | P_SetPsprite (player, |
||
681 | ps_flash, |
||
682 | weaponinfo[player->readyweapon].flashstate); |
||
683 | |||
684 | P_BulletSlope (player->mo); |
||
685 | |||
686 | for (i=0 ; i<7 ; i++) |
||
687 | P_GunShot (player->mo, false); |
||
688 | } |
||
689 | |||
690 | |||
691 | |||
692 | // |
||
693 | // A_FireShotgun2 |
||
694 | // |
||
695 | void |
||
696 | A_FireShotgun2 |
||
697 | ( player_t* player, |
||
698 | pspdef_t* psp ) |
||
699 | { |
||
700 | int i; |
||
701 | angle_t angle; |
||
702 | int damage; |
||
703 | |||
704 | |||
705 | S_StartSound (player->mo, sfx_dshtgn); |
||
706 | P_SetMobjState (player->mo, S_PLAY_ATK2); |
||
707 | |||
708 | player->ammo[weaponinfo[player->readyweapon].ammo]-=2; |
||
709 | |||
710 | P_SetPsprite (player, |
||
711 | ps_flash, |
||
712 | weaponinfo[player->readyweapon].flashstate); |
||
713 | |||
714 | P_BulletSlope (player->mo); |
||
715 | |||
716 | for (i=0 ; i<20 ; i++) |
||
717 | { |
||
718 | damage = 5*(P_Random ()%3+1); |
||
719 | angle = player->mo->angle; |
||
720 | angle += (P_Random()-P_Random())<<19; |
||
721 | P_LineAttack (player->mo, |
||
722 | angle, |
||
723 | MISSILERANGE, |
||
724 | bulletslope + ((P_Random()-P_Random())<<5), damage); |
||
725 | } |
||
726 | } |
||
727 | |||
728 | |||
729 | // |
||
730 | // A_FireCGun |
||
731 | // |
||
732 | void |
||
733 | A_FireCGun |
||
734 | ( player_t* player, |
||
735 | pspdef_t* psp ) |
||
736 | { |
||
737 | S_StartSound (player->mo, sfx_pistol); |
||
738 | |||
739 | if (!player->ammo[weaponinfo[player->readyweapon].ammo]) |
||
740 | return; |
||
741 | |||
742 | P_SetMobjState (player->mo, S_PLAY_ATK2); |
||
743 | player->ammo[weaponinfo[player->readyweapon].ammo]--; |
||
744 | |||
745 | P_SetPsprite (player, |
||
746 | ps_flash, |
||
747 | weaponinfo[player->readyweapon].flashstate |
||
748 | + psp->state |
||
749 | - &states[S_CHAIN1] ); |
||
750 | |||
751 | P_BulletSlope (player->mo); |
||
752 | |||
753 | P_GunShot (player->mo, !player->refire); |
||
754 | } |
||
755 | |||
756 | |||
757 | |||
758 | // |
||
759 | // ? |
||
760 | // |
||
761 | void A_Light0 (player_t *player, pspdef_t *psp) |
||
762 | { |
||
763 | player->extralight = 0; |
||
764 | } |
||
765 | |||
766 | void A_Light1 (player_t *player, pspdef_t *psp) |
||
767 | { |
||
768 | player->extralight = 1; |
||
769 | } |
||
770 | |||
771 | void A_Light2 (player_t *player, pspdef_t *psp) |
||
772 | { |
||
773 | player->extralight = 2; |
||
774 | } |
||
775 | |||
776 | |||
777 | // |
||
778 | // A_BFGSpray |
||
779 | // Spawn a BFG explosion on every monster in view |
||
780 | // |
||
781 | void A_BFGSpray (mobj_t* mo) |
||
782 | { |
||
783 | int i; |
||
784 | int j; |
||
785 | int damage; |
||
786 | angle_t an; |
||
787 | |||
788 | // offset angles from its attack angle |
||
789 | for (i=0 ; i<40 ; i++) |
||
790 | { |
||
791 | an = mo->angle - ANG90/2 + ANG90/40*i; |
||
792 | |||
793 | // mo->target is the originator (player) |
||
794 | // of the missile |
||
795 | P_AimLineAttack (mo->target, an, 16*64*FRACUNIT); |
||
796 | |||
797 | if (!linetarget) |
||
798 | continue; |
||
799 | |||
800 | P_SpawnMobj (linetarget->x, |
||
801 | linetarget->y, |
||
802 | linetarget->z + (linetarget->height>>2), |
||
803 | MT_EXTRABFG); |
||
804 | |||
805 | damage = 0; |
||
806 | for (j=0;j<15;j++) |
||
807 | damage += (P_Random()&7) + 1; |
||
808 | |||
809 | P_DamageMobj (linetarget, mo->target,mo->target, damage); |
||
810 | } |
||
811 | } |
||
812 | |||
813 | |||
814 | // |
||
815 | // A_BFGsound |
||
816 | // |
||
817 | void |
||
818 | A_BFGsound |
||
819 | ( player_t* player, |
||
820 | pspdef_t* psp ) |
||
821 | { |
||
822 | S_StartSound (player->mo, sfx_bfg); |
||
823 | } |
||
824 | |||
825 | |||
826 | |||
827 | // |
||
828 | // P_SetupPsprites |
||
829 | // Called at start of level for each player. |
||
830 | // |
||
831 | void P_SetupPsprites (player_t* player) |
||
832 | { |
||
833 | int i; |
||
834 | |||
835 | // remove all psprites |
||
836 | for (i=0 ; i |
||
837 | player->psprites[i].state = NULL; |
||
838 | |||
839 | // spawn the gun |
||
840 | player->pendingweapon = player->readyweapon; |
||
841 | P_BringUpWeapon (player); |
||
842 | } |
||
843 | |||
844 | |||
845 | |||
846 | |||
847 | // |
||
848 | // P_MovePsprites |
||
849 | // Called every tic by player thinking routine. |
||
850 | // |
||
851 | void P_MovePsprites (player_t* player) |
||
852 | { |
||
853 | int i; |
||
854 | pspdef_t* psp; |
||
855 | state_t* state; |
||
856 | |||
857 | psp = &player->psprites[0]; |
||
858 | for (i=0 ; i |
||
859 | { |
||
860 | // a null state means not active |
||
861 | if ( (state = psp->state) ) |
||
862 | { |
||
863 | // drop tic count and possibly change state |
||
864 | |||
865 | // a -1 tic count never changes |
||
866 | if (psp->tics != -1) |
||
867 | { |
||
868 | psp->tics--; |
||
869 | if (!psp->tics) |
||
870 | P_SetPsprite (player, i, psp->state->nextstate); |
||
871 | } |
||
872 | } |
||
873 | } |
||
874 | |||
875 | player->psprites[ps_flash].sx = player->psprites[ps_weapon].sx; |
||
876 | player->psprites[ps_flash].sy = player->psprites[ps_weapon].sy; |
||
877 | }15;j++) |
||
878 | |||
879 |