mirror of
https://github.com/ZDoom/gzdoom-gles.git
synced 2024-11-28 06:53:40 +00:00
- 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 267 additions and 367 deletions
|
@ -1,4 +1,6 @@
|
|||
September 21, 2008 (Changes by Graf Zahl)
|
||||
- did some code cleanup and reorganization in thingdef.cpp.
|
||||
- Replaced the translation parser for TEXTURES with FRemapTable::AddToTranslation.
|
||||
- To get the game name the screenshot code might as well use the globally
|
||||
available GameNames array instead of creating its own list.
|
||||
- Moved backpack names for cheat into gameinfo.
|
||||
|
|
|
@ -953,16 +953,11 @@ void FTextureManager::AddTexturesLumps (int lump1, int lump2, int patcheslump)
|
|||
}
|
||||
|
||||
|
||||
static bool Check(char *& range, char c)
|
||||
{
|
||||
while (isspace(*range)) range++;
|
||||
if (*range==c)
|
||||
{
|
||||
range++;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
//==========================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
void FMultiPatchTexture::ParsePatch(FScanner &sc, TexPart & part)
|
||||
{
|
||||
|
@ -1056,46 +1051,7 @@ void FMultiPatchTexture::ParsePatch(FScanner &sc, TexPart & part)
|
|||
do
|
||||
{
|
||||
sc.MustGetString();
|
||||
|
||||
char *range = sc.String;
|
||||
int start,end;
|
||||
|
||||
start=strtol(range, &range, 10);
|
||||
if (!Check(range, ':')) return;
|
||||
end=strtol(range, &range, 10);
|
||||
if (!Check(range, '=')) return;
|
||||
if (!Check(range, '['))
|
||||
{
|
||||
int pal1,pal2;
|
||||
|
||||
pal1=strtol(range, &range, 10);
|
||||
if (!Check(range, ':')) return;
|
||||
pal2=strtol(range, &range, 10);
|
||||
|
||||
part.Translation->AddIndexRange(start, end, pal1, pal2);
|
||||
}
|
||||
else
|
||||
{
|
||||
// translation using RGB values
|
||||
int r1,g1,b1,r2,g2,b2;
|
||||
|
||||
r1=strtol(range, &range, 10);
|
||||
if (!Check(range, ',')) return;
|
||||
g1=strtol(range, &range, 10);
|
||||
if (!Check(range, ',')) return;
|
||||
b1=strtol(range, &range, 10);
|
||||
if (!Check(range, ']')) return;
|
||||
if (!Check(range, ':')) return;
|
||||
if (!Check(range, '[')) return;
|
||||
r2=strtol(range, &range, 10);
|
||||
if (!Check(range, ',')) return;
|
||||
g2=strtol(range, &range, 10);
|
||||
if (!Check(range, ',')) return;
|
||||
b2=strtol(range, &range, 10);
|
||||
if (!Check(range, ']')) return;
|
||||
|
||||
part.Translation->AddColorRange(start, end, r1, g1, b1, r2, g2, b2);
|
||||
}
|
||||
part.Translation->AddToTranslation(sc.String);
|
||||
}
|
||||
while (sc.CheckString(","));
|
||||
}
|
||||
|
@ -1161,6 +1117,11 @@ void FMultiPatchTexture::ParsePatch(FScanner &sc, TexPart & part)
|
|||
}
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// Constructor for text based multipatch definitions
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
FMultiPatchTexture::FMultiPatchTexture (FScanner &sc, int usetype)
|
||||
: Pixels (0), Spans(0), Parts(0), bRedirect(false), bTranslucentPatches(false)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -106,7 +106,7 @@ void InstallStates(FActorInfo *info, AActor *defaults);
|
|||
void MakeStateDefines(const FStateLabels *list);
|
||||
void AddStateDefines(const FStateLabels *list);
|
||||
FState *P_GetState(AActor *self, FState *CallingState, int offset);
|
||||
int FinishStates (FScanner &sc, FActorInfo *actor, AActor *defaults, Baggage &bag);
|
||||
int FinishStates (FActorInfo *actor, AActor *defaults);
|
||||
int ParseStates(FScanner &sc, FActorInfo *actor, AActor *defaults, Baggage &bag);
|
||||
FState *CheckState(FScanner &sc, PClass *type);
|
||||
|
||||
|
|
|
@ -526,7 +526,14 @@ void FinishActor(FScanner &sc, FActorInfo *info, Baggage &bag)
|
|||
{
|
||||
AActor *defaults = (AActor*)info->Class->Defaults;
|
||||
|
||||
FinishStates (sc, info, defaults, bag);
|
||||
try
|
||||
{
|
||||
FinishStates (info, defaults);
|
||||
}
|
||||
catch (CRecoverableError &err)
|
||||
{
|
||||
sc.ScriptError(err.GetMessage());
|
||||
}
|
||||
InstallStates (info, defaults);
|
||||
if (bag.DropItemSet)
|
||||
{
|
||||
|
|
|
@ -2013,7 +2013,7 @@ DEFINE_CLASS_PROPERTY_PREFIX(player, startitem, S_i, PlayerPawn)
|
|||
di->amount = 1;
|
||||
if (PROP_PARM_COUNT > 1)
|
||||
{
|
||||
PROP_INT_PARM(amt, 0);
|
||||
PROP_INT_PARM(amt, 1);
|
||||
di->amount = amt;
|
||||
}
|
||||
di->Next = bag.DropItemList;
|
||||
|
|
|
@ -387,6 +387,40 @@ void AddStateDefines(const FStateLabels *list)
|
|||
|
||||
//==========================================================================
|
||||
//
|
||||
// RetargetState(Pointer)s
|
||||
//
|
||||
// These functions are used when a goto follows one or more labels.
|
||||
// Because multiple labels are permitted to occur consecutively with no
|
||||
// intervening states, it is not enough to remember the last label defined
|
||||
// and adjust it. So these functions search for all labels that point to
|
||||
// the current position in the state array and give them a copy of the
|
||||
// target string instead.
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
static void RetargetStatePointers (intptr_t count, const char *target, TArray<FStateDefine> & statelist)
|
||||
{
|
||||
for(unsigned i = 0;i<statelist.Size(); i++)
|
||||
{
|
||||
if (statelist[i].State == (FState*)count)
|
||||
{
|
||||
statelist[i].State = target == NULL ? NULL : (FState *)copystring (target);
|
||||
}
|
||||
if (statelist[i].Children.Size() > 0)
|
||||
{
|
||||
RetargetStatePointers(count, target, statelist[i].Children);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void RetargetStates (intptr_t count, const char *target)
|
||||
{
|
||||
RetargetStatePointers(count, target, StateLabels);
|
||||
}
|
||||
|
||||
|
||||
//==========================================================================
|
||||
//***
|
||||
// PrepareStateParameters
|
||||
// creates an empty parameter list for a parameterized function call
|
||||
//
|
||||
|
@ -403,7 +437,7 @@ int PrepareStateParameters(FState * state, int numparams)
|
|||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//***
|
||||
// DoActionSpecials
|
||||
// handles action specials as code pointers
|
||||
//
|
||||
|
@ -457,40 +491,7 @@ bool DoActionSpecials(FScanner &sc, FState & state, bool multistate, int * state
|
|||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// RetargetState(Pointer)s
|
||||
//
|
||||
// These functions are used when a goto follows one or more labels.
|
||||
// Because multiple labels are permitted to occur consecutively with no
|
||||
// intervening states, it is not enough to remember the last label defined
|
||||
// and adjust it. So these functions search for all labels that point to
|
||||
// the current position in the state array and give them a copy of the
|
||||
// target string instead.
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
static void RetargetStatePointers (intptr_t count, const char *target, TArray<FStateDefine> & statelist)
|
||||
{
|
||||
for(unsigned i = 0;i<statelist.Size(); i++)
|
||||
{
|
||||
if (statelist[i].State == (FState*)count)
|
||||
{
|
||||
statelist[i].State = target == NULL ? NULL : (FState *)copystring (target);
|
||||
}
|
||||
if (statelist[i].Children.Size() > 0)
|
||||
{
|
||||
RetargetStatePointers(count, target, statelist[i].Children);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void RetargetStates (intptr_t count, const char *target)
|
||||
{
|
||||
RetargetStatePointers(count, target, StateLabels);
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//***
|
||||
// Reads a state label that may contain '.'s.
|
||||
// processes a state block
|
||||
//
|
||||
|
@ -515,7 +516,7 @@ static FString ParseStateString(FScanner &sc)
|
|||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//***
|
||||
// ParseStates
|
||||
// parses a state block
|
||||
//
|
||||
|
@ -821,7 +822,7 @@ endofstate:
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
static FState *ResolveGotoLabel (FScanner &sc, AActor *actor, const PClass *mytype, char *name)
|
||||
static FState *ResolveGotoLabel (AActor *actor, const PClass *mytype, char *name)
|
||||
{
|
||||
const PClass *type=mytype;
|
||||
FState *state;
|
||||
|
@ -849,15 +850,15 @@ static FState *ResolveGotoLabel (FScanner &sc, AActor *actor, const PClass *myty
|
|||
const PClass *stype = PClass::FindClass (classname);
|
||||
if (stype == NULL)
|
||||
{
|
||||
sc.ScriptError ("%s is an unknown class.", classname);
|
||||
I_Error ("%s is an unknown class.", classname);
|
||||
}
|
||||
if (!stype->IsDescendantOf (RUNTIME_CLASS(AActor)))
|
||||
{
|
||||
sc.ScriptError ("%s is not an actor class, so it has no states.", stype->TypeName.GetChars());
|
||||
I_Error ("%s is not an actor class, so it has no states.", stype->TypeName.GetChars());
|
||||
}
|
||||
if (!stype->IsAncestorOf (type))
|
||||
{
|
||||
sc.ScriptError ("%s is not derived from %s so cannot access its states.",
|
||||
I_Error ("%s is not derived from %s so cannot access its states.",
|
||||
type->TypeName.GetChars(), stype->TypeName.GetChars());
|
||||
}
|
||||
if (type != stype)
|
||||
|
@ -887,7 +888,7 @@ static FState *ResolveGotoLabel (FScanner &sc, AActor *actor, const PClass *myty
|
|||
}
|
||||
else if (v != 0)
|
||||
{
|
||||
sc.ScriptError ("Attempt to get invalid state %s from actor %s.", label, type->TypeName.GetChars());
|
||||
I_Error ("Attempt to get invalid state %s from actor %s.", label, type->TypeName.GetChars());
|
||||
}
|
||||
delete[] namestart; // free the allocated string buffer
|
||||
return state;
|
||||
|
@ -922,15 +923,15 @@ static void FixStatePointers (FActorInfo *actor, TArray<FStateDefine> & list)
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
static void FixStatePointersAgain (FScanner &sc, FActorInfo *actor, AActor *defaults, TArray<FStateDefine> & list)
|
||||
static void FixStatePointersAgain (FActorInfo *actor, AActor *defaults, TArray<FStateDefine> & list)
|
||||
{
|
||||
for(unsigned i=0;i<list.Size(); i++)
|
||||
{
|
||||
if (list[i].State != NULL && FState::StaticFindStateOwner (list[i].State, actor) == NULL)
|
||||
{ // It's not a valid state, so it must be a label string. Resolve it.
|
||||
list[i].State = ResolveGotoLabel (sc, defaults, actor->Class, (char *)list[i].State);
|
||||
list[i].State = ResolveGotoLabel (defaults, actor->Class, (char *)list[i].State);
|
||||
}
|
||||
if (list[i].Children.Size() > 0) FixStatePointersAgain(sc, actor, defaults, list[i].Children);
|
||||
if (list[i].Children.Size() > 0) FixStatePointersAgain(actor, defaults, list[i].Children);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -942,7 +943,7 @@ static void FixStatePointersAgain (FScanner &sc, FActorInfo *actor, AActor *defa
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
int FinishStates (FScanner &sc, FActorInfo *actor, AActor *defaults, Baggage &bag)
|
||||
int FinishStates (FActorInfo *actor, AActor *defaults)
|
||||
{
|
||||
static int c=0;
|
||||
int count = StateArray.Size();
|
||||
|
@ -985,7 +986,7 @@ int FinishStates (FScanner &sc, FActorInfo *actor, AActor *defaults, Baggage &ba
|
|||
}
|
||||
else // goto
|
||||
{
|
||||
realstates[i].NextState = ResolveGotoLabel (sc, defaults, bag.Info->Class, (char *)realstates[i].NextState);
|
||||
realstates[i].NextState = ResolveGotoLabel (defaults, actor->Class, (char *)realstates[i].NextState);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -993,7 +994,7 @@ int FinishStates (FScanner &sc, FActorInfo *actor, AActor *defaults, Baggage &ba
|
|||
StateArray.Clear ();
|
||||
|
||||
// Fix state pointers that are gotos
|
||||
FixStatePointersAgain (sc, actor, defaults, StateLabels);
|
||||
FixStatePointersAgain (actor, defaults, StateLabels);
|
||||
|
||||
return count;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue