1998-04-07 00:00:00 +00:00
|
|
|
// Emacs style mode select -*- C++ -*-
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
//
|
|
|
|
// $Id:$
|
|
|
|
//
|
|
|
|
// Copyright (C) 1993-1996 by id Software, Inc.
|
|
|
|
//
|
|
|
|
// This source is available for distribution and/or modification
|
|
|
|
// only under the terms of the DOOM Source Code License as
|
|
|
|
// published by id Software. All rights reserved.
|
|
|
|
//
|
|
|
|
// The source is distributed in the hope that it will be useful,
|
|
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
// FITNESS FOR A PARTICULAR PURPOSE. See the DOOM Source Code License
|
|
|
|
// for more details.
|
|
|
|
//
|
|
|
|
// $Log:$
|
|
|
|
//
|
|
|
|
// DESCRIPTION:
|
|
|
|
// Handling interactions (i.e., collisions).
|
|
|
|
//
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Data.
|
|
|
|
#include "doomdef.h"
|
|
|
|
#include "dstrings.h"
|
|
|
|
|
|
|
|
#include "doomstat.h"
|
|
|
|
|
|
|
|
#include "m_random.h"
|
|
|
|
#include "i_system.h"
|
|
|
|
|
|
|
|
#include "am_map.h"
|
|
|
|
|
1998-07-14 00:00:00 +00:00
|
|
|
#include "c_consol.h"
|
1998-04-07 00:00:00 +00:00
|
|
|
|
|
|
|
#include "p_local.h"
|
|
|
|
|
|
|
|
#include "s_sound.h"
|
|
|
|
|
|
|
|
#include "p_inter.h"
|
1998-12-22 00:00:00 +00:00
|
|
|
#include "p_lnspec.h"
|
1998-04-07 00:00:00 +00:00
|
|
|
|
|
|
|
|
|
|
|
#define BONUSADD 6
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// a weapon is found with two clip loads,
|
|
|
|
// a big item has five clip loads
|
|
|
|
int maxammo[NUMAMMO] = {200, 50, 300, 50};
|
|
|
|
int clipammo[NUMAMMO] = {10, 4, 20, 1};
|
|
|
|
|
|
|
|
|
1999-02-17 00:00:00 +00:00
|
|
|
static void PickupMessage (mobj_t *toucher, const char *message)
|
|
|
|
{
|
1999-02-21 00:00:00 +00:00
|
|
|
// Some maps have multiple items stacked on top of each other.
|
|
|
|
// It looks odd to display pickup messages for all of them.
|
|
|
|
static int lastmessagetic;
|
|
|
|
static const char *lastmessage = NULL;
|
|
|
|
|
|
|
|
if (toucher == players[consoleplayer].camera
|
|
|
|
&& (lastmessagetic != gametic || lastmessage != message))
|
|
|
|
{
|
|
|
|
lastmessagetic = gametic;
|
|
|
|
lastmessage = message;
|
1999-02-17 00:00:00 +00:00
|
|
|
Printf (PRINT_LOW, "%s\n", message);
|
1999-02-21 00:00:00 +00:00
|
|
|
}
|
1999-02-17 00:00:00 +00:00
|
|
|
}
|
|
|
|
|
1998-04-07 00:00:00 +00:00
|
|
|
//
|
|
|
|
// GET STUFF
|
|
|
|
//
|
|
|
|
|
|
|
|
//
|
|
|
|
// P_GiveAmmo
|
|
|
|
// Num is the number of clip loads,
|
|
|
|
// not the individual count (0= 1/2 clip).
|
|
|
|
// Returns false if the ammo can't be picked up at all
|
|
|
|
//
|
|
|
|
|
1998-07-14 00:00:00 +00:00
|
|
|
BOOL P_GiveAmmo (player_t *player, ammotype_t ammo, int num)
|
1998-04-07 00:00:00 +00:00
|
|
|
{
|
1999-02-17 00:00:00 +00:00
|
|
|
int oldammo;
|
1998-04-07 00:00:00 +00:00
|
|
|
|
|
|
|
if (ammo == am_noammo)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
if (ammo < 0 || ammo > NUMAMMO)
|
|
|
|
I_Error ("P_GiveAmmo: bad type %i", ammo);
|
|
|
|
|
|
|
|
if ( player->ammo[ammo] == player->maxammo[ammo] )
|
|
|
|
return false;
|
|
|
|
|
|
|
|
if (num)
|
|
|
|
num *= clipammo[ammo];
|
|
|
|
else
|
|
|
|
num = clipammo[ammo]/2;
|
|
|
|
|
|
|
|
if (gameskill->value == sk_baby
|
|
|
|
|| gameskill->value == sk_nightmare)
|
|
|
|
{
|
|
|
|
// give double ammo in trainer mode,
|
|
|
|
// you'll need in nightmare
|
|
|
|
num <<= 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
oldammo = player->ammo[ammo];
|
|
|
|
player->ammo[ammo] += num;
|
|
|
|
|
|
|
|
if (player->ammo[ammo] > player->maxammo[ammo])
|
|
|
|
player->ammo[ammo] = player->maxammo[ammo];
|
|
|
|
|
|
|
|
// If non zero ammo,
|
|
|
|
// don't change up weapons,
|
|
|
|
// player was lower on purpose.
|
|
|
|
if (oldammo)
|
|
|
|
return true;
|
|
|
|
|
|
|
|
// We were down to zero,
|
|
|
|
// so select a new weapon.
|
|
|
|
// Preferences are not user selectable.
|
|
|
|
switch (ammo)
|
|
|
|
{
|
|
|
|
case am_clip:
|
|
|
|
if (player->readyweapon == wp_fist)
|
|
|
|
{
|
|
|
|
if (player->weaponowned[wp_chaingun])
|
|
|
|
player->pendingweapon = wp_chaingun;
|
|
|
|
else
|
|
|
|
player->pendingweapon = wp_pistol;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case am_shell:
|
|
|
|
if (player->readyweapon == wp_fist
|
|
|
|
|| player->readyweapon == wp_pistol)
|
|
|
|
{
|
|
|
|
if (player->weaponowned[wp_shotgun])
|
|
|
|
player->pendingweapon = wp_shotgun;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case am_cell:
|
|
|
|
if (player->readyweapon == wp_fist
|
|
|
|
|| player->readyweapon == wp_pistol)
|
|
|
|
{
|
|
|
|
if (player->weaponowned[wp_plasma])
|
|
|
|
player->pendingweapon = wp_plasma;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case am_misl:
|
|
|
|
if (player->readyweapon == wp_fist)
|
|
|
|
{
|
|
|
|
if (player->weaponowned[wp_missile])
|
|
|
|
player->pendingweapon = wp_missile;
|
|
|
|
}
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
// P_GiveWeapon
|
|
|
|
// The weapon name may have a MF_DROPPED flag ored in.
|
|
|
|
//
|
1998-07-14 00:00:00 +00:00
|
|
|
BOOL P_GiveWeapon (player_t *player, weapontype_t weapon, BOOL dropped)
|
1998-04-07 00:00:00 +00:00
|
|
|
{
|
1998-07-14 00:00:00 +00:00
|
|
|
BOOL gaveammo;
|
|
|
|
BOOL gaveweapon;
|
1999-02-17 00:00:00 +00:00
|
|
|
|
|
|
|
// [RH] Don't get the weapon if no graphics for it
|
|
|
|
state_t *state = states + weaponinfo[weapon].readystate;
|
|
|
|
if ((state->frame & FF_FRAMEMASK) >= sprites[state->sprite].numframes)
|
|
|
|
return false;
|
|
|
|
|
1998-07-14 00:00:00 +00:00
|
|
|
if (netgame && (!deathmatch->value || dmflags & DF_WEAPONS_STAY) && !dropped)
|
1998-04-07 00:00:00 +00:00
|
|
|
{
|
|
|
|
// leave placed weapons forever on net games
|
|
|
|
if (player->weaponowned[weapon])
|
|
|
|
return false;
|
|
|
|
|
|
|
|
player->bonuscount += BONUSADD;
|
|
|
|
player->weaponowned[weapon] = true;
|
|
|
|
|
1998-07-14 00:00:00 +00:00
|
|
|
if (deathmatch->value)
|
1998-04-07 00:00:00 +00:00
|
|
|
P_GiveAmmo (player, weaponinfo[weapon].ammo, 5);
|
|
|
|
else
|
|
|
|
P_GiveAmmo (player, weaponinfo[weapon].ammo, 2);
|
1999-02-17 00:00:00 +00:00
|
|
|
if (!player->userinfo.neverswitch)
|
|
|
|
player->pendingweapon = weapon;
|
1998-04-07 00:00:00 +00:00
|
|
|
|
1999-02-17 00:00:00 +00:00
|
|
|
S_Sound (player->mo, CHAN_ITEM, "misc/w_pkup", 1, ATTN_NORM);
|
1998-04-07 00:00:00 +00:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (weaponinfo[weapon].ammo != am_noammo)
|
|
|
|
{
|
|
|
|
// give one clip with a dropped weapon,
|
|
|
|
// two clips with a found weapon
|
|
|
|
if (dropped)
|
|
|
|
gaveammo = P_GiveAmmo (player, weaponinfo[weapon].ammo, 1);
|
|
|
|
else
|
|
|
|
gaveammo = P_GiveAmmo (player, weaponinfo[weapon].ammo, 2);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
gaveammo = false;
|
|
|
|
|
|
|
|
if (player->weaponowned[weapon])
|
|
|
|
gaveweapon = false;
|
|
|
|
else
|
|
|
|
{
|
|
|
|
gaveweapon = true;
|
|
|
|
player->weaponowned[weapon] = true;
|
1999-02-17 00:00:00 +00:00
|
|
|
if (!player->userinfo.neverswitch)
|
|
|
|
player->pendingweapon = weapon;
|
1998-04-07 00:00:00 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return (gaveweapon || gaveammo);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
// P_GiveBody
|
|
|
|
// Returns false if the body isn't needed at all
|
|
|
|
//
|
1998-07-14 00:00:00 +00:00
|
|
|
BOOL P_GiveBody (player_t *player, int num)
|
1998-04-07 00:00:00 +00:00
|
|
|
{
|
|
|
|
if (player->health >= MAXHEALTH)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
player->health += num;
|
|
|
|
if (player->health > MAXHEALTH)
|
|
|
|
player->health = MAXHEALTH;
|
|
|
|
player->mo->health = player->health;
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
// P_GiveArmor
|
|
|
|
// Returns false if the armor is worse
|
|
|
|
// than the current armor.
|
|
|
|
//
|
1998-07-14 00:00:00 +00:00
|
|
|
BOOL P_GiveArmor (player_t *player, int armortype)
|
1998-04-07 00:00:00 +00:00
|
|
|
{
|
|
|
|
int hits;
|
|
|
|
|
|
|
|
hits = armortype*100;
|
|
|
|
if (player->armorpoints >= hits)
|
|
|
|
return false; // don't pick up
|
|
|
|
|
|
|
|
player->armortype = armortype;
|
|
|
|
player->armorpoints = hits;
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
// P_GiveCard
|
|
|
|
//
|
1998-04-07 00:00:00 +00:00
|
|
|
void P_GiveCard (player_t *player, card_t card)
|
1998-04-07 00:00:00 +00:00
|
|
|
{
|
|
|
|
if (player->cards[card])
|
|
|
|
return;
|
|
|
|
|
|
|
|
player->bonuscount = BONUSADD;
|
|
|
|
player->cards[card] = 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
// P_GivePower
|
|
|
|
//
|
1998-07-14 00:00:00 +00:00
|
|
|
BOOL P_GivePower (player_t *player, int /*powertype_t*/ power)
|
1998-04-07 00:00:00 +00:00
|
|
|
{
|
|
|
|
if (power == pw_invulnerability)
|
|
|
|
{
|
|
|
|
player->powers[power] = INVULNTICS;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (power == pw_invisibility)
|
|
|
|
{
|
|
|
|
player->powers[power] = INVISTICS;
|
|
|
|
player->mo->flags |= MF_SHADOW;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (power == pw_infrared)
|
|
|
|
{
|
|
|
|
player->powers[power] = INFRATICS;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (power == pw_ironfeet)
|
|
|
|
{
|
|
|
|
player->powers[power] = IRONTICS;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (power == pw_strength)
|
|
|
|
{
|
|
|
|
P_GiveBody (player, 100);
|
|
|
|
player->powers[power] = 1;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (player->powers[power])
|
|
|
|
return false; // already got it
|
|
|
|
|
|
|
|
player->powers[power] = 1;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
// P_TouchSpecialThing
|
|
|
|
//
|
1998-04-07 00:00:00 +00:00
|
|
|
void P_TouchSpecialThing (mobj_t *special, mobj_t *toucher)
|
1998-04-07 00:00:00 +00:00
|
|
|
{
|
|
|
|
player_t* player;
|
|
|
|
int i;
|
|
|
|
fixed_t delta;
|
|
|
|
int sound;
|
|
|
|
|
|
|
|
delta = special->z - toucher->z;
|
|
|
|
|
1999-02-17 00:00:00 +00:00
|
|
|
if (delta > toucher->height || delta < -8*FRACUNIT)
|
1998-04-07 00:00:00 +00:00
|
|
|
{
|
|
|
|
// out of reach
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
1998-12-22 00:00:00 +00:00
|
|
|
sound = 0;
|
1998-04-07 00:00:00 +00:00
|
|
|
player = toucher->player;
|
|
|
|
|
|
|
|
// Dead thing touching.
|
|
|
|
// Can happen with a sliding player corpse.
|
|
|
|
if (toucher->health <= 0)
|
|
|
|
return;
|
|
|
|
|
|
|
|
// Identify by sprite.
|
|
|
|
switch (special->sprite)
|
|
|
|
{
|
|
|
|
// armor
|
|
|
|
case SPR_ARM1:
|
1998-12-22 00:00:00 +00:00
|
|
|
if (!P_GiveArmor (player, deh.GreenAC))
|
1998-04-07 00:00:00 +00:00
|
|
|
return;
|
1999-02-17 00:00:00 +00:00
|
|
|
PickupMessage (toucher, GOTARMOR);
|
1998-04-07 00:00:00 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case SPR_ARM2:
|
1998-12-22 00:00:00 +00:00
|
|
|
if (!P_GiveArmor (player, deh.BlueAC))
|
1998-04-07 00:00:00 +00:00
|
|
|
return;
|
1999-02-17 00:00:00 +00:00
|
|
|
PickupMessage (toucher, GOTMEGA);
|
1998-04-07 00:00:00 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
// bonus items
|
|
|
|
case SPR_BON1:
|
|
|
|
player->health++; // can go over 100%
|
1998-12-22 00:00:00 +00:00
|
|
|
if (player->health > deh.MaxSoulsphere)
|
|
|
|
player->health = deh.MaxSoulsphere;
|
1998-04-07 00:00:00 +00:00
|
|
|
player->mo->health = player->health;
|
1999-02-17 00:00:00 +00:00
|
|
|
PickupMessage (toucher, GOTHTHBONUS);
|
1998-04-07 00:00:00 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case SPR_BON2:
|
|
|
|
player->armorpoints++; // can go over 100%
|
1998-12-22 00:00:00 +00:00
|
|
|
if (player->armorpoints > deh.MaxArmor)
|
|
|
|
player->armorpoints = deh.MaxArmor;
|
1998-04-07 00:00:00 +00:00
|
|
|
if (!player->armortype)
|
1998-12-22 00:00:00 +00:00
|
|
|
player->armortype = deh.GreenAC;
|
1999-02-17 00:00:00 +00:00
|
|
|
PickupMessage (toucher, GOTARMBONUS);
|
1998-04-07 00:00:00 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case SPR_SOUL:
|
1998-12-22 00:00:00 +00:00
|
|
|
player->health += deh.SoulsphereHealth;
|
|
|
|
if (player->health > deh.MaxSoulsphere)
|
|
|
|
player->health = deh.MaxSoulsphere;
|
1998-04-07 00:00:00 +00:00
|
|
|
player->mo->health = player->health;
|
1999-02-17 00:00:00 +00:00
|
|
|
PickupMessage (toucher, GOTSUPER);
|
1998-12-22 00:00:00 +00:00
|
|
|
sound = 1;
|
1998-04-07 00:00:00 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case SPR_MEGA:
|
|
|
|
if (gamemode != commercial)
|
|
|
|
return;
|
1998-12-22 00:00:00 +00:00
|
|
|
player->health = deh.MegasphereHealth;
|
1998-04-07 00:00:00 +00:00
|
|
|
player->mo->health = player->health;
|
1998-12-22 00:00:00 +00:00
|
|
|
P_GiveArmor (player,deh.BlueAC);
|
1999-02-17 00:00:00 +00:00
|
|
|
PickupMessage (toucher, GOTMSPHERE);
|
1998-12-22 00:00:00 +00:00
|
|
|
sound = 1;
|
1998-04-07 00:00:00 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
// cards
|
|
|
|
// leave cards for everyone
|
|
|
|
case SPR_BKEY:
|
|
|
|
if (!player->cards[it_bluecard])
|
1999-02-17 00:00:00 +00:00
|
|
|
PickupMessage (toucher, GOTBLUECARD);
|
1998-04-07 00:00:00 +00:00
|
|
|
P_GiveCard (player, it_bluecard);
|
1998-12-22 00:00:00 +00:00
|
|
|
sound = 3;
|
1998-04-07 00:00:00 +00:00
|
|
|
if (!netgame)
|
|
|
|
break;
|
|
|
|
return;
|
|
|
|
|
|
|
|
case SPR_YKEY:
|
|
|
|
if (!player->cards[it_yellowcard])
|
1999-02-17 00:00:00 +00:00
|
|
|
PickupMessage (toucher, GOTYELWCARD);
|
1998-04-07 00:00:00 +00:00
|
|
|
P_GiveCard (player, it_yellowcard);
|
1998-12-22 00:00:00 +00:00
|
|
|
sound = 3;
|
1998-04-07 00:00:00 +00:00
|
|
|
if (!netgame)
|
|
|
|
break;
|
|
|
|
return;
|
|
|
|
|
|
|
|
case SPR_RKEY:
|
|
|
|
if (!player->cards[it_redcard])
|
1999-02-17 00:00:00 +00:00
|
|
|
PickupMessage (toucher, GOTREDCARD);
|
1998-04-07 00:00:00 +00:00
|
|
|
P_GiveCard (player, it_redcard);
|
1998-12-22 00:00:00 +00:00
|
|
|
sound = 3;
|
1998-04-07 00:00:00 +00:00
|
|
|
if (!netgame)
|
|
|
|
break;
|
|
|
|
return;
|
|
|
|
|
|
|
|
case SPR_BSKU:
|
|
|
|
if (!player->cards[it_blueskull])
|
1999-02-17 00:00:00 +00:00
|
|
|
PickupMessage (toucher, GOTBLUESKUL);
|
1998-04-07 00:00:00 +00:00
|
|
|
P_GiveCard (player, it_blueskull);
|
1998-12-22 00:00:00 +00:00
|
|
|
sound = 3;
|
1998-04-07 00:00:00 +00:00
|
|
|
if (!netgame)
|
|
|
|
break;
|
|
|
|
return;
|
|
|
|
|
|
|
|
case SPR_YSKU:
|
|
|
|
if (!player->cards[it_yellowskull])
|
1999-02-17 00:00:00 +00:00
|
|
|
PickupMessage (toucher, GOTYELWSKUL);
|
1998-04-07 00:00:00 +00:00
|
|
|
P_GiveCard (player, it_yellowskull);
|
1998-12-22 00:00:00 +00:00
|
|
|
sound = 3;
|
1998-04-07 00:00:00 +00:00
|
|
|
if (!netgame)
|
|
|
|
break;
|
|
|
|
return;
|
|
|
|
|
|
|
|
case SPR_RSKU:
|
|
|
|
if (!player->cards[it_redskull])
|
1999-02-17 00:00:00 +00:00
|
|
|
PickupMessage (toucher, GOTREDSKULL);
|
1998-04-07 00:00:00 +00:00
|
|
|
P_GiveCard (player, it_redskull);
|
1998-12-22 00:00:00 +00:00
|
|
|
sound = 3;
|
1998-04-07 00:00:00 +00:00
|
|
|
if (!netgame)
|
|
|
|
break;
|
|
|
|
return;
|
|
|
|
|
|
|
|
// medikits, heals
|
|
|
|
case SPR_STIM:
|
|
|
|
if (!P_GiveBody (player, 10))
|
|
|
|
return;
|
1999-02-17 00:00:00 +00:00
|
|
|
PickupMessage (toucher, GOTSTIM);
|
1998-04-07 00:00:00 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case SPR_MEDI:
|
|
|
|
if (!P_GiveBody (player, 25))
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (player->health < 25)
|
1999-02-17 00:00:00 +00:00
|
|
|
PickupMessage (toucher, GOTMEDINEED);
|
1998-04-07 00:00:00 +00:00
|
|
|
else
|
1999-02-17 00:00:00 +00:00
|
|
|
PickupMessage (toucher, GOTMEDIKIT);
|
1998-04-07 00:00:00 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
|
|
// power ups
|
|
|
|
case SPR_PINV:
|
|
|
|
if (!P_GivePower (player, pw_invulnerability))
|
|
|
|
return;
|
1999-02-17 00:00:00 +00:00
|
|
|
PickupMessage (toucher, GOTINVUL);
|
1998-12-22 00:00:00 +00:00
|
|
|
sound = 1;
|
1998-04-07 00:00:00 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case SPR_PSTR:
|
|
|
|
if (!P_GivePower (player, pw_strength))
|
|
|
|
return;
|
1999-02-17 00:00:00 +00:00
|
|
|
PickupMessage (toucher, GOTBERSERK);
|
1998-04-07 00:00:00 +00:00
|
|
|
if (player->readyweapon != wp_fist)
|
|
|
|
player->pendingweapon = wp_fist;
|
1998-12-22 00:00:00 +00:00
|
|
|
sound = 1;
|
1998-04-07 00:00:00 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case SPR_PINS:
|
|
|
|
if (!P_GivePower (player, pw_invisibility))
|
|
|
|
return;
|
1999-02-17 00:00:00 +00:00
|
|
|
PickupMessage (toucher, GOTINVIS);
|
1998-12-22 00:00:00 +00:00
|
|
|
sound = 1;
|
1998-04-07 00:00:00 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case SPR_SUIT:
|
|
|
|
if (!P_GivePower (player, pw_ironfeet))
|
|
|
|
return;
|
1999-02-17 00:00:00 +00:00
|
|
|
PickupMessage (toucher, GOTSUIT);
|
1998-12-22 00:00:00 +00:00
|
|
|
sound = 1;
|
1998-04-07 00:00:00 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case SPR_PMAP:
|
|
|
|
if (!P_GivePower (player, pw_allmap))
|
|
|
|
return;
|
1999-02-17 00:00:00 +00:00
|
|
|
PickupMessage (toucher, GOTMAP);
|
1998-12-22 00:00:00 +00:00
|
|
|
sound = 1;
|
1998-04-07 00:00:00 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case SPR_PVIS:
|
|
|
|
if (!P_GivePower (player, pw_infrared))
|
|
|
|
return;
|
1999-02-17 00:00:00 +00:00
|
|
|
PickupMessage (toucher, GOTVISOR);
|
1998-12-22 00:00:00 +00:00
|
|
|
sound = 1;
|
1998-04-07 00:00:00 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
// ammo
|
|
|
|
case SPR_CLIP:
|
|
|
|
if (special->flags & MF_DROPPED)
|
|
|
|
{
|
|
|
|
if (!P_GiveAmmo (player,am_clip,0))
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (!P_GiveAmmo (player,am_clip,1))
|
|
|
|
return;
|
|
|
|
}
|
1999-02-17 00:00:00 +00:00
|
|
|
PickupMessage (toucher, GOTCLIP);
|
1998-04-07 00:00:00 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case SPR_AMMO:
|
|
|
|
if (!P_GiveAmmo (player, am_clip,5))
|
|
|
|
return;
|
1999-02-17 00:00:00 +00:00
|
|
|
PickupMessage (toucher, GOTCLIPBOX);
|
1998-04-07 00:00:00 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case SPR_ROCK:
|
|
|
|
if (!P_GiveAmmo (player, am_misl,1))
|
|
|
|
return;
|
1999-02-17 00:00:00 +00:00
|
|
|
PickupMessage (toucher, GOTROCKET);
|
1998-04-07 00:00:00 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case SPR_BROK:
|
|
|
|
if (!P_GiveAmmo (player, am_misl,5))
|
|
|
|
return;
|
1999-02-17 00:00:00 +00:00
|
|
|
PickupMessage (toucher, GOTROCKBOX);
|
1998-04-07 00:00:00 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case SPR_CELL:
|
|
|
|
if (!P_GiveAmmo (player, am_cell,1))
|
|
|
|
return;
|
1999-02-17 00:00:00 +00:00
|
|
|
PickupMessage (toucher, GOTCELL);
|
1998-04-07 00:00:00 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case SPR_CELP:
|
|
|
|
if (!P_GiveAmmo (player, am_cell,5))
|
|
|
|
return;
|
1999-02-17 00:00:00 +00:00
|
|
|
PickupMessage (toucher, GOTCELLBOX);
|
1998-04-07 00:00:00 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case SPR_SHEL:
|
|
|
|
if (!P_GiveAmmo (player, am_shell,1))
|
|
|
|
return;
|
1999-02-17 00:00:00 +00:00
|
|
|
PickupMessage (toucher, GOTSHELLS);
|
1998-04-07 00:00:00 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case SPR_SBOX:
|
|
|
|
if (!P_GiveAmmo (player, am_shell,5))
|
|
|
|
return;
|
1999-02-17 00:00:00 +00:00
|
|
|
PickupMessage (toucher, GOTSHELLBOX);
|
1998-04-07 00:00:00 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case SPR_BPAK:
|
|
|
|
if (!player->backpack)
|
|
|
|
{
|
|
|
|
for (i=0 ; i<NUMAMMO ; i++)
|
|
|
|
player->maxammo[i] *= 2;
|
|
|
|
player->backpack = true;
|
|
|
|
}
|
|
|
|
for (i=0 ; i<NUMAMMO ; i++)
|
|
|
|
P_GiveAmmo (player, i, 1);
|
1999-02-17 00:00:00 +00:00
|
|
|
PickupMessage (toucher, GOTBACKPACK);
|
1998-04-07 00:00:00 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
// weapons
|
|
|
|
case SPR_BFUG:
|
|
|
|
if (!P_GiveWeapon (player, wp_bfg, false) )
|
|
|
|
return;
|
1999-02-17 00:00:00 +00:00
|
|
|
PickupMessage (toucher, GOTBFG9000);
|
1998-12-22 00:00:00 +00:00
|
|
|
sound = 2;
|
1998-04-07 00:00:00 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case SPR_MGUN:
|
1999-02-17 00:00:00 +00:00
|
|
|
if (!P_GiveWeapon (player, wp_chaingun, special->flags & MF_DROPPED))
|
1998-04-07 00:00:00 +00:00
|
|
|
return;
|
1999-02-17 00:00:00 +00:00
|
|
|
PickupMessage (toucher, GOTCHAINGUN);
|
1998-12-22 00:00:00 +00:00
|
|
|
sound = 2;
|
1998-04-07 00:00:00 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case SPR_CSAW:
|
|
|
|
if (!P_GiveWeapon (player, wp_chainsaw, false) )
|
|
|
|
return;
|
1999-02-17 00:00:00 +00:00
|
|
|
PickupMessage (toucher, GOTCHAINSAW);
|
1998-12-22 00:00:00 +00:00
|
|
|
sound = 2;
|
1998-04-07 00:00:00 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case SPR_LAUN:
|
|
|
|
if (!P_GiveWeapon (player, wp_missile, false) )
|
|
|
|
return;
|
1999-02-17 00:00:00 +00:00
|
|
|
PickupMessage (toucher, GOTLAUNCHER);
|
1998-12-22 00:00:00 +00:00
|
|
|
sound = 2;
|
1998-04-07 00:00:00 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case SPR_PLAS:
|
|
|
|
if (!P_GiveWeapon (player, wp_plasma, false) )
|
|
|
|
return;
|
1999-02-17 00:00:00 +00:00
|
|
|
PickupMessage (toucher, GOTPLASMA);
|
1998-12-22 00:00:00 +00:00
|
|
|
sound = 2;
|
1998-04-07 00:00:00 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case SPR_SHOT:
|
1999-02-17 00:00:00 +00:00
|
|
|
if (!P_GiveWeapon (player, wp_shotgun, special->flags & MF_DROPPED))
|
1998-04-07 00:00:00 +00:00
|
|
|
return;
|
1999-02-17 00:00:00 +00:00
|
|
|
PickupMessage (toucher, GOTSHOTGUN);
|
1998-12-22 00:00:00 +00:00
|
|
|
sound = 2;
|
1998-04-07 00:00:00 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case SPR_SGN2:
|
1999-02-17 00:00:00 +00:00
|
|
|
if (!P_GiveWeapon (player, wp_supershotgun, special->flags & MF_DROPPED))
|
1998-04-07 00:00:00 +00:00
|
|
|
return;
|
1999-02-17 00:00:00 +00:00
|
|
|
PickupMessage (toucher, GOTSHOTGUN2);
|
1998-12-22 00:00:00 +00:00
|
|
|
sound = 2;
|
1998-04-07 00:00:00 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
I_Error ("P_SpecialThing: Unknown gettable thing");
|
|
|
|
}
|
1999-02-17 00:00:00 +00:00
|
|
|
|
|
|
|
// [RH] Execute an attached special (if any)
|
|
|
|
if (special->special) {
|
|
|
|
LineSpecials[special->special] (NULL, toucher, special->args[0],
|
|
|
|
special->args[1], special->args[2], special->args[3], special->args[4]);
|
|
|
|
special->special = 0;
|
|
|
|
}
|
|
|
|
|
1998-04-07 00:00:00 +00:00
|
|
|
if (special->flags & MF_COUNTITEM) {
|
1998-04-07 00:00:00 +00:00
|
|
|
player->itemcount++;
|
1998-04-07 00:00:00 +00:00
|
|
|
level.found_items++;
|
|
|
|
}
|
1998-04-07 00:00:00 +00:00
|
|
|
P_RemoveMobj (special);
|
|
|
|
player->bonuscount += BONUSADD;
|
1999-02-21 00:00:00 +00:00
|
|
|
|
|
|
|
{
|
|
|
|
mobj_t *ent;
|
|
|
|
|
|
|
|
if (player->mo == players[consoleplayer].camera)
|
|
|
|
ent = NULL;
|
|
|
|
else
|
|
|
|
ent = player->mo;
|
|
|
|
|
|
|
|
switch (sound) {
|
|
|
|
case 0:
|
|
|
|
case 3:
|
|
|
|
S_Sound (ent, CHAN_ITEM, "misc/i_pkup", 1, ATTN_NORM);
|
|
|
|
break;
|
|
|
|
case 1:
|
|
|
|
S_Sound (ent, CHAN_ITEM, "misc/p_pkup", 1,
|
|
|
|
!ent ? ATTN_SURROUND : ATTN_NORM);
|
|
|
|
break;
|
|
|
|
case 2:
|
|
|
|
S_Sound (ent, CHAN_ITEM, "misc/w_pkup", 1, ATTN_NORM);
|
|
|
|
break;
|
|
|
|
}
|
1998-04-07 00:00:00 +00:00
|
|
|
}
|
1998-04-07 00:00:00 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
1998-12-22 00:00:00 +00:00
|
|
|
// [RH]
|
1999-02-17 00:00:00 +00:00
|
|
|
// SexMessage: Replace parts of strings with gender-specific pronouns
|
1998-12-22 00:00:00 +00:00
|
|
|
//
|
|
|
|
// The following expansions are performed:
|
|
|
|
// %g -> he/she/it
|
|
|
|
// %h -> him/her/it
|
|
|
|
// %p -> his/her/its
|
|
|
|
//
|
|
|
|
void SexMessage (const char *from, char *to, int gender)
|
|
|
|
{
|
|
|
|
static const char *genderstuff[3][3] = {
|
|
|
|
{ "he", "him", "his" },
|
|
|
|
{ "she", "her", "her" },
|
|
|
|
{ "it", "it", "its" }
|
|
|
|
};
|
|
|
|
static const int gendershift[3][3] = {
|
|
|
|
{ 2, 3, 3 },
|
|
|
|
{ 3, 3, 3 },
|
|
|
|
{ 2, 2, 3 }
|
|
|
|
};
|
|
|
|
int gendermsg;
|
|
|
|
|
|
|
|
do {
|
|
|
|
if (*from != '%') {
|
|
|
|
*to++ = *from;
|
|
|
|
} else {
|
|
|
|
switch (from[1]) {
|
|
|
|
case 'g': gendermsg = 0; break;
|
|
|
|
case 'h': gendermsg = 1; break;
|
|
|
|
case 'p': gendermsg = 2; break;
|
|
|
|
default: gendermsg = -1; break;
|
|
|
|
}
|
|
|
|
if (gendermsg < 0) {
|
|
|
|
*to++ = '%';
|
|
|
|
} else {
|
|
|
|
strcpy (to, genderstuff[gender][gendermsg]);
|
|
|
|
to += gendershift[gender][gendermsg];
|
|
|
|
from++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} while (*from++);
|
|
|
|
}
|
|
|
|
|
1998-07-14 00:00:00 +00:00
|
|
|
// [RH]
|
|
|
|
// ClientObituary: Show a message when a player dies
|
|
|
|
//
|
|
|
|
void ClientObituary (mobj_t *self, mobj_t *inflictor, mobj_t *attacker)
|
|
|
|
{
|
1998-12-22 00:00:00 +00:00
|
|
|
int mod;
|
|
|
|
char *message;
|
|
|
|
char gendermessage[1024];
|
|
|
|
BOOL friendly;
|
|
|
|
int gender;
|
|
|
|
|
|
|
|
if (!self->player)
|
|
|
|
return;
|
|
|
|
|
|
|
|
gender = self->player->userinfo.gender;
|
|
|
|
|
1999-02-17 00:00:00 +00:00
|
|
|
// Treat voodoo dolls as unknown deaths
|
|
|
|
if (inflictor && inflictor->player == self->player)
|
|
|
|
MeansOfDeath = MOD_UNKNOWN;
|
|
|
|
|
1998-12-22 00:00:00 +00:00
|
|
|
if (netgame && !deathmatch->value)
|
|
|
|
MeansOfDeath |= MOD_FRIENDLY_FIRE;
|
1998-07-14 00:00:00 +00:00
|
|
|
|
1998-12-22 00:00:00 +00:00
|
|
|
friendly = MeansOfDeath & MOD_FRIENDLY_FIRE;
|
|
|
|
mod = MeansOfDeath & ~MOD_FRIENDLY_FIRE;
|
|
|
|
message = NULL;
|
|
|
|
|
|
|
|
switch (mod) {
|
|
|
|
case MOD_SUICIDE:
|
|
|
|
message = OB_SUICIDE;
|
|
|
|
break;
|
|
|
|
case MOD_FALLING:
|
|
|
|
message = OB_FALLING;
|
|
|
|
break;
|
|
|
|
case MOD_CRUSH:
|
|
|
|
message = OB_CRUSH;
|
|
|
|
break;
|
|
|
|
case MOD_EXIT:
|
|
|
|
message = OB_EXIT;
|
|
|
|
break;
|
|
|
|
case MOD_WATER:
|
|
|
|
message = OB_WATER;
|
|
|
|
break;
|
|
|
|
case MOD_SLIME:
|
|
|
|
message = OB_SLIME;
|
|
|
|
break;
|
|
|
|
case MOD_LAVA:
|
|
|
|
message = OB_LAVA;
|
|
|
|
break;
|
|
|
|
case MOD_BARREL:
|
|
|
|
message = OB_BARREL;
|
|
|
|
break;
|
|
|
|
case MOD_SPLASH:
|
|
|
|
message = OB_SPLASH;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (attacker && !message) {
|
|
|
|
if (attacker == self) {
|
|
|
|
switch (mod) {
|
|
|
|
case MOD_R_SPLASH:
|
|
|
|
message = OB_R_SPLASH;
|
|
|
|
break;
|
|
|
|
case MOD_ROCKET:
|
|
|
|
message = OB_ROCKET;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
message = OB_KILLEDSELF;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
} else if (!attacker->player) {
|
|
|
|
switch (attacker->type) {
|
|
|
|
case MT_STEALTHBABY:
|
|
|
|
message = OB_STEALTHBABY;
|
|
|
|
break;
|
|
|
|
case MT_STEALTHVILE:
|
|
|
|
message = OB_STEALTHVILE;
|
|
|
|
break;
|
|
|
|
case MT_STEALTHBRUISER:
|
|
|
|
message = OB_STEALTHBARON;
|
|
|
|
break;
|
|
|
|
case MT_STEALTHHEAD:
|
|
|
|
message = OB_STEALTHCACO;
|
|
|
|
break;
|
|
|
|
case MT_STEALTHCHAINGUY:
|
|
|
|
message = OB_STEALTHCHAINGUY;
|
|
|
|
break;
|
|
|
|
case MT_STEALTHSERGEANT:
|
|
|
|
message = OB_STEALTHDEMON;
|
|
|
|
break;
|
|
|
|
case MT_STEALTHKNIGHT:
|
|
|
|
message = OB_STEALTHKNIGHT;
|
|
|
|
break;
|
|
|
|
case MT_STEALTHIMP:
|
|
|
|
message = OB_STEALTHIMP;
|
|
|
|
break;
|
|
|
|
case MT_STEALTHFATSO:
|
|
|
|
message = OB_STEALTHFATSO;
|
|
|
|
break;
|
|
|
|
case MT_STEALTHUNDEAD:
|
|
|
|
message = OB_STEALTHUNDEAD;
|
|
|
|
break;
|
|
|
|
case MT_STEALTHSHOTGUY:
|
|
|
|
message = OB_STEALTHSHOTGUY;
|
|
|
|
break;
|
|
|
|
case MT_STEALTHZOMBIE:
|
|
|
|
message = OB_STEALTHZOMBIE;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
if (mod == MOD_HIT) {
|
|
|
|
switch (attacker->type) {
|
|
|
|
case MT_UNDEAD:
|
|
|
|
message = OB_UNDEADHIT;
|
|
|
|
break;
|
|
|
|
case MT_TROOP:
|
|
|
|
message = OB_IMPHIT;
|
|
|
|
break;
|
|
|
|
case MT_HEAD:
|
|
|
|
message = OB_CACOHIT;
|
|
|
|
break;
|
|
|
|
case MT_SERGEANT:
|
|
|
|
message = OB_DEMONHIT;
|
|
|
|
break;
|
|
|
|
case MT_SHADOWS:
|
|
|
|
message = OB_SPECTREHIT;
|
|
|
|
break;
|
|
|
|
case MT_BRUISER:
|
|
|
|
message = OB_BARONHIT;
|
|
|
|
break;
|
|
|
|
case MT_KNIGHT:
|
|
|
|
message = OB_KNIGHTHIT;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
switch (attacker->type) {
|
|
|
|
case MT_POSSESSED:
|
|
|
|
message = OB_ZOMBIE;
|
|
|
|
break;
|
|
|
|
case MT_SHOTGUY:
|
|
|
|
message = OB_SHOTGUY;
|
|
|
|
break;
|
|
|
|
case MT_VILE:
|
|
|
|
message = OB_VILE;
|
|
|
|
break;
|
|
|
|
case MT_UNDEAD:
|
|
|
|
message = OB_UNDEAD;
|
|
|
|
break;
|
|
|
|
case MT_FATSO:
|
|
|
|
message = OB_FATSO;
|
|
|
|
break;
|
|
|
|
case MT_CHAINGUY:
|
|
|
|
message = OB_CHAINGUY;
|
|
|
|
break;
|
|
|
|
case MT_SKULL:
|
|
|
|
message = OB_SKULL;
|
|
|
|
break;
|
|
|
|
case MT_TROOP:
|
|
|
|
message = OB_IMP;
|
|
|
|
break;
|
|
|
|
case MT_HEAD:
|
|
|
|
message = OB_CACO;
|
|
|
|
break;
|
|
|
|
case MT_BRUISER:
|
|
|
|
message = OB_BARON;
|
|
|
|
break;
|
|
|
|
case MT_KNIGHT:
|
|
|
|
message = OB_KNIGHT;
|
|
|
|
break;
|
|
|
|
case MT_SPIDER:
|
|
|
|
message = OB_SPIDER;
|
|
|
|
break;
|
|
|
|
case MT_BABY:
|
|
|
|
message = OB_BABY;
|
|
|
|
break;
|
|
|
|
case MT_CYBORG:
|
|
|
|
message = OB_CYBORG;
|
|
|
|
break;
|
|
|
|
case MT_WOLFSS:
|
|
|
|
message = OB_WOLFSS;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
1998-07-14 00:00:00 +00:00
|
|
|
}
|
1998-12-22 00:00:00 +00:00
|
|
|
}
|
|
|
|
break;
|
1998-07-14 00:00:00 +00:00
|
|
|
}
|
|
|
|
}
|
1998-12-22 00:00:00 +00:00
|
|
|
}
|
1998-07-14 00:00:00 +00:00
|
|
|
|
1998-12-22 00:00:00 +00:00
|
|
|
if (message) {
|
|
|
|
SexMessage (message, gendermessage, gender);
|
1999-02-17 00:00:00 +00:00
|
|
|
Printf (PRINT_MEDIUM, "%s %s.\n", self->player->userinfo.netname, gendermessage);
|
1998-12-22 00:00:00 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (attacker && attacker->player) {
|
|
|
|
if (friendly) {
|
|
|
|
int rnum = P_Random (pr_obituary);
|
1998-07-14 00:00:00 +00:00
|
|
|
|
1998-12-22 00:00:00 +00:00
|
|
|
attacker->player->fragcount -= 2;
|
|
|
|
attacker->player->frags[attacker->player-players]++;
|
|
|
|
self = attacker;
|
1999-02-17 00:00:00 +00:00
|
|
|
gender = self->player->userinfo.gender;
|
1998-12-22 00:00:00 +00:00
|
|
|
|
|
|
|
if (rnum < 64)
|
|
|
|
message = OB_FRIENDLY1;
|
|
|
|
else if (rnum < 128)
|
|
|
|
message = OB_FRIENDLY2;
|
|
|
|
else if (rnum < 192)
|
|
|
|
message = OB_FRIENDLY3;
|
|
|
|
else
|
|
|
|
message = OB_FRIENDLY4;
|
|
|
|
} else {
|
1998-07-14 00:00:00 +00:00
|
|
|
switch (mod) {
|
|
|
|
case MOD_FIST:
|
1998-12-22 00:00:00 +00:00
|
|
|
message = OB_MPFIST;
|
1998-07-14 00:00:00 +00:00
|
|
|
break;
|
|
|
|
case MOD_CHAINSAW:
|
1998-12-22 00:00:00 +00:00
|
|
|
message = OB_MPCHAINSAW;
|
1998-07-14 00:00:00 +00:00
|
|
|
break;
|
|
|
|
case MOD_PISTOL:
|
1998-12-22 00:00:00 +00:00
|
|
|
message = OB_MPPISTOL;
|
1998-07-14 00:00:00 +00:00
|
|
|
break;
|
|
|
|
case MOD_SHOTGUN:
|
1998-12-22 00:00:00 +00:00
|
|
|
message = OB_MPSHOTGUN;
|
1998-07-14 00:00:00 +00:00
|
|
|
break;
|
|
|
|
case MOD_SSHOTGUN:
|
1998-12-22 00:00:00 +00:00
|
|
|
message = OB_MPSSHOTGUN;
|
1998-07-14 00:00:00 +00:00
|
|
|
break;
|
|
|
|
case MOD_CHAINGUN:
|
1998-12-22 00:00:00 +00:00
|
|
|
message = OB_MPCHAINGUN;
|
1998-07-14 00:00:00 +00:00
|
|
|
break;
|
|
|
|
case MOD_ROCKET:
|
1998-12-22 00:00:00 +00:00
|
|
|
message = OB_MPROCKET;
|
1998-07-14 00:00:00 +00:00
|
|
|
break;
|
|
|
|
case MOD_R_SPLASH:
|
1998-12-22 00:00:00 +00:00
|
|
|
message = OB_MPR_SPLASH;
|
1998-07-14 00:00:00 +00:00
|
|
|
break;
|
|
|
|
case MOD_PLASMARIFLE:
|
1998-12-22 00:00:00 +00:00
|
|
|
message = OB_MPPLASMARIFLE;
|
1998-07-14 00:00:00 +00:00
|
|
|
break;
|
|
|
|
case MOD_BFG_BOOM:
|
1998-12-22 00:00:00 +00:00
|
|
|
message = OB_MPBFG_BOOM;
|
1998-07-14 00:00:00 +00:00
|
|
|
break;
|
|
|
|
case MOD_BFG_SPLASH:
|
1998-12-22 00:00:00 +00:00
|
|
|
message = OB_MPBFG_SPLASH;
|
1998-07-14 00:00:00 +00:00
|
|
|
break;
|
|
|
|
case MOD_TELEFRAG:
|
1998-12-22 00:00:00 +00:00
|
|
|
message = OB_MPTELEFRAG;
|
1998-07-14 00:00:00 +00:00
|
|
|
break;
|
1999-02-17 00:00:00 +00:00
|
|
|
case MOD_RAILGUN:
|
|
|
|
message = OB_RAILGUN;
|
|
|
|
break;
|
1998-07-14 00:00:00 +00:00
|
|
|
}
|
|
|
|
}
|
1998-12-22 00:00:00 +00:00
|
|
|
}
|
1998-07-14 00:00:00 +00:00
|
|
|
|
1998-12-22 00:00:00 +00:00
|
|
|
if (message) {
|
|
|
|
char work[256];
|
|
|
|
|
|
|
|
SexMessage (message, gendermessage, gender);
|
|
|
|
sprintf (work, "%%s %s\n", gendermessage);
|
1999-02-17 00:00:00 +00:00
|
|
|
Printf (PRINT_MEDIUM, work, self->player->userinfo.netname,
|
1998-12-22 00:00:00 +00:00
|
|
|
attacker->player->userinfo.netname);
|
|
|
|
return;
|
1998-07-14 00:00:00 +00:00
|
|
|
}
|
|
|
|
|
1998-12-22 00:00:00 +00:00
|
|
|
SexMessage (OB_DEFAULT, gendermessage, gender);
|
1999-02-17 00:00:00 +00:00
|
|
|
Printf (PRINT_MEDIUM, "%s %s.\n", self->player->userinfo.netname, gendermessage);
|
1998-07-14 00:00:00 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
1998-04-07 00:00:00 +00:00
|
|
|
//
|
|
|
|
// KillMobj
|
|
|
|
//
|
1998-07-14 00:00:00 +00:00
|
|
|
extern cvar_t *fraglimit;
|
|
|
|
|
|
|
|
void P_KillMobj (mobj_t *source, mobj_t *target, mobj_t *inflictor)
|
1998-04-07 00:00:00 +00:00
|
|
|
{
|
|
|
|
mobjtype_t item;
|
|
|
|
mobj_t* mo;
|
|
|
|
|
|
|
|
target->flags &= ~(MF_SHOOTABLE|MF_FLOAT|MF_SKULLFLY);
|
|
|
|
|
|
|
|
if (target->type != MT_SKULL)
|
|
|
|
target->flags &= ~MF_NOGRAVITY;
|
|
|
|
|
|
|
|
target->flags |= MF_CORPSE|MF_DROPOFF;
|
1999-02-17 00:00:00 +00:00
|
|
|
target->flags2 &= ~MF2_PASSMOBJ;
|
1998-04-07 00:00:00 +00:00
|
|
|
target->height >>= 2;
|
|
|
|
|
1998-12-22 00:00:00 +00:00
|
|
|
// [RH] If the thing has a special, execute and remove it
|
|
|
|
// Note that the thing that killed it is considered
|
|
|
|
// the activator of the script.
|
1999-02-17 00:00:00 +00:00
|
|
|
if ((target->flags & MF_COUNTKILL) && target->special) {
|
1998-12-22 00:00:00 +00:00
|
|
|
LineSpecials[target->special] (NULL, source, target->args[0],
|
|
|
|
target->args[1], target->args[2],
|
|
|
|
target->args[3], target->args[4]);
|
|
|
|
target->special = 0;
|
|
|
|
}
|
1999-02-17 00:00:00 +00:00
|
|
|
// [RH] Also set the thing's tid to 0. [why?]
|
1998-12-22 00:00:00 +00:00
|
|
|
target->tid = 0;
|
|
|
|
|
1998-04-07 00:00:00 +00:00
|
|
|
if (source && source->player)
|
|
|
|
{
|
|
|
|
// count for intermission
|
1998-04-07 00:00:00 +00:00
|
|
|
if (target->flags & MF_COUNTKILL) {
|
|
|
|
source->player->killcount++;
|
|
|
|
level.killed_monsters++;
|
|
|
|
}
|
1998-04-07 00:00:00 +00:00
|
|
|
|
1998-12-22 00:00:00 +00:00
|
|
|
// Don't count any frags at level start, because they're just telefrags
|
|
|
|
// resulting from insufficient deathmatch starts, and it wouldn't be
|
|
|
|
// fair to count them toward a player's score.
|
|
|
|
if (target->player && level.time) {
|
1998-04-07 00:00:00 +00:00
|
|
|
source->player->frags[target->player-players]++;
|
1998-07-14 00:00:00 +00:00
|
|
|
if (target->player == source->player) // [RH] Cumulative frag count
|
|
|
|
source->player->fragcount--;
|
|
|
|
else
|
|
|
|
source->player->fragcount++;
|
|
|
|
|
|
|
|
// [RH] Implement fraglimit
|
|
|
|
if (deathmatch->value && fraglimit->value &&
|
|
|
|
(int)fraglimit->value == source->player->fragcount) {
|
1999-02-17 00:00:00 +00:00
|
|
|
Printf (PRINT_HIGH, "Fraglimit hit.\n");
|
1998-12-22 00:00:00 +00:00
|
|
|
G_ExitLevel (0);
|
1998-07-14 00:00:00 +00:00
|
|
|
}
|
|
|
|
}
|
1998-04-07 00:00:00 +00:00
|
|
|
}
|
|
|
|
else if (!netgame && (target->flags & MF_COUNTKILL) )
|
|
|
|
{
|
|
|
|
// count all monster deaths,
|
|
|
|
// even those caused by other monsters
|
|
|
|
players[0].killcount++;
|
1998-04-07 00:00:00 +00:00
|
|
|
level.killed_monsters++;
|
1998-04-07 00:00:00 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (target->player)
|
|
|
|
{
|
1998-07-14 00:00:00 +00:00
|
|
|
// [RH] Force a delay between death and respawn
|
1999-02-17 00:00:00 +00:00
|
|
|
target->player->respawn_time = level.time + TICRATE;
|
1998-07-14 00:00:00 +00:00
|
|
|
|
1998-04-07 00:00:00 +00:00
|
|
|
// count environment kills against you
|
1998-07-14 00:00:00 +00:00
|
|
|
if (!source) {
|
1998-04-07 00:00:00 +00:00
|
|
|
target->player->frags[target->player-players]++;
|
1998-07-14 00:00:00 +00:00
|
|
|
target->player->fragcount--; // [RH] Cumulative frag count
|
|
|
|
}
|
1998-04-07 00:00:00 +00:00
|
|
|
|
|
|
|
target->flags &= ~MF_SOLID;
|
|
|
|
target->player->playerstate = PST_DEAD;
|
|
|
|
P_DropWeapon (target->player);
|
|
|
|
|
1999-02-21 00:00:00 +00:00
|
|
|
if (target == players[consoleplayer].camera && automapactive)
|
1998-04-07 00:00:00 +00:00
|
|
|
{
|
1999-02-17 00:00:00 +00:00
|
|
|
// don't die in auto map, switch view prior to dying
|
1998-04-07 00:00:00 +00:00
|
|
|
AM_Stop ();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (target->health < -target->info->spawnhealth
|
|
|
|
&& target->info->xdeathstate)
|
|
|
|
{
|
|
|
|
P_SetMobjState (target, target->info->xdeathstate);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
P_SetMobjState (target, target->info->deathstate);
|
1998-07-14 00:00:00 +00:00
|
|
|
target->tics -= P_Random (pr_killmobj) & 3;
|
1998-04-07 00:00:00 +00:00
|
|
|
|
|
|
|
if (target->tics < 1)
|
|
|
|
target->tics = 1;
|
|
|
|
|
1998-07-14 00:00:00 +00:00
|
|
|
// [RH] Death messages
|
1999-02-17 00:00:00 +00:00
|
|
|
if (target->player && level.time)
|
1998-07-14 00:00:00 +00:00
|
|
|
ClientObituary (target, inflictor, source);
|
1998-04-07 00:00:00 +00:00
|
|
|
|
|
|
|
// Drop stuff.
|
|
|
|
// This determines the kind of object spawned
|
|
|
|
// during the death frame of a thing.
|
|
|
|
switch (target->type)
|
|
|
|
{
|
|
|
|
case MT_WOLFSS:
|
|
|
|
case MT_POSSESSED:
|
|
|
|
item = MT_CLIP;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case MT_SHOTGUY:
|
|
|
|
item = MT_SHOTGUN;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case MT_CHAINGUY:
|
|
|
|
item = MT_CHAINGUN;
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
1999-02-17 00:00:00 +00:00
|
|
|
mo = P_SpawnMobj (target->x, target->y, ONFLOORZ, item);
|
1998-04-07 00:00:00 +00:00
|
|
|
mo->flags |= MF_DROPPED; // special versions of items
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
// P_DamageMobj
|
|
|
|
// Damages both enemies and players
|
|
|
|
// "inflictor" is the thing that caused the damage
|
|
|
|
// creature or missile, can be NULL (slime, etc)
|
|
|
|
// "source" is the thing to target after taking damage
|
|
|
|
// creature or NULL
|
|
|
|
// Source and inflictor are the same for melee attacks.
|
|
|
|
// Source can be NULL for slime, barrel explosions
|
|
|
|
// and other environmental stuff.
|
|
|
|
//
|
1998-07-14 00:00:00 +00:00
|
|
|
int MeansOfDeath;
|
|
|
|
|
|
|
|
void P_DamageMobj (mobj_t *target, mobj_t *inflictor, mobj_t *source, int damage, int mod)
|
1998-04-07 00:00:00 +00:00
|
|
|
{
|
|
|
|
unsigned ang;
|
|
|
|
int saved;
|
|
|
|
player_t* player;
|
|
|
|
fixed_t thrust;
|
|
|
|
int temp;
|
|
|
|
|
|
|
|
if ( !(target->flags & MF_SHOOTABLE) )
|
|
|
|
return; // shouldn't happen...
|
|
|
|
|
|
|
|
if (target->health <= 0)
|
|
|
|
return;
|
|
|
|
|
1998-07-14 00:00:00 +00:00
|
|
|
MeansOfDeath = mod;
|
|
|
|
|
1998-04-07 00:00:00 +00:00
|
|
|
// [RH] Andy Baker's Stealth monsters
|
|
|
|
if (target->flags & MF_STEALTH)
|
|
|
|
{
|
|
|
|
P_BecomeVisible(target);
|
|
|
|
}
|
|
|
|
|
1998-04-07 00:00:00 +00:00
|
|
|
if ( target->flags & MF_SKULLFLY )
|
|
|
|
{
|
|
|
|
target->momx = target->momy = target->momz = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
player = target->player;
|
|
|
|
if (player && gameskill->value == sk_baby)
|
|
|
|
damage >>= 1; // take half damage in trainer mode
|
|
|
|
|
|
|
|
// Some close combat weapons should not
|
|
|
|
// inflict thrust and push the victim out of reach,
|
|
|
|
// thus kick away unless using the chainsaw.
|
|
|
|
if (inflictor
|
|
|
|
&& !(target->flags & MF_NOCLIP)
|
|
|
|
&& (!source
|
|
|
|
|| !source->player
|
|
|
|
|| source->player->readyweapon != wp_chainsaw))
|
|
|
|
{
|
|
|
|
ang = R_PointToAngle2 ( inflictor->x,
|
|
|
|
inflictor->y,
|
|
|
|
target->x,
|
|
|
|
target->y);
|
|
|
|
|
|
|
|
thrust = damage*(FRACUNIT>>3)*100/target->info->mass;
|
|
|
|
|
|
|
|
// make fall forwards sometimes
|
|
|
|
if ( damage < 40
|
|
|
|
&& damage > target->health
|
|
|
|
&& target->z - inflictor->z > 64*FRACUNIT
|
1998-07-14 00:00:00 +00:00
|
|
|
&& (P_Random (pr_damagemobj)&1) )
|
1998-04-07 00:00:00 +00:00
|
|
|
{
|
|
|
|
ang += ANG180;
|
|
|
|
thrust *= 4;
|
|
|
|
}
|
1998-12-22 00:00:00 +00:00
|
|
|
|
1998-04-07 00:00:00 +00:00
|
|
|
ang >>= ANGLETOFINESHIFT;
|
|
|
|
target->momx += FixedMul (thrust, finecosine[ang]);
|
|
|
|
target->momy += FixedMul (thrust, finesine[ang]);
|
|
|
|
}
|
1998-12-22 00:00:00 +00:00
|
|
|
|
1998-04-07 00:00:00 +00:00
|
|
|
// player specific
|
|
|
|
if (player)
|
|
|
|
{
|
|
|
|
// end of game hell hack
|
1999-02-17 00:00:00 +00:00
|
|
|
if ((target->subsector->sector->special & 255) == dDamage_End
|
1998-04-07 00:00:00 +00:00
|
|
|
&& damage >= target->health)
|
|
|
|
{
|
|
|
|
damage = target->health - 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Below certain threshold,
|
|
|
|
// ignore damage in GOD mode, or with INVUL power.
|
|
|
|
if ( damage < 1000
|
|
|
|
&& ( (player->cheats&CF_GODMODE)
|
|
|
|
|| player->powers[pw_invulnerability] ) )
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
1998-12-22 00:00:00 +00:00
|
|
|
|
|
|
|
// [RH] Avoid friendly fire if enabled
|
|
|
|
if (teamplay->value && source && source->player &&
|
|
|
|
source->player->userinfo.team[0] &&
|
|
|
|
!stricmp (player->userinfo.team, source->player->userinfo.team)) {
|
|
|
|
if (dmflags & DF_NO_FRIENDLY_FIRE)
|
|
|
|
return;
|
|
|
|
else
|
|
|
|
MeansOfDeath |= MOD_FRIENDLY_FIRE;
|
|
|
|
}
|
|
|
|
|
1998-04-07 00:00:00 +00:00
|
|
|
if (player->armortype)
|
|
|
|
{
|
1998-12-22 00:00:00 +00:00
|
|
|
if (player->armortype == deh.GreenAC)
|
1998-04-07 00:00:00 +00:00
|
|
|
saved = damage/3;
|
|
|
|
else
|
|
|
|
saved = damage/2;
|
|
|
|
|
|
|
|
if (player->armorpoints <= saved)
|
|
|
|
{
|
|
|
|
// armor is used up
|
|
|
|
saved = player->armorpoints;
|
|
|
|
player->armortype = 0;
|
|
|
|
}
|
|
|
|
player->armorpoints -= saved;
|
|
|
|
damage -= saved;
|
|
|
|
}
|
|
|
|
player->health -= damage; // mirror mobj health here for Dave
|
|
|
|
if (player->health < 0)
|
|
|
|
player->health = 0;
|
|
|
|
|
|
|
|
player->attacker = source;
|
|
|
|
player->damagecount += damage; // add damage after armor / invuln
|
|
|
|
|
|
|
|
if (player->damagecount > 100)
|
|
|
|
player->damagecount = 100; // teleport stomp does 10k points...
|
|
|
|
|
|
|
|
temp = damage < 100 ? damage : 100;
|
|
|
|
|
|
|
|
if (player == &players[consoleplayer])
|
|
|
|
I_Tactile (40,10,40+temp*2);
|
|
|
|
}
|
|
|
|
|
1998-12-22 00:00:00 +00:00
|
|
|
// do the damage
|
|
|
|
// [RH] Only if not immune
|
1999-02-17 00:00:00 +00:00
|
|
|
if (!(target->flags2 & (MF2_INVULNERABLE | MF2_DORMANT))) {
|
1998-12-22 00:00:00 +00:00
|
|
|
target->health -= damage;
|
|
|
|
if (target->health <= 0)
|
|
|
|
{
|
|
|
|
P_KillMobj (source, target, inflictor);
|
|
|
|
return;
|
|
|
|
}
|
1998-04-07 00:00:00 +00:00
|
|
|
}
|
|
|
|
|
1998-12-22 00:00:00 +00:00
|
|
|
if (!(target->flags2 & MF2_DORMANT)) {
|
|
|
|
// [RH] Only react if not dormant
|
|
|
|
if ( (P_Random (pr_damagemobj) < target->info->painchance)
|
|
|
|
&& !(target->flags&MF_SKULLFLY) )
|
|
|
|
{
|
|
|
|
target->flags |= MF_JUSTHIT; // fight back!
|
|
|
|
|
|
|
|
P_SetMobjState (target, target->info->painstate);
|
|
|
|
}
|
|
|
|
|
|
|
|
target->reactiontime = 0; // we're awake now...
|
1998-04-07 00:00:00 +00:00
|
|
|
|
1998-12-22 00:00:00 +00:00
|
|
|
if ( (!target->threshold || target->type == MT_VILE)
|
|
|
|
&& source && source != target
|
|
|
|
&& source->type != MT_VILE)
|
|
|
|
{
|
|
|
|
// if not intent on another player, chase after this one
|
|
|
|
|
|
|
|
// killough 2/15/98: remember last enemy, to prevent
|
|
|
|
// sleeping early; 2/21/98: Place priority on players
|
|
|
|
|
|
|
|
if (!target->lastenemy || !target->lastenemy->player ||
|
|
|
|
target->lastenemy->health <= 0)
|
|
|
|
target->lastenemy = target->target; // remember last enemy - killough
|
|
|
|
|
|
|
|
target->target = source;
|
|
|
|
target->threshold = BASETHRESHOLD;
|
|
|
|
if (target->state == &states[target->info->spawnstate]
|
|
|
|
&& target->info->seestate != S_NULL)
|
|
|
|
P_SetMobjState (target, target->info->seestate);
|
|
|
|
}
|
1998-04-07 00:00:00 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
1998-07-14 00:00:00 +00:00
|
|
|
BOOL CheckCheatmode (void);
|
|
|
|
|
1998-04-07 00:00:00 +00:00
|
|
|
void Cmd_Kill (player_t *plyr, int argc, char **argv)
|
|
|
|
{
|
|
|
|
if (argc > 1 && !stricmp (argv[1], "monsters")) {
|
|
|
|
// Kill all the monsters
|
1998-07-14 00:00:00 +00:00
|
|
|
if (CheckCheatmode ())
|
|
|
|
return;
|
1998-04-07 00:00:00 +00:00
|
|
|
|
1998-07-14 00:00:00 +00:00
|
|
|
Net_WriteByte (DEM_GENERICCHEAT);
|
|
|
|
Net_WriteByte (CHT_MASSACRE);
|
1998-04-07 00:00:00 +00:00
|
|
|
} else {
|
|
|
|
// Kill the player
|
1998-07-14 00:00:00 +00:00
|
|
|
Net_WriteByte (DEM_SUICIDE);
|
1998-04-07 00:00:00 +00:00
|
|
|
}
|
|
|
|
C_HideConsole ();
|
|
|
|
}
|