- Fixed: The global WeaponSection string was never freed. It has been replaced

with an FString now.
- Fixed: The music strings in the default level info were never freed and
  caused memory leaks when used repeatedly.
- Fixed: The intermusic string in the level info was never freed.
- Fixed: The default fire obituary should only be printed if the damage
  came from the environment. If it comes from a monster the monster specific
  obituary should be used instead.
- Added custom damage types from the floating point test release.
- Changed Pain Elemental's massacre check. Now A_PainDie checks for the damage 
  type and doesn't spawn anything if it is NAME_Massacre. A_PainDie can also 
  be used by other actors so a more generalized approach is needed than hard
  coding it into the Pain Elemental.
- Converted a few of Doom's monsters to DECORATE because I couldn't test the
  first version of the custom state code with the corpses inheriting from them.
- Added custom states from last year's floating point test release and fixed
  some bugs I found in that code. Unfortunately it wasn't all salvageable
  and it was easier to recreate some parts from scratch.



SVN r368 (trunk)
This commit is contained in:
Christoph Oelckers 2006-10-31 14:53:21 +00:00
commit 063c85b157
118 changed files with 2103 additions and 1818 deletions

View file

@ -49,6 +49,7 @@
#include "r_state.h"
#include "i_system.h"
#include "p_local.h"
#include "templates.h"
extern void LoadDecorations (void (*process)(FState *, int));
@ -64,6 +65,11 @@ extern void LoadDecorations (void (*process)(FState *, int));
#define NULL_STATE_INDEX 127
//==========================================================================
//
//
//==========================================================================
FArchive &operator<< (FArchive &arc, FState *&state)
{
const PClass *info;
@ -119,7 +125,12 @@ FArchive &operator<< (FArchive &arc, FState *&state)
return arc;
}
//==========================================================================
//
// Find the actor that a state belongs to.
//
//==========================================================================
const PClass *FState::StaticFindStateOwner (const FState *state)
{
const FActorInfo *info = RUNTIME_CLASS(AActor)->ActorInfo;
@ -153,8 +164,13 @@ const PClass *FState::StaticFindStateOwner (const FState *state)
return NULL;
}
//==========================================================================
//
// Find the actor that a state belongs to, but restrict the search to
// the specified type and its ancestors.
//
//==========================================================================
const PClass *FState::StaticFindStateOwner (const FState *state, const FActorInfo *info)
{
while (info != NULL)
@ -169,6 +185,11 @@ const PClass *FState::StaticFindStateOwner (const FState *state, const FActorInf
return NULL;
}
//==========================================================================
//
//
//==========================================================================
int GetSpriteIndex(const char * spritename)
{
for (unsigned i = 0; i < sprites.Size (); ++i)
@ -187,7 +208,12 @@ int GetSpriteIndex(const char * spritename)
}
//==========================================================================
//
// Change sprite names to indices
//
//==========================================================================
static void ProcessStates (FState *states, int numstates)
{
int sprite = -1;
@ -205,6 +231,12 @@ static void ProcessStates (FState *states, int numstates)
}
}
//==========================================================================
//
//
//==========================================================================
void FActorInfo::StaticInit ()
{
TAutoSegIterator<FActorInfo *, &ARegHead, &ARegTail> reg;
@ -247,7 +279,12 @@ void FActorInfo::StaticInit ()
LoadDecorations (ProcessStates);
}
//==========================================================================
//
// Called after the IWAD has been identified
//
//==========================================================================
void FActorInfo::StaticGameSet ()
{
// Run every AT_GAME_SET function
@ -258,7 +295,12 @@ void FActorInfo::StaticGameSet ()
}
}
//==========================================================================
//
// Called after Dehacked patches are applied
//
//==========================================================================
void FActorInfo::StaticSetActorNums ()
{
memset (SpawnableThings, 0, sizeof(SpawnableThings));
@ -278,6 +320,11 @@ void FActorInfo::StaticSetActorNums ()
}
}
//==========================================================================
//
//
//==========================================================================
void FActorInfo::RegisterIDs ()
{
if (GameFilter == GAME_Any || (GameFilter & gameinfo.gametype))
@ -293,8 +340,12 @@ void FActorInfo::RegisterIDs ()
}
}
//==========================================================================
//
// Called when a new game is started, but only if the game
// speed has changed.
//
//==========================================================================
void FActorInfo::StaticSpeedSet ()
{
@ -305,6 +356,11 @@ void FActorInfo::StaticSpeedSet ()
}
}
//==========================================================================
//
//
//==========================================================================
FActorInfo *FActorInfo::GetReplacement ()
{
if (Replacement == NULL)
@ -320,6 +376,11 @@ FActorInfo *FActorInfo::GetReplacement ()
return rep;
}
//==========================================================================
//
//
//==========================================================================
FActorInfo *FActorInfo::GetReplacee ()
{
if (Replacee == NULL)
@ -335,6 +396,267 @@ FActorInfo *FActorInfo::GetReplacee ()
return rep;
}
//==========================================================================
//
//
//==========================================================================
FStateLabel *FStateLabels::FindLabel (FName label)
{
return const_cast<FStateLabel *>(BinarySearch<FStateLabel, FName> (Labels, NumLabels, &FStateLabel::Label, label));
}
void FStateLabels::Destroy ()
{
for(int i=0; i<NumLabels;i++)
{
if (Labels[i].Children != NULL)
{
Labels[i].Children->Destroy();
free (Labels[i].Children); // These are malloc'd, not new'd!
Labels[i].Children=NULL;
}
}
}
//===========================================================================
//
// FindState (one name version)
//
// Finds a state with the exact specified name.
//
//===========================================================================
FState *AActor::FindState (FName label) const
{
const FActorInfo *info = GetClass()->ActorInfo;
FStateLabel *slabel;
while (info != NULL)
{
if (info->StateList != NULL)
{
slabel = info->StateList->FindLabel (label);
if (slabel != NULL && slabel->valid)
{
return slabel->State;
}
}
info = info->Class->ParentClass->ActorInfo;
}
return NULL;
}
//===========================================================================
//
// HasStates
//
// Checks whether the actor has substates for the given name.
//
//===========================================================================
bool AActor::HasStates (FName label) const
{
const FActorInfo *info = GetClass()->ActorInfo;
FStateLabel *slabel;
while (info != NULL)
{
if (info->StateList != NULL)
{
slabel = info->StateList->FindLabel (label);
if (slabel != NULL)
{
return true;
}
}
info = info->Class->ParentClass->ActorInfo;
}
return false;
}
//===========================================================================
//
// FindState (multiple names version)
//
// Finds a state that matches as many of the supplied names as possible.
// A state with more names than those provided does not match.
// A state with fewer names can match if there are no states with the exact
// same number of names.
//
// The search proceeds like this. For the current class, keeping matching
// names until there are no more. If both the argument list and the state
// are out of names, it's an exact match, so return it. If the state still
// has names, ignore it. If the argument list still has names, remember it.
// Repeat with each successive ancestor class. The state with the longest
// match not exceeding the supplied number of names is returned.
//
//===========================================================================
FState *AActor::FindState (int numnames, int first, ...) const // The 'first' parameter is only here to
// disambiguate from the single parameter version
{
va_list arglist;
va_start (arglist, numnames);
return FindState (numnames, arglist);
}
FState *FActorInfo::FindState (int numnames, ...) const
{
va_list arglist;
va_start (arglist, numnames);
return FindState (numnames, arglist);
}
FState *AActor::FindState (int numnames, va_list arglist) const
{
return GetClass()->ActorInfo->FindState (numnames, arglist);
}
FState *FActorInfo::FindState (int numnames, va_list arglist) const
{
const FActorInfo *info = this;
FState *best = NULL;
int bestcount = 0;
// Search this actor's class, plus all its ancestors for a match.
while (info != NULL && bestcount < numnames)
{
FStateLabels *labels = info->StateList;
if (labels != NULL)
{
va_list names = arglist;
int count = 0;
FStateLabel *slabel = NULL;
FName label;
// Find the best-matching label for this class.
while (labels != NULL && count < numnames)
{
label = ENamedName(va_arg (names, int));
slabel = labels->FindLabel (label);
if (slabel != NULL)
{
count++;
labels = slabel->Children;
// Labels that are more specific than what we want do not match.
// Less specific labels do match.
if (slabel->valid && count > bestcount)
{
if (count == numnames)
{
return slabel->State;
}
bestcount = count;
best = slabel->State;
}
}
else
{
break;
}
}
}
// Walk up the class hierarchy and repeat.
info = info->Class->ParentClass->ActorInfo;
}
return best;
}
//===========================================================================
//
// FindStateExact
//
// This is like FindState, except it will only return states whose labels
// match the requested one exactly.
//
//===========================================================================
FState *FActorInfo::FindStateExact (int numnames, ...) const
{
va_list arglist;
va_start (arglist, numnames);
return FindStateExact (numnames, arglist);
}
FState *FActorInfo::FindStateExact (int numnames, va_list arglist) const
{
const FActorInfo *info = this;
// Search this actor's class, plus all its ancestors for a match.
while (info != NULL)
{
FStateLabels *labels = info->StateList;
if (labels != NULL)
{
va_list names = arglist;
int count = 0;
FStateLabel *slabel = NULL;
FName label;
// Look for a matching label for this class.
while (labels != NULL && count < numnames)
{
label = ENamedName(va_arg (names, int));
slabel = labels->FindLabel (label);
if (slabel != NULL)
{
count++;
labels = slabel->Children;
}
else
{
break;
}
}
// Only exact matches count.
if (slabel != NULL && slabel->valid && count == numnames)
{
return slabel->State;
}
}
// Walk up the class hierarchy and repeat.
info = info->Class->ParentClass->ActorInfo;
}
return NULL;
}
//===========================================================================
//
// Changes a single state
//
// If the given state does not exist it won't be changed
//
//===========================================================================
void FActorInfo::ChangeState (FName label, FState * newstate) const
{
FStateLabel *slabel;
if (StateList != NULL)
{
slabel = StateList->FindLabel (label);
if (slabel != NULL)
{
slabel->State = newstate;
}
}
}
//==========================================================================
//
//
//==========================================================================
FDoomEdMap DoomEdMap;
FDoomEdMap::FDoomEdEntry *FDoomEdMap::DoomEdHash[DOOMED_HASHSIZE];