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