mirror of
https://github.com/ZDoom/qzdoom-gpl.git
synced 2024-11-15 16:51:31 +00:00
- Added support for damage-specific player pain sounds.
- Removed the constraint that all $playerreserve SNDINFO commands must come before the other $player commands. - Fixed: TArray::Reserve did not construct its newly allocated entries. - Changed the damage type for drowning from 'Water' to 'Drowning'. SVN r466 (trunk)
This commit is contained in:
parent
ba5e77e021
commit
72c93b479e
13 changed files with 233 additions and 46 deletions
|
@ -1,4 +1,9 @@
|
|||
January 27, 2007
|
||||
- Added support for damage-specific player pain sounds.
|
||||
- Removed the constraint that all $playerreserve SNDINFO commands must come
|
||||
before the other $player commands.
|
||||
- Fixed: TArray::Reserve did not construct its newly allocated entries.
|
||||
- Changed the damage type for drowning from 'Water' to 'Drowning'.
|
||||
- Fixed: Since FMemLump is now implemented on top of FString, it never
|
||||
contains a NULL point, so the GetMem() method should fake it by
|
||||
returning NULL when the string is empty. Reverted p_xlat.cpp to its
|
||||
|
|
|
@ -260,6 +260,8 @@ public:
|
|||
|
||||
WORD accuracy, stamina; // [RH] Strife stats
|
||||
|
||||
FName LastDamageType; // [RH] For damage-specific pain and death sounds
|
||||
|
||||
//Added by MC:
|
||||
angle_t savedyaw;
|
||||
int savedpitch;
|
||||
|
|
|
@ -124,7 +124,7 @@ bool ABasicArmor::HandlePickup (AInventory *item)
|
|||
|
||||
void ABasicArmor::AbsorbDamage (int damage, FName damageType, int &newdamage)
|
||||
{
|
||||
if (damageType != NAME_Water)
|
||||
if (damageType != NAME_Drowning)
|
||||
{
|
||||
int saved = FixedMul (damage, SavePercent);
|
||||
if (Amount < saved)
|
||||
|
@ -440,7 +440,7 @@ bool AHexenArmor::AddArmorToSlot (AActor *actor, int slot, int amount)
|
|||
|
||||
void AHexenArmor::AbsorbDamage (int damage, FName damageType, int &newdamage)
|
||||
{
|
||||
if (damageType != NAME_Water)
|
||||
if (damageType != NAME_Drowning)
|
||||
{
|
||||
fixed_t savedPercent = Slots[0] + Slots[1] + Slots[2] + Slots[3] + Slots[4];
|
||||
|
||||
|
|
|
@ -722,7 +722,7 @@ END_DEFAULTS
|
|||
|
||||
void APowerIronFeet::AbsorbDamage (int damage, FName damageType, int &newdamage)
|
||||
{
|
||||
if (damageType == NAME_Water)
|
||||
if (damageType == NAME_Drowning)
|
||||
{
|
||||
newdamage = 0;
|
||||
if (Owner->player != NULL)
|
||||
|
|
|
@ -171,7 +171,7 @@ xx(Drop)
|
|||
//xx(Fire) already defined above
|
||||
//xx(Ice)
|
||||
//xx(Disintegrate)
|
||||
//xx(Water)
|
||||
xx(Drowning)
|
||||
xx(Slime)
|
||||
//xx(Crush)
|
||||
xx(Telefrag)
|
||||
|
|
|
@ -2521,18 +2521,39 @@ void A_Pain (AActor *actor)
|
|||
// [RH] Vary player pain sounds depending on health (ala Quake2)
|
||||
if (actor->player && actor->player->morphTics == 0)
|
||||
{
|
||||
const char *painchoice;
|
||||
const char *pain_amount;
|
||||
int sfx_id = 0;
|
||||
|
||||
if (actor->health < 25)
|
||||
painchoice = "*pain25";
|
||||
pain_amount = "*pain25";
|
||||
else if (actor->health < 50)
|
||||
painchoice = "*pain50";
|
||||
pain_amount = "*pain50";
|
||||
else if (actor->health < 75)
|
||||
painchoice = "*pain75";
|
||||
pain_amount = "*pain75";
|
||||
else
|
||||
painchoice = "*pain100";
|
||||
pain_amount = "*pain100";
|
||||
|
||||
S_Sound (actor, CHAN_VOICE, painchoice, 1, ATTN_NORM);
|
||||
// Try for damage-specific sounds first.
|
||||
if (actor->player->LastDamageType != NAME_None)
|
||||
{
|
||||
FString pain_sound = pain_amount;
|
||||
pain_sound += '-';
|
||||
pain_sound += actor->player->LastDamageType;
|
||||
sfx_id = S_FindSound (pain_sound);
|
||||
if (sfx_id == 0)
|
||||
{
|
||||
// Try again without a specific pain amount.
|
||||
pain_sound = "*pain-";
|
||||
pain_sound += actor->player->LastDamageType;
|
||||
sfx_id = S_FindSound (pain_sound);
|
||||
}
|
||||
}
|
||||
if (sfx_id == 0)
|
||||
{
|
||||
sfx_id = S_FindSound (pain_amount);
|
||||
}
|
||||
|
||||
S_SoundID (actor, CHAN_VOICE, sfx_id, 1, ATTN_NORM);
|
||||
}
|
||||
else if (actor->PainSound)
|
||||
{
|
||||
|
|
|
@ -221,7 +221,7 @@ void ClientObituary (AActor *self, AActor *inflictor, AActor *attacker)
|
|||
case NAME_Falling: messagename = "OB_FALLING"; break;
|
||||
case NAME_Crush: messagename = "OB_CRUSH"; break;
|
||||
case NAME_Exit: messagename = "OB_EXIT"; break;
|
||||
case NAME_Water: messagename = "OB_WATER"; break;
|
||||
case NAME_Drowning: messagename = "OB_WATER"; break;
|
||||
case NAME_Slime: messagename = "OB_SLIME"; break;
|
||||
case NAME_Fire: if (attacker == NULL) messagename = "OB_LAVA"; break;
|
||||
}
|
||||
|
@ -1024,6 +1024,7 @@ void P_DamageMobj (AActor *target, AActor *inflictor, AActor *source, int damage
|
|||
{
|
||||
player->health = 0;
|
||||
}
|
||||
player->LastDamageType = mod;
|
||||
player->attacker = source;
|
||||
player->damagecount += damage; // add damage after armor / invuln
|
||||
if (player->damagecount > 100)
|
||||
|
|
|
@ -69,7 +69,7 @@ FName MODtoDamageType (int mod)
|
|||
{
|
||||
default: return NAME_None; break;
|
||||
case 9: return NAME_BFGSplash; break;
|
||||
case 12: return NAME_Water; break;
|
||||
case 12: return NAME_Drowning; break;
|
||||
case 13: return NAME_Slime; break;
|
||||
case 14: return NAME_Fire; break;
|
||||
case 15: return NAME_Crush; break;
|
||||
|
|
|
@ -2132,7 +2132,7 @@ void P_PlayerThink (player_t *player)
|
|||
}
|
||||
else if (player->air_finished <= level.time && !(level.time & 31))
|
||||
{
|
||||
P_DamageMobj (player->mo, NULL, NULL, 2 + 2*((level.time-player->air_finished)/TICRATE), NAME_Water);
|
||||
P_DamageMobj (player->mo, NULL, NULL, 2 + 2*((level.time-player->air_finished)/TICRATE), NAME_Drowning);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
** Translate old Doom format maps to the Hexen format
|
||||
**
|
||||
**---------------------------------------------------------------------------
|
||||
** Copyright 1998-2006 Randy Heit
|
||||
** Copyright 1998-2007 Randy Heit
|
||||
** All rights reserved.
|
||||
**
|
||||
** Redistribution and use in source and binary forms, with or without
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
** Routines for managing SNDINFO lumps and ambient sounds
|
||||
**
|
||||
**---------------------------------------------------------------------------
|
||||
** Copyright 1998-2006 Randy Heit
|
||||
** Copyright 1998-2007 Randy Heit
|
||||
** All rights reserved.
|
||||
**
|
||||
** Redistribution and use in source and binary forms, with or without
|
||||
|
@ -87,6 +87,33 @@ struct FPlayerClassLookup
|
|||
WORD ListIndex[3]; // indices into PlayerSounds (0xffff means empty)
|
||||
};
|
||||
|
||||
// Used to lookup a sound like "*grunt". This contains all player sounds for
|
||||
// a particular class and gender.
|
||||
class FPlayerSoundHashTable
|
||||
{
|
||||
public:
|
||||
FPlayerSoundHashTable();
|
||||
FPlayerSoundHashTable(const FPlayerSoundHashTable &other);
|
||||
~FPlayerSoundHashTable();
|
||||
|
||||
void AddSound (int player_sound_id, int sfx_id);
|
||||
int LookupSound (int player_sound_id);
|
||||
FPlayerSoundHashTable &operator= (const FPlayerSoundHashTable &other);
|
||||
|
||||
protected:
|
||||
struct Entry
|
||||
{
|
||||
Entry *Next;
|
||||
int PlayerSoundID;
|
||||
int SfxID;
|
||||
};
|
||||
enum { NUM_BUCKETS = 23 };
|
||||
Entry *Buckets[NUM_BUCKETS];
|
||||
|
||||
void Init ();
|
||||
void Free ();
|
||||
};
|
||||
|
||||
static struct AmbientSound
|
||||
{
|
||||
unsigned type; // type of ambient sound
|
||||
|
@ -218,11 +245,10 @@ static FMusicVolume *MusicVolumes;
|
|||
static TArray<FSavedPlayerSoundInfo> SavedPlayerSounds;
|
||||
|
||||
static int NumPlayerReserves;
|
||||
static bool DoneReserving;
|
||||
static bool PlayerClassesIsSorted;
|
||||
|
||||
static TArray<FPlayerClassLookup> PlayerClassLookups;
|
||||
static TArray<WORD> PlayerSounds;
|
||||
static TArray<FPlayerSoundHashTable> PlayerSounds;
|
||||
|
||||
static char DefPlayerClassName[MAX_SNDNAME+1];
|
||||
static int DefPlayerClass;
|
||||
|
@ -507,21 +533,20 @@ int S_AddPlayerSound (const char *pclass, int gender, int refid,
|
|||
|
||||
int S_AddPlayerSound (const char *pclass, int gender, int refid, int lumpnum, bool fromskin)
|
||||
{
|
||||
char fakename[MAX_SNDNAME+1];
|
||||
size_t len;
|
||||
FString fakename;
|
||||
int id;
|
||||
|
||||
len = strlen (pclass);
|
||||
memcpy (fakename, pclass, len);
|
||||
fakename[len] = '|';
|
||||
fakename[len+1] = gender + '0';
|
||||
strcpy (&fakename[len+2], S_sfx[refid].name);
|
||||
fakename = pclass;
|
||||
fakename += ';';
|
||||
fakename += '0' + gender;
|
||||
fakename += ';';
|
||||
fakename += S_sfx[refid].name;
|
||||
|
||||
id = S_AddSoundLump (fakename, lumpnum);
|
||||
int classnum = S_AddPlayerClass (pclass);
|
||||
int soundlist = S_AddPlayerGender (classnum, gender);
|
||||
|
||||
PlayerSounds[soundlist + S_sfx[refid].link] = id;
|
||||
PlayerSounds[soundlist].AddSound (S_sfx[refid].link, id);
|
||||
|
||||
if (fromskin) S_SavePlayerSound(pclass, gender, refid, lumpnum, false);
|
||||
|
||||
|
@ -541,7 +566,7 @@ int S_AddPlayerSoundExisting (const char *pclass, int gender, int refid,
|
|||
int classnum = S_AddPlayerClass (pclass);
|
||||
int soundlist = S_AddPlayerGender (classnum, gender);
|
||||
|
||||
PlayerSounds[soundlist + S_sfx[refid].link] = aliasto;
|
||||
PlayerSounds[soundlist].AddSound (S_sfx[refid].link, aliasto);
|
||||
|
||||
if (fromskin) S_SavePlayerSound(pclass, gender, refid, aliasto, true);
|
||||
|
||||
|
@ -561,6 +586,148 @@ int S_DupPlayerSound (const char *pclass, int gender, int refid, int aliasref)
|
|||
return S_AddPlayerSoundExisting (pclass, gender, refid, aliasto);
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// FPlayerSoundHashTable constructor
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
FPlayerSoundHashTable::FPlayerSoundHashTable ()
|
||||
{
|
||||
Init();
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// FPlayerSoundHashTable copy constructor
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
FPlayerSoundHashTable::FPlayerSoundHashTable (const FPlayerSoundHashTable &other)
|
||||
{
|
||||
Init();
|
||||
*this = other;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// FPlayerSoundHashTable destructor
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
FPlayerSoundHashTable::~FPlayerSoundHashTable ()
|
||||
{
|
||||
Free ();
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// FPlayerSoundHashTable :: Init
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
void FPlayerSoundHashTable::Init ()
|
||||
{
|
||||
for (int i = 0; i < NUM_BUCKETS; ++i)
|
||||
{
|
||||
Buckets[i] = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// FPlayerSoundHashTable :: Free
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
void FPlayerSoundHashTable::Free ()
|
||||
{
|
||||
for (int i = 0; i < NUM_BUCKETS; ++i)
|
||||
{
|
||||
Entry *entry, *next;
|
||||
|
||||
for (entry = Buckets[i]; entry != NULL; )
|
||||
{
|
||||
next = entry->Next;
|
||||
delete entry;
|
||||
entry = next;
|
||||
}
|
||||
Buckets[i] = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// FPlayerSoundHashTable :: operator=
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
FPlayerSoundHashTable &FPlayerSoundHashTable::operator= (const FPlayerSoundHashTable &other)
|
||||
{
|
||||
Free ();
|
||||
for (int i = 0; i < NUM_BUCKETS; ++i)
|
||||
{
|
||||
Entry *entry;
|
||||
|
||||
for (entry = other.Buckets[i]; entry != NULL; entry = entry->Next)
|
||||
{
|
||||
AddSound (entry->PlayerSoundID, entry->SfxID);
|
||||
}
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// FPlayerSoundHashTable :: AddSound
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
void FPlayerSoundHashTable::AddSound (int player_sound_id, int sfx_id)
|
||||
{
|
||||
Entry *entry;
|
||||
unsigned bucket_num = (unsigned)player_sound_id % NUM_BUCKETS;
|
||||
|
||||
// See if the entry exists already.
|
||||
for (entry = Buckets[bucket_num];
|
||||
entry != NULL && entry->PlayerSoundID != player_sound_id;
|
||||
entry = entry->Next)
|
||||
{ }
|
||||
|
||||
if (entry != NULL)
|
||||
{ // If the player sound is already present, redefine it.
|
||||
entry->SfxID = sfx_id;
|
||||
}
|
||||
else
|
||||
{ // Otherwise, add it to the start of its bucket.
|
||||
entry = new Entry;
|
||||
entry->Next = Buckets[bucket_num];
|
||||
entry->PlayerSoundID = player_sound_id;
|
||||
entry->SfxID = sfx_id;
|
||||
Buckets[bucket_num] = entry;
|
||||
}
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// FPlayerSoundHashTable :: LookupSound
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
int FPlayerSoundHashTable::LookupSound (int player_sound_id)
|
||||
{
|
||||
Entry *entry;
|
||||
unsigned bucket_num = (unsigned)player_sound_id % NUM_BUCKETS;
|
||||
|
||||
// See if the entry exists already.
|
||||
for (entry = Buckets[bucket_num];
|
||||
entry != NULL && entry->PlayerSoundID != player_sound_id;
|
||||
entry = entry->Next)
|
||||
{ }
|
||||
|
||||
return entry != NULL ? entry->SfxID : 0;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// S_ClearSoundData
|
||||
|
@ -599,7 +766,6 @@ static void S_ClearSoundData()
|
|||
}
|
||||
S_rnd.Clear();
|
||||
|
||||
DoneReserving = false;
|
||||
NumPlayerReserves = 0;
|
||||
PlayerClassesIsSorted = false;
|
||||
PlayerClassLookups.Clear();
|
||||
|
@ -836,11 +1002,6 @@ static void S_AddSNDINFO (int lump)
|
|||
|
||||
case SI_PlayerReserve:
|
||||
// $playerreserve <logical name>
|
||||
if (DoneReserving)
|
||||
{
|
||||
SC_ScriptError ("All $playerreserves must come before any $playersounds or $playeraliases");
|
||||
}
|
||||
else
|
||||
{
|
||||
SC_MustGetString ();
|
||||
int id = S_AddSound (sc_String, -1);
|
||||
|
@ -1102,7 +1263,6 @@ static void S_AddStrifeVoice (int lumpnum)
|
|||
|
||||
static void S_ParsePlayerSoundCommon (char pclass[MAX_SNDNAME+1], int &gender, int &refid)
|
||||
{
|
||||
DoneReserving = true;
|
||||
SC_MustGetString ();
|
||||
strcpy (pclass, sc_String);
|
||||
SC_MustGetString ();
|
||||
|
@ -1204,19 +1364,13 @@ static int S_FindPlayerClass (const char *name)
|
|||
|
||||
static int S_AddPlayerGender (int classnum, int gender)
|
||||
{
|
||||
int index;
|
||||
unsigned int index;
|
||||
|
||||
index = PlayerClassLookups[classnum].ListIndex[gender];
|
||||
if (index == 0xffff)
|
||||
{
|
||||
WORD pushee = 0;
|
||||
|
||||
index = (int)PlayerSounds.Size ();
|
||||
index = PlayerSounds.Reserve (1);
|
||||
PlayerClassLookups[classnum].ListIndex[gender] = (WORD)index;
|
||||
for (int i = NumPlayerReserves; i != 0; --i)
|
||||
{
|
||||
PlayerSounds.Push (pushee);
|
||||
}
|
||||
}
|
||||
return index;
|
||||
}
|
||||
|
@ -1302,7 +1456,7 @@ static int S_LookupPlayerSound (int classidx, int gender, int refid)
|
|||
gender = g;
|
||||
}
|
||||
|
||||
int sndnum = PlayerSounds[listidx + S_sfx[refid].link];
|
||||
int sndnum = PlayerSounds[listidx].LookupSound (S_sfx[refid].link);
|
||||
|
||||
// If we're not done parsing SNDINFO yet, assume that the target sound is valid
|
||||
if (PlayerClassesIsSorted &&
|
||||
|
@ -1545,9 +1699,9 @@ CCMD (playersounds)
|
|||
if ((l = PlayerClassLookups[i].ListIndex[j]) != 0xffff)
|
||||
{
|
||||
Printf ("\n%s, %s:\n", PlayerClassLookups[i].Name, GenderNames[j]);
|
||||
for (k = 0; k < NumPlayerReserves; ++l, ++k)
|
||||
for (k = 0; k < NumPlayerReserves; ++k)
|
||||
{
|
||||
Printf (" %-16s%s\n", reserveNames[k], S_sfx[PlayerSounds[l]].name);
|
||||
Printf (" %-16s%s\n", reserveNames[k], S_sfx[PlayerSounds[l].LookupSound (k)].name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
** Templated, automatically resizing array
|
||||
**
|
||||
**---------------------------------------------------------------------------
|
||||
** Copyright 1998-2006 Randy Heit
|
||||
** Copyright 1998-2007 Randy Heit
|
||||
** All rights reserved.
|
||||
**
|
||||
** Redistribution and use in source and binary forms, with or without
|
||||
|
@ -214,6 +214,10 @@ public:
|
|||
Grow (amount);
|
||||
unsigned int place = Count;
|
||||
Count += amount;
|
||||
for (unsigned int i = place; i < Count; ++i)
|
||||
{
|
||||
::new((void *)&Array[i]) T;
|
||||
}
|
||||
return place;
|
||||
}
|
||||
unsigned int Size () const
|
||||
|
|
|
@ -133,7 +133,7 @@ public:
|
|||
FMemLump &operator= (const FMemLump ©);
|
||||
~FMemLump ();
|
||||
void *GetMem () { return Block.Len() == 0 ? NULL : (void *)Block.GetChars(); }
|
||||
unsigned int GetSize () { return Block.Len(); }
|
||||
size_t GetSize () { return Block.Len(); }
|
||||
|
||||
private:
|
||||
FMemLump (const FString &source);
|
||||
|
|
Loading…
Reference in a new issue