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 #include <stdlib.h>
22
23 #include "doomdef.h"
24 #include "d_event.h"
25 #include "p_local.h"
26 #include "sounds.h" // villsa [STRIFE]
27 #include "p_dialog.h" // villsa [STRIFE]
28 #include "d_main.h" // villsa [STRIFE]
29 #include "doomstat.h"
30 #include "deh_str.h" // haleyjd [STRIFE]
31 #include "z_zone.h"
32 #include "w_wad.h"
33 #include "p_pspr.h"
34 #include "m_misc.h"
35 #include "m_random.h"
36 #include "s_sound.h"
37 #include "p_inter.h"
38
39
40
41 // Index of the special effects (INVUL inverse) map.
42 #define LOOKPITCHAMOUNT 6 // villsa [STRIFE]
43 #define CENTERVIEWAMOUNT (LOOKPITCHAMOUNT + 2) // villsa [STRIFE]
44 #define LOOKUPMAX 90 // villsa [STRIFE]
45 #define LOOKDOWNMAX -110 // villsa [STRIFE]
46
47
48 void P_DropInventoryItem(player_t* player, int sprite); // villsa [STRIFE]
49 boolean P_ItemBehavior(player_t* player, int item); // villsa [STRIFE]
50 static char useinventorymsg[44]; // villsa [STRIFE]
51
52 //
53 // Movement.
54 //
55
56 // 16 pixels of bob
57 #define MAXBOB 0x100000
58
59 boolean onground;
60
61
62 //
63 // P_Thrust
64 // Moves the given origin along a given angle.
65 //
66 // [STRIFE] Verified unmodified
67 //
68 void
P_Thrust(player_t * player,angle_t angle,fixed_t move)69 P_Thrust
70 ( player_t* player,
71 angle_t angle,
72 fixed_t move )
73 {
74 angle >>= ANGLETOFINESHIFT;
75
76 player->mo->momx += FixedMul(move,finecosine[angle]);
77 player->mo->momy += FixedMul(move,finesine[angle]);
78 }
79
80
81
82
83 //
84 // P_CalcHeight
85 // Calculate the walking / running height adjustment
86 //
87 // [STRIFE] Some odd adjustments, and terrain view height adjustment
88 //
P_CalcHeight(player_t * player)89 void P_CalcHeight (player_t* player)
90 {
91 int angle;
92 fixed_t bob;
93
94 // Regular movement bobbing
95 // (needs to be calculated for gun swing
96 // even if not on ground)
97 // OPTIMIZE: tablify angle
98 // Note: a LUT allows for effects
99 // like a ramp with low health.
100 player->bob =
101 FixedMul (player->mo->momx, player->mo->momx)
102 + FixedMul (player->mo->momy,player->mo->momy);
103
104 player->bob >>= 2;
105
106 if (player->bob>MAXBOB)
107 player->bob = MAXBOB;
108
109 // haleyjd 20110205 [STRIFE]: No CF_NOMOMENTUM check, and Rogue also removed
110 // the dead code inside.
111 if (!onground)
112 {
113 /*
114 player->viewz = player->mo->z + VIEWHEIGHT;
115
116 if (player->viewz > player->mo->ceilingz-4*FRACUNIT)
117 player->viewz = player->mo->ceilingz-4*FRACUNIT;
118 */
119
120 player->viewz = player->mo->z + player->viewheight;
121 return;
122 }
123
124 angle = (FINEANGLES/20*leveltime)&FINEMASK;
125 bob = FixedMul ( player->bob/2, finesine[angle]);
126
127 // move viewheight
128 if (player->playerstate == PST_LIVE)
129 {
130 player->viewheight += player->deltaviewheight;
131
132 if (player->viewheight > VIEWHEIGHT)
133 {
134 player->viewheight = VIEWHEIGHT;
135 player->deltaviewheight = 0;
136 }
137
138 if (player->viewheight < VIEWHEIGHT/2)
139 {
140 player->viewheight = VIEWHEIGHT/2;
141 if (player->deltaviewheight <= 0)
142 player->deltaviewheight = 1;
143 }
144
145 if (player->deltaviewheight)
146 {
147 player->deltaviewheight += FRACUNIT/4;
148 if (!player->deltaviewheight)
149 player->deltaviewheight = 1;
150 }
151 }
152 player->viewz = player->mo->z + player->viewheight + bob;
153
154 // villsa [STRIFE] account for terrain lowering the view
155 if(player->mo->flags & MF_FEETCLIPPED)
156 player->viewz -= 13*FRACUNIT;
157
158 if (player->viewz > player->mo->ceilingz-4*FRACUNIT)
159 player->viewz = player->mo->ceilingz-4*FRACUNIT;
160
161 // haleyjd [STRIFE]: added a floorz clip here
162 if (player->viewz < player->mo->floorz)
163 player->viewz = player->mo->floorz;
164 }
165
166
167
168 //
169 // P_MovePlayer
170 //
171 // [STRIFE] Adjustments to allow air control, jumping, and up/down look.
172 //
P_MovePlayer(player_t * player)173 void P_MovePlayer (player_t* player)
174 {
175 ticcmd_t* cmd;
176
177 cmd = &player->cmd;
178
179 player->mo->angle += (cmd->angleturn<<16);
180
181 // Do not let the player control movement
182 // if not onground.
183 onground = (player->mo->z <= player->mo->floorz);
184
185 // villsa [STRIFE] allows player to climb over things by jumping
186 // haleyjd 20110205: air control thrust should be 256, not cmd->forwardmove
187 if(!onground)
188 {
189 if(cmd->forwardmove)
190 P_Thrust (player, player->mo->angle, 256);
191 }
192 else
193 {
194 // villsa [STRIFE] jump button
195 if (cmd->buttons2 & BT2_JUMP)
196 {
197 if(!player->deltaviewheight)
198 player->mo->momz += 8*FRACUNIT;
199 }
200
201 // haleyjd 20110205 [STRIFE] Either Rogue or Watcom removed the
202 // redundant "onground" checks from these if's.
203 if (cmd->forwardmove)
204 P_Thrust (player, player->mo->angle, cmd->forwardmove*2048);
205
206 if (cmd->sidemove)
207 P_Thrust (player, player->mo->angle-ANG90, cmd->sidemove*2048);
208 }
209
210 // villsa [STRIFE] player walking state set
211 if ( (cmd->forwardmove || cmd->sidemove)
212 && player->mo->state == &states[S_PLAY_00] )
213 {
214 P_SetMobjState (player->mo, S_PLAY_01);
215 }
216
217 // villsa [STRIFE] centerview button
218 if (cmd->buttons2 & BT2_CENTERVIEW)
219 player->centerview = 1;
220
221 // villsa [STRIFE] adjust player's pitch when centerviewing
222 if (player->centerview)
223 {
224 if (player->pitch <= 0)
225 {
226 if (player->pitch < 0)
227 player->pitch = player->pitch + CENTERVIEWAMOUNT;
228 }
229 else
230 {
231 player->pitch = player->pitch - CENTERVIEWAMOUNT;
232 }
233 if (abs(player->pitch) < CENTERVIEWAMOUNT)
234 {
235 player->pitch = 0;
236 player->centerview = 0;
237 }
238 }
239
240 // villsa [STRIFE] look up action
241 if (cmd->buttons2 & BT2_LOOKUP)
242 {
243 player->pitch += LOOKPITCHAMOUNT;
244 if (player->pitch > LOOKUPMAX ||
245 player->pitch < LOOKDOWNMAX)
246 player->pitch -= LOOKPITCHAMOUNT;
247 }
248 else
249 {
250 // villsa [STRIFE] look down action
251 if (cmd->buttons2 & BT2_LOOKDOWN)
252 {
253 player->pitch -= LOOKPITCHAMOUNT;
254 if (player->pitch > LOOKUPMAX ||
255 player->pitch < LOOKDOWNMAX)
256 player->pitch += LOOKPITCHAMOUNT;
257 }
258 }
259
260 }
261
262
263
264 //
265 // P_DeathThink
266 // Fall on your face when dying.
267 // Decrease POV height to floor height.
268 //
269 // [STRIFE] Modifications for up/down look.
270 //
271 #define ANG5 (ANG90/18)
272
P_DeathThink(player_t * player)273 void P_DeathThink(player_t* player)
274 {
275 angle_t angle;
276 angle_t delta;
277
278 P_MovePsprites(player);
279
280 // fall to the ground
281 if (player->viewheight > 6*FRACUNIT)
282 player->viewheight -= FRACUNIT;
283
284 if (player->viewheight < 6*FRACUNIT)
285 player->viewheight = 6*FRACUNIT;
286
287 player->deltaviewheight = 0;
288 onground = (player->mo->z <= player->mo->floorz);
289 P_CalcHeight(player);
290
291 if(player->attacker && player->attacker != player->mo)
292 {
293 angle = R_PointToAngle2 (player->mo->x,
294 player->mo->y,
295 player->attacker->x,
296 player->attacker->y);
297
298 delta = angle - player->mo->angle;
299
300 if (delta < ANG5 || delta > (unsigned)-ANG5)
301 {
302 // Looking at killer,
303 // so fade damage flash down.
304 player->mo->angle = angle;
305
306 if (player->damagecount)
307 player->damagecount--;
308 }
309 else if (delta < ANG180)
310 player->mo->angle += ANG5;
311 else
312 player->mo->angle -= ANG5;
313 }
314 else if (player->damagecount)
315 player->damagecount--;
316
317 // villsa [STRIFE]
318 if(player->pitch <= 90)
319 player->pitch = player->pitch + 3;
320
321 if(player->cmd.buttons & BT_USE)
322 player->playerstate = PST_REBORN;
323 }
324
325
326
327 //
328 // P_PlayerThink
329 //
330 // [STRIFE] Massive changes/additions:
331 // * NOCLIP hack removed
332 // * P_DeathThink moved up
333 // * Inventory use/dropping
334 // * Strife weapons logic
335 // * Dialog
336 // * Strife powerups and nukage behavior
337 // * Fire Death/Sigil Shock
338 //
P_PlayerThink(player_t * player)339 void P_PlayerThink (player_t* player)
340 {
341 ticcmd_t* cmd;
342 weapontype_t newweapon;
343
344 // villsa [STRIFE] unused code (see ST_Responder)
345 /*
346 // fixme: do this in the cheat code
347 if (player->cheats & CF_NOCLIP)
348 player->mo->flags |= MF_NOCLIP;
349 else
350 player->mo->flags &= ~MF_NOCLIP;
351 */
352
353 // haleyjd 20110205 [STRIFE]: P_DeathThink moved up
354 if (player->playerstate == PST_DEAD)
355 {
356 P_DeathThink (player);
357 return;
358 }
359
360 // chain saw run forward
361 cmd = &player->cmd;
362 if (player->mo->flags & MF_JUSTATTACKED)
363 {
364 cmd->angleturn = 0;
365 cmd->forwardmove = 0xc800/512;
366 cmd->sidemove = 0;
367 player->mo->flags &= ~MF_JUSTATTACKED;
368 }
369
370 // Move around.
371 // Reactiontime is used to prevent movement
372 // for a bit after a teleport.
373 if (player->mo->reactiontime)
374 player->mo->reactiontime--;
375 else
376 P_MovePlayer (player);
377
378 P_CalcHeight (player);
379
380 if (player->mo->subsector->sector->special)
381 P_PlayerInSpecialSector (player);
382
383 // villsa [STRIFE] handle inventory input
384 if(cmd->buttons2 & (BT2_HEALTH|BT2_INVUSE|BT2_INVDROP))
385 {
386 if(!player->inventorydown)
387 {
388 if(cmd->buttons2 & BT2_HEALTH)
389 P_UseInventoryItem(player, SPR_FULL);
390 else if(cmd->buttons2 & BT2_INVUSE)
391 P_UseInventoryItem(player, cmd->inventory);
392 else if(cmd->buttons2 & BT2_INVDROP)
393 {
394 P_DropInventoryItem(player, cmd->inventory);
395
396 // haleyjd 20110205: removed incorrect "else" here
397 // villsa [STRIFE]
398 if(workparm)
399 {
400 int cheat = player->cheats ^ 1;
401 player->cheats ^= CF_NOCLIP;
402
403 if(cheat & CF_NOCLIP)
404 {
405 player->message = DEH_String("No Clipping Mode ON");
406 player->mo->flags |= MF_NOCLIP;
407 }
408 else
409 {
410 player->mo->flags &= ~MF_NOCLIP;
411 player->message = DEH_String("No Clipping Mode OFF");
412 }
413 }
414 }
415 }
416
417 player->inventorydown = true;
418 }
419 else
420 player->inventorydown = false;
421
422 // Check for weapon change.
423
424 // A special event has no other buttons.
425 if(cmd->buttons & BT_SPECIAL)
426 cmd->buttons = 0;
427
428 if(cmd->buttons & BT_CHANGE)
429 {
430 // The actual changing of the weapon is done
431 // when the weapon psprite can do it
432 // (read: not in the middle of an attack).
433 newweapon = (cmd->buttons & BT_WEAPONMASK) >> BT_WEAPONSHIFT;
434
435 // villsa [STRIFE] select poison bow
436 if(newweapon == wp_elecbow)
437 {
438 if(player->weaponowned[wp_poisonbow] && player->readyweapon == wp_elecbow)
439 {
440 if(player->ammo[weaponinfo[wp_poisonbow].ammo])
441 newweapon = wp_poisonbow;
442 }
443 }
444
445 // villsa [STRIFE] select wp grenade launcher
446 if(newweapon == wp_hegrenade)
447 {
448 if(player->weaponowned[wp_wpgrenade] && player->readyweapon == wp_hegrenade)
449 {
450 if(player->ammo[weaponinfo[wp_wpgrenade].ammo])
451 newweapon = wp_wpgrenade;
452 }
453 }
454
455 // villsa [STRIFE] select torpedo
456 if(newweapon == wp_mauler)
457 {
458 if(player->weaponowned[wp_torpedo] && player->readyweapon == wp_mauler)
459 {
460 // haleyjd 20140924: bug fix - using wrong enum value am_cell
461 // caused this to check the missile launcher for rocket ammo
462 if(player->ammo[weaponinfo[wp_torpedo].ammo] >= 30)
463 newweapon = wp_torpedo;
464 }
465 }
466
467 if(player->weaponowned[newweapon] && newweapon != player->readyweapon)
468 {
469 // villsa [STRIFE] check weapon if in demo mode or not
470 if(weaponinfo[newweapon].availabledemo || !isdemoversion)
471 {
472 if(player->ammo[weaponinfo[newweapon].ammo])
473 player->pendingweapon = newweapon;
474 else
475 {
476 // decide between electric bow or poison arrow
477 if(newweapon == wp_elecbow &&
478 player->ammo[am_poisonbolts] &&
479 player->readyweapon != wp_poisonbow)
480 {
481 player->pendingweapon = wp_poisonbow;
482 }
483 // decide between hp grenade launcher or wp grenade launcher
484 else if(newweapon == wp_hegrenade &&
485 player->ammo[am_wpgrenades] &&
486 player->readyweapon != wp_wpgrenade)
487 {
488 player->pendingweapon = wp_wpgrenade;
489 }
490
491 // villsa [STRIFE] - no check for mauler/torpedo??
492 }
493 }
494 }
495 }
496
497 // check for use
498 if(cmd->buttons & BT_USE)
499 {
500 if(!player->usedown)
501 {
502 P_DialogStart(player); // villsa [STRIFE]
503 P_UseLines (player);
504 player->usedown = true;
505 }
506 }
507 else
508 player->usedown = false;
509
510 // cycle psprites
511 P_MovePsprites (player);
512
513 // Counters, time dependend power ups.
514
515 // Strength counts up to diminish fade.
516 if (player->powers[pw_strength])
517 player->powers[pw_strength]++;
518
519 // villsa [STRIFE] targeter powerup
520 if(player->powers[pw_targeter])
521 {
522 player->powers[pw_targeter]--;
523 if(player->powers[pw_targeter] == 1)
524 {
525 P_SetPsprite(player, ps_targcenter, S_NULL);
526 P_SetPsprite(player, ps_targleft, S_NULL);
527 P_SetPsprite(player, ps_targright, S_NULL);
528 }
529 else if(player->powers[pw_targeter] - 1 < 5*TICRATE)
530 {
531 if(player->powers[pw_targeter] & 32)
532 {
533 P_SetPsprite(player, ps_targright, S_NULL);
534 P_SetPsprite(player, ps_targleft, S_TRGT_01); // 11
535 }
536 else if(player->powers[pw_targeter] & 16) // haleyjd 20110205: missing else
537 {
538 P_SetPsprite(player, ps_targright, S_TRGT_02); // 12
539 P_SetPsprite(player, ps_targleft, S_NULL);
540 }
541 }
542 }
543
544 if(player->powers[pw_invisibility])
545 {
546 // villsa [STRIFE] remove mvis flag as well
547 if(!--player->powers[pw_invisibility])
548 player->mo->flags &= ~(MF_SHADOW|MF_MVIS);
549 }
550
551 if(player->powers[pw_ironfeet])
552 {
553 player->powers[pw_ironfeet]--;
554
555 // villsa [STRIFE] gasmask sound
556 if(!(leveltime & 0x3f))
557 S_StartSound(player->mo, sfx_mask);
558 }
559
560 if(player->powers[pw_allmap] > 1)
561 player->powers[pw_allmap]--;
562
563 // haleyjd 08/30/10: [STRIFE]
564 // Nukage count keeps track of exposure to hazardous conditions over time.
565 // After accumulating 16 total seconds or more of exposure, you will take
566 // 5 damage roughly once per second until the count drops back under 560
567 // tics.
568 if(player->nukagecount)
569 {
570 player->nukagecount--;
571 if(!(leveltime & 0x1f) && player->nukagecount > 16*TICRATE)
572 P_DamageMobj(player->mo, NULL, NULL, 5);
573 }
574
575 if(player->damagecount)
576 player->damagecount--;
577
578 if(player->bonuscount)
579 player->bonuscount--;
580
581 // villsa [STRIFE] checks for extralight
582 if(player->extralight >= 0)
583 {
584 if(player->cheats & CF_ONFIRE)
585 player->fixedcolormap = 1;
586 else
587 player->fixedcolormap = 0;
588 }
589 else // Sigil shock:
590 player->fixedcolormap = INVERSECOLORMAP;
591 }
592
593
594 //
595 // P_RemoveInventoryItem
596 // villsa [STRIFE] new function
597 //
P_RemoveInventoryItem(player_t * player,int slot,int amount)598 const char* P_RemoveInventoryItem(player_t *player, int slot, int amount)
599 {
600 mobjtype_t type;
601
602 player->inventory[slot].amount -= amount;
603 player->st_update = true;
604
605 type = player->inventory[slot].type;
606
607 if(!player->inventory[slot].amount)
608 {
609 // shift everything above it down
610 // see P_TakeDialogItem for notes on possible bugs
611 int j;
612
613 for(j = slot + 1; j <= player->numinventory; j++)
614 {
615 inventory_t *item1 = &(player->inventory[j - 1]);
616 inventory_t *item2 = &(player->inventory[j]);
617
618 *item1 = *item2;
619 }
620
621 player->inventory[player->numinventory].type = NUMMOBJTYPES;
622 player->inventory[player->numinventory].sprite = -1;
623 player->numinventory--;
624
625 // update cursor position
626 if(player->inventorycursor >= player->numinventory)
627 {
628 if(player->inventorycursor)
629 player->inventorycursor--;
630 }
631 }
632
633 return mobjinfo[type].name;
634 }
635
636 //
637 // P_DropInventoryItem
638 // villsa [STRIFE] new function
639 //
P_DropInventoryItem(player_t * player,int sprite)640 void P_DropInventoryItem(player_t* player, int sprite)
641 {
642 int invslot;
643 inventory_t *item;
644 mobjtype_t type;
645 int amount;
646
647 invslot = 0;
648 amount = 1;
649
650 while(invslot < player->numinventory && sprite != player->inventory[invslot].sprite)
651 invslot++;
652
653 item = &(player->inventory[invslot]);
654 type = item->type;
655
656 if(item->amount)
657 {
658 angle_t angle;
659 fixed_t dist;
660 mobj_t* mo;
661 mobj_t* mobjitem;
662 fixed_t x;
663 fixed_t y;
664 fixed_t z;
665 int r;
666
667 if(item->type == MT_MONY_1)
668 {
669 if(item->amount >= 50)
670 {
671 type = MT_MONY_50;
672 amount = 50;
673 }
674 else if(item->amount >= 25)
675 {
676 type = MT_MONY_25;
677 amount = 25;
678 }
679 else if(item->amount >= 10)
680 {
681 type = MT_MONY_10;
682 amount = 10;
683 }
684 }
685
686 if(type >= NUMMOBJTYPES)
687 return;
688
689 angle = player->mo->angle;
690 r = P_Random();
691 angle = (angle + ((r - P_Random()) << 18)) >> ANGLETOFINESHIFT;
692
693 if(angle < 7618 && angle >= 6718)
694 angle = 7618;
695
696 else if(angle < 5570 && angle >= 4670)
697 angle = 5570;
698
699 else if(angle < 3522 && angle >= 2622)
700 angle = 3522;
701
702 else if(angle < 1474 && angle >= 574)
703 angle = 1474;
704
705 mo = player->mo;
706 dist = mobjinfo[type].radius + mo->info->radius + (4*FRACUNIT);
707
708 x = mo->x + FixedMul(finecosine[angle], dist);
709 y = mo->y + FixedMul(finesine[angle], dist);
710 z = mo->z + (10*FRACUNIT);
711 mobjitem = P_SpawnMobj(x, y, z, type);
712 mobjitem->flags |= (MF_SPECIAL|MF_DROPPED);
713
714 if(P_CheckPosition(mobjitem, x, y))
715 {
716 mobjitem->angle = (angle << ANGLETOFINESHIFT);
717 mobjitem->momx = FixedMul(finecosine[angle], (5*FRACUNIT)) + mo->momx;
718 mobjitem->momy = FixedMul(finesine[angle], (5*FRACUNIT)) + mo->momy;
719 mobjitem->momz = FRACUNIT;
720
721 P_RemoveInventoryItem(player, invslot, amount);
722 }
723 else
724 P_RemoveMobj(mobjitem);
725 }
726 }
727
728 //
729 // P_TossDegninOre
730 // villsa [STRIFE] new function
731 //
P_TossDegninOre(player_t * player)732 boolean P_TossDegninOre(player_t* player)
733 {
734 angle_t angle;
735 mobj_t* mo;
736 mobj_t* ore;
737 fixed_t x;
738 fixed_t y;
739 fixed_t z;
740 fixed_t dist;
741
742 angle = player->mo->angle >> ANGLETOFINESHIFT;
743
744 if(angle < 7618 && angle >= 6718)
745 angle = 7618;
746
747 else if(angle < 5570 && angle >= 4670)
748 angle = 5570;
749
750 else if(angle < 3522 && angle >= 2622)
751 angle = 3522;
752
753 else if(angle < 1474 && angle >= 574)
754 angle = 1474;
755
756 mo = player->mo;
757 dist = mobjinfo[MT_DEGNINORE].radius + mo->info->radius + (4*FRACUNIT);
758
759 x = mo->x + FixedMul(finecosine[angle], dist);
760 y = mo->y + FixedMul(finesine[angle], dist);
761 z = mo->z + (10*FRACUNIT);
762 ore = P_SpawnMobj(x, y, z, MT_DEGNINORE);
763
764 if(P_CheckPosition(ore, x, y))
765 {
766 ore->target = mo;
767 ore->angle = (angle << ANGLETOFINESHIFT);
768 ore->momx = FixedMul(finecosine[angle], (5*FRACUNIT));
769 ore->momy = FixedMul(finesine[angle], (5*FRACUNIT));
770 ore->momz = FRACUNIT;
771 return true;
772 }
773 else
774 P_RemoveMobj(ore);
775
776 return false;
777 }
778
779 //
780 // P_SpawnTeleportBeacon
781 //
782 // villsa [STRIFE] new function
783 // haleyjd 20140918: bug fixed to propagate allegiance properly.
784 //
P_SpawnTeleportBeacon(player_t * player)785 boolean P_SpawnTeleportBeacon(player_t* player)
786 {
787 angle_t angle;
788 int r;
789 mobj_t* mo;
790 mobj_t* beacon;
791 fixed_t x;
792 fixed_t y;
793 fixed_t z;
794 fixed_t dist;
795
796 angle = player->mo->angle;
797 r = P_Random();
798 angle = (angle + ((r - P_Random()) << 18)) >> ANGLETOFINESHIFT;
799
800 if(angle < 7618 && angle >= 6718)
801 angle = 7618;
802
803 else if(angle < 5570 && angle >= 4670)
804 angle = 5570;
805
806 else if(angle < 3522 && angle >= 2622)
807 angle = 3522;
808
809 else if(angle < 1474 && angle >= 574)
810 angle = 1474;
811
812 mo = player->mo;
813 dist = mobjinfo[MT_BEACON].radius + mo->info->radius + (4*FRACUNIT);
814
815 x = mo->x + FixedMul(finecosine[angle], dist);
816 y = mo->y + FixedMul(finesine[angle], dist);
817 z = mo->z + (10*FRACUNIT);
818 beacon = P_SpawnMobj(x, y, z, MT_BEACON);
819
820 if(P_CheckPosition(beacon, x, y))
821 {
822 beacon->target = mo;
823 beacon->miscdata = (byte)(player->allegiance);
824 beacon->angle = (angle << ANGLETOFINESHIFT);
825 beacon->momx = FixedMul(finecosine[angle], (5*FRACUNIT));
826 beacon->momy = FixedMul(finesine[angle], (5*FRACUNIT));
827 beacon->momz = FRACUNIT;
828 P_SetMobjState(beacon, beacon->info->seestate);
829 return true;
830 }
831 else
832 P_RemoveMobj(beacon);
833
834 return false;
835 }
836
837 //
838 // P_UseInventoryItem
839 // villsa [STRIFE] new function
840 //
P_UseInventoryItem(player_t * player,int item)841 boolean P_UseInventoryItem(player_t* player, int item)
842 {
843 int i;
844 const char *name;
845
846 if(player->cheats & CF_ONFIRE)
847 return false;
848
849 for(i = 0; i < player->numinventory; i++)
850 {
851 if(item != player->inventory[i].sprite)
852 continue;
853
854 if(!P_ItemBehavior(player, item))
855 return false;
856
857 name = P_RemoveInventoryItem(player, i, 1);
858 if(name == NULL)
859 name = "Item";
860
861 M_snprintf(useinventorymsg, sizeof(useinventorymsg),
862 "You used the %s.", name);
863 player->message = useinventorymsg;
864
865 if(player == &players[consoleplayer])
866 S_StartSound(NULL, sfx_itemup);
867
868 return true;
869 }
870
871 return false;
872 }
873
874 //
875 // P_ItemBehavior
876 // villsa [STRIFE] new function
877 //
P_ItemBehavior(player_t * player,int item)878 boolean P_ItemBehavior(player_t* player, int item)
879 {
880 switch(item)
881 {
882 case SPR_ARM1: // 136
883 return P_GiveArmor(player, 2);
884
885 case SPR_ARM2: // 137
886 return P_GiveArmor(player, 1);
887
888 case SPR_SHD1: // 186
889 return P_GivePower(player, pw_invisibility);
890
891 case SPR_MASK: // 187
892 return P_GivePower(player, pw_ironfeet);
893
894 case SPR_PMUP: // 191
895 if(!player->powers[pw_allmap])
896 {
897 player->message = "The scanner won't work without a map!";
898 return false;
899 }
900 player->powers[pw_allmap] = PMUPTICS;
901 return true; // haleyjd 20110228: repaired
902
903 case SPR_STMP: // 180
904 return P_GiveBody(player, 10);
905
906 case SPR_MDKT: // 181
907 return P_GiveBody(player, 25);
908
909 case SPR_FULL: // 130
910 return P_GiveBody(player, 200);
911
912 case SPR_BEAC: // 135
913 return P_SpawnTeleportBeacon(player);
914
915 case SPR_TARG: // 108
916 return P_GivePower(player, pw_targeter);
917 }
918
919 return false;
920 }
921