- 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:
parent
6227906072
commit
8a79985f46
7 changed files with 255 additions and 355 deletions
|
|
@ -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)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue