This commit is contained in:
Rachael Alexanderson 2017-04-12 20:33:38 -04:00
commit a15031706d
128 changed files with 5354 additions and 5093 deletions

View file

@ -1215,6 +1215,7 @@ set (PCH_SOURCES
r_data/renderstyle.cpp
r_data/r_interpolate.cpp
scripting/symbols.cpp
scripting/types.cpp
scripting/thingdef.cpp
scripting/thingdef_data.cpp
scripting/thingdef_properties.cpp

View file

@ -33,7 +33,6 @@
// States are tied to finite states are tied to animation frames.
#include "info.h"
#include <forward_list>
#include "doomdef.h"
#include "textures/textures.h"
#include "r_data/renderstyle.h"
@ -612,6 +611,12 @@ public:
return (AActor *)(this->GetClass()->Defaults);
}
FActorInfo *GetInfo() const
{
return ((PClassActor*)GetClass())->ActorInfo();
}
FDropItem *GetDropItems() const;
// Return true if the monster should use a missile attack, false for melee
@ -1566,6 +1571,17 @@ template<class T> inline T *Spawn() // for inventory items we do not need coordi
return static_cast<T *>(AActor::StaticSpawn(RUNTIME_TEMPLATE_CLASS(T), DVector3(0, 0, 0), NO_REPLACE));
}
inline PClassActor *PClass::FindActor(FName name)
{
auto cls = FindClass(name);
return cls && cls->IsDescendantOf(RUNTIME_CLASS(AActor)) ? static_cast<PClassActor*>(cls) : nullptr;
}
inline PClassActor *ValidateActor(PClass *cls)
{
return cls && cls->IsDescendantOf(RUNTIME_CLASS(AActor)) ? static_cast<PClassActor*>(cls) : nullptr;
}
void PrintMiscActorInfo(AActor * query);
AActor *P_LinePickActor(AActor *t1, DAngle angle, double distance, DAngle pitch, ActorFlags actorMask, uint32_t wallMask);

View file

@ -734,8 +734,6 @@ static int grid = 0;
bool automapactive = false;
DEFINE_GLOBAL(automapactive);
// location of window on screen
static int f_x;
static int f_y;

View file

@ -14,6 +14,7 @@
#include "d_net.h"
#include "serializer.h"
#include "d_player.h"
#include "vm.h"
IMPLEMENT_CLASS(DBot, false, true)

View file

@ -62,6 +62,7 @@ Everything that is changed is marked (maybe commented) with "Added by MC"
#include "d_player.h"
#include "doomerrors.h"
#include "events.h"
#include "vm.h"
static FRandom pr_botspawn ("BotSpawn");

View file

@ -46,6 +46,7 @@
#include "w_wad.h"
#include "templates.h"
#include "dobject.h"
#include "vm.h"
#include <math.h>
#include <stdlib.h>

View file

@ -1147,34 +1147,6 @@ CCMD(currentpos)
}
}
//-----------------------------------------------------------------------------
//
//
//
//-----------------------------------------------------------------------------
CCMD(vmengine)
{
if (argv.argc() == 2)
{
if (stricmp(argv[1], "default") == 0)
{
VMSelectEngine(VMEngine_Default);
return;
}
else if (stricmp(argv[1], "checked") == 0)
{
VMSelectEngine(VMEngine_Checked);
return;
}
else if (stricmp(argv[1], "unchecked") == 0)
{
VMSelectEngine(VMEngine_Unchecked);
return;
}
}
Printf("Usage: vmengine <default|checked|unchecked>\n");
}
//-----------------------------------------------------------------------------
//
// Print secret info (submitted by Karl Murks)

View file

@ -68,6 +68,7 @@
#include "gstrings.h"
#include "c_consolebuffer.h"
#include "g_levellocals.h"
#include "vm.h"
FString FStringFormat(VM_ARGS); // extern from thingdef_data.cpp

View file

@ -52,6 +52,7 @@
#include "v_video.h"
#include "colormatcher.h"
#include "menu/menu.h"
#include "vm.h"
struct FLatchedValue
{

View file

@ -55,6 +55,7 @@
#include "d_main.h"
#include "serializer.h"
#include "menu/menu.h"
#include "vm.h"
// MACROS ------------------------------------------------------------------

View file

@ -74,6 +74,7 @@
#include "info.h"
#include "v_text.h"
#include "backend/vmbuilder.h"
#include "types.h"
// [SO] Just the way Randy said to do it :)
// [RH] Made this CVAR_SERVERINFO
@ -791,7 +792,7 @@ void SetDehParams(FState *state, int codepointer)
// Let's identify the codepointer we're dealing with.
PFunction *sym;
sym = dyn_cast<PFunction>(RUNTIME_CLASS(AWeapon)->Symbols.FindSymbol(FName(MBFCodePointers[codepointer].name), true));
sym = dyn_cast<PFunction>(RUNTIME_CLASS(AWeapon)->FindSymbol(FName(MBFCodePointers[codepointer].name), true));
if (sym == NULL) return;
if (codepointer < 0 || (unsigned)codepointer >= countof(MBFCodePointerFactories))
@ -876,7 +877,7 @@ static int PatchThing (int thingy)
else
{
info = GetDefaultByType (type);
ednum = &type->DoomEdNum;
ednum = &type->ActorInfo()->DoomEdNum;
}
}
}
@ -1984,7 +1985,7 @@ static int PatchMisc (int dummy)
player->health = deh.StartHealth;
// Hm... I'm not sure that this is the right way to change this info...
FDropItem *di = PClass::FindActor(NAME_DoomPlayer)->DropItems;
FDropItem *di = PClass::FindActor(NAME_DoomPlayer)->ActorInfo()->DropItems;
while (di != NULL)
{
if (di->Name == NAME_Clip)
@ -2118,7 +2119,7 @@ static int PatchCodePtrs (int dummy)
// This skips the action table and goes directly to the internal symbol table
// DEH compatible functions are easy to recognize.
PFunction *sym = dyn_cast<PFunction>(RUNTIME_CLASS(AWeapon)->Symbols.FindSymbol(symname, true));
PFunction *sym = dyn_cast<PFunction>(RUNTIME_CLASS(AWeapon)->FindSymbol(symname, true));
if (sym == NULL)
{
Printf(TEXTCOLOR_RED "Frame %d: Unknown code pointer '%s'\n", frame, Line2);
@ -2744,7 +2745,7 @@ static bool LoadDehSupp ()
// or AActor so this will find all of them.
FString name = "A_";
name << sc.String;
PFunction *sym = dyn_cast<PFunction>(RUNTIME_CLASS(AWeapon)->Symbols.FindSymbol(name, true));
PFunction *sym = dyn_cast<PFunction>(RUNTIME_CLASS(AWeapon)->FindSymbol(name, true));
if (sym == NULL)
{
sc.ScriptError("Unknown code pointer '%s'", sc.String);
@ -2827,7 +2828,7 @@ static bool LoadDehSupp ()
{
sc.ScriptError ("Can't find type %s", sc.String);
}
else if (!type->IsKindOf(RUNTIME_CLASS(PClassActor)))
else if (!type->IsDescendantOf(RUNTIME_CLASS(AActor)))
{
sc.ScriptError ("%s is not an actor", sc.String);
}
@ -2843,7 +2844,7 @@ static bool LoadDehSupp ()
sc.MustGetStringName(",");
sc.MustGetNumber();
if (s.State == NULL || s.State + sc.Number > actortype->OwnedStates + actortype->NumOwnedStates)
if (s.State == NULL || !actortype->OwnsState(s.State + sc.Number))
{
sc.ScriptError("Invalid state range in '%s'", type->TypeName.GetChars());
}
@ -3034,7 +3035,8 @@ void FinishDehPatch ()
subclass = static_cast<PClassActor *>(dehtype->CreateDerivedClass(typeNameBuilder, dehtype->Size));
}
while (subclass == nullptr);
NewClassType(subclass); // This needs a VM type to work as intended.
AActor *defaults2 = GetDefaultByType (subclass);
memcpy ((void *)defaults2, (void *)defaults1, sizeof(AActor));
@ -3045,21 +3047,21 @@ void FinishDehPatch ()
if (!type->IsDescendantOf(RUNTIME_CLASS(AInventory)))
{
// If this is a hacked non-inventory item we must also copy AInventory's special states
statedef.AddStateDefines(RUNTIME_CLASS(AInventory)->StateList);
statedef.AddStateDefines(RUNTIME_CLASS(AInventory)->GetStateLabels());
}
statedef.InstallStates(subclass, defaults2);
// Use the DECORATE replacement feature to redirect all spawns
// of the original class to the new one.
PClassActor *old_replacement = type->Replacement;
PClassActor *old_replacement = type->ActorInfo()->Replacement;
type->Replacement = subclass;
subclass->Replacee = type;
type->ActorInfo()->Replacement = subclass;
subclass->ActorInfo()->Replacee = type;
// If this actor was already replaced by another actor, copy that
// replacement over to this item.
if (old_replacement != NULL)
{
subclass->Replacement = old_replacement;
subclass->ActorInfo()->Replacement = old_replacement;
}
DPrintf (DMSG_NOTIFY, "%s replaces %s\n", subclass->TypeName.GetChars(), type->TypeName.GetChars());
@ -3116,7 +3118,7 @@ void FinishDehPatch ()
{
if (AmmoPerAttacks[j].ptr == nullptr)
{
auto p = dyn_cast<PFunction>(RUNTIME_CLASS(AWeapon)->Symbols.FindSymbol(AmmoPerAttacks[j].func, true));
auto p = dyn_cast<PFunction>(RUNTIME_CLASS(AWeapon)->FindSymbol(AmmoPerAttacks[j].func, true));
if (p != nullptr) AmmoPerAttacks[j].ptr = p->Variants[0].Implementation;
}
if (state->ActionFunc == AmmoPerAttacks[j].ptr)
@ -3152,7 +3154,7 @@ DEFINE_ACTION_FUNCTION(ADehackedPickup, DetermineType)
int lex = memcmp (DehSpriteMappings[mid].Sprite, sprites[self->sprite].name, 4);
if (lex == 0)
{
ACTION_RETURN_OBJECT(PClass::FindActor(DehSpriteMappings[mid].ClassName));
ACTION_RETURN_POINTER(PClass::FindActor(DehSpriteMappings[mid].ClassName));
}
else if (lex < 0)
{
@ -3163,6 +3165,6 @@ DEFINE_ACTION_FUNCTION(ADehackedPickup, DetermineType)
max = mid - 1;
}
}
ACTION_RETURN_OBJECT(nullptr);
ACTION_RETURN_POINTER(nullptr);
}

View file

@ -112,6 +112,8 @@
#include "g_levellocals.h"
#include "events.h"
#include "r_utility.h"
#include "vm.h"
#include "types.h"
EXTERN_CVAR(Bool, hud_althud)
void DrawHUD();

View file

@ -2592,7 +2592,7 @@ void Net_DoCommand (int type, uint8_t **stream, int player)
char *classname = ReadString(stream);
int removecount = 0;
PClassActor *cls = PClass::FindActor(classname);
if (cls != NULL && cls->IsKindOf(RUNTIME_CLASS(PClassActor)))
if (cls != NULL && cls->IsDescendantOf(RUNTIME_CLASS(AActor)))
{
removecount = RemoveClass(cls);
const PClass *cls_rep = cls->GetReplacement();

View file

@ -57,6 +57,7 @@
#include "templates.h"
#include "cmdlib.h"
#include "serializer.h"
#include "vm.h"
static FRandom pr_pickteam ("PickRandomTeam");
@ -158,7 +159,7 @@ int D_PlayerClassToInt (const char *classname)
{
auto type = PlayerClasses[i].Type;
if (type->DisplayName.IsNotEmpty() && stricmp(type->DisplayName, classname) == 0)
if (type->GetDisplayName().IsNotEmpty() && stricmp(type->GetDisplayName(), classname) == 0)
{
return i;
}
@ -737,7 +738,7 @@ void D_WriteUserInfoStrings (int pnum, uint8_t **stream, bool compact)
case NAME_PlayerClass:
*stream += sprintf(*((char **)stream), "\\%s", info->GetPlayerClassNum() == -1 ? "Random" :
D_EscapeUserInfo(info->GetPlayerClassType()->DisplayName.GetChars()).GetChars());
D_EscapeUserInfo(info->GetPlayerClassType()->GetDisplayName().GetChars()).GetChars());
break;
case NAME_Skin:
@ -915,7 +916,7 @@ void WriteUserInfo(FSerializer &arc, userinfo_t &info)
case NAME_PlayerClass:
i = info.GetPlayerClassNum();
string = (i == -1 ? "Random" : PlayerClasses[i].Type->DisplayName.GetChars());
string = (i == -1 ? "Random" : PlayerClasses[i].Type->GetDisplayName().GetChars());
break;
default:
@ -1001,7 +1002,7 @@ CCMD (playerinfo)
Printf("%20s: %s (%d)\n", "Skin", Skins[ui->GetSkin()].Name.GetChars(), ui->GetSkin());
Printf("%20s: %s (%d)\n", "Gender", GenderNames[ui->GetGender()], ui->GetGender());
Printf("%20s: %s (%d)\n", "PlayerClass",
ui->GetPlayerClassNum() == -1 ? "Random" : ui->GetPlayerClassType()->DisplayName.GetChars(),
ui->GetPlayerClassNum() == -1 ? "Random" : ui->GetPlayerClassType()->GetDisplayName().GetChars(),
ui->GetPlayerClassNum());
// Print generic info

View file

@ -48,8 +48,9 @@
#include "a_sharedglobal.h"
#include "dsectoreffect.h"
#include "serializer.h"
#include "virtual.h"
#include "vm.h"
#include "g_levellocals.h"
#include "types.h"
//==========================================================================
//
@ -91,21 +92,22 @@ CCMD (dumpactors)
"25:DoomStrifeChex", "26:HereticStrifeChex", "27:NotHexen", "28:HexenStrifeChex", "29:NotHeretic",
"30:NotDoom", "31:All",
};
Printf("%i object class types total\nActor\tEd Num\tSpawnID\tFilter\tSource\n", PClass::AllClasses.Size());
Printf("%u object class types total\nActor\tEd Num\tSpawnID\tFilter\tSource\n", PClass::AllClasses.Size());
for (unsigned int i = 0; i < PClass::AllClasses.Size(); i++)
{
PClass *cls = PClass::AllClasses[i];
PClassActor *acls = dyn_cast<PClassActor>(cls);
PClassActor *acls = ValidateActor(cls);
if (acls != NULL)
{
auto ainfo = acls->ActorInfo();
Printf("%s\t%i\t%i\t%s\t%s\n",
acls->TypeName.GetChars(), acls->DoomEdNum,
acls->SpawnID, filters[acls->GameFilter & 31],
acls->TypeName.GetChars(), ainfo->DoomEdNum,
ainfo->SpawnID, filters[ainfo->GameFilter & 31],
acls->SourceLumpName.GetChars());
}
else if (cls != NULL)
{
Printf("%s\tn/a\tn/a\tn/a\tEngine (not an actor type)\n", cls->TypeName.GetChars());
Printf("%s\tn/a\tn/a\tn/a\tEngine (not an actor type)\tSource: %s\n", cls->TypeName.GetChars(), cls->SourceLumpName.GetChars());
}
else
{
@ -371,7 +373,7 @@ void DObject:: Destroy ()
IFVIRTUAL(DObject, OnDestroy)
{
VMValue params[1] = { (DObject*)this };
GlobalVMStack.Call(func, params, 1, nullptr, 0);
VMCall(func, params, 1, nullptr, 0);
}
}
OnDestroy();
@ -624,7 +626,7 @@ DEFINE_ACTION_FUNCTION(DObject, MSTime)
void *DObject::ScriptVar(FName field, PType *type)
{
auto cls = GetClass();
auto sym = dyn_cast<PField>(cls->Symbols.FindSymbol(field, true));
auto sym = dyn_cast<PField>(cls->FindSymbol(field, true));
if (sym && (sym->Type == type || type == nullptr))
{
if (!(sym->Flags & VARF_Meta))

View file

@ -247,13 +247,13 @@ public:
void Destroy();
// Add other types as needed.
bool &BoolVar(FName field);
int &IntVar(FName field);
FSoundID &SoundVar(FName field);
PalEntry &ColorVar(FName field);
FName &NameVar(FName field);
double &FloatVar(FName field);
FString &StringVar(FName field);
inline bool &BoolVar(FName field);
inline int &IntVar(FName field);
inline FSoundID &SoundVar(FName field);
inline PalEntry &ColorVar(FName field);
inline FName &NameVar(FName field);
inline double &FloatVar(FName field);
inline FString &StringVar(FName field);
template<class T> T*& PointerVar(FName field);
// If you need to replace one object with another and want to
@ -409,4 +409,40 @@ template<class T> const T *dyn_cast(const DObject *p)
return dyn_cast<T>(const_cast<DObject *>(p));
}
inline bool &DObject::BoolVar(FName field)
{
return *(bool*)ScriptVar(field, nullptr);
}
inline int &DObject::IntVar(FName field)
{
return *(int*)ScriptVar(field, nullptr);
}
inline FSoundID &DObject::SoundVar(FName field)
{
return *(FSoundID*)ScriptVar(field, nullptr);
}
inline PalEntry &DObject::ColorVar(FName field)
{
return *(PalEntry*)ScriptVar(field, nullptr);
}
inline FName &DObject::NameVar(FName field)
{
return *(FName*)ScriptVar(field, nullptr);
}
inline double &DObject::FloatVar(FName field)
{
return *(double*)ScriptVar(field, nullptr);
}
template<class T>
inline T *&DObject::PointerVar(FName field)
{
return *(T**)ScriptVar(field, nullptr); // pointer check is more tricky and for the handful of uses in the DECORATE parser not worth the hassle.
}
#endif //__DOBJECT_H__

File diff suppressed because it is too large Load diff

View file

@ -5,50 +5,17 @@
#error You must #include "dobject.h" to get dobjtype.h
#endif
typedef std::pair<const class PType *, unsigned> FTypeAndOffset;
class PStruct;
#include "memarena.h"
typedef std::pair<const class PType *, unsigned> FTypeAndOffset;
#if 0
// This is intentionally not in vm.h so that this file remains free of DObject pollution.
class VMException : public DObject
{
DECLARE_CLASS(VMException, DObject);
};
#include "vm.h"
// Variable/parameter/field flags -------------------------------------------
// Making all these different storage types use a common set of flags seems
// like the simplest thing to do.
enum
{
VARF_Optional = (1<<0), // func param is optional
VARF_Method = (1<<1), // func has an implied self parameter
VARF_Action = (1<<2), // func has implied owner and state parameters
VARF_Native = (1<<3), // func is native code, field is natively defined
VARF_ReadOnly = (1<<4), // field is read only, do not write to it
VARF_Private = (1<<5), // field is private to containing class
VARF_Protected = (1<<6), // field is only accessible by containing class and children.
VARF_Deprecated = (1<<7), // Deprecated fields should output warnings when used.
VARF_Virtual = (1<<8), // function is virtual
VARF_Final = (1<<9), // Function may not be overridden in subclasses
VARF_In = (1<<10),
VARF_Out = (1<<11),
VARF_Implicit = (1<<12), // implicitly created parameters (i.e. do not compare types when checking function signatures)
VARF_Static = (1<<13),
VARF_InternalAccess = (1<<14), // overrides VARF_ReadOnly for internal script code.
VARF_Override = (1<<15), // overrides a virtual function from the parent class.
VARF_Ref = (1<<16), // argument is passed by reference.
VARF_Transient = (1<<17), // don't auto serialize field.
VARF_Meta = (1<<18), // static class data (by necessity read only.)
VARF_VarArg = (1<<19), // [ZZ] vararg: don't typecheck values after ... in function signature
VARF_UI = (1<<20), // [ZZ] ui: object is ui-scope only (can't modify playsim)
VARF_Play = (1<<21), // [ZZ] play: object is playsim-scope only (can't access ui)
VARF_VirtualScope = (1<<22), // [ZZ] virtualscope: object should use the scope of the particular class it's being used with (methods only)
VARF_ClearScope = (1<<23), // [ZZ] clearscope: this method ignores the member access chain that leads to it and is always plain data.
};
#endif
// An action function -------------------------------------------------------
@ -58,567 +25,55 @@ class VMFrameStack;
struct VMValue;
struct VMReturn;
class VMFunction;
class PClassType;
struct FNamespaceManager;
// Basic information shared by all types ------------------------------------
// Only one copy of a type is ever instantiated at one time.
// - Enums, classes, and structs are defined by their names and outer classes.
// - Pointers are uniquely defined by the type they point at.
// - ClassPointers are also defined by their class restriction.
// - Arrays are defined by their element type and count.
// - DynArrays are defined by their element type.
// - Maps are defined by their key and value types.
// - Prototypes are defined by the argument and return types.
// - Functions are defined by their names and outer objects.
// In table form:
// Outer Name Type Type2 Count
// Enum * *
// Class * *
// Struct * *
// Function * *
// Pointer *
// ClassPointer + *
// Array * *
// DynArray *
// Map * *
// Prototype *+ *+
struct ZCC_ExprConstant;
class PType : public PTypeBase
{
DECLARE_ABSTRACT_CLASS(PType, PTypeBase)
protected:
public:
PClass *TypeTableType; // The type to use for hashing into the type table
unsigned int Size; // this type's size
unsigned int Align; // this type's preferred alignment
PType *HashNext; // next type in this type table
PSymbolTable Symbols;
bool MemberOnly = false; // type may only be used as a struct/class member but not as a local variable or function argument.
FString mDescriptiveName;
VersionInfo mVersion = { 0,0,0 };
uint8_t loadOp, storeOp, moveOp, RegType, RegCount;
PType(unsigned int size = 1, unsigned int align = 1);
virtual ~PType();
virtual bool isNumeric() { return false; }
// Writes the value of a variable of this type at (addr) to an archive, preceded by
// a tag indicating its type. The tag is there so that variable types can be changed
// without completely breaking savegames, provided that the change isn't between
// totally unrelated types.
virtual void WriteValue(FSerializer &ar, const char *key,const void *addr) const;
// Returns true if the stored value was compatible. False otherwise.
// If the value was incompatible, then the memory at *addr is unchanged.
virtual bool ReadValue(FSerializer &ar, const char *key,void *addr) const;
// Sets the default value for this type at (base + offset)
// If the default value is binary 0, then this function doesn't need
// to do anything, because PClass::Extend() takes care of that.
//
// The stroffs array is so that types that need special initialization
// and destruction (e.g. strings) can add their offsets to it for special
// initialization when the object is created and destruction when the
// object is destroyed.
virtual void SetDefaultValue(void *base, unsigned offset, TArray<FTypeAndOffset> *special=NULL) const;
virtual void SetPointer(void *base, unsigned offset, TArray<size_t> *ptrofs = NULL) const;
virtual void SetPointerArray(void *base, unsigned offset, TArray<size_t> *ptrofs = NULL) const;
// Initialize the value, if needed (e.g. strings)
virtual void InitializeValue(void *addr, const void *def) const;
// Destroy the value, if needed (e.g. strings)
virtual void DestroyValue(void *addr) const;
// Sets the value of a variable of this type at (addr)
virtual void SetValue(void *addr, int val);
virtual void SetValue(void *addr, double val);
// Gets the value of a variable of this type at (addr)
virtual int GetValueInt(void *addr) const;
virtual double GetValueFloat(void *addr) const;
// Gets the opcode to store from a register to memory
int GetStoreOp() const
{
return storeOp;
}
// Gets the opcode to load from memory to a register
int GetLoadOp() const
{
return loadOp;
}
// Gets the opcode to move from register to another register
int GetMoveOp() const
{
return moveOp;
}
// Gets the register type for this type
int GetRegType() const
{
return RegType;
}
int GetRegCount() const
{
return RegCount;
}
// Returns true if this type matches the two identifiers. Referring to the
// above table, any type is identified by at most two characteristics. Each
// type that implements this function will cast these to the appropriate type.
// It is up to the caller to make sure they are the correct types. There is
// only one prototype for this function in order to simplify type table
// management.
virtual bool IsMatch(intptr_t id1, intptr_t id2) const;
// Get the type IDs used by IsMatch
virtual void GetTypeIDs(intptr_t &id1, intptr_t &id2) const;
const char *DescriptiveName() const;
static void StaticInit();
};
// Not-really-a-type types --------------------------------------------------
class PErrorType : public PType
{
DECLARE_CLASS(PErrorType, PType);
public:
PErrorType(int which = 1) : PType(0, which) {}
};
class PVoidType : public PType
{
DECLARE_CLASS(PVoidType, PType);
public:
PVoidType() : PType(0, 1) {}
};
// Some categorization typing -----------------------------------------------
class PBasicType : public PType
{
DECLARE_ABSTRACT_CLASS(PBasicType, PType);
public:
PBasicType();
PBasicType(unsigned int size, unsigned int align);
};
class PCompoundType : public PType
{
DECLARE_ABSTRACT_CLASS(PCompoundType, PType);
};
class PNamedType : public PCompoundType
{
DECLARE_ABSTRACT_CLASS(PNamedType, PCompoundType);
public:
PTypeBase *Outer; // object this type is contained within
FName TypeName; // this type's name
PNamedType() : Outer(NULL) {
mDescriptiveName = "NamedType";
}
PNamedType(FName name, PTypeBase *outer) : Outer(outer), TypeName(name) {
mDescriptiveName = name.GetChars();
}
virtual bool IsMatch(intptr_t id1, intptr_t id2) const;
virtual void GetTypeIDs(intptr_t &id1, intptr_t &id2) const;
};
// Basic types --------------------------------------------------------------
class PInt : public PBasicType
{
DECLARE_CLASS(PInt, PBasicType);
public:
PInt(unsigned int size, bool unsign, bool compatible = true);
void WriteValue(FSerializer &ar, const char *key,const void *addr) const override;
bool ReadValue(FSerializer &ar, const char *key,void *addr) const override;
virtual void SetValue(void *addr, int val);
virtual void SetValue(void *addr, double val);
virtual int GetValueInt(void *addr) const;
virtual double GetValueFloat(void *addr) const;
virtual bool isNumeric() override { return IntCompatible; }
bool Unsigned;
bool IntCompatible;
protected:
PInt();
void SetOps();
};
class PBool : public PInt
{
DECLARE_CLASS(PBool, PInt);
public:
PBool();
virtual void SetValue(void *addr, int val);
virtual void SetValue(void *addr, double val);
virtual int GetValueInt(void *addr) const;
virtual double GetValueFloat(void *addr) const;
};
class PFloat : public PBasicType
{
DECLARE_CLASS(PFloat, PBasicType);
public:
PFloat(unsigned int size);
void WriteValue(FSerializer &ar, const char *key,const void *addr) const override;
bool ReadValue(FSerializer &ar, const char *key,void *addr) const override;
virtual void SetValue(void *addr, int val);
virtual void SetValue(void *addr, double val);
virtual int GetValueInt(void *addr) const;
virtual double GetValueFloat(void *addr) const;
virtual bool isNumeric() override { return true; }
protected:
PFloat();
void SetOps();
private:
struct SymbolInitF
{
ENamedName Name;
double Value;
};
struct SymbolInitI
{
ENamedName Name;
int Value;
};
void SetSingleSymbols();
void SetDoubleSymbols();
void SetSymbols(const SymbolInitF *syminit, size_t count);
void SetSymbols(const SymbolInitI *syminit, size_t count);
};
class PString : public PBasicType
{
DECLARE_CLASS(PString, PBasicType);
public:
PString();
void WriteValue(FSerializer &ar, const char *key,const void *addr) const override;
bool ReadValue(FSerializer &ar, const char *key,void *addr) const override;
void SetDefaultValue(void *base, unsigned offset, TArray<FTypeAndOffset> *special=NULL) const override;
void InitializeValue(void *addr, const void *def) const override;
void DestroyValue(void *addr) const override;
};
// Variations of integer types ----------------------------------------------
class PName : public PInt
{
DECLARE_CLASS(PName, PInt);
public:
PName();
void WriteValue(FSerializer &ar, const char *key,const void *addr) const override;
bool ReadValue(FSerializer &ar, const char *key,void *addr) const override;
};
class PSound : public PInt
{
DECLARE_CLASS(PSound, PInt);
public:
PSound();
void WriteValue(FSerializer &ar, const char *key,const void *addr) const override;
bool ReadValue(FSerializer &ar, const char *key,void *addr) const override;
};
class PSpriteID : public PInt
{
DECLARE_CLASS(PSpriteID, PInt);
public:
PSpriteID();
void WriteValue(FSerializer &ar, const char *key, const void *addr) const override;
bool ReadValue(FSerializer &ar, const char *key, void *addr) const override;
};
class PTextureID : public PInt
{
DECLARE_CLASS(PTextureID, PInt);
public:
PTextureID();
void WriteValue(FSerializer &ar, const char *key, const void *addr) const override;
bool ReadValue(FSerializer &ar, const char *key, void *addr) const override;
};
class PColor : public PInt
{
DECLARE_CLASS(PColor, PInt);
public:
PColor();
};
class PStateLabel : public PInt
{
DECLARE_CLASS(PStateLabel, PInt);
public:
PStateLabel();
};
// Pointers -----------------------------------------------------------------
class PPointer : public PBasicType
{
DECLARE_CLASS(PPointer, PBasicType);
public:
typedef void(*WriteHandler)(FSerializer &ar, const char *key, const void *addr);
typedef bool(*ReadHandler)(FSerializer &ar, const char *key, void *addr);
PPointer();
PPointer(PType *pointsat, bool isconst = false);
PType *PointedType;
bool IsConst;
WriteHandler writer = nullptr;
ReadHandler reader = nullptr;
void InstallHandlers(WriteHandler w, ReadHandler r)
{
writer = w;
reader = r;
}
virtual bool IsMatch(intptr_t id1, intptr_t id2) const;
virtual void GetTypeIDs(intptr_t &id1, intptr_t &id2) const;
void SetPointer(void *base, unsigned offset, TArray<size_t> *special = NULL) const override;
void WriteValue(FSerializer &ar, const char *key,const void *addr) const override;
bool ReadValue(FSerializer &ar, const char *key,void *addr) const override;
protected:
void SetOps();
};
class PStatePointer : public PPointer
{
DECLARE_CLASS(PStatePointer, PPointer);
public:
PStatePointer();
void WriteValue(FSerializer &ar, const char *key, const void *addr) const override;
bool ReadValue(FSerializer &ar, const char *key, void *addr) const override;
};
class PClassPointer : public PPointer
{
DECLARE_CLASS(PClassPointer, PPointer);
public:
PClassPointer(class PClass *restrict = nullptr);
class PClass *ClassRestriction;
bool isCompatible(PType *type);
void SetPointer(void *base, unsigned offset, TArray<size_t> *special = NULL) const override;
virtual bool IsMatch(intptr_t id1, intptr_t id2) const;
virtual void GetTypeIDs(intptr_t &id1, intptr_t &id2) const;
};
// Compound types -----------------------------------------------------------
class PEnum : public PInt
{
DECLARE_CLASS(PEnum, PInt);
public:
PEnum(FName name, PTypeBase *outer);
PTypeBase *Outer;
FName EnumName;
protected:
PEnum();
};
class PArray : public PCompoundType
{
DECLARE_CLASS(PArray, PCompoundType);
public:
PArray(PType *etype, unsigned int ecount);
PType *ElementType;
unsigned int ElementCount;
unsigned int ElementSize;
virtual bool IsMatch(intptr_t id1, intptr_t id2) const;
virtual void GetTypeIDs(intptr_t &id1, intptr_t &id2) const;
void WriteValue(FSerializer &ar, const char *key,const void *addr) const override;
bool ReadValue(FSerializer &ar, const char *key,void *addr) const override;
void SetDefaultValue(void *base, unsigned offset, TArray<FTypeAndOffset> *special) const override;
void SetPointer(void *base, unsigned offset, TArray<size_t> *special) const override;
protected:
PArray();
};
class PStaticArray : public PArray
{
DECLARE_CLASS(PStaticArray, PArray);
public:
PStaticArray(PType *etype);
virtual bool IsMatch(intptr_t id1, intptr_t id2) const;
virtual void GetTypeIDs(intptr_t &id1, intptr_t &id2) const;
protected:
PStaticArray();
};
class PDynArray : public PCompoundType
{
DECLARE_CLASS(PDynArray, PCompoundType);
public:
PDynArray(PType *etype, PStruct *backing);
PType *ElementType;
PStruct *BackingType;
virtual bool IsMatch(intptr_t id1, intptr_t id2) const;
virtual void GetTypeIDs(intptr_t &id1, intptr_t &id2) const;
void WriteValue(FSerializer &ar, const char *key, const void *addr) const override;
bool ReadValue(FSerializer &ar, const char *key, void *addr) const override;
void SetDefaultValue(void *base, unsigned offset, TArray<FTypeAndOffset> *specials) const override;
void InitializeValue(void *addr, const void *def) const override;
void DestroyValue(void *addr) const override;
void SetPointerArray(void *base, unsigned offset, TArray<size_t> *ptrofs = NULL) const override;
protected:
PDynArray();
};
class PMap : public PCompoundType
{
DECLARE_CLASS(PMap, PCompoundType);
public:
PMap(PType *keytype, PType *valtype);
PType *KeyType;
PType *ValueType;
virtual bool IsMatch(intptr_t id1, intptr_t id2) const;
virtual void GetTypeIDs(intptr_t &id1, intptr_t &id2) const;
protected:
PMap();
};
class PStruct : public PNamedType
{
DECLARE_CLASS(PStruct, PNamedType);
public:
PStruct(FName name, PTypeBase *outer);
TArray<PField *> Fields;
bool HasNativeFields;
// Some internal structs require explicit construction and destruction of fields the VM cannot handle directly so use thes two functions for it.
VMFunction *mConstructor = nullptr;
VMFunction *mDestructor = nullptr;
virtual PField *AddField(FName name, PType *type, uint32_t flags=0);
virtual PField *AddNativeField(FName name, PType *type, size_t address, uint32_t flags = 0, int bitvalue = 0);
void WriteValue(FSerializer &ar, const char *key,const void *addr) const override;
bool ReadValue(FSerializer &ar, const char *key,void *addr) const override;
void SetDefaultValue(void *base, unsigned offset, TArray<FTypeAndOffset> *specials) const override;
void SetPointer(void *base, unsigned offset, TArray<size_t> *specials) const override;
static void WriteFields(FSerializer &ar, const void *addr, const TArray<PField *> &fields);
bool ReadFields(FSerializer &ar, void *addr) const;
protected:
PStruct();
};
// a native struct will always be abstract and cannot be instantiated. All variables are references.
// In addition, native structs can have methods (but no virtual ones.)
class PNativeStruct : public PStruct
{
DECLARE_CLASS(PNativeStruct, PStruct);
public:
PNativeStruct(FName name = NAME_None, PTypeBase *outer = nullptr);
};
class PPrototype : public PCompoundType
{
DECLARE_CLASS(PPrototype, PCompoundType);
public:
PPrototype(const TArray<PType *> &rettypes, const TArray<PType *> &argtypes);
TArray<PType *> ArgumentTypes;
TArray<PType *> ReturnTypes;
size_t PropagateMark();
virtual bool IsMatch(intptr_t id1, intptr_t id2) const;
virtual void GetTypeIDs(intptr_t &id1, intptr_t &id2) const;
protected:
PPrototype();
};
// Meta-info for every class derived from DObject ---------------------------
extern FMemArena ClassDataAllocator;
enum
{
TentativeClass = UINT_MAX,
};
class PClass : public PNativeStruct
class PClass
{
DECLARE_CLASS(PClass, PNativeStruct);
// We unravel _WITH_META here just as we did for PType.
protected:
TArray<FTypeAndOffset> MetaInits;
void Derive(PClass *newclass, FName name);
void InitializeSpecials(void *addr, void *defaults, TArray<FTypeAndOffset> PClass::*Inits);
void SetSuper();
PField *AddMetaField(FName name, PType *type, uint32_t flags);
public:
void WriteValue(FSerializer &ar, const char *key,const void *addr) const override;
void WriteAllFields(FSerializer &ar, const void *addr) const;
bool ReadValue(FSerializer &ar, const char *key,void *addr) const override;
bool ReadAllFields(FSerializer &ar, void *addr) const;
void InitializeDefaults();
int FindVirtualIndex(FName name, PPrototype *proto);
virtual void DeriveData(PClass *newclass);
PSymbol *FindSymbol(FName symname, bool searchparents) const;
PField *AddField(FName name, PType *type, uint32_t flags);
static void StaticInit();
static void StaticShutdown();
static void StaticBootstrap();
// Per-class information -------------------------------------
TArray<FTypeAndOffset> SpecialInits;
PClass *ParentClass; // the class this class derives from
const size_t *Pointers; // object pointers defined by this class *only*
const size_t *FlatPointers; // object pointers defined by this class and all its superclasses; not initialized by default
const size_t *ArrayPointers; // dynamic arrays containing object pointers.
uint8_t *Defaults;
uint8_t *Meta; // Per-class static script data
unsigned MetaSize;
bool bRuntimeClass; // class was defined at run-time, not compile-time
bool bExported; // This type has been declared in a script
bool bDecorateClass; // may be subject to some idiosyncracies due to DECORATE backwards compatibility
PClass *ParentClass = nullptr; // the class this class derives from
const size_t *Pointers = nullptr; // object pointers defined by this class *only*
const size_t *FlatPointers = nullptr; // object pointers defined by this class and all its superclasses; not initialized by default
const size_t *ArrayPointers = nullptr; // dynamic arrays containing object pointers.
uint8_t *Defaults = nullptr;
uint8_t *Meta = nullptr; // Per-class static script data
unsigned Size = sizeof(DObject);
unsigned MetaSize = 0;
FName TypeName;
FName SourceLumpName;
bool bRuntimeClass = false; // class was defined at run-time, not compile-time
bool bDecorateClass = false; // may be subject to some idiosyncracies due to DECORATE backwards compatibility
bool bAbstract = false;
bool bOptional = false;
TArray<VMFunction*> Virtuals; // virtual function table
TArray<FTypeAndOffset> MetaInits;
TArray<FTypeAndOffset> SpecialInits;
TArray<PField *> Fields;
PClassType *VMType = nullptr;
void (*ConstructNative)(void *);
@ -628,12 +83,12 @@ public:
void InsertIntoHash();
DObject *CreateNew();
PClass *CreateDerivedClass(FName name, unsigned int size);
PField *AddField(FName name, PType *type, uint32_t flags=0) override;
void InitializeActorInfo();
void BuildFlatPointers();
void BuildArrayPointers();
void InitMeta();
void DestroySpecials(void *addr);
void DestroyMeta(void *addr);
const PClass *NativeClass() const;
// Returns true if this type is an ancestor of (or same as) the passed type.
@ -681,6 +136,7 @@ public:
static void FindFunction(VMFunction **pptr, FName cls, FName func);
PClass *FindClassTentative(FName name);
static TMap<FName, PClass*> ClassMap;
static TArray<PClass *> AllClasses;
static TArray<VMFunction**> FunctionPtrList;
@ -688,106 +144,4 @@ public:
static bool bVMOperational;
};
// Type tables --------------------------------------------------------------
struct FTypeTable
{
enum { HASH_SIZE = 1021 };
PType *TypeHash[HASH_SIZE];
PType *FindType(PClass *metatype, intptr_t parm1, intptr_t parm2, size_t *bucketnum);
void AddType(PType *type, PClass *metatype, intptr_t parm1, intptr_t parm2, size_t bucket);
void AddType(PType *type);
void Clear();
static size_t Hash(const PClass *p1, intptr_t p2, intptr_t p3);
};
extern FTypeTable TypeTable;
// Returns a type from the TypeTable. Will create one if it isn't present.
PMap *NewMap(PType *keytype, PType *valuetype);
PArray *NewArray(PType *type, unsigned int count);
PStaticArray *NewStaticArray(PType *type);
PDynArray *NewDynArray(PType *type);
PPointer *NewPointer(PType *type, bool isconst = false);
PClassPointer *NewClassPointer(PClass *restrict);
PEnum *NewEnum(FName name, PTypeBase *outer);
PStruct *NewStruct(FName name, PTypeBase *outer);
PNativeStruct *NewNativeStruct(FName name, PTypeBase *outer);
PPrototype *NewPrototype(const TArray<PType *> &rettypes, const TArray<PType *> &argtypes);
// Built-in types -----------------------------------------------------------
extern PErrorType *TypeError;
extern PErrorType *TypeAuto;
extern PVoidType *TypeVoid;
extern PInt *TypeSInt8, *TypeUInt8;
extern PInt *TypeSInt16, *TypeUInt16;
extern PInt *TypeSInt32, *TypeUInt32;
extern PBool *TypeBool;
extern PFloat *TypeFloat32, *TypeFloat64;
extern PString *TypeString;
extern PName *TypeName;
extern PSound *TypeSound;
extern PColor *TypeColor;
extern PTextureID *TypeTextureID;
extern PSpriteID *TypeSpriteID;
extern PStruct *TypeVector2;
extern PStruct *TypeVector3;
extern PStruct *TypeColorStruct;
extern PStruct *TypeStringStruct;
extern PStatePointer *TypeState;
extern PPointer *TypeFont;
extern PStateLabel *TypeStateLabel;
extern PPointer *TypeNullPtr;
extern PPointer *TypeVoidPtr;
// Enumerations for serializing types in an archive -------------------------
inline bool &DObject::BoolVar(FName field)
{
return *(bool*)ScriptVar(field, TypeBool);
}
inline int &DObject::IntVar(FName field)
{
return *(int*)ScriptVar(field, TypeSInt32);
}
inline FSoundID &DObject::SoundVar(FName field)
{
return *(FSoundID*)ScriptVar(field, TypeSound);
}
inline PalEntry &DObject::ColorVar(FName field)
{
return *(PalEntry*)ScriptVar(field, TypeColor);
}
inline FName &DObject::NameVar(FName field)
{
return *(FName*)ScriptVar(field, TypeName);
}
inline double &DObject::FloatVar(FName field)
{
return *(double*)ScriptVar(field, TypeFloat64);
}
inline FString &DObject::StringVar(FName field)
{
return *(FString*)ScriptVar(field, TypeString);
}
template<class T>
inline T *&DObject::PointerVar(FName field)
{
return *(T**)ScriptVar(field, nullptr); // pointer check is more tricky and for the handful of uses in the DECORATE parser not worth the hassle.
}
void RemoveUnusedSymbols();
#endif

View file

@ -61,7 +61,6 @@ CUSTOM_CVAR (String, language, "auto", CVAR_ARCHIVE)
// [RH] Network arbitrator
int Net_Arbitrator = 0;
DEFINE_GLOBAL(Net_Arbitrator);
int NextSkill = -1;

View file

@ -31,6 +31,7 @@
#include "statnums.h"
#include "serializer.h"
#include "doomstat.h"
#include "vm.h"
IMPLEMENT_CLASS(DSectorEffect, false, false)
@ -75,16 +76,12 @@ void DSectorEffect::Serialize(FSerializer &arc)
DEFINE_FIELD(DSectorEffect, m_Sector)
IMPLEMENT_CLASS(DMover, false, true)
IMPLEMENT_CLASS(DMover, true, true)
IMPLEMENT_POINTERS_START(DMover)
IMPLEMENT_POINTER(interpolation)
IMPLEMENT_POINTERS_END
DMover::DMover ()
{
}
DMover::DMover (sector_t *sector)
: DSectorEffect (sector)
{
@ -112,11 +109,8 @@ void DMover::StopInterpolation(bool force)
}
}
IMPLEMENT_CLASS(DMovingFloor, false, false)
IMPLEMENT_CLASS(DMovingFloor, true, false)
DMovingFloor::DMovingFloor ()
{
}
DMovingFloor::DMovingFloor (sector_t *sector)
: DMover (sector)
@ -125,11 +119,8 @@ DMovingFloor::DMovingFloor (sector_t *sector)
interpolation = sector->SetInterpolation(sector_t::FloorMove, true);
}
IMPLEMENT_CLASS(DMovingCeiling, false, false)
IMPLEMENT_CLASS(DMovingCeiling, true, false)
DMovingCeiling::DMovingCeiling ()
{
}
DMovingCeiling::DMovingCeiling (sector_t *sector, bool interpolate)
: DMover (sector)

View file

@ -25,16 +25,17 @@ protected:
class DMover : public DSectorEffect
{
DECLARE_CLASS (DMover, DSectorEffect)
DECLARE_ABSTRACT_CLASS (DMover, DSectorEffect)
HAS_OBJECT_POINTERS
public:
protected:
DMover (sector_t *sector);
void StopInterpolation(bool force = false);
protected:
TObjPtr<DInterpolation*> interpolation;
private:
public:
void StopInterpolation(bool force = false);
protected:
DMover ();
DMover () {}
void Serialize(FSerializer &arc);
void OnDestroy() override;
@ -42,20 +43,18 @@ protected:
class DMovingFloor : public DMover
{
DECLARE_CLASS (DMovingFloor, DMover)
public:
DMovingFloor (sector_t *sector);
DECLARE_ABSTRACT_CLASS (DMovingFloor, DMover)
protected:
DMovingFloor ();
DMovingFloor (sector_t *sector);
DMovingFloor() {}
};
class DMovingCeiling : public DMover
{
DECLARE_CLASS (DMovingCeiling, DMover)
public:
DMovingCeiling (sector_t *sector, bool interpolate = true);
DECLARE_ABSTRACT_CLASS (DMovingCeiling, DMover)
protected:
DMovingCeiling ();
DMovingCeiling (sector_t *sector, bool interpolate = true);
DMovingCeiling () {}
};
#endif //__DSECTOREFFECT_H__

View file

@ -40,7 +40,7 @@
#include "doomerrors.h"
#include "serializer.h"
#include "d_player.h"
#include "virtual.h"
#include "vm.h"
static int ThinkCount;
@ -315,7 +315,7 @@ void DThinker::CallPostBeginPlay()
{
// Without the type cast this picks the 'void *' assignment...
VMValue params[1] = { (DObject*)this };
GlobalVMStack.Call(func, params, 1, nullptr, 0, nullptr);
VMCall(func, params, 1, nullptr, 0);
}
else
{
@ -560,7 +560,7 @@ void DThinker::CallTick()
{
// Without the type cast this picks the 'void *' assignment...
VMValue params[1] = { (DObject*)this };
GlobalVMStack.Call(func, params, 1, nullptr, 0, nullptr);
VMCall(func, params, 1, nullptr, 0);
}
else Tick();
}

View file

@ -1,5 +1,5 @@
#include "events.h"
#include "virtual.h"
#include "vm.h"
#include "r_utility.h"
#include "g_levellocals.h"
#include "gi.h"
@ -7,6 +7,7 @@
#include "actor.h"
#include "c_dispatch.h"
#include "d_net.h"
#include "vm.h"
DStaticEventHandler* E_FirstEventHandler = nullptr;
DStaticEventHandler* E_LastEventHandler = nullptr;
@ -626,7 +627,7 @@ void DStaticEventHandler::OnRegister()
if (func == DStaticEventHandler_OnRegister_VMPtr)
return;
VMValue params[1] = { (DStaticEventHandler*)this };
GlobalVMStack.Call(func, params, 1, nullptr, 0, nullptr);
VMCall(func, params, 1, nullptr, 0);
}
}
@ -638,7 +639,7 @@ void DStaticEventHandler::OnUnregister()
if (func == DStaticEventHandler_OnUnregister_VMPtr)
return;
VMValue params[1] = { (DStaticEventHandler*)this };
GlobalVMStack.Call(func, params, 1, nullptr, 0, nullptr);
VMCall(func, params, 1, nullptr, 0);
}
}
@ -660,7 +661,7 @@ void DStaticEventHandler::WorldLoaded()
return;
FWorldEvent e = E_SetupWorldEvent();
VMValue params[2] = { (DStaticEventHandler*)this, &e };
GlobalVMStack.Call(func, params, 2, nullptr, 0, nullptr);
VMCall(func, params, 2, nullptr, 0);
}
}
@ -673,7 +674,7 @@ void DStaticEventHandler::WorldUnloaded()
return;
FWorldEvent e = E_SetupWorldEvent();
VMValue params[2] = { (DStaticEventHandler*)this, &e };
GlobalVMStack.Call(func, params, 2, nullptr, 0, nullptr);
VMCall(func, params, 2, nullptr, 0);
}
}
@ -687,7 +688,7 @@ void DStaticEventHandler::WorldThingSpawned(AActor* actor)
FWorldEvent e = E_SetupWorldEvent();
e.Thing = actor;
VMValue params[2] = { (DStaticEventHandler*)this, &e };
GlobalVMStack.Call(func, params, 2, nullptr, 0, nullptr);
VMCall(func, params, 2, nullptr, 0);
}
}
@ -702,7 +703,7 @@ void DStaticEventHandler::WorldThingDied(AActor* actor, AActor* inflictor)
e.Thing = actor;
e.Inflictor = inflictor;
VMValue params[2] = { (DStaticEventHandler*)this, &e };
GlobalVMStack.Call(func, params, 2, nullptr, 0, nullptr);
VMCall(func, params, 2, nullptr, 0);
}
}
@ -716,7 +717,7 @@ void DStaticEventHandler::WorldThingRevived(AActor* actor)
FWorldEvent e = E_SetupWorldEvent();
e.Thing = actor;
VMValue params[2] = { (DStaticEventHandler*)this, &e };
GlobalVMStack.Call(func, params, 2, nullptr, 0, nullptr);
VMCall(func, params, 2, nullptr, 0);
}
}
@ -735,7 +736,7 @@ void DStaticEventHandler::WorldThingDamaged(AActor* actor, AActor* inflictor, AA
e.DamageFlags = flags;
e.DamageAngle = angle;
VMValue params[2] = { (DStaticEventHandler*)this, &e };
GlobalVMStack.Call(func, params, 2, nullptr, 0, nullptr);
VMCall(func, params, 2, nullptr, 0);
}
}
@ -749,7 +750,7 @@ void DStaticEventHandler::WorldThingDestroyed(AActor* actor)
FWorldEvent e = E_SetupWorldEvent();
e.Thing = actor;
VMValue params[2] = { (DStaticEventHandler*)this, &e };
GlobalVMStack.Call(func, params, 2, nullptr, 0, nullptr);
VMCall(func, params, 2, nullptr, 0);
}
}
@ -762,7 +763,7 @@ void DStaticEventHandler::WorldLightning()
return;
FWorldEvent e = E_SetupWorldEvent();
VMValue params[2] = { (DStaticEventHandler*)this, &e };
GlobalVMStack.Call(func, params, 2, nullptr, 0, nullptr);
VMCall(func, params, 2, nullptr, 0);
}
}
@ -774,7 +775,7 @@ void DStaticEventHandler::WorldTick()
if (func == DStaticEventHandler_WorldTick_VMPtr)
return;
VMValue params[1] = { (DStaticEventHandler*)this };
GlobalVMStack.Call(func, params, 1, nullptr, 0, nullptr);
VMCall(func, params, 1, nullptr, 0);
}
}
@ -799,7 +800,7 @@ void DStaticEventHandler::RenderFrame()
return;
FRenderEvent e = E_SetupRenderEvent();
VMValue params[2] = { (DStaticEventHandler*)this, &e };
GlobalVMStack.Call(func, params, 2, nullptr, 0, nullptr);
VMCall(func, params, 2, nullptr, 0);
}
}
@ -813,7 +814,7 @@ void DStaticEventHandler::RenderOverlay(EHudState state)
FRenderEvent e = E_SetupRenderEvent();
e.HudState = int(state);
VMValue params[2] = { (DStaticEventHandler*)this, &e };
GlobalVMStack.Call(func, params, 2, nullptr, 0, nullptr);
VMCall(func, params, 2, nullptr, 0);
}
}
@ -826,7 +827,7 @@ void DStaticEventHandler::PlayerEntered(int num, bool fromhub)
return;
FPlayerEvent e = { num, fromhub };
VMValue params[2] = { (DStaticEventHandler*)this, &e };
GlobalVMStack.Call(func, params, 2, nullptr, 0, nullptr);
VMCall(func, params, 2, nullptr, 0);
}
}
@ -839,7 +840,7 @@ void DStaticEventHandler::PlayerRespawned(int num)
return;
FPlayerEvent e = { num, false };
VMValue params[2] = { (DStaticEventHandler*)this, &e };
GlobalVMStack.Call(func, params, 2, nullptr, 0, nullptr);
VMCall(func, params, 2, nullptr, 0);
}
}
@ -852,7 +853,7 @@ void DStaticEventHandler::PlayerDied(int num)
return;
FPlayerEvent e = { num, false };
VMValue params[2] = { (DStaticEventHandler*)this, &e };
GlobalVMStack.Call(func, params, 2, nullptr, 0, nullptr);
VMCall(func, params, 2, nullptr, 0);
}
}
@ -865,7 +866,7 @@ void DStaticEventHandler::PlayerDisconnected(int num)
return;
FPlayerEvent e = { num, false };
VMValue params[2] = { (DStaticEventHandler*)this, &e };
GlobalVMStack.Call(func, params, 2, nullptr, 0, nullptr);
VMCall(func, params, 2, nullptr, 0);
}
}
@ -921,7 +922,7 @@ bool DStaticEventHandler::UiProcess(const event_t* ev)
int processed;
VMReturn results[1] = { &processed };
VMValue params[2] = { (DStaticEventHandler*)this, &e };
GlobalVMStack.Call(func, params, 2, results, 1, nullptr);
VMCall(func, params, 2, results, 1);
return !!processed;
}
@ -969,7 +970,7 @@ bool DStaticEventHandler::InputProcess(const event_t* ev)
int processed;
VMReturn results[1] = { &processed };
VMValue params[2] = { (DStaticEventHandler*)this, &e };
GlobalVMStack.Call(func, params, 2, results, 1, nullptr);
VMCall(func, params, 2, results, 1);
return !!processed;
}
@ -984,7 +985,7 @@ void DStaticEventHandler::UiTick()
if (func == DStaticEventHandler_UiTick_VMPtr)
return;
VMValue params[1] = { (DStaticEventHandler*)this };
GlobalVMStack.Call(func, params, 1, nullptr, 0, nullptr);
VMCall(func, params, 1, nullptr, 0);
}
}
@ -1008,7 +1009,7 @@ void DStaticEventHandler::ConsoleProcess(int player, FString name, int arg1, int
e.IsManual = manual;
VMValue params[2] = { (DStaticEventHandler*)this, &e };
GlobalVMStack.Call(func, params, 2, nullptr, 0, nullptr);
VMCall(func, params, 2, nullptr, 0);
}
}
else
@ -1029,7 +1030,7 @@ void DStaticEventHandler::ConsoleProcess(int player, FString name, int arg1, int
e.IsManual = manual;
VMValue params[2] = { (DStaticEventHandler*)this, &e };
GlobalVMStack.Call(func, params, 2, nullptr, 0, nullptr);
VMCall(func, params, 2, nullptr, 0);
}
}
}

View file

@ -85,6 +85,7 @@
#include "serializer.h"
#include "w_zip.h"
#include "resourcefiles/resourcefile.h"
#include "vm.h"
#include <zlib.h>
@ -3012,3 +3013,5 @@ DEFINE_GLOBAL(skyflatnum)
DEFINE_GLOBAL_NAMED(bglobal.freeze, globalfreeze)
DEFINE_GLOBAL(gametic)
DEFINE_GLOBAL(demoplayback)
DEFINE_GLOBAL(automapactive);
DEFINE_GLOBAL(Net_Arbitrator);

View file

@ -43,7 +43,7 @@
#include "w_wad.h"
#include "doomstat.h"
#include "v_font.h"
#include "vm.h"
//===========================================================================
//

View file

@ -19,9 +19,10 @@
#include "d_player.h"
#include "p_spec.h"
#include "serializer.h"
#include "virtual.h"
#include "vm.h"
#include "c_functions.h"
#include "g_levellocals.h"
#include "vm.h"
EXTERN_CVAR(Bool, sv_unlimited_pickup)
@ -237,7 +238,7 @@ double AInventory::GetSpeedFactor()
VMValue params[1] = { (DObject*)self };
double retval;
VMReturn ret(&retval);
GlobalVMStack.Call(func, params, 1, &ret, 1, nullptr);
VMCall(func, params, 1, &ret, 1);
factor *= retval;
}
self = self->Inventory;
@ -261,7 +262,7 @@ bool AInventory::GetNoTeleportFreeze ()
VMValue params[1] = { (DObject*)self };
int retval;
VMReturn ret(&retval);
GlobalVMStack.Call(func, params, 1, &ret, 1, nullptr);
VMCall(func, params, 1, &ret, 1);
if (retval) return true;
}
self = self->Inventory;
@ -282,7 +283,7 @@ bool AInventory::CallUse(bool pickup)
VMValue params[2] = { (DObject*)this, pickup };
int retval;
VMReturn ret(&retval);
GlobalVMStack.Call(func, params, 2, &ret, 1, nullptr);
VMCall(func, params, 2, &ret, 1);
return !!retval;
}
return false;
@ -347,7 +348,7 @@ void AInventory::DepleteOrDestroy ()
IFVIRTUAL(AInventory, DepleteOrDestroy)
{
VMValue params[1] = { (DObject*)this };
GlobalVMStack.Call(func, params, 1, nullptr, 0, nullptr);
VMCall(func, params, 1, nullptr, 0);
}
}
@ -367,7 +368,7 @@ PalEntry AInventory::CallGetBlend()
VMValue params[1] = { (DObject*)this };
int retval;
VMReturn ret(&retval);
GlobalVMStack.Call(func, params, 1, &ret, 1, nullptr);
VMCall(func, params, 1, &ret, 1);
return retval;
}
else return 0;
@ -479,7 +480,7 @@ bool AInventory::CallTryPickup(AActor *toucher, AActor **toucher_return)
AActor *tret;
ret[0].IntAt(&res);
ret[1].PointerAt((void**)&tret);
GlobalVMStack.Call(func, params, 2, ret, 2);
VMCall(func, params, 2, ret, 2);
if (toucher_return) *toucher_return = tret;
return !!res;
}

View file

@ -52,11 +52,7 @@
#include "g_level.h"
#include "d_net.h"
#include "serializer.h"
#include "thingdef.h"
#include "virtual.h"
extern FFlagDef WeaponFlagDefs[];
#include "vm.h"
IMPLEMENT_CLASS(AWeapon, false, true)
@ -66,7 +62,6 @@ IMPLEMENT_POINTERS_START(AWeapon)
IMPLEMENT_POINTER(SisterWeapon)
IMPLEMENT_POINTERS_END
DEFINE_FIELD(AWeapon, WeaponFlags)
DEFINE_FIELD(AWeapon, AmmoType1)
DEFINE_FIELD(AWeapon, AmmoType2)
DEFINE_FIELD(AWeapon, AmmoGive1)
@ -99,6 +94,7 @@ DEFINE_FIELD(AWeapon, Crosshair)
DEFINE_FIELD(AWeapon, GivenAsMorphWeapon)
DEFINE_FIELD(AWeapon, bAltFire)
DEFINE_FIELD(AWeapon, SlotNumber)
DEFINE_FIELD(AWeapon, WeaponFlags)
DEFINE_FIELD_BIT(AWeapon, WeaponFlags, bDehAmmo, WIF_DEHAMMO)
//===========================================================================
@ -404,7 +400,7 @@ FState *AWeapon::GetUpState ()
VMReturn ret;
FState *retval;
ret.PointerAt((void**)&retval);
GlobalVMStack.Call(func, params, 1, &ret, 1, nullptr);
VMCall(func, params, 1, &ret, 1);
return retval;
}
return nullptr;
@ -424,7 +420,7 @@ FState *AWeapon::GetDownState ()
VMReturn ret;
FState *retval;
ret.PointerAt((void**)&retval);
GlobalVMStack.Call(func, params, 1, &ret, 1, nullptr);
VMCall(func, params, 1, &ret, 1);
return retval;
}
return nullptr;
@ -444,7 +440,7 @@ FState *AWeapon::GetReadyState ()
VMReturn ret;
FState *retval;
ret.PointerAt((void**)&retval);
GlobalVMStack.Call(func, params, 1, &ret, 1, nullptr);
VMCall(func, params, 1, &ret, 1);
return retval;
}
return nullptr;
@ -464,7 +460,7 @@ FState *AWeapon::GetAtkState (bool hold)
VMReturn ret;
FState *retval;
ret.PointerAt((void**)&retval);
GlobalVMStack.Call(func, params, 2, &ret, 1, nullptr);
VMCall(func, params, 2, &ret, 1);
return retval;
}
return nullptr;
@ -484,7 +480,7 @@ FState *AWeapon::GetAltAtkState (bool hold)
VMReturn ret;
FState *retval;
ret.PointerAt((void**)&retval);
GlobalVMStack.Call(func, params, 2, &ret, 1, nullptr);
VMCall(func, params, 2, &ret, 1);
return retval;
}
return nullptr;
@ -514,7 +510,7 @@ FState *AWeapon::GetStateForButtonName (FName button)
bool FWeaponSlot::AddWeapon(const char *type)
{
return AddWeapon(static_cast<PClassActor *>(PClass::FindClass(type)));
return AddWeapon(PClass::FindActor(type));
}
bool FWeaponSlot::AddWeapon(PClassActor *type)
@ -985,8 +981,9 @@ void FWeaponSlots::AddExtraWeapons()
continue;
}
auto weapdef = ((AWeapon*)GetDefaultByType(cls));
if ((cls->GameFilter == GAME_Any || (cls->GameFilter & gameinfo.gametype)) &&
cls->Replacement == nullptr && // Replaced weapons don't get slotted.
auto gf = cls->ActorInfo()->GameFilter;
if ((gf == GAME_Any || (gf & gameinfo.gametype)) &&
cls->ActorInfo()->Replacement == nullptr && // Replaced weapons don't get slotted.
!(weapdef->WeaponFlags & WIF_POWERED_UP) &&
!LocateWeapon(cls, nullptr, nullptr) // Don't duplicate it if it's already present.
)
@ -1268,7 +1265,7 @@ CCMD (setslot)
Net_WriteByte(argv.argc()-2);
for (int i = 2; i < argv.argc(); i++)
{
Net_WriteWeapon(dyn_cast<PClassActor>(PClass::FindClass(argv[i])));
Net_WriteWeapon(PClass::FindActor(argv[i]));
}
}
}
@ -1297,7 +1294,7 @@ CCMD (addslot)
return;
}
PClassActor *type= dyn_cast<PClassActor>(PClass::FindClass(argv[2]));
PClassActor *type= PClass::FindActor(argv[2]);
if (type == nullptr)
{
Printf("%s is not a weapon\n", argv[2]);
@ -1373,7 +1370,7 @@ CCMD (addslotdefault)
return;
}
type = dyn_cast<PClassActor>(PClass::FindClass(argv[2]));
type = PClass::FindActor(argv[2]);
if (type == nullptr)
{
Printf ("%s is not a weapon\n", argv[2]);
@ -1442,7 +1439,7 @@ void P_SetupWeapons_ntohton()
if (cls->IsDescendantOf(NAME_Weapon))
{
Weapons_ntoh.Push(static_cast<PClassActor *>(cls));
Weapons_ntoh.Push(cls);
}
}
qsort(&Weapons_ntoh[1], Weapons_ntoh.Size() - 1, sizeof(Weapons_ntoh[0]), ntoh_cmp);
@ -1470,8 +1467,8 @@ static int ntoh_cmp(const void *a, const void *b)
{
PClassActor *c1 = *(PClassActor **)a;
PClassActor *c2 = *(PClassActor **)b;
int g1 = c1->GameFilter == GAME_Any ? 1 : (c1->GameFilter & gameinfo.gametype) ? 0 : 2;
int g2 = c2->GameFilter == GAME_Any ? 1 : (c2->GameFilter & gameinfo.gametype) ? 0 : 2;
int g1 = c1->ActorInfo()->GameFilter == GAME_Any ? 1 : (c1->ActorInfo()->GameFilter & gameinfo.gametype) ? 0 : 2;
int g2 = c2->ActorInfo()->GameFilter == GAME_Any ? 1 : (c2->ActorInfo()->GameFilter & gameinfo.gametype) ? 0 : 2;
if (g1 != g2)
{
return g1 - g2;
@ -1522,7 +1519,7 @@ void P_ReadDemoWeaponsChunk(uint8_t **demo)
for (i = 1; i < count; ++i)
{
s = ReadStringConst(demo);
type = dyn_cast<PClassActor>(PClass::FindClass(s));
type = PClass::FindActor(s);
// If a demo was recorded with a weapon that is no longer present,
// should we report it?
Weapons_ntoh[i] = type;

View file

@ -84,7 +84,7 @@
#include "r_utility.h"
#include "p_spec.h"
#include "serializer.h"
#include "virtual.h"
#include "vm.h"
#include "events.h"
#include "gi.h"
@ -92,6 +92,7 @@
#include "g_hub.h"
#include "g_levellocals.h"
#include "actorinlines.h"
#include "vm.h"
#include <string.h>
@ -1318,8 +1319,7 @@ void G_FinishTravel ()
IFVIRTUALPTR(inv, AInventory, Travelled)
{
VMValue params[1] = { inv };
VMFrameStack stack;
GlobalVMStack.Call(func, params, 1, nullptr, 0, nullptr);
VMCall(func, params, 1, nullptr, 0);
}
}
if (ib_compatflags & BCOMPATF_RESETPLAYERSPEED)

View file

@ -11,6 +11,7 @@
#include "templates.h"
#include "serializer.h"
#include "r_data/r_translate.h"
#include "vm.h"
//----------------------------------------------------------------------------
//

View file

@ -60,7 +60,7 @@
#include "p_local.h"
#include "c_dispatch.h"
#include "g_level.h"
#include "scripting/thingdef.h"
#include "thingdef.h"
#include "i_system.h"
#include "templates.h"
#include "doomdata.h"
@ -74,6 +74,7 @@
#include "actorinlines.h"
#include "c_cvars.h"
#include "gl/system//gl_interface.h"
#include "vm.h"
EXTERN_CVAR(Int, vid_renderer)

View file

@ -1058,7 +1058,7 @@ void InitializeActorLights()
void *mem = ClassDataAllocator.Alloc(sizeof(FInternalLightAssociation));
FInternalLightAssociation * iasso = new(mem) FInternalLightAssociation(&LightAssociations[i]);
if (iasso->Light() != nullptr)
ti->LightAssociations.Push(iasso);
ti->ActorInfo()->LightAssociations.Push(iasso);
}
}
// we don't need the parser data for the light associations anymore
@ -1124,7 +1124,7 @@ void AActor::AttachLight(unsigned int count, const FLightDefaults *lightdef)
void AActor::SetDynamicLights()
{
TArray<FInternalLightAssociation *> & LightAssociations = GetClass()->LightAssociations;
TArray<FInternalLightAssociation *> & LightAssociations = GetInfo()->LightAssociations;
unsigned int count = 0;
if (state == NULL) return;

View file

@ -15,7 +15,8 @@
#include "d_player.h"
#include "r_data/sprites.h"
#include "g_levellocals.h"
#include "virtual.h"
#include "vm.h"
#include "vm.h"
static FRandom pr_morphmonst ("MorphMonster");
@ -612,8 +613,7 @@ void EndAllPowerupEffects(AInventory *item)
IFVIRTUALPTRNAME(item, NAME_Powerup, EndEffect)
{
VMValue params[1] = { item };
VMFrameStack stack;
GlobalVMStack.Call(func, params, 1, nullptr, 0, nullptr);
VMCall(func, params, 1, nullptr, 0);
}
}
item = item->Inventory;
@ -638,8 +638,7 @@ void InitAllPowerupEffects(AInventory *item)
IFVIRTUALPTRNAME(item, NAME_Powerup, InitEffect)
{
VMValue params[1] = { item };
VMFrameStack stack;
GlobalVMStack.Call(func, params, 1, nullptr, 0, nullptr);
VMCall(func, params, 1, nullptr, 0);
}
}
item = item->Inventory;
@ -714,14 +713,14 @@ DEFINE_ACTION_FUNCTION(AActor, A_Morph)
bool res = false;
if (self->player)
{
if (type->IsKindOf(RUNTIME_CLASS(APlayerPawn)))
if (type->IsDescendantOf(RUNTIME_CLASS(APlayerPawn)))
{
res = P_MorphPlayer(self->player, self->player, type, duration, flags, enter_flash, exit_flash);
}
}
else
{
if (type->IsKindOf(RUNTIME_CLASS(AMorphedMonster)))
if (type->IsDescendantOf(RUNTIME_CLASS(AMorphedMonster)))
{
res = P_MorphMonster(self, type, duration, flags, enter_flash, exit_flash);
}

View file

@ -40,6 +40,7 @@
#include "doomstat.h"
#include "serializer.h"
#include "a_pickups.h"
#include "vm.h"
static FRandom pr_spot ("SpecialSpot");
static FRandom pr_spawnmace ("SpawnMace");

View file

@ -54,7 +54,7 @@
#include "r_utility.h"
#include "cmdlib.h"
#include "g_levellocals.h"
#include "virtual.h"
#include "vm.h"
#include <time.h>
@ -385,21 +385,20 @@ static void SetKeyTypes()
{
for(unsigned int i = 0; i < PClassActor::AllActorClasses.Size(); i++)
{
PClass *ti = PClassActor::AllActorClasses[i];
PClassActor *ti = PClassActor::AllActorClasses[i];
auto kt = PClass::FindActor(NAME_Key);
if (ti->IsDescendantOf(kt))
{
PClassActor *tia = static_cast<PClassActor *>(ti);
AInventory *key = (AInventory*)(GetDefaultByType(tia));
AInventory *key = (AInventory*)(GetDefaultByType(ti));
if (key->Icon.isValid() && key->special1 > 0)
{
KeyTypes.Push(tia);
KeyTypes.Push(ti);
}
else
{
UnassignedKeyTypes.Push(tia);
UnassignedKeyTypes.Push(ti);
}
}
}
@ -1094,7 +1093,7 @@ static void DrawPowerups(player_t *CPlayer)
VMValue param[] = { item };
int rv;
VMReturn ret(&rv);
GlobalVMStack.Call(func, param, 1, &ret, 1);
VMCall(func, param, 1, &ret, 1);
auto tex = FSetTextureID(rv);
if (!tex.isValid()) continue;
auto texture = TexMan(tex);

View file

@ -44,6 +44,7 @@
#include "m_fixed.h"
#include "gstrings.h"
#include "g_levellocals.h"
#include "vm.h"
TArray<FSkillInfo> AllSkills;
int DefaultSkill = -1;
@ -476,7 +477,7 @@ const char * G_SkillName()
const char *name = AllSkills[gameskill].MenuName;
player_t *player = &players[consoleplayer];
const char *playerclass = player->mo->GetClass()->DisplayName;
const char *playerclass = player->mo->GetInfo()->DisplayName;
if (playerclass != NULL)
{

View file

@ -57,7 +57,7 @@
#include "gstrings.h"
#include "cmdlib.h"
#include "g_levellocals.h"
#include "virtual.h"
#include "vm.h"
#define ARTIFLASH_OFFSET (statusBar->invBarOffset+6)
enum

View file

@ -1441,7 +1441,7 @@ class CommandDrawNumber : public CommandDrawString
VMValue params[] = { statusBar->CPlayer->mo, inventoryItem };
int retv;
VMReturn ret(&retv);
GlobalVMStack.Call(func, params, 2, &ret, 1);
VMCall(func, params, 2, &ret, 1);
num = retv < 0? 0 : retv / TICRATE + 1;
break;
}
@ -2738,7 +2738,7 @@ class CommandDrawBar : public SBarInfoCommand
int ival;
ret[0].IntAt(&ival);
ret[1].IntAt(&max);
GlobalVMStack.Call(func, params, 2, ret, 2);
VMCall(func, params, 2, ret, 2);
value = ival + 1;
max++;
break;
@ -2925,7 +2925,7 @@ class CommandPlayerClass : public SBarInfoCommandFlowControl
bool foundClass = false;
for(unsigned int c = 0;c < PlayerClasses.Size();c++)
{
if(stricmp(sc.String, PlayerClasses[c].Type->DisplayName) == 0)
if(stricmp(sc.String, PlayerClasses[c].Type->GetDisplayName()) == 0)
{
foundClass = true;
classes.Push(PlayerClasses[c].Type);

View file

@ -57,7 +57,7 @@
#include "r_utility.h"
#include "cmdlib.h"
#include "g_levellocals.h"
#include "virtual.h"
#include "vm.h"
#include "p_acs.h"
#include "r_data/r_translate.h"
#include "sbarinfo.h"
@ -329,7 +329,7 @@ void ST_CreateStatusBar(bool bTitleLevel)
IFVIRTUALPTR(StatusBar, DBaseStatusBar, Init)
{
VMValue params[] = { StatusBar };
GlobalVMStack.Call(func, params, 1, nullptr, 0);
VMCall(func, params, 1, nullptr, 0);
}
GC::WriteBarrier(StatusBar);
@ -560,7 +560,7 @@ void DBaseStatusBar::AttachToPlayer(player_t *player)
IFVIRTUAL(DBaseStatusBar, AttachToPlayer)
{
VMValue params[] = { (DObject*)this, player };
GlobalVMStack.Call(func, params, countof(params), nullptr, 0);
VMCall(func, params, countof(params), nullptr, 0);
}
}
@ -641,7 +641,7 @@ void DBaseStatusBar::CallTick()
IFVIRTUAL(DBaseStatusBar, Tick)
{
VMValue params[] = { (DObject*)this };
GlobalVMStack.Call(func, params, countof(params), nullptr, 0);
VMCall(func, params, countof(params), nullptr, 0);
}
else Tick();
mugshot.Tick(CPlayer);
@ -973,7 +973,7 @@ void DBaseStatusBar::Draw (EHudState state)
IFVIRTUAL(DBaseStatusBar, DrawMyPos)
{
VMValue params[] = { (DObject*)this };
GlobalVMStack.Call(func, params, countof(params), nullptr, 0);
VMCall(func, params, countof(params), nullptr, 0);
}
V_SetBorderNeedRefresh();
}
@ -990,7 +990,7 @@ void DBaseStatusBar::Draw (EHudState state)
IFVIRTUAL(DBaseStatusBar, DrawAutomapHUD)
{
VMValue params[] = { (DObject*)this, r_viewpoint.TicFrac };
GlobalVMStack.Call(func, params, countof(params), nullptr, 0);
VMCall(func, params, countof(params), nullptr, 0);
}
}
}
@ -1008,7 +1008,7 @@ void DBaseStatusBar::CallDraw(EHudState state)
IFVIRTUAL(DBaseStatusBar, Draw)
{
VMValue params[] = { (DObject*)this, state, r_viewpoint.TicFrac };
GlobalVMStack.Call(func, params, countof(params), nullptr, 0);
VMCall(func, params, countof(params), nullptr, 0);
}
else Draw(state);
screen->ClearClipRect(); // make sure the scripts don't leave a valid clipping rect behind.
@ -1073,7 +1073,7 @@ bool DBaseStatusBar::MustDrawLog(EHudState state)
VMValue params[] = { (DObject*)this };
int rv;
VMReturn ret(&rv);
GlobalVMStack.Call(func, params, countof(params), &ret, 1);
VMCall(func, params, countof(params), &ret, 1);
return !!rv;
}
return true;
@ -1095,7 +1095,7 @@ void DBaseStatusBar::SetMugShotState(const char *stateName, bool waitTillDone, b
{
FString statestring = stateName;
VMValue params[] = { (DObject*)this, &statestring, waitTillDone, reset };
GlobalVMStack.Call(func, params, countof(params), nullptr, 0);
VMCall(func, params, countof(params), nullptr, 0);
}
}
@ -1133,7 +1133,7 @@ void DBaseStatusBar::DrawTopStuff (EHudState state)
IFVIRTUAL(DBaseStatusBar, DrawPowerups)
{
VMValue params[] = { (DObject*)this };
GlobalVMStack.Call(func, params, 1, nullptr, 0);
VMCall(func, params, 1, nullptr, 0);
}
fullscreenOffsets = saved;
}
@ -1261,7 +1261,7 @@ void DBaseStatusBar::FlashItem (const PClass *itemtype)
IFVIRTUAL(DBaseStatusBar, FlashItem)
{
VMValue params[] = { (DObject*)this, (PClass*)itemtype };
GlobalVMStack.Call(func, params, countof(params), nullptr, 0);
VMCall(func, params, countof(params), nullptr, 0);
}
}
@ -1270,7 +1270,7 @@ void DBaseStatusBar::NewGame ()
IFVIRTUAL(DBaseStatusBar, NewGame)
{
VMValue params[] = { (DObject*)this };
GlobalVMStack.Call(func, params, countof(params), nullptr, 0);
VMCall(func, params, countof(params), nullptr, 0);
}
mugshot.Reset();
}
@ -1280,7 +1280,7 @@ void DBaseStatusBar::ShowPop(int pop)
IFVIRTUAL(DBaseStatusBar, ShowPop)
{
VMValue params[] = { (DObject*)this, pop };
GlobalVMStack.Call(func, params, countof(params), nullptr, 0);
VMCall(func, params, countof(params), nullptr, 0);
}
}
@ -1319,7 +1319,7 @@ void DBaseStatusBar::CallScreenSizeChanged()
IFVIRTUAL(DBaseStatusBar, ScreenSizeChanged)
{
VMValue params[] = { (DObject*)this };
GlobalVMStack.Call(func, params, countof(params), nullptr, 0);
VMCall(func, params, countof(params), nullptr, 0);
}
else ScreenSizeChanged();
}

View file

@ -42,6 +42,7 @@
#include "i_system.h"
#include "v_video.h"
#include "g_level.h"
#include "vm.h"
gameinfo_t gameinfo;

View file

@ -360,7 +360,7 @@ void GLSceneDrawer::RenderThings(subsector_t * sub, sector_t * sector)
if (thing->validcount == validcount) continue;
thing->validcount = validcount;
FIntCVar *cvar = thing->GetClass()->distancecheck;
FIntCVar *cvar = thing->GetInfo()->distancecheck;
if (cvar != NULL && *cvar >= 0)
{
double dist = (thing->Pos() - r_viewpoint.Pos).LengthSquared();
@ -378,7 +378,7 @@ void GLSceneDrawer::RenderThings(subsector_t * sub, sector_t * sector)
for (msecnode_t *node = sec->sectorportal_thinglist; node; node = node->m_snext)
{
AActor *thing = node->m_thing;
FIntCVar *cvar = thing->GetClass()->distancecheck;
FIntCVar *cvar = thing->GetInfo()->distancecheck;
if (cvar != NULL && *cvar >= 0)
{
double dist = (thing->Pos() - r_viewpoint.Pos).LengthSquared();

View file

@ -33,6 +33,7 @@
#include "c_dispatch.h"
#include "r_state.h"
#include "actor.h"
#include "cmdlib.h"
#ifdef _WIN32
#include "win32gliface.h"
#endif
@ -841,10 +842,11 @@ void gl_PrecacheTexture(uint8_t *texhitlist, TMap<PClassActor*, bool> &actorhitl
PClassActor *cls = pair->Key;
int gltrans = GLTranslationPalette::GetInternalTranslation(GetDefaultByType(cls)->Translation);
for (int i = 0; i < cls->NumOwnedStates; i++)
for (int i = 0; i < cls->GetStateCount(); i++)
{
spritelist[cls->OwnedStates[i].sprite].Insert(gltrans, true);
FSpriteModelFrame * smf = gl_FindModelFrame(cls, cls->OwnedStates[i].sprite, cls->OwnedStates[i].Frame, false);
auto &state = cls->GetStates()[i];
spritelist[state.sprite].Insert(gltrans, true);
FSpriteModelFrame * smf = gl_FindModelFrame(cls, state.sprite, state.Frame, false);
if (smf != NULL)
{
for (int i = 0; i < MAX_MODELS_PER_FRAME; i++)

View file

@ -55,6 +55,8 @@
#include "d_player.h"
#include "doomerrors.h"
#include "events.h"
#include "types.h"
#include "vm.h"
extern void LoadActors ();
extern void InitBotStuff();
@ -65,6 +67,62 @@ FRandom FState::pr_statetics("StateTics");
cycle_t ActionCycles;
//==========================================================================
//
// special type for the native ActorInfo. This allows to let this struct
// be handled by the generic object constructors for the VM.
//
//==========================================================================
class PActorInfo : public PBasicType
{
DECLARE_CLASS(PActorInfo, PBasicType);
public:
PActorInfo()
:PBasicType(sizeof(FActorInfo), alignof(FActorInfo))
{
}
void SetDefaultValue(void *base, unsigned offset, TArray<FTypeAndOffset> *special) override
{
if (base != nullptr) new((uint8_t *)base + offset) FActorInfo;
if (special != nullptr)
{
special->Push(std::make_pair(this, offset));
}
}
void InitializeValue(void *addr, const void *def) const override
{
if (def == nullptr)
{
new(addr) FActorInfo;
}
else
{
new(addr) FActorInfo(*(const FActorInfo*)def);
}
}
void DestroyValue(void *addr) const override
{
FActorInfo *self = (FActorInfo*)addr;
self->~FActorInfo();
}
};
IMPLEMENT_CLASS(PActorInfo, false, false)
void AddActorInfo(PClass *cls)
{
auto type = new PActorInfo;
TypeTable.AddType(type);
cls->AddField("*", type, VARF_Meta);
}
void FState::SetAction(const char *name)
{
ActionFunc = FindVMFunction(RUNTIME_CLASS(AActor), name);
@ -72,49 +130,47 @@ void FState::SetAction(const char *name)
bool FState::CallAction(AActor *self, AActor *stateowner, FStateParamInfo *info, FState **stateret)
{
if (ActionFunc != NULL)
if (ActionFunc != nullptr)
{
ActionCycles.Clock();
VMValue params[3] = { self, stateowner, VMValue(info) };
// If the function returns a state, store it at *stateret.
// If it doesn't return a state but stateret is non-NULL, we need
// to set *stateret to NULL.
if (stateret != NULL)
// If it doesn't return a state but stateret is non-nullptr, we need
// to set *stateret to nullptr.
if (stateret != nullptr)
{
*stateret = NULL;
if (ActionFunc->Proto == NULL ||
*stateret = nullptr;
if (ActionFunc->Proto == nullptr ||
ActionFunc->Proto->ReturnTypes.Size() == 0 ||
ActionFunc->Proto->ReturnTypes[0] != TypeState)
{
stateret = NULL;
stateret = nullptr;
}
}
try
{
if (stateret == NULL)
if (stateret == nullptr)
{
GlobalVMStack.Call(ActionFunc, params, ActionFunc->ImplicitArgs, NULL, 0, NULL);
VMCall(ActionFunc, params, ActionFunc->ImplicitArgs, nullptr, 0);
}
else
{
VMReturn ret;
ret.PointerAt((void **)stateret);
GlobalVMStack.Call(ActionFunc, params, ActionFunc->ImplicitArgs, &ret, 1, NULL);
VMCall(ActionFunc, params, ActionFunc->ImplicitArgs, &ret, 1);
}
}
catch (CVMAbortException &err)
{
err.MaybePrintMessage();
auto owner = FState::StaticFindStateOwner(this);
int offs = int(this - owner->OwnedStates);
const char *callinfo = "";
if (info != nullptr && info->mStateType == STATE_Psprite)
{
if (stateowner->IsKindOf(NAME_Weapon) && stateowner != self) callinfo = "weapon ";
else callinfo = "overlay ";
}
err.stacktrace.AppendFormat("Called from %sstate %s.%d in %s\n", callinfo, owner->TypeName.GetChars(), offs, stateowner->GetClass()->TypeName.GetChars());
err.stacktrace.AppendFormat("Called from %sstate %s in %s\n", callinfo, FState::StaticGetStateName(this), stateowner->GetClass()->TypeName.GetChars());
throw;
throw;
}
@ -177,8 +233,6 @@ DEFINE_ACTION_FUNCTION(AActor, GetSpriteIndex)
ACTION_RETURN_INT(GetSpriteIndex(sprt.GetChars(), false));
}
IMPLEMENT_CLASS(PClassActor, false, false)
//==========================================================================
//
// PClassActor :: StaticInit STATIC
@ -228,95 +282,10 @@ void PClassActor::StaticSetActorNums()
{
for (unsigned int i = 0; i < PClassActor::AllActorClasses.Size(); ++i)
{
static_cast<PClassActor *>(PClassActor::AllActorClasses[i])->RegisterIDs();
PClassActor::AllActorClasses[i]->RegisterIDs();
}
}
//==========================================================================
//
// PClassActor Constructor
//
//==========================================================================
PClassActor::PClassActor()
{
GameFilter = GAME_Any;
SpawnID = 0;
DoomEdNum = -1;
OwnedStates = NULL;
NumOwnedStates = 0;
Replacement = NULL;
Replacee = NULL;
StateList = NULL;
DamageFactors = NULL;
PainChances = NULL;
DropItems = NULL;
// Record this in the master list.
AllActorClasses.Push(this);
}
//==========================================================================
//
// PClassActor Destructor
//
//==========================================================================
PClassActor::~PClassActor()
{
if (OwnedStates != NULL)
{
delete[] OwnedStates;
}
if (DamageFactors != NULL)
{
delete DamageFactors;
}
if (PainChances != NULL)
{
delete PainChances;
}
if (StateList != NULL)
{
StateList->Destroy();
M_Free(StateList);
}
}
//==========================================================================
//
// PClassActor :: Derive
//
//==========================================================================
void PClassActor::DeriveData(PClass *newclass)
{
assert(newclass->IsKindOf(RUNTIME_CLASS(PClassActor)));
PClassActor *newa = static_cast<PClassActor *>(newclass);
newa->DefaultStateUsage = DefaultStateUsage;
newa->distancecheck = distancecheck;
newa->DropItems = DropItems;
newa->VisibleToPlayerClass = VisibleToPlayerClass;
if (DamageFactors != NULL)
{
// copy damage factors from parent
newa->DamageFactors = new DmgFactors;
*newa->DamageFactors = *DamageFactors;
}
if (PainChances != NULL)
{
// copy pain chances from parent
newa->PainChances = new PainChanceList;
*newa->PainChances = *PainChances;
}
newa->DisplayName = DisplayName;
}
//==========================================================================
//
// PClassActor :: SetReplacement
@ -339,27 +308,13 @@ bool PClassActor::SetReplacement(FName replaceName)
}
if (replacee != nullptr)
{
replacee->Replacement = this;
Replacee = replacee;
replacee->ActorInfo()->Replacement = this;
ActorInfo()->Replacee = replacee;
}
}
return true;
}
//==========================================================================
//
// PClassActor :: SetDropItems
//
// Sets a new drop item list
//
//==========================================================================
void PClassActor::SetDropItems(FDropItem *drops)
{
DropItems = drops;
}
//==========================================================================
//
// PClassActor :: Finalize
@ -378,11 +333,11 @@ void AActor::Finalize(FStateDefinitions &statedef)
}
catch (CRecoverableError &)
{
statedef.MakeStateDefines(NULL);
statedef.MakeStateDefines(nullptr);
throw;
}
statedef.InstallStates(GetClass(), defaults);
statedef.MakeStateDefines(NULL);
statedef.MakeStateDefines(nullptr);
}
//==========================================================================
@ -397,23 +352,25 @@ void PClassActor::RegisterIDs()
{
PClassActor *cls = PClass::FindActor(TypeName);
if (cls == NULL)
if (cls == nullptr)
{
Printf(TEXTCOLOR_RED"The actor '%s' has been hidden by a non-actor of the same name\n", TypeName.GetChars());
return;
}
// Conversation IDs have never been filtered by game so we cannot start doing that.
auto ConversationID = ActorInfo()->ConversationID;
if (ConversationID > 0)
{
StrifeTypes[ConversationID] = cls;
if (cls != this)
{
Printf(TEXTCOLOR_RED"Conversation ID %d refers to hidden class type '%s'\n", SpawnID, cls->TypeName.GetChars());
Printf(TEXTCOLOR_RED"Conversation ID %d refers to hidden class type '%s'\n", ConversationID, cls->TypeName.GetChars());
}
}
if (GameFilter == GAME_Any || (GameFilter & gameinfo.gametype))
if (ActorInfo()->GameFilter == GAME_Any || (ActorInfo()->GameFilter & gameinfo.gametype))
{
auto SpawnID = ActorInfo()->SpawnID;
if (SpawnID > 0)
{
SpawnableThings[SpawnID] = cls;
@ -422,10 +379,11 @@ void PClassActor::RegisterIDs()
Printf(TEXTCOLOR_RED"Spawn ID %d refers to hidden class type '%s'\n", SpawnID, cls->TypeName.GetChars());
}
}
auto DoomEdNum = ActorInfo()->DoomEdNum;
if (DoomEdNum != -1)
{
FDoomEdEntry *oldent = DoomEdMap.CheckKey(DoomEdNum);
if (oldent != NULL && oldent->Special == -2)
if (oldent != nullptr && oldent->Special == -2)
{
Printf(TEXTCOLOR_RED"Editor number %d defined twice for classes '%s' and '%s'\n", DoomEdNum, cls->TypeName.GetChars(), oldent->Type->TypeName.GetChars());
}
@ -455,7 +413,7 @@ PClassActor *PClassActor::GetReplacement(bool lookskill)
if (lookskill && AllSkills.Size() > (unsigned)gameskill)
{
skillrepname = AllSkills[gameskill].GetReplacement(TypeName);
if (skillrepname != NAME_None && PClass::FindClass(skillrepname) == NULL)
if (skillrepname != NAME_None && PClass::FindClass(skillrepname) == nullptr)
{
Printf("Warning: incorrect actor name in definition of skill %s: \n"
"class %s is replaced by non-existent class %s\n"
@ -467,15 +425,15 @@ PClassActor *PClassActor::GetReplacement(bool lookskill)
lookskill = false; skillrepname = NAME_None;
}
}
if (Replacement == NULL && (!lookskill || skillrepname == NAME_None))
auto Replacement = ActorInfo()->Replacement;
if (Replacement == nullptr && (!lookskill || skillrepname == NAME_None))
{
return this;
}
// The Replacement field is temporarily NULLed to prevent
// potential infinite recursion.
PClassActor *savedrep = Replacement;
Replacement = NULL;
PClassActor *rep = savedrep;
ActorInfo()->Replacement = nullptr;
PClassActor *rep = Replacement;
// Handle skill-based replacement here. It has precedence on DECORATE replacement
// in that the skill replacement is applied first, followed by DECORATE replacement
// on the actor indicated by the skill replacement.
@ -487,7 +445,7 @@ PClassActor *PClassActor::GetReplacement(bool lookskill)
// Skill replacements are not recursive, contrarily to DECORATE replacements
rep = rep->GetReplacement(false);
// Reset the temporarily NULLed field
Replacement = savedrep;
ActorInfo()->Replacement = Replacement;
return rep;
}
@ -511,7 +469,7 @@ PClassActor *PClassActor::GetReplacee(bool lookskill)
if (lookskill && AllSkills.Size() > (unsigned)gameskill)
{
skillrepname = AllSkills[gameskill].GetReplacedBy(TypeName);
if (skillrepname != NAME_None && PClass::FindClass(skillrepname) == NULL)
if (skillrepname != NAME_None && PClass::FindClass(skillrepname) == nullptr)
{
Printf("Warning: incorrect actor name in definition of skill %s: \n"
"non-existent class %s is replaced by class %s\n"
@ -523,21 +481,21 @@ PClassActor *PClassActor::GetReplacee(bool lookskill)
lookskill = false;
}
}
if (Replacee == NULL && (!lookskill || skillrepname == NAME_None))
PClassActor *savedrep = ActorInfo()->Replacee;
if (savedrep == nullptr && (!lookskill || skillrepname == NAME_None))
{
return this;
}
// The Replacee field is temporarily NULLed to prevent
// potential infinite recursion.
PClassActor *savedrep = Replacee;
Replacee = NULL;
ActorInfo()->Replacee = nullptr;
PClassActor *rep = savedrep;
if (lookskill && (skillrepname != NAME_None) && (PClass::FindClass(skillrepname) != NULL))
if (lookskill && (skillrepname != NAME_None) && (PClass::FindClass(skillrepname) != nullptr))
{
rep = PClass::FindActor(skillrepname);
}
rep = rep->GetReplacee(false);
Replacee = savedrep;
ActorInfo()->Replacee = savedrep;
return rep;
}
@ -556,11 +514,12 @@ DEFINE_ACTION_FUNCTION(AActor, GetReplacee)
void PClassActor::SetDamageFactor(FName type, double factor)
{
if (DamageFactors == NULL)
for (auto & p : ActorInfo()->DamageFactors)
{
DamageFactors = new DmgFactors;
if (p.first == type) p.second = factor;
return;
}
DamageFactors->Insert(type, factor);
ActorInfo()->DamageFactors.Push({ type, factor });
}
//==========================================================================
@ -571,17 +530,15 @@ void PClassActor::SetDamageFactor(FName type, double factor)
void PClassActor::SetPainChance(FName type, int chance)
{
for (auto & p : ActorInfo()->PainChances)
{
if (p.first == type) p.second = chance;
return;
}
if (chance >= 0)
{
if (PainChances == NULL)
{
PainChances = new PainChanceList;
}
PainChances->Insert(type, MIN(chance, 256));
}
else if (PainChances != NULL)
{
PainChances->Remove(type);
ActorInfo()->PainChances.Push({ type, MIN(chance, 256) });
}
}
@ -596,13 +553,22 @@ void PClassActor::SetPainChance(FName type, int chance)
int DmgFactors::Apply(FName type, int damage)
{
auto pdf = CheckKey(type);
if (pdf == NULL && type != NAME_None)
double factor = -1.;
for (auto & p : *this)
{
pdf = CheckKey(NAME_None);
if (p.first == type)
{
factor = p.second;
break;
}
if (p.first == NAME_None)
{
factor = p.second;
}
}
if (!pdf) return damage;
return int(damage * *pdf);
if (factor < 0.) return damage;
return int(damage * factor);
}
@ -614,7 +580,7 @@ static void SummonActor (int command, int command2, FCommandLine argv)
if (argv.argc() > 1)
{
PClassActor *type = PClass::FindActor(argv[1]);
if (type == NULL)
if (type == nullptr)
{
Printf ("Unknown actor '%s'\n", argv[1]);
return;
@ -709,13 +675,15 @@ FString DamageTypeDefinition::GetObituary(FName type)
double DamageTypeDefinition::GetMobjDamageFactor(FName type, DmgFactors const * const factors)
{
double defaultfac = -1.;
if (factors)
{
// If the actor has named damage factors, look for a specific factor
auto pdf = factors->CheckKey(type);
if (pdf) return *pdf; // type specific damage type
for (auto & p : *factors)
{
if (p.first == type) return p.second; // type specific damage type
if (p.first == NAME_None) defaultfac = p.second;
}
// If this was nonspecific damage, don't fall back to nonspecific search
if (type == NAME_None) return 1.;
}
@ -733,18 +701,17 @@ double DamageTypeDefinition::GetMobjDamageFactor(FName type, DmgFactors const *
}
{
auto pdf = factors->CheckKey(NAME_None);
DamageTypeDefinition *dtd = Get(type);
// Here we are looking for modifications to untyped damage
// If the calling actor defines untyped damage factor, that is contained in "pdf".
if (pdf) // normal damage available
if (defaultfac >= 0.) // normal damage available
{
if (dtd)
{
if (dtd->ReplaceFactor) return dtd->DefaultFactor; // use default instead of untyped factor
return *pdf * dtd->DefaultFactor; // use default as modification of untyped factor
return defaultfac * dtd->DefaultFactor; // use default as modification of untyped factor
}
return *pdf; // there was no default, so actor default is used
return defaultfac; // there was no default, so actor default is used
}
else if (dtd)
{

View file

@ -177,6 +177,7 @@ public:
bool CallAction(AActor *self, AActor *stateowner, FStateParamInfo *stateinfo, FState **stateret);
static PClassActor *StaticFindStateOwner (const FState *state);
static PClassActor *StaticFindStateOwner (const FState *state, PClassActor *info);
static FString StaticGetStateName(const FState *state);
static FRandom pr_statetics;
};
@ -200,11 +201,11 @@ struct FStateLabels
#include "gametype.h"
struct DmgFactors : public TMap<FName, double>
struct DmgFactors : public TArray<std::pair<FName, double>>
{
int Apply(FName type, int damage);
};
typedef TMap<FName, int> PainChanceList;
typedef TArray<std::pair<FName, int>> PainChanceList;
struct DamageTypeDefinition
{
@ -236,17 +237,64 @@ private:
struct FDropItem;
struct FActorInfo
{
TArray<FInternalLightAssociation *> LightAssociations;
PClassActor *Replacement = nullptr;
PClassActor *Replacee = nullptr;
FState *OwnedStates = nullptr;
int NumOwnedStates = 0;
uint8_t GameFilter = GAME_Any;
uint16_t SpawnID = 0;
uint16_t ConversationID = 0;
int16_t DoomEdNum = -1;
FStateLabels *StateList = nullptr;
DmgFactors DamageFactors;
PainChanceList PainChances;
TArray<PClassActor *> VisibleToPlayerClass;
FDropItem *DropItems;
FIntCVar *distancecheck;
// This is from PClassPlayerPawn
FString DisplayName;
uint8_t DefaultStateUsage = 0; // state flag defaults for blocks without a qualifier.
FActorInfo() {}
FActorInfo(const FActorInfo & other)
{
// only copy the fields that get inherited
DefaultStateUsage = other.DefaultStateUsage;
DamageFactors = other.DamageFactors;
PainChances = other.PainChances;
VisibleToPlayerClass = other.VisibleToPlayerClass;
DropItems = other.DropItems;
distancecheck = other.distancecheck;
DisplayName = other.DisplayName;
}
~FActorInfo()
{
if (StateList != NULL)
{
StateList->Destroy();
M_Free(StateList);
}
}
};
// This is now merely a wrapper that adds actor-specific functionality to PClass.
// No objects of this type will be created ever - its only use is to static_casr
// PClass to it.
class PClassActor : public PClass
{
DECLARE_CLASS(PClassActor, PClass);
protected:
public:
static void StaticInit ();
static void StaticSetActorNums ();
virtual void DeriveData(PClass *newclass);
PClassActor();
~PClassActor();
void BuildDefaults();
void ApplyDefaults(uint8_t *defaults);
@ -254,7 +302,36 @@ public:
void SetDamageFactor(FName type, double factor);
void SetPainChance(FName type, int chance);
bool SetReplacement(FName replaceName);
void SetDropItems(FDropItem *drops);
FActorInfo *ActorInfo() const
{
return (FActorInfo*)Meta;
}
void SetDropItems(FDropItem *drops)
{
ActorInfo()->DropItems = drops;
}
const FString &GetDisplayName() const
{
return ActorInfo()->DisplayName;
}
FState *GetStates() const
{
return ActorInfo()->OwnedStates;
}
unsigned GetStateCount() const
{
return ActorInfo()->NumOwnedStates;
}
FStateLabels *GetStateLabels() const
{
return ActorInfo()->StateList;
}
FState *FindState(int numnames, FName *names, bool exact=false) const;
FState *FindStateByString(const char *name, bool exact=false);
@ -265,44 +342,17 @@ public:
bool OwnsState(const FState *state)
{
return state >= OwnedStates && state < OwnedStates + NumOwnedStates;
auto i = ActorInfo();
return state >= i->OwnedStates && state < i->OwnedStates + i->NumOwnedStates;
}
PClassActor *GetReplacement(bool lookskill=true);
PClassActor *GetReplacee(bool lookskill=true);
TArray<FInternalLightAssociation *> LightAssociations;
FState *OwnedStates;
PClassActor *Replacement;
PClassActor *Replacee;
int NumOwnedStates;
uint8_t GameFilter;
uint8_t DefaultStateUsage; // state flag defaults for blocks without a qualifier.
uint16_t SpawnID;
uint16_t ConversationID;
int16_t DoomEdNum;
FStateLabels *StateList;
DmgFactors *DamageFactors;
PainChanceList *PainChances;
TArray<PClassActor *> VisibleToPlayerClass;
FDropItem *DropItems;
FString SourceLumpName;
FIntCVar *distancecheck;
// This is from PClassPlayerPawn
FString DisplayName;
// For those times when being able to scan every kind of actor is convenient
static TArray<PClassActor *> AllActorClasses;
};
inline PClassActor *PClass::FindActor(FName name)
{
return dyn_cast<PClassActor>(FindClass(name));
}
struct FDoomEdEntry
{
PClassActor *Type;

View file

@ -48,7 +48,7 @@
#include "r_utility.h"
#include "a_morph.h"
#include "g_levellocals.h"
#include "virtual.h"
#include "vm.h"
#include "events.h"
#include "p_acs.h"
@ -479,7 +479,7 @@ void cht_DoCheat (player_t *player, int cheat)
VMReturn ret;
int oldpieces = 1;
ret.IntAt(&oldpieces);
GlobalVMStack.Call(gsp, params, 1, &ret, 1, nullptr);
VMCall(gsp, params, 1, &ret, 1);
item = player->mo->FindInventory(NAME_Sigil);
if (item != NULL)
@ -604,7 +604,7 @@ void cht_Give (player_t *player, const char *name, int amount)
{
FString namestr = name;
VMValue params[3] = { player->mo, &namestr, amount };
GlobalVMStack.Call(func, params, 3, nullptr, 0);
VMCall(func, params, 3, nullptr, 0);
}
}
@ -616,7 +616,7 @@ void cht_Take (player_t *player, const char *name, int amount)
{
FString namestr = name;
VMValue params[3] = { player->mo, &namestr, amount };
GlobalVMStack.Call(func, params, 3, nullptr, 0);
VMCall(func, params, 3, nullptr, 0);
}
}

View file

@ -50,6 +50,7 @@
#include "d_gui.h"
#include "i_music.h"
#include "m_joy.h"
#include "vm.h"
static TArray<IJoystickConfig *> Joysticks;

View file

@ -48,6 +48,7 @@
#include "d_gui.h"
#include "serializer.h"
#include "resourcefiles/resourcefile.h"
#include "vm.h"
// Save name length limit for old binary formats.
#define OLDSAVESTRINGSIZE 24

View file

@ -55,7 +55,7 @@
#include "r_utility.h"
#include "menu/menu.h"
#include "textures/textures.h"
#include "virtual.h"
#include "vm.h"
#include "events.h"
#include "gl/renderer/gl_renderer.h" // for menu blur
@ -183,7 +183,7 @@ bool DMenu::CallResponder(event_t *ev)
VMValue params[] = { (DObject*)this, &e };
int retval;
VMReturn ret(&retval);
GlobalVMStack.Call(func, params, 2, &ret, 1, nullptr);
VMCall(func, params, 2, &ret, 1);
return !!retval;
}
}
@ -195,7 +195,7 @@ bool DMenu::CallResponder(event_t *ev)
VMValue params[] = { (DObject*)this, &e };
int retval;
VMReturn ret(&retval);
GlobalVMStack.Call(func, params, 2, &ret, 1, nullptr);
VMCall(func, params, 2, &ret, 1);
return !!retval;
}
}
@ -215,7 +215,7 @@ bool DMenu::CallMenuEvent(int mkey, bool fromcontroller)
VMValue params[] = { (DObject*)this, mkey, fromcontroller };
int retval;
VMReturn ret(&retval);
GlobalVMStack.Call(func, params, 3, &ret, 1, nullptr);
VMCall(func, params, 3, &ret, 1);
return !!retval;
}
else return false;
@ -247,7 +247,7 @@ void DMenu::Close ()
IFVIRTUALPTR(CurrentMenu, DMenu, OnReturn)
{
VMValue params[] = { CurrentMenu };
GlobalVMStack.Call(func, params, 1, nullptr, 0, nullptr);
VMCall(func, params, 1, nullptr, 0);
}
}
@ -275,7 +275,7 @@ void DMenu::CallTicker()
IFVIRTUAL(DMenu, Ticker)
{
VMValue params[] = { (DObject*)this };
GlobalVMStack.Call(func, params, 1, nullptr, 0, nullptr);
VMCall(func, params, 1, nullptr, 0);
}
}
@ -285,7 +285,7 @@ void DMenu::CallDrawer()
IFVIRTUAL(DMenu, Drawer)
{
VMValue params[] = { (DObject*)this };
GlobalVMStack.Call(func, params, 1, nullptr, 0, nullptr);
VMCall(func, params, 1, nullptr, 0);
screen->ClearClipRect(); // make sure the scripts don't leave a valid clipping rect behind.
}
}
@ -297,7 +297,7 @@ bool DMenu::TranslateKeyboardEvents()
VMValue params[] = { (DObject*)this };
int retval;
VMReturn ret(&retval);
GlobalVMStack.Call(func, params, countof(params), &ret, 1, nullptr);
VMCall(func, params, countof(params), &ret, 1);
return !!retval;
}
return true;
@ -473,7 +473,7 @@ void M_SetMenu(FName menu, int param)
IFVIRTUALPTRNAME(newmenu, "ListMenu", Init)
{
VMValue params[3] = { newmenu, CurrentMenu, ld };
GlobalVMStack.Call(func, params, 3, nullptr, 0);
VMCall(func, params, 3, nullptr, 0);
}
M_ActivateMenu(newmenu);
}
@ -489,7 +489,7 @@ void M_SetMenu(FName menu, int param)
IFVIRTUALPTRNAME(newmenu, "OptionMenu", Init)
{
VMValue params[3] = { newmenu, CurrentMenu, ld };
GlobalVMStack.Call(func, params, 3, nullptr, 0);
VMCall(func, params, 3, nullptr, 0);
}
M_ActivateMenu(newmenu);
}
@ -507,7 +507,7 @@ void M_SetMenu(FName menu, int param)
IFVIRTUALPTRNAME(newmenu, "GenericMenu", Init)
{
VMValue params[3] = { newmenu, CurrentMenu };
GlobalVMStack.Call(func, params, 2, nullptr, 0);
VMCall(func, params, 2, nullptr, 0);
}
M_ActivateMenu(newmenu);
return;
@ -1061,7 +1061,7 @@ CCMD(undocolorpic)
IFVIRTUALPTR(CurrentMenu, DMenu, ResetColor)
{
VMValue params[] = { (DObject*)CurrentMenu };
GlobalVMStack.Call(func, params, countof(params), nullptr, 0, nullptr);
VMCall(func, params, countof(params), nullptr, 0);
}
}
}
@ -1130,8 +1130,8 @@ DMenuItemBase * CreateOptionMenuItemStaticText(const char *name, bool v)
auto p = c->CreateNew();
FString namestr = name;
VMValue params[] = { p, &namestr, v };
auto f = dyn_cast<PFunction>(c->Symbols.FindSymbol("Init", false));
GlobalVMStack.Call(f->Variants[0].Implementation, params, countof(params), nullptr, 0);
auto f = dyn_cast<PFunction>(c->FindSymbol("Init", false));
VMCall(f->Variants[0].Implementation, params, countof(params), nullptr, 0);
return (DMenuItemBase*)p;
}
@ -1141,8 +1141,8 @@ DMenuItemBase * CreateOptionMenuItemJoyConfigMenu(const char *label, IJoystickCo
auto p = c->CreateNew();
FString namestr = label;
VMValue params[] = { p, &namestr, joy };
auto f = dyn_cast<PFunction>(c->Symbols.FindSymbol("Init", false));
GlobalVMStack.Call(f->Variants[0].Implementation, params, countof(params), nullptr, 0);
auto f = dyn_cast<PFunction>(c->FindSymbol("Init", false));
VMCall(f->Variants[0].Implementation, params, countof(params), nullptr, 0);
return (DMenuItemBase*)p;
}
@ -1152,8 +1152,8 @@ DMenuItemBase * CreateOptionMenuItemSubmenu(const char *label, FName cmd, int ce
auto p = c->CreateNew();
FString namestr = label;
VMValue params[] = { p, &namestr, cmd.GetIndex(), center };
auto f = dyn_cast<PFunction>(c->Symbols.FindSymbol("Init", false));
GlobalVMStack.Call(f->Variants[0].Implementation, params, countof(params), nullptr, 0);
auto f = dyn_cast<PFunction>(c->FindSymbol("Init", false));
VMCall(f->Variants[0].Implementation, params, countof(params), nullptr, 0);
return (DMenuItemBase*)p;
}
@ -1163,8 +1163,8 @@ DMenuItemBase * CreateOptionMenuItemControl(const char *label, FName cmd, FKeyBi
auto p = c->CreateNew();
FString namestr = label;
VMValue params[] = { p, &namestr, cmd.GetIndex(), bindings };
auto f = dyn_cast<PFunction>(c->Symbols.FindSymbol("Init", false));
GlobalVMStack.Call(f->Variants[0].Implementation, params, countof(params), nullptr, 0);
auto f = dyn_cast<PFunction>(c->FindSymbol("Init", false));
VMCall(f->Variants[0].Implementation, params, countof(params), nullptr, 0);
return (DMenuItemBase*)p;
}
@ -1174,8 +1174,8 @@ DMenuItemBase * CreateListMenuItemPatch(double x, double y, int height, int hotk
auto p = c->CreateNew();
FString keystr = FString(char(hotkey));
VMValue params[] = { p, x, y, height, tex.GetIndex(), &keystr, command.GetIndex(), param };
auto f = dyn_cast<PFunction>(c->Symbols.FindSymbol("InitDirect", false));
GlobalVMStack.Call(f->Variants[0].Implementation, params, countof(params), nullptr, 0);
auto f = dyn_cast<PFunction>(c->FindSymbol("InitDirect", false));
VMCall(f->Variants[0].Implementation, params, countof(params), nullptr, 0);
return (DMenuItemBase*)p;
}
@ -1186,8 +1186,8 @@ DMenuItemBase * CreateListMenuItemText(double x, double y, int height, int hotke
FString keystr = FString(char(hotkey));
FString textstr = text;
VMValue params[] = { p, x, y, height, &keystr, &textstr, font, int(color1.d), int(color2.d), command.GetIndex(), param };
auto f = dyn_cast<PFunction>(c->Symbols.FindSymbol("InitDirect", false));
GlobalVMStack.Call(f->Variants[0].Implementation, params, countof(params), nullptr, 0);
auto f = dyn_cast<PFunction>(c->FindSymbol("InitDirect", false));
VMCall(f->Variants[0].Implementation, params, countof(params), nullptr, 0);
return (DMenuItemBase*)p;
}
@ -1198,7 +1198,7 @@ bool DMenuItemBase::Activate()
VMValue params[] = { (DObject*)this };
int retval;
VMReturn ret(&retval);
GlobalVMStack.Call(func, params, countof(params), &ret, 1, nullptr);
VMCall(func, params, countof(params), &ret, 1);
return !!retval;
}
return false;
@ -1212,7 +1212,7 @@ bool DMenuItemBase::SetString(int i, const char *s)
VMValue params[] = { (DObject*)this, i, &namestr };
int retval;
VMReturn ret(&retval);
GlobalVMStack.Call(func, params, countof(params), &ret, 1, nullptr);
VMCall(func, params, countof(params), &ret, 1);
return !!retval;
}
return false;
@ -1226,7 +1226,7 @@ bool DMenuItemBase::GetString(int i, char *s, int len)
int retval;
FString retstr;
VMReturn ret[2]; ret[0].IntAt(&retval); ret[1].StringAt(&retstr);
GlobalVMStack.Call(func, params, countof(params), ret, 2, nullptr);
VMCall(func, params, countof(params), ret, 2);
strncpy(s, retstr, len);
return !!retval;
}
@ -1241,7 +1241,7 @@ bool DMenuItemBase::SetValue(int i, int value)
VMValue params[] = { (DObject*)this, i, value };
int retval;
VMReturn ret(&retval);
GlobalVMStack.Call(func, params, countof(params), &ret, 1, nullptr);
VMCall(func, params, countof(params), &ret, 1);
return !!retval;
}
return false;
@ -1254,7 +1254,7 @@ bool DMenuItemBase::GetValue(int i, int *pvalue)
VMValue params[] = { (DObject*)this, i };
int retval[2];
VMReturn ret[2]; ret[0].IntAt(&retval[0]); ret[1].IntAt(&retval[1]);
GlobalVMStack.Call(func, params, countof(params), ret, 2, nullptr);
VMCall(func, params, countof(params), ret, 2);
*pvalue = retval[1];
return !!retval[0];
}

View file

@ -51,6 +51,8 @@
#include "gi.h"
#include "i_sound.h"
#include "cmdlib.h"
#include "vm.h"
#include "types.h"
@ -371,7 +373,7 @@ static void ParseListMenuBody(FScanner &sc, DListMenuDescriptor *desc)
PClass *cls = PClass::FindClass(buildname);
if (cls != nullptr && cls->IsDescendantOf("ListMenuItem"))
{
auto func = dyn_cast<PFunction>(cls->Symbols.FindSymbol("Init", true));
auto func = dyn_cast<PFunction>(cls->FindSymbol("Init", true));
if (func != nullptr && !(func->Variants[0].Flags & (VARF_Protected | VARF_Private))) // skip internal classes which have a protexted init method.
{
auto &args = func->Variants[0].Proto->ArgumentTypes;
@ -384,7 +386,7 @@ static void ParseListMenuBody(FScanner &sc, DListMenuDescriptor *desc)
params.Push(desc);
start = 2;
}
auto TypeCVar = NewPointer(NewNativeStruct("CVar", nullptr));
auto TypeCVar = NewPointer(NewStruct("CVar", nullptr, true));
// Note that this array may not be reallocated so its initial size must be the maximum possible elements.
TArray<FString> strings(args.Size());
@ -480,7 +482,7 @@ static void ParseListMenuBody(FScanner &sc, DListMenuDescriptor *desc)
}
DMenuItemBase *item = (DMenuItemBase*)cls->CreateNew();
params[0] = item;
GlobalVMStack.Call(func->Variants[0].Implementation, &params[0], params.Size(), nullptr, 0);
VMCall(func->Variants[0].Implementation, &params[0], params.Size(), nullptr, 0);
desc->mItems.Push((DMenuItemBase*)item);
if (cls->IsDescendantOf("ListMenuItemSelectable"))
@ -746,14 +748,14 @@ static void ParseOptionMenuBody(FScanner &sc, DOptionMenuDescriptor *desc)
PClass *cls = PClass::FindClass(buildname);
if (cls != nullptr && cls->IsDescendantOf("OptionMenuItem"))
{
auto func = dyn_cast<PFunction>(cls->Symbols.FindSymbol("Init", true));
auto func = dyn_cast<PFunction>(cls->FindSymbol("Init", true));
if (func != nullptr && !(func->Variants[0].Flags & (VARF_Protected | VARF_Private))) // skip internal classes which have a protexted init method.
{
auto &args = func->Variants[0].Proto->ArgumentTypes;
TArray<VMValue> params;
params.Push(0);
auto TypeCVar = NewPointer(NewNativeStruct("CVar", nullptr));
auto TypeCVar = NewPointer(NewStruct("CVar", nullptr, true));
// Note that this array may not be reallocated so its initial size must be the maximum possible elements.
TArray<FString> strings(args.Size());
@ -837,7 +839,7 @@ static void ParseOptionMenuBody(FScanner &sc, DOptionMenuDescriptor *desc)
DMenuItemBase *item = (DMenuItemBase*)cls->CreateNew();
params[0] = item;
GlobalVMStack.Call(func->Variants[0].Implementation, &params[0], params.Size(), nullptr, 0);
VMCall(func->Variants[0].Implementation, &params[0], params.Size(), nullptr, 0);
desc->mItems.Push((DMenuItemBase*)item);
success = true;

View file

@ -45,6 +45,7 @@
#include "st_start.h"
#include "c_dispatch.h"
#include "g_game.h"
#include "vm.h"
EXTERN_CVAR (Bool, saveloadconfirmation) // [mxd]
@ -70,8 +71,8 @@ DMenu *CreateMessageBoxMenu(DMenu *parent, const char *message, int messagemode,
FString namestr = message;
VMValue params[] = { p, parent, &namestr, messagemode, playsound, action.GetIndex(), reinterpret_cast<void*>(handler) };
auto f = dyn_cast<PFunction>(c->Symbols.FindSymbol("Init", false));
GlobalVMStack.Call(f->Variants[0].Implementation, params, countof(params), nullptr, 0);
auto f = dyn_cast<PFunction>(c->FindSymbol("Init", false));
VMCall(f->Variants[0].Implementation, params, countof(params), nullptr, 0);
return (DMenu*)p;
}

View file

@ -47,6 +47,7 @@
#include "r_state.h"
#include "r_data/r_translate.h"
#include "v_text.h"
#include "vm.h"
EXTERN_CVAR(Int, team)
EXTERN_CVAR(Float, autoaim)

View file

@ -53,6 +53,7 @@
#include "m_joy.h"
#include "sbar.h"
#include "hardware.h"
#include "vm.h"
/*=======================================
*

View file

@ -87,6 +87,8 @@
#include "g_levellocals.h"
#include "actorinlines.h"
#include "stats.h"
#include "types.h"
#include "vm.h"
// P-codes for ACS scripts
enum
@ -5012,7 +5014,7 @@ int DLevelScript::LineFromID(int id)
bool GetVarAddrType(AActor *self, FName varname, int index, void *&addr, PType *&type, bool readonly)
{
PField *var = dyn_cast<PField>(self->GetClass()->Symbols.FindSymbol(varname, true));
PField *var = dyn_cast<PField>(self->GetClass()->FindSymbol(varname, true));
PArray *arraytype;
if (var == NULL || (!readonly && (var->Flags & VARF_Native)))
@ -5362,7 +5364,7 @@ static int ScriptCall(AActor *activator, unsigned argc, int32_t *args)
{
I_Error("ACS call to unknown class in script function %s.%s", clsname, funcname);
}
auto funcsym = dyn_cast<PFunction>(cls->Symbols.FindSymbol(funcname, true));
auto funcsym = dyn_cast<PFunction>(cls->FindSymbol(funcname, true));
if (funcsym == nullptr)
{
I_Error("ACS call to unknown script function %s.%s", clsname, funcname);
@ -5431,7 +5433,7 @@ static int ScriptCall(AActor *activator, unsigned argc, int32_t *args)
// The return value can be the same types as the parameter types, plus void
if (func->Proto->ReturnTypes.Size() == 0)
{
GlobalVMStack.Call(func, &params[0], params.Size(), nullptr, 0);
VMCall(func, &params[0], params.Size(), nullptr, 0);
}
else
{
@ -5439,7 +5441,7 @@ static int ScriptCall(AActor *activator, unsigned argc, int32_t *args)
if (rettype == TypeSInt32 || rettype == TypeBool || rettype == TypeColor || rettype == TypeName || rettype == TypeSound)
{
VMReturn ret(&retval);
GlobalVMStack.Call(func, &params[0], params.Size(), &ret, 1);
VMCall(func, &params[0], params.Size(), &ret, 1);
if (rettype == TypeName)
{
retval = GlobalACSStrings.AddString(FName(ENamedName(retval)));
@ -5453,20 +5455,20 @@ static int ScriptCall(AActor *activator, unsigned argc, int32_t *args)
{
double d;
VMReturn ret(&d);
GlobalVMStack.Call(func, &params[0], params.Size(), &ret, 1);
VMCall(func, &params[0], params.Size(), &ret, 1);
retval = DoubleToACS(d);
}
else if (rettype == TypeString)
{
FString d;
VMReturn ret(&d);
GlobalVMStack.Call(func, &params[0], params.Size(), &ret, 1);
VMCall(func, &params[0], params.Size(), &ret, 1);
retval = GlobalACSStrings.AddString(d);
}
else
{
// All other return values can not be handled so ignore them.
GlobalVMStack.Call(func, &params[0], params.Size(), nullptr, 0);
VMCall(func, &params[0], params.Size(), nullptr, 0);
}
}
}
@ -6910,7 +6912,7 @@ static void SetMarineWeapon(AActor *marine, int weapon)
if (smw)
{
VMValue params[2] = { marine, weapon };
GlobalVMStack.Call(smw, params, 2, nullptr, 0, nullptr);
VMCall(smw, params, 2, nullptr, 0);
}
}
@ -6921,7 +6923,7 @@ static void SetMarineSprite(AActor *marine, PClassActor *source)
if (sms)
{
VMValue params[2] = { marine, source };
GlobalVMStack.Call(sms, params, 2, nullptr, 0, nullptr);
VMCall(sms, params, 2, nullptr, 0);
}
}
@ -9777,8 +9779,7 @@ scriptwait:
}
else
{
AInventory *item = activator->FindInventory (dyn_cast<PClassActor>(
PClass::FindClass (FBehavior::StaticLookupString (STACK(1)))));
AInventory *item = activator->FindInventory (PClass::FindActor (FBehavior::StaticLookupString (STACK(1))));
if (item == NULL || !item->IsKindOf(NAME_Weapon))
{

View file

@ -82,6 +82,8 @@
#include "r_utility.h"
#include "sbar.h"
#include "actorinlines.h"
#include "vm.h"
#include "types.h"
AActor *SingleActorFromTID(int tid, AActor *defactor);
@ -130,8 +132,7 @@ bool AStateProvider::CallStateChain (AActor *actor, FState *state)
{
if (!(state->UseFlags & SUF_ITEM))
{
auto so = FState::StaticFindStateOwner(state);
Printf(TEXTCOLOR_RED "State %s.%d not flagged for use in CustomInventory state chains.\n", so->TypeName.GetChars(), int(state - so->OwnedStates));
Printf(TEXTCOLOR_RED "State %s not flagged for use in CustomInventory state chains.\n", FState::StaticGetStateName(state));
return false;
}
@ -144,8 +145,8 @@ bool AStateProvider::CallStateChain (AActor *actor, FState *state)
{
// If an unsafe function (i.e. one that accesses user variables) is being detected, print a warning once and remove the bogus function. We may not call it because that would inevitably crash.
auto owner = FState::StaticFindStateOwner(state);
Printf(TEXTCOLOR_RED "Unsafe state call in state %s.%d to %s which accesses user variables. The action function has been removed from this state\n",
owner->TypeName.GetChars(), int(state - owner->OwnedStates), state->ActionFunc->PrintableName.GetChars());
Printf(TEXTCOLOR_RED "Unsafe state call in state %s to %s which accesses user variables. The action function has been removed from this state\n",
FState::StaticGetStateName(state), state->ActionFunc->PrintableName.GetChars());
state->ActionFunc = nullptr;
}
@ -183,14 +184,12 @@ bool AStateProvider::CallStateChain (AActor *actor, FState *state)
}
try
{
GlobalVMStack.Call(state->ActionFunc, params, state->ActionFunc->ImplicitArgs, wantret, numret);
VMCall(state->ActionFunc, params, state->ActionFunc->ImplicitArgs, wantret, numret);
}
catch (CVMAbortException &err)
{
err.MaybePrintMessage();
auto owner = FState::StaticFindStateOwner(state);
int offs = int(state - owner->OwnedStates);
err.stacktrace.AppendFormat("Called from state %s.%d in inventory state chain in %s\n", owner->TypeName.GetChars(), offs, GetClass()->TypeName.GetChars());
err.stacktrace.AppendFormat("Called from state %s in inventory state chain in %s\n", FState::StaticGetStateName(state), GetClass()->TypeName.GetChars());
throw;
}
@ -3320,9 +3319,9 @@ DEFINE_ACTION_FUNCTION(AActor, A_SpawnDebris)
{
mo->Translation = self->Translation;
}
if (i < mo->GetClass()->NumOwnedStates)
if (i < mo->GetInfo()->NumOwnedStates)
{
mo->SetState (mo->GetClass()->OwnedStates + i);
mo->SetState (mo->GetInfo()->OwnedStates + i);
}
mo->Vel.X = mult_h * pr_spawndebris.Random2() / 64.;
mo->Vel.Y = mult_h * pr_spawndebris.Random2() / 64.;
@ -4752,7 +4751,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_ChangeVelocity)
static PField *GetVar(DObject *self, FName varname)
{
PField *var = dyn_cast<PField>(self->GetClass()->Symbols.FindSymbol(varname, true));
PField *var = dyn_cast<PField>(self->GetClass()->FindSymbol(varname, true));
if (var == NULL || (var->Flags & (VARF_Native | VARF_Private | VARF_Protected | VARF_Static)) || !var->Type->IsKindOf(RUNTIME_CLASS(PBasicType)))
{
@ -4801,7 +4800,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_SetUserVarFloat)
static PField *GetArrayVar(DObject *self, FName varname, int pos)
{
PField *var = dyn_cast<PField>(self->GetClass()->Symbols.FindSymbol(varname, true));
PField *var = dyn_cast<PField>(self->GetClass()->FindSymbol(varname, true));
if (var == NULL || (var->Flags & (VARF_Native | VARF_Private | VARF_Protected | VARF_Static)) ||
!var->Type->IsKindOf(RUNTIME_CLASS(PArray)) ||

View file

@ -33,6 +33,7 @@
#include "p_spec.h"
#include "g_levellocals.h"
#include "textures.h"
#include "vm.h"
//============================================================================
//

View file

@ -61,7 +61,7 @@
#include "p_local.h"
#include "menu/menu.h"
#include "g_levellocals.h"
#include "virtual.h"
#include "vm.h"
#include "actorinlines.h"
// The conversations as they exist inside a SCRIPTxx lump.
@ -367,7 +367,7 @@ static FStrifeDialogueNode *ReadRetailNode (FileReader *lump, uint32_t &prevSpea
node->SpeakerName = speech.Name;
// The item the speaker should drop when killed.
node->DropType = dyn_cast<PClassActor>(GetStrifeType(speech.DropType));
node->DropType = GetStrifeType(speech.DropType);
// Items you need to have to make the speaker use a different node.
node->ItemCheck.Resize(3);
@ -447,7 +447,7 @@ static FStrifeDialogueNode *ReadTeaserNode (FileReader *lump, uint32_t &prevSpea
node->SpeakerName = speech.Name;
// The item the speaker should drop when killed.
node->DropType = dyn_cast<PClassActor>(GetStrifeType (speech.DropType));
node->DropType = GetStrifeType (speech.DropType);
// Items you need to have to make the speaker use a different node.
node->ItemCheck.Resize(3);
@ -512,7 +512,7 @@ static void ParseReplies (FStrifeDialogueReply **replyptr, Response *responses)
reply->LogString = "";
// The item to receive when this reply is used.
reply->GiveType = dyn_cast<PClassActor>(GetStrifeType (rsp->GiveType));
reply->GiveType = GetStrifeType (rsp->GiveType);
reply->ActionSpecial = 0;
// Do you need anything special for this reply to succeed?
@ -639,7 +639,7 @@ static void TakeStrifeItem (player_t *player, PClassActor *itemtype, int amount)
return;
// Don't take the sigil.
if (itemtype->GetClass()->TypeName == NAME_Sigil)
if (itemtype->TypeName == NAME_Sigil)
return;
player->mo->TakeInventory(itemtype, amount);
@ -867,7 +867,7 @@ void P_StartConversation (AActor *npc, AActor *pc, bool facetalker, bool saveang
{
VMValue params[] = { cmenu, CurNode, pc->player, StaticLastReply };
VMReturn ret(&ConversationMenuY);
GlobalVMStack.Call(func, params, countof(params), &ret, 1);
VMCall(func, params, countof(params), &ret, 1);
}
if (CurNode != PrevNode)

View file

@ -54,6 +54,7 @@
#include "d_player.h"
#include "r_utility.h"
#include "g_levellocals.h"
#include "vm.h"
CVAR (Int, cl_rockettrails, 1, CVAR_ARCHIVE);
CVAR (Bool, r_rail_smartspiral, 0, CVAR_ARCHIVE);

View file

@ -52,7 +52,7 @@
#include "p_checkposition.h"
#include "math/cmath.h"
#include "g_levellocals.h"
#include "virtual.h"
#include "vm.h"
#include "actorinlines.h"
#include "gi.h"
@ -3332,7 +3332,7 @@ AInventory *P_DropItem (AActor *source, PClassActor *type, int dropamount, int c
VMValue params[2] = { inv, source };
int retval;
VMReturn ret(&retval);
GlobalVMStack.Call(func, params, 2, &ret, 1, nullptr);
VMCall(func, params, 2, &ret, 1);
if (retval)
{
// The special action indicates that the item should not spawn

View file

@ -33,6 +33,7 @@
#include "p_spec.h"
#include "r_data/r_interpolate.h"
#include "g_levellocals.h"
#include "vm.h"
//==========================================================================
//

View file

@ -58,7 +58,7 @@
#include "d_net.h"
#include "d_netinf.h"
#include "a_morph.h"
#include "virtual.h"
#include "vm.h"
#include "g_levellocals.h"
#include "events.h"
#include "actorinlines.h"
@ -248,7 +248,7 @@ void ClientObituary (AActor *self, AActor *inflictor, AActor *attacker, int dmgf
VMValue params[] = { attacker, self, inflictor, mod.GetIndex(), !!(dmgflags & DMG_PLAYERATTACK) };
FString ret;
VMReturn rett(&ret);
GlobalVMStack.Call(func, params, countof(params), &rett, 1);
VMCall(func, params, countof(params), &rett, 1);
if (ret.IsNotEmpty()) message = ret;
}
}
@ -326,7 +326,7 @@ void AActor::Die (AActor *source, AActor *inflictor, int dmgflags)
IFVIRTUALPTR(item, AInventory, OwnerDied)
{
VMValue params[1] = { item };
GlobalVMStack.Call(func, params, 1, nullptr, 0);
VMCall(func, params, 1, nullptr, 0);
}
item = next;
}
@ -367,7 +367,7 @@ void AActor::Die (AActor *source, AActor *inflictor, int dmgflags)
{
VMValue params[] = { (DObject*)this };
VMReturn ret(&Height);
GlobalVMStack.Call(func, params, 1, &ret, 1);
VMCall(func, params, 1, &ret, 1);
}
// [RH] If the thing has a special, execute and remove it
@ -733,7 +733,7 @@ void AActor::CallDie(AActor *source, AActor *inflictor, int dmgflags)
IFVIRTUAL(AActor, Die)
{
VMValue params[4] = { (DObject*)this, source, inflictor, dmgflags };
GlobalVMStack.Call(func, params, 4, nullptr, 0, nullptr);
VMCall(func, params, 4, nullptr, 0);
}
else return Die(source, inflictor, dmgflags);
}
@ -916,7 +916,6 @@ static int DamageMobj (AActor *target, AActor *inflictor, AActor *source, int da
int temp;
int painchance = 0;
FState * woundstate = NULL;
PainChanceList * pc = NULL;
bool justhit = false;
bool plrDontThrust = false;
bool invulpain = false;
@ -1422,7 +1421,7 @@ static int DamageMobj (AActor *target, AActor *inflictor, AActor *source, int da
{
VMValue params[] = { source, target, draindmg, mod.GetIndex() };
VMReturn ret(&draindmg);
GlobalVMStack.Call(func, params, countof(params), &ret, 1);
VMCall(func, params, countof(params), &ret, 1);
}
if (P_GiveBody(source, draindmg))
{
@ -1500,14 +1499,13 @@ fakepain: //Needed so we can skip the rest of the above, but still obey the orig
if (!(target->flags5 & MF5_NOPAIN) && (inflictor == NULL || !(inflictor->flags5 & MF5_PAINLESS)) &&
(target->player != NULL || !G_SkillProperty(SKILLP_NoPain)) && !(target->flags & MF_SKULLFLY))
{
pc = target->GetClass()->PainChances;
painchance = target->PainChance;
if (pc != NULL)
for (auto & pc : target->GetInfo()->PainChances)
{
int *ppc = pc->CheckKey(mod);
if (ppc != NULL)
if (pc.first == mod)
{
painchance = *ppc;
painchance = pc.second;
break;
}
}
@ -1620,7 +1618,7 @@ int P_DamageMobj(AActor *target, AActor *inflictor, AActor *source, int damage,
VMReturn ret;
int retval;
ret.IntAt(&retval);
GlobalVMStack.Call(func, params, 7, &ret, 1, nullptr);
VMCall(func, params, 7, &ret, 1);
return retval;
}
else
@ -1772,7 +1770,7 @@ bool AActor::CallOkayToSwitchTarget(AActor *other)
VMValue params[] = { (DObject*)this, other };
int retv;
VMReturn ret(&retv);
GlobalVMStack.Call(func, params, 2, &ret, 1);
VMCall(func, params, 2, &ret, 1);
return !!retv;
}
return OkayToSwitchTarget(other);

View file

@ -38,6 +38,7 @@
#include "p_lnspec.h"
#include "p_spec.h"
#include "g_levellocals.h"
#include "vm.h"
enum
{

View file

@ -62,6 +62,7 @@
#include "fragglescript/t_fs.h"
#include "p_spec.h"
#include "g_levellocals.h"
#include "vm.h"
// Remaps EE sector change types to Generic_Floor values. According to the Eternity Wiki:
/*

View file

@ -47,7 +47,7 @@
#include "r_utility.h"
#include "p_blockmap.h"
#include "p_3dmidtex.h"
#include "virtual.h"
#include "vm.h"
#include "s_sound.h"
#include "decallib.h"
@ -154,7 +154,7 @@ bool P_CanCollideWith(AActor *tmthing, AActor *thing)
VMFunction *func = clss->Virtuals.Size() > VIndex ? clss->Virtuals[VIndex] : nullptr;
if (func != nullptr)
{
GlobalVMStack.Call(func, params, 3, &ret, 1, nullptr);
VMCall(func, params, 3, &ret, 1);
if (!retval) return false;
}
std::swap(params[0].a, params[1].a);
@ -165,7 +165,7 @@ bool P_CanCollideWith(AActor *tmthing, AActor *thing)
func = clss->Virtuals.Size() > VIndex ? clss->Virtuals[VIndex] : nullptr;
if (func != nullptr)
{
GlobalVMStack.Call(func, params, 3, &ret, 1, nullptr);
VMCall(func, params, 3, &ret, 1);
if (!retval) return false;
}
return true;
@ -5302,7 +5302,7 @@ bool P_UseTraverse(AActor *usething, const DVector2 &start, const DVector2 &end,
VMValue params[] = { mobj, usething };
int ret;
VMReturn vret(&ret);
GlobalVMStack.Call(func, params, 2, &vret, 1);
VMCall(func, params, 2, &vret, 1);
if (ret) return true;
}
continue;

View file

@ -47,6 +47,7 @@
#include "templates.h"
#include "po_man.h"
#include "g_levellocals.h"
#include "vm.h"
sector_t *P_PointInSectorBuggy(double x, double y);
int P_VanillaPointOnDivlineSide(double x, double y, const divline_t* line);

View file

@ -68,7 +68,7 @@
#include "r_utility.h"
#include "thingdef.h"
#include "d_player.h"
#include "virtual.h"
#include "vm.h"
#include "g_levellocals.h"
#include "a_morph.h"
#include "events.h"
@ -153,9 +153,6 @@ AActor::~AActor ()
// Use Destroy() instead.
}
extern FFlagDef InternalActorFlagDefs[];
extern FFlagDef ActorFlagDefs[];
DEFINE_FIELD(AActor, snext)
DEFINE_FIELD(AActor, player)
DEFINE_FIELD_NAMED(AActor, __Pos, pos)
@ -632,8 +629,7 @@ bool AActor::SetState (FState *newstate, bool nofunction)
}
if (!(newstate->UseFlags & SUF_ACTOR))
{
auto so = FState::StaticFindStateOwner(newstate);
Printf(TEXTCOLOR_RED "State %s.%d in %s not flagged for use as an actor sprite\n", so->TypeName.GetChars(), int(newstate - so->OwnedStates), GetClass()->TypeName.GetChars());
Printf(TEXTCOLOR_RED "State %s in %s not flagged for use as an actor sprite\n", FState::StaticGetStateName(newstate), GetClass()->TypeName.GetChars());
state = nullptr;
Destroy();
return false;
@ -842,7 +838,7 @@ void AActor::RemoveInventory(AInventory *item)
IFVIRTUALPTR(item, AInventory, DetachFromOwner)
{
VMValue params[1] = { item };
GlobalVMStack.Call(func, params, 1, nullptr, 0, nullptr);
VMCall(func, params, 1, nullptr, 0);
}
item->Owner = NULL;
@ -1110,7 +1106,7 @@ AInventory *AActor::DropInventory (AInventory *item, int amt)
{
VMValue params[] = { (DObject*)item, amt };
VMReturn ret((void**)&drop);
GlobalVMStack.Call(func, params, countof(params), &ret, 1, nullptr);
VMCall(func, params, countof(params), &ret, 1);
}
if (drop == nullptr) return NULL;
drop->SetOrigin(PosPlusZ(10.), false);
@ -1606,22 +1602,21 @@ bool AActor::IsVisibleToPlayer() const
(signed)(VisibleToTeam-1) != players[consoleplayer].userinfo.GetTeam() )
return false;
auto &vis = GetInfo()->VisibleToPlayerClass;
if (vis.Size() == 0) return true; // early out for the most common case.
const player_t* pPlayer = players[consoleplayer].camera->player;
if (pPlayer && pPlayer->mo && GetClass()->VisibleToPlayerClass.Size() > 0)
if (pPlayer)
{
bool visible = false;
for(unsigned int i = 0;i < GetClass()->VisibleToPlayerClass.Size();++i)
for(auto cls : vis)
{
auto cls = GetClass()->VisibleToPlayerClass[i];
if (cls && pPlayer->mo->GetClass()->IsDescendantOf(cls))
{
visible = true;
break;
return true;
}
}
if (!visible)
return false;
return false;
}
// [BB] Passed all checks.
@ -1683,7 +1678,7 @@ void AActor::CallTouch(AActor *toucher)
IFVIRTUAL(AActor, Touch)
{
VMValue params[2] = { (DObject*)this, toucher };
GlobalVMStack.Call(func, params, 2, nullptr, 0, nullptr);
VMCall(func, params, 2, nullptr, 0);
}
else Touch(toucher);
}
@ -3575,7 +3570,7 @@ int AActor::GetMissileDamage (int mask, int add)
result.IntAt(&amount);
if (GlobalVMStack.Call(DamageFunc, &param, 1, &result, 1) < 1)
if (VMCall(DamageFunc, &param, 1, &result, 1) < 1)
{ // No results
return 0;
}
@ -3640,7 +3635,7 @@ bool AActor::CallSlam(AActor *thing)
VMReturn ret;
int retval;
ret.IntAt(&retval);
GlobalVMStack.Call(func, params, 2, &ret, 1, nullptr);
VMCall(func, params, 2, &ret, 1);
return !!retval;
}
@ -3658,7 +3653,7 @@ int AActor::SpecialMissileHit (AActor *victim)
VMReturn ret;
int retval;
ret.IntAt(&retval);
GlobalVMStack.Call(func, params, 2, &ret, 1, nullptr);
VMCall(func, params, 2, &ret, 1);
return retval;
}
else return -1;
@ -3718,7 +3713,7 @@ int AActor::AbsorbDamage(int damage, FName dmgtype)
IFVIRTUALPTR(item, AInventory, AbsorbDamage)
{
VMValue params[4] = { item, damage, dmgtype.GetIndex(), &damage };
GlobalVMStack.Call(func, params, 4, nullptr, 0, nullptr);
VMCall(func, params, 4, nullptr, 0);
}
}
return damage;
@ -3738,7 +3733,7 @@ void AActor::AlterWeaponSprite(visstyle_t *vis)
IFVIRTUALPTR(items[i], AInventory, AlterWeaponSprite)
{
VMValue params[3] = { items[i], vis, &changed };
GlobalVMStack.Call(func, params, 3, nullptr, 0, nullptr);
VMCall(func, params, 3, nullptr, 0);
}
}
}
@ -3893,7 +3888,7 @@ PClassActor *AActor::GetBloodType(int type) const
VMValue params[] = { (DObject*)this, type };
PClassActor *res;
VMReturn ret((void**)&res);
GlobalVMStack.Call(func, params, countof(params), &ret, 1);
VMCall(func, params, countof(params), &ret, 1);
return res;
}
return nullptr;
@ -4053,7 +4048,7 @@ void AActor::Tick ()
IFVIRTUALPTR(item, AInventory, DoEffect)
{
VMValue params[1] = { item };
GlobalVMStack.Call(func, params, 1, nullptr, 0, nullptr);
VMCall(func, params, 1, nullptr, 0);
}
item = item->Inventory;
}
@ -5043,7 +5038,7 @@ PClassActor *ClassForSpawn(FName classname)
{
I_Error("Attempt to spawn actor of unknown type '%s'\n", classname.GetChars());
}
if (!cls->IsKindOf(RUNTIME_CLASS(PClassActor)))
if (!cls->IsDescendantOf(RUNTIME_CLASS(AActor)))
{
I_Error("Attempt to spawn non-actor of type '%s'\n", classname.GetChars());
}
@ -5141,7 +5136,7 @@ void AActor::CallBeginPlay()
{
// Without the type cast this picks the 'void *' assignment...
VMValue params[1] = { (DObject*)this };
GlobalVMStack.Call(func, params, 1, nullptr, 0, nullptr);
VMCall(func, params, 1, nullptr, 0);
}
else BeginPlay();
}
@ -5232,7 +5227,7 @@ void AActor::CallActivate(AActor *activator)
{
// Without the type cast this picks the 'void *' assignment...
VMValue params[2] = { (DObject*)this, (DObject*)activator };
GlobalVMStack.Call(func, params, 2, nullptr, 0, nullptr);
VMCall(func, params, 2, nullptr, 0);
}
else Activate(activator);
}
@ -5278,7 +5273,7 @@ void AActor::CallDeactivate(AActor *activator)
{
// Without the type cast this picks the 'void *' assignment...
VMValue params[2] = { (DObject*)this, (DObject*)activator };
GlobalVMStack.Call(func, params, 2, nullptr, 0, nullptr);
VMCall(func, params, 2, nullptr, 0);
}
else Deactivate(activator);
}
@ -5584,7 +5579,7 @@ APlayerPawn *P_SpawnPlayer (FPlayerStart *mthing, int playernum, int flags)
IFVIRTUALPTR(p->mo, APlayerPawn, OnRespawn)
{
VMValue param = p->mo;
GlobalVMStack.Call(func, &param, 1, nullptr, 0);
VMCall(func, &param, 1, nullptr, 0);
}
}
@ -5865,7 +5860,7 @@ AActor *P_SpawnMapThing (FMapThing *mthing, int position)
Printf ("%s at (%.1f, %.1f) has no frames\n",
i->TypeName.GetChars(), mthing->pos.X, mthing->pos.Y);
i = PClass::FindActor("Unknown");
assert(i->IsKindOf(RUNTIME_CLASS(PClassActor)));
assert(i->IsDescendantOf(RUNTIME_CLASS(AActor)));
}
const AActor *info = GetDefaultByType (i);
@ -7460,7 +7455,7 @@ int AActor::CallDoSpecialDamage(AActor *target, int damage, FName damagetype)
VMReturn ret;
int retval;
ret.IntAt(&retval);
GlobalVMStack.Call(func, params, 4, &ret, 1, nullptr);
VMCall(func, params, 4, &ret, 1);
return retval;
}
else return DoSpecialDamage(target, damage, damagetype);
@ -7525,7 +7520,7 @@ int AActor::CallTakeSpecialDamage(AActor *inflictor, AActor *source, int damage,
VMReturn ret;
int retval;
ret.IntAt(&retval);
GlobalVMStack.Call(func, params, 5, &ret, 1, nullptr);
VMCall(func, params, 5, &ret, 1);
return retval;
}
else return TakeSpecialDamage(inflictor, source, damage, damagetype);
@ -7669,7 +7664,7 @@ int AActor::GetGibHealth() const
VMValue params[] = { (DObject*)this };
int h;
VMReturn ret(&h);
GlobalVMStack.Call(func, params, 1, &ret, 1);
VMCall(func, params, 1, &ret, 1);
return h;
}
return -SpawnHealth();
@ -7689,7 +7684,7 @@ DEFINE_ACTION_FUNCTION(AActor, GetCameraHeight)
FDropItem *AActor::GetDropItems() const
{
return GetClass()->DropItems;
return GetInfo()->DropItems;
}
DEFINE_ACTION_FUNCTION(AActor, GetDropItems)
@ -7805,7 +7800,7 @@ int AActor::GetModifiedDamage(FName damagetype, int damage, bool passive)
IFVIRTUALPTR(inv, AInventory, ModifyDamage)
{
VMValue params[5] = { (DObject*)inv, damage, int(damagetype), &damage, passive };
GlobalVMStack.Call(func, params, 5, nullptr, 0, nullptr);
VMCall(func, params, 5, nullptr, 0);
}
inv = inv->Inventory;
}
@ -7826,7 +7821,7 @@ int AActor::ApplyDamageFactor(FName damagetype, int damage) const
damage = int(damage * DamageFactor);
if (damage > 0)
{
damage = DamageTypeDefinition::ApplyMobjDamageFactor(damage, damagetype, GetClass()->DamageFactors);
damage = DamageTypeDefinition::ApplyMobjDamageFactor(damage, damagetype, &GetInfo()->DamageFactors);
}
return damage;
}
@ -8277,10 +8272,10 @@ DEFINE_ACTION_FUNCTION(AActor, ApplyDamageFactors)
PARAM_INT(damage);
PARAM_INT(defdamage);
DmgFactors *df = itemcls->DamageFactors;
if (df != nullptr && df->CountUsed() != 0)
DmgFactors &df = itemcls->ActorInfo()->DamageFactors;
if (df.Size() != 0)
{
ACTION_RETURN_INT(df->Apply(damagetype, damage));
ACTION_RETURN_INT(df.Apply(damagetype, damage));
}
else
{

View file

@ -31,6 +31,7 @@
#include "v_text.h"
#include "cmdlib.h"
#include "g_levellocals.h"
#include "vm.h"
// MACROS ------------------------------------------------------------------
@ -350,8 +351,7 @@ void DPSprite::SetState(FState *newstate, bool pending)
if (!(newstate->UseFlags & (SUF_OVERLAY|SUF_WEAPON))) // Weapon and overlay are mostly the same, the main difference is that weapon states restrict the self pointer to class Actor.
{
auto so = FState::StaticFindStateOwner(newstate);
Printf(TEXTCOLOR_RED "State %s.%d not flagged for use in overlays or weapons\n", so->TypeName.GetChars(), int(newstate - so->OwnedStates));
Printf(TEXTCOLOR_RED "State %s not flagged for use in overlays or weapons\n", FState::StaticGetStateName(newstate));
State = nullptr;
Destroy();
return;
@ -360,8 +360,7 @@ void DPSprite::SetState(FState *newstate, bool pending)
{
if (Caller->IsKindOf(NAME_Weapon))
{
auto so = FState::StaticFindStateOwner(newstate);
Printf(TEXTCOLOR_RED "State %s.%d not flagged for use in weapons\n", so->TypeName.GetChars(), int(newstate - so->OwnedStates));
Printf(TEXTCOLOR_RED "State %s.%d not flagged for use in weapons\n", FState::StaticGetStateName(newstate));
State = nullptr;
Destroy();
return;
@ -414,9 +413,8 @@ void DPSprite::SetState(FState *newstate, bool pending)
if (newstate->ActionFunc != nullptr && newstate->ActionFunc->Unsafe)
{
// If an unsafe function (i.e. one that accesses user variables) is being detected, print a warning once and remove the bogus function. We may not call it because that would inevitably crash.
auto owner = FState::StaticFindStateOwner(newstate);
Printf(TEXTCOLOR_RED "Unsafe state call in state %s.%d to %s which accesses user variables. The action function has been removed from this state\n",
owner->TypeName.GetChars(), int(newstate - owner->OwnedStates), newstate->ActionFunc->PrintableName.GetChars());
Printf(TEXTCOLOR_RED "Unsafe state call in state %sd to %s which accesses user variables. The action function has been removed from this state\n",
FState::StaticGetStateName(newstate), newstate->ActionFunc->PrintableName.GetChars());
newstate->ActionFunc = nullptr;
}
if (newstate->CallAction(Owner->mo, Caller, &stp, &nextstate))
@ -1512,11 +1510,11 @@ void P_SetSafeFlash(AWeapon *weapon, player_t *player, FState *flashstate, int i
PClassActor *cls = weapon->GetClass();
while (cls != RUNTIME_CLASS(AWeapon))
{
if (flashstate >= cls->OwnedStates && flashstate < cls->OwnedStates + cls->NumOwnedStates)
if (cls->OwnsState(flashstate))
{
// The flash state belongs to this class.
// Now let's check if the actually wanted state does also
if (flashstate + index < cls->OwnedStates + cls->NumOwnedStates)
if (cls->OwnsState(flashstate + index))
{
// we're ok so set the state
P_SetPsprite(player, PSP_FLASH, flashstate + index, true);

View file

@ -852,7 +852,7 @@ void CopyPlayer(player_t *dst, player_t *src, const char *name)
{
dst->userinfo.TransferFrom(uibackup);
// The player class must come from the save, so that the menu reflects the currently playing one.
dst->userinfo.PlayerClassChanged(src->mo->GetClass()->DisplayName);
dst->userinfo.PlayerClassChanged(src->mo->GetInfo()->DisplayName);
}
// Validate the skin

View file

@ -36,7 +36,7 @@
#include "r_sky.h"
#include "r_data/colormaps.h"
#include "g_levellocals.h"
#include "virtual.h"
#include "vm.h"
// [RH]
@ -1514,7 +1514,7 @@ DEFINE_ACTION_FUNCTION(_Sector, NextLowestFloorAt)
VMReturn ret;
int didit;
ret.IntAt(&didit);
GlobalVMStack.Call(func, params, 3, &ret, 1, nullptr);
VMCall(func, params, 3, &ret, 1);
if (didit)
{

View file

@ -79,6 +79,7 @@
#include "edata.h"
#endif
#include "events.h"
#include "types.h"
#include "fragglescript/t_fs.h"
@ -1616,7 +1617,7 @@ static void SetMapThingUserData(AActor *actor, unsigned udi)
{
FName varname = MapThingsUserData[udi].Property;
int value = MapThingsUserData[udi].Value;
PField *var = dyn_cast<PField>(actor->GetClass()->Symbols.FindSymbol(varname, true));
PField *var = dyn_cast<PField>(actor->GetClass()->FindSymbol(varname, true));
udi++;

View file

@ -24,6 +24,7 @@
#include "r_utility.h"
#include "b_bot.h"
#include "p_spec.h"
#include "vm.h"
// State.
#include "r_state.h"

View file

@ -76,6 +76,7 @@
#ifndef NO_EDATA
#include "edata.h"
#endif
#include "vm.h"
// State.
#include "r_state.h"

View file

@ -41,6 +41,7 @@
#include "v_text.h"
#include "thingdef.h"
#include "r_state.h"
#include "vm.h"
// stores indices for symbolic state labels for some old-style DECORATE functions.
@ -96,8 +97,7 @@ PClassActor *FState::StaticFindStateOwner (const FState *state)
for (unsigned int i = 0; i < PClassActor::AllActorClasses.Size(); ++i)
{
PClassActor *info = PClassActor::AllActorClasses[i];
if (state >= info->OwnedStates &&
state < info->OwnedStates + info->NumOwnedStates)
if (info->OwnsState(state))
{
return info;
}
@ -117,16 +117,25 @@ PClassActor *FState::StaticFindStateOwner (const FState *state, PClassActor *inf
{
while (info != NULL)
{
if (state >= info->OwnedStates &&
state < info->OwnedStates + info->NumOwnedStates)
if (info->OwnsState(state))
{
return info;
}
info = dyn_cast<PClassActor>(info->ParentClass);
info = ValidateActor(info->ParentClass);
}
return NULL;
}
//==========================================================================
//
//
//==========================================================================
FString FState::StaticGetStateName(const FState *state)
{
auto so = FState::StaticFindStateOwner(state);
return FStringf("%s.%d", so->TypeName.GetChars(), int(state - so->GetStates()));
}
//==========================================================================
//
@ -164,9 +173,9 @@ bool AActor::HasSpecialDeathStates () const
{
const PClassActor *info = static_cast<PClassActor *>(GetClass());
if (info->StateList != NULL)
if (info->GetStateLabels() != NULL)
{
FStateLabel *slabel = info->StateList->FindLabel (NAME_Death);
FStateLabel *slabel = info->GetStateLabels()->FindLabel (NAME_Death);
if (slabel != NULL && slabel->Children != NULL)
{
for(int i = 0; i < slabel->Children->NumLabels; i++)
@ -249,7 +258,7 @@ TArray<FName> &MakeStateNameList(const char * fname)
//===========================================================================
FState *PClassActor::FindState(int numnames, FName *names, bool exact) const
{
FStateLabels *labels = StateList;
FStateLabels *labels = GetStateLabels();
FState *best = NULL;
if (labels != NULL)
@ -573,12 +582,13 @@ void FStateDefinitions::InstallStates(PClassActor *info, AActor *defaults)
SetStateLabel("Spawn", GetDefault<AActor>()->SpawnState);
}
if (info->StateList != NULL)
auto &sl = info->ActorInfo()->StateList;
if (sl != NULL)
{
info->StateList->Destroy();
M_Free(info->StateList);
sl->Destroy();
M_Free(sl);
}
info->StateList = CreateStateLabelList(StateLabels);
sl = CreateStateLabelList(StateLabels);
// Cache these states as member veriables.
defaults->SpawnState = info->FindState(NAME_Spawn);
@ -623,9 +633,9 @@ void FStateDefinitions::MakeStateDefines(const PClassActor *cls)
laststatebeforelabel = NULL;
lastlabel = -1;
if (cls != NULL && cls->StateList != NULL)
if (cls != NULL && cls->GetStateLabels() != NULL)
{
MakeStateList(cls->StateList, StateLabels);
MakeStateList(cls->GetStateLabels(), StateLabels);
}
else
{
@ -730,7 +740,7 @@ FState *FStateDefinitions::ResolveGotoLabel (AActor *actor, PClassActor *mytype,
// superclass, or it may be the name of any class that this one derives from.
if (stricmp (classname, "Super") == 0)
{
type = dyn_cast<PClassActor>(type->ParentClass);
type = ValidateActor(type->ParentClass);
actor = GetDefaultByType(type);
}
else
@ -808,7 +818,7 @@ void FStateDefinitions::FixStatePointers (PClassActor *actor, TArray<FStateDefin
if (list[i].DefineFlags == SDF_INDEX)
{
size_t v = (size_t)list[i].State;
list[i].State = actor->OwnedStates + v - 1;
list[i].State = actor->GetStates() + v - 1;
list[i].DefineFlags = SDF_STATE;
}
if (list[i].Children.Size() > 0)
@ -1000,12 +1010,12 @@ int FStateDefinitions::FinishStates(PClassActor *actor, AActor *defaults)
if (count > 0)
{
FState *realstates = new FState[count];
FState *realstates = (FState*)ClassDataAllocator.Alloc(count * sizeof(FState));
int i;
memcpy(realstates, &StateArray[0], count*sizeof(FState));
actor->OwnedStates = realstates;
actor->NumOwnedStates = count;
actor->ActorInfo()->OwnedStates = realstates;
actor->ActorInfo()->NumOwnedStates = count;
SaveStateSourceLines(realstates, SourceLines);
// adjust the state pointers
@ -1071,8 +1081,7 @@ void DumpStateHelper(FStateLabels *StateList, const FString &prefix)
}
else
{
Printf(PRINT_LOG, "%s%s: %s.%d\n", prefix.GetChars(), StateList->Labels[i].Label.GetChars(),
owner->TypeName.GetChars(), int(StateList->Labels[i].State - owner->OwnedStates));
Printf(PRINT_LOG, "%s%s: %s\n", prefix.GetChars(), StateList->Labels[i].Label.GetChars(), FState::StaticGetStateName(StateList->Labels[i].State));
}
}
if (StateList->Labels[i].Children != NULL)
@ -1088,7 +1097,7 @@ CCMD(dumpstates)
{
PClassActor *info = PClassActor::AllActorClasses[i];
Printf(PRINT_LOG, "State labels for %s\n", info->TypeName.GetChars());
DumpStateHelper(info->StateList, "");
DumpStateHelper(info->GetStateLabels(), "");
Printf(PRINT_LOG, "----------------------------\n");
}
}
@ -1124,7 +1133,7 @@ DEFINE_ACTION_FUNCTION(FState, DistanceTo)
{
// Safely calculate the distance between two states.
auto o1 = FState::StaticFindStateOwner(self);
if (other >= o1->OwnedStates && other < o1->OwnedStates + o1->NumOwnedStates) retv = int(other - self);
if (o1->OwnsState(other)) retv = int(other - self);
}
ACTION_RETURN_INT(retv);
}

View file

@ -37,6 +37,7 @@
#include "p_tags.h"
#include "c_dispatch.h"
#include "g_levellocals.h"
#include "vm.h"
FTagManager tagManager;

View file

@ -39,6 +39,7 @@
#include "r_utility.h"
#include "p_spec.h"
#include "g_levellocals.h"
#include "vm.h"
#define FUDGEFACTOR 10

View file

@ -47,6 +47,7 @@
#include "p_local.h"
#include "templates.h"
#include "actor.h"
#include "vm.h"
// MACROS ------------------------------------------------------------------

View file

@ -53,6 +53,7 @@
#include "actorptrselect.h"
#include "g_levellocals.h"
#include "actorinlines.h"
#include "vm.h"
// Set of spawnable things for the Thing_Spawn and Thing_Projectile specials.
FClassMap SpawnableThings;
@ -526,7 +527,7 @@ DEFINE_ACTION_FUNCTION(AActor, GetSpawnableType)
{
PARAM_PROLOGUE;
PARAM_INT(num);
ACTION_RETURN_OBJECT(P_GetSpawnableType(num));
ACTION_RETURN_POINTER(P_GetSpawnableType(num));
}
struct MapinfoSpawnItem

View file

@ -50,6 +50,7 @@
#include "p_terrain.h"
#include "g_levellocals.h"
#include "info.h"
#include "vm.h"
//===========================================================================
//

View file

@ -58,7 +58,7 @@
#include "p_blockmap.h"
#include "a_morph.h"
#include "p_spec.h"
#include "virtual.h"
#include "vm.h"
#include "g_levellocals.h"
#include "actorinlines.h"
#include "r_data/r_translate.h"
@ -170,14 +170,14 @@ FString GetPrintableDisplayName(PClassActor *cls)
{
// Fixme; This needs a decent way to access the string table without creating a mess.
// [RH] ????
return cls->DisplayName;
return cls->GetDisplayName();
}
DEFINE_ACTION_FUNCTION(APlayerPawn, GetPrintableDisplayName)
{
PARAM_PROLOGUE;
PARAM_CLASS(type, AActor);
ACTION_RETURN_STRING(type->DisplayName);
ACTION_RETURN_STRING(type->GetDisplayName());
}
bool ValidatePlayerClass(PClassActor *ti, const char *name)
@ -192,7 +192,7 @@ bool ValidatePlayerClass(PClassActor *ti, const char *name)
Printf("Invalid player class '%s'\n", name);
return false;
}
else if (ti->DisplayName.IsEmpty())
else if (ti->GetDisplayName().IsEmpty())
{
Printf ("Missing displayname for player class '%s'\n", name);
return false;
@ -267,7 +267,7 @@ CCMD (playerclasses)
{
Printf ("%3d: Class = %s, Name = %s\n", i,
PlayerClasses[i].Type->TypeName.GetChars(),
PlayerClasses[i].Type->DisplayName.GetChars());
PlayerClasses[i].Type->GetDisplayName().GetChars());
}
}
@ -1242,7 +1242,7 @@ void APlayerPawn::CheckWeaponSwitch(PClassActor *ammotype)
DEFINE_ACTION_FUNCTION(APlayerPawn, CheckWeaponSwitch)
{
PARAM_SELF_PROLOGUE(APlayerPawn);
PARAM_OBJECT(ammotype, PClassActor);
PARAM_POINTER(ammotype, PClassActor);
self->CheckWeaponSwitch(ammotype);
return 0;
}
@ -1505,7 +1505,7 @@ void APlayerPawn::PlayIdle ()
IFVIRTUAL(APlayerPawn, PlayIdle)
{
VMValue params[1] = { (DObject*)this };
GlobalVMStack.Call(func, params, 1, nullptr, 0, nullptr);
VMCall(func, params, 1, nullptr, 0);
}
}
@ -1514,7 +1514,7 @@ void APlayerPawn::PlayRunning ()
IFVIRTUAL(APlayerPawn, PlayRunning)
{
VMValue params[1] = { (DObject*)this };
GlobalVMStack.Call(func, params, 1, nullptr, 0, nullptr);
VMCall(func, params, 1, nullptr, 0);
}
}
@ -1523,7 +1523,7 @@ void APlayerPawn::PlayAttacking ()
IFVIRTUAL(APlayerPawn, PlayAttacking)
{
VMValue params[1] = { (DObject*)this };
GlobalVMStack.Call(func, params, 1, nullptr, 0, nullptr);
VMCall(func, params, 1, nullptr, 0);
}
}
@ -1532,7 +1532,7 @@ void APlayerPawn::PlayAttacking2 ()
IFVIRTUAL(APlayerPawn, PlayAttacking2)
{
VMValue params[1] = { (DObject*)this };
GlobalVMStack.Call(func, params, 1, nullptr, 0, nullptr);
VMCall(func, params, 1, nullptr, 0);
}
}
@ -1630,7 +1630,7 @@ void APlayerPawn::MorphPlayerThink ()
IFVIRTUAL(APlayerPawn, MorphPlayerThink)
{
VMValue params[1] = { (DObject*)this };
GlobalVMStack.Call(func, params, 1, nullptr, 0, nullptr);
VMCall(func, params, 1, nullptr, 0);
}
}

View file

@ -154,7 +154,7 @@ void RenderPolySprite::Render(const TriMatrix &worldToClip, const PolyClipPlane
bool RenderPolySprite::IsThingCulled(AActor *thing)
{
FIntCVar *cvar = thing->GetClass()->distancecheck;
FIntCVar *cvar = thing->GetInfo()->distancecheck;
if (cvar != nullptr && *cvar >= 0)
{
double dist = (thing->Pos() - PolyRenderer::Instance()->Viewpoint.Pos).LengthSquared();

View file

@ -52,6 +52,7 @@
#include "p_checkposition.h"
#include "math/cmath.h"
#include "g_levellocals.h"
#include "vm.h"
// simulation recurions maximum
CVAR(Int, sv_portal_recursions, 4, CVAR_ARCHIVE|CVAR_SERVERINFO)

View file

@ -50,6 +50,7 @@
#include "d_player.h"
#include "r_data/sprites.h"
#include "r_state.h"
#include "vm.h"
#include "gi.h"
#include "stats.h"

View file

@ -14,6 +14,7 @@
#include "r_data/sprites.h"
#include "r_data/voxels.h"
#include "textures/textures.h"
#include "vm.h"
void gl_InitModels();

View file

@ -30,6 +30,7 @@
#include "serializer.h"
#include "d_player.h"
#include "g_levellocals.h"
#include "vm.h"
// MACROS ------------------------------------------------------------------

View file

@ -54,7 +54,7 @@
#include "d_player.h"
#include "r_state.h"
#include "g_levellocals.h"
#include "virtual.h"
#include "vm.h"
// MACROS ------------------------------------------------------------------
@ -487,7 +487,7 @@ void S_PrecacheLevel ()
{
// Without the type cast this picks the 'void *' assignment...
VMValue params[1] = { actor };
GlobalVMStack.Call(func, params, 1, nullptr, 0, nullptr);
VMCall(func, params, 1, nullptr, 0);
}
else
{

View file

@ -56,6 +56,8 @@
#include "w_wad.h"
#include "math/cmath.h"
inline PClass *PObjectPointer::PointedClass() const { return static_cast<PClassType*>(PointedType)->Descriptor; }
extern FRandom pr_exrandom;
FMemArena FxAlloc(65536);
int utf8_decode(const char *src, int *size);
@ -112,7 +114,7 @@ FCompileContext::FCompileContext(PNamespace *cg, PFunction *fnc, PPrototype *ret
if (fnc != nullptr) Class = fnc->OwningClass;
}
FCompileContext::FCompileContext(PNamespace *cg, PStruct *cls, bool fromdecorate)
FCompileContext::FCompileContext(PNamespace *cg, PContainerType *cls, bool fromdecorate)
: ReturnProto(nullptr), Function(nullptr), Class(cls), FromDecorate(fromdecorate), StateIndex(-1), StateCount(0), Lump(-1), CurGlobals(cg)
{
}
@ -198,14 +200,14 @@ FxLocalVariableDeclaration *FCompileContext::FindLocalVariable(FName name)
}
}
static PStruct *FindStructType(FName name, FCompileContext &ctx)
static PContainerType *FindContainerType(FName name, FCompileContext &ctx)
{
auto sym = ctx.Class->Symbols.FindSymbol(name, true);
if (sym == nullptr) sym = ctx.CurGlobals->Symbols.FindSymbol(name, true);
if (sym && sym->IsKindOf(RUNTIME_CLASS(PSymbolType)))
{
auto type = static_cast<PSymbolType*>(sym);
return dyn_cast<PStruct>(type->Type);
return dyn_cast<PContainerType>(type->Type);
}
return nullptr;
}
@ -217,11 +219,18 @@ static PClass *FindClassType(FName name, FCompileContext &ctx)
if (sym && sym->IsKindOf(RUNTIME_CLASS(PSymbolType)))
{
auto type = static_cast<PSymbolType*>(sym);
return dyn_cast<PClass>(type->Type);
auto ctype = dyn_cast<PClassType>(type->Type);
if (ctype) return ctype->Descriptor;
}
return nullptr;
}
bool isActor(PContainerType *type)
{
auto cls = dyn_cast<PClassType>(type);
return cls ? cls->Descriptor->IsDescendantOf(RUNTIME_CLASS(AActor)) : false;
}
//==========================================================================
//
// ExpEmit
@ -294,10 +303,18 @@ static bool AreCompatiblePointerTypes(PType *dest, PType *source, bool forcompar
// A type is always compatible to itself.
if (fromtype == totype) return true;
// Pointers to different types are only compatible if both point to an object and the source type is a child of the destination type.
if (fromtype->PointedType->IsKindOf(RUNTIME_CLASS(PClass)) && totype->PointedType->IsKindOf(RUNTIME_CLASS(PClass)))
if (source->IsA(RUNTIME_CLASS(PObjectPointer)) && dest->IsA(RUNTIME_CLASS(PObjectPointer)))
{
auto fromcls = static_cast<PClass *>(fromtype->PointedType);
auto tocls = static_cast<PClass *>(totype->PointedType);
auto fromcls = static_cast<PObjectPointer*>(source)->PointedClass();
auto tocls = static_cast<PObjectPointer*>(dest)->PointedClass();
if (forcompare && tocls->IsDescendantOf(fromcls)) return true;
return (fromcls->IsDescendantOf(tocls));
}
// The same rules apply to class pointers. A child type can be assigned to a variable of a parent type.
if (source->IsA(RUNTIME_CLASS(PClassPointer)) && dest->IsA(RUNTIME_CLASS(PClassPointer)))
{
auto fromcls = static_cast<PClassPointer*>(source)->ClassRestriction;
auto tocls = static_cast<PClassPointer*>(dest)->ClassRestriction;
if (forcompare && tocls->IsDescendantOf(fromcls)) return true;
return (fromcls->IsDescendantOf(tocls));
}
@ -1746,17 +1763,17 @@ FxExpression *FxTypeCast::Resolve(FCompileContext &ctx)
// this is not yet ready and does not get assigned to actual values.
}
*/
else if (ValueType->IsKindOf(RUNTIME_CLASS(PClass))) // this should never happen because the VM doesn't handle plain class types - just pointers
else if (ValueType->IsKindOf(RUNTIME_CLASS(PClassType))) // this should never happen because the VM doesn't handle plain class types - just pointers
{
if (basex->ValueType->IsKindOf(RUNTIME_CLASS(PClass)))
if (basex->ValueType->IsKindOf(RUNTIME_CLASS(PClassType)))
{
// class types are only compatible if the base type is a descendant of the result type.
auto fromtype = static_cast<PClass *>(basex->ValueType);
auto totype = static_cast<PClass *>(ValueType);
auto fromtype = static_cast<PClassType *>(basex->ValueType)->Descriptor;
auto totype = static_cast<PClassType *>(ValueType)->Descriptor;
if (fromtype->IsDescendantOf(totype)) goto basereturn;
}
}
else if (basex->ValueType->IsA(RUNTIME_CLASS(PNativeStruct)) && ValueType->IsKindOf(RUNTIME_CLASS(PPointer)) && static_cast<PPointer*>(ValueType)->PointedType == basex->ValueType)
else if (basex->IsNativeStruct() && ValueType->IsKindOf(RUNTIME_CLASS(PPointer)) && static_cast<PPointer*>(ValueType)->PointedType == basex->ValueType)
{
bool writable;
basex->RequestAddress(ctx, &writable);
@ -2477,7 +2494,7 @@ FxExpression *FxAssign::Resolve(FCompileContext &ctx)
}
// Both types are the same so this is ok.
}
else if (Right->ValueType->IsA(RUNTIME_CLASS(PNativeStruct)) && Base->ValueType->IsKindOf(RUNTIME_CLASS(PPointer)) && static_cast<PPointer*>(Base->ValueType)->PointedType == Right->ValueType)
else if (Right->IsNativeStruct() && Base->ValueType->IsKindOf(RUNTIME_CLASS(PPointer)) && static_cast<PPointer*>(Base->ValueType)->PointedType == Right->ValueType)
{
// allow conversion of native structs to pointers of the same type. This is necessary to assign elements from global arrays like players, sectors, etc. to local pointers.
// For all other types this is not needed. Structs are not assignable and classes can only exist as references.
@ -5132,7 +5149,7 @@ FxExpression *FxNew::Resolve(FCompileContext &ctx)
if (val->isConstant())
{
auto cls = static_cast<PClass *>(static_cast<FxConstant*>(val)->GetValue().GetPointer());
if (cls->ObjectFlags & OF_Abstract)
if (cls->bAbstract)
{
ScriptPosition.Message(MSG_ERROR, "Cannot instantiate abstract class %s", cls->TypeName.GetChars());
delete this;
@ -5143,7 +5160,7 @@ FxExpression *FxNew::Resolve(FCompileContext &ctx)
int outerside = ctx.Function && ctx.Function->Variants.Size() ? FScopeBarrier::SideFromFlags(ctx.Function->Variants[0].Flags) : FScopeBarrier::Side_Virtual;
if (outerside == FScopeBarrier::Side_Virtual)
outerside = FScopeBarrier::SideFromObjectFlags(ctx.Class->ObjectFlags);
int innerside = FScopeBarrier::SideFromObjectFlags(cls->ObjectFlags);
int innerside = FScopeBarrier::SideFromObjectFlags(cls->VMType->ObjectFlags);
if ((outerside != innerside) && (innerside != FScopeBarrier::Side_PlainData)) // "cannot construct ui class ... from data context"
{
ScriptPosition.Message(MSG_ERROR, "Cannot construct %s class %s from %s context", FScopeBarrier::StringFromSide(innerside), cls->TypeName.GetChars(), FScopeBarrier::StringFromSide(outerside));
@ -5953,7 +5970,7 @@ FxExpression *FxIdentifier::Resolve(FCompileContext& ctx)
delete this;
return nullptr;
}
if (!ctx.Function->Variants[0].SelfClass->IsKindOf(RUNTIME_CLASS(PClassActor)))
if (!isActor(ctx.Function->Variants[0].SelfClass))
{
ScriptPosition.Message(MSG_ERROR, "'Default' requires an actor type.");
delete this;
@ -6105,15 +6122,15 @@ foundit:
//
//==========================================================================
FxExpression *FxIdentifier::ResolveMember(FCompileContext &ctx, PStruct *classctx, FxExpression *&object, PStruct *objtype)
FxExpression *FxIdentifier::ResolveMember(FCompileContext &ctx, PContainerType *classctx, FxExpression *&object, PContainerType *objtype)
{
PSymbol *sym;
PSymbolTable *symtbl;
bool isclass = objtype->IsKindOf(RUNTIME_CLASS(PClass));
bool isclass = objtype->IsKindOf(RUNTIME_CLASS(PClassType));
if (Identifier == NAME_Default)
{
if (!objtype->IsKindOf(RUNTIME_CLASS(PClassActor)))
if (!isActor(objtype))
{
ScriptPosition.Message(MSG_ERROR, "'Default' requires an actor type.");
delete object;
@ -6163,8 +6180,8 @@ FxExpression *FxIdentifier::ResolveMember(FCompileContext &ctx, PStruct *classct
object = nullptr;
return nullptr;
}
PClass* cls_ctx = dyn_cast<PClass>(classctx);
PClass* cls_target = dyn_cast<PClass>(objtype);
auto cls_ctx = dyn_cast<PClassType>(classctx);
auto cls_target = dyn_cast<PClassType>(objtype);
// [ZZ] neither PSymbol, PField or PSymbolTable have the necessary information. so we need to do the more complex check here.
if (vsym->Flags & VARF_Protected)
{
@ -6178,7 +6195,7 @@ FxExpression *FxIdentifier::ResolveMember(FCompileContext &ctx, PStruct *classct
}
// find the class that declared this field.
PClass* p = cls_target;
auto p = cls_target;
while (p)
{
if (&p->Symbols == symtbl)
@ -6187,10 +6204,10 @@ FxExpression *FxIdentifier::ResolveMember(FCompileContext &ctx, PStruct *classct
break;
}
p = p->ParentClass;
p = p->ParentType;
}
if (!cls_ctx->IsDescendantOf(cls_target))
if (!cls_ctx->Descriptor->IsDescendantOf(cls_target->Descriptor))
{
ScriptPosition.Message(MSG_ERROR, "Protected member %s not accessible", vsym->SymbolName.GetChars());
delete object;
@ -6253,7 +6270,7 @@ FxMemberIdentifier::~FxMemberIdentifier()
FxExpression *FxMemberIdentifier::Resolve(FCompileContext& ctx)
{
PStruct *ccls = nullptr;
PContainerType *ccls = nullptr;
CHECKRESOLVED();
if (Object->ExprType == EFX_Identifier)
@ -6261,7 +6278,7 @@ FxExpression *FxMemberIdentifier::Resolve(FCompileContext& ctx)
auto id = static_cast<FxIdentifier *>(Object)->Identifier;
// If the left side is a class name for a static member function call it needs to be resolved manually
// because the resulting value type would cause problems in nearly every other place where identifiers are being used.
ccls = FindStructType(id, ctx);
ccls = FindContainerType(id, ctx);
if (ccls != nullptr)
{
static_cast<FxIdentifier *>(Object)->noglobal = true;
@ -6342,32 +6359,29 @@ FxExpression *FxMemberIdentifier::Resolve(FCompileContext& ctx)
{
if (ccls != nullptr)
{
if (!ccls->IsKindOf(RUNTIME_CLASS(PClass)) || static_cast<PClass *>(ccls)->bExported)
PSymbol *sym;
if ((sym = ccls->Symbols.FindSymbol(Identifier, true)) != nullptr)
{
PSymbol *sym;
if ((sym = ccls->Symbols.FindSymbol(Identifier, true)) != nullptr)
if (sym->IsKindOf(RUNTIME_CLASS(PSymbolConst)))
{
if (sym->IsKindOf(RUNTIME_CLASS(PSymbolConst)))
ScriptPosition.Message(MSG_DEBUGLOG, "Resolving name '%s.%s' as constant\n", ccls->TypeName.GetChars(), Identifier.GetChars());
delete this;
return FxConstant::MakeConstant(sym, ScriptPosition);
}
else
{
auto f = dyn_cast<PField>(sym);
if (f != nullptr && (f->Flags & (VARF_Static | VARF_ReadOnly | VARF_Meta)) == (VARF_Static | VARF_ReadOnly))
{
ScriptPosition.Message(MSG_DEBUGLOG, "Resolving name '%s.%s' as constant\n", ccls->TypeName.GetChars(), Identifier.GetChars());
auto x = new FxGlobalVariable(f, ScriptPosition);
delete this;
return FxConstant::MakeConstant(sym, ScriptPosition);
return x->Resolve(ctx);
}
else
{
auto f = dyn_cast<PField>(sym);
if (f != nullptr && (f->Flags & (VARF_Static | VARF_ReadOnly | VARF_Meta)) == (VARF_Static | VARF_ReadOnly))
{
auto x = new FxGlobalVariable(f, ScriptPosition);
delete this;
return x->Resolve(ctx);
}
else
{
ScriptPosition.Message(MSG_ERROR, "Unable to access '%s.%s' in a static context\n", ccls->TypeName.GetChars(), Identifier.GetChars());
delete this;
return nullptr;
}
ScriptPosition.Message(MSG_ERROR, "Unable to access '%s.%s' in a static context\n", ccls->TypeName.GetChars(), Identifier.GetChars());
delete this;
return nullptr;
}
}
}
@ -6382,9 +6396,9 @@ FxExpression *FxMemberIdentifier::Resolve(FCompileContext& ctx)
if (Object->ValueType->IsKindOf(RUNTIME_CLASS(PPointer)))
{
auto ptype = static_cast<PPointer *>(Object->ValueType)->PointedType;
if (ptype->IsKindOf(RUNTIME_CLASS(PStruct)))
if (ptype->IsKindOf(RUNTIME_CLASS(PContainerType)))
{
auto ret = ResolveMember(ctx, ctx.Class, Object, static_cast<PStruct *>(ptype));
auto ret = ResolveMember(ctx, ctx.Class, Object, static_cast<PContainerType *>(ptype));
delete this;
return ret;
}
@ -6606,7 +6620,7 @@ ExpEmit FxClassDefaults::Emit(VMFunctionBuilder *build)
ob.Free(build);
ExpEmit meta(build, REGT_POINTER);
build->Emit(OP_CLSS, meta.RegNum, ob.RegNum);
build->Emit(OP_LOS, meta.RegNum, meta.RegNum, build->GetConstantInt(myoffsetof(PClass, Defaults)));
build->Emit(OP_LP, meta.RegNum, meta.RegNum, build->GetConstantInt(myoffsetof(PClass, Defaults)));
return meta;
}
@ -6864,7 +6878,7 @@ ExpEmit FxStackVariable::Emit(VMFunctionBuilder *build)
if (offsetreg == -1) offsetreg = build->GetConstantInt(0);
auto op = membervar->Type->GetLoadOp();
if (op == OP_LO)
op = OP_LOS;
op = OP_LP;
build->Emit(op, loc.RegNum, build->FramePointer.RegNum, offsetreg);
}
else
@ -6958,8 +6972,8 @@ FxExpression *FxStructMember::Resolve(FCompileContext &ctx)
if (membervar->SymbolName == NAME_Default)
{
if (!classx->ValueType->IsKindOf(RUNTIME_CLASS(PPointer))
|| !static_cast<PPointer *>(classx->ValueType)->PointedType->IsKindOf(RUNTIME_CLASS(AActor)))
if (!classx->ValueType->IsKindOf(RUNTIME_CLASS(PObjectPointer))
|| !static_cast<PObjectPointer *>(classx->ValueType)->PointedClass()->IsDescendantOf(RUNTIME_CLASS(AActor)))
{
ScriptPosition.Message(MSG_ERROR, "'Default' requires an actor type");
delete this;
@ -7007,7 +7021,7 @@ FxExpression *FxStructMember::Resolve(FCompileContext &ctx)
if (classx->ValueType->IsKindOf(RUNTIME_CLASS(PPointer)))
{
PPointer *ptrtype = dyn_cast<PPointer>(classx->ValueType);
if (ptrtype == nullptr || !ptrtype->PointedType->IsKindOf(RUNTIME_CLASS(PStruct)))
if (ptrtype == nullptr || !ptrtype->PointedType->IsKindOf(RUNTIME_CLASS(PContainerType)))
{
ScriptPosition.Message(MSG_ERROR, "Member variable requires a struct or class object");
delete this;
@ -7484,9 +7498,9 @@ static bool CheckFunctionCompatiblity(FScriptPosition &ScriptPosition, PFunction
bool match = (callingself == calledself);
if (!match)
{
auto callingselfcls = dyn_cast<PClass>(caller->Variants[0].SelfClass);
auto calledselfcls = dyn_cast<PClass>(callee->Variants[0].SelfClass);
match = callingselfcls != nullptr && calledselfcls != nullptr && callingselfcls->IsDescendantOf(calledselfcls);
auto callingselfcls = dyn_cast<PClassType>(caller->Variants[0].SelfClass);
auto calledselfcls = dyn_cast<PClassType>(callee->Variants[0].SelfClass);
match = callingselfcls != nullptr && calledselfcls != nullptr && callingselfcls->Descriptor->IsDescendantOf(calledselfcls->Descriptor);
}
if (!match)
@ -7597,7 +7611,6 @@ FxExpression *FxFunctionCall::Resolve(FCompileContext& ctx)
}
// [ZZ] validate call
PClass* cls = (PClass*)ctx.Class;
int outerflags = 0;
if (ctx.Function)
{
@ -7610,7 +7623,7 @@ FxExpression *FxFunctionCall::Resolve(FCompileContext& ctx)
// [ZZ] check this at compile time. this would work for most legit cases.
if (innerside == FScopeBarrier::Side_Virtual)
{
innerside = FScopeBarrier::SideFromObjectFlags(cls->ObjectFlags);
innerside = FScopeBarrier::SideFromObjectFlags(ctx.Class->ObjectFlags);
innerflags = FScopeBarrier::FlagsFromSide(innerside);
}
FScopeBarrier scopeBarrier(outerflags, innerflags, MethodName.GetChars());
@ -7679,14 +7692,14 @@ FxExpression *FxFunctionCall::Resolve(FCompileContext& ctx)
delete this;
return nullptr;
}
FxExpression *self = (ctx.Function && (ctx.Function->Variants[0].Flags & VARF_Method) && ctx.Class->IsKindOf(RUNTIME_CLASS(PClassActor))) ? new FxSelf(ScriptPosition) : (FxExpression*)new FxConstant(ScriptPosition);
FxExpression *self = (ctx.Function && (ctx.Function->Variants[0].Flags & VARF_Method) && isActor(ctx.Class)) ? new FxSelf(ScriptPosition) : (FxExpression*)new FxConstant(ScriptPosition);
FxExpression *x = new FxActionSpecialCall(self, special, ArgList, ScriptPosition);
delete this;
return x->Resolve(ctx);
}
PClass *cls = FindClassType(MethodName, ctx);
if (cls != nullptr && cls->bExported)
if (cls != nullptr)
{
if (CheckArgSize(MethodName, ArgList, 1, 1, ScriptPosition))
{
@ -7847,14 +7860,17 @@ FxExpression *FxFunctionCall::Resolve(FCompileContext& ctx)
if (CheckArgSize(MethodName, ArgList, 0, 1, ScriptPosition))
{
// [ZZ] allow implicit new() call to mean "create current class instance"
if (!ArgList.Size() && !ctx.Class->IsKindOf(RUNTIME_CLASS(PClass)))
if (!ArgList.Size() && !ctx.Class->IsKindOf(RUNTIME_CLASS(PClassType)))
{
ScriptPosition.Message(MSG_ERROR, "Cannot use implicit new() in a struct");
delete this;
return nullptr;
}
else if (!ArgList.Size())
ArgList.Push(new FxConstant((PClass*)ctx.Class, NewClassPointer((PClass*)ctx.Class), ScriptPosition));
{
auto cls = static_cast<PClassType*>(ctx.Class)->Descriptor;
ArgList.Push(new FxConstant(cls, NewClassPointer(cls), ScriptPosition));
}
func = new FxNew(ArgList[0]);
ArgList[0] = nullptr;
@ -7909,12 +7925,12 @@ FxMemberFunctionCall::~FxMemberFunctionCall()
FxExpression *FxMemberFunctionCall::Resolve(FCompileContext& ctx)
{
PStruct *cls;
PContainerType *cls = nullptr;
bool staticonly = false;
bool novirtual = false;
bool isreadonly = false;
PStruct *ccls = nullptr;
PContainerType *ccls = nullptr;
if (ctx.Class == nullptr)
{
@ -7941,7 +7957,7 @@ FxExpression *FxMemberFunctionCall::Resolve(FCompileContext& ctx)
// because the resulting value type would cause problems in nearly every other place where identifiers are being used.
// [ZZ] substitute ccls for String internal type.
if (id == NAME_String) ccls = TypeStringStruct;
else ccls = FindStructType(id, ctx);
else ccls = FindContainerType(id, ctx);
if (ccls != nullptr) static_cast<FxIdentifier *>(Self)->noglobal = true;
}
@ -7951,40 +7967,37 @@ FxExpression *FxMemberFunctionCall::Resolve(FCompileContext& ctx)
{
if (ccls != nullptr)
{
if (!ccls->IsKindOf(RUNTIME_CLASS(PClass)) || static_cast<PClass *>(ccls)->bExported)
cls = ccls;
staticonly = true;
if (ccls->IsKindOf(RUNTIME_CLASS(PClassType)))
{
cls = ccls;
staticonly = true;
if (ccls->IsKindOf(RUNTIME_CLASS(PClass)))
if (ctx.Function == nullptr)
{
if (ctx.Function == nullptr)
ScriptPosition.Message(MSG_ERROR, "Unable to call %s from constant declaration", MethodName.GetChars());
delete this;
return nullptr;
}
auto clstype = dyn_cast<PClassType>(ctx.Function->Variants[0].SelfClass);
if (clstype != nullptr)
{
novirtual = clstype->Descriptor->IsDescendantOf(static_cast<PClassType*>(ccls)->Descriptor);
if (novirtual)
{
ScriptPosition.Message(MSG_ERROR, "Unable to call %s from constant declaration", MethodName.GetChars());
delete this;
return nullptr;
}
auto clstype = dyn_cast<PClass>(ctx.Function->Variants[0].SelfClass);
if (clstype != nullptr)
{
novirtual = clstype->IsDescendantOf(static_cast<PClass*>(ccls));
if (novirtual)
bool error;
PFunction *afd = FindClassMemberFunction(ccls, ctx.Class, MethodName, ScriptPosition, &error);
if ((afd->Variants[0].Flags & VARF_Method) && (afd->Variants[0].Flags & VARF_Virtual))
{
bool error;
PFunction *afd = FindClassMemberFunction(ccls, ctx.Class, MethodName, ScriptPosition, &error);
if ((afd->Variants[0].Flags & VARF_Method) && (afd->Variants[0].Flags & VARF_Virtual))
{
staticonly = false;
novirtual = true;
delete Self;
Self = new FxSelf(ScriptPosition);
Self->ValueType = NewPointer(cls);
}
else novirtual = false;
staticonly = false;
novirtual = true;
delete Self;
Self = new FxSelf(ScriptPosition);
Self->ValueType = NewPointer(cls);
}
else novirtual = false;
}
}
if (!novirtual) goto isresolved;
}
if (!novirtual) goto isresolved;
}
}
@ -7996,11 +8009,11 @@ FxExpression *FxMemberFunctionCall::Resolve(FCompileContext& ctx)
delete this;
return nullptr;
}
auto clstype = dyn_cast<PClass>(ctx.Function->Variants[0].SelfClass);
auto clstype = dyn_cast<PClassType>(ctx.Function->Variants[0].SelfClass);
if (clstype != nullptr)
{
// give the node the proper value type now that we know it's properly used.
cls = clstype->ParentClass;
cls = clstype->ParentType;
Self->ValueType = NewPointer(cls);
Self->ExprType = EFX_Self;
novirtual = true; // super calls are always non-virtual
@ -8212,9 +8225,9 @@ FxExpression *FxMemberFunctionCall::Resolve(FCompileContext& ctx)
if (Self->ValueType->IsKindOf(RUNTIME_CLASS(PPointer)) && !Self->ValueType->IsKindOf(RUNTIME_CLASS(PClassPointer)))
{
auto ptype = static_cast<PPointer *>(Self->ValueType)->PointedType;
if (ptype->IsKindOf(RUNTIME_CLASS(PStruct)))
if (ptype->IsKindOf(RUNTIME_CLASS(PContainerType)))
{
if (ptype->IsKindOf(RUNTIME_CLASS(PClass)) && MethodName == NAME_GetClass)
if (ptype->IsKindOf(RUNTIME_CLASS(PClassType)) && MethodName == NAME_GetClass)
{
if (ArgList.Size() > 0)
{
@ -8227,7 +8240,7 @@ FxExpression *FxMemberFunctionCall::Resolve(FCompileContext& ctx)
}
cls = static_cast<PStruct *>(ptype);
cls = static_cast<PContainerType *>(ptype);
}
else
{
@ -8317,9 +8330,9 @@ isresolved:
{
if (!novirtual || !(afd->Variants[0].Flags & VARF_Virtual))
{
auto clstype = dyn_cast<PClass>(ctx.Class);
auto ccls = dyn_cast<PClass>(cls);
if (clstype == nullptr || ccls == nullptr || !clstype->IsDescendantOf(ccls))
auto clstype = dyn_cast<PClassType>(ctx.Class);
auto ccls = dyn_cast<PClassType>(cls);
if (clstype == nullptr || ccls == nullptr || !clstype->Descriptor->IsDescendantOf(ccls->Descriptor))
{
ScriptPosition.Message(MSG_ERROR, "Cannot call non-static function %s::%s from here", cls->TypeName.GetChars(), MethodName.GetChars());
delete this;
@ -8809,9 +8822,9 @@ FxExpression *FxVMFunctionCall::Resolve(FCompileContext& ctx)
ArgList[i] = ArgList[i]->Resolve(ctx); // nust be resolved before the address is requested.
if (ArgList[i] != nullptr && ArgList[i]->ValueType != TypeNullPtr)
{
if (type == ArgList[i]->ValueType && type->IsA(RUNTIME_CLASS(PPointer)) && static_cast<PPointer*>(type)->IsA(RUNTIME_CLASS(PStruct)))
if (type == ArgList[i]->ValueType && type->IsA(RUNTIME_CLASS(PPointer)) && static_cast<PPointer*>(type)->PointedType->IsA(RUNTIME_CLASS(PStruct)))
{
// trying to pass a struct reference as a struct refg
// trying to pass a struct reference as a struct reference. This must preserve the type.
}
else
{
@ -9287,7 +9300,7 @@ FxExpression *FxGetClass::Resolve(FCompileContext &ctx)
delete this;
return nullptr;
}
ValueType = NewClassPointer(static_cast<PClass*>(static_cast<PPointer*>(Self->ValueType)->PointedType));
ValueType = NewClassPointer(static_cast<PClassType*>(static_cast<PPointer*>(Self->ValueType)->PointedType)->Descriptor);
return this;
}
@ -9342,7 +9355,7 @@ ExpEmit FxGetParentClass::Emit(VMFunctionBuilder *build)
op.Free(build);
}
ExpEmit to(build, REGT_POINTER);
build->Emit(OP_LOS, to.RegNum, op.RegNum, build->GetConstantInt(myoffsetof(PClass, ParentClass)));
build->Emit(OP_LP, to.RegNum, op.RegNum, build->GetConstantInt(myoffsetof(PClass, ParentClass)));
return to;
}
@ -9414,7 +9427,7 @@ ExpEmit FxGetDefaultByType::Emit(VMFunctionBuilder *build)
build->Emit(OP_LKP, to.RegNum, op.RegNum);
op = to;
}
build->Emit(OP_LOS, to.RegNum, op.RegNum, build->GetConstantInt(myoffsetof(PClass, Defaults)));
build->Emit(OP_LP, to.RegNum, op.RegNum, build->GetConstantInt(myoffsetof(PClass, Defaults)));
return to;
}
@ -10623,7 +10636,7 @@ FxExpression *FxClassTypeCast::Resolve(FCompileContext &ctx)
if (Explicit) cls = FindClassType(clsname, ctx);
else cls = PClass::FindClass(clsname);
if (cls == nullptr)
if (cls == nullptr || cls->VMType == nullptr)
{
/* lax */
// Since this happens in released WADs it must pass without a terminal error... :(
@ -10678,14 +10691,14 @@ int BuiltinNameToClass(VMValue *param, TArray<VMValue> &defaultparam, int numpar
const PClass *cls = PClass::FindClass(clsname);
const PClass *desttype = reinterpret_cast<PClass *>(param[1].a);
if (!cls->IsDescendantOf(desttype))
if (cls->VMType == nullptr || !cls->IsDescendantOf(desttype))
{
// Let the caller check this. Making this an error with a message is only taking away options from the user.
cls = nullptr;
}
ret->SetObject(const_cast<PClass *>(cls));
ret->SetPointer(const_cast<PClass *>(cls));
}
else ret->SetObject(nullptr);
else ret->SetPointer(nullptr);
return 1;
}
@ -10800,7 +10813,7 @@ int BuiltinClassCast(VMValue *param, TArray<VMValue> &defaultparam, int numparam
PARAM_PROLOGUE;
PARAM_CLASS(from, DObject);
PARAM_CLASS(to, DObject);
ACTION_RETURN_OBJECT(from && to && from->IsDescendantOf(to) ? from : nullptr);
ACTION_RETURN_POINTER(from && to && from->IsDescendantOf(to) ? from : nullptr);
}
ExpEmit FxClassPtrCast::Emit(VMFunctionBuilder *build)
@ -10835,19 +10848,21 @@ FxExpression *FxStateByIndex::Resolve(FCompileContext &ctx)
{
CHECKRESOLVED();
ABORT(ctx.Class);
auto aclass = dyn_cast<PClassActor>(ctx.Class);
auto vclass = dyn_cast<PClassType>(ctx.Class);
assert(vclass != nullptr);
auto aclass = ValidateActor(vclass->Descriptor);
// This expression type can only be used from actors, for everything else it has already produced a compile error.
assert(aclass != nullptr && aclass->NumOwnedStates > 0);
assert(aclass != nullptr && aclass->GetStateCount() > 0);
if (aclass->NumOwnedStates <= index)
if (aclass->GetStateCount() <= index)
{
ScriptPosition.Message(MSG_ERROR, "%s: Attempt to jump to non existing state index %d",
ctx.Class->TypeName.GetChars(), index);
delete this;
return nullptr;
}
int symlabel = StateLabels.AddPointer(aclass->OwnedStates + index);
int symlabel = StateLabels.AddPointer(aclass->GetStates() + index);
FxExpression *x = new FxConstant(symlabel, ScriptPosition);
x->ValueType = TypeStateLabel;
delete this;
@ -10911,9 +10926,13 @@ FxExpression *FxRuntimeStateIndex::Resolve(FCompileContext &ctx)
Index = new FxIntCast(Index, ctx.FromDecorate);
SAFE_RESOLVE(Index, ctx);
}
auto aclass = dyn_cast<PClassActor>(ctx.Class);
assert(aclass != nullptr && aclass->NumOwnedStates > 0);
symlabel = StateLabels.AddPointer(aclass->OwnedStates + ctx.StateIndex);
auto vclass = dyn_cast<PClassType>(ctx.Class);
assert(vclass != nullptr);
auto aclass = ValidateActor(vclass->Descriptor);
assert(aclass != nullptr && aclass->GetStateCount() > 0);
symlabel = StateLabels.AddPointer(aclass->GetStates() + ctx.StateIndex);
ValueType = TypeStateLabel;
return this;
}
@ -10967,7 +10986,10 @@ FxExpression *FxMultiNameState::Resolve(FCompileContext &ctx)
CHECKRESOLVED();
ABORT(ctx.Class);
int symlabel;
auto clstype = dyn_cast<PClassActor>(ctx.Class);
auto vclass = dyn_cast<PClassType>(ctx.Class);
assert(vclass != nullptr);
auto clstype = ValidateActor(vclass->Descriptor);
if (names[0] == NAME_None)
{
@ -10982,7 +11004,7 @@ FxExpression *FxMultiNameState::Resolve(FCompileContext &ctx)
}
else if (names[0] == NAME_Super)
{
scope = dyn_cast<PClassActor>(clstype->ParentClass);
scope = ValidateActor(clstype->ParentClass);
}
else
{

View file

@ -46,6 +46,8 @@
#include "actor.h"
#include "vmbuilder.h"
#include "scopebarrier.h"
#include "types.h"
#include "vmintern.h"
#define CHECKRESOLVED() if (isresolved) return this; isresolved=true;
@ -78,7 +80,7 @@ struct FCompileContext
FxCompoundStatement *Block = nullptr;
PPrototype *ReturnProto;
PFunction *Function; // The function that is currently being compiled (or nullptr for constant evaluation.)
PStruct *Class; // The type of the owning class.
PContainerType *Class; // The type of the owning class.
bool FromDecorate; // DECORATE must silence some warnings and demote some errors.
int StateIndex; // index in actor's state table for anonymous functions, otherwise -1 (not used by DECORATE which pre-resolves state indices)
int StateCount; // amount of states an anoymous function is being used on (must be 1 for state indices to be allowed.)
@ -90,7 +92,7 @@ struct FCompileContext
FString VersionString;
FCompileContext(PNamespace *spc, PFunction *func, PPrototype *ret, bool fromdecorate, int stateindex, int statecount, int lump, const VersionInfo &ver);
FCompileContext(PNamespace *spc, PStruct *cls, bool fromdecorate); // only to be used to resolve constants!
FCompileContext(PNamespace *spc, PContainerType *cls, bool fromdecorate); // only to be used to resolve constants!
PSymbol *FindInClass(FName identifier, PSymbolTable *&symt);
PSymbol *FindInSelfClass(FName identifier, PSymbolTable *&symt);
@ -333,10 +335,11 @@ public:
bool IsPointer() const { return ValueType->GetRegType() == REGT_POINTER; }
bool IsVector() const { return ValueType == TypeVector2 || ValueType == TypeVector3; };
bool IsBoolCompat() const { return ValueType->GetRegCount() == 1 && (ValueType->GetRegType() == REGT_INT || ValueType->GetRegType() == REGT_FLOAT || ValueType->GetRegType() == REGT_POINTER); }
bool IsObject() const { return ValueType->IsKindOf(RUNTIME_CLASS(PPointer)) && !ValueType->IsKindOf(RUNTIME_CLASS(PClassPointer)) && ValueType != TypeNullPtr && static_cast<PPointer*>(ValueType)->PointedType->IsKindOf(RUNTIME_CLASS(PClass)); }
bool IsObject() const { return ValueType->IsKindOf(RUNTIME_CLASS(PObjectPointer)); }
bool IsArray() const { return ValueType->IsKindOf(RUNTIME_CLASS(PArray)) || (ValueType->IsKindOf(RUNTIME_CLASS(PPointer)) && static_cast<PPointer*>(ValueType)->PointedType->IsKindOf(RUNTIME_CLASS(PArray))); }
bool IsResizableArray() const { return (ValueType->IsKindOf(RUNTIME_CLASS(PPointer)) && static_cast<PPointer*>(ValueType)->PointedType->IsKindOf(RUNTIME_CLASS(PStaticArray))); } // can only exist in pointer form.
bool IsDynamicArray() const { return (ValueType->IsKindOf(RUNTIME_CLASS(PDynArray))); }
bool IsNativeStruct() const { return (ValueType->IsA(RUNTIME_CLASS(PStruct)) && static_cast<PStruct*>(ValueType)->isNative); }
virtual ExpEmit Emit(VMFunctionBuilder *build);
void EmitStatement(VMFunctionBuilder *build);
@ -372,7 +375,7 @@ public:
FxIdentifier(FName i, const FScriptPosition &p);
FxExpression *Resolve(FCompileContext&);
FxExpression *ResolveMember(FCompileContext&, PStruct*, FxExpression*&, PStruct*);
FxExpression *ResolveMember(FCompileContext&, PContainerType*, FxExpression*&, PContainerType*);
};
@ -2004,7 +2007,7 @@ public:
class FxStateByIndex : public FxExpression
{
int index;
unsigned index;
public:

View file

@ -39,7 +39,9 @@
#include "tarray.h"
#include "dobject.h"
#include "thingdef.h"
#include "vm.h"
#include "types.h"
// We need one specific type for each of the 7 integral VM types and instantiate the needed functions for each of them.
// Dynamic arrays cannot hold structs because for every type there'd need to be an internal implementation which is impossible.
@ -97,7 +99,7 @@ DEFINE_ACTION_FUNCTION(FDynArray_I8, Delete)
{
PARAM_SELF_STRUCT_PROLOGUE(FDynArray_I8);
PARAM_INT(index);
PARAM_INT(count);
PARAM_INT_DEF(count);
self->Delete(index, count);
return 0;
}
@ -200,7 +202,7 @@ DEFINE_ACTION_FUNCTION(FDynArray_I16, Delete)
{
PARAM_SELF_STRUCT_PROLOGUE(FDynArray_I16);
PARAM_INT(index);
PARAM_INT(count);
PARAM_INT_DEF(count);
self->Delete(index, count);
return 0;
}
@ -303,7 +305,7 @@ DEFINE_ACTION_FUNCTION(FDynArray_I32, Delete)
{
PARAM_SELF_STRUCT_PROLOGUE(FDynArray_I32);
PARAM_INT(index);
PARAM_INT(count);
PARAM_INT_DEF(count);
self->Delete(index, count);
return 0;
}
@ -406,7 +408,7 @@ DEFINE_ACTION_FUNCTION(FDynArray_F32, Delete)
{
PARAM_SELF_STRUCT_PROLOGUE(FDynArray_F32);
PARAM_INT(index);
PARAM_INT(count);
PARAM_INT_DEF(count);
self->Delete(index, count);
return 0;
}
@ -509,7 +511,7 @@ DEFINE_ACTION_FUNCTION(FDynArray_F64, Delete)
{
PARAM_SELF_STRUCT_PROLOGUE(FDynArray_F64);
PARAM_INT(index);
PARAM_INT(count);
PARAM_INT_DEF(count);
self->Delete(index, count);
return 0;
}
@ -612,7 +614,7 @@ DEFINE_ACTION_FUNCTION(FDynArray_Ptr, Delete)
{
PARAM_SELF_STRUCT_PROLOGUE(FDynArray_Ptr);
PARAM_INT(index);
PARAM_INT(count);
PARAM_INT_DEF(count);
self->Delete(index, count);
return 0;
}
@ -716,7 +718,7 @@ DEFINE_ACTION_FUNCTION(FDynArray_String, Delete)
{
PARAM_SELF_STRUCT_PROLOGUE(FDynArray_String);
PARAM_INT(index);
PARAM_INT(count);
PARAM_INT_DEF(count);
self->Delete(index, count);
return 0;
}

View file

@ -1,5 +1,7 @@
#include "dobject.h"
#include "scopebarrier.h"
#include "types.h"
#include "vmintern.h"
// Note: the same object can't be both UI and Play. This is checked explicitly in the field construction and will cause esoteric errors here if found.
@ -175,14 +177,14 @@ void FScopeBarrier::AddFlags(int flags1, int flags2, const char* name)
// these are for vmexec.h
void FScopeBarrier::ValidateNew(PClass* cls, int outerside)
{
int innerside = FScopeBarrier::SideFromObjectFlags(cls->ObjectFlags);
int innerside = FScopeBarrier::SideFromObjectFlags(cls->VMType->ObjectFlags);
if ((outerside != innerside) && (innerside != FScopeBarrier::Side_PlainData)) // "cannot construct ui class ... from data context"
ThrowAbortException(X_OTHER, "Cannot construct %s class %s from %s context", FScopeBarrier::StringFromSide(innerside), cls->TypeName.GetChars(), FScopeBarrier::StringFromSide(outerside));
}
void FScopeBarrier::ValidateCall(PClass* selftype, VMFunction *calledfunc, int outerside)
{
int innerside = FScopeBarrier::SideFromObjectFlags(selftype->ObjectFlags);
int innerside = FScopeBarrier::SideFromObjectFlags(selftype->VMType->ObjectFlags);
if ((outerside != innerside) && (innerside != FScopeBarrier::Side_PlainData))
ThrowAbortException(X_OTHER, "Cannot call %s function %s from %s context", FScopeBarrier::StringFromSide(innerside), calledfunc->PrintableName.GetChars(), FScopeBarrier::StringFromSide(outerside));
}

View file

@ -35,8 +35,9 @@
#include "codegen.h"
#include "info.h"
#include "m_argv.h"
#include "thingdef.h"
//#include "thingdef.h"
#include "doomerrors.h"
#include "vmintern.h"
struct VMRemap
{

View file

@ -2,6 +2,7 @@
#define VMUTIL_H
#include "dobject.h"
#include "vmintern.h"
class VMFunctionBuilder;
class FxExpression;

View file

@ -34,6 +34,7 @@
#include "dobject.h"
#include "c_console.h"
#include "templates.h"
#include "vmintern.h"
#define NOP MODE_AUNUSED | MODE_BUNUSED | MODE_CUNUSED

View file

@ -86,7 +86,7 @@ static const char *RenderStyles[] =
"STYLE_Translucent",
"STYLE_Add",
//"STYLE_Shaded",
NULL
nullptr
};
// CODE --------------------------------------------------------------------
@ -124,14 +124,12 @@ void ParseOldDecoration(FScanner &sc, EDefinitionType def, PNamespace *ns)
bag.ClassName = type->TypeName;
#endif
type->GameFilter = GAME_Any;
sc.MustGetStringName("{");
memset (&extra, 0, sizeof(extra));
ParseInsideDecoration (bag, (AActor *)(type->Defaults), extra, def, sc, StateArray, SourceLines);
bag.Info->NumOwnedStates = StateArray.Size();
if (bag.Info->NumOwnedStates == 0)
if (StateArray.Size() == 0)
{
sc.ScriptError ("%s does not define any animation frames", typeName.GetChars() );
}
@ -155,17 +153,17 @@ void ParseOldDecoration(FScanner &sc, EDefinitionType def, PNamespace *ns)
FScriptPosition icepos = SourceLines[extra.IceDeathEnd - 1];
StateArray.Push (icecopy);
SourceLines.Push(icepos);
type->NumOwnedStates += 1;
}
type->OwnedStates = new FState[type->NumOwnedStates];
SaveStateSourceLines(type->OwnedStates, SourceLines);
memcpy (type->OwnedStates, &StateArray[0], type->NumOwnedStates * sizeof(type->OwnedStates[0]));
if (type->NumOwnedStates == 1)
FState *states;
states = (FState*)ClassDataAllocator.Alloc(StateArray.Size() * sizeof(FState));
SaveStateSourceLines(states, SourceLines);
memcpy (states, &StateArray[0], StateArray.Size() * sizeof(states[0]));
if (StateArray.Size() == 1)
{
type->OwnedStates->Tics = -1;
type->OwnedStates->TicRange = 0;
type->OwnedStates->Misc1 = 0;
states->Tics = -1;
states->TicRange = 0;
states->Misc1 = 0;
}
else
{
@ -174,50 +172,51 @@ void ParseOldDecoration(FScanner &sc, EDefinitionType def, PNamespace *ns)
// Spawn states loop endlessly
for (i = extra.SpawnStart; i < extra.SpawnEnd-1; ++i)
{
type->OwnedStates[i].NextState = &type->OwnedStates[i+1];
states[i].NextState = &states[i+1];
}
type->OwnedStates[i].NextState = &type->OwnedStates[extra.SpawnStart];
states[i].NextState = &states[extra.SpawnStart];
// Death states are one-shot and freeze on the final state
if (extra.DeathEnd != 0)
{
for (i = extra.DeathStart; i < extra.DeathEnd-1; ++i)
{
type->OwnedStates[i].NextState = &type->OwnedStates[i+1];
states[i].NextState = &states[i+1];
}
FState *state = &states[i];
if (extra.bDiesAway || def == DEF_Projectile)
{
type->OwnedStates[i].NextState = NULL;
state->NextState = nullptr;
}
else
{
type->OwnedStates[i].Tics = -1;
type->OwnedStates[i].TicRange = 0;
type->OwnedStates[i].Misc1 = 0;
state->Tics = -1;
state->TicRange = 0;
state->Misc1 = 0;
}
if (def == DEF_Projectile)
{
if (extra.bExplosive)
{
type->OwnedStates[extra.DeathStart].SetAction("A_Explode");
states[extra.DeathStart].SetAction("A_Explode");
}
}
else
{
// The first frame plays the death sound and
// the second frame makes it nonsolid.
type->OwnedStates[extra.DeathStart].SetAction("A_Scream");
states[extra.DeathStart].SetAction("A_Scream");
if (extra.bSolidOnDeath)
{
}
else if (extra.DeathStart + 1 < extra.DeathEnd)
{
type->OwnedStates[extra.DeathStart+1].SetAction("A_NoBlocking");
states[extra.DeathStart+1].SetAction("A_NoBlocking");
}
else
{
type->OwnedStates[extra.DeathStart].SetAction("A_ScreamAndUnblock");
states[extra.DeathStart].SetAction("A_ScreamAndUnblock");
}
if (extra.DeathHeight == 0)
@ -226,7 +225,7 @@ void ParseOldDecoration(FScanner &sc, EDefinitionType def, PNamespace *ns)
}
((AActor*)(type->Defaults))->FloatVar("DeathHeight") = extra.DeathHeight;
}
bag.statedef.SetStateLabel("Death", &type->OwnedStates[extra.DeathStart]);
bag.statedef.SetStateLabel("Death", &states[extra.DeathStart]);
}
// Burn states are the same as death states, except they can optionally terminate
@ -234,38 +233,39 @@ void ParseOldDecoration(FScanner &sc, EDefinitionType def, PNamespace *ns)
{
for (i = extra.FireDeathStart; i < extra.FireDeathEnd-1; ++i)
{
type->OwnedStates[i].NextState = &type->OwnedStates[i+1];
states[i].NextState = &states[i+1];
}
FState *state = &states[i];
if (extra.bBurnAway)
{
type->OwnedStates[i].NextState = NULL;
state->NextState = nullptr;
}
else
{
type->OwnedStates[i].Tics = -1;
type->OwnedStates[i].TicRange = 0;
type->OwnedStates[i].Misc1 = 0;
state->Tics = -1;
state->TicRange = 0;
state->Misc1 = 0;
}
// The first frame plays the burn sound and
// the second frame makes it nonsolid.
type->OwnedStates[extra.FireDeathStart].SetAction("A_ActiveSound");
states[extra.FireDeathStart].SetAction("A_ActiveSound");
if (extra.bSolidOnBurn)
{
}
else if (extra.FireDeathStart + 1 < extra.FireDeathEnd)
{
type->OwnedStates[extra.FireDeathStart+1].SetAction("A_NoBlocking");
states[extra.FireDeathStart+1].SetAction("A_NoBlocking");
}
else
{
type->OwnedStates[extra.FireDeathStart].SetAction("A_ActiveAndUnblock");
states[extra.FireDeathStart].SetAction("A_ActiveAndUnblock");
}
if (extra.BurnHeight == 0) extra.BurnHeight = ((AActor*)(type->Defaults))->Height;
((AActor*)(type->Defaults))->FloatVar("BurnHeight") = extra.BurnHeight;
bag.statedef.SetStateLabel("Burn", &type->OwnedStates[extra.FireDeathStart]);
bag.statedef.SetStateLabel("Burn", &states[extra.FireDeathStart]);
}
// Ice states are similar to burn and death, except their final frame enters
@ -274,21 +274,22 @@ void ParseOldDecoration(FScanner &sc, EDefinitionType def, PNamespace *ns)
{
for (i = extra.IceDeathStart; i < extra.IceDeathEnd-1; ++i)
{
type->OwnedStates[i].NextState = &type->OwnedStates[i+1];
states[i].NextState = &states[i+1];
}
type->OwnedStates[i].NextState = &type->OwnedStates[type->NumOwnedStates-1];
type->OwnedStates[i].Tics = 5;
type->OwnedStates[i].TicRange = 0;
type->OwnedStates[i].Misc1 = 0;
type->OwnedStates[i].SetAction("A_FreezeDeath");
FState *state = &states[i];
state->NextState = &states[StateArray.Size() - 1];
state->Tics = 5;
state->TicRange = 0;
state->Misc1 = 0;
state->SetAction("A_FreezeDeath");
i = type->NumOwnedStates - 1;
type->OwnedStates[i].NextState = &type->OwnedStates[i];
type->OwnedStates[i].Tics = 1;
type->OwnedStates[i].TicRange = 0;
type->OwnedStates[i].Misc1 = 0;
type->OwnedStates[i].SetAction("A_FreezeDeathChunks");
bag.statedef.SetStateLabel("Ice", &type->OwnedStates[extra.IceDeathStart]);
i = StateArray.Size() - 1;
state->NextState = &states[i];
state->Tics = 1;
state->TicRange = 0;
state->Misc1 = 0;
state->SetAction("A_FreezeDeathChunks");
bag.statedef.SetStateLabel("Ice", &states[extra.IceDeathStart]);
}
else if (extra.bGenericIceDeath)
{
@ -303,8 +304,10 @@ void ParseOldDecoration(FScanner &sc, EDefinitionType def, PNamespace *ns)
{
((AActor *)(type->Defaults))->flags |= MF_DROPOFF|MF_MISSILE;
}
bag.statedef.SetStateLabel("Spawn", &type->OwnedStates[extra.SpawnStart]);
bag.statedef.SetStateLabel("Spawn", &states[extra.SpawnStart]);
bag.statedef.InstallStates (type, ((AActor *)(type->Defaults)));
bag.Info->ActorInfo()->OwnedStates = states;
bag.Info->ActorInfo()->NumOwnedStates = StateArray.Size();
}
//==========================================================================
@ -331,7 +334,7 @@ static void ParseInsideDecoration (Baggage &bag, AActor *defaults,
{
sc.ScriptError ("DoomEdNum must be in the range [-1,32767]");
}
bag.Info->DoomEdNum = (int16_t)sc.Number;
bag.Info->ActorInfo()->DoomEdNum = (int16_t)sc.Number;
}
else if (sc.Compare ("SpawnNum"))
{
@ -340,7 +343,7 @@ static void ParseInsideDecoration (Baggage &bag, AActor *defaults,
{
sc.ScriptError ("SpawnNum must be in the range [0,255]");
}
bag.Info->SpawnID = (uint8_t)sc.Number;
bag.Info->ActorInfo()->SpawnID = (uint8_t)sc.Number;
}
else if (sc.Compare ("Sprite") || (
(def == DEF_BreakableDecoration || def == DEF_Projectile) &&
@ -558,11 +561,11 @@ static void ParseInsideDecoration (Baggage &bag, AActor *defaults,
}
else if (sc.String[0] != '*')
{
HandleActorFlag(sc, bag, sc.String, NULL, '+');
HandleActorFlag(sc, bag, sc.String, nullptr, '+');
}
else
{
sc.ScriptError (NULL);
sc.ScriptError (nullptr);
}
sc.MustGetString ();
}
@ -619,9 +622,9 @@ static void ParseSpriteFrames (PClassActor *info, TArray<FState> &states, TArray
char *token = strtok (sc.String, ",\t\n\r");
memset (&state, 0, sizeof(state));
state.UseFlags = info->DefaultStateUsage;
state.UseFlags = info->ActorInfo()->DefaultStateUsage;
while (token != NULL)
while (token != nullptr)
{
// Skip leading white space
while (*token == ' ')
@ -631,7 +634,7 @@ static void ParseSpriteFrames (PClassActor *info, TArray<FState> &states, TArray
bool firstState = true;
char *colon = strchr (token, ':');
if (colon != NULL)
if (colon != nullptr)
{
char *stop;
@ -682,7 +685,7 @@ static void ParseSpriteFrames (PClassActor *info, TArray<FState> &states, TArray
SourceLines.Push(sc);
}
token = strtok (NULL, ",\t\n\r");
token = strtok (nullptr, ",\t\n\r");
}
}

View file

@ -88,7 +88,7 @@ FxExpression *ParseExpression (FScanner &sc, PClassActor *cls, PNamespace *spc)
if (spc)
{
FCompileContext ctx(spc, cls, true);
FCompileContext ctx(spc, cls->VMType, true);
data = data->Resolve(ctx);
}
@ -505,7 +505,7 @@ static FxExpression *ParseExpression0 (FScanner &sc, PClassActor *cls)
default:
if (cls != nullptr)
{
func = dyn_cast<PFunction>(cls->Symbols.FindSymbol(identifier, true));
func = dyn_cast<PFunction>(cls->FindSymbol(identifier, true));
// There is an action function ACS_NamedExecuteWithResult which must be ignored here for this to work.
if (func != nullptr && identifier != NAME_ACS_NamedExecuteWithResult)

View file

@ -69,9 +69,9 @@ EXTERN_CVAR(Bool, strictdecorate);
PClassActor *DecoDerivedClass(const FScriptPosition &sc, PClassActor *parent, FName typeName)
{
if (parent->mVersion > MakeVersion(2, 0))
if (parent->VMType->mVersion > MakeVersion(2, 0))
{
sc.Message(MSG_ERROR, "Parent class %s of %s not accessible to DECORATE", parent->GetClass()->TypeName.GetChars(), typeName.GetChars());
sc.Message(MSG_ERROR, "Parent class %s of %s not accessible to DECORATE", parent->TypeName.GetChars(), typeName.GetChars());
}
PClassActor *type = static_cast<PClassActor *>(parent->CreateDerivedClass(typeName, parent->Size));
if (type == nullptr)
@ -101,7 +101,8 @@ PClassActor *DecoDerivedClass(const FScriptPosition &sc, PClassActor *parent, FN
if (type != nullptr)
{
// [ZZ] DECORATE classes are always play
type->ObjectFlags = FScopeBarrier::ChangeSideInObjectFlags(type->ObjectFlags, FScopeBarrier::Side_Play);
auto vmtype = type->VMType;
vmtype->ObjectFlags = FScopeBarrier::ChangeSideInObjectFlags(vmtype->ObjectFlags, FScopeBarrier::Side_Play);
}
return type;
@ -582,7 +583,7 @@ static FState *CheckState(FScanner &sc, PClass *type)
FState *state = NULL;
sc.MustGetString();
PClassActor *info = dyn_cast<PClassActor>(type->ParentClass);
PClassActor *info = ValidateActor(type->ParentClass);
if (info != NULL)
{
@ -964,7 +965,7 @@ static void ParseActorProperty(FScanner &sc, Baggage &bag)
FName name(propname, true);
if (name != NAME_None)
{
auto propp = dyn_cast<PProperty>(bag.Info->Symbols.FindSymbol(name, true));
auto propp = dyn_cast<PProperty>(bag.Info->FindSymbol(name, true));
if (propp != nullptr)
{
DispatchScriptProperty(sc, propp, (AActor *)bag.Info->Defaults, bag);
@ -999,7 +1000,7 @@ PClassActor *CreateNewActor(const FScriptPosition &sc, FName typeName, FName par
sc.Message(MSG_ERROR, "'%s' inherits from a class with the same name", typeName.GetChars());
break;
}
p = dyn_cast<PClassActor>(p->ParentClass);
p = ValidateActor(p->ParentClass);
}
if (parent == NULL)
@ -1016,8 +1017,7 @@ PClassActor *CreateNewActor(const FScriptPosition &sc, FName typeName, FName par
ti = DecoDerivedClass(sc, parent, typeName);
ti->bDecorateClass = true; // we only set this for 'modern' DECORATE. The original stuff is so limited that it cannot do anything that may require flagging.
ti->Replacee = ti->Replacement = NULL;
ti->DoomEdNum = -1;
ti->ActorInfo()->DoomEdNum = -1;
return ti;
}
@ -1109,7 +1109,7 @@ static PClassActor *ParseActorHeader(FScanner &sc, Baggage *bag)
try
{
PClassActor *info = CreateNewActor(sc, typeName, parentName);
info->DoomEdNum = DoomEdNum > 0 ? DoomEdNum : -1;
info->ActorInfo()->DoomEdNum = DoomEdNum > 0 ? DoomEdNum : -1;
info->SourceLumpName = Wads.GetLumpFullPath(sc.LumpNum);
if (!info->SetReplacement(replaceName))
@ -1117,7 +1117,7 @@ static PClassActor *ParseActorHeader(FScanner &sc, Baggage *bag)
sc.ScriptMessage("Replaced type '%s' not found for %s", replaceName.GetChars(), info->TypeName.GetChars());
}
ResetBaggage (bag, info == RUNTIME_CLASS(AActor) ? NULL : static_cast<PClassActor *>(info->ParentClass));
ResetBaggage (bag, ValidateActor(info->ParentClass));
bag->Info = info;
bag->Lumpnum = sc.LumpNum;
#ifdef _DEBUG
@ -1152,15 +1152,15 @@ static void ParseActor(FScanner &sc, PNamespace *ns)
switch (sc.TokenType)
{
case TK_Const:
ParseConstant (sc, &info->Symbols, info, ns);
ParseConstant (sc, &info->VMType->Symbols, info, ns);
break;
case TK_Enum:
ParseEnum (sc, &info->Symbols, info, ns);
ParseEnum (sc, &info->VMType->Symbols, info, ns);
break;
case TK_Var:
ParseUserVariable (sc, &info->Symbols, info, ns);
ParseUserVariable (sc, &info->VMType->Symbols, info, ns);
break;
case TK_Identifier:

View file

@ -97,7 +97,7 @@ FxVMFunctionCall *DoActionSpecials(FScanner &sc, FState & state, Baggage &bag)
{
sc.ScriptError ("Too many arguments to %s", specname.GetChars());
}
auto f = dyn_cast<PFunction>(RUNTIME_CLASS(AActor)->Symbols.FindSymbol("A_CallSpecial", false));
auto f = dyn_cast<PFunction>(RUNTIME_CLASS(AActor)->FindSymbol("A_CallSpecial", false));
assert(f != nullptr);
return new FxVMFunctionCall(new FxSelf(sc), f, args, sc, false);
}
@ -142,7 +142,7 @@ void ParseStates(FScanner &sc, PClassActor * actor, AActor * defaults, Baggage &
char lastsprite[5] = "";
FxExpression *ScriptCode;
FArgumentList *args = nullptr;
int flagdef = actor->DefaultStateUsage;
int flagdef = actor->ActorInfo()->DefaultStateUsage;
FScriptPosition scp;
if (sc.CheckString("("))
@ -339,7 +339,7 @@ do_stop:
endofstate:
if (ScriptCode != nullptr)
{
auto funcsym = CreateAnonymousFunction(actor, nullptr, state.UseFlags);
auto funcsym = CreateAnonymousFunction(actor->VMType, nullptr, state.UseFlags);
state.ActionFunc = FunctionBuildList.AddFunction(bag.Namespace, bag.Version, funcsym, ScriptCode, FStringf("%s.StateFunction.%d", actor->TypeName.GetChars(), bag.statedef.GetStateCount()), true, bag.statedef.GetStateCount(), int(statestring.Len()), sc.LumpNum);
}
int count = bag.statedef.AddStates(&state, statestring, scp);
@ -583,7 +583,7 @@ FxVMFunctionCall *ParseAction(FScanner &sc, FState state, FString statestring, B
FName symname = FName(sc.String, true);
symname = CheckCastKludges(symname);
PFunction *afd = dyn_cast<PFunction>(bag.Info->Symbols.FindSymbol(symname, true));
PFunction *afd = dyn_cast<PFunction>(bag.Info->FindSymbol(symname, true));
if (afd != NULL)
{
FArgumentList args;

View file

@ -36,6 +36,10 @@
#include <float.h>
#include "dobject.h"
#include "i_system.h"
#include "templates.h"
#include "serializer.h"
#include "types.h"
#include "vm.h"
// PUBLIC DATA DEFINITIONS -------------------------------------------------
@ -102,7 +106,7 @@ unsigned PFunction::AddVariant(PPrototype *proto, TArray<uint32_t> &argflags, TA
assert(proto->ArgumentTypes.Size() > 0);
auto selftypeptr = dyn_cast<PPointer>(proto->ArgumentTypes[0]);
assert(selftypeptr != nullptr);
variant.SelfClass = dyn_cast<PStruct>(selftypeptr->PointedType);
variant.SelfClass = dyn_cast<PContainerType>(selftypeptr->PointedType);
assert(variant.SelfClass != nullptr);
}
else
@ -126,6 +130,80 @@ int PFunction::GetImplicitArgs()
return 0;
}
/* PField *****************************************************************/
IMPLEMENT_CLASS(PField, false, false)
//==========================================================================
//
// PField - Default Constructor
//
//==========================================================================
PField::PField()
: PSymbol(NAME_None), Offset(0), Type(nullptr), Flags(0)
{
}
PField::PField(FName name, PType *type, uint32_t flags, size_t offset, int bitvalue)
: PSymbol(name), Offset(offset), Type(type), Flags(flags)
{
if (bitvalue != 0)
{
BitValue = 0;
unsigned val = bitvalue;
while ((val >>= 1)) BitValue++;
if (type->IsA(RUNTIME_CLASS(PInt)) && unsigned(BitValue) < 8u * type->Size)
{
// map to the single bytes in the actual variable. The internal bit instructions operate on 8 bit values.
#ifndef __BIG_ENDIAN__
Offset += BitValue / 8;
#else
Offset += type->Size - 1 - BitValue / 8;
#endif
BitValue &= 7;
Type = TypeBool;
}
else
{
// Just abort. Bit fields should only be defined internally.
I_Error("Trying to create an invalid bit field element: %s", name.GetChars());
}
}
else BitValue = -1;
}
VersionInfo PField::GetVersion()
{
VersionInfo Highest = { 0,0,0 };
if (!(Flags & VARF_Deprecated)) Highest = mVersion;
if (Type->mVersion > Highest) Highest = Type->mVersion;
return Highest;
}
/* PProperty *****************************************************************/
IMPLEMENT_CLASS(PProperty, false, false)
//==========================================================================
//
// PField - Default Constructor
//
//==========================================================================
PProperty::PProperty()
: PSymbol(NAME_None)
{
}
PProperty::PProperty(FName name, TArray<PField *> &fields)
: PSymbol(name)
{
Variables = std::move(fields);
}
//==========================================================================
//
//
@ -238,6 +316,123 @@ PSymbol *PSymbolTable::AddSymbol (PSymbol *sym)
//
//==========================================================================
PField *PSymbolTable::AddField(FName name, PType *type, uint32_t flags, unsigned &Size, unsigned *Align)
{
PField *field = new PField(name, type, flags);
// The new field is added to the end of this struct, alignment permitting.
field->Offset = (Size + (type->Align - 1)) & ~(type->Align - 1);
// Enlarge this struct to enclose the new field.
Size = unsigned(field->Offset + type->Size);
// This struct's alignment is the same as the largest alignment of any of
// its fields.
if (Align != nullptr)
{
*Align = MAX(*Align, type->Align);
}
if (AddSymbol(field) == nullptr)
{ // name is already in use
field->Destroy();
return nullptr;
}
return field;
}
//==========================================================================
//
// PStruct :: AddField
//
// Appends a new native field to the struct. Returns either the new field
// or nullptr if a symbol by that name already exists.
//
//==========================================================================
PField *PSymbolTable::AddNativeField(FName name, PType *type, size_t address, uint32_t flags, int bitvalue)
{
PField *field = new PField(name, type, flags | VARF_Native | VARF_Transient, address, bitvalue);
if (AddSymbol(field) == nullptr)
{ // name is already in use
field->Destroy();
return nullptr;
}
return field;
}
//==========================================================================
//
// PClass :: WriteFields
//
//==========================================================================
void PSymbolTable::WriteFields(FSerializer &ar, const void *addr, const void *def) const
{
auto it = MapType::ConstIterator(Symbols);
MapType::ConstPair *pair;
while (it.NextPair(pair))
{
const PField *field = dyn_cast<PField>(pair->Value);
// Skip fields without or with native serialization
if (field && !(field->Flags & (VARF_Transient | VARF_Meta)))
{
// todo: handle defaults in WriteValue
//auto defp = def == nullptr ? nullptr : (const uint8_t *)def + field->Offset;
field->Type->WriteValue(ar, field->SymbolName.GetChars(), (const uint8_t *)addr + field->Offset);
}
}
}
//==========================================================================
//
// PClass :: ReadFields
//
//==========================================================================
bool PSymbolTable::ReadFields(FSerializer &ar, void *addr, const char *TypeName) const
{
bool readsomething = false;
bool foundsomething = false;
const char *label;
while ((label = ar.GetKey()))
{
foundsomething = true;
const PSymbol *sym = FindSymbol(FName(label, true), false);
if (sym == nullptr)
{
DPrintf(DMSG_ERROR, "Cannot find field %s in %s\n",
label, TypeName);
}
else if (!sym->IsKindOf(RUNTIME_CLASS(PField)))
{
DPrintf(DMSG_ERROR, "Symbol %s in %s is not a field\n",
label, TypeName);
}
else if ((static_cast<const PField *>(sym)->Flags & (VARF_Transient | VARF_Meta)))
{
DPrintf(DMSG_ERROR, "Symbol %s in %s is not a serializable field\n",
label, TypeName);
}
else
{
readsomething |= static_cast<const PField *>(sym)->Type->ReadValue(ar, nullptr,
(uint8_t *)addr + static_cast<const PField *>(sym)->Offset);
}
}
return readsomething || !foundsomething;
}
//==========================================================================
//
//
//
//==========================================================================
void PSymbolTable::RemoveSymbol(PSymbol *sym)
{
auto mysym = Symbols.CheckKey(sym->SymbolName);
@ -387,7 +582,7 @@ void RemoveUnusedSymbols()
{
for (PType *ty = TypeTable.TypeHash[i]; ty != nullptr; ty = ty->HashNext)
{
if (ty->IsKindOf(RUNTIME_CLASS(PStruct)))
if (ty->IsKindOf(RUNTIME_CLASS(PContainerType)))
{
auto it = ty->Symbols.GetIterator();
PSymbolTable::MapType::Pair *pair;

View file

@ -10,7 +10,7 @@ class VMFunction;
class PType;
class PPrototype;
struct ZCC_TreeNode;
class PStruct;
class PContainerType;
// Symbol information -------------------------------------------------------
@ -175,15 +175,15 @@ public:
TArray<FName> ArgNames; // we need the names to access them later when the function gets compiled.
uint32_t Flags;
int UseFlags;
PStruct *SelfClass;
PContainerType *SelfClass;
};
TArray<Variant> Variants;
PStruct *OwningClass = nullptr;
PContainerType *OwningClass = nullptr;
unsigned AddVariant(PPrototype *proto, TArray<uint32_t> &argflags, TArray<FName> &argnames, VMFunction *impl, int flags, int useflags);
int GetImplicitArgs();
PFunction(PStruct *owner = nullptr, FName name = NAME_None) : PSymbol(name), OwningClass(owner) {}
PFunction(PContainerType *owner = nullptr, FName name = NAME_None) : PSymbol(name), OwningClass(owner) {}
};
// A symbol table -----------------------------------------------------------
@ -215,6 +215,10 @@ struct PSymbolTable
// a symbol with the same name is already in the table. This symbol is
// not copied and will be freed when the symbol table is destroyed.
PSymbol *AddSymbol (PSymbol *sym);
PField *AddField(FName name, PType *type, uint32_t flags, unsigned &Size, unsigned *Align = nullptr);
PField *AddNativeField(FName name, PType *type, size_t address, uint32_t flags, int bitvalue);
bool ReadFields(FSerializer &ar, void *addr, const char *TypeName) const;
void WriteFields(FSerializer &ar, const void *addr, const void *def = nullptr) const;
// Similar to AddSymbol but always succeeds. Returns the symbol that used
// to be in the table with this name, if any.
@ -270,5 +274,4 @@ struct FNamespaceManager
};
extern FNamespaceManager Namespaces;
void RemoveUnusedSymbols();

View file

@ -59,7 +59,7 @@
#include "a_weapons.h"
#include "p_conversation.h"
#include "v_text.h"
#include "thingdef.h"
//#include "thingdef.h"
#include "backend/codegen.h"
#include "a_sharedglobal.h"
#include "backend/vmbuilder.h"
@ -101,7 +101,7 @@ FScriptPosition & GetStateSource(FState *state)
//
//==========================================================================
void SetImplicitArgs(TArray<PType *> *args, TArray<uint32_t> *argflags, TArray<FName> *argnames, PStruct *cls, uint32_t funcflags, int useflags)
void SetImplicitArgs(TArray<PType *> *args, TArray<uint32_t> *argflags, TArray<FName> *argnames, PContainerType *cls, uint32_t funcflags, int useflags)
{
// Must be called before adding any other arguments.
assert(args == nullptr || args->Size() == 0);
@ -154,7 +154,7 @@ void SetImplicitArgs(TArray<PType *> *args, TArray<uint32_t> *argflags, TArray<F
//
//==========================================================================
PFunction *CreateAnonymousFunction(PClass *containingclass, PType *returntype, int flags)
PFunction *CreateAnonymousFunction(PContainerType *containingclass, PType *returntype, int flags)
{
TArray<PType *> rets(1);
TArray<PType *> args;
@ -184,7 +184,7 @@ PFunction *CreateAnonymousFunction(PClass *containingclass, PType *returntype, i
//
//==========================================================================
PFunction *FindClassMemberFunction(PStruct *selfcls, PStruct *funccls, FName name, FScriptPosition &sc, bool *error)
PFunction *FindClassMemberFunction(PContainerType *selfcls, PContainerType *funccls, FName name, FScriptPosition &sc, bool *error)
{
// Skip ACS_NamedExecuteWithResult. Anything calling this should use the builtin instead.
if (name == NAME_ACS_NamedExecuteWithResult) return nullptr;
@ -195,8 +195,8 @@ PFunction *FindClassMemberFunction(PStruct *selfcls, PStruct *funccls, FName nam
if (symbol != nullptr)
{
PClass* cls_ctx = dyn_cast<PClass>(funccls);
PClass* cls_target = funcsym?dyn_cast<PClass>(funcsym->OwningClass):nullptr;
auto cls_ctx = dyn_cast<PClassType>(funccls);
auto cls_target = funcsym ? dyn_cast<PClassType>(funcsym->OwningClass) : nullptr;
if (funcsym == nullptr)
{
sc.Message(MSG_ERROR, "%s is not a member function of %s", name.GetChars(), selfcls->TypeName.GetChars());
@ -206,7 +206,7 @@ PFunction *FindClassMemberFunction(PStruct *selfcls, PStruct *funccls, FName nam
// private access is only allowed if the symbol table belongs to the class in which the current function is being defined.
sc.Message(MSG_ERROR, "%s is declared private and not accessible", symbol->SymbolName.GetChars());
}
else if ((funcsym->Variants[0].Flags & VARF_Protected) && symtable != &funccls->Symbols && (!cls_ctx || !cls_target || !cls_ctx->IsDescendantOf((PClass*)cls_target)))
else if ((funcsym->Variants[0].Flags & VARF_Protected) && symtable != &funccls->Symbols && (!cls_ctx || !cls_target || !cls_ctx->Descriptor->IsDescendantOf(cls_target->Descriptor)))
{
sc.Message(MSG_ERROR, "%s is declared protected and not accessible", symbol->SymbolName.GetChars());
}
@ -236,7 +236,7 @@ void CreateDamageFunction(PNamespace *OutNamespace, const VersionInfo &ver, PCla
else
{
auto dmg = new FxReturnStatement(new FxIntCast(id, true), id->ScriptPosition);
auto funcsym = CreateAnonymousFunction(info, TypeSInt32, 0);
auto funcsym = CreateAnonymousFunction(info->VMType, TypeSInt32, 0);
defaults->DamageFunc = FunctionBuildList.AddFunction(OutNamespace, ver, funcsym, dmg, FStringf("%s.DamageFunction", info->TypeName.GetChars()), fromDecorate, -1, 0, lumpnum);
}
}
@ -282,9 +282,8 @@ static void CheckForUnsafeStates(PClassActor *obj)
if (state->ActionFunc && state->ActionFunc->Unsafe)
{
// If an unsafe function (i.e. one that accesses user variables) is being detected, print a warning once and remove the bogus function. We may not call it because that would inevitably crash.
auto owner = FState::StaticFindStateOwner(state);
GetStateSource(state).Message(MSG_ERROR, TEXTCOLOR_RED "Unsafe state call in state %s.%d which accesses user variables, reached by %s.%s.\n",
owner->TypeName.GetChars(), int(state - owner->OwnedStates), obj->TypeName.GetChars(), FName(*test).GetChars());
GetStateSource(state).Message(MSG_ERROR, TEXTCOLOR_RED "Unsafe state call in state %s which accesses user variables, reached by %s.%s.\n",
FState::StaticGetStateName(state), obj->TypeName.GetChars(), FName(*test).GetChars());
}
state = state->NextState;
}
@ -308,9 +307,8 @@ static void CheckLabel(PClassActor *obj, FStateLabel *slb, int useflag, FName st
{
if (!(state->UseFlags & useflag))
{
auto owner = FState::StaticFindStateOwner(state);
GetStateSource(state).Message(MSG_ERROR, TEXTCOLOR_RED "%s references state %s.%d as %s state, but this state is not flagged for use as %s.\n",
obj->TypeName.GetChars(), owner->TypeName.GetChars(), int(state - owner->OwnedStates), statename.GetChars(), descript);
GetStateSource(state).Message(MSG_ERROR, TEXTCOLOR_RED "%s references state %s as %s state, but this state is not flagged for use as %s.\n",
obj->TypeName.GetChars(), FState::StaticGetStateName(state), statename.GetChars(), descript);
}
}
if (slb->Children != nullptr)
@ -325,7 +323,7 @@ static void CheckLabel(PClassActor *obj, FStateLabel *slb, int useflag, FName st
static void CheckStateLabels(PClassActor *obj, ENamedName *test, int useflag, const char *descript)
{
FStateLabels *labels = obj->StateList;
FStateLabels *labels = obj->GetStateLabels();
for (; *test != NAME_None; test++)
{
@ -355,13 +353,13 @@ static void CheckStates(PClassActor *obj)
{
CheckStateLabels(obj, pickupstates, SUF_ITEM, "CustomInventory state chain");
}
for (int i = 0; i < obj->NumOwnedStates; i++)
for (unsigned i = 0; i < obj->GetStateCount(); i++)
{
auto state = obj->OwnedStates + i;
auto state = obj->GetStates() + i;
if (state->NextState && (state->UseFlags & state->NextState->UseFlags) != state->UseFlags)
{
GetStateSource(state).Message(MSG_ERROR, TEXTCOLOR_RED "State %s.%d links to a state with incompatible restrictions.\n",
obj->TypeName.GetChars(), int(state - obj->OwnedStates));
GetStateSource(state).Message(MSG_ERROR, TEXTCOLOR_RED "State %s links to a state with incompatible restrictions.\n",
FState::StaticGetStateName(state));
}
}
}
@ -375,6 +373,7 @@ static void CheckStates(PClassActor *obj)
//==========================================================================
void ParseScripts();
void ParseAllDecorate();
void SynthesizeFlagFields();
void LoadActors()
{
@ -389,6 +388,7 @@ void LoadActors()
FScriptPosition::StrictErrors = false;
ParseAllDecorate();
SynthesizeFlagFields();
FunctionBuildList.Build();
@ -403,7 +403,7 @@ void LoadActors()
auto ti = PClassActor::AllActorClasses[i];
if (ti->Size == TentativeClass)
{
if (ti->ObjectFlags & OF_Transient)
if (ti->bOptional)
{
Printf(TEXTCOLOR_ORANGE "Class %s referenced but not defined\n", ti->TypeName.GetChars());
FScriptPosition::WarnCounter++;

View file

@ -6,6 +6,7 @@
#include "s_sound.h"
#include "sc_man.h"
#include "cmdlib.h"
#include "vm.h"
class FScanner;
@ -148,8 +149,8 @@ inline void ResetBaggage (Baggage *bag, PClassActor *stateclass)
//
//==========================================================================
AFuncDesc *FindFunction(PStruct *cls, const char * string);
FieldDesc *FindField(PStruct *cls, const char * string);
AFuncDesc *FindFunction(PContainerType *cls, const char * string);
FieldDesc *FindField(PContainerType *cls, const char * string);
FxExpression *ParseExpression(FScanner &sc, PClassActor *cls, PNamespace *resolvenspc = nullptr);
@ -159,9 +160,9 @@ void ParseFunctionParameters(FScanner &sc, PClassActor *cls, TArray<FxExpression
FxExpression *ParseActions(FScanner &sc, FState state, FString statestring, Baggage &bag, bool &endswithret);
class FxVMFunctionCall *ParseAction(FScanner &sc, FState state, FString statestring, Baggage &bag);
FName CheckCastKludges(FName in);
void SetImplicitArgs(TArray<PType *> *args, TArray<uint32_t> *argflags, TArray<FName> *argnames, PStruct *cls, uint32_t funcflags, int useflags);
PFunction *CreateAnonymousFunction(PClass *containingclass, PType *returntype, int flags);
PFunction *FindClassMemberFunction(PStruct *cls, PStruct *funccls, FName name, FScriptPosition &sc, bool *error);
void SetImplicitArgs(TArray<PType *> *args, TArray<uint32_t> *argflags, TArray<FName> *argnames, PContainerType *cls, uint32_t funcflags, int useflags);
PFunction *CreateAnonymousFunction(PContainerType *containingclass, PType *returntype, int flags);
PFunction *FindClassMemberFunction(PContainerType *cls, PContainerType *funccls, FName name, FScriptPosition &sc, bool *error);
void CreateDamageFunction(PNamespace *ns, const VersionInfo &ver, PClassActor *info, AActor *defaults, FxExpression *id, bool fromDecorate, int lumpnum);
//==========================================================================

View file

@ -61,13 +61,22 @@
#include "serializer.h"
#include "wi_stuff.h"
#include "a_dynlight.h"
#include "vm.h"
#include "types.h"
static TArray<FPropertyInfo*> properties;
static TArray<AFuncDesc> AFTable;
static TArray<FieldDesc> FieldTable;
extern int BackbuttonTime;
extern float BackbuttonAlpha;
static AWeapon *wpnochg;
// Argh. It sucks when bad hacks need to be supported. WP_NOCHANGE is just a bogus pointer but is used everywhere as a special flag.
// It cannot be defined as constant because constants can either be numbers or strings but nothing else, so the only 'solution'
// is to create a static variable from it that points to an otherwise unused object and reference that in the script. Yuck!!!
// This must point to a valid DObject derived object so that the garbage collector can deal with it.
// The global VM types are the most convenient options here because they get created before the compiler is started and they
// are not exposed in other ways to scripts - and they do not change unless the engine is shut down.
DEFINE_GLOBAL_NAMED(TypeSInt32, wp_nochange);
//==========================================================================
//
@ -505,6 +514,7 @@ static const struct FFlagList { const PClass * const *Type; FFlagDef *Defs; int
{ &RUNTIME_CLASS_CASTLESS(AInventory), InventoryFlagDefs, countof(InventoryFlagDefs), 3 },
{ &RUNTIME_CLASS_CASTLESS(AWeapon), WeaponFlagDefs, countof(WeaponFlagDefs), 3 },
{ &RUNTIME_CLASS_CASTLESS(APlayerPawn), PlayerPawnFlagDefs, countof(PlayerPawnFlagDefs), 3 },
{ &RUNTIME_CLASS_CASTLESS(ADynamicLight),DynLightFlagDefs, countof(DynLightFlagDefs), 3 },
};
#define NUM_FLAG_LISTS (countof(FlagLists))
@ -667,7 +677,7 @@ static int CompareClassNames(const Desc& a, const Desc& b)
//
//==========================================================================
AFuncDesc *FindFunction(PStruct *cls, const char * string)
AFuncDesc *FindFunction(PContainerType *cls, const char * string)
{
int min = 0, max = AFTable.Size() - 1;
@ -698,7 +708,7 @@ AFuncDesc *FindFunction(PStruct *cls, const char * string)
//
//==========================================================================
FieldDesc *FindField(PStruct *cls, const char * string)
FieldDesc *FindField(PContainerType *cls, const char * string)
{
int min = 0, max = FieldTable.Size() - 1;
const char * cname = cls ? cls->TypeName.GetChars() : "";
@ -733,7 +743,7 @@ FieldDesc *FindField(PStruct *cls, const char * string)
VMFunction *FindVMFunction(PClass *cls, const char *name)
{
auto f = dyn_cast<PFunction>(cls->Symbols.FindSymbol(name, true));
auto f = dyn_cast<PFunction>(cls->FindSymbol(name, true));
return f == nullptr ? nullptr : f->Variants[0].Implementation;
}
@ -777,11 +787,11 @@ static int fieldcmp(const void * a, const void * b)
void InitThingdef()
{
// Some native types need size and serialization information added before the scripts get compiled.
auto secplanestruct = NewNativeStruct("Secplane", nullptr);
auto secplanestruct = NewStruct("Secplane", nullptr, true);
secplanestruct->Size = sizeof(secplane_t);
secplanestruct->Align = alignof(secplane_t);
auto sectorstruct = NewNativeStruct("Sector", nullptr);
auto sectorstruct = NewStruct("Sector", nullptr, true);
sectorstruct->Size = sizeof(sector_t);
sectorstruct->Align = alignof(sector_t);
NewPointer(sectorstruct, false)->InstallHandlers(
@ -796,7 +806,7 @@ void InitThingdef()
}
);
auto linestruct = NewNativeStruct("Line", nullptr);
auto linestruct = NewStruct("Line", nullptr, true);
linestruct->Size = sizeof(line_t);
linestruct->Align = alignof(line_t);
NewPointer(linestruct, false)->InstallHandlers(
@ -811,7 +821,7 @@ void InitThingdef()
}
);
auto sidestruct = NewNativeStruct("Side", nullptr);
auto sidestruct = NewStruct("Side", nullptr, true);
sidestruct->Size = sizeof(side_t);
sidestruct->Align = alignof(side_t);
NewPointer(sidestruct, false)->InstallHandlers(
@ -826,7 +836,7 @@ void InitThingdef()
}
);
auto vertstruct = NewNativeStruct("Vertex", nullptr);
auto vertstruct = NewStruct("Vertex", nullptr, true);
vertstruct->Size = sizeof(vertex_t);
vertstruct->Align = alignof(vertex_t);
NewPointer(vertstruct, false)->InstallHandlers(
@ -841,23 +851,23 @@ void InitThingdef()
}
);
auto sectorportalstruct = NewNativeStruct("SectorPortal", nullptr);
auto sectorportalstruct = NewStruct("SectorPortal", nullptr, true);
sectorportalstruct->Size = sizeof(FSectorPortal);
sectorportalstruct->Align = alignof(FSectorPortal);
auto playerclassstruct = NewNativeStruct("PlayerClass", nullptr);
auto playerclassstruct = NewStruct("PlayerClass", nullptr, true);
playerclassstruct->Size = sizeof(FPlayerClass);
playerclassstruct->Align = alignof(FPlayerClass);
auto playerskinstruct = NewNativeStruct("PlayerSkin", nullptr);
auto playerskinstruct = NewStruct("PlayerSkin", nullptr, true);
playerskinstruct->Size = sizeof(FPlayerSkin);
playerskinstruct->Align = alignof(FPlayerSkin);
auto teamstruct = NewNativeStruct("Team", nullptr);
auto teamstruct = NewStruct("Team", nullptr, true);
teamstruct->Size = sizeof(FTeam);
teamstruct->Align = alignof(FTeam);
PStruct *pstruct = NewNativeStruct("PlayerInfo", nullptr);
PStruct *pstruct = NewStruct("PlayerInfo", nullptr, true);
pstruct->Size = sizeof(player_t);
pstruct->Align = alignof(player_t);
NewPointer(pstruct, false)->InstallHandlers(
@ -872,7 +882,7 @@ void InitThingdef()
}
);
auto fontstruct = NewNativeStruct("FFont", nullptr);
auto fontstruct = NewStruct("FFont", nullptr, true);
fontstruct->Size = sizeof(FFont);
fontstruct->Align = alignof(FFont);
NewPointer(fontstruct, false)->InstallHandlers(
@ -887,32 +897,9 @@ void InitThingdef()
}
);
auto wbplayerstruct = NewNativeStruct("WBPlayerStruct", nullptr);
auto wbplayerstruct = NewStruct("WBPlayerStruct", nullptr, true);
wbplayerstruct->Size = sizeof(wbplayerstruct_t);
wbplayerstruct->Align = alignof(wbplayerstruct_t);
// Argh. It sucks when bad hacks need to be supported. WP_NOCHANGE is just a bogus pointer but it used everywhere as a special flag.
// It cannot be defined as constant because constants can either be numbers or strings but nothing else, so the only 'solution'
// is to create a static variable from it and reference that in the script. Yuck!!!
wpnochg = WP_NOCHANGE;
PField *fieldptr = new PField("WP_NOCHANGE", NewPointer(RUNTIME_CLASS(AWeapon), false), VARF_Native | VARF_Static | VARF_ReadOnly, (intptr_t)&wpnochg);
Namespaces.GlobalNamespace->Symbols.AddSymbol(fieldptr);
// synthesize a symbol for each flag from the flag name tables to avoid redundant declaration of them.
for (auto &fl : FlagLists)
{
if (fl.Use & 2)
{
for(int i=0;i<fl.NumDefs;i++)
{
if (fl.Defs[i].structoffset > 0) // skip the deprecated entries in this list
{
const_cast<PClass*>(*fl.Type)->AddNativeField(FStringf("b%s", fl.Defs[i].name), (fl.Defs[i].fieldsize == 4 ? TypeSInt32 : TypeSInt16), fl.Defs[i].structoffset, fl.Defs[i].varflags, fl.Defs[i].flagbit);
}
}
}
}
FAutoSegIterator probe(CRegHead, CRegTail);
@ -980,9 +967,37 @@ void InitThingdef()
FieldTable.ShrinkToFit();
qsort(&FieldTable[0], FieldTable.Size(), sizeof(FieldTable[0]), fieldcmp);
}
}
void SynthesizeFlagFields()
{
// These are needed for inserting the flag symbols
/*
NewClassType(RUNTIME_CLASS(DObject));
NewClassType(RUNTIME_CLASS(DThinker));
NewClassType(RUNTIME_CLASS(AActor));
NewClassType(RUNTIME_CLASS(AInventory));
NewClassType(RUNTIME_CLASS(AStateProvider));
NewClassType(RUNTIME_CLASS(AWeapon));
NewClassType(RUNTIME_CLASS(APlayerPawn));
NewClassType(RUNTIME_CLASS(ADynamicLight));
*/
// synthesize a symbol for each flag from the flag name tables to avoid redundant declaration of them.
for (auto &fl : FlagLists)
{
auto cls = const_cast<PClass*>(*fl.Type);
if (fl.Use & 2)
{
for (int i = 0; i < fl.NumDefs; i++)
{
if (fl.Defs[i].structoffset > 0) // skip the deprecated entries in this list
{
cls->VMType->AddNativeField(FStringf("b%s", fl.Defs[i].name), (fl.Defs[i].fieldsize == 4 ? TypeSInt32 : TypeSInt16), fl.Defs[i].structoffset, fl.Defs[i].varflags, fl.Defs[i].flagbit);
}
}
}
}
}
DEFINE_ACTION_FUNCTION(DObject, GameType)
{
PARAM_PROLOGUE;

View file

@ -70,6 +70,7 @@
#include "a_keys.h"
#include "g_levellocals.h"
#include "d_player.h"
#include "types.h"
//==========================================================================
//
@ -92,7 +93,7 @@ static PClassActor *FindClassTentative(const char *name, PClass *ancestor, bool
}
if (cls->Size == TentativeClass && optional)
{
cls->ObjectFlags |= OF_Transient; // since this flag has no meaning in class types, let's use it for marking the type optional.
cls->bOptional = true;
}
return static_cast<PClassActor *>(cls);
}
@ -342,7 +343,7 @@ void HandleDeprecatedFlags(AActor *defaults, PClassActor *info, bool set, int in
FName name(propname, true);
if (name != NAME_None)
{
auto propp = dyn_cast<PProperty>(info->Symbols.FindSymbol(name, true));
auto propp = dyn_cast<PProperty>(info->FindSymbol(name, true));
if (propp != nullptr)
{
*((char*)defaults + propp->Variables[0]->Offset) = set ? 1 : 0;
@ -391,10 +392,9 @@ bool CheckDeprecatedFlags(const AActor *actor, PClassActor *info, int index)
case DEPF_QUARTERGRAVITY:
return actor->Gravity == 1./4;
case DEPF_FIRERESIST:
if (info->DamageFactors)
for (auto &df : info->ActorInfo()->DamageFactors)
{
double *df = info->DamageFactors->CheckKey(NAME_Fire);
return df && (*df) == 0.5;
if (df.first == NAME_Fire) return df.second == 0.5;
}
return false;
@ -464,33 +464,34 @@ static bool PointerCheck(PType *symtype, PType *checktype)
DEFINE_INFO_PROPERTY(game, S, Actor)
{
PROP_STRING_PARM(str, 0);
auto & GameFilter = info->ActorInfo()->GameFilter;
if (!stricmp(str, "Doom"))
{
info->GameFilter |= GAME_Doom;
GameFilter |= GAME_Doom;
}
else if (!stricmp(str, "Heretic"))
{
info->GameFilter |= GAME_Heretic;
GameFilter |= GAME_Heretic;
}
else if (!stricmp(str, "Hexen"))
{
info->GameFilter |= GAME_Hexen;
GameFilter |= GAME_Hexen;
}
else if (!stricmp(str, "Raven"))
{
info->GameFilter |= GAME_Raven;
GameFilter |= GAME_Raven;
}
else if (!stricmp(str, "Strife"))
{
info->GameFilter |= GAME_Strife;
GameFilter |= GAME_Strife;
}
else if (!stricmp(str, "Chex"))
{
info->GameFilter |= GAME_Chex;
GameFilter |= GAME_Chex;
}
else if (!stricmp(str, "Any"))
{
info->GameFilter = GAME_Any;
GameFilter = GAME_Any;
}
else
{
@ -508,7 +509,7 @@ DEFINE_INFO_PROPERTY(spawnid, I, Actor)
{
I_Error ("SpawnID must be in the range [0,65535]");
}
else info->SpawnID=(uint16_t)id;
else info->ActorInfo()->SpawnID=(uint16_t)id;
}
//==========================================================================
@ -521,7 +522,7 @@ DEFINE_INFO_PROPERTY(conversationid, IiI, Actor)
PROP_INT_PARM(id2, 2);
if (convid <= 0 || convid > 65535) return; // 0 is not usable because the dialogue scripts use it as 'no object'.
else info->ConversationID=(uint16_t)convid;
else info->ActorInfo()->ConversationID=(uint16_t)convid;
}
//==========================================================================
@ -559,7 +560,7 @@ DEFINE_PROPERTY(skip_super, 0, Actor)
DEFINE_PROPERTY(defaultstateusage, I, Actor)
{
PROP_INT_PARM(use, 0);
static_cast<PClassActor*>(bag.Info)->DefaultStateUsage = use;
static_cast<PClassActor*>(bag.Info)->ActorInfo()->DefaultStateUsage = use;
}
//==========================================================================
@ -740,7 +741,7 @@ DEFINE_PROPERTY(translation, L, Actor)
if (type == 0)
{
PROP_INT_PARM(trans, 1);
int max = 6;// (gameinfo.gametype == GAME_Strife || (info->GameFilter&GAME_Strife)) ? 6 : 2;
int max = 6;
if (trans < 0 || trans > max)
{
I_Error ("Translation must be in the range [0,%d]", max);
@ -1048,12 +1049,12 @@ DEFINE_PROPERTY(visibletoteam, I, Actor)
//==========================================================================
DEFINE_PROPERTY(visibletoplayerclass, Ssssssssssssssssssss, Actor)
{
info->VisibleToPlayerClass.Clear();
info->ActorInfo()->VisibleToPlayerClass.Clear();
for(int i = 0;i < PROP_PARM_COUNT;++i)
{
PROP_STRING_PARM(n, i);
if (*n != 0)
info->VisibleToPlayerClass.Push(FindClassTentative(n, RUNTIME_CLASS(APlayerPawn)));
info->ActorInfo()->VisibleToPlayerClass.Push(FindClassTentative(n, RUNTIME_CLASS(APlayerPawn)));
}
}
@ -1071,7 +1072,7 @@ DEFINE_PROPERTY(distancecheck, S, Actor)
}
else if (cv->GetRealType() == CVAR_Int)
{
static_cast<PClassActor*>(info)->distancecheck = static_cast<FIntCVar *>(cv);
info->ActorInfo()->distancecheck = static_cast<FIntCVar *>(cv);
}
else
{
@ -1133,7 +1134,7 @@ static void SetIcon(FTextureID &icon, Baggage &bag, const char *i)
{
// Don't print warnings if the item is for another game or if this is a shareware IWAD.
// Strife's teaser doesn't contain all the icon graphics of the full game.
if ((bag.Info->GameFilter == GAME_Any || bag.Info->GameFilter & gameinfo.gametype) &&
if ((bag.Info->ActorInfo()->GameFilter == GAME_Any || bag.Info->ActorInfo()->GameFilter & gameinfo.gametype) &&
!(gameinfo.flags&GI_SHAREWARE) && Wads.GetLumpFile(bag.Lumpnum) != 0)
{
bag.ScriptPosition.Message(MSG_WARNING,
@ -1367,7 +1368,7 @@ DEFINE_SCRIPTED_PROPERTY_PREFIX(powerup, type, S, PowerupGiver)
DEFINE_CLASS_PROPERTY_PREFIX(player, displayname, S, PlayerPawn)
{
PROP_STRING_PARM(str, 0);
info->DisplayName = str;
info->ActorInfo()->DisplayName = str;
}
//==========================================================================

Some files were not shown because too many files have changed in this diff Show more