mirror of
https://github.com/ZDoom/gzdoom-gles.git
synced 2024-11-10 06:41:41 +00:00
- Removed the Actor uservar array and replaced it with user-defined variables.
A_SetUserVar/SetUserVariable/GetUserVariable now take a variable name instead of an array index. A_SetUserArray/SetUserArray/GetUserArray have been added to access elements in user-defined arrays. SVN r1933 (trunk)
This commit is contained in:
parent
f40462dfb4
commit
19b23f2cf3
15 changed files with 374 additions and 28 deletions
|
@ -1,4 +1,8 @@
|
|||
October 24, 2009
|
||||
- Removed the Actor uservar array and replaced it with user-defined variables.
|
||||
A_SetUserVar/SetUserVariable/GetUserVariable now take a variable name
|
||||
instead of an array index. A_SetUserArray/SetUserArray/GetUserArray
|
||||
have been added to access elements in user-defined arrays.
|
||||
- Rewrote wide sky texture scaling again. This time, it should work for any
|
||||
size textures at any scale. I also tried doing sky scrolling on the sky
|
||||
cylinder, but that didn't look so good, so I left it in screen space.
|
||||
|
|
|
@ -789,7 +789,6 @@ public:
|
|||
int tid; // thing identifier
|
||||
int special; // special
|
||||
int args[5]; // special arguments
|
||||
int uservar[10]; // user variables, accessible by DECORATE and ACS
|
||||
|
||||
AActor *inext, **iprev;// Links to other mobjs in same bucket
|
||||
TObjPtr<AActor> goal; // Monster's goal if not chasing anything
|
||||
|
|
|
@ -506,6 +506,88 @@ size_t DObject::StaticPointerSubstitution (DObject *old, DObject *notOld)
|
|||
return changed;
|
||||
}
|
||||
|
||||
void DObject::SerializeUserVars(FArchive &arc)
|
||||
{
|
||||
PSymbolTable *symt;
|
||||
FName varname;
|
||||
DWORD count, j;
|
||||
int *varloc;
|
||||
|
||||
if (SaveVersion < 1933)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
symt = &GetClass()->Symbols;
|
||||
|
||||
if (arc.IsStoring())
|
||||
{
|
||||
// Write all user variables.
|
||||
for (; symt != NULL; symt = symt->ParentSymbolTable)
|
||||
{
|
||||
for (unsigned i = 0; i < symt->Symbols.Size(); ++i)
|
||||
{
|
||||
PSymbol *sym = symt->Symbols[i];
|
||||
if (sym->SymbolType == SYM_Variable)
|
||||
{
|
||||
PSymbolVariable *var = static_cast<PSymbolVariable *>(sym);
|
||||
if (var->bUserVar)
|
||||
{
|
||||
count = var->ValueType.Type == VAL_Array ? var->ValueType.size : 1;
|
||||
varloc = (int *)(reinterpret_cast<BYTE *>(this) + var->offset);
|
||||
|
||||
arc << var->SymbolName;
|
||||
arc.WriteCount(count);
|
||||
for (j = 0; j < count; ++j)
|
||||
{
|
||||
arc << varloc[j];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// Write terminator.
|
||||
varname = NAME_None;
|
||||
arc << varname;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Read user variables until 'None' is encountered.
|
||||
arc << varname;
|
||||
while (varname != NAME_None)
|
||||
{
|
||||
PSymbol *sym = symt->FindSymbol(varname, true);
|
||||
DWORD wanted = 0;
|
||||
|
||||
if (sym != NULL && sym->SymbolType == SYM_Variable)
|
||||
{
|
||||
PSymbolVariable *var = static_cast<PSymbolVariable *>(sym);
|
||||
|
||||
if (var->bUserVar)
|
||||
{
|
||||
wanted = var->ValueType.Type == VAL_Array ? var->ValueType.size : 1;
|
||||
varloc = (int *)(reinterpret_cast<BYTE *>(this) + var->offset);
|
||||
}
|
||||
}
|
||||
count = arc.ReadCount();
|
||||
for (j = 0; j < MIN(wanted, count); ++j)
|
||||
{
|
||||
arc << varloc[j];
|
||||
}
|
||||
if (wanted < count)
|
||||
{
|
||||
// Ignore remaining values from archive.
|
||||
for (; j < count; ++j)
|
||||
{
|
||||
int foo;
|
||||
arc << foo;
|
||||
}
|
||||
}
|
||||
arc << varname;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DObject::Serialize (FArchive &arc)
|
||||
{
|
||||
ObjectFlags |= OF_SerialSuccess;
|
||||
|
|
|
@ -456,6 +456,7 @@ public:
|
|||
inline bool IsKindOf (const PClass *base) const;
|
||||
inline bool IsA (const PClass *type) const;
|
||||
|
||||
void SerializeUserVars(FArchive &arc);
|
||||
virtual void Serialize (FArchive &arc);
|
||||
|
||||
// For catching Serialize functions in derived classes
|
||||
|
|
|
@ -118,7 +118,7 @@ void PClass::StaticFreeData (PClass *type)
|
|||
{
|
||||
if (type->Defaults != NULL)
|
||||
{
|
||||
delete[] type->Defaults;
|
||||
M_Free(type->Defaults);
|
||||
type->Defaults = NULL;
|
||||
}
|
||||
type->FreeStateList ();
|
||||
|
@ -281,7 +281,7 @@ PClass *PClass::CreateDerivedClass (FName name, unsigned int size)
|
|||
type->Meta = Meta;
|
||||
|
||||
// Set up default instance of the new class.
|
||||
type->Defaults = new BYTE[size];
|
||||
type->Defaults = (BYTE *)M_Malloc(size);
|
||||
memcpy (type->Defaults, Defaults, Size);
|
||||
if (size > Size)
|
||||
{
|
||||
|
@ -315,6 +315,19 @@ PClass *PClass::CreateDerivedClass (FName name, unsigned int size)
|
|||
return type;
|
||||
}
|
||||
|
||||
// Add <extension> bytes to the end of this class. Returns the
|
||||
// previous size of the class.
|
||||
unsigned int PClass::Extend(unsigned int extension)
|
||||
{
|
||||
assert(this->bRuntimeClass);
|
||||
|
||||
unsigned int oldsize = Size;
|
||||
Size += extension;
|
||||
Defaults = (BYTE *)M_Realloc(Defaults, Size);
|
||||
memset(Defaults + oldsize, 0, extension);
|
||||
return oldsize;
|
||||
}
|
||||
|
||||
// Like FindClass but creates a placeholder if no class
|
||||
// is found. CreateDerivedClass will automatcally fill in
|
||||
// the placeholder when the actual class is defined.
|
||||
|
|
|
@ -46,8 +46,9 @@ struct PSymbolConst : public PSymbol
|
|||
struct PSymbolVariable : public PSymbol
|
||||
{
|
||||
FExpressionType ValueType;
|
||||
int size;
|
||||
//int size;
|
||||
intptr_t offset;
|
||||
bool bUserVar;
|
||||
|
||||
PSymbolVariable(FName name) : PSymbol(name, SYM_Variable) {}
|
||||
};
|
||||
|
@ -113,6 +114,8 @@ public:
|
|||
private:
|
||||
PSymbolTable *ParentSymbolTable;
|
||||
TArray<PSymbol *> Symbols;
|
||||
|
||||
friend class DObject;
|
||||
};
|
||||
|
||||
// Meta-info for every class derived from DObject ---------------------------
|
||||
|
@ -143,6 +146,7 @@ struct PClass
|
|||
void InsertIntoHash ();
|
||||
DObject *CreateNew () const;
|
||||
PClass *CreateDerivedClass (FName name, unsigned int size);
|
||||
unsigned int Extend(unsigned int extension);
|
||||
void InitializeActorInfo ();
|
||||
void BuildFlatPointers ();
|
||||
void FreeStateList();
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
** Implements an archiver for DObject serialization.
|
||||
**
|
||||
**---------------------------------------------------------------------------
|
||||
** Copyright 1998-2006 Randy Heit
|
||||
** Copyright 1998-2009 Randy Heit
|
||||
** All rights reserved.
|
||||
**
|
||||
** Redistribution and use in source and binary forms, with or without
|
||||
|
@ -1074,6 +1074,7 @@ FArchive &FArchive::WriteObject (DObject *obj)
|
|||
WriteClass (type);
|
||||
// Printf ("Make class %s (%u)\n", type->Name, m_File->Tell());
|
||||
MapObject (obj);
|
||||
obj->SerializeUserVars (*this);
|
||||
obj->Serialize (*this);
|
||||
obj->CheckIfSerialized ();
|
||||
}
|
||||
|
@ -1105,6 +1106,7 @@ FArchive &FArchive::WriteObject (DObject *obj)
|
|||
WriteCount (m_TypeMap[type->ClassIndex].toArchive);
|
||||
// Printf ("Reuse class %s (%u)\n", type->Name, m_File->Tell());
|
||||
MapObject (obj);
|
||||
obj->SerializeUserVars (*this);
|
||||
obj->Serialize (*this);
|
||||
obj->CheckIfSerialized ();
|
||||
}
|
||||
|
@ -1160,6 +1162,7 @@ FArchive &FArchive::ReadObject (DObject* &obj, PClass *wanttype)
|
|||
// stored in the archive.
|
||||
AActor *tempobj = static_cast<AActor *>(type->CreateNew ());
|
||||
MapObject (obj != NULL ? obj : tempobj);
|
||||
tempobj->SerializeUserVars (*this);
|
||||
tempobj->Serialize (*this);
|
||||
tempobj->CheckIfSerialized ();
|
||||
// If this player is not present anymore, keep the new body
|
||||
|
@ -1187,6 +1190,7 @@ FArchive &FArchive::ReadObject (DObject* &obj, PClass *wanttype)
|
|||
// Printf ("New class: %s (%u)\n", type->Name, m_File->Tell());
|
||||
obj = type->CreateNew ();
|
||||
MapObject (obj);
|
||||
obj->SerializeUserVars (*this);
|
||||
obj->Serialize (*this);
|
||||
obj->CheckIfSerialized ();
|
||||
break;
|
||||
|
@ -1201,6 +1205,7 @@ FArchive &FArchive::ReadObject (DObject* &obj, PClass *wanttype)
|
|||
|
||||
AActor *tempobj = static_cast<AActor *>(type->CreateNew ());
|
||||
MapObject (obj != NULL ? obj : tempobj);
|
||||
tempobj->SerializeUserVars (*this);
|
||||
tempobj->Serialize (*this);
|
||||
tempobj->CheckIfSerialized ();
|
||||
if (obj != NULL)
|
||||
|
@ -1225,6 +1230,7 @@ FArchive &FArchive::ReadObject (DObject* &obj, PClass *wanttype)
|
|||
// Printf ("Use class: %s (%u)\n", type->Name, m_File->Tell());
|
||||
obj = type->CreateNew ();
|
||||
MapObject (obj);
|
||||
obj->SerializeUserVars (*this);
|
||||
obj->Serialize (*this);
|
||||
obj->CheckIfSerialized ();
|
||||
break;
|
||||
|
|
120
src/p_acs.cpp
120
src/p_acs.cpp
|
@ -2908,6 +2908,8 @@ enum EACSFunctions
|
|||
ACSF_GetUserVariable,
|
||||
ACSF_Radius_Quake2,
|
||||
ACSF_CheckActorClass,
|
||||
ACSF_SetUserArray,
|
||||
ACSF_GetUserArray,
|
||||
};
|
||||
|
||||
int DLevelScript::SideFromID(int id, int side)
|
||||
|
@ -2942,6 +2944,67 @@ int DLevelScript::LineFromID(int id)
|
|||
}
|
||||
}
|
||||
|
||||
static void SetUserVariable(AActor *self, FName varname, int index, int value)
|
||||
{
|
||||
PSymbol *sym = self->GetClass()->Symbols.FindSymbol(varname, true);
|
||||
int max;
|
||||
PSymbolVariable *var;
|
||||
|
||||
if (sym == NULL || sym->SymbolType != SYM_Variable ||
|
||||
!(var = static_cast<PSymbolVariable *>(sym))->bUserVar)
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (var->ValueType.Type == VAL_Int)
|
||||
{
|
||||
max = 1;
|
||||
}
|
||||
else if (var->ValueType.Type == VAL_Array && var->ValueType.BaseType == VAL_Int)
|
||||
{
|
||||
max = var->ValueType.size;
|
||||
}
|
||||
else
|
||||
{
|
||||
return;
|
||||
}
|
||||
// Set the value of the specified user variable.
|
||||
if (index >= 0 && index < max)
|
||||
{
|
||||
((int *)(reinterpret_cast<BYTE *>(self) + var->offset))[index] = value;
|
||||
}
|
||||
}
|
||||
|
||||
static int GetUserVariable(AActor *self, FName varname, int index)
|
||||
{
|
||||
PSymbol *sym = self->GetClass()->Symbols.FindSymbol(varname, true);
|
||||
int max;
|
||||
PSymbolVariable *var;
|
||||
|
||||
if (sym == NULL || sym->SymbolType != SYM_Variable ||
|
||||
!(var = static_cast<PSymbolVariable *>(sym))->bUserVar)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
if (var->ValueType.Type == VAL_Int)
|
||||
{
|
||||
max = 1;
|
||||
}
|
||||
else if (var->ValueType.Type == VAL_Array && var->ValueType.BaseType == VAL_Int)
|
||||
{
|
||||
max = var->ValueType.size;
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
// Get the value of the specified user variable.
|
||||
if (index >= 0 && index < max)
|
||||
{
|
||||
return ((int *)(reinterpret_cast<BYTE *>(self) + var->offset))[index];
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int DLevelScript::CallFunction(int argCount, int funcIndex, SDWORD *args)
|
||||
{
|
||||
AActor *actor;
|
||||
|
@ -3109,23 +3172,24 @@ int DLevelScript::CallFunction(int argCount, int funcIndex, SDWORD *args)
|
|||
case ACSF_SetUserVariable:
|
||||
{
|
||||
int cnt = 0;
|
||||
if (args[1] >= 0 && args[1] < 10)
|
||||
FName varname(FBehavior::StaticLookupString(args[1]), true);
|
||||
if (varname != NAME_None)
|
||||
{
|
||||
if (args[0] == 0)
|
||||
{
|
||||
if (activator != NULL)
|
||||
{
|
||||
activator->uservar[args[1]] = args[2];
|
||||
SetUserVariable(activator, varname, 0, args[2]);
|
||||
}
|
||||
cnt++;
|
||||
}
|
||||
else
|
||||
{
|
||||
TActorIterator<AActor> iterator (args[0]);
|
||||
TActorIterator<AActor> iterator(args[0]);
|
||||
|
||||
while ( (actor = iterator.Next ()) )
|
||||
while ( (actor = iterator.Next()) )
|
||||
{
|
||||
actor->uservar[args[1]] = args[2];
|
||||
SetUserVariable(actor, varname, 0, args[2]);
|
||||
cnt++;
|
||||
}
|
||||
}
|
||||
|
@ -3135,12 +3199,52 @@ int DLevelScript::CallFunction(int argCount, int funcIndex, SDWORD *args)
|
|||
|
||||
case ACSF_GetUserVariable:
|
||||
{
|
||||
if (args[1] >= 0 && args[1] < 10)
|
||||
FName varname(FBehavior::StaticLookupString(args[1]), true);
|
||||
if (varname != NAME_None)
|
||||
{
|
||||
AActor *a = args[0] == 0 ? (AActor *)activator : SingleActorFromTID(args[0], NULL);
|
||||
return a != NULL? a->uservar[args[1]] : 0;
|
||||
return a != NULL ? GetUserVariable(a, varname, 0) : 0;
|
||||
}
|
||||
else return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
case ACSF_SetUserArray:
|
||||
{
|
||||
int cnt = 0;
|
||||
FName varname(FBehavior::StaticLookupString(args[1]), true);
|
||||
if (varname != NAME_None)
|
||||
{
|
||||
if (args[0] == 0)
|
||||
{
|
||||
if (activator != NULL)
|
||||
{
|
||||
SetUserVariable(activator, varname, args[2], args[3]);
|
||||
}
|
||||
cnt++;
|
||||
}
|
||||
else
|
||||
{
|
||||
TActorIterator<AActor> iterator(args[0]);
|
||||
|
||||
while ( (actor = iterator.Next()) )
|
||||
{
|
||||
SetUserVariable(actor, varname, args[2], args[3]);
|
||||
cnt++;
|
||||
}
|
||||
}
|
||||
}
|
||||
return cnt;
|
||||
}
|
||||
|
||||
case ACSF_GetUserArray:
|
||||
{
|
||||
FName varname(FBehavior::StaticLookupString(args[1]), true);
|
||||
if (varname != NAME_None)
|
||||
{
|
||||
AActor *a = args[0] == 0 ? (AActor *)activator : SingleActorFromTID(args[0], NULL);
|
||||
return a != NULL ? GetUserVariable(a, varname, args[2]) : 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
case ACSF_Radius_Quake2:
|
||||
|
|
|
@ -314,7 +314,13 @@ void AActor::Serialize (FArchive &arc)
|
|||
arc << DamageFactor;
|
||||
}
|
||||
|
||||
for(int i=0; i<10; i++) arc << uservar[i];
|
||||
// Skip past uservar array in old savegames
|
||||
if (SaveVersion < 1933)
|
||||
{
|
||||
int foo;
|
||||
for (int i = 0; i < 10; ++i)
|
||||
arc << foo;
|
||||
}
|
||||
|
||||
if (arc.IsStoring ())
|
||||
{
|
||||
|
|
|
@ -175,6 +175,7 @@ enum
|
|||
TK_Exec,
|
||||
TK_DefaultProperties,
|
||||
TK_Native,
|
||||
TK_Var,
|
||||
TK_Out,
|
||||
TK_Ref,
|
||||
TK_Event,
|
||||
|
|
|
@ -109,6 +109,7 @@ std2:
|
|||
'exec' { RET(TK_Exec); }
|
||||
'defaultproperties' { RET(TK_DefaultProperties); }
|
||||
'native' { RET(TK_Native); }
|
||||
'var' { RET(TK_Var); }
|
||||
'out' { RET(TK_Out); }
|
||||
'ref' { RET(TK_Ref); }
|
||||
'event' { RET(TK_Event); }
|
||||
|
|
|
@ -1742,6 +1742,19 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_Log)
|
|||
Printf("%s\n", text);
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// A_LogInt
|
||||
//
|
||||
//===========================================================================
|
||||
|
||||
DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_LogInt)
|
||||
{
|
||||
ACTION_PARAM_START(1);
|
||||
ACTION_PARAM_INT(num, 0);
|
||||
Printf("%d\n", num);
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// A_SetTranslucent
|
||||
|
@ -2900,21 +2913,63 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_SetSpecial)
|
|||
|
||||
//===========================================================================
|
||||
//
|
||||
// A_SetVar
|
||||
// A_SetUserVar
|
||||
//
|
||||
//===========================================================================
|
||||
|
||||
DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_SetUserVar)
|
||||
{
|
||||
ACTION_PARAM_START(2);
|
||||
ACTION_PARAM_INT(pos, 0);
|
||||
ACTION_PARAM_NAME(varname, 0);
|
||||
ACTION_PARAM_INT(value, 1);
|
||||
|
||||
if (pos < 0 || pos > 9)
|
||||
PSymbol *sym = self->GetClass()->Symbols.FindSymbol(varname, true);
|
||||
PSymbolVariable *var;
|
||||
|
||||
if (sym == NULL || sym->SymbolType != SYM_Variable ||
|
||||
!(var = static_cast<PSymbolVariable *>(sym))->bUserVar ||
|
||||
var->ValueType.Type != VAL_Int)
|
||||
{
|
||||
Printf("%s is not a user variable in class %s\n", varname.GetChars(),
|
||||
self->GetClass()->TypeName.GetChars());
|
||||
return;
|
||||
|
||||
// Set the value of the specified arg
|
||||
self->uservar[pos] = value;
|
||||
}
|
||||
// Set the value of the specified user variable.
|
||||
*(int *)(reinterpret_cast<BYTE *>(self) + var->offset) = value;
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// A_SetUserArray
|
||||
//
|
||||
//===========================================================================
|
||||
|
||||
DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_SetUserArray)
|
||||
{
|
||||
ACTION_PARAM_START(3);
|
||||
ACTION_PARAM_NAME(varname, 0);
|
||||
ACTION_PARAM_INT(pos, 1);
|
||||
ACTION_PARAM_INT(value, 2);
|
||||
|
||||
PSymbol *sym = self->GetClass()->Symbols.FindSymbol(varname, true);
|
||||
PSymbolVariable *var;
|
||||
|
||||
if (sym == NULL || sym->SymbolType != SYM_Variable ||
|
||||
!(var = static_cast<PSymbolVariable *>(sym))->bUserVar ||
|
||||
var->ValueType.Type != VAL_Array || var->ValueType.BaseType != VAL_Int)
|
||||
{
|
||||
Printf("%s is not a user array in class %s\n", varname.GetChars(),
|
||||
self->GetClass()->TypeName.GetChars());
|
||||
return;
|
||||
}
|
||||
if (pos < 0 || pos >= var->ValueType.size)
|
||||
{
|
||||
Printf("%d is out of bounds in array %s in class %s\n", pos, varname.GetChars(),
|
||||
self->GetClass()->TypeName.GetChars());
|
||||
return;
|
||||
}
|
||||
// Set the value of the specified user array at index pos.
|
||||
((int *)(reinterpret_cast<BYTE *>(self) + var->offset))[pos] = value;
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
|
|
|
@ -78,7 +78,6 @@ DEFINE_MEMBER_VARIABLE_ALIAS(momy, vely, AActor)
|
|||
DEFINE_MEMBER_VARIABLE_ALIAS(momz, velz, AActor)
|
||||
DEFINE_MEMBER_VARIABLE(Damage, AActor)
|
||||
DEFINE_MEMBER_VARIABLE(Score, AActor)
|
||||
DEFINE_MEMBER_VARIABLE(uservar, AActor)
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
|
|
|
@ -248,13 +248,13 @@ static void ParseEnum (FScanner &sc, PSymbolTable *symt, PClass *cls)
|
|||
|
||||
//==========================================================================
|
||||
//
|
||||
// ActorConstDef
|
||||
// ParseNativeVariable
|
||||
//
|
||||
// Parses a constant definition.
|
||||
// Parses a native variable declaration.
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
static void ParseVariable (FScanner &sc, PSymbolTable * symt, PClass *cls)
|
||||
static void ParseNativeVariable (FScanner &sc, PSymbolTable * symt, PClass *cls)
|
||||
{
|
||||
FExpressionType valuetype;
|
||||
|
||||
|
@ -319,6 +319,7 @@ static void ParseVariable (FScanner &sc, PSymbolTable * symt, PClass *cls)
|
|||
PSymbolVariable *sym = new PSymbolVariable(symname);
|
||||
sym->offset = vi->address; // todo
|
||||
sym->ValueType = valuetype;
|
||||
sym->bUserVar = false;
|
||||
|
||||
if (symt->AddSymbol (sym) == NULL)
|
||||
{
|
||||
|
@ -328,6 +329,70 @@ static void ParseVariable (FScanner &sc, PSymbolTable * symt, PClass *cls)
|
|||
}
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// ParseUserVariable
|
||||
//
|
||||
// Parses a user variable declaration.
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
static void ParseUserVariable (FScanner &sc, PSymbolTable *symt, PClass *cls)
|
||||
{
|
||||
FExpressionType valuetype;
|
||||
|
||||
// Only non-native classes may have user variables.
|
||||
if (!cls->bRuntimeClass)
|
||||
{
|
||||
sc.ScriptError("Native classes may not have user variables");
|
||||
}
|
||||
|
||||
// Read the type and make sure it's int.
|
||||
sc.MustGetAnyToken();
|
||||
if (sc.TokenType == TK_Int)
|
||||
{
|
||||
valuetype = VAL_Int;
|
||||
}
|
||||
else
|
||||
{
|
||||
sc.ScriptError("User variables must be of type int");
|
||||
}
|
||||
|
||||
sc.MustGetToken(TK_Identifier);
|
||||
// For now, restrict user variables to those that begin with "user_" to guarantee
|
||||
// no clashes with internal member variable names.
|
||||
if (sc.StringLen < 6 || strnicmp("user_", sc.String, 5) != 0)
|
||||
{
|
||||
sc.ScriptError("User variable names must begin with \"user_\"");
|
||||
}
|
||||
|
||||
FName symname = sc.String;
|
||||
if (sc.CheckToken('['))
|
||||
{
|
||||
FxExpression *expr = ParseExpression(sc, cls);
|
||||
int maxelems = expr->EvalExpression(NULL).GetInt();
|
||||
delete expr;
|
||||
sc.MustGetToken(']');
|
||||
if (maxelems <= 0)
|
||||
{
|
||||
sc.ScriptError("Array size must be positive");
|
||||
}
|
||||
valuetype.MakeArray(maxelems);
|
||||
}
|
||||
sc.MustGetToken(';');
|
||||
|
||||
PSymbolVariable *sym = new PSymbolVariable(symname);
|
||||
sym->offset = cls->Extend(sizeof(int) * (valuetype.Type == VAL_Array ? valuetype.size : 1));
|
||||
sym->ValueType = valuetype;
|
||||
sym->bUserVar = true;
|
||||
if (symt->AddSymbol(sym) == NULL)
|
||||
{
|
||||
delete sym;
|
||||
sc.ScriptError ("'%s' is already defined in '%s'.",
|
||||
symname.GetChars(), cls ? cls->TypeName.GetChars() : "Global");
|
||||
}
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// Parses a flag name
|
||||
|
@ -1064,7 +1129,11 @@ static void ParseActor(FScanner &sc)
|
|||
break;
|
||||
|
||||
case TK_Native:
|
||||
ParseVariable (sc, &info->Class->Symbols, info->Class);
|
||||
ParseNativeVariable (sc, &info->Class->Symbols, info->Class);
|
||||
break;
|
||||
|
||||
case TK_Var:
|
||||
ParseUserVariable (sc, &info->Class->Symbols, info->Class);
|
||||
break;
|
||||
|
||||
case TK_Identifier:
|
||||
|
@ -1125,7 +1194,7 @@ void ParseDecorate (FScanner &sc)
|
|||
break;
|
||||
|
||||
case TK_Native:
|
||||
ParseVariable(sc, &GlobalSymbols, NULL);
|
||||
ParseNativeVariable(sc, &GlobalSymbols, NULL);
|
||||
break;
|
||||
|
||||
case ';':
|
||||
|
|
|
@ -27,7 +27,6 @@ ACTOR Actor native //: Thinker
|
|||
native fixed_t alpha;
|
||||
native angle_t angle;
|
||||
native int args[5];
|
||||
native int uservar[10];
|
||||
native fixed_t ceilingz;
|
||||
native fixed_t floorz;
|
||||
native int health;
|
||||
|
@ -47,6 +46,7 @@ ACTOR Actor native //: Thinker
|
|||
native fixed_t momy; // alias for vely
|
||||
native fixed_t momz; // alias for velz
|
||||
native int score;
|
||||
|
||||
// Meh, MBF redundant functions. Only for DeHackEd support.
|
||||
action native A_Turn(float angle = 0);
|
||||
action native A_LineEffect(int boomspecial = 0, int tag = 0);
|
||||
|
@ -195,6 +195,7 @@ ACTOR Actor native //: Thinker
|
|||
action native A_Print(string whattoprint, float time = 0, string fontname = "");
|
||||
action native A_PrintBold(string whattoprint, float time = 0, string fontname = "");
|
||||
action native A_Log(string whattoprint);
|
||||
action native A_LogInt(int whattoprint);
|
||||
action native A_SetTranslucent(float alpha, int style = 0);
|
||||
action native A_FadeIn(float reduce = 0.1);
|
||||
action native A_FadeOut(float reduce = 0.1, bool remove = true);
|
||||
|
@ -261,7 +262,8 @@ ACTOR Actor native //: Thinker
|
|||
action native A_ScaleVelocity(float scale);
|
||||
action native A_ChangeVelocity(float x = 0, float y = 0, float z = 0, int flags = 0);
|
||||
action native A_SetArg(int pos, int value);
|
||||
action native A_SetUserVar(int pos, int value);
|
||||
action native A_SetUserVar(name varname, int value);
|
||||
action native A_SetUserArray(name varname, int index, int value);
|
||||
action native A_SetSpecial(int spec, int arg0 = 0, int arg1 = 0, int arg2 = 0, int arg3 = 0, int arg4 = 0);
|
||||
action native A_Quake(int intensity, int duration, int damrad, int tremrad, sound sfx = "world/quake");
|
||||
|
||||
|
|
Loading…
Reference in a new issue