diff --git a/docs/rh-log.txt b/docs/rh-log.txt index 39bab19b7a..cfcc4f7822 100644 --- a/docs/rh-log.txt +++ b/docs/rh-log.txt @@ -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 diff --git a/src/actor.h b/src/actor.h index 45a35223a2..6dfd3f447b 100644 --- a/src/actor.h +++ b/src/actor.h @@ -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 (); diff --git a/src/dobject.cpp b/src/dobject.cpp index fe5bca6a43..f690a542c1 100644 --- a/src/dobject.cpp +++ b/src/dobject.cpp @@ -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) diff --git a/src/dobject.h b/src/dobject.h index 511752a988..254ec7851a 100644 --- a/src/dobject.h +++ b/src/dobject.h @@ -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; diff --git a/src/g_doom/a_painelemental.cpp b/src/g_doom/a_painelemental.cpp index 28e0b176f3..80cd6f3182 100644 --- a/src/g_doom/a_painelemental.cpp +++ b/src/g_doom/a_painelemental.cpp @@ -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; } diff --git a/src/g_shared/a_pickups.h b/src/g_shared/a_pickups.h index 4a78ca4f0f..ff709dba78 100644 --- a/src/g_shared/a_pickups.h +++ b/src/g_shared/a_pickups.h @@ -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); diff --git a/src/info.h b/src/info.h index 0011a7117f..6ac5e959e6 100644 --- a/src/info.h +++ b/src/info.h @@ -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); diff --git a/src/p_enemy.cpp b/src/p_enemy.cpp index 97eaf128ba..af65d20163 100644 --- a/src/p_enemy.cpp +++ b/src/p_enemy.cpp @@ -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. diff --git a/src/p_interaction.cpp b/src/p_interaction.cpp index aba3d43188..fdcefe38f2 100644 --- a/src/p_interaction.cpp +++ b/src/p_interaction.cpp @@ -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 && (healthWoundState != 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)) { diff --git a/src/p_local.h b/src/p_local.h index 3e0fa22dd1..54cf2475e0 100644 --- a/src/p_local.h +++ b/src/p_local.h @@ -275,9 +275,6 @@ extern TArray 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); diff --git a/src/p_map.cpp b/src/p_map.cpp index fec6d7b666..c7ee297184 100644 --- a/src/p_map.cpp +++ b/src/p_map.cpp @@ -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)) diff --git a/src/p_mobj.cpp b/src/p_mobj.cpp index e44782b002..69689a1edb 100644 --- a/src/p_mobj.cpp +++ b/src/p_mobj.cpp @@ -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 && diff --git a/src/s_advsound.cpp b/src/s_advsound.cpp index 5c5d7815ca..b0211990ae 100644 --- a/src/s_advsound.cpp +++ b/src/s_advsound.cpp @@ -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 () - { - return true; - } - template<> friend inline void ConstructInTArray (FMusicVolume *dst, const FMusicVolume &src) - { - new (dst) FMusicVolume(src); - } - template<> friend inline void ConstructEmptyInTArray (FMusicVolume *dst) - { - new (dst) FMusicVolume; - } -#else - template friend inline bool NeedsDestructor (); - template friend inline void ConstructInTArray (FMusicVolume *dst, const FMusicVolume &src) - template friend inline void ConstructEmptyInTArray (FMusicVolume *dst) -#endif + char MusicName[1]; }; -template<> inline bool NeedsDestructor () -{ - return true; -} -template<> inline void ConstructInTArray (FMusicVolume *dst, const FMusicVolume &src) -{ - new (dst) FMusicVolume(src); -} -template<> inline void ConstructEmptyInTArray (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 S_rnd; -static TArray 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; diff --git a/src/s_sound.cpp b/src/s_sound.cpp index 0daeb856bc..90ea1db9a6 100644 --- a/src/s_sound.cpp +++ b/src/s_sound.cpp @@ -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 ---------------------------------------------- diff --git a/src/sound/i_music.cpp b/src/sound/i_music.cpp index c40857f0e7..5e215b1fca 100644 --- a/src/sound/i_music.cpp +++ b/src/sound/i_music.cpp @@ -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(self*relative_volume, 0.0f, 1.0f)); + currSong->SetVolume (clamp (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(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) diff --git a/src/sound/music_midi_stream.cpp b/src/sound/music_midi_stream.cpp index f4141641e9..571beff122 100644 --- a/src/sound/music_midi_stream.cpp +++ b/src/sound/music_midi_stream.cpp @@ -27,7 +27,7 @@ CUSTOM_CVAR (Float, snd_midivolume, 0.5f, CVAR_ARCHIVE|CVAR_GLOBALCONFIG) self = 1.f; else { - float realvolume = clamp(self * relative_volume, 0, 1.0f); + float realvolume = clamp(self * relative_volume, 0.f, 1.f); DWORD onechanvol = clamp((DWORD)(realvolume * 65535.f), 0, 65535); midivolume = (onechanvol << 16) | onechanvol; if (currSong && currSong->IsMIDI ()) diff --git a/src/thingdef_codeptr.cpp b/src/thingdef_codeptr.cpp index 71e780a1bb..a702fb0acc 100644 --- a/src/thingdef_codeptr.cpp +++ b/src/thingdef_codeptr.cpp @@ -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) {