summaryrefslogtreecommitdiff
path: root/src/strife/p_user.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/strife/p_user.c')
-rw-r--r--src/strife/p_user.c923
1 files changed, 923 insertions, 0 deletions
diff --git a/src/strife/p_user.c b/src/strife/p_user.c
new file mode 100644
index 00000000..af03e81f
--- /dev/null
+++ b/src/strife/p_user.c
@@ -0,0 +1,923 @@
+// Emacs style mode select -*- C++ -*-
+//-----------------------------------------------------------------------------
+//
+// Copyright(C) 1993-1996 Id Software, Inc.
+// Copyright(C) 2005 Simon Howard
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+// 02111-1307, USA.
+//
+// DESCRIPTION:
+// Player related stuff.
+// Bobbing POV/weapon, movement.
+// Pending weapon.
+//
+//-----------------------------------------------------------------------------
+
+#include <stdlib.h>
+
+#include "doomdef.h"
+#include "d_event.h"
+#include "p_local.h"
+#include "sounds.h" // villsa [STRIFE]
+#include "p_dialog.h" // villsa [STRIFE]
+#include "d_main.h" // villsa [STRIFE]
+#include "doomstat.h"
+#include "deh_str.h" // haleyjd [STRIFE]
+#include "z_zone.h"
+#include "w_wad.h"
+#include "p_pspr.h"
+#include "m_random.h"
+#include "s_sound.h"
+#include "p_inter.h"
+
+
+
+// Index of the special effects (INVUL inverse) map.
+#define LOOKPITCHAMOUNT 6 // villsa [STRIFE]
+#define CENTERVIEWAMOUNT (LOOKPITCHAMOUNT + 2) // villsa [STRIFE]
+#define LOOKUPMAX 90 // villsa [STRIFE]
+#define LOOKDOWNMAX -110 // villsa [STRIFE]
+
+
+boolean P_UseInventoryItem(player_t* player, int item); // fraggle [STRIFE]
+void P_DropInventoryItem(player_t* player, int sprite); // villsa [STRIFE]
+boolean P_ItemBehavior(player_t* player, int item); // villsa [STRIFE]
+static char useinventorymsg[44]; // villsa [STRIFE]
+
+//
+// Movement.
+//
+
+// 16 pixels of bob
+#define MAXBOB 0x100000
+
+boolean onground;
+
+
+//
+// P_Thrust
+// Moves the given origin along a given angle.
+//
+// [STRIFE] Verified unmodified
+//
+void
+P_Thrust
+( player_t* player,
+ angle_t angle,
+ fixed_t move )
+{
+ angle >>= ANGLETOFINESHIFT;
+
+ player->mo->momx += FixedMul(move,finecosine[angle]);
+ player->mo->momy += FixedMul(move,finesine[angle]);
+}
+
+
+
+
+//
+// P_CalcHeight
+// Calculate the walking / running height adjustment
+//
+// [STRIFE] Some odd adjustments, and terrain view height adjustment
+//
+void P_CalcHeight (player_t* player)
+{
+ int angle;
+ fixed_t bob;
+
+ // Regular movement bobbing
+ // (needs to be calculated for gun swing
+ // even if not on ground)
+ // OPTIMIZE: tablify angle
+ // Note: a LUT allows for effects
+ // like a ramp with low health.
+ player->bob =
+ FixedMul (player->mo->momx, player->mo->momx)
+ + FixedMul (player->mo->momy,player->mo->momy);
+
+ player->bob >>= 2;
+
+ if (player->bob>MAXBOB)
+ player->bob = MAXBOB;
+
+ // haleyjd 20110205 [STRIFE]: No CF_NOMOMENTUM check, and Rogue also removed
+ // the dead code inside.
+ if (!onground)
+ {
+ /*
+ player->viewz = player->mo->z + VIEWHEIGHT;
+
+ if (player->viewz > player->mo->ceilingz-4*FRACUNIT)
+ player->viewz = player->mo->ceilingz-4*FRACUNIT;
+ */
+
+ player->viewz = player->mo->z + player->viewheight;
+ return;
+ }
+
+ angle = (FINEANGLES/20*leveltime)&FINEMASK;
+ bob = FixedMul ( player->bob/2, finesine[angle]);
+
+ // move viewheight
+ if (player->playerstate == PST_LIVE)
+ {
+ player->viewheight += player->deltaviewheight;
+
+ if (player->viewheight > VIEWHEIGHT)
+ {
+ player->viewheight = VIEWHEIGHT;
+ player->deltaviewheight = 0;
+ }
+
+ if (player->viewheight < VIEWHEIGHT/2)
+ {
+ player->viewheight = VIEWHEIGHT/2;
+ if (player->deltaviewheight <= 0)
+ player->deltaviewheight = 1;
+ }
+
+ if (player->deltaviewheight)
+ {
+ player->deltaviewheight += FRACUNIT/4;
+ if (!player->deltaviewheight)
+ player->deltaviewheight = 1;
+ }
+ }
+ player->viewz = player->mo->z + player->viewheight + bob;
+
+ // villsa [STRIFE] account for terrain lowering the view
+ if(player->mo->flags & MF_FEETCLIPPED)
+ player->viewz -= 13*FRACUNIT;
+
+ if (player->viewz > player->mo->ceilingz-4*FRACUNIT)
+ player->viewz = player->mo->ceilingz-4*FRACUNIT;
+
+ // haleyjd [STRIFE]: added a floorz clip here
+ if (player->viewz < player->mo->floorz)
+ player->viewz = player->mo->floorz;
+}
+
+
+
+//
+// P_MovePlayer
+//
+// [STRIFE] Adjustments to allow air control, jumping, and up/down look.
+//
+void P_MovePlayer (player_t* player)
+{
+ ticcmd_t* cmd;
+
+ cmd = &player->cmd;
+
+ player->mo->angle += (cmd->angleturn<<16);
+
+ // Do not let the player control movement
+ // if not onground.
+ onground = (player->mo->z <= player->mo->floorz);
+
+ // villsa [STRIFE] allows player to climb over things by jumping
+ // haleyjd 20110205: air control thrust should be 256, not cmd->forwardmove
+ if(!onground)
+ {
+ if(cmd->forwardmove)
+ P_Thrust (player, player->mo->angle, 256);
+ }
+ else
+ {
+ // villsa [STRIFE] jump button
+ if (cmd->buttons2 & BT2_JUMP)
+ {
+ if(!player->deltaviewheight)
+ player->mo->momz += 8*FRACUNIT;
+ }
+
+ // haleyjd 20110205 [STRIFE] Either Rogue or Watcom removed the
+ // redundant "onground" checks from these if's.
+ if (cmd->forwardmove)
+ P_Thrust (player, player->mo->angle, cmd->forwardmove*2048);
+
+ if (cmd->sidemove)
+ P_Thrust (player, player->mo->angle-ANG90, cmd->sidemove*2048);
+ }
+
+ // villsa [STRIFE] player walking state set
+ if ( (cmd->forwardmove || cmd->sidemove)
+ && player->mo->state == &states[S_PLAY_00] )
+ {
+ P_SetMobjState (player->mo, S_PLAY_01);
+ }
+
+ // villsa [STRIFE] centerview button
+ if (cmd->buttons2 & BT2_CENTERVIEW)
+ player->centerview = 1;
+
+ // villsa [STRIFE] adjust player's pitch when centerviewing
+ if (player->centerview)
+ {
+ if (player->pitch <= 0)
+ {
+ if (player->pitch < 0)
+ player->pitch = player->pitch + CENTERVIEWAMOUNT;
+ }
+ else
+ {
+ player->pitch = player->pitch - CENTERVIEWAMOUNT;
+ }
+ if (abs(player->pitch) < CENTERVIEWAMOUNT)
+ {
+ player->pitch = 0;
+ player->centerview = 0;
+ }
+ }
+
+ // villsa [STRIFE] look up action
+ if (cmd->buttons2 & BT2_LOOKUP)
+ {
+ player->pitch += LOOKPITCHAMOUNT;
+ if ((player->pitch + LOOKPITCHAMOUNT) > LOOKUPMAX ||
+ (player->pitch + LOOKPITCHAMOUNT) < LOOKDOWNMAX)
+ player->pitch -= LOOKPITCHAMOUNT;
+ }
+ else
+ {
+ // villsa [STRIFE] look down action
+ if (cmd->buttons2 & BT2_LOOKDOWN)
+ {
+ player->pitch -= LOOKPITCHAMOUNT;
+ if ((player->pitch - LOOKPITCHAMOUNT) > LOOKUPMAX ||
+ (player->pitch - LOOKPITCHAMOUNT) < LOOKDOWNMAX)
+ player->pitch += LOOKPITCHAMOUNT;
+ }
+ }
+
+}
+
+
+
+//
+// P_DeathThink
+// Fall on your face when dying.
+// Decrease POV height to floor height.
+//
+// [STRIFE] Modifications for up/down look.
+//
+#define ANG5 (ANG90/18)
+
+void P_DeathThink(player_t* player)
+{
+ angle_t angle;
+ angle_t delta;
+
+ P_MovePsprites(player);
+
+ // fall to the ground
+ if (player->viewheight > 6*FRACUNIT)
+ player->viewheight -= FRACUNIT;
+
+ if (player->viewheight < 6*FRACUNIT)
+ player->viewheight = 6*FRACUNIT;
+
+ player->deltaviewheight = 0;
+ onground = (player->mo->z <= player->mo->floorz);
+ P_CalcHeight(player);
+
+ if(player->attacker && player->attacker != player->mo)
+ {
+ angle = R_PointToAngle2 (player->mo->x,
+ player->mo->y,
+ player->attacker->x,
+ player->attacker->y);
+
+ delta = angle - player->mo->angle;
+
+ if (delta < ANG5 || delta > (unsigned)-ANG5)
+ {
+ // Looking at killer,
+ // so fade damage flash down.
+ player->mo->angle = angle;
+
+ if (player->damagecount)
+ player->damagecount--;
+ }
+ else if (delta < ANG180)
+ player->mo->angle += ANG5;
+ else
+ player->mo->angle -= ANG5;
+ }
+ else if (player->damagecount)
+ player->damagecount--;
+
+ // villsa [STRIFE]
+ if(player->pitch <= 90)
+ player->pitch = player->pitch + 3;
+
+ if(player->cmd.buttons & BT_USE)
+ player->playerstate = PST_REBORN;
+}
+
+
+
+//
+// P_PlayerThink
+//
+// [STRIFE] Massive changes/additions:
+// * NOCLIP hack removed
+// * P_DeathThink moved up
+// * Inventory use/dropping
+// * Strife weapons logic
+// * Dialog
+// * Strife powerups and nukage behavior
+// * Fire Death/Sigil Shock
+//
+void P_PlayerThink (player_t* player)
+{
+ ticcmd_t* cmd;
+ weapontype_t newweapon;
+
+ // villsa [STRIFE] unused code (see ST_Responder)
+ /*
+ // fixme: do this in the cheat code
+ if (player->cheats & CF_NOCLIP)
+ player->mo->flags |= MF_NOCLIP;
+ else
+ player->mo->flags &= ~MF_NOCLIP;
+ */
+
+ // haleyjd 20110205 [STRIFE]: P_DeathThink moved up
+ if (player->playerstate == PST_DEAD)
+ {
+ P_DeathThink (player);
+ return;
+ }
+
+ // chain saw run forward
+ cmd = &player->cmd;
+ if (player->mo->flags & MF_JUSTATTACKED)
+ {
+ cmd->angleturn = 0;
+ cmd->forwardmove = 0xc800/512;
+ cmd->sidemove = 0;
+ player->mo->flags &= ~MF_JUSTATTACKED;
+ }
+
+ // Move around.
+ // Reactiontime is used to prevent movement
+ // for a bit after a teleport.
+ if (player->mo->reactiontime)
+ player->mo->reactiontime--;
+ else
+ P_MovePlayer (player);
+
+ P_CalcHeight (player);
+
+ if (player->mo->subsector->sector->special)
+ P_PlayerInSpecialSector (player);
+
+ // villsa [STRIFE] handle inventory input
+ if(cmd->buttons2 & (BT2_HEALTH|BT2_INVUSE|BT2_INVDROP))
+ {
+ if(!player->inventorydown)
+ {
+ if(cmd->buttons2 & BT2_HEALTH)
+ P_UseInventoryItem(player, SPR_FULL);
+ else if(cmd->buttons2 & BT2_INVUSE)
+ P_UseInventoryItem(player, cmd->inventory);
+ else if(cmd->buttons2 & BT2_INVDROP)
+ {
+ P_DropInventoryItem(player, cmd->inventory);
+
+ // haleyjd 20110205: removed incorrect "else" here
+ // villsa [STRIFE]
+ if(workparm)
+ {
+ int cheat = player->cheats ^ 1;
+ player->cheats ^= CF_NOCLIP;
+
+ if(cheat & CF_NOCLIP)
+ {
+ player->message = DEH_String("No Clipping Mode ON");
+ player->mo->flags |= MF_NOCLIP;
+ }
+ else
+ {
+ player->mo->flags &= ~MF_NOCLIP;
+ player->message = DEH_String("No Clipping Mode OFF");
+ }
+ }
+ }
+ }
+
+ player->inventorydown = true;
+ }
+ else
+ player->inventorydown = false;
+
+ // Check for weapon change.
+
+ // A special event has no other buttons.
+ if(cmd->buttons & BT_SPECIAL)
+ cmd->buttons = 0;
+
+ if(cmd->buttons & BT_CHANGE)
+ {
+ // The actual changing of the weapon is done
+ // when the weapon psprite can do it
+ // (read: not in the middle of an attack).
+ newweapon = (cmd->buttons & BT_WEAPONMASK) >> BT_WEAPONSHIFT;
+
+ // villsa [STRIFE] select poison bow
+ if(newweapon == wp_elecbow)
+ {
+ if(player->weaponowned[wp_poisonbow] && player->readyweapon == wp_elecbow)
+ {
+ if(player->ammo[weaponinfo[wp_poisonbow].ammo])
+ newweapon = wp_poisonbow;
+ }
+ }
+
+ // villsa [STRIFE] select wp grenade launcher
+ if(newweapon == wp_hegrenade)
+ {
+ if(player->weaponowned[wp_wpgrenade] && player->readyweapon == wp_hegrenade)
+ {
+ if(player->ammo[weaponinfo[wp_wpgrenade].ammo])
+ newweapon = wp_wpgrenade;
+ }
+ }
+
+ // villsa [STRIFE] select torpedo
+ if(newweapon == wp_mauler)
+ {
+ if(player->weaponowned[wp_torpedo] && player->readyweapon == wp_mauler)
+ {
+ if(player->ammo[weaponinfo[am_cell].ammo] >= 30)
+ newweapon = wp_torpedo;
+ }
+ }
+
+ if(player->weaponowned[newweapon] && newweapon != player->readyweapon)
+ {
+ // villsa [STRIFE] check weapon if in demo mode or not
+ if(weaponinfo[newweapon].availabledemo || !isdemoversion)
+ {
+ if(player->ammo[weaponinfo[newweapon].ammo])
+ player->pendingweapon = newweapon;
+ else
+ {
+ // decide between electric bow or poison arrow
+ if(newweapon == wp_elecbow &&
+ player->ammo[am_poisonbolts] &&
+ player->readyweapon != wp_poisonbow)
+ {
+ player->pendingweapon = wp_poisonbow;
+ }
+ // decide between hp grenade launcher or wp grenade launcher
+ else if(newweapon == wp_hegrenade &&
+ player->ammo[am_wpgrenades] &&
+ player->readyweapon != wp_wpgrenade)
+ {
+ player->pendingweapon = wp_wpgrenade;
+ }
+
+ // villsa [STRIFE] - no check for mauler/torpedo??
+ }
+ }
+ }
+ }
+
+ // check for use
+ if(cmd->buttons & BT_USE)
+ {
+ if(!player->usedown)
+ {
+ P_DialogStart(player); // villsa [STRIFE]
+ P_UseLines (player);
+ player->usedown = true;
+ }
+ }
+ else
+ player->usedown = false;
+
+ // cycle psprites
+ P_MovePsprites (player);
+
+ // Counters, time dependend power ups.
+
+ // Strength counts up to diminish fade.
+ if (player->powers[pw_strength])
+ player->powers[pw_strength]++;
+
+ // villsa [STRIFE] targeter powerup
+ if(player->powers[pw_targeter])
+ {
+ player->powers[pw_targeter]--;
+ if(player->powers[pw_targeter] == 1)
+ {
+ P_SetPsprite(player, ps_targcenter, S_NULL);
+ P_SetPsprite(player, ps_targleft, S_NULL);
+ P_SetPsprite(player, ps_targright, S_NULL);
+ }
+ else if(player->powers[pw_targeter] - 1 < 5*TICRATE)
+ {
+ if(player->powers[pw_targeter] & 32)
+ {
+ P_SetPsprite(player, ps_targright, S_NULL);
+ P_SetPsprite(player, ps_targleft, S_TRGT_01); // 11
+ }
+ else if(player->powers[pw_targeter] & 16) // haleyjd 20110205: missing else
+ {
+ P_SetPsprite(player, ps_targright, S_TRGT_02); // 12
+ P_SetPsprite(player, ps_targleft, S_NULL);
+ }
+ }
+ }
+
+ if(player->powers[pw_invisibility])
+ {
+ // villsa [STRIFE] remove mvis flag as well
+ if(!--player->powers[pw_invisibility])
+ player->mo->flags &= ~(MF_SHADOW|MF_MVIS);
+ }
+
+ if(player->powers[pw_ironfeet])
+ {
+ player->powers[pw_ironfeet]--;
+
+ // villsa [STRIFE] gasmask sound
+ if(!(leveltime & 0x3f))
+ S_StartSound(player->mo, sfx_mask);
+ }
+
+ if(player->powers[pw_allmap] > 1)
+ player->powers[pw_allmap]--;
+
+ // haleyjd 08/30/10: [STRIFE]
+ // Nukage count keeps track of exposure to hazardous conditions over time.
+ // After accumulating 16 total seconds or more of exposure, you will take
+ // 5 damage roughly once per second until the count drops back under 560
+ // tics.
+ if(player->nukagecount)
+ {
+ player->nukagecount--;
+ if(!(leveltime & 0x1f) && player->nukagecount > 16*TICRATE)
+ P_DamageMobj(player->mo, NULL, NULL, 5);
+ }
+
+ if(player->damagecount)
+ player->damagecount--;
+
+ if(player->bonuscount)
+ player->bonuscount--;
+
+ // villsa [STRIFE] checks for extralight
+ if(player->extralight >= 0)
+ {
+ if(player->cheats & CF_ONFIRE)
+ player->fixedcolormap = 1;
+ else
+ player->fixedcolormap = 0;
+ }
+ else // Sigil shock:
+ player->fixedcolormap = INVERSECOLORMAP;
+}
+
+
+//
+// P_RemoveInventoryItem
+// villsa [STRIFE] new function
+//
+char* P_RemoveInventoryItem(player_t *player, int slot, int amount)
+{
+ mobjtype_t type;
+
+ player->inventory[slot].amount -= amount;
+ player->st_update = true;
+
+ type = player->inventory[slot].type;
+
+ if(!player->inventory[slot].amount)
+ {
+ // shift everything above it down
+ // see P_TakeDialogItem for notes on possible bugs
+ int j;
+
+ for(j = slot + 1; j <= player->numinventory; j++)
+ {
+ inventory_t *item1 = &(player->inventory[j - 1]);
+ inventory_t *item2 = &(player->inventory[j]);
+
+ *item1 = *item2;
+ }
+
+ player->inventory[player->numinventory].type = NUMMOBJTYPES;
+ player->inventory[player->numinventory].sprite = -1;
+ player->numinventory--;
+
+ // update cursor position
+ if(player->inventorycursor >= player->numinventory)
+ {
+ if(player->inventorycursor)
+ player->inventorycursor--;
+ }
+ }
+
+ return mobjinfo[type].name;
+}
+
+//
+// P_DropInventoryItem
+// villsa [STRIFE] new function
+//
+void P_DropInventoryItem(player_t* player, int sprite)
+{
+ int invslot;
+ inventory_t *item;
+ mobjtype_t type;
+ int amount;
+
+ invslot = 0;
+ amount = 1;
+
+ while(invslot < player->numinventory && sprite != player->inventory[invslot].sprite)
+ invslot++;
+
+ item = &(player->inventory[invslot]);
+ type = item->type;
+
+ if(item->amount)
+ {
+ angle_t angle;
+ fixed_t dist;
+ mobj_t* mo;
+ mobj_t* mobjitem;
+ fixed_t x;
+ fixed_t y;
+ fixed_t z;
+ int r;
+
+ if(item->type == MT_MONY_1)
+ {
+ if(item->amount >= 50)
+ {
+ type = MT_MONY_50;
+ amount = 50;
+ }
+ else if(item->amount >= 25)
+ {
+ type = MT_MONY_25;
+ amount = 25;
+ }
+ else if(item->amount >= 10)
+ {
+ type = MT_MONY_10;
+ amount = 10;
+ }
+ }
+
+ if(type >= NUMMOBJTYPES)
+ return;
+
+ angle = player->mo->angle;
+ r = P_Random();
+ angle = (angle + ((r - P_Random()) << 18)) >> ANGLETOFINESHIFT;
+
+ if(angle < 7618 && angle >= 6718)
+ angle = 7618;
+
+ else if(angle < 5570 && angle >= 4670)
+ angle = 5570;
+
+ else if(angle < 3522 && angle >= 2622)
+ angle = 3522;
+
+ else if(angle < 1474 && angle >= 574)
+ angle = 1474;
+
+ mo = player->mo;
+ dist = mobjinfo[type].radius + mo->info->radius + (4*FRACUNIT);
+
+ x = mo->x + FixedMul(finecosine[angle], dist);
+ y = mo->y + FixedMul(finesine[angle], dist);
+ z = mo->z + (10*FRACUNIT);
+ mobjitem = P_SpawnMobj(x, y, z, type);
+ mobjitem->flags |= (MF_SPECIAL|MF_DROPPED);
+
+ if(P_CheckPosition(mobjitem, x, y))
+ {
+ mobjitem->angle = (angle << ANGLETOFINESHIFT);
+ mobjitem->momx = FixedMul(finecosine[angle], (5*FRACUNIT)) + mo->momx;
+ mobjitem->momy = FixedMul(finesine[angle], (5*FRACUNIT)) + mo->momy;
+ mobjitem->momz = FRACUNIT;
+
+ P_RemoveInventoryItem(player, invslot, amount);
+ }
+ else
+ P_RemoveMobj(mobjitem);
+ }
+}
+
+//
+// P_TossDegninOre
+// villsa [STRIFE] new function
+//
+boolean P_TossDegninOre(player_t* player)
+{
+ angle_t angle;
+ mobj_t* mo;
+ mobj_t* ore;
+ fixed_t x;
+ fixed_t y;
+ fixed_t z;
+ fixed_t dist;
+
+ angle = player->mo->angle >> ANGLETOFINESHIFT;
+
+ if(angle < 7618 && angle >= 6718)
+ angle = 7618;
+
+ else if(angle < 5570 && angle >= 4670)
+ angle = 5570;
+
+ else if(angle < 3522 && angle >= 2622)
+ angle = 3522;
+
+ else if(angle < 1474 && angle >= 574)
+ angle = 1474;
+
+ mo = player->mo;
+ dist = mobjinfo[MT_DEGNINORE].radius + mo->info->radius + (4*FRACUNIT);
+
+ x = mo->x + FixedMul(finecosine[angle], dist);
+ y = mo->y + FixedMul(finesine[angle], dist);
+ z = mo->z + (10*FRACUNIT);
+ ore = P_SpawnMobj(x, y, z, MT_DEGNINORE);
+
+ if(P_CheckPosition(ore, x, y))
+ {
+ ore->target = mo;
+ ore->angle = (angle << ANGLETOFINESHIFT);
+ ore->momx = FixedMul(finecosine[angle], (5*FRACUNIT));
+ ore->momy = FixedMul(finesine[angle], (5*FRACUNIT));
+ ore->momz = FRACUNIT;
+ return true;
+ }
+ else
+ P_RemoveMobj(ore);
+
+ return false;
+}
+
+//
+// P_SpawnTeleportBeacon
+// villsa [STRIFE] new function
+//
+boolean P_SpawnTeleportBeacon(player_t* player)
+{
+ angle_t angle;
+ int r;
+ mobj_t* mo;
+ mobj_t* beacon;
+ fixed_t x;
+ fixed_t y;
+ fixed_t z;
+ fixed_t dist;
+
+ angle = player->mo->angle;
+ r = P_Random();
+ angle = (angle + ((r - P_Random()) << 18)) >> ANGLETOFINESHIFT;
+
+ if(angle < 7618 && angle >= 6718)
+ angle = 7618;
+
+ else if(angle < 5570 && angle >= 4670)
+ angle = 5570;
+
+ else if(angle < 3522 && angle >= 2622)
+ angle = 3522;
+
+ else if(angle < 1474 && angle >= 574)
+ angle = 1474;
+
+ mo = player->mo;
+ dist = mobjinfo[MT_BEACON].radius + mo->info->radius + (4*FRACUNIT);
+
+ x = mo->x + FixedMul(finecosine[angle], dist);
+ y = mo->y + FixedMul(finesine[angle], dist);
+ z = mo->z + (10*FRACUNIT);
+ beacon = P_SpawnMobj(x, y, z, MT_BEACON);
+
+ if(P_CheckPosition(beacon, x, y))
+ {
+ beacon->target = mo;
+ beacon->miscdata = mo->miscdata;
+ beacon->angle = (angle << ANGLETOFINESHIFT);
+ beacon->momx = FixedMul(finecosine[angle], (5*FRACUNIT));
+ beacon->momy = FixedMul(finesine[angle], (5*FRACUNIT));
+ beacon->momz = FRACUNIT;
+ P_SetMobjState(beacon, beacon->info->seestate);
+ return true;
+ }
+ else
+ P_RemoveMobj(beacon);
+
+ return false;
+}
+
+//
+// P_UseInventoryItem
+// villsa [STRIFE] new function
+//
+boolean P_UseInventoryItem(player_t* player, int item)
+{
+ int i;
+ char* name;
+
+ if(player->cheats & CF_ONFIRE)
+ return false;
+
+ for(i = 0; i < player->numinventory; i++)
+ {
+ if(item != player->inventory[i].sprite)
+ continue;
+
+ if(!P_ItemBehavior(player, item))
+ return false;
+
+ name = P_RemoveInventoryItem(player, i, 1);
+ if(name == NULL)
+ name = "Item";
+
+ sprintf(useinventorymsg, "You used the %s.", name);
+ player->message = useinventorymsg;
+
+ if(player == &players[consoleplayer])
+ S_StartSound(NULL, sfx_itemup);
+
+ return true;
+ }
+
+ return false;
+}
+
+//
+// P_ItemBehavior
+// villsa [STRIFE] new function
+//
+boolean P_ItemBehavior(player_t* player, int item)
+{
+ switch(item)
+ {
+ case SPR_ARM1: // 136
+ return P_GiveArmor(player, 2);
+
+ case SPR_ARM2: // 137
+ return P_GiveArmor(player, 1);
+
+ case SPR_SHD1: // 186
+ return P_GivePower(player, pw_invisibility);
+
+ case SPR_MASK: // 187
+ return P_GivePower(player, pw_ironfeet);
+
+ case SPR_PMUP: // 191
+ if(!player->powers[pw_allmap])
+ {
+ player->message = "The scanner won't work without a map!";
+ return false;
+ }
+ player->powers[pw_allmap] = PMUPTICS;
+ return true; // haleyjd 20110228: repaired
+
+ case SPR_STMP: // 180
+ return P_GiveBody(player, 10);
+
+ case SPR_MDKT: // 181
+ return P_GiveBody(player, 25);
+
+ case SPR_FULL: // 130
+ return P_GiveBody(player, 200);
+
+ case SPR_BEAC: // 135
+ return P_SpawnTeleportBeacon(player);
+
+ case SPR_TARG: // 108
+ return P_GivePower(player, pw_targeter);
+ }
+
+ return false;
+}