mirror of
https://github.com/ZDoom/qzdoom.git
synced 2025-01-31 04:50:48 +00:00
This commit is contained in:
commit
a15031706d
128 changed files with 5354 additions and 5093 deletions
|
@ -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
|
||||
|
|
18
src/actor.h
18
src/actor.h
|
@ -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);
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
#include "d_net.h"
|
||||
#include "serializer.h"
|
||||
#include "d_player.h"
|
||||
#include "vm.h"
|
||||
|
||||
IMPLEMENT_CLASS(DBot, false, true)
|
||||
|
||||
|
|
|
@ -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");
|
||||
|
||||
|
|
|
@ -46,6 +46,7 @@
|
|||
#include "w_wad.h"
|
||||
#include "templates.h"
|
||||
#include "dobject.h"
|
||||
#include "vm.h"
|
||||
|
||||
#include <math.h>
|
||||
#include <stdlib.h>
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -52,6 +52,7 @@
|
|||
#include "v_video.h"
|
||||
#include "colormatcher.h"
|
||||
#include "menu/menu.h"
|
||||
#include "vm.h"
|
||||
|
||||
struct FLatchedValue
|
||||
{
|
||||
|
|
|
@ -55,6 +55,7 @@
|
|||
#include "d_main.h"
|
||||
#include "serializer.h"
|
||||
#include "menu/menu.h"
|
||||
#include "vm.h"
|
||||
|
||||
// MACROS ------------------------------------------------------------------
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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))
|
||||
|
|
|
@ -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__
|
||||
|
|
2990
src/dobjtype.cpp
2990
src/dobjtype.cpp
File diff suppressed because it is too large
Load diff
710
src/dobjtype.h
710
src/dobjtype.h
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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__
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -43,7 +43,7 @@
|
|||
#include "w_wad.h"
|
||||
#include "doomstat.h"
|
||||
#include "v_font.h"
|
||||
|
||||
#include "vm.h"
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
#include "templates.h"
|
||||
#include "serializer.h"
|
||||
#include "r_data/r_translate.h"
|
||||
#include "vm.h"
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
//
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -42,6 +42,7 @@
|
|||
#include "i_system.h"
|
||||
#include "v_video.h"
|
||||
#include "g_level.h"
|
||||
#include "vm.h"
|
||||
|
||||
gameinfo_t gameinfo;
|
||||
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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++)
|
||||
|
|
289
src/info.cpp
289
src/info.cpp
|
@ -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)
|
||||
{
|
||||
|
|
124
src/info.h
124
src/info.h
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -50,6 +50,7 @@
|
|||
#include "d_gui.h"
|
||||
#include "i_music.h"
|
||||
#include "m_joy.h"
|
||||
#include "vm.h"
|
||||
|
||||
static TArray<IJoystickConfig *> Joysticks;
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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];
|
||||
}
|
||||
|
|
|
@ -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, ¶ms[0], params.Size(), nullptr, 0);
|
||||
VMCall(func->Variants[0].Implementation, ¶ms[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, ¶ms[0], params.Size(), nullptr, 0);
|
||||
VMCall(func->Variants[0].Implementation, ¶ms[0], params.Size(), nullptr, 0);
|
||||
desc->mItems.Push((DMenuItemBase*)item);
|
||||
|
||||
success = true;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -53,6 +53,7 @@
|
|||
#include "m_joy.h"
|
||||
#include "sbar.h"
|
||||
#include "hardware.h"
|
||||
#include "vm.h"
|
||||
|
||||
/*=======================================
|
||||
*
|
||||
|
|
|
@ -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, ¶ms[0], params.Size(), nullptr, 0);
|
||||
VMCall(func, ¶ms[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, ¶ms[0], params.Size(), &ret, 1);
|
||||
VMCall(func, ¶ms[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, ¶ms[0], params.Size(), &ret, 1);
|
||||
VMCall(func, ¶ms[0], params.Size(), &ret, 1);
|
||||
retval = DoubleToACS(d);
|
||||
}
|
||||
else if (rettype == TypeString)
|
||||
{
|
||||
FString d;
|
||||
VMReturn ret(&d);
|
||||
GlobalVMStack.Call(func, ¶ms[0], params.Size(), &ret, 1);
|
||||
VMCall(func, ¶ms[0], params.Size(), &ret, 1);
|
||||
retval = GlobalACSStrings.AddString(d);
|
||||
}
|
||||
else
|
||||
{
|
||||
// All other return values can not be handled so ignore them.
|
||||
GlobalVMStack.Call(func, ¶ms[0], params.Size(), nullptr, 0);
|
||||
VMCall(func, ¶ms[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))
|
||||
{
|
||||
|
|
|
@ -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)) ||
|
||||
|
|
|
@ -33,6 +33,7 @@
|
|||
#include "p_spec.h"
|
||||
#include "g_levellocals.h"
|
||||
#include "textures.h"
|
||||
#include "vm.h"
|
||||
|
||||
//============================================================================
|
||||
//
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -33,6 +33,7 @@
|
|||
#include "p_spec.h"
|
||||
#include "r_data/r_interpolate.h"
|
||||
#include "g_levellocals.h"
|
||||
#include "vm.h"
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -38,6 +38,7 @@
|
|||
#include "p_lnspec.h"
|
||||
#include "p_spec.h"
|
||||
#include "g_levellocals.h"
|
||||
#include "vm.h"
|
||||
|
||||
enum
|
||||
{
|
||||
|
|
|
@ -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:
|
||||
/*
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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, ¶m, 1, &result, 1) < 1)
|
||||
if (VMCall(DamageFunc, ¶m, 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, ¶m, 1, nullptr, 0);
|
||||
VMCall(func, ¶m, 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
|
||||
{
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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++;
|
||||
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
#include "r_utility.h"
|
||||
#include "b_bot.h"
|
||||
#include "p_spec.h"
|
||||
#include "vm.h"
|
||||
|
||||
// State.
|
||||
#include "r_state.h"
|
||||
|
|
|
@ -76,6 +76,7 @@
|
|||
#ifndef NO_EDATA
|
||||
#include "edata.h"
|
||||
#endif
|
||||
#include "vm.h"
|
||||
|
||||
// State.
|
||||
#include "r_state.h"
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -37,6 +37,7 @@
|
|||
#include "p_tags.h"
|
||||
#include "c_dispatch.h"
|
||||
#include "g_levellocals.h"
|
||||
#include "vm.h"
|
||||
|
||||
FTagManager tagManager;
|
||||
|
||||
|
|
|
@ -39,6 +39,7 @@
|
|||
#include "r_utility.h"
|
||||
#include "p_spec.h"
|
||||
#include "g_levellocals.h"
|
||||
#include "vm.h"
|
||||
|
||||
#define FUDGEFACTOR 10
|
||||
|
||||
|
|
|
@ -47,6 +47,7 @@
|
|||
#include "p_local.h"
|
||||
#include "templates.h"
|
||||
#include "actor.h"
|
||||
#include "vm.h"
|
||||
|
||||
// MACROS ------------------------------------------------------------------
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -50,6 +50,7 @@
|
|||
#include "p_terrain.h"
|
||||
#include "g_levellocals.h"
|
||||
#include "info.h"
|
||||
#include "vm.h"
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
#include "r_data/sprites.h"
|
||||
#include "r_data/voxels.h"
|
||||
#include "textures/textures.h"
|
||||
#include "vm.h"
|
||||
|
||||
void gl_InitModels();
|
||||
|
||||
|
|
|
@ -30,6 +30,7 @@
|
|||
#include "serializer.h"
|
||||
#include "d_player.h"
|
||||
#include "g_levellocals.h"
|
||||
#include "vm.h"
|
||||
|
||||
// MACROS ------------------------------------------------------------------
|
||||
|
||||
|
|
|
@ -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
|
||||
{
|
||||
|
|
|
@ -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
|
||||
{
|
||||
|
|
|
@ -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:
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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));
|
||||
}
|
|
@ -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
|
||||
{
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
#define VMUTIL_H
|
||||
|
||||
#include "dobject.h"
|
||||
#include "vmintern.h"
|
||||
|
||||
class VMFunctionBuilder;
|
||||
class FxExpression;
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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++;
|
||||
|
|
|
@ -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);
|
||||
|
||||
//==========================================================================
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
Loading…
Reference in a new issue