- scriptified A_SpawnFly.

- added support for global variables to the code generator - not the compiler, though. For the handful of entries this is needed for it may just as well be done manually. So far FLevelLocals level is the only one being exported.
- fixed: The VM disassembler truncated 64 bit pointers to 15 digits because the output buffer was too small.
- resolve entire FxSequences instead of aborting on the first failed entry. This allows to output all errors at once.
This commit is contained in:
Christoph Oelckers 2016-11-03 13:38:40 +01:00
parent 6aecb29995
commit a45523fb63
15 changed files with 274 additions and 39 deletions

View file

@ -2100,6 +2100,7 @@ PStruct::PStruct(FName name, PTypeBase *outer)
{ {
mDescriptiveName.Format("Struct<%s>", name.GetChars()); mDescriptiveName.Format("Struct<%s>", name.GetChars());
Size = 0; Size = 0;
HasNativeFields = false;
} }
//========================================================================== //==========================================================================
@ -2114,7 +2115,7 @@ void PStruct::SetDefaultValue(void *base, unsigned offset, TArray<FTypeAndOffset
{ {
if (!(field->Flags & VARF_Native)) if (!(field->Flags & VARF_Native))
{ {
field->Type->SetDefaultValue(base, offset + field->Offset, special); field->Type->SetDefaultValue(base, unsigned(offset + field->Offset), special);
} }
} }
} }
@ -2216,13 +2217,13 @@ bool PStruct::ReadFields(FSerializer &ar, void *addr) const
PField *PStruct::AddField(FName name, PType *type, DWORD flags) PField *PStruct::AddField(FName name, PType *type, DWORD flags)
{ {
PField *field = new PField(name, type); PField *field = new PField(name, type, flags);
// The new field is added to the end of this struct, alignment permitting. // The new field is added to the end of this struct, alignment permitting.
field->Offset = (Size + (type->Align - 1)) & ~(type->Align - 1); field->Offset = (Size + (type->Align - 1)) & ~(type->Align - 1);
// Enlarge this struct to enclose the new field. // Enlarge this struct to enclose the new field.
Size = field->Offset + type->Size; Size = unsigned(field->Offset + type->Size);
// This struct's alignment is the same as the largest alignment of any of // This struct's alignment is the same as the largest alignment of any of
// its fields. // its fields.
@ -2238,6 +2239,29 @@ PField *PStruct::AddField(FName name, PType *type, DWORD flags)
return field; return field;
} }
//==========================================================================
//
// PStruct :: AddField
//
// Appends a new native field to the struct. Returns either the new field
// or NULL if a symbol by that name already exists.
//
//==========================================================================
PField *PStruct::AddNativeField(FName name, PType *type, size_t address, DWORD flags, int bitvalue)
{
PField *field = new PField(name, type, flags|VARF_Native, address, bitvalue);
if (Symbols.AddSymbol(field) == nullptr)
{ // name is already in use
delete field;
return nullptr;
}
Fields.Push(field);
HasNativeFields = true;
return field;
}
//========================================================================== //==========================================================================
// //
// PStruct :: PropagateMark // PStruct :: PropagateMark
@ -2286,7 +2310,7 @@ PField::PField()
} }
PField::PField(FName name, PType *type, DWORD flags, size_t offset, int bitvalue) PField::PField(FName name, PType *type, DWORD flags, size_t offset, int bitvalue)
: PSymbol(name), Offset(unsigned(offset)), Type(type), Flags(flags) : PSymbol(name), Offset(offset), Type(type), Flags(flags)
{ {
BitValue = bitvalue; BitValue = bitvalue;
if (bitvalue > -1) if (bitvalue > -1)
@ -3085,7 +3109,7 @@ PField *PClass::AddField(FName name, PType *type, DWORD flags)
{ {
Defaults = (BYTE *)M_Realloc(Defaults, Size); Defaults = (BYTE *)M_Realloc(Defaults, Size);
memset(Defaults + oldsize, 0, Size - oldsize); memset(Defaults + oldsize, 0, Size - oldsize);
type->SetDefaultValue(Defaults, field->Offset, &SpecialInits); type->SetDefaultValue(Defaults, unsigned(field->Offset), &SpecialInits);
} }
return field; return field;
} }

View file

@ -574,7 +574,7 @@ class PField : public PSymbol
public: public:
PField(FName name, PType *type, DWORD flags = 0, size_t offset = 0, int bitvalue = -1); PField(FName name, PType *type, DWORD flags = 0, size_t offset = 0, int bitvalue = -1);
unsigned int Offset; size_t Offset;
PType *Type; PType *Type;
DWORD Flags; DWORD Flags;
int BitValue; int BitValue;
@ -669,8 +669,10 @@ public:
PStruct(FName name, PTypeBase *outer); PStruct(FName name, PTypeBase *outer);
TArray<PField *> Fields; TArray<PField *> Fields;
bool HasNativeFields;
virtual PField *AddField(FName name, PType *type, DWORD flags=0); virtual PField *AddField(FName name, PType *type, DWORD flags=0);
virtual PField *AddNativeField(FName name, PType *type, size_t address, DWORD flags = 0, int bitvalue = -1);
size_t PropagateMark(); size_t PropagateMark();

View file

@ -1848,6 +1848,65 @@ void FLevelLocals::AddScroller (int secnum)
} }
} }
//==========================================================================
//
// sets up the script-side version of FLevelLocals
// Since this is a global variable and the script compiler does
// not allow defining them, it will be fully set up here.
//
//==========================================================================
inline int val2bit(int val)
{
int bit = 0;
while ((val >>= 1)) bit++;
return bit;
}
void G_InitLevelLocalsForScript()
{
PStruct *lstruct = NewStruct("LevelLocals", nullptr);
PField *levelf = new PField("level", lstruct, VARF_Native | VARF_Static, (intptr_t)&level);
GlobalSymbols.AddSymbol(levelf);
// This only exports a selection of fields. Not everything here is useful to the playsim.
lstruct->AddNativeField("time", TypeSInt32, myoffsetof(FLevelLocals, time), VARF_ReadOnly);
lstruct->AddNativeField("maptime", TypeSInt32, myoffsetof(FLevelLocals, maptime), VARF_ReadOnly);
lstruct->AddNativeField("totaltime", TypeSInt32, myoffsetof(FLevelLocals, totaltime), VARF_ReadOnly);
lstruct->AddNativeField("starttime", TypeSInt32, myoffsetof(FLevelLocals, starttime), VARF_ReadOnly);
lstruct->AddNativeField("partime", TypeSInt32, myoffsetof(FLevelLocals, partime), VARF_ReadOnly);
lstruct->AddNativeField("sucktime", TypeSInt32, myoffsetof(FLevelLocals, sucktime), VARF_ReadOnly);
lstruct->AddNativeField("cluster", TypeSInt32, myoffsetof(FLevelLocals, cluster), VARF_ReadOnly);
lstruct->AddNativeField("clusterflags", TypeSInt32, myoffsetof(FLevelLocals, clusterflags), VARF_ReadOnly);
lstruct->AddNativeField("levelnum", TypeSInt32, myoffsetof(FLevelLocals, levelnum), VARF_ReadOnly);
//lstruct->AddNativeField("levelname", TypeString, myoffsetof(FLevelLocals, LevelName), VARF_ReadOnly); // must use an access function to resolve string table references.
lstruct->AddNativeField("mapname", TypeString, myoffsetof(FLevelLocals, MapName), VARF_ReadOnly);
lstruct->AddNativeField("nextmap", TypeString, myoffsetof(FLevelLocals, NextMap));
lstruct->AddNativeField("nextsecretmap", TypeString, myoffsetof(FLevelLocals, NextSecretMap));
lstruct->AddNativeField("maptype", TypeSInt32, myoffsetof(FLevelLocals, maptype), VARF_ReadOnly);
lstruct->AddNativeField("monsterstelefrag", TypeSInt32, myoffsetof(FLevelLocals, flags), VARF_ReadOnly, val2bit(LEVEL_MONSTERSTELEFRAG));
lstruct->AddNativeField("actownspecial", TypeSInt32, myoffsetof(FLevelLocals, flags), VARF_ReadOnly, val2bit(LEVEL_ACTOWNSPECIAL));
lstruct->AddNativeField("sndseqtotalctrl", TypeSInt32, myoffsetof(FLevelLocals, flags), VARF_ReadOnly, val2bit(LEVEL_SNDSEQTOTALCTRL));
lstruct->AddNativeField("allmap", TypeSInt32, myoffsetof(FLevelLocals, flags2), 0, val2bit(LEVEL2_ALLMAP));
lstruct->AddNativeField("missilesactivateimpact", TypeSInt32, myoffsetof(FLevelLocals, flags2), 0, val2bit(LEVEL2_MISSILESACTIVATEIMPACT));
lstruct->AddNativeField("monsterfallingdamage", TypeSInt32, myoffsetof(FLevelLocals, flags2), 0, val2bit(LEVEL2_MONSTERFALLINGDAMAGE));
lstruct->AddNativeField("checkswitchrange", TypeSInt32, myoffsetof(FLevelLocals, flags2), 0, val2bit(LEVEL2_CHECKSWITCHRANGE));
lstruct->AddNativeField("polygrind", TypeSInt32, myoffsetof(FLevelLocals, flags2), 0, val2bit(LEVEL2_POLYGRIND));
lstruct->AddNativeField("music", TypeString, myoffsetof(FLevelLocals, Music), VARF_ReadOnly);
lstruct->AddNativeField("musicorder", TypeSInt32, myoffsetof(FLevelLocals, musicorder), VARF_ReadOnly);
lstruct->AddNativeField("total_secrets", TypeSInt32, myoffsetof(FLevelLocals, total_secrets), VARF_ReadOnly);
lstruct->AddNativeField("found_secrets", TypeSInt32, myoffsetof(FLevelLocals, found_secrets));
lstruct->AddNativeField("total_items", TypeSInt32, myoffsetof(FLevelLocals, total_items), VARF_ReadOnly);
lstruct->AddNativeField("found_items", TypeSInt32, myoffsetof(FLevelLocals, found_items));
lstruct->AddNativeField("total_monsters", TypeSInt32, myoffsetof(FLevelLocals, total_monsters), VARF_ReadOnly);
lstruct->AddNativeField("killed_monsters", TypeSInt32, myoffsetof(FLevelLocals, killed_monsters));
lstruct->AddNativeField("gravity", TypeFloat64, myoffsetof(FLevelLocals, gravity));
lstruct->AddNativeField("aircontrol", TypeFloat64, myoffsetof(FLevelLocals, aircontrol));
lstruct->AddNativeField("airfriction", TypeFloat64, myoffsetof(FLevelLocals, airfriction));
lstruct->AddNativeField("airsupply", TypeSInt32, myoffsetof(FLevelLocals, airsupply));
lstruct->AddNativeField("teamdamage", TypeFloat64, myoffsetof(FLevelLocals, teamdamage));
}
//========================================================================== //==========================================================================
// //
// Lists all currently defined maps // Lists all currently defined maps

View file

@ -260,7 +260,7 @@ struct FOptionalMapinfoDataPtr
typedef TMap<FName, FOptionalMapinfoDataPtr> FOptData; typedef TMap<FName, FOptionalMapinfoDataPtr> FOptData;
typedef TMap<int, FName> FMusicMap; typedef TMap<int, FName> FMusicMap;
enum EMapType enum EMapType : int
{ {
MAPTYPE_UNKNOWN = 0, MAPTYPE_UNKNOWN = 0,
MAPTYPE_DOOM, MAPTYPE_DOOM,

View file

@ -1790,6 +1790,13 @@ bool P_LookForPlayers (AActor *actor, INTBOOL allaround, FLookExParams *params)
} }
} }
DEFINE_ACTION_FUNCTION(AActor, LookForPlayers)
{
PARAM_SELF_PROLOGUE(AActor);
PARAM_BOOL(allaround);
ACTION_RETURN_BOOL(P_LookForPlayers(self, allaround, nullptr));
}
// //
// ACTION ROUTINES // ACTION ROUTINES
// //

View file

@ -444,6 +444,17 @@ bool P_TeleportMove(AActor* thing, const DVector3 &pos, bool telefrag, bool modi
return true; return true;
} }
DEFINE_ACTION_FUNCTION(AActor, TeleportMove)
{
PARAM_SELF_PROLOGUE(AActor);
PARAM_FLOAT(x);
PARAM_FLOAT(y);
PARAM_FLOAT(z);
PARAM_BOOL(telefrag);
PARAM_BOOL_DEF(modify);
ACTION_RETURN_BOOL(P_TeleportMove(self, DVector3(x, y, z), telefrag, modify));
}
//========================================================================== //==========================================================================
// //
// [RH] P_PlayerStartStomp // [RH] P_PlayerStartStomp

View file

@ -990,6 +990,15 @@ void AActor::CopyFriendliness (AActor *other, bool changeTarget, bool resetHealt
level.total_monsters += CountsAsKill(); level.total_monsters += CountsAsKill();
} }
DEFINE_ACTION_FUNCTION(AActor, CopyFriendliness)
{
PARAM_SELF_PROLOGUE(AActor);
PARAM_OBJECT(other, AActor);
PARAM_BOOL_DEF(changetarget);
PARAM_BOOL_DEF(resethealth);
self->CopyFriendliness(other, changetarget, resethealth);
return 0;
}
//============================================================================ //============================================================================
// //
// AActor :: ObtainInventory // AActor :: ObtainInventory
@ -6515,6 +6524,12 @@ DDropItem *AActor::GetDropItems() const
return GetClass()->DropItems; return GetClass()->DropItems;
} }
DEFINE_ACTION_FUNCTION(AActor, GetDropItems)
{
PARAM_SELF_PROLOGUE(AActor);
ACTION_RETURN_OBJECT(self->GetDropItems());
}
double AActor::GetGravity() const double AActor::GetGravity() const
{ {
if (flags & MF_NOGRAVITY) return 0; if (flags & MF_NOGRAVITY) return 0;

View file

@ -5067,6 +5067,12 @@ FxExpression *FxIdentifier::Resolve(FCompileContext& ctx)
ScriptPosition.Message(MSG_DEBUGLOG, "Resolving name '%s' as global constant\n", Identifier.GetChars()); ScriptPosition.Message(MSG_DEBUGLOG, "Resolving name '%s' as global constant\n", Identifier.GetChars());
newex = FxConstant::MakeConstant(sym, ScriptPosition); newex = FxConstant::MakeConstant(sym, ScriptPosition);
} }
else if (sym->IsKindOf(RUNTIME_CLASS(PField)))
{
// internally defined global variable
ScriptPosition.Message(MSG_DEBUGLOG, "Resolving name '%s' as global variable\n", Identifier.GetChars());
newex = new FxGlobalVariable(static_cast<PField *>(sym), ScriptPosition);
}
else else
{ {
ScriptPosition.Message(MSG_ERROR, "Invalid global identifier '%s'\n", Identifier.GetChars()); ScriptPosition.Message(MSG_ERROR, "Invalid global identifier '%s'\n", Identifier.GetChars());
@ -5303,6 +5309,72 @@ ExpEmit FxSelf::Emit(VMFunctionBuilder *build)
} }
//==========================================================================
//
//
//
//==========================================================================
FxGlobalVariable::FxGlobalVariable(PField* mem, const FScriptPosition &pos)
: FxExpression(EFX_GlobalVariable, pos)
{
membervar = mem;
AddressRequested = false;
AddressWritable = true; // must be true unless classx tells us otherwise if requested.
}
//==========================================================================
//
//
//
//==========================================================================
bool FxGlobalVariable::RequestAddress(bool *writable)
{
AddressRequested = true;
if (writable != nullptr) *writable = AddressWritable && !(membervar->Flags & VARF_ReadOnly);
return true;
}
//==========================================================================
//
//
//
//==========================================================================
FxExpression *FxGlobalVariable::Resolve(FCompileContext &ctx)
{
CHECKRESOLVED();
ValueType = membervar->Type;
return this;
}
ExpEmit FxGlobalVariable::Emit(VMFunctionBuilder *build)
{
ExpEmit obj(build, REGT_POINTER);
build->Emit(OP_LKP, obj.RegNum, build->GetConstantAddress((void*)(intptr_t)membervar->Offset, ATAG_GENERIC));
if (AddressRequested)
{
return obj;
}
ExpEmit loc(build, membervar->Type->GetRegType(), membervar->Type->GetRegCount());
if (membervar->BitValue == -1)
{
int offsetreg = build->GetConstantInt(0);
build->Emit(membervar->Type->GetLoadOp(), loc.RegNum, obj.RegNum, offsetreg);
}
else
{
build->Emit(OP_LBIT, loc.RegNum, obj.RegNum, 1 << membervar->BitValue);
}
obj.Free(build);
return loc;
}
//========================================================================== //==========================================================================
// //
// //
@ -5377,11 +5449,21 @@ FxExpression *FxStructMember::Resolve(FCompileContext &ctx)
classx = nullptr; classx = nullptr;
return x; return x;
} }
else if (classx->ExprType == EFX_GlobalVariable)
{
auto parentfield = static_cast<FxGlobalVariable *>(classx)->membervar;
auto newfield = new PField(membervar->SymbolName, membervar->Type, membervar->Flags | parentfield->Flags, membervar->Offset + parentfield->Offset, membervar->BitValue);
static_cast<FxGlobalVariable *>(classx)->membervar = newfield;
classx->isresolved = false; // re-resolve the parent so it can also check if it can be optimized away.
auto x = classx->Resolve(ctx);
classx = nullptr;
return x;
}
else if (classx->ExprType == EFX_LocalVariable && classx->IsVector()) // vectors are a special case because they are held in registers else if (classx->ExprType == EFX_LocalVariable && classx->IsVector()) // vectors are a special case because they are held in registers
{ {
// since this is a vector, all potential things that may get here are single float or an xy-vector. // since this is a vector, all potential things that may get here are single float or an xy-vector.
auto locvar = static_cast<FxLocalVariable *>(classx); auto locvar = static_cast<FxLocalVariable *>(classx);
locvar->RegOffset = membervar->Offset / 8; locvar->RegOffset = int(membervar->Offset / 8);
locvar->ValueType = membervar->Type; locvar->ValueType = membervar->Type;
classx = nullptr; classx = nullptr;
delete this; delete this;
@ -5816,13 +5898,15 @@ FxExpression *FxFunctionCall::Resolve(FCompileContext& ctx)
case NAME_Name: case NAME_Name:
case NAME_Color: case NAME_Color:
case NAME_Sound: case NAME_Sound:
case NAME_State:
if (CheckArgSize(MethodName, ArgList, 1, 1, ScriptPosition)) if (CheckArgSize(MethodName, ArgList, 1, 1, ScriptPosition))
{ {
PType *type = MethodName == NAME_Int ? TypeSInt32 : PType *type = MethodName == NAME_Int ? TypeSInt32 :
MethodName == NAME_uInt ? TypeUInt32 : MethodName == NAME_uInt ? TypeUInt32 :
MethodName == NAME_Double ? TypeFloat64 : MethodName == NAME_Double ? TypeFloat64 :
MethodName == NAME_Name ? TypeName : MethodName == NAME_Name ? TypeName :
MethodName == NAME_Color ? TypeColor : (PType*)TypeSound; MethodName == NAME_Color ? TypeColor :
MethodName == NAME_State? TypeState :(PType*)TypeSound;
func = new FxTypeCast((*ArgList)[0], type, true, true); func = new FxTypeCast((*ArgList)[0], type, true, true);
(*ArgList)[0] = nullptr; (*ArgList)[0] = nullptr;
@ -6615,14 +6699,19 @@ ExpEmit FxVectorBuiltin::Emit(VMFunctionBuilder *build)
FxExpression *FxSequence::Resolve(FCompileContext &ctx) FxExpression *FxSequence::Resolve(FCompileContext &ctx)
{ {
CHECKRESOLVED(); CHECKRESOLVED();
bool fail = false;
for (unsigned i = 0; i < Expressions.Size(); ++i) for (unsigned i = 0; i < Expressions.Size(); ++i)
{ {
if (nullptr == (Expressions[i] = Expressions[i]->Resolve(ctx))) if (nullptr == (Expressions[i] = Expressions[i]->Resolve(ctx)))
{ {
delete this; fail = true;
return nullptr;
} }
} }
if (fail)
{
delete this;
return nullptr;
}
return this; return this;
} }

View file

@ -269,6 +269,7 @@ enum EFxType
EFX_VectorBuiltin, EFX_VectorBuiltin,
EFX_TypeCheck, EFX_TypeCheck,
EFX_DynamicCast, EFX_DynamicCast,
EFX_GlobalVariable,
EFX_COUNT EFX_COUNT
}; };
@ -1136,6 +1137,25 @@ public:
}; };
//==========================================================================
//
// FxGlobalVariaböe
//
//==========================================================================
class FxGlobalVariable : public FxExpression
{
public:
PField *membervar;
bool AddressRequested;
bool AddressWritable;
FxGlobalVariable(PField*, const FScriptPosition&);
FxExpression *Resolve(FCompileContext&);
bool RequestAddress(bool *writable);
ExpEmit Emit(VMFunctionBuilder *build);
};
//========================================================================== //==========================================================================
// //
// FxClassMember // FxClassMember

View file

@ -215,6 +215,7 @@ void CreateDamageFunction(PClassActor *info, AActor *defaults, FxExpression *id,
//========================================================================== //==========================================================================
void ParseScripts(); void ParseScripts();
void ParseAllDecorate(); void ParseAllDecorate();
void G_InitLevelLocalsForScript();
void LoadActors () void LoadActors ()
{ {
@ -223,6 +224,7 @@ void LoadActors ()
timer.Reset(); timer.Clock(); timer.Reset(); timer.Clock();
FScriptPosition::ResetErrorCounter(); FScriptPosition::ResetErrorCounter();
G_InitLevelLocalsForScript();
InitThingdef(); InitThingdef();
FScriptPosition::StrictErrors = true; FScriptPosition::StrictErrors = true;
ParseScripts(); ParseScripts();

View file

@ -673,10 +673,16 @@ void InitThingdef()
qsort(&AFTable[0], AFTable.Size(), sizeof(AFTable[0]), funccmp); qsort(&AFTable[0], AFTable.Size(), sizeof(AFTable[0]), funccmp);
} }
PType *TypeActor = NewPointer(RUNTIME_CLASS(AActor));
PStruct *sstruct = NewStruct("Sector", nullptr);
auto sptr = NewPointer(sstruct);
sstruct->AddNativeField("soundtarget", TypeActor, myoffsetof(sector_t, SoundTarget));
// Define some member variables we feel like exposing to the user // Define some member variables we feel like exposing to the user
PSymbolTable &symt = RUNTIME_CLASS(AActor)->Symbols; PSymbolTable &symt = RUNTIME_CLASS(AActor)->Symbols;
PType *array5 = NewArray(TypeSInt32, 5); PType *array5 = NewArray(TypeSInt32, 5);
PType *TypeActor = NewPointer(RUNTIME_CLASS(AActor)); symt.AddSymbol(new PField("sector", sptr, VARF_Native, myoffsetof(AActor, Sector)));
symt.AddSymbol(new PField(NAME_Alpha, TypeFloat64, VARF_Native, myoffsetof(AActor, Alpha))); symt.AddSymbol(new PField(NAME_Alpha, TypeFloat64, VARF_Native, myoffsetof(AActor, Alpha)));
symt.AddSymbol(new PField(NAME_Angle, TypeFloat64, VARF_Native, myoffsetof(AActor, Angles.Yaw))); symt.AddSymbol(new PField(NAME_Angle, TypeFloat64, VARF_Native, myoffsetof(AActor, Angles.Yaw)));
symt.AddSymbol(new PField(NAME_Args, array5, VARF_Native, myoffsetof(AActor, args))); symt.AddSymbol(new PField(NAME_Args, array5, VARF_Native, myoffsetof(AActor, args)));
@ -725,12 +731,14 @@ void InitThingdef()
symt.AddSymbol(new PField("RipperLevel", TypeSInt32, VARF_Native, myoffsetof(AActor, RipperLevel))); symt.AddSymbol(new PField("RipperLevel", TypeSInt32, VARF_Native, myoffsetof(AActor, RipperLevel)));
symt.AddSymbol(new PField("RipLevelMin", TypeSInt32, VARF_Native, myoffsetof(AActor, RipLevelMin))); symt.AddSymbol(new PField("RipLevelMin", TypeSInt32, VARF_Native, myoffsetof(AActor, RipLevelMin)));
symt.AddSymbol(new PField("RipLevelMax", TypeSInt32, VARF_Native, myoffsetof(AActor, RipLevelMax))); symt.AddSymbol(new PField("RipLevelMax", TypeSInt32, VARF_Native, myoffsetof(AActor, RipLevelMax)));
symt.AddSymbol(new PField("special2", TypeSInt32, VARF_Native, myoffsetof(AActor, special2)));
symt.AddSymbol(new PField(NAME_VisibleStartAngle, TypeFloat64, VARF_Native, myoffsetof(AActor, VisibleStartAngle))); symt.AddSymbol(new PField(NAME_VisibleStartAngle, TypeFloat64, VARF_Native, myoffsetof(AActor, VisibleStartAngle)));
symt.AddSymbol(new PField(NAME_VisibleStartPitch, TypeFloat64, VARF_Native, myoffsetof(AActor, VisibleStartPitch))); symt.AddSymbol(new PField(NAME_VisibleStartPitch, TypeFloat64, VARF_Native, myoffsetof(AActor, VisibleStartPitch)));
symt.AddSymbol(new PField(NAME_VisibleEndAngle, TypeFloat64, VARF_Native, myoffsetof(AActor, VisibleEndAngle))); symt.AddSymbol(new PField(NAME_VisibleEndAngle, TypeFloat64, VARF_Native, myoffsetof(AActor, VisibleEndAngle)));
symt.AddSymbol(new PField(NAME_VisibleEndPitch, TypeFloat64, VARF_Native, myoffsetof(AActor, VisibleEndPitch))); symt.AddSymbol(new PField(NAME_VisibleEndPitch, TypeFloat64, VARF_Native, myoffsetof(AActor, VisibleEndPitch)));
symt.AddSymbol(new PField("AttackSound", TypeSound, VARF_Native, myoffsetof(AActor, AttackSound))); symt.AddSymbol(new PField("AttackSound", TypeSound, VARF_Native, myoffsetof(AActor, AttackSound)));
symt.AddSymbol(new PField("DeathSound", TypeSound, VARF_Native, myoffsetof(AActor, DeathSound))); symt.AddSymbol(new PField("DeathSound", TypeSound, VARF_Native, myoffsetof(AActor, DeathSound)));
symt.AddSymbol(new PField("SeeSound", TypeSound, VARF_Native, myoffsetof(AActor, SeeSound)));
symt.AddSymbol(new PField("Pos", TypeVector3, VARF_Native|VARF_ReadOnly, myoffsetof(AActor, __Pos))); symt.AddSymbol(new PField("Pos", TypeVector3, VARF_Native|VARF_ReadOnly, myoffsetof(AActor, __Pos)));
symt.AddSymbol(new PField("Vel", TypeVector3, VARF_Native, myoffsetof(AActor, Vel))); symt.AddSymbol(new PField("Vel", TypeVector3, VARF_Native, myoffsetof(AActor, Vel)));
symt.AddSymbol(new PField("Scale", TypeVector2, VARF_Native, myoffsetof(AActor, Scale))); symt.AddSymbol(new PField("Scale", TypeVector2, VARF_Native, myoffsetof(AActor, Scale)));
@ -761,8 +769,11 @@ void InitThingdef()
PSymbolTable &symt2 = RUNTIME_CLASS(DDropItem)->Symbols; PSymbolTable &symt2 = RUNTIME_CLASS(DDropItem)->Symbols;
PType *TypeDropItem = NewPointer(RUNTIME_CLASS(DDropItem)); PType *TypeDropItem = NewPointer(RUNTIME_CLASS(DDropItem));
symt2.AddSymbol(new PField("Next", TypeDropItem, VARF_Native | VARF_ReadOnly, myoffsetof(DDropItem, Next))); symt2.AddSymbol(new PField("Next", TypeDropItem, VARF_Native | VARF_ReadOnly, myoffsetof(DDropItem, Next)));
symt2.AddSymbol(new PField("ItemName", TypeName, VARF_Native | VARF_ReadOnly, myoffsetof(DDropItem, Name))); symt2.AddSymbol(new PField("Name", TypeName, VARF_Native | VARF_ReadOnly, myoffsetof(DDropItem, Name)));
symt2.AddSymbol(new PField("Probability", TypeSInt32, VARF_Native | VARF_ReadOnly, myoffsetof(DDropItem, Probability))); symt2.AddSymbol(new PField("Probability", TypeSInt32, VARF_Native | VARF_ReadOnly, myoffsetof(DDropItem, Probability)));
symt2.AddSymbol(new PField("Amount", TypeSInt32, VARF_Native | VARF_ReadOnly, myoffsetof(DDropItem, Amount))); symt2.AddSymbol(new PField("Amount", TypeSInt32, VARF_Native, myoffsetof(DDropItem, Amount)));
PSymbolTable &symt3 = RUNTIME_CLASS(DObject)->Symbols;
symt3.AddSymbol(new PField("bDestroyed", TypeSInt32, VARF_Native|VARF_ReadOnly, myoffsetof(DObject, ObjectFlags), 5/*OF_EuthanizeMe*/));
} }

View file

@ -30,6 +30,8 @@ public:
// Returns the constant register holding the value. // Returns the constant register holding the value.
int GetConstantInt(int val); int GetConstantInt(int val);
int GetConstantInt(size_t val) { return GetConstantInt(int(val)); }
int GetConstantInt(unsigned val) { return GetConstantInt(int(val)); }
int GetConstantFloat(double val); int GetConstantFloat(double val);
int GetConstantAddress(void *ptr, VM_ATAG tag); int GetConstantAddress(void *ptr, VM_ATAG tag);
int GetConstantString(FString str); int GetConstantString(FString str);

View file

@ -199,7 +199,7 @@ static int printf_wrapper(FILE *f, const char *fmt, ...)
void VMDumpConstants(FILE *out, const VMScriptFunction *func) void VMDumpConstants(FILE *out, const VMScriptFunction *func)
{ {
char tmp[21]; char tmp[30];
int i, j, k, kk; int i, j, k, kk;
if (func->KonstD != NULL && func->NumKonstD != 0) if (func->KonstD != NULL && func->NumKonstD != 0)
@ -239,7 +239,7 @@ void VMDumpConstants(FILE *out, const VMScriptFunction *func)
for (j = 0, k = i; j < 4 && k < func->NumKonstA; j++, k += kk) for (j = 0, k = i; j < 4 && k < func->NumKonstA; j++, k += kk)
{ {
mysnprintf(tmp, countof(tmp), "%3d. %p:%d", k, func->KonstA[k].v, func->KonstATags()[k]); mysnprintf(tmp, countof(tmp), "%3d. %p:%d", k, func->KonstA[k].v, func->KonstATags()[k]);
printf_wrapper(out, "%-20s", tmp); printf_wrapper(out, "%-22s", tmp);
} }
printf_wrapper(out, "\n"); printf_wrapper(out, "\n");
} }

View file

@ -77,6 +77,10 @@ class Actor : Thinker native
native void VelFromAngle(float speed = 0, float angle = 0); native void VelFromAngle(float speed = 0, float angle = 0);
native bool isFriend(Actor other); native bool isFriend(Actor other);
native void AdjustFloorClip(); native void AdjustFloorClip();
native DropItem GetDropItems();
native void CopyFriendliness (Actor other, bool changeTarget, bool resetHealth = true);
native bool LookForPlayers(bool allaround);
native bool TeleportMove(Vector3 pos, bool telefrag, bool modifyactor = true);
// DECORATE compatible functions // DECORATE compatible functions
native bool CheckClass(class<Actor> checkclass, int ptr_select = AAPTR_DEFAULT, bool match_superclass = false); native bool CheckClass(class<Actor> checkclass, int ptr_select = AAPTR_DEFAULT, bool match_superclass = false);

View file

@ -280,13 +280,12 @@ extend class Actor
} }
*/ */
/*
private void SpawnFly(class<Actor> spawntype, sound snd) private void SpawnFly(class<Actor> spawntype, sound snd)
{ {
AActor newmobj; Actor newmobj;
AActor fog; Actor fog;
AActor eye = master; // The eye is the spawnshot's master, not the target! Actor eye = master; // The eye is the spawnshot's master, not the target!
AActor targ = target; // Unlike other projectiles, the target is the intended destination. Actor targ = target; // Unlike other projectiles, the target is the intended destination.
int r; int r;
// [GZ] Should be more viable than a countdown... // [GZ] Should be more viable than a countdown...
@ -307,7 +306,7 @@ extend class Actor
if (fog) A_PlaySound(snd, CHAN_BODY); if (fog) A_PlaySound(snd, CHAN_BODY);
} }
class<Actor> SpawnName; class<Actor> SpawnName = null;
DropItem di; // di will be our drop item list iterator DropItem di; // di will be our drop item list iterator
DropItem drop; // while drop stays as the reference point. DropItem drop; // while drop stays as the reference point.
@ -334,7 +333,7 @@ extend class Actor
} }
} }
di = drop; di = drop;
n = randon[pr_spawnfly](0, n); n = random[pr_spawnfly](0, n);
while (n >= 0) while (n >= 0)
{ {
if (di.Name != 'none') if (di.Name != 'none')
@ -385,11 +384,11 @@ extend class Actor
// (if the player has made noise). // (if the player has made noise).
newmobj.LastHeard = newmobj.Sector.SoundTarget; newmobj.LastHeard = newmobj.Sector.SoundTarget;
if (newmobj.SeeState != null && newmobj.LookForPlayers (true, null)) if (newmobj.SeeState != null && newmobj.LookForPlayers (true))
{ {
newmobj.SetState (newmobj.SeeState); newmobj.SetState (newmobj.SeeState);
} }
if (!(newmobj.ObjectFlags & OF_EuthanizeMe)) if (!newmobj.bDestroyed)
{ {
// telefrag anything in this spot // telefrag anything in this spot
newmobj.TeleportMove (newmobj.pos, true); newmobj.TeleportMove (newmobj.pos, true);
@ -401,13 +400,8 @@ extend class Actor
// remove self (i.e., cube). // remove self (i.e., cube).
Destroy (); Destroy ();
} }
*/
void A_SpawnFly(class<Actor> spawntype = null)
native
void A_SpawnFly(class<Actor> spawntype = null) // needs special treatment for default
;
/*
{ {
sound snd; sound snd;
if (spawntype != null) if (spawntype != null)
@ -419,18 +413,13 @@ extend class Actor
spawntype = "SpawnFire"; spawntype = "SpawnFire";
snd = "brain/spawn"; snd = "brain/spawn";
} }
SpawnFly(self, spawntype, snd); SpawnFly(spawntype, snd);
} }
*/
native void A_SpawnSound()
void A_SpawnSound()
;
/*
{ {
// travelling cube sound // travelling cube sound
A_PlaySound("brain/cube", CHAN_BODY); A_PlaySound("brain/cube", CHAN_BODY);
SpawnFly("SpawnFire", "brain/spawn"); SpawnFly("SpawnFire", "brain/spawn");
} }
*/
} }