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 // Weapon sprite animation, weapon objects.
17 // Action functions for weapons.
18 //
19
20
21 #include "doomdef.h"
22 #include "d_event.h"
23
24 #include "deh_misc.h"
25
26 #include "m_random.h"
27 #include "p_local.h"
28 #include "s_sound.h"
29
30 // State.
31 #include "doomstat.h"
32
33 // Data.
34 #include "sounds.h"
35
36 #include "p_pspr.h"
37
38 #define LOWERSPEED FRACUNIT*6
39 #define RAISESPEED FRACUNIT*6
40
41 #define WEAPONBOTTOM 128*FRACUNIT
42 #define WEAPONTOP 32*FRACUNIT
43
44
45
46 //
47 // P_SetPsprite
48 //
49 // [STRIFE]
50 // villsa: Removed psprite sx, sy modification via misc1/2
51 //
52 void
P_SetPsprite(player_t * player,int position,statenum_t stnum)53 P_SetPsprite
54 ( player_t* player,
55 int position,
56 statenum_t stnum )
57 {
58 pspdef_t* psp;
59 state_t* state;
60
61 psp = &player->psprites[position];
62
63 do
64 {
65 if (!stnum)
66 {
67 // object removed itself
68 psp->state = NULL;
69 break;
70 }
71
72 state = &states[stnum];
73 psp->state = state;
74 psp->tics = state->tics; // could be 0
75
76 // villsa [STRIFE] unused
77 /*if (state->misc1)
78 {
79 // coordinate set
80 psp->sx = state->misc1 << FRACBITS;
81 psp->sy = state->misc2 << FRACBITS;
82 }*/
83
84 // Call action routine.
85 // Modified handling.
86 if (state->action.acp2)
87 {
88 state->action.acp2(player, psp);
89 if (!psp->state)
90 break;
91 }
92
93 stnum = psp->state->nextstate;
94
95 } while (!psp->tics);
96 // an initial state of 0 could cycle through
97 }
98
99 // haleyjd 09/06/10: [STRIFE] Removed P_CalcSwing
100
101 //
102 // P_BringUpWeapon
103 // Starts bringing the pending weapon up
104 // from the bottom of the screen.
105 // Uses player
106 //
107 // villsa [STRIFE] Modifications for Strife weapons
108 //
P_BringUpWeapon(player_t * player)109 void P_BringUpWeapon (player_t* player)
110 {
111 statenum_t newstate;
112
113 if (player->pendingweapon == wp_nochange)
114 player->pendingweapon = player->readyweapon;
115
116 if (player->pendingweapon == wp_flame)
117 S_StartSound (player->mo, sfx_flidl); // villsa [STRIFE] flame sounds
118
119 newstate = weaponinfo[player->pendingweapon].upstate;
120
121 player->psprites[ps_weapon].sy = WEAPONBOTTOM;
122 P_SetPsprite (player, ps_weapon, newstate);
123
124 // villsa [STRIFE] set various flash states
125 if(player->pendingweapon == wp_elecbow)
126 P_SetPsprite(player, ps_flash, S_XBOW_10); // 31
127 else if(player->pendingweapon == wp_sigil && player->sigiltype)
128 P_SetPsprite(player, ps_flash, S_SIGH_00 + player->sigiltype); // 117
129 else
130 P_SetPsprite(player, ps_flash, S_NULL);
131
132 player->pendingweapon = wp_nochange;
133 }
134
135 //
136 // P_CheckAmmo
137 // Returns true if there is enough ammo to shoot.
138 // If not, selects the next weapon to use.
139 //
140 // villsa [STRIFE] Changes to handle Strife weapons
141 //
P_CheckAmmo(player_t * player)142 boolean P_CheckAmmo (player_t* player)
143 {
144 ammotype_t ammo;
145 int count;
146
147 ammo = weaponinfo[player->readyweapon].ammo;
148
149 // Minimal amount for one shot varies.
150 if (player->readyweapon == wp_torpedo)
151 count = 30;
152 else if (player->readyweapon == wp_mauler)
153 count = 20;
154 else
155 count = 1; // Regular.
156
157 // Some do not need ammunition anyway.
158 // Return if current ammunition sufficient.
159 if (ammo == am_noammo || player->ammo[ammo] >= count)
160 return true;
161
162 // Out of ammo, pick a weapon to change to.
163 // Preferences are set here.
164
165 // villsa [STRIFE] new weapon preferences
166 if (player->weaponowned[wp_mauler] && player->ammo[am_cell] >= 20)
167 player->pendingweapon = wp_mauler;
168
169 else if(player->weaponowned[wp_rifle] && player->ammo[am_bullets])
170 player->pendingweapon = wp_rifle;
171
172 else if (player->weaponowned[wp_elecbow] && player->ammo[am_elecbolts])
173 player->pendingweapon = wp_elecbow;
174
175 else if (player->weaponowned[wp_missile] && player->ammo[am_missiles])
176 player->pendingweapon = wp_missile;
177
178 else if (player->weaponowned[wp_flame] && player->ammo[am_cell])
179 player->pendingweapon = wp_flame;
180
181 else if (player->weaponowned[wp_hegrenade] && player->ammo[am_hegrenades])
182 player->pendingweapon = wp_hegrenade;
183
184 else if (player->weaponowned[wp_poisonbow] && player->ammo[am_poisonbolts])
185 player->pendingweapon = wp_poisonbow;
186
187 else if (player->weaponowned[wp_wpgrenade] && player->ammo[am_wpgrenades])
188 player->pendingweapon = wp_wpgrenade;
189
190 // BUG: This will *never* be selected for an automatic switch because the
191 // normal Mauler is higher priority and uses less ammo.
192 else if (player->weaponowned[wp_torpedo] && player->ammo[am_cell] >= 30)
193 player->pendingweapon = wp_torpedo;
194
195 else
196 player->pendingweapon = wp_fist;
197
198
199 // Now set appropriate weapon overlay.
200 P_SetPsprite(player, ps_weapon, weaponinfo[player->readyweapon].downstate);
201
202 return false;
203 }
204
205
206 //
207 // P_FireWeapon.
208 //
209 // villsa [STRIFE] Changes for player state and weapons
210 //
P_FireWeapon(player_t * player)211 void P_FireWeapon (player_t* player)
212 {
213 statenum_t newstate;
214
215 if (!P_CheckAmmo (player))
216 return;
217
218 P_SetMobjState (player->mo, S_PLAY_05); // 292
219 newstate = weaponinfo[player->readyweapon].atkstate;
220 P_SetPsprite (player, ps_weapon, newstate);
221
222 // villsa [STRIFE] exclude these weapons from causing noise
223 if(player->readyweapon > wp_elecbow && player->readyweapon != wp_poisonbow)
224 P_NoiseAlert (player->mo, player->mo);
225 }
226
227
228
229 //
230 // P_DropWeapon
231 // Player died, so put the weapon away.
232 //
P_DropWeapon(player_t * player)233 void P_DropWeapon (player_t* player)
234 {
235 P_SetPsprite (player,
236 ps_weapon,
237 weaponinfo[player->readyweapon].downstate);
238 }
239
240
241
242 //
243 // A_WeaponReady
244 // The player can fire the weapon
245 // or change to another weapon at this time.
246 // Follows after getting weapon up,
247 // or after previous attack/fire sequence.
248 //
A_WeaponReady(player_t * player,pspdef_t * psp)249 void A_WeaponReady( player_t* player, pspdef_t* psp)
250 {
251 statenum_t newstate;
252 int angle;
253
254 // get out of attack state
255 if (player->mo->state == &states[S_PLAY_05] || // 292
256 player->mo->state == &states[S_PLAY_06]) // 293
257 {
258 P_SetMobjState (player->mo, S_PLAY_00); // 287
259 }
260
261 // villsa [STRIFE] check for wp_flame instead of chainsaw
262 // haleyjd 09/06/10: fixed state (00 rather than 01)
263 if (player->readyweapon == wp_flame
264 && psp->state == &states[S_FLMT_00]) // 62
265 {
266 S_StartSound (player->mo, sfx_flidl);
267 }
268
269 // check for change
270 // if player is dead, put the weapon away
271 if (player->pendingweapon != wp_nochange || !player->health)
272 {
273 // change weapon
274 // (pending weapon should allready be validated)
275 newstate = weaponinfo[player->readyweapon].downstate;
276 P_SetPsprite (player, ps_weapon, newstate);
277 return;
278 }
279
280 // check for fire
281 // the missile launcher and torpedo do not auto fire
282 if (player->cmd.buttons & BT_ATTACK)
283 {
284 if ( !player->attackdown
285 || (player->readyweapon != wp_missile
286 && player->readyweapon != wp_torpedo)) // villsa [STRIFE] replace bfg with torpedo
287 {
288 player->attackdown = true;
289 P_FireWeapon (player);
290 return;
291 }
292 }
293 else
294 player->attackdown = false;
295
296 // bob the weapon based on movement speed
297 angle = (128*leveltime)&FINEMASK;
298 psp->sx = FRACUNIT + FixedMul (player->bob, finecosine[angle]);
299 angle &= FINEANGLES/2-1;
300 psp->sy = WEAPONTOP + FixedMul (player->bob, finesine[angle]);
301 }
302
303
304
305 //
306 // A_ReFire
307 // The player can re-fire the weapon
308 // without lowering it entirely.
309 //
A_ReFire(player_t * player,pspdef_t * psp)310 void A_ReFire
311 ( player_t* player,
312 pspdef_t* psp )
313 {
314
315 // check for fire
316 // (if a weaponchange is pending, let it go through instead)
317 if ( (player->cmd.buttons & BT_ATTACK)
318 && player->pendingweapon == wp_nochange
319 && player->health)
320 {
321 player->refire++;
322 P_FireWeapon (player);
323 }
324 else
325 {
326 player->refire = 0;
327 P_CheckAmmo (player);
328 }
329 }
330
331 //
332 // A_CheckReload
333 //
A_CheckReload(player_t * player,pspdef_t * psp)334 void A_CheckReload(player_t* player, pspdef_t* psp)
335 {
336 P_CheckAmmo(player);
337
338 // villsa [STRIFE] set animating sprite for crossbow
339 if(player->readyweapon == wp_elecbow)
340 P_SetPsprite(player, player->readyweapon, S_XBOW_10);
341 }
342
343
344
345 //
346 // A_Lower
347 // Lowers current weapon,
348 // and changes weapon at bottom.
349 //
350 void
A_Lower(player_t * player,pspdef_t * psp)351 A_Lower
352 ( player_t* player,
353 pspdef_t* psp )
354 {
355 psp->sy += LOWERSPEED;
356
357 // Is already down.
358 if (psp->sy < WEAPONBOTTOM )
359 return;
360
361 // Player is dead.
362 if (player->playerstate == PST_DEAD)
363 {
364 psp->sy = WEAPONBOTTOM;
365
366 // don't bring weapon back up
367 return;
368 }
369
370 // The old weapon has been lowered off the screen,
371 // so change the weapon and start raising it
372 if (!player->health)
373 {
374 // Player is dead, so keep the weapon off screen.
375 P_SetPsprite (player, ps_weapon, S_NULL);
376 return;
377 }
378
379 player->readyweapon = player->pendingweapon;
380
381 P_BringUpWeapon (player);
382 }
383
384
385 //
386 // A_Raise
387 //
388 void
A_Raise(player_t * player,pspdef_t * psp)389 A_Raise
390 ( player_t* player,
391 pspdef_t* psp )
392 {
393 statenum_t newstate;
394
395 psp->sy -= RAISESPEED;
396
397 if (psp->sy > WEAPONTOP )
398 return;
399
400 psp->sy = WEAPONTOP;
401
402 // The weapon has been raised all the way,
403 // so change to the ready state.
404 newstate = weaponinfo[player->readyweapon].readystate;
405
406 P_SetPsprite (player, ps_weapon, newstate);
407 }
408
409
410
411 //
412 // A_GunFlash
413 //
414 void
A_GunFlash(player_t * player,pspdef_t * psp)415 A_GunFlash
416 ( player_t* player,
417 pspdef_t* psp )
418 {
419 P_SetMobjState (player->mo, S_PLAY_06);
420 P_SetPsprite (player,ps_flash,weaponinfo[player->readyweapon].flashstate);
421 }
422
423
424
425 //
426 // WEAPON ATTACKS
427 //
428
429
430 //
431 // A_Punch
432 //
433
A_Punch(player_t * player,pspdef_t * psp)434 void A_Punch(player_t* player, pspdef_t* psp)
435 {
436 angle_t angle;
437 int damage;
438 int slope;
439 int sound;
440 int stamina;
441 int t;
442
443 // villsa [STRIFE] new damage formula
444 // haleyjd 09/19/10: seriously corrected...
445 stamina = player->stamina;
446 damage = (P_Random() & ((stamina/10) + 7)) * ((stamina/10) + 2);
447
448 if(player->powers[pw_strength])
449 damage *= 10;
450
451 angle = player->mo->angle;
452 t = P_Random();
453 angle += (t - P_Random()) << 18;
454 slope = P_AimLineAttack (player->mo, angle, PLAYERMELEERANGE);
455 P_LineAttack (player->mo, angle, PLAYERMELEERANGE, slope, damage);
456
457 // turn to face target
458 if(linetarget)
459 {
460 // villsa [STRIFE] check for non-flesh types
461 if(linetarget->flags & MF_NOBLOOD)
462 sound = sfx_mtalht;
463 else
464 sound = sfx_meatht;
465
466 S_StartSound (player->mo, sound);
467 player->mo->angle = R_PointToAngle2 (player->mo->x,
468 player->mo->y,
469 linetarget->x,
470 linetarget->y);
471
472 // villsa [STRIFE] apply flag
473 player->mo->flags |= MF_JUSTATTACKED;
474
475 // villsa [STRIFE] do punch alert routine
476 P_DoPunchAlert(player->mo, linetarget);
477 }
478 else
479 S_StartSound (player->mo, sfx_swish);
480 }
481
482
483 //
484 // A_FireFlameThrower
485 //
486 // villsa [STRIFE] new codepointer
487 //
A_FireFlameThrower(player_t * player,pspdef_t * psp)488 void A_FireFlameThrower(player_t* player, pspdef_t* psp)
489 {
490 mobj_t* mo;
491 int t;
492
493 P_SetMobjState(player->mo, S_PLAY_06);
494 player->ammo[weaponinfo[player->readyweapon].ammo]--;
495 t = P_Random();
496 player->mo->angle += (t - P_Random()) << 18;
497
498 mo = P_SpawnPlayerMissile(player->mo, MT_SFIREBALL);
499 mo->momz += (5*FRACUNIT);
500 }
501
502 //
503 // A_FireMissile
504 //
505 // villsa [STRIFE] completly new compared to the original
506 //
A_FireMissile(player_t * player,pspdef_t * psp)507 void A_FireMissile(player_t* player, pspdef_t* psp)
508 {
509 angle_t an;
510 int t;
511
512 // haleyjd 09/19/10: I previously missed an add op that meant it should be
513 // accuracy * 5, not 4. Checks out with other sources.
514 an = player->mo->angle;
515 t = P_Random();
516 player->mo->angle += (t - P_Random()) << (19 - (player->accuracy * 5 / 100));
517 P_SetMobjState(player->mo, S_PLAY_06);
518 player->ammo[weaponinfo[player->readyweapon].ammo]--;
519 P_SpawnPlayerMissile(player->mo, MT_MINIMISSLE);
520 player->mo->angle = an;
521 }
522
523 //
524 // A_FireMauler2
525 //
526 // villsa [STRIFE] - new codepointer
527 //
A_FireMauler2(player_t * player,pspdef_t * pspr)528 void A_FireMauler2(player_t* player, pspdef_t* pspr)
529 {
530 P_SetMobjState(player->mo, S_PLAY_06);
531 P_DamageMobj(player->mo, player->mo, NULL, 20);
532 player->ammo[weaponinfo[player->readyweapon].ammo] -= 30;
533 P_SpawnPlayerMissile(player->mo, MT_TORPEDO);
534 P_Thrust(player, player->mo->angle + ANG180, 512000);
535 }
536
537 //
538 // A_FireGrenade
539 //
540 // villsa [STRIFE] - new codepointer
541 //
A_FireGrenade(player_t * player,pspdef_t * pspr)542 void A_FireGrenade(player_t* player, pspdef_t* pspr)
543 {
544 mobjtype_t type;
545 mobj_t* mo;
546 state_t* st1;
547 state_t* st2;
548 angle_t an;
549 fixed_t radius;
550
551 // decide on what type of grenade to spawn
552 if(player->readyweapon == wp_hegrenade)
553 {
554 type = MT_HEGRENADE;
555 }
556 else if(player->readyweapon == wp_wpgrenade)
557 {
558 type = MT_PGRENADE;
559 }
560 else
561 {
562 type = MT_HEGRENADE;
563 fprintf(stderr, "Warning: A_FireGrenade used on wrong weapon!\n");
564 }
565
566 player->ammo[weaponinfo[player->readyweapon].ammo]--;
567
568 // set flash frame
569 st1 = &states[(pspr->state - states) + weaponinfo[player->readyweapon].flashstate];
570 st2 = &states[weaponinfo[player->readyweapon].atkstate];
571 P_SetPsprite(player, ps_flash, st1 - st2);
572
573 player->mo->z += 32*FRACUNIT; // ugh
574 mo = P_SpawnMortar(player->mo, type);
575 player->mo->z -= 32*FRACUNIT; // ugh
576
577 // change momz based on player's pitch
578 mo->momz = FixedMul((player->pitch<<FRACBITS) / 160, mo->info->speed) + (8*FRACUNIT);
579 S_StartSound(mo, mo->info->seesound);
580
581 radius = mobjinfo[type].radius + player->mo->info->radius;
582 an = (player->mo->angle >> ANGLETOFINESHIFT);
583
584 mo->x += FixedMul(finecosine[an], radius + (4*FRACUNIT));
585 mo->y += FixedMul(finesine[an], radius + (4*FRACUNIT));
586
587 // shoot grenade from left or right side?
588 if(&states[weaponinfo[player->readyweapon].atkstate] == pspr->state)
589 an = (player->mo->angle - ANG90) >> ANGLETOFINESHIFT;
590 else
591 an = (player->mo->angle + ANG90) >> ANGLETOFINESHIFT;
592
593 mo->x += FixedMul((15*FRACUNIT), finecosine[an]);
594 mo->y += FixedMul((15*FRACUNIT), finesine[an]);
595
596 // set bounce flag
597 mo->flags |= MF_BOUNCE;
598 }
599
600 //
601 // A_FireElectricBolt
602 // villsa [STRIFE] - new codepointer
603 //
604
A_FireElectricBolt(player_t * player,pspdef_t * pspr)605 void A_FireElectricBolt(player_t* player, pspdef_t* pspr)
606 {
607 angle_t an = player->mo->angle;
608 int t;
609
610 // haleyjd 09/19/10: Use 5 mul on accuracy here as well
611 t = P_Random();
612 player->mo->angle += (t - P_Random()) << (18 - (player->accuracy * 5 / 100));
613 player->ammo[weaponinfo[player->readyweapon].ammo]--;
614 P_SpawnPlayerMissile(player->mo, MT_ELECARROW);
615 player->mo->angle = an;
616 S_StartSound(player->mo, sfx_xbow);
617 }
618
619 //
620 // A_FirePoisonBolt
621 // villsa [STRIFE] - new codepointer
622 //
623
A_FirePoisonBolt(player_t * player,pspdef_t * pspr)624 void A_FirePoisonBolt(player_t* player, pspdef_t* pspr)
625 {
626 angle_t an = player->mo->angle;
627 int t;
628
629 // haleyjd 09/19/10: Use 5 mul on accuracy here as well
630 t = P_Random();
631 player->mo->angle += (t - P_Random()) << (18 - (player->accuracy * 5 / 100));
632 player->ammo[weaponinfo[player->readyweapon].ammo]--;
633 P_SpawnPlayerMissile(player->mo, MT_POISARROW);
634 player->mo->angle = an;
635 S_StartSound(player->mo, sfx_xbow);
636 }
637
638 //
639 // P_BulletSlope
640 // Sets a slope so a near miss is at aproximately
641 // the height of the intended target
642 //
643 // haleyjd 09/06/10 [STRIFE] Modified with a little target hack...
644 //
645 fixed_t bulletslope;
646
647
P_BulletSlope(mobj_t * mo)648 void P_BulletSlope (mobj_t *mo)
649 {
650 angle_t an;
651
652 // see which target is to be aimed at
653 an = mo->angle;
654 bulletslope = P_AimLineAttack (mo, an, 16*64*FRACUNIT);
655
656 if (!linetarget)
657 {
658 an += 1<<26;
659 bulletslope = P_AimLineAttack (mo, an, 16*64*FRACUNIT);
660 if (!linetarget)
661 {
662 an -= 2<<26;
663 bulletslope = P_AimLineAttack (mo, an, 16*64*FRACUNIT);
664 }
665 }
666
667 // haleyjd 09/06/10: [STRIFE] Somebody added this here, and without it, you
668 // will get spurious crashing in routines such as P_LookForPlayers!
669 if(linetarget)
670 mo->target = linetarget;
671 }
672
673
674 //
675 // P_GunShot
676 //
677 // [STRIFE] Modifications to support accuracy.
678 //
679 void
P_GunShot(mobj_t * mo,boolean accurate)680 P_GunShot
681 ( mobj_t* mo,
682 boolean accurate )
683 {
684 angle_t angle;
685 int damage;
686
687 angle = mo->angle;
688
689 // villsa [STRIFE] apply player accuracy
690 // haleyjd 09/18/10: made some corrections: use 5x accuracy;
691 // eliminated order-of-evaluation dependency
692 if (!accurate)
693 {
694 int t = P_Random();
695 angle += (t - P_Random()) << (20 - ((mo->player->accuracy * 5) / 100));
696 }
697
698 // haleyjd 09/18/10 [STRIFE] corrected damage formula and moved down to
699 // preserve proper P_Random call order.
700 damage = 4 * (P_Random() % 3 + 1);
701
702 P_LineAttack (mo, angle, MISSILERANGE, bulletslope, damage);
703 }
704
705 //
706 // A_FireRifle
707 //
708 // villsa [STRIFE] - new codepointer
709 //
A_FireRifle(player_t * player,pspdef_t * pspr)710 void A_FireRifle(player_t* player, pspdef_t* pspr)
711 {
712 S_StartSound(player->mo, sfx_rifle);
713
714 if(player->ammo[weaponinfo[player->readyweapon].ammo])
715 {
716 P_SetMobjState(player->mo, S_PLAY_06); // 293
717 player->ammo[weaponinfo[player->readyweapon].ammo]--;
718 P_BulletSlope(player->mo);
719 P_GunShot(player->mo, !player->refire);
720 }
721 }
722
723 //
724 // A_FireMauler1
725 //
726 // villsa [STRIFE] - new codepointer
727 //
A_FireMauler1(player_t * player,pspdef_t * pspr)728 void A_FireMauler1(player_t* player, pspdef_t* pspr)
729 {
730 int i;
731 angle_t angle;
732 int damage;
733
734 // haleyjd 09/18/10: Corrected ammo check to use >=
735 if(player->ammo[weaponinfo[player->readyweapon].ammo] >= 20)
736 {
737 player->ammo[weaponinfo[player->readyweapon].ammo] -= 20;
738 P_BulletSlope(player->mo);
739 S_StartSound(player->mo, sfx_pgrdat);
740
741 for(i = 0; i < 20; i++)
742 {
743 int t;
744 damage = 5*(P_Random ()%3+1);
745 angle = player->mo->angle;
746 t = P_Random();
747 angle += (t - P_Random()) << 19;
748 t = P_Random();
749 P_LineAttack(player->mo, angle, 2112*FRACUNIT,
750 bulletslope + ((t - P_Random())<<5), damage);
751 }
752 }
753 }
754
755 //
756 // A_SigilSound
757 //
758 // villsa [STRIFE] - new codepointer
759 //
A_SigilSound(player_t * player,pspdef_t * pspr)760 void A_SigilSound(player_t* player, pspdef_t* pspr)
761 {
762 S_StartSound(player->mo, sfx_siglup);
763 player->extralight = 2;
764
765 }
766
767 //
768 // A_FireSigil
769 //
770 // villsa [STRIFE] - new codepointer
771 //
A_FireSigil(player_t * player,pspdef_t * pspr)772 void A_FireSigil(player_t* player, pspdef_t* pspr)
773 {
774 mobj_t* mo;
775 angle_t an;
776 int i;
777
778 // keep info on armor because sigil does piercing damage
779 i = player->armortype;
780 player->armortype = 0;
781
782 // BUG: setting inflictor causes firing the Sigil to always push the player
783 // toward the east, no matter what direction he is facing.
784 P_DamageMobj(player->mo, player->mo, NULL, 4 * (player->sigiltype + 1));
785
786 // restore armor
787 player->armortype = i;
788
789 S_StartSound(player->mo, sfx_siglup);
790
791 switch(player->sigiltype)
792 {
793 // falling lightning bolts from the sky
794 case 0:
795 P_BulletSlope(player->mo);
796 if(linetarget)
797 {
798 // haleyjd 09/18/10: corrected z coordinate
799 mo = P_SpawnMobj(linetarget->x, linetarget->y, ONFLOORZ,
800 MT_SIGIL_A_GROUND);
801 mo->tracer = linetarget;
802 }
803 else
804 {
805 an = player->mo->angle>>ANGLETOFINESHIFT;
806 mo = P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z,
807 MT_SIGIL_A_GROUND);
808 mo->momx += FixedMul((28*FRACUNIT), finecosine[an]);
809 mo->momy += FixedMul((28*FRACUNIT), finesine[an]);
810 }
811 mo->health = -1;
812 mo->target = player->mo;
813 break;
814
815 // simple projectile
816 case 1:
817 P_SpawnPlayerMissile(player->mo, MT_SIGIL_B_SHOT)->health = -1;
818 break;
819
820 // spread shot
821 case 2:
822 player->mo->angle -= ANG90; // starting at 270...
823 for(i = 0; i < 20; i++) // increment by 1/10 of 90, 20 times.
824 {
825 player->mo->angle += (ANG90 / 10);
826 mo = P_SpawnMortar(player->mo, MT_SIGIL_C_SHOT);
827 mo->health = -1;
828 mo->z = player->mo->z + (32*FRACUNIT);
829 }
830 player->mo->angle -= ANG90; // subtract off the extra 90
831 break;
832
833 // tracer attack
834 case 3:
835 P_BulletSlope(player->mo);
836 if(linetarget)
837 {
838 mo = P_SpawnPlayerMissile(player->mo, MT_SIGIL_D_SHOT);
839 mo->tracer = linetarget;
840 }
841 else
842 {
843 an = player->mo->angle >> ANGLETOFINESHIFT;
844 mo = P_SpawnPlayerMissile(player->mo, MT_SIGIL_D_SHOT);
845 mo->momx += FixedMul(mo->info->speed, finecosine[an]);
846 mo->momy += FixedMul(mo->info->speed, finesine[an]);
847 }
848 mo->health = -1;
849 break;
850
851 // mega blast
852 case 4:
853 mo = P_SpawnPlayerMissile(player->mo, MT_SIGIL_E_SHOT);
854 mo->health = -1;
855 if(!linetarget)
856 {
857 an = (unsigned int)player->pitch >> ANGLETOFINESHIFT;
858 mo->momz += FixedMul(finesine[an], mo->info->speed);
859 }
860 break;
861
862 default:
863 break;
864 }
865 }
866
867 //
868 // A_GunFlashThinker
869 //
870 // villsa [STRIFE] - new codepointer
871 //
A_GunFlashThinker(player_t * player,pspdef_t * pspr)872 void A_GunFlashThinker(player_t* player, pspdef_t* pspr)
873 {
874 if(player->readyweapon == wp_sigil && player->sigiltype)
875 P_SetPsprite(player, ps_flash, S_SIGH_00 + player->sigiltype);
876 else
877 P_SetPsprite(player, ps_flash, S_NULL);
878
879 }
880
881
882 //
883 // ?
884 //
A_Light0(player_t * player,pspdef_t * psp)885 void A_Light0 (player_t *player, pspdef_t *psp)
886 {
887 player->extralight = 0;
888 }
889
A_Light1(player_t * player,pspdef_t * psp)890 void A_Light1 (player_t *player, pspdef_t *psp)
891 {
892 player->extralight = 1;
893 }
894
A_Light2(player_t * player,pspdef_t * psp)895 void A_Light2 (player_t *player, pspdef_t *psp)
896 {
897 player->extralight = 2;
898 }
899
900 //
901 // A_SigilShock
902 //
903 // villsa [STRIFE] - new codepointer
904 //
A_SigilShock(player_t * player,pspdef_t * psp)905 void A_SigilShock (player_t *player, pspdef_t *psp)
906 {
907 player->extralight = -3;
908 }
909
910 //
911 // A_TorpedoExplode
912 //
913 // villsa [STRIFE] - new codepointer
914 //
A_TorpedoExplode(mobj_t * actor)915 void A_TorpedoExplode(mobj_t* actor)
916 {
917 int i;
918
919 actor->angle -= ANG180;
920
921 for(i = 0; i < 80; i++)
922 {
923 actor->angle += (ANG90 / 20);
924 P_SpawnMortar(actor, MT_TORPEDOSPREAD)->target = actor->target;
925 }
926 }
927
928 //
929 // A_MaulerSound
930 //
931 // villsa [STRIFE] - new codepointer
932 //
A_MaulerSound(player_t * player,pspdef_t * psp)933 void A_MaulerSound(player_t *player, pspdef_t *psp)
934 {
935 int t;
936 S_StartSound(player->mo, sfx_proton);
937 t = P_Random();
938 psp->sx += (t - P_Random()) << 10;
939 t = P_Random();
940 psp->sy += (t - P_Random()) << 10;
941
942 }
943
944
945 //
946 // P_SetupPsprites
947 // Called at start of level for each player.
948 //
P_SetupPsprites(player_t * player)949 void P_SetupPsprites(player_t* player)
950 {
951 int i;
952
953 // remove all psprites
954 for(i = 0; i < NUMPSPRITES; i++)
955 player->psprites[i].state = NULL;
956
957 // spawn the gun
958 player->pendingweapon = player->readyweapon;
959 P_BringUpWeapon(player);
960 }
961
962
963
964
965 //
966 // P_MovePsprites
967 // Called every tic by player thinking routine.
968 //
P_MovePsprites(player_t * player)969 void P_MovePsprites (player_t* player)
970 {
971 int i;
972 pspdef_t* psp;
973 state_t* state;
974
975 psp = &player->psprites[0];
976 for(i = 0; i < NUMPSPRITES; i++, psp++)
977 {
978 // a null state means not active
979 if((state = psp->state))
980 {
981 // drop tic count and possibly change state
982
983 // a -1 tic count never changes
984 if(psp->tics != -1)
985 {
986 psp->tics--;
987 if(!psp->tics)
988 P_SetPsprite (player, i, psp->state->nextstate);
989 }
990 }
991 }
992
993 player->psprites[ps_flash].sx = player->psprites[ps_weapon].sx;
994 player->psprites[ps_flash].sy = player->psprites[ps_weapon].sy;
995
996 // villsa [STRIFE] extra stuff for targeter
997 player->psprites[ps_targleft].sx =
998 (160*FRACUNIT) - ((100 - player->accuracy) << FRACBITS);
999
1000 player->psprites[ps_targright].sx =
1001 ((100 - player->accuracy) << FRACBITS) + (160*FRACUNIT);
1002 }
1003
1004
1005