- Rewrote MusicVolumes handling so it's a list and not an array.

- Removed I_SetMusicVolume(). It isn't used.
- Moved P_IsFriend(), P_IsHostile(), and P_GetSpecies() into AActor.

SVN r18 (trunk)
This commit is contained in:
Randy Heit 2006-03-03 03:57:01 +00:00
parent cf11cbdb30
commit 75d072c09a
17 changed files with 135 additions and 175 deletions

View File

@ -1,3 +1,8 @@
March 1, 2006
- Rewrote MusicVolumes handling so it's a list and not an array.
- Removed I_SetMusicVolume(). It isn't used.
- Moved P_IsFriend(), P_IsHostile(), and P_GetSpecies() into AActor.
February 18, 2006
- Various fixes for compilation with GCC/Linux.
- Various fixes from Graf Zahl: Wrong blood color with P_BloodSplatter2() and

View File

@ -552,6 +552,18 @@ public:
// Die. Now.
virtual bool Massacre ();
// Is the other actor on my team?
bool IsTeammate (AActor *other);
// Is the other actor my friend?
bool IsFriend (AActor *other);
// Do I hate the other actor?
bool IsHostile (AActor *other);
// What species am I?
virtual const TypeInfo *GetSpecies();
// info for drawing
// NOTE: The first member variable *must* be x.
fixed_t x,y,z;
@ -677,9 +689,6 @@ public:
// [RH] Used to interpolate the view to get >35 FPS
fixed_t PrevX, PrevY, PrevZ;
// Public functions
bool IsTeammate (AActor *other);
// ThingIDs
static void ClearTIDHashes ();
void AddToHash ();

View File

@ -375,10 +375,10 @@ void FMetaTable::SetMetaInt (DWORD id, int parm)
meta->Value.Int = parm;
}
int FMetaTable::GetMetaInt (DWORD id) const
int FMetaTable::GetMetaInt (DWORD id, int def) const
{
FMetaData *meta = FindMeta (META_Int, id);
return meta != NULL ? meta->Value.Int : 0;
return meta != NULL ? meta->Value.Int : def;
}
void FMetaTable::SetMetaFixed (DWORD id, fixed_t parm)
@ -387,10 +387,10 @@ void FMetaTable::SetMetaFixed (DWORD id, fixed_t parm)
meta->Value.Fixed = parm;
}
fixed_t FMetaTable::GetMetaFixed (DWORD id) const
fixed_t FMetaTable::GetMetaFixed (DWORD id, fixed_t def) const
{
FMetaData *meta = FindMeta (META_Fixed, id);
return meta != NULL ? meta->Value.Fixed : 0;
return meta != NULL ? meta->Value.Fixed : def;
}
void FMetaTable::SetMetaString (DWORD id, const char *parm)

View File

@ -117,8 +117,8 @@ public:
void SetMetaFixed (DWORD id, fixed_t parm);
void SetMetaString (DWORD id, const char *parm); // The string is copied
int GetMetaInt (DWORD id) const;
fixed_t GetMetaFixed (DWORD id) const;
int GetMetaInt (DWORD id, int def=0) const;
fixed_t GetMetaFixed (DWORD id, fixed_t def=0) const;
const char *GetMetaString (DWORD id) const;
FMetaData *FindMeta (EMetaType type, DWORD id) const;

View File

@ -212,7 +212,7 @@ void A_PainAttack (AActor *self)
void A_PainDie (AActor *self)
{
if (P_IsFriend (self, self->target))
if (self->IsFriend (self->target))
{ // And I thought you were my friend!
self->flags &= ~MF_FRIENDLY;
}

View File

@ -156,6 +156,9 @@ class ACustomInventory : public AInventory
public:
FState *UseState, *PickupState, *DropState;
// This is used when an inventory item's use state sequence is executed.
static bool CallStateChain (AActor *actor, FState *state);
void Serialize (FArchive &arc);
bool TryPickup (AActor *toucher);
bool Use (bool pickup);

View File

@ -166,9 +166,6 @@ struct FState
extern FState * CallingState;
int CheckIndex(int paramsize, FState ** pcallstate=NULL);
// This is used when an inventory item's use state sequence is executed.
bool CallStateChain(AActor * actor, FState * State);
FArchive &operator<< (FArchive &arc, FState *&state);

View File

@ -344,10 +344,10 @@ bool P_HitFriend(AActor * self)
{
angle_t angle = R_PointToAngle2 (self->x, self->y, self->target->x, self->target->y);
fixed_t dist = P_AproxDistance (self->x-self->target->x, self->y-self->target->y);
P_AimLineAttack (self, self->angle, dist, 0);
P_AimLineAttack (self, angle, dist, 0);
if (linetarget != NULL && linetarget != self->target)
{
return P_IsFriend(self, linetarget);
return self->IsFriend (linetarget);
}
}
return false;
@ -1104,7 +1104,7 @@ AActor *LookForEnemiesInBlock (AActor *lookee, int index)
if (other)
{
AActor *targ = other->target;
if (targ && targ->target == other && pr_skiptarget() > 100 && P_IsFriend(lookee, targ) &&
if (targ && targ->target == other && pr_skiptarget() > 100 && lookee->IsFriend (targ) &&
targ->health*2 >= targ->GetDefault()->health)
{
continue;
@ -1374,7 +1374,7 @@ void A_Look (AActor *actor)
if (targ && (targ->flags & MF_SHOOTABLE))
{
if (P_IsFriend(actor, targ)) // be a little more precise!
if (actor->IsFriend (targ)) // be a little more precise!
{
// If we find a valid target here, the wandering logic should *not*
// be activated! If would cause the seestate to be set twice.

View File

@ -648,8 +648,8 @@ void AActor::Die (AActor *source, AActor *inflictor)
int flags4 = !inflictor ? 0 : inflictor->player && inflictor->player->ReadyWeapon ?
inflictor->player->ReadyWeapon->flags4 : inflictor->flags4;
int gibhealth = -abs(GetClass()->Meta.GetMetaInt (AMETA_GibHealth));
if (gibhealth == 0) gibhealth = (gameinfo.gametype == GAME_Doom ? -GetDefault()->health : -GetDefault()->health/2);
int gibhealth = -abs(GetClass()->Meta.GetMetaInt (AMETA_GibHealth,
gameinfo.gametype == GAME_Doom ? -GetDefault()->health : -GetDefault()->health/2));
DamageType = MOD_UNKNOWN; // [RH] "Frozen" barrels shouldn't do freezing damage
if (XDeathState && (health<gibhealth || flags4 & MF4_EXTREMEDEATH) && !(flags4 & MF4_NOEXTREMEDEATH))
@ -1103,9 +1103,7 @@ void P_DamageMobj (AActor *target, AActor *inflictor, AActor *source, int damage
}
if (target->WoundState != NULL)
{
int woundhealth = RUNTIME_TYPE(target)->Meta.GetMetaInt (AMETA_WoundHealth);
if (!woundhealth)
woundhealth = 6;
int woundhealth = RUNTIME_TYPE(target)->Meta.GetMetaInt (AMETA_WoundHealth, 6);
if (target->health <= woundhealth)
{
@ -1211,17 +1209,10 @@ bool AActor::OkayToSwitchTarget (AActor *other)
return false;
if (threshold != 0 && !(flags4 & MF4_QUICKTORETALIATE))
return false;
if (P_IsFriend (this, other))
if (IsFriend (other))
{ // [RH] Friendlies don't target other friendlies
return false;
}
if ((flags & MF_FRIENDLY) && other->player != NULL)
{ // [RH] Friendlies don't target their player friends either
if (!deathmatch || other->player - players == FriendPlayer+1)
{
return false;
}
}
if ((gameinfo.gametype == GAME_Strife || infighting < 0) &&
other->player == NULL && !P_IsHostile (this, other))
{

View File

@ -275,9 +275,6 @@ extern TArray<line_t *> spechit;
extern bool DoRipping;
extern AActor *LastRipped;
bool P_IsFriend(AActor * self, AActor * other);
bool P_IsHostile(AActor * self, AActor * other);
BOOL P_TestMobjLocation (AActor *mobj);
bool P_TestMobjZ (AActor *mobj);
BOOL P_CheckPosition (AActor *thing, fixed_t x, fixed_t y);

View File

@ -788,61 +788,6 @@ BOOL PIT_CheckLine (line_t *ld)
return true;
}
//==========================================================================
//
// Species is defined as the lowest base class that is a monster
// with no non-monster class in between
//
//==========================================================================
const TypeInfo * P_GetSpecies(AActor * self)
{
const TypeInfo * thistype=self->GetClass();
if (GetDefaultByType(thistype)->flags3 & MF3_ISMONSTER) while (thistype->ParentType)
{
if (GetDefaultByType(thistype->ParentType)->flags3 & MF3_ISMONSTER)
thistype=thistype->ParentType;
else
break;
}
return thistype;
}
//==========================================================================
//
// Checks whether 2 monsters have to be considered friendly
//
//==========================================================================
bool P_IsFriend(AActor * self, AActor * other)
{
if (self->flags & other->flags&MF_FRIENDLY)
{
return !deathmatch || self->FriendPlayer==other->FriendPlayer || self->FriendPlayer==0 || other->FriendPlayer==0;
}
return false;
}
//==========================================================================
//
// Checks whether 2 monsters have to be considered hostile under any circumstances
//
//==========================================================================
bool P_IsHostile(AActor * self, AActor * other)
{
// Both monsters are non-friendlies so hostilities depend on infighting settings
if (!((self->flags | other->flags) & MF_FRIENDLY)) return false;
// Both monsters are friendly and belong to the same player if applicable.
if (self->flags & other->flags&MF_FRIENDLY)
{
return deathmatch && self->FriendPlayer!=other->FriendPlayer && self->FriendPlayer!=0 && other->FriendPlayer!=0;
}
return true;
}
//==========================================================================
//
// PIT_CheckThing
@ -1014,7 +959,7 @@ BOOL PIT_CheckThing (AActor *thing)
{
// 0: Monsters cannot hurt same species except
// cases where they are clearly supposed to do that
if (P_IsFriend(thing, tmthing->target))
if (thing->IsFriend (tmthing->target))
{
// Friends never harm each other
return false;
@ -1024,7 +969,7 @@ BOOL PIT_CheckThing (AActor *thing)
// [RH] Don't hurt monsters that hate the same thing as you do
return false;
}
if (P_GetSpecies(thing) == P_GetSpecies(tmthing->target))
if (thing->GetSpecies() == tmthing->target->GetSpecies())
{
// Don't hurt same species or any relative
if (!P_IsHostile(thing, tmthing->target))

View File

@ -3770,7 +3770,7 @@ AActor *P_SpawnPuff (const TypeInfo *pufftype, fixed_t x, fixed_t y, fixed_t z,
puff->SetState (puff->MeleeState);
}
if (cl_pufftype && updown != 3 && puff->flags4&MF4_ALLOWPARTICLES)
if (cl_pufftype && updown != 3 && (puff->flags4 & MF4_ALLOWPARTICLES))
{
P_DrawSplash2 (32, x, y, z, dir, updown, 1);
puff->renderflags |= RF_INVISIBLE;
@ -4429,6 +4429,77 @@ bool AActor::IsTeammate (AActor *other)
return false;
}
//==========================================================================
//
// AActor :: GetSpecies
//
// Species is defined as the lowest base class that is a monster
// with no non-monster class in between. This is virtualized, so special
// monsters can change this behavior if they like.
//
//==========================================================================
const TypeInfo *AActor::GetSpecies()
{
const TypeInfo *thistype = GetClass();
if (GetDefaultByType(thistype)->flags3 & MF3_ISMONSTER)
{
while (thistype->ParentType)
{
if (GetDefaultByType(thistype->ParentType)->flags3 & MF3_ISMONSTER)
thistype = thistype->ParentType;
else
break;
}
}
return thistype;
}
//==========================================================================
//
// AActor :: IsFriend
//
// Checks if two monsters have to be considered friendly.
//
//==========================================================================
bool AActor::IsFriend (AActor *other)
{
if (flags & other->flags & MF_FRIENDLY)
{
return !deathmatch ||
FriendPlayer == other->FriendPlayer ||
FriendPlayer == 0 ||
other->FriendPlayer == 0;
}
return false;
}
//==========================================================================
//
// AActor :: IsHostile
//
// Checks if two monsters have to be considered hostile under any circumstances
//
//==========================================================================
bool P_IsHostile (AActor *other)
{
// Both monsters are non-friendlies so hostilities depend on infighting settings
if (!((flags | other->flags) & MF_FRIENDLY)) return false;
// Both monsters are friendly and belong to the same player if applicable.
if (flags & other->flags & MF_FRIENDLY)
{
return deathmatch &&
self->FriendPlayer != other->FriendPlayer &&
self->FriendPlayer !=0 &&
other->FriendPlayer != 0;
}
return true;
}
int AActor::DoSpecialDamage (AActor *target, int damage)
{
if (target->player && target->player->mo == target && damage < 1000 &&

View File

@ -123,64 +123,11 @@ struct FBloodSFX
// music volume multipliers
struct FMusicVolume
{
FMusicVolume() : MusicName(), Volume(1) {}
FMusicVolume (const FMusicVolume &other)
{
MusicName = other.MusicName;
Volume = other.Volume;
}
FMusicVolume &operator= (const FMusicVolume &other)
{
MusicName = other.MusicName;
Volume = other.Volume;
return *this;
}
string MusicName;
FMusicVolume *Next;
float Volume;
private:
void *operator new (size_t size, FMusicVolume *addr)
{
return addr;
}
void operator delete (void *, FMusicVolume *)
{
}
#ifndef __GNUC__
template<> friend inline bool NeedsDestructor<FMusicVolume> ()
{
return true;
}
template<> friend inline void ConstructInTArray<FMusicVolume> (FMusicVolume *dst, const FMusicVolume &src)
{
new (dst) FMusicVolume(src);
}
template<> friend inline void ConstructEmptyInTArray<FMusicVolume> (FMusicVolume *dst)
{
new (dst) FMusicVolume;
}
#else
template<struct FMusicVolume> friend inline bool NeedsDestructor<FMusicVolume> ();
template<struct FMusicVolume> friend inline void ConstructInTArray<FMusicVolume> (FMusicVolume *dst, const FMusicVolume &src)
template<struct FMusicVolume> friend inline void ConstructEmptyInTArray<FMusicVolume> (FMusicVolume *dst)
#endif
char MusicName[1];
};
template<> inline bool NeedsDestructor<FMusicVolume> ()
{
return true;
}
template<> inline void ConstructInTArray<FMusicVolume> (FMusicVolume *dst, const FMusicVolume &src)
{
new (dst) FMusicVolume(src);
}
template<> inline void ConstructEmptyInTArray<FMusicVolume> (FMusicVolume *dst)
{
new (dst) FMusicVolume;
}
// EXTERNAL FUNCTION PROTOTYPES --------------------------------------------
void S_StartNamedSound (AActor *ent, fixed_t *pt, int channel,
@ -241,7 +188,7 @@ static const char *SICommandStrings[] =
};
static TArray<FRandomSoundList> S_rnd;
static TArray<FMusicVolume> MusicVolumes;
static FMusicVolume *MusicVolumes;
static int NumPlayerReserves;
static bool DoneReserving;
@ -268,12 +215,15 @@ static FRandom pr_randsound ("RandSound");
float S_GetMusicVolume (const char *music)
{
for (int i = 0; i < MusicVolumes.Size(); i++)
FMusicVolume *musvol = MusicVolumes;
while (musvol != NULL)
{
if (!stricmp(music, MusicVolumes[i].MusicName.GetChars()))
if (!stricmp (music, musvol->MusicName))
{
return MusicVolumes[i].Volume;
return musvol->Volume;
}
musvol = musvol->Next;
}
return 1.f;
}
@ -926,12 +876,14 @@ static void S_AddSNDINFO (int lump)
break;
case SI_MusicVolume: {
FMusicVolume mv;
SC_MustGetString();
mv.MusicName = sc_String;
string musname (sc_String);
SC_MustGetFloat();
mv.Volume = sc_Float;
MusicVolumes.Push (mv);
FMusicVolume *mv = (FMusicVolume *)Malloc (sizeof(*mv) + musname.Len());
mv->Volume = sc_Float;
strcpy (mv->MusicName, musname.GetChars());
mv->Next = MusicVolumes;
MusicVolumes = mv;
}
break;

View File

@ -123,7 +123,7 @@ struct MusPlayingInfo
// EXTERNAL FUNCTION PROTOTYPES --------------------------------------------
float S_GetMusicVolume (const char *music);
extern float S_GetMusicVolume (const char *music);
// PUBLIC FUNCTION PROTOTYPES ----------------------------------------------

View File

@ -83,8 +83,7 @@ static bool MusicDown = true;
MusInfo *currSong;
int nomusic = 0;
float relative_volume = 1.0f;
float saved_relative_volume = 1.0f; // this could be used to implement an ACS FadeMusic function
float relative_volume = 1.f;
//==========================================================================
//
@ -100,7 +99,7 @@ CUSTOM_CVAR (Float, snd_musicvolume, 0.3f, CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
else if (self > 1.f)
self = 1.f;
else if (currSong != NULL && !currSong->IsMIDI ())
currSong->SetVolume (clamp<float>(self*relative_volume, 0.0f, 1.0f));
currSong->SetVolume (clamp<float> (self * relative_volume, 0.f, 1.f));
}
MusInfo::~MusInfo ()
@ -160,7 +159,7 @@ void I_PlaySong (void *handle, int _looping, float rel_vol)
if (!info || nomusic)
return;
saved_relative_volume = relative_volume = rel_vol;
relative_volume = rel_vol;
info->Stop ();
info->Play (_looping ? true : false);
@ -417,17 +416,6 @@ bool I_SetSongPosition (void *handle, int order)
return info ? info->SetPosition (order) : false;
}
// Sets relative music volume. Takes $musicvolume in SNDINFO into consideration
void I_SetMusicVolume (float factor)
{
factor = clamp<float>(factor, 0, 2.0f);
relative_volume = saved_relative_volume * factor;
#ifdef _WIN32
snd_midivolume.Callback();
#endif
snd_musicvolume.Callback();
}
CCMD(testmusicvol)
{
if (argv.argc() > 1)

View File

@ -27,7 +27,7 @@ CUSTOM_CVAR (Float, snd_midivolume, 0.5f, CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
self = 1.f;
else
{
float realvolume = clamp<float>(self * relative_volume, 0, 1.0f);
float realvolume = clamp<float>(self * relative_volume, 0.f, 1.f);
DWORD onechanvol = clamp<DWORD>((DWORD)(realvolume * 65535.f), 0, 65535);
midivolume = (onechanvol << 16) | onechanvol;
if (currSong && currSong->IsMIDI ())

View File

@ -96,18 +96,20 @@ StateCallData StateCall;
//==========================================================================
//
// ACustomInventory :: CallStateChain
//
// Executes the code pointers in a chain of states
// until there is no next state
//
//==========================================================================
bool CallStateChain(AActor * actor, FState * State)
bool ACustomInventory::CallStateChain (AActor *actor, FState * State)
{
bool result = false;
int counter=0;
int counter = 0;
StateCall.State = State;
while (StateCall.State !=NULL)
while (StateCall.State != NULL)
{
// Assume success. The code pointer will set this to false if necessary
StateCall.Result = true;
@ -119,7 +121,7 @@ bool CallStateChain(AActor * actor, FState * State)
// Since there are no delays it is a good idea to check for infinite loops here!
counter++;
if (counter>=10000) break;
if (counter >= 10000) break;
if (StateCall.State == CallingState)
{