mirror of
https://github.com/ZDoom/qzdoom.git
synced 2024-11-28 06:53:58 +00:00
- Changed state label storage so that each actor owns all the state labels itself
and doesn't have to traverse parent lists to find them. This is required for Dehacked actors that inherit states (e.g. NonsolidMeat and Spectre) but it also makes the data much easier to handle. SVN r413 (trunk)
This commit is contained in:
parent
638526946b
commit
979dfdf4cf
6 changed files with 92 additions and 131 deletions
|
@ -1,4 +1,8 @@
|
||||||
December 16, 2006 (Changes by Graf Zahl)
|
December 16, 2006 (Changes by Graf Zahl)
|
||||||
|
- Changed state label storage so that each actor owns all the state labels itself
|
||||||
|
and doesn't have to traverse parent lists to find them. This is required for
|
||||||
|
Dehacked actors that inherit states (e.g. NonsolidMeat and Spectre) but it also
|
||||||
|
makes the data much easier to handle.
|
||||||
- Merged the fallingdamage setting into one menu item and added Strife damage to it.
|
- Merged the fallingdamage setting into one menu item and added Strife damage to it.
|
||||||
- Moved deathmatch options into their own category in the gameplay options menu.
|
- Moved deathmatch options into their own category in the gameplay options menu.
|
||||||
- Added the sv_smartaim code from GZDoom which tries to avoid autoaiming
|
- Added the sv_smartaim code from GZDoom which tries to avoid autoaiming
|
||||||
|
|
|
@ -357,7 +357,7 @@ static void ParseDecorate (void (*process)(FState *, int))
|
||||||
info = type->ActorInfo;
|
info = type->ActorInfo;
|
||||||
info->GameFilter = 0x80;
|
info->GameFilter = 0x80;
|
||||||
Decorations.Push (info);
|
Decorations.Push (info);
|
||||||
ClearStateLabels();
|
MakeStateDefines(parent->ActorInfo->StateList);
|
||||||
|
|
||||||
SC_MustGetString ();
|
SC_MustGetString ();
|
||||||
while (!SC_Compare ("{"))
|
while (!SC_Compare ("{"))
|
||||||
|
|
63
src/info.cpp
63
src/info.cpp
|
@ -432,20 +432,15 @@ void FStateLabels::Destroy ()
|
||||||
FState *AActor::FindState (FName label) const
|
FState *AActor::FindState (FName label) const
|
||||||
{
|
{
|
||||||
const FActorInfo *info = GetClass()->ActorInfo;
|
const FActorInfo *info = GetClass()->ActorInfo;
|
||||||
FStateLabel *slabel;
|
|
||||||
|
|
||||||
while (info != NULL)
|
|
||||||
{
|
|
||||||
if (info->StateList != NULL)
|
if (info->StateList != NULL)
|
||||||
{
|
{
|
||||||
slabel = info->StateList->FindLabel (label);
|
FStateLabel *slabel = info->StateList->FindLabel (label);
|
||||||
if (slabel != NULL && slabel->valid)
|
if (slabel != NULL)
|
||||||
{
|
{
|
||||||
return slabel->State;
|
return slabel->State;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
info = info->Class->ParentClass->ActorInfo;
|
|
||||||
}
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -460,34 +455,18 @@ FState *AActor::FindState (FName label) const
|
||||||
bool AActor::HasSpecialDeathStates () const
|
bool AActor::HasSpecialDeathStates () const
|
||||||
{
|
{
|
||||||
const FActorInfo *info = GetClass()->ActorInfo;
|
const FActorInfo *info = GetClass()->ActorInfo;
|
||||||
FStateLabel *slabel;
|
|
||||||
TArray<FName> checkedTypes;
|
|
||||||
|
|
||||||
while (info != NULL)
|
|
||||||
{
|
|
||||||
if (info->StateList != NULL)
|
if (info->StateList != NULL)
|
||||||
{
|
{
|
||||||
slabel = info->StateList->FindLabel (NAME_Death);
|
FStateLabel *slabel = info->StateList->FindLabel (NAME_Death);
|
||||||
if (slabel != NULL && slabel->Children != NULL)
|
if (slabel != NULL && slabel->Children != NULL)
|
||||||
{
|
{
|
||||||
for(int i=0;i<slabel->Children->NumLabels;i++)
|
for(int i=0;i<slabel->Children->NumLabels;i++)
|
||||||
{
|
|
||||||
unsigned int j;
|
|
||||||
for(j=0;j<checkedTypes.Size();j++)
|
|
||||||
{
|
|
||||||
if (slabel->Children->Labels[i].Label == checkedTypes[j]) break;
|
|
||||||
}
|
|
||||||
// Only check if this damage type hasn't been checked by another class with higher priority.
|
|
||||||
if (j==checkedTypes.Size())
|
|
||||||
{
|
{
|
||||||
if (slabel->Children->Labels[i].State != NULL) return true;
|
if (slabel->Children->Labels[i].State != NULL) return true;
|
||||||
else if (slabel->Children->Labels[i].valid) checkedTypes.Push(slabel->Children->Labels[i].Label);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
info = info->Class->ParentClass->ActorInfo;
|
|
||||||
}
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -504,8 +483,6 @@ bool AActor::HasSpecialDeathStates () const
|
||||||
// names until there are no more. If both the argument list and the state
|
// 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
|
// 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.
|
// 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.
|
|
||||||
//
|
//
|
||||||
//===========================================================================
|
//===========================================================================
|
||||||
|
|
||||||
|
@ -533,14 +510,8 @@ FState *AActor::FindState (int numnames, va_list arglist) const
|
||||||
|
|
||||||
FState *FActorInfo::FindState (int numnames, va_list arglist) const
|
FState *FActorInfo::FindState (int numnames, va_list arglist) const
|
||||||
{
|
{
|
||||||
const FActorInfo *info = this;
|
FStateLabels *labels = StateList;
|
||||||
FState *best = NULL;
|
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)
|
if (labels != NULL)
|
||||||
{
|
{
|
||||||
|
@ -559,28 +530,14 @@ FState *FActorInfo::FindState (int numnames, va_list arglist) const
|
||||||
{
|
{
|
||||||
count++;
|
count++;
|
||||||
labels = slabel->Children;
|
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;
|
best = slabel->State;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Walk up the class hierarchy and repeat.
|
|
||||||
info = info->Class->ParentClass->ActorInfo;
|
|
||||||
}
|
|
||||||
return best;
|
return best;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -602,12 +559,7 @@ FState *FActorInfo::FindStateExact (int numnames, ...) const
|
||||||
|
|
||||||
FState *FActorInfo::FindStateExact (int numnames, va_list arglist) const
|
FState *FActorInfo::FindStateExact (int numnames, va_list arglist) const
|
||||||
{
|
{
|
||||||
const FActorInfo *info = this;
|
FStateLabels *labels = StateList;
|
||||||
|
|
||||||
// Search this actor's class, plus all its ancestors for a match.
|
|
||||||
while (info != NULL)
|
|
||||||
{
|
|
||||||
FStateLabels *labels = info->StateList;
|
|
||||||
|
|
||||||
if (labels != NULL)
|
if (labels != NULL)
|
||||||
{
|
{
|
||||||
|
@ -633,14 +585,11 @@ FState *FActorInfo::FindStateExact (int numnames, va_list arglist) const
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Only exact matches count.
|
// Only exact matches count.
|
||||||
if (slabel != NULL && slabel->valid && count == numnames)
|
if (slabel != NULL && count == numnames)
|
||||||
{
|
{
|
||||||
return slabel->State;
|
return slabel->State;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Walk up the class hierarchy and repeat.
|
|
||||||
info = info->Class->ParentClass->ActorInfo;
|
|
||||||
}
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -153,7 +153,6 @@ struct FStateLabels;
|
||||||
struct FStateLabel
|
struct FStateLabel
|
||||||
{
|
{
|
||||||
FName Label;
|
FName Label;
|
||||||
bool valid; // needed to recognize genuine NULL states
|
|
||||||
FState *State;
|
FState *State;
|
||||||
FStateLabels *Children;
|
FStateLabels *Children;
|
||||||
};
|
};
|
||||||
|
|
|
@ -70,12 +70,6 @@ void FActorInfo::BuildDefaults ()
|
||||||
{
|
{
|
||||||
memset (Class->Defaults + parent->Size, 0, Class->Size - parent->Size);
|
memset (Class->Defaults + parent->Size, 0, Class->Size - parent->Size);
|
||||||
}
|
}
|
||||||
if (parent == RUNTIME_CLASS(AActor) && OwnedStates == NULL)
|
|
||||||
{ // Stateless actors that are direct subclasses of AActor
|
|
||||||
// have their spawnstate default to something that won't
|
|
||||||
// immediately destroy them.
|
|
||||||
((AActor *)(Class->Defaults))->SpawnState = &AActor::States[0];
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
ApplyDefaults (Class->Defaults);
|
ApplyDefaults (Class->Defaults);
|
||||||
}
|
}
|
||||||
|
@ -358,7 +352,14 @@ void FActorInfo::ApplyDefaults (BYTE *defaults)
|
||||||
sgClass = Class;
|
sgClass = Class;
|
||||||
sgDefaults = defaults;
|
sgDefaults = defaults;
|
||||||
|
|
||||||
|
if (Class != RUNTIME_CLASS(AActor))
|
||||||
|
{
|
||||||
|
MakeStateDefines(Class->ParentClass->ActorInfo->StateList);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
ClearStateLabels();
|
ClearStateLabels();
|
||||||
|
}
|
||||||
#if _MSC_VER
|
#if _MSC_VER
|
||||||
const BYTE *parser = DefaultList;
|
const BYTE *parser = DefaultList;
|
||||||
|
|
||||||
|
|
|
@ -774,7 +774,6 @@ static const ActorProps *is_actorprop (const char *str);
|
||||||
struct FStateDefine
|
struct FStateDefine
|
||||||
{
|
{
|
||||||
FName Label;
|
FName Label;
|
||||||
bool valid;
|
|
||||||
TArray<FStateDefine> Children;
|
TArray<FStateDefine> Children;
|
||||||
FState *State;
|
FState *State;
|
||||||
};
|
};
|
||||||
|
@ -803,7 +802,6 @@ static FStateDefine * FindStateLabelInList(TArray<FStateDefine> & list, FName na
|
||||||
FStateDefine def;
|
FStateDefine def;
|
||||||
def.Label=name;
|
def.Label=name;
|
||||||
def.State=NULL;
|
def.State=NULL;
|
||||||
def.valid=false;
|
|
||||||
return &list[list.Push(def)];
|
return &list[list.Push(def)];
|
||||||
}
|
}
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -882,7 +880,6 @@ void AddState (const char * statename, FState * state)
|
||||||
{
|
{
|
||||||
FStateDefine * std = FindStateAddress(statename);
|
FStateDefine * std = FindStateAddress(statename);
|
||||||
std->State = state;
|
std->State = state;
|
||||||
std->valid = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
@ -902,12 +899,7 @@ FState * FindState(AActor * actor, const PClass * type, const char * name)
|
||||||
for(unsigned i=0;i<namelist.Size();i++)
|
for(unsigned i=0;i<namelist.Size();i++)
|
||||||
{
|
{
|
||||||
statedef = FindStateLabelInList(*statelist, namelist[i], false);
|
statedef = FindStateLabelInList(*statelist, namelist[i], false);
|
||||||
if (statedef == NULL)
|
if (statedef == NULL) return NULL;
|
||||||
{
|
|
||||||
FActorInfo * parentinfo = type->ParentClass->ActorInfo;
|
|
||||||
if (parentinfo) return parentinfo->FindStateExact(namelist.Size(), (va_list)&namelist[0]);
|
|
||||||
else return NULL;
|
|
||||||
}
|
|
||||||
statelist = &statedef->Children;
|
statelist = &statedef->Children;
|
||||||
}
|
}
|
||||||
return statedef? statedef->State : NULL;
|
return statedef? statedef->State : NULL;
|
||||||
|
@ -961,6 +953,15 @@ static int STACK_ARGS labelcmp(const void * a, const void * b)
|
||||||
|
|
||||||
static FStateLabels * CreateStateLabelList(TArray<FStateDefine> & statelist)
|
static FStateLabels * CreateStateLabelList(TArray<FStateDefine> & statelist)
|
||||||
{
|
{
|
||||||
|
// First delete all empty labels from the list
|
||||||
|
for (int i=statelist.Size()-1;i>=0;i--)
|
||||||
|
{
|
||||||
|
if (statelist[i].Label == NAME_None || (statelist[i].State == NULL && statelist[i].Children.Size() == 0))
|
||||||
|
{
|
||||||
|
statelist.Delete(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int count=statelist.Size();
|
int count=statelist.Size();
|
||||||
|
|
||||||
if (count == 0) return NULL;
|
if (count == 0) return NULL;
|
||||||
|
@ -968,17 +969,11 @@ static FStateLabels * CreateStateLabelList(TArray<FStateDefine> & statelist)
|
||||||
FStateLabels * list = (FStateLabels*)M_Malloc(sizeof(FStateLabels)+(count-1)*sizeof(FStateLabel));
|
FStateLabels * list = (FStateLabels*)M_Malloc(sizeof(FStateLabels)+(count-1)*sizeof(FStateLabel));
|
||||||
list->NumLabels = count;
|
list->NumLabels = count;
|
||||||
|
|
||||||
int j=0;
|
for (int i=0;i<count;i++)
|
||||||
for (unsigned i=0;i<statelist.Size();i++)
|
|
||||||
{
|
{
|
||||||
if (statelist[i].Label != NAME_None)
|
list->Labels[i].Label = statelist[i].Label;
|
||||||
{
|
list->Labels[i].State = statelist[i].State;
|
||||||
list->Labels[j].Label = statelist[i].Label;
|
list->Labels[i].Children = CreateStateLabelList(statelist[i].Children);
|
||||||
list->Labels[j].State = statelist[i].State;
|
|
||||||
list->Labels[j].valid = statelist[i].valid;
|
|
||||||
list->Labels[j].Children = CreateStateLabelList(statelist[i].Children);
|
|
||||||
j++;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
qsort(list->Labels, count, sizeof(FStateLabel), labelcmp);
|
qsort(list->Labels, count, sizeof(FStateLabel), labelcmp);
|
||||||
return list;
|
return list;
|
||||||
|
@ -994,14 +989,28 @@ static FStateLabels * CreateStateLabelList(TArray<FStateDefine> & statelist)
|
||||||
|
|
||||||
void InstallStates(FActorInfo *info, AActor *defaults)
|
void InstallStates(FActorInfo *info, AActor *defaults)
|
||||||
{
|
{
|
||||||
|
// First ensure we have a valid spawn state.
|
||||||
FState * state = FindState(defaults, info->Class, "Spawn");
|
FState * state = FindState(defaults, info->Class, "Spawn");
|
||||||
// If the actor doesn't provide a valid spawn state we have to substutute it
|
|
||||||
// with the default.
|
// Stateless actors that are direct subclasses of AActor
|
||||||
if (state == &AActor::States[2] || state == NULL)
|
// have their spawnstate default to something that won't
|
||||||
|
// immediately destroy them.
|
||||||
|
if (state == &AActor::States[2] && info->Class->ParentClass == RUNTIME_CLASS(AActor))
|
||||||
{
|
{
|
||||||
AddState("Spawn", &AActor::States[0]);
|
AddState("Spawn", &AActor::States[0]);
|
||||||
}
|
}
|
||||||
|
else if (state == NULL)
|
||||||
|
{
|
||||||
|
// A NULL spawn state will crash the engine so set it to something that will make
|
||||||
|
// the actor disappear as quickly as possible.
|
||||||
|
AddState("Spawn", &AActor::States[2]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (info->StateList != NULL)
|
||||||
|
{
|
||||||
|
info->StateList->Destroy();
|
||||||
|
free(info->StateList);
|
||||||
|
}
|
||||||
info->StateList = CreateStateLabelList(StateLabels);
|
info->StateList = CreateStateLabelList(StateLabels);
|
||||||
|
|
||||||
// Cache these states as member veriables.
|
// Cache these states as member veriables.
|
||||||
|
@ -1032,7 +1041,6 @@ static void MakeStateList(const FStateLabels *list, TArray<FStateDefine> &dest)
|
||||||
|
|
||||||
def.Label = list->Labels[i].Label;
|
def.Label = list->Labels[i].Label;
|
||||||
def.State = list->Labels[i].State;
|
def.State = list->Labels[i].State;
|
||||||
def.valid = list->Labels[i].valid;
|
|
||||||
dest.Push(def);
|
dest.Push(def);
|
||||||
if (list->Labels[i].Children != NULL)
|
if (list->Labels[i].Children != NULL)
|
||||||
{
|
{
|
||||||
|
@ -1150,7 +1158,7 @@ static FActorInfo * CreateNewActor(FActorInfo ** parentc, Baggage *bag)
|
||||||
FActorInfo * info = ti->ActorInfo;
|
FActorInfo * info = ti->ActorInfo;
|
||||||
|
|
||||||
Decorations.Push (info);
|
Decorations.Push (info);
|
||||||
ClearStateLabels();
|
MakeStateDefines(parent->ActorInfo->StateList);
|
||||||
info->NumOwnedStates = 0;
|
info->NumOwnedStates = 0;
|
||||||
info->OwnedStates = NULL;
|
info->OwnedStates = NULL;
|
||||||
info->SpawnID = 0;
|
info->SpawnID = 0;
|
||||||
|
|
Loading…
Reference in a new issue