mirror of
https://github.com/ZDoom/qzdoom.git
synced 2024-11-28 06:53:58 +00:00
- Made several DECORATE errors which do not involve parsing non-fatal.
- Added a static error counter to FScriptPosition class. - Changed initialization of actor class type properties: fuglyname is gone as is the postprocessing in FinishThingdef. Instead an empty placeholder class is now created when a class is first referenced and this placeholder is later filled in. - Added option to replace backslash with '^' in state frame definitions because the backslash is just causing too many problems because it's also an escape character. SVN r1334 (trunk)
This commit is contained in:
parent
8f686a5e02
commit
f8c38e5f54
12 changed files with 211 additions and 186 deletions
|
@ -1,3 +1,14 @@
|
||||||
|
December 30, 2008 (Changes by Graf Zahl)
|
||||||
|
- Made several DECORATE errors which do not involve parsing non-fatal.
|
||||||
|
- Added a static error counter to FScriptPosition class.
|
||||||
|
- Changed initialization of actor class type properties: fuglyname is gone as
|
||||||
|
is the postprocessing in FinishThingdef. Instead an empty placeholder class
|
||||||
|
is now created when a class is first referenced and this placeholder is later
|
||||||
|
filled in.
|
||||||
|
- Added option to replace backslash with '^' in state frame definitions because
|
||||||
|
the backslash is just causing too many problems because it's also an escape
|
||||||
|
character.
|
||||||
|
|
||||||
December 28, 2008 (Changes by Graf Zahl)
|
December 28, 2008 (Changes by Graf Zahl)
|
||||||
- Added Karate Chris's new DMFlags submission.
|
- Added Karate Chris's new DMFlags submission.
|
||||||
|
|
||||||
|
|
|
@ -216,7 +216,7 @@ const PClass *PClass::FindClass (FName zaname)
|
||||||
}
|
}
|
||||||
else if (lexx == 0)
|
else if (lexx == 0)
|
||||||
{
|
{
|
||||||
return cls;
|
return cls->Size<0? NULL : cls;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -247,15 +247,34 @@ DObject *PClass::CreateNew () const
|
||||||
PClass *PClass::CreateDerivedClass (FName name, unsigned int size)
|
PClass *PClass::CreateDerivedClass (FName name, unsigned int size)
|
||||||
{
|
{
|
||||||
assert (size >= Size);
|
assert (size >= Size);
|
||||||
|
PClass *type;
|
||||||
|
bool notnew;
|
||||||
|
|
||||||
PClass *type = new PClass;
|
const PClass *existclass = FindClass(name);
|
||||||
|
|
||||||
|
// This is a placeholder so fill it in
|
||||||
|
if (existclass != NULL && existclass->Size == -1)
|
||||||
|
{
|
||||||
|
type = const_cast<PClass*>(existclass);
|
||||||
|
if (!IsDescendantOf(type->ParentClass))
|
||||||
|
{
|
||||||
|
I_Error("%s must inherit from %s but doesn't.", name.GetChars(), type->ParentClass->TypeName.GetChars());
|
||||||
|
}
|
||||||
|
Printf("Defining placeholder class %s\n", name.GetChars());
|
||||||
|
notnew = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
type = new PClass;
|
||||||
|
notnew = false;
|
||||||
|
}
|
||||||
|
|
||||||
type->TypeName = name;
|
type->TypeName = name;
|
||||||
type->ParentClass = this;
|
type->ParentClass = this;
|
||||||
type->Size = size;
|
type->Size = size;
|
||||||
type->Pointers = NULL;
|
type->Pointers = NULL;
|
||||||
type->ConstructNative = ConstructNative;
|
type->ConstructNative = ConstructNative;
|
||||||
type->ClassIndex = m_Types.Push (type);
|
if (!notnew) type->ClassIndex = m_Types.Push (type);
|
||||||
type->Meta = Meta;
|
type->Meta = Meta;
|
||||||
type->Defaults = new BYTE[size];
|
type->Defaults = new BYTE[size];
|
||||||
memcpy (type->Defaults, Defaults, Size);
|
memcpy (type->Defaults, Defaults, Size);
|
||||||
|
@ -267,7 +286,7 @@ PClass *PClass::CreateDerivedClass (FName name, unsigned int size)
|
||||||
type->bRuntimeClass = true;
|
type->bRuntimeClass = true;
|
||||||
type->ActorInfo = NULL;
|
type->ActorInfo = NULL;
|
||||||
type->Symbols.SetParentTable (&this->Symbols);
|
type->Symbols.SetParentTable (&this->Symbols);
|
||||||
type->InsertIntoHash();
|
if (!notnew) type->InsertIntoHash();
|
||||||
|
|
||||||
// If this class has an actor info, then any classes derived from it
|
// If this class has an actor info, then any classes derived from it
|
||||||
// also need an actor info.
|
// also need an actor info.
|
||||||
|
@ -290,6 +309,51 @@ PClass *PClass::CreateDerivedClass (FName name, unsigned int size)
|
||||||
return type;
|
return type;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Like FindClass but creates a placeholder if no class
|
||||||
|
// is found. CreateDerivedClass will automatcally fill in
|
||||||
|
// the placeholder when the actual class is defined.
|
||||||
|
const PClass *PClass::FindClassTentative (FName name)
|
||||||
|
{
|
||||||
|
if (name == NAME_None)
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
PClass *cls = TypeHash[name % HASH_SIZE];
|
||||||
|
|
||||||
|
while (cls != 0)
|
||||||
|
{
|
||||||
|
int lexx = int(name) - int(cls->TypeName);
|
||||||
|
if (lexx > 0)
|
||||||
|
{
|
||||||
|
cls = cls->HashNext;
|
||||||
|
}
|
||||||
|
else if (lexx == 0)
|
||||||
|
{
|
||||||
|
return cls;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
PClass *type = new PClass;
|
||||||
|
Printf("Creating placeholder class %s : %s\n", name.GetChars(), TypeName.GetChars());
|
||||||
|
|
||||||
|
type->TypeName = name;
|
||||||
|
type->ParentClass = this;
|
||||||
|
type->Size = -1;
|
||||||
|
type->Pointers = NULL;
|
||||||
|
type->ConstructNative = NULL;
|
||||||
|
type->ClassIndex = m_Types.Push (type);
|
||||||
|
type->Defaults = NULL;
|
||||||
|
type->FlatPointers = NULL;
|
||||||
|
type->bRuntimeClass = true;
|
||||||
|
type->ActorInfo = NULL;
|
||||||
|
type->InsertIntoHash();
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
|
||||||
// This is used by DECORATE to assign ActorInfos to internal classes
|
// This is used by DECORATE to assign ActorInfos to internal classes
|
||||||
void PClass::InitializeActorInfo ()
|
void PClass::InitializeActorInfo ()
|
||||||
{
|
{
|
||||||
|
|
|
@ -169,6 +169,7 @@ struct PClass
|
||||||
static const PClass *FindClass (const FString &name) { return FindClass (FName (name, true)); }
|
static const PClass *FindClass (const FString &name) { return FindClass (FName (name, true)); }
|
||||||
static const PClass *FindClass (ENamedName name) { return FindClass (FName (name)); }
|
static const PClass *FindClass (ENamedName name) { return FindClass (FName (name)); }
|
||||||
static const PClass *FindClass (FName name);
|
static const PClass *FindClass (FName name);
|
||||||
|
const PClass *FindClassTentative (FName name); // not static!
|
||||||
|
|
||||||
static TArray<PClass *> m_Types;
|
static TArray<PClass *> m_Types;
|
||||||
static TArray<PClass *> m_RuntimeActors;
|
static TArray<PClass *> m_RuntimeActors;
|
||||||
|
|
|
@ -826,8 +826,14 @@ bool FStateDefinitions::AddStates(FState *state, const char *framechars)
|
||||||
bool error = false;
|
bool error = false;
|
||||||
while (*framechars)
|
while (*framechars)
|
||||||
{
|
{
|
||||||
int frame=((*framechars++)&223)-'A';
|
int frame;
|
||||||
|
|
||||||
|
if (*framechars == '^')
|
||||||
|
frame = '\\'-'A';
|
||||||
|
else
|
||||||
|
frame = ((*framechars)&223)-'A';
|
||||||
|
|
||||||
|
framechars++;
|
||||||
if (frame<0 || frame>28)
|
if (frame<0 || frame>28)
|
||||||
{
|
{
|
||||||
frame = 0;
|
frame = 0;
|
||||||
|
|
|
@ -1030,6 +1030,7 @@ void FScanner::CheckOpen()
|
||||||
// a class that remembers a parser position
|
// a class that remembers a parser position
|
||||||
//
|
//
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
int FScriptPosition::ErrorCounter;
|
||||||
|
|
||||||
FScriptPosition::FScriptPosition(const FScriptPosition &other)
|
FScriptPosition::FScriptPosition(const FScriptPosition &other)
|
||||||
{
|
{
|
||||||
|
@ -1092,6 +1093,7 @@ void STACK_ARGS FScriptPosition::Message (int severity, const char *message, ...
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case MSG_ERROR:
|
case MSG_ERROR:
|
||||||
|
ErrorCounter++;
|
||||||
type = "error";
|
type = "error";
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|
|
@ -238,6 +238,7 @@ enum
|
||||||
|
|
||||||
struct FScriptPosition
|
struct FScriptPosition
|
||||||
{
|
{
|
||||||
|
static int ErrorCounter;
|
||||||
FString FileName;
|
FString FileName;
|
||||||
int ScriptLine;
|
int ScriptLine;
|
||||||
|
|
||||||
|
@ -250,6 +251,10 @@ struct FScriptPosition
|
||||||
FScriptPosition(FScanner &sc);
|
FScriptPosition(FScanner &sc);
|
||||||
FScriptPosition &operator=(const FScriptPosition &other);
|
FScriptPosition &operator=(const FScriptPosition &other);
|
||||||
void Message(int severity, const char *message,...) const;
|
void Message(int severity, const char *message,...) const;
|
||||||
|
static void ResetErrorCounter()
|
||||||
|
{
|
||||||
|
ErrorCounter = 0;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -184,7 +184,8 @@ void SetReplacement(FActorInfo *info, FName replaceName)
|
||||||
|
|
||||||
void FinishActor(const FScriptPosition &sc, FActorInfo *info, Baggage &bag)
|
void FinishActor(const FScriptPosition &sc, FActorInfo *info, Baggage &bag)
|
||||||
{
|
{
|
||||||
AActor *defaults = (AActor*)info->Class->Defaults;
|
PClass *ti = info->Class;
|
||||||
|
AActor *defaults = (AActor*)ti->Defaults;
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
@ -192,7 +193,9 @@ void FinishActor(const FScriptPosition &sc, FActorInfo *info, Baggage &bag)
|
||||||
}
|
}
|
||||||
catch (CRecoverableError &err)
|
catch (CRecoverableError &err)
|
||||||
{
|
{
|
||||||
sc.Message(MSG_FATAL, "%s", err.GetMessage());
|
sc.Message(MSG_ERROR, "%s", err.GetMessage());
|
||||||
|
bag.statedef.MakeStateDefines(NULL);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
bag.statedef.InstallStates (info, defaults);
|
bag.statedef.InstallStates (info, defaults);
|
||||||
bag.statedef.MakeStateDefines(NULL);
|
bag.statedef.MakeStateDefines(NULL);
|
||||||
|
@ -200,69 +203,78 @@ void FinishActor(const FScriptPosition &sc, FActorInfo *info, Baggage &bag)
|
||||||
{
|
{
|
||||||
if (bag.DropItemList == NULL)
|
if (bag.DropItemList == NULL)
|
||||||
{
|
{
|
||||||
if (info->Class->Meta.GetMetaInt (ACMETA_DropItems) != 0)
|
if (ti->Meta.GetMetaInt (ACMETA_DropItems) != 0)
|
||||||
{
|
{
|
||||||
info->Class->Meta.SetMetaInt (ACMETA_DropItems, 0);
|
ti->Meta.SetMetaInt (ACMETA_DropItems, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
info->Class->Meta.SetMetaInt (ACMETA_DropItems,
|
ti->Meta.SetMetaInt (ACMETA_DropItems,
|
||||||
StoreDropItemChain(bag.DropItemList));
|
StoreDropItemChain(bag.DropItemList));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (info->Class->IsDescendantOf (RUNTIME_CLASS(AInventory)))
|
if (ti->IsDescendantOf (RUNTIME_CLASS(AInventory)))
|
||||||
{
|
{
|
||||||
defaults->flags |= MF_SPECIAL;
|
defaults->flags |= MF_SPECIAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Weapons must be checked for all relevant states. They may crash the game otherwise.
|
||||||
|
if (ti->IsDescendantOf(RUNTIME_CLASS(AWeapon)))
|
||||||
|
{
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
if (!ready)
|
||||||
|
{
|
||||||
|
sc.Message(MSG_ERROR, "Weapon %s doesn't define a ready state.\n", ti->TypeName.GetChars());
|
||||||
|
}
|
||||||
|
if (!select)
|
||||||
|
{
|
||||||
|
sc.Message(MSG_ERROR, "Weapon %s doesn't define a select state.\n", ti->TypeName.GetChars());
|
||||||
|
}
|
||||||
|
if (!deselect)
|
||||||
|
{
|
||||||
|
sc.Message(MSG_ERROR, "Weapon %s doesn't define a deselect state.\n", ti->TypeName.GetChars());
|
||||||
|
}
|
||||||
|
if (!fire)
|
||||||
|
{
|
||||||
|
sc.Message(MSG_ERROR, "Weapon %s doesn't define a fire state.\n", ti->TypeName.GetChars());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
//
|
//
|
||||||
// Do some postprocessing after everything has been defined
|
// Do some postprocessing after everything has been defined
|
||||||
// This also processes all the internal actors to adjust the type
|
|
||||||
// fields in the weapons
|
|
||||||
//
|
//
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static void FinishThingdef()
|
static void FinishThingdef()
|
||||||
{
|
{
|
||||||
unsigned int i;
|
int errorcount = StateParams.ResolveAll();
|
||||||
int errorcount;
|
|
||||||
|
|
||||||
errorcount = StateParams.ResolveAll();
|
for (unsigned i = 0;i < PClass::m_Types.Size(); i++)
|
||||||
|
|
||||||
for (i = 0;i < PClass::m_Types.Size(); i++)
|
|
||||||
{
|
{
|
||||||
PClass * ti = PClass::m_Types[i];
|
PClass * ti = PClass::m_Types[i];
|
||||||
|
|
||||||
// Skip non-actors
|
// Skip non-actors
|
||||||
if (!ti->IsDescendantOf(RUNTIME_CLASS(AActor))) continue;
|
if (!ti->IsDescendantOf(RUNTIME_CLASS(AActor))) continue;
|
||||||
|
|
||||||
|
if (ti->Size == -1)
|
||||||
|
{
|
||||||
|
Printf("Class %s referenced but not defined\n", ti->TypeName.GetChars());
|
||||||
|
errorcount++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
AActor *def = GetDefaultByType(ti);
|
AActor *def = GetDefaultByType(ti);
|
||||||
|
|
||||||
if (!def)
|
if (!def)
|
||||||
|
@ -271,100 +283,6 @@ static void FinishThingdef()
|
||||||
errorcount++;
|
errorcount++;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Friendlies never count as kills!
|
|
||||||
if (def->flags & MF_FRIENDLY)
|
|
||||||
{
|
|
||||||
def->flags &=~MF_COUNTKILL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ti->IsDescendantOf(RUNTIME_CLASS(AInventory)))
|
|
||||||
{
|
|
||||||
AInventory * defaults=(AInventory *)def;
|
|
||||||
errorcount += ResolvePointer(&defaults->PickupFlash, ti, RUNTIME_CLASS(AActor), "pickup flash");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ti->IsDescendantOf(RUNTIME_CLASS(APowerupGiver)) && ti != RUNTIME_CLASS(APowerupGiver))
|
|
||||||
{
|
|
||||||
FString typestr;
|
|
||||||
APowerupGiver * defaults=(APowerupGiver *)def;
|
|
||||||
fuglyname v;
|
|
||||||
|
|
||||||
v = defaults->PowerupType;
|
|
||||||
if (v != NAME_None && v.IsValidName())
|
|
||||||
{
|
|
||||||
typestr.Format ("Power%s", v.GetChars());
|
|
||||||
const PClass * powertype=PClass::FindClass(typestr);
|
|
||||||
if (!powertype) powertype=PClass::FindClass(v.GetChars());
|
|
||||||
|
|
||||||
if (!powertype)
|
|
||||||
{
|
|
||||||
Printf("Unknown powerup type '%s' in '%s'\n", v.GetChars(), ti->TypeName.GetChars());
|
|
||||||
errorcount++;
|
|
||||||
}
|
|
||||||
else if (!powertype->IsDescendantOf(RUNTIME_CLASS(APowerup)))
|
|
||||||
{
|
|
||||||
Printf("Invalid powerup type '%s' in '%s'\n", v.GetChars(), ti->TypeName.GetChars());
|
|
||||||
errorcount++;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
defaults->PowerupType=powertype;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (v == NAME_None)
|
|
||||||
{
|
|
||||||
Printf("No powerup type specified in '%s'\n", ti->TypeName.GetChars());
|
|
||||||
errorcount++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// the typeinfo properties of weapons have to be fixed here after all actors have been declared
|
|
||||||
if (ti->IsDescendantOf(RUNTIME_CLASS(AWeapon)))
|
|
||||||
{
|
|
||||||
AWeapon * defaults=(AWeapon *)def;
|
|
||||||
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");
|
|
||||||
|
|
||||||
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;
|
|
||||||
errorcount += ResolvePointer(&defaults->WeaponClass, ti, RUNTIME_CLASS(AWeapon), "weapon type");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (errorcount > 0)
|
if (errorcount > 0)
|
||||||
{
|
{
|
||||||
|
@ -378,7 +296,6 @@ static void FinishThingdef()
|
||||||
mysnprintf(fmt, countof(fmt), "QuestItem%d", i+1);
|
mysnprintf(fmt, countof(fmt), "QuestItem%d", i+1);
|
||||||
QuestItemClasses[i] = PClass::FindClass(fmt);
|
QuestItemClasses[i] = PClass::FindClass(fmt);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -395,6 +312,7 @@ void LoadActors ()
|
||||||
{
|
{
|
||||||
int lastlump, lump;
|
int lastlump, lump;
|
||||||
|
|
||||||
|
FScriptPosition::ResetErrorCounter();
|
||||||
InitThingdef();
|
InitThingdef();
|
||||||
lastlump = 0;
|
lastlump = 0;
|
||||||
while ((lump = Wads.FindLump ("DECORATE", &lastlump)) != -1)
|
while ((lump = Wads.FindLump ("DECORATE", &lastlump)) != -1)
|
||||||
|
@ -402,6 +320,10 @@ void LoadActors ()
|
||||||
FScanner sc(lump);
|
FScanner sc(lump);
|
||||||
ParseDecorate (sc);
|
ParseDecorate (sc);
|
||||||
}
|
}
|
||||||
|
if (FScriptPosition::ErrorCounter > 0)
|
||||||
|
{
|
||||||
|
I_Error("%d errors while parsing DECORATE scripts", FScriptPosition::ErrorCounter);
|
||||||
|
}
|
||||||
FinishThingdef();
|
FinishThingdef();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -27,31 +27,6 @@ FFlagDef *FindFlag (const PClass *type, const char *part1, const char *part2);
|
||||||
void HandleDeprecatedFlags(AActor *defaults, FActorInfo *info, bool set, int index);
|
void HandleDeprecatedFlags(AActor *defaults, FActorInfo *info, bool set, int index);
|
||||||
|
|
||||||
|
|
||||||
//==========================================================================
|
|
||||||
//
|
|
||||||
// This class is for storing a name inside a const PClass* field without
|
|
||||||
// generating compiler warnings. It does not manipulate data in any other
|
|
||||||
// way.
|
|
||||||
//
|
|
||||||
//==========================================================================
|
|
||||||
class fuglyname : public FName
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
fuglyname() : FName() {}
|
|
||||||
fuglyname(const char *foo) : FName(foo) {}
|
|
||||||
operator const PClass *()
|
|
||||||
{
|
|
||||||
return reinterpret_cast<const PClass *>(size_t(int(*this)));
|
|
||||||
}
|
|
||||||
fuglyname &operator= (const PClass *foo)
|
|
||||||
{
|
|
||||||
FName *p = this;
|
|
||||||
*p = ENamedName(reinterpret_cast<size_t>(foo));
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
//
|
//
|
||||||
// State parser
|
// State parser
|
||||||
|
|
|
@ -62,6 +62,12 @@ struct FCompileContext
|
||||||
bool lax;
|
bool lax;
|
||||||
bool isconst;
|
bool isconst;
|
||||||
|
|
||||||
|
FCompileContext(const PClass *_cls = NULL, bool _lax = false, bool _isconst = false)
|
||||||
|
{
|
||||||
|
cls = _cls;
|
||||||
|
lax = _lax;
|
||||||
|
isconst = _isconst;
|
||||||
|
}
|
||||||
|
|
||||||
PSymbol *FindInClass(FName identifier)
|
PSymbol *FindInClass(FName identifier)
|
||||||
{
|
{
|
||||||
|
|
|
@ -232,7 +232,7 @@ static ExpVal GetVariableValue (void *address, FExpressionType &type)
|
||||||
|
|
||||||
ExpVal FxExpression::EvalExpression (AActor *self)
|
ExpVal FxExpression::EvalExpression (AActor *self)
|
||||||
{
|
{
|
||||||
I_Error("Unresolved expression found");
|
ScriptPosition.Message(MSG_ERROR, "Unresolved expression found");
|
||||||
ExpVal val;
|
ExpVal val;
|
||||||
|
|
||||||
val.Type = VAL_Int;
|
val.Type = VAL_Int;
|
||||||
|
@ -2635,23 +2635,27 @@ FxExpression *FxMultiNameState::Resolve(FCompileContext &ctx)
|
||||||
}
|
}
|
||||||
if (scope != NULL)
|
if (scope != NULL)
|
||||||
{
|
{
|
||||||
|
FState *destination = NULL;
|
||||||
// If the label is class specific we can resolve it right here
|
// If the label is class specific we can resolve it right here
|
||||||
if (scope->ActorInfo == NULL)
|
if (names[1] != NAME_None)
|
||||||
{
|
{
|
||||||
ScriptPosition.Message(MSG_ERROR, "'%s' has no actorinfo", names[0].GetChars());
|
if (scope->ActorInfo == NULL)
|
||||||
delete this;
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
FState *destination = scope->ActorInfo->FindState(names.Size()-1, &names[1], false);
|
|
||||||
if (destination == NULL)
|
|
||||||
{
|
|
||||||
ScriptPosition.Message(ctx.lax? MSG_WARNING:MSG_ERROR, "Unknown state jump destination");
|
|
||||||
if (!ctx.lax)
|
|
||||||
{
|
{
|
||||||
|
ScriptPosition.Message(MSG_ERROR, "'%s' has no actorinfo", names[0].GetChars());
|
||||||
delete this;
|
delete this;
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
return this;
|
destination = scope->ActorInfo->FindState(names.Size()-1, &names[1], false);
|
||||||
|
if (destination == NULL)
|
||||||
|
{
|
||||||
|
ScriptPosition.Message(ctx.lax? MSG_WARNING:MSG_ERROR, "Unknown state jump destination");
|
||||||
|
if (!ctx.lax)
|
||||||
|
{
|
||||||
|
delete this;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
FxExpression *x = new FxConstant(destination, ScriptPosition);
|
FxExpression *x = new FxConstant(destination, ScriptPosition);
|
||||||
delete this;
|
delete this;
|
||||||
|
@ -2707,7 +2711,7 @@ FStateExpressions StateParams;
|
||||||
|
|
||||||
FStateExpressions::~FStateExpressions()
|
FStateExpressions::~FStateExpressions()
|
||||||
{
|
{
|
||||||
for(int i=0; i<Size(); i++)
|
for(unsigned i=0; i<Size(); i++)
|
||||||
{
|
{
|
||||||
if (expressions[i].expr != NULL && !expressions[i].cloned)
|
if (expressions[i].expr != NULL && !expressions[i].cloned)
|
||||||
{
|
{
|
||||||
|
@ -2797,7 +2801,7 @@ int FStateExpressions::ResolveAll()
|
||||||
|
|
||||||
FCompileContext ctx;
|
FCompileContext ctx;
|
||||||
ctx.lax = true;
|
ctx.lax = true;
|
||||||
for(int i=0; i<Size(); i++)
|
for(unsigned i=0; i<Size(); i++)
|
||||||
{
|
{
|
||||||
if (expressions[i].cloned)
|
if (expressions[i].cloned)
|
||||||
{
|
{
|
||||||
|
@ -2822,7 +2826,7 @@ int FStateExpressions::ResolveAll()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for(int i=0; i<Size(); i++)
|
for(unsigned i=0; i<Size(); i++)
|
||||||
{
|
{
|
||||||
if (expressions[i].expr != NULL)
|
if (expressions[i].expr != NULL)
|
||||||
{
|
{
|
||||||
|
|
|
@ -69,6 +69,25 @@
|
||||||
#include "colormatcher.h"
|
#include "colormatcher.h"
|
||||||
#include "autosegs.h"
|
#include "autosegs.h"
|
||||||
|
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
// Gets a class pointer and performs an error check for correct type
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
static const PClass *FindClassTentative(const char *name, const char *ancestor)
|
||||||
|
{
|
||||||
|
const PClass *anc = PClass::FindClass(ancestor);
|
||||||
|
assert(anc != NULL); // parent classes used here should always be natively defined
|
||||||
|
const PClass *cls = const_cast<PClass*>(anc)->FindClassTentative(name);
|
||||||
|
assert (cls != NULL); // cls can not ne NULL here
|
||||||
|
if (!cls->IsDescendantOf(anc))
|
||||||
|
{
|
||||||
|
I_Error("%s does not inherit from %s\n", name, ancestor);
|
||||||
|
}
|
||||||
|
return cls;
|
||||||
|
}
|
||||||
|
|
||||||
//===========================================================================
|
//===========================================================================
|
||||||
//
|
//
|
||||||
// HandleDeprecatedFlags
|
// HandleDeprecatedFlags
|
||||||
|
@ -107,7 +126,7 @@ void HandleDeprecatedFlags(AActor *defaults, FActorInfo *info, bool set, int ind
|
||||||
case DEPF_PICKUPFLASH:
|
case DEPF_PICKUPFLASH:
|
||||||
if (set)
|
if (set)
|
||||||
{
|
{
|
||||||
static_cast<AInventory*>(defaults)->PickupFlash = fuglyname("PickupFlash");
|
static_cast<AInventory*>(defaults)->PickupFlash = FindClassTentative("PickupFlash", "Actor");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -1160,7 +1179,7 @@ DEFINE_CLASS_PROPERTY(defmaxamount, 0, Inventory)
|
||||||
DEFINE_CLASS_PROPERTY(pickupflash, S, Inventory)
|
DEFINE_CLASS_PROPERTY(pickupflash, S, Inventory)
|
||||||
{
|
{
|
||||||
PROP_STRING_PARM(str, 0);
|
PROP_STRING_PARM(str, 0);
|
||||||
defaults->PickupFlash = fuglyname(str);
|
defaults->PickupFlash = FindClassTentative(str, "Actor");
|
||||||
}
|
}
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
@ -1270,7 +1289,7 @@ DEFINE_CLASS_PROPERTY(ammogive2, I, Weapon)
|
||||||
DEFINE_CLASS_PROPERTY(ammotype, S, Weapon)
|
DEFINE_CLASS_PROPERTY(ammotype, S, Weapon)
|
||||||
{
|
{
|
||||||
PROP_STRING_PARM(str, 0);
|
PROP_STRING_PARM(str, 0);
|
||||||
defaults->AmmoType1 = fuglyname(str);
|
defaults->AmmoType1 = FindClassTentative(str, "Ammo");
|
||||||
}
|
}
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
@ -1279,7 +1298,7 @@ DEFINE_CLASS_PROPERTY(ammotype, S, Weapon)
|
||||||
DEFINE_CLASS_PROPERTY(ammotype1, S, Weapon)
|
DEFINE_CLASS_PROPERTY(ammotype1, S, Weapon)
|
||||||
{
|
{
|
||||||
PROP_STRING_PARM(str, 0);
|
PROP_STRING_PARM(str, 0);
|
||||||
defaults->AmmoType1 = fuglyname(str);
|
defaults->AmmoType1 = FindClassTentative(str, "Ammo");
|
||||||
}
|
}
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
@ -1288,7 +1307,7 @@ DEFINE_CLASS_PROPERTY(ammotype1, S, Weapon)
|
||||||
DEFINE_CLASS_PROPERTY(ammotype2, S, Weapon)
|
DEFINE_CLASS_PROPERTY(ammotype2, S, Weapon)
|
||||||
{
|
{
|
||||||
PROP_STRING_PARM(str, 0);
|
PROP_STRING_PARM(str, 0);
|
||||||
defaults->AmmoType2 = fuglyname(str);
|
defaults->AmmoType2 = FindClassTentative(str, "Ammo");
|
||||||
}
|
}
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
@ -1359,7 +1378,7 @@ DEFINE_CLASS_PROPERTY(selectionorder, I, Weapon)
|
||||||
DEFINE_CLASS_PROPERTY(sisterweapon, S, Weapon)
|
DEFINE_CLASS_PROPERTY(sisterweapon, S, Weapon)
|
||||||
{
|
{
|
||||||
PROP_STRING_PARM(str, 0);
|
PROP_STRING_PARM(str, 0);
|
||||||
defaults->SisterWeaponType = fuglyname(str);
|
defaults->SisterWeaponType = FindClassTentative(str, "Weapon");
|
||||||
}
|
}
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
@ -1395,7 +1414,7 @@ DEFINE_CLASS_PROPERTY(number, I, WeaponPiece)
|
||||||
DEFINE_CLASS_PROPERTY(weapon, S, WeaponPiece)
|
DEFINE_CLASS_PROPERTY(weapon, S, WeaponPiece)
|
||||||
{
|
{
|
||||||
PROP_STRING_PARM(str, 0);
|
PROP_STRING_PARM(str, 0);
|
||||||
defaults->WeaponClass = fuglyname(str);
|
defaults->WeaponClass = FindClassTentative(str, "Weapon");
|
||||||
}
|
}
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
@ -1505,7 +1524,18 @@ DEFINE_CLASS_PROPERTY_PREFIX(powerup, mode, S, PowerupGiver)
|
||||||
DEFINE_CLASS_PROPERTY_PREFIX(powerup, type, S, PowerupGiver)
|
DEFINE_CLASS_PROPERTY_PREFIX(powerup, type, S, PowerupGiver)
|
||||||
{
|
{
|
||||||
PROP_STRING_PARM(str, 0);
|
PROP_STRING_PARM(str, 0);
|
||||||
defaults->PowerupType = fuglyname(str);
|
|
||||||
|
// Yuck! What was I thinking when I decided to prepend "Power" to the name?
|
||||||
|
// Now it's too late to change it...
|
||||||
|
const PClass *cls = PClass::FindClass(str);
|
||||||
|
if (cls == NULL || !cls->IsDescendantOf(RUNTIME_CLASS(APowerupGiver)))
|
||||||
|
{
|
||||||
|
FString st;
|
||||||
|
st.Format("%s%s", strnicmp(str, "power", 5)? "Power" : "", str);
|
||||||
|
cls = FindClassTentative(st, "Powerup");
|
||||||
|
}
|
||||||
|
|
||||||
|
defaults->PowerupType = cls;
|
||||||
}
|
}
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
|
|
@ -17,7 +17,6 @@ enum ExpValType
|
||||||
VAL_Pointer, // Dereferenced variable (only used for addressing arrays for now.)
|
VAL_Pointer, // Dereferenced variable (only used for addressing arrays for now.)
|
||||||
VAL_Sound, // Sound identifier. Internally it's an int.
|
VAL_Sound, // Sound identifier. Internally it's an int.
|
||||||
VAL_Name, // A Name
|
VAL_Name, // A Name
|
||||||
VAL_MultiName, // Multiple names for multi-label states
|
|
||||||
VAL_Color, // A color.
|
VAL_Color, // A color.
|
||||||
VAL_State, // A State pointer
|
VAL_State, // A State pointer
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue