- did some code cleanup and reorganization in thingdef.cpp.

- Replaced the translation parser for TEXTURES with FRemapTable::AddToTranslation.


SVN r1241 (trunk)
This commit is contained in:
Christoph Oelckers 2008-09-21 22:25:23 +00:00
commit 8a79985f46
7 changed files with 255 additions and 355 deletions

View file

@ -353,123 +353,64 @@ static void ParseActionDef (FScanner &sc, PClass *cls)
// Starts a new actor definition
//
//==========================================================================
static FActorInfo *CreateNewActor(FScanner &sc, FActorInfo **parentc, Baggage *bag)
static FActorInfo *CreateNewActor(FName typeName, FName parentName, FName replaceName,
int DoomEdNum, bool native)
{
FName typeName;
const PClass *replacee = NULL;
int DoomEdNum = -1;
PClass *ti = NULL;
FActorInfo *info = NULL;
// Get actor name
sc.MustGetString();
char *colon = strchr(sc.String, ':');
if (colon != NULL)
{
*colon++ = 0;
}
/*
if (PClass::FindClass (sc.String) != NULL)
{
sc.ScriptError ("Actor %s is already defined.", sc.String);
}
*/
typeName = sc.String;
PClass *parent = RUNTIME_CLASS(AActor);
if (parentc)
{
*parentc = NULL;
// Do some tweaking so that a definition like 'Actor:Parent' which is read as a single token is recognized as well
// without having resort to C-mode (which disallows periods in actor names.)
if (colon == NULL)
{
sc.MustGetString ();
if (sc.String[0]==':')
{
colon = sc.String + 1;
}
}
if (colon != NULL)
{
if (colon[0] == 0)
{
sc.MustGetString ();
colon = sc.String;
}
}
if (colon != NULL)
{
parent = const_cast<PClass *> (PClass::FindClass (colon));
if (parent == NULL)
{
sc.ScriptError ("Parent type '%s' not found", colon);
}
else if (!parent->IsDescendantOf(RUNTIME_CLASS(AActor)))
{
sc.ScriptError ("Parent type '%s' is not an actor", colon);
}
else if (parent->ActorInfo == NULL)
{
sc.ScriptError ("uninitialized parent type '%s'", colon);
}
else
{
*parentc = parent->ActorInfo;
}
if (parentName != NAME_None)
{
parent = const_cast<PClass *> (PClass::FindClass (parentName));
if (parent == NULL)
{
I_Error ("Parent type '%s' not found in %s", parentName.GetChars(), typeName.GetChars());
}
else if (!parent->IsDescendantOf(RUNTIME_CLASS(AActor)))
{
I_Error ("Parent type '%s' is not an actor in %s", parentName.GetChars(), typeName.GetChars());
}
else if (parent->ActorInfo == NULL)
{
I_Error ("uninitialized parent type '%s' in %s", parentName.GetChars(), typeName.GetChars());
}
else sc.UnGet();
}
// Check for "replaces"
if (sc.CheckString ("replaces"))
if (replaceName != NAME_None)
{
// Get actor name
sc.MustGetString ();
replacee = PClass::FindClass (sc.String);
replacee = PClass::FindClass (replaceName);
if (replacee == NULL)
{
sc.ScriptError ("Replaced type '%s' not found", sc.String);
I_Error ("Replaced type '%s' not found in %s", replaceName.GetChars(), typeName.GetChars());
}
else if (replacee->ActorInfo == NULL)
{
sc.ScriptError ("Replaced type '%s' is not an actor", sc.String);
I_Error ("Replaced type '%s' is not an actor in %s", replaceName.GetChars(), typeName.GetChars());
}
}
// Now, after the actor names have been parsed, it is time to switch to C-mode
// for the rest of the actor definition.
sc.SetCMode (true);
if (sc.CheckNumber())
{
if (sc.Number>=-1 && sc.Number<32768) DoomEdNum = sc.Number;
else sc.ScriptError ("DoomEdNum must be in the range [-1,32767]");
}
if (sc.CheckString("native"))
Printf("Defining %s\n", typeName.GetChars());
if (native)
{
ti = (PClass*)PClass::FindClass(typeName);
if (ti == NULL)
{
sc.ScriptError("Unknown native class '%s'", typeName.GetChars());
I_Error("Unknown native class '%s'", typeName.GetChars());
}
else if (ti != RUNTIME_CLASS(AActor) && ti->ParentClass->NativeClass() != parent->NativeClass())
{
sc.ScriptError("Native class '%s' does not inherit from '%s'",
typeName.GetChars(),parent->TypeName.GetChars());
I_Error("Native class '%s' does not inherit from '%s'", typeName.GetChars(), parentName.GetChars());
}
else if (ti->ActorInfo != NULL)
{
sc.ScriptMessage("Redefinition of internal class '%s'", typeName.GetChars());
I_Error("Redefinition of internal class '%s'", typeName.GetChars());
}
ti->InitializeActorInfo();
info = ti->ActorInfo;
@ -482,10 +423,6 @@ static FActorInfo *CreateNewActor(FScanner &sc, FActorInfo **parentc, Baggage *b
MakeStateDefines(parent->ActorInfo->StateList);
ResetBaggage (bag);
bag->Info = info;
bag->Lumpnum = sc.LumpNum;
info->DoomEdNum = -1;
if (parent->ActorInfo->DamageFactors != NULL)
{
@ -506,10 +443,98 @@ static FActorInfo *CreateNewActor(FScanner &sc, FActorInfo **parentc, Baggage *b
ti->ActorInfo->Replacee = replacee->ActorInfo;
}
info->DoomEdNum = DoomEdNum;
if (DoomEdNum > 0) info->DoomEdNum = DoomEdNum;
return info;
}
//==========================================================================
//
// Starts a new actor definition
//
//==========================================================================
static FActorInfo *ParseActorHeader(FScanner &sc, Baggage *bag)
{
FName typeName;
FName parentName;
FName replaceName;
bool native = false;
int DoomEdNum = -1;
// Get actor name
sc.MustGetString();
char *colon = strchr(sc.String, ':');
if (colon != NULL)
{
*colon++ = 0;
}
typeName = sc.String;
// Do some tweaking so that a definition like 'Actor:Parent' which is read as a single token is recognized as well
// without having resort to C-mode (which disallows periods in actor names.)
if (colon == NULL)
{
sc.MustGetString ();
if (sc.String[0]==':')
{
colon = sc.String + 1;
}
}
if (colon != NULL)
{
if (colon[0] == 0)
{
sc.MustGetString ();
colon = sc.String;
}
}
if (colon == NULL)
{
sc.UnGet();
}
parentName = colon;
// Check for "replaces"
if (sc.CheckString ("replaces"))
{
// Get actor name
sc.MustGetString ();
replaceName = sc.String;
}
// Now, after the actor names have been parsed, it is time to switch to C-mode
// for the rest of the actor definition.
sc.SetCMode (true);
if (sc.CheckNumber())
{
if (sc.Number>=-1 && sc.Number<32768) DoomEdNum = sc.Number;
else sc.ScriptError ("DoomEdNum must be in the range [-1,32767]");
}
if (sc.CheckString("native"))
{
native = true;
}
try
{
FActorInfo *info = CreateNewActor(typeName, parentName, replaceName, DoomEdNum, native);
ResetBaggage (bag);
bag->Info = info;
bag->Lumpnum = sc.LumpNum;
return info;
}
catch (CRecoverableError &err)
{
sc.ScriptError("%s", err.GetMessage());
return NULL;
}
}
//==========================================================================
//
// Reads an actor definition
@ -520,64 +545,41 @@ void ParseActor(FScanner &sc)
FActorInfo * info=NULL;
Baggage bag;
try
info = ParseActorHeader(sc, &bag);
sc.MustGetToken('{');
while (sc.MustGetAnyToken(), sc.TokenType != '}')
{
FActorInfo * parent;
info = CreateNewActor(sc, &parent, &bag);
sc.MustGetToken('{');
while (sc.MustGetAnyToken(), sc.TokenType != '}')
switch (sc.TokenType)
{
switch (sc.TokenType)
{
case TK_Action:
ParseActionDef (sc, info->Class);
break;
case TK_Action:
ParseActionDef (sc, info->Class);
break;
case TK_Const:
ParseConstant (sc, &info->Class->Symbols, info->Class);
break;
case TK_Const:
ParseConstant (sc, &info->Class->Symbols, info->Class);
break;
case TK_Enum:
ParseEnum (sc, &info->Class->Symbols, info->Class);
break;
case TK_Enum:
ParseEnum (sc, &info->Class->Symbols, info->Class);
break;
case TK_Identifier:
// other identifier related checks here
case TK_Projectile: // special case: both keyword and property name
ParseActorProperty(sc, bag);
break;
case TK_Identifier:
// other identifier related checks here
case TK_Projectile: // special case: both keyword and property name
ParseActorProperty(sc, bag);
break;
case '+':
case '-':
ParseActorFlag(sc, bag, sc.TokenType);
break;
default:
sc.ScriptError("Unexpected '%s' in definition of '%s'", sc.String, bag.Info->Class->TypeName.GetChars());
break;
}
case '+':
case '-':
ParseActorFlag(sc, bag, sc.TokenType);
break;
default:
sc.ScriptError("Unexpected '%s' in definition of '%s'", sc.String, bag.Info->Class->TypeName.GetChars());
break;
}
FinishActor(sc, info, bag);
}
catch(CRecoverableError & e)
{
throw e;
}
// I think this is better than a crash log.
#ifndef _DEBUG
catch (...)
{
if (info)
sc.ScriptError("Unexpected error during parsing of actor %s", info->Class->TypeName.GetChars());
else
sc.ScriptError("Unexpected error during parsing of actor definitions");
}
#endif
sc.SetCMode (false);
}
@ -589,10 +591,33 @@ void ParseActor(FScanner &sc)
//
//==========================================================================
static int ResolvePointer(const PClass **pPtr, const PClass *owner, const PClass *destclass, const char *description)
{
fuglyname v;
v = *pPtr;
if (v != NAME_None && v.IsValidName())
{
*pPtr = PClass::FindClass(v);
if (!*pPtr)
{
Printf("Unknown %s '%s' in '%s'\n", description, v.GetChars(), owner->TypeName.GetChars());
return 1;
}
else if (!(*pPtr)->IsDescendantOf(destclass))
{
*pPtr = NULL;
Printf("Invalid %s '%s' in '%s'\n", description, v.GetChars(), owner->TypeName.GetChars());
return 1;
}
}
return 0;
}
void FinishThingdef()
{
unsigned int i;
bool isRuntimeActor=false;
int errorcount=0;
for (i = 0;i < PClass::m_Types.Size(); i++)
@ -602,13 +627,6 @@ void FinishThingdef()
// Skip non-actors
if (!ti->IsDescendantOf(RUNTIME_CLASS(AActor))) continue;
// Everything coming after the first runtime actor is also a runtime actor
// so this check is sufficient
if (ti == PClass::m_RuntimeActors[0])
{
isRuntimeActor=true;
}
AActor *def = GetDefaultByType(ti);
if (!def)
@ -627,21 +645,7 @@ void FinishThingdef()
if (ti->IsDescendantOf(RUNTIME_CLASS(AInventory)))
{
AInventory * defaults=(AInventory *)def;
fuglyname v;
v = defaults->PickupFlash;
if (v != NAME_None && v.IsValidName())
{
defaults->PickupFlash = PClass::FindClass(v);
if (isRuntimeActor)
{
if (!defaults->PickupFlash)
{
Printf("Unknown pickup flash '%s' in '%s'\n", v.GetChars(), ti->TypeName.GetChars());
errorcount++;
}
}
}
errorcount += ResolvePointer(&defaults->PickupFlash, ti, RUNTIME_CLASS(AActor), "pickup flash");
}
if (ti->IsDescendantOf(RUNTIME_CLASS(APowerupGiver)) && ti != RUNTIME_CLASS(APowerupGiver))
@ -683,122 +687,47 @@ void FinishThingdef()
if (ti->IsDescendantOf(RUNTIME_CLASS(AWeapon)))
{
AWeapon * defaults=(AWeapon *)def;
fuglyname v;
errorcount += ResolvePointer(&defaults->AmmoType1, ti, RUNTIME_CLASS(AAmmo), "ammo type");
errorcount += ResolvePointer(&defaults->AmmoType2, ti, RUNTIME_CLASS(AAmmo), "ammo type");
errorcount += ResolvePointer(&defaults->SisterWeaponType, ti, RUNTIME_CLASS(AWeapon), "sister weapon type");
v = defaults->AmmoType1;
if (v != NAME_None && v.IsValidName())
FState * ready = ti->ActorInfo->FindState(NAME_Ready);
FState * select = ti->ActorInfo->FindState(NAME_Select);
FState * deselect = ti->ActorInfo->FindState(NAME_Deselect);
FState * fire = ti->ActorInfo->FindState(NAME_Fire);
// Consider any weapon without any valid state abstract and don't output a warning
// This is for creating base classes for weapon groups that only set up some properties.
if (ready || select || deselect || fire)
{
defaults->AmmoType1 = PClass::FindClass(v);
if (isRuntimeActor)
// Do some consistency checks. If these states are undefined the weapon cannot work!
if (!ready)
{
if (!defaults->AmmoType1)
{
Printf("Unknown ammo type '%s' in '%s'\n", v.GetChars(), ti->TypeName.GetChars());
errorcount++;
}
else if (defaults->AmmoType1->ParentClass != RUNTIME_CLASS(AAmmo))
{
Printf("Invalid ammo type '%s' in '%s'\n", v.GetChars(), ti->TypeName.GetChars());
errorcount++;
}
Printf("Weapon %s doesn't define a ready state.\n", ti->TypeName.GetChars());
errorcount++;
}
if (!select)
{
Printf("Weapon %s doesn't define a select state.\n", ti->TypeName.GetChars());
errorcount++;
}
if (!deselect)
{
Printf("Weapon %s doesn't define a deselect state.\n", ti->TypeName.GetChars());
errorcount++;
}
if (!fire)
{
Printf("Weapon %s doesn't define a fire state.\n", ti->TypeName.GetChars());
errorcount++;
}
}
v = defaults->AmmoType2;
if (v != NAME_None && v.IsValidName())
{
defaults->AmmoType2 = PClass::FindClass(v);
if (isRuntimeActor)
{
if (!defaults->AmmoType2)
{
Printf("Unknown ammo type '%s' in '%s'\n", v.GetChars(), ti->TypeName.GetChars());
errorcount++;
}
else if (defaults->AmmoType2->ParentClass != RUNTIME_CLASS(AAmmo))
{
Printf("Invalid ammo type '%s' in '%s'\n", v.GetChars(), ti->TypeName.GetChars());
errorcount++;
}
}
}
v = defaults->SisterWeaponType;
if (v != NAME_None && v.IsValidName())
{
defaults->SisterWeaponType = PClass::FindClass(v);
if (isRuntimeActor)
{
if (!defaults->SisterWeaponType)
{
Printf("Unknown sister weapon type '%s' in '%s'\n", v.GetChars(), ti->TypeName.GetChars());
errorcount++;
}
else if (!defaults->SisterWeaponType->IsDescendantOf(RUNTIME_CLASS(AWeapon)))
{
Printf("Invalid sister weapon type '%s' in '%s'\n", v.GetChars(), ti->TypeName.GetChars());
errorcount++;
}
}
}
if (isRuntimeActor)
{
FState * ready = ti->ActorInfo->FindState(NAME_Ready);
FState * select = ti->ActorInfo->FindState(NAME_Select);
FState * deselect = ti->ActorInfo->FindState(NAME_Deselect);
FState * fire = ti->ActorInfo->FindState(NAME_Fire);
// Consider any weapon without any valid state abstract and don't output a warning
// This is for creating base classes for weapon groups that only set up some properties.
if (ready || select || deselect || fire)
{
// Do some consistency checks. If these states are undefined the weapon cannot work!
if (!ready)
{
Printf("Weapon %s doesn't define a ready state.\n", ti->TypeName.GetChars());
errorcount++;
}
if (!select)
{
Printf("Weapon %s doesn't define a select state.\n", ti->TypeName.GetChars());
errorcount++;
}
if (!deselect)
{
Printf("Weapon %s doesn't define a deselect state.\n", ti->TypeName.GetChars());
errorcount++;
}
if (!fire)
{
Printf("Weapon %s doesn't define a fire state.\n", ti->TypeName.GetChars());
errorcount++;
}
}
}
}
// same for the weapon type of weapon pieces.
else if (ti->IsDescendantOf(RUNTIME_CLASS(AWeaponPiece)))
{
AWeaponPiece * defaults=(AWeaponPiece *)def;
fuglyname v;
v = defaults->WeaponClass;
if (v != NAME_None && v.IsValidName())
{
defaults->WeaponClass = PClass::FindClass(v);
if (!defaults->WeaponClass)
{
Printf("Unknown weapon type '%s' in '%s'\n", v.GetChars(), ti->TypeName.GetChars());
errorcount++;
}
else if (!defaults->WeaponClass->IsDescendantOf(RUNTIME_CLASS(AWeapon)))
{
Printf("Invalid weapon type '%s' in '%s'\n", v.GetChars(), ti->TypeName.GetChars());
errorcount++;
}
}
errorcount += ResolvePointer(&defaults->WeaponClass, ti, RUNTIME_CLASS(AWeapon), "weapon type");
}
}
if (errorcount > 0)