From a45523fb63239a4d9a35a596f0bcb7131c1a56a2 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Thu, 3 Nov 2016 13:38:40 +0100 Subject: [PATCH] - 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. --- src/dobjtype.cpp | 34 +++++++-- src/dobjtype.h | 4 +- src/g_level.cpp | 59 ++++++++++++++ src/g_level.h | 2 +- src/p_enemy.cpp | 7 ++ src/p_map.cpp | 11 +++ src/p_mobj.cpp | 15 ++++ src/scripting/codegeneration/codegen.cpp | 97 +++++++++++++++++++++++- src/scripting/codegeneration/codegen.h | 20 +++++ src/scripting/thingdef.cpp | 2 + src/scripting/thingdef_data.cpp | 17 ++++- src/scripting/vm/vmbuilder.h | 2 + src/scripting/vm/vmdisasm.cpp | 4 +- wadsrc/static/zscript/actor.txt | 4 + wadsrc/static/zscript/doom/bossbrain.txt | 35 +++------ 15 files changed, 274 insertions(+), 39 deletions(-) diff --git a/src/dobjtype.cpp b/src/dobjtype.cpp index 57a67384a..53eedc456 100644 --- a/src/dobjtype.cpp +++ b/src/dobjtype.cpp @@ -2100,6 +2100,7 @@ PStruct::PStruct(FName name, PTypeBase *outer) { mDescriptiveName.Format("Struct<%s>", name.GetChars()); Size = 0; + HasNativeFields = false; } //========================================================================== @@ -2114,7 +2115,7 @@ void PStruct::SetDefaultValue(void *base, unsigned offset, TArrayFlags & 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 *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. field->Offset = (Size + (type->Align - 1)) & ~(type->Align - 1); // 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 // its fields. @@ -2238,6 +2239,29 @@ PField *PStruct::AddField(FName name, PType *type, DWORD flags) 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 @@ -2286,7 +2310,7 @@ PField::PField() } 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; if (bitvalue > -1) @@ -3085,7 +3109,7 @@ PField *PClass::AddField(FName name, PType *type, DWORD flags) { Defaults = (BYTE *)M_Realloc(Defaults, Size); memset(Defaults + oldsize, 0, Size - oldsize); - type->SetDefaultValue(Defaults, field->Offset, &SpecialInits); + type->SetDefaultValue(Defaults, unsigned(field->Offset), &SpecialInits); } return field; } diff --git a/src/dobjtype.h b/src/dobjtype.h index 5aeefac50..db468870f 100644 --- a/src/dobjtype.h +++ b/src/dobjtype.h @@ -574,7 +574,7 @@ class PField : public PSymbol public: PField(FName name, PType *type, DWORD flags = 0, size_t offset = 0, int bitvalue = -1); - unsigned int Offset; + size_t Offset; PType *Type; DWORD Flags; int BitValue; @@ -669,8 +669,10 @@ public: PStruct(FName name, PTypeBase *outer); TArray Fields; + bool HasNativeFields; 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(); diff --git a/src/g_level.cpp b/src/g_level.cpp index 9e8448879..5b0c46fa2 100644 --- a/src/g_level.cpp +++ b/src/g_level.cpp @@ -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 diff --git a/src/g_level.h b/src/g_level.h index 2b0de7b68..790eba344 100644 --- a/src/g_level.h +++ b/src/g_level.h @@ -260,7 +260,7 @@ struct FOptionalMapinfoDataPtr typedef TMap FOptData; typedef TMap FMusicMap; -enum EMapType +enum EMapType : int { MAPTYPE_UNKNOWN = 0, MAPTYPE_DOOM, diff --git a/src/p_enemy.cpp b/src/p_enemy.cpp index 77082f3a4..833732008 100644 --- a/src/p_enemy.cpp +++ b/src/p_enemy.cpp @@ -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 // diff --git a/src/p_map.cpp b/src/p_map.cpp index a2e83b73f..d7bffa589 100644 --- a/src/p_map.cpp +++ b/src/p_map.cpp @@ -444,6 +444,17 @@ bool P_TeleportMove(AActor* thing, const DVector3 &pos, bool telefrag, bool modi 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 diff --git a/src/p_mobj.cpp b/src/p_mobj.cpp index bd78fdcef..08b662767 100644 --- a/src/p_mobj.cpp +++ b/src/p_mobj.cpp @@ -990,6 +990,15 @@ void AActor::CopyFriendliness (AActor *other, bool changeTarget, bool resetHealt 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 @@ -6515,6 +6524,12 @@ DDropItem *AActor::GetDropItems() const return GetClass()->DropItems; } +DEFINE_ACTION_FUNCTION(AActor, GetDropItems) +{ + PARAM_SELF_PROLOGUE(AActor); + ACTION_RETURN_OBJECT(self->GetDropItems()); +} + double AActor::GetGravity() const { if (flags & MF_NOGRAVITY) return 0; diff --git a/src/scripting/codegeneration/codegen.cpp b/src/scripting/codegeneration/codegen.cpp index 620d9feed..50cd7699b 100644 --- a/src/scripting/codegeneration/codegen.cpp +++ b/src/scripting/codegeneration/codegen.cpp @@ -5067,6 +5067,12 @@ FxExpression *FxIdentifier::Resolve(FCompileContext& ctx) ScriptPosition.Message(MSG_DEBUGLOG, "Resolving name '%s' as global constant\n", Identifier.GetChars()); 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(sym), ScriptPosition); + } else { 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; return x; } + else if (classx->ExprType == EFX_GlobalVariable) + { + auto parentfield = static_cast(classx)->membervar; + auto newfield = new PField(membervar->SymbolName, membervar->Type, membervar->Flags | parentfield->Flags, membervar->Offset + parentfield->Offset, membervar->BitValue); + static_cast(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 { // since this is a vector, all potential things that may get here are single float or an xy-vector. auto locvar = static_cast(classx); - locvar->RegOffset = membervar->Offset / 8; + locvar->RegOffset = int(membervar->Offset / 8); locvar->ValueType = membervar->Type; classx = nullptr; delete this; @@ -5816,13 +5898,15 @@ FxExpression *FxFunctionCall::Resolve(FCompileContext& ctx) case NAME_Name: case NAME_Color: case NAME_Sound: + case NAME_State: if (CheckArgSize(MethodName, ArgList, 1, 1, ScriptPosition)) { PType *type = MethodName == NAME_Int ? TypeSInt32 : MethodName == NAME_uInt ? TypeUInt32 : MethodName == NAME_Double ? TypeFloat64 : 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); (*ArgList)[0] = nullptr; @@ -6615,14 +6699,19 @@ ExpEmit FxVectorBuiltin::Emit(VMFunctionBuilder *build) FxExpression *FxSequence::Resolve(FCompileContext &ctx) { CHECKRESOLVED(); + bool fail = false; for (unsigned i = 0; i < Expressions.Size(); ++i) { if (nullptr == (Expressions[i] = Expressions[i]->Resolve(ctx))) { - delete this; - return nullptr; + fail = true; } } + if (fail) + { + delete this; + return nullptr; + } return this; } diff --git a/src/scripting/codegeneration/codegen.h b/src/scripting/codegeneration/codegen.h index ee792e5bf..b118b8d5d 100644 --- a/src/scripting/codegeneration/codegen.h +++ b/src/scripting/codegeneration/codegen.h @@ -269,6 +269,7 @@ enum EFxType EFX_VectorBuiltin, EFX_TypeCheck, EFX_DynamicCast, + EFX_GlobalVariable, 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 diff --git a/src/scripting/thingdef.cpp b/src/scripting/thingdef.cpp index 8c42e8987..38bf2bcf6 100644 --- a/src/scripting/thingdef.cpp +++ b/src/scripting/thingdef.cpp @@ -215,6 +215,7 @@ void CreateDamageFunction(PClassActor *info, AActor *defaults, FxExpression *id, //========================================================================== void ParseScripts(); void ParseAllDecorate(); +void G_InitLevelLocalsForScript(); void LoadActors () { @@ -223,6 +224,7 @@ void LoadActors () timer.Reset(); timer.Clock(); FScriptPosition::ResetErrorCounter(); + G_InitLevelLocalsForScript(); InitThingdef(); FScriptPosition::StrictErrors = true; ParseScripts(); diff --git a/src/scripting/thingdef_data.cpp b/src/scripting/thingdef_data.cpp index b0edcb167..4d18a083b 100644 --- a/src/scripting/thingdef_data.cpp +++ b/src/scripting/thingdef_data.cpp @@ -673,10 +673,16 @@ void InitThingdef() 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 PSymbolTable &symt = RUNTIME_CLASS(AActor)->Symbols; 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_Angle, TypeFloat64, VARF_Native, myoffsetof(AActor, Angles.Yaw))); 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("RipLevelMin", TypeSInt32, VARF_Native, myoffsetof(AActor, RipLevelMin))); 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_VisibleStartPitch, TypeFloat64, VARF_Native, myoffsetof(AActor, VisibleStartPitch))); 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("AttackSound", TypeSound, VARF_Native, myoffsetof(AActor, AttackSound))); 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("Vel", TypeVector3, VARF_Native, myoffsetof(AActor, Vel))); symt.AddSymbol(new PField("Scale", TypeVector2, VARF_Native, myoffsetof(AActor, Scale))); @@ -761,8 +769,11 @@ void InitThingdef() PSymbolTable &symt2 = RUNTIME_CLASS(DDropItem)->Symbols; PType *TypeDropItem = NewPointer(RUNTIME_CLASS(DDropItem)); 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("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*/)); } diff --git a/src/scripting/vm/vmbuilder.h b/src/scripting/vm/vmbuilder.h index 9a97c216d..c94d85f3c 100644 --- a/src/scripting/vm/vmbuilder.h +++ b/src/scripting/vm/vmbuilder.h @@ -30,6 +30,8 @@ public: // Returns the constant register holding the value. 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 GetConstantAddress(void *ptr, VM_ATAG tag); int GetConstantString(FString str); diff --git a/src/scripting/vm/vmdisasm.cpp b/src/scripting/vm/vmdisasm.cpp index ea199612c..239a0dc51 100644 --- a/src/scripting/vm/vmdisasm.cpp +++ b/src/scripting/vm/vmdisasm.cpp @@ -199,7 +199,7 @@ static int printf_wrapper(FILE *f, const char *fmt, ...) void VMDumpConstants(FILE *out, const VMScriptFunction *func) { - char tmp[21]; + char tmp[30]; int i, j, k, kk; 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) { 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"); } diff --git a/wadsrc/static/zscript/actor.txt b/wadsrc/static/zscript/actor.txt index 0b3c4d40b..091fba4b5 100644 --- a/wadsrc/static/zscript/actor.txt +++ b/wadsrc/static/zscript/actor.txt @@ -77,6 +77,10 @@ class Actor : Thinker native native void VelFromAngle(float speed = 0, float angle = 0); native bool isFriend(Actor other); 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 native bool CheckClass(class checkclass, int ptr_select = AAPTR_DEFAULT, bool match_superclass = false); diff --git a/wadsrc/static/zscript/doom/bossbrain.txt b/wadsrc/static/zscript/doom/bossbrain.txt index 641263ecc..cb30e886b 100644 --- a/wadsrc/static/zscript/doom/bossbrain.txt +++ b/wadsrc/static/zscript/doom/bossbrain.txt @@ -280,13 +280,12 @@ extend class Actor } */ - /* private void SpawnFly(class spawntype, sound snd) { - AActor newmobj; - AActor fog; - AActor 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 newmobj; + Actor fog; + Actor eye = master; // The eye is the spawnshot's master, not the target! + Actor targ = target; // Unlike other projectiles, the target is the intended destination. int r; // [GZ] Should be more viable than a countdown... @@ -307,7 +306,7 @@ extend class Actor if (fog) A_PlaySound(snd, CHAN_BODY); } - class SpawnName; + class SpawnName = null; DropItem di; // di will be our drop item list iterator DropItem drop; // while drop stays as the reference point. @@ -334,7 +333,7 @@ extend class Actor } } di = drop; - n = randon[pr_spawnfly](0, n); + n = random[pr_spawnfly](0, n); while (n >= 0) { if (di.Name != 'none') @@ -385,11 +384,11 @@ extend class Actor // (if the player has made noise). newmobj.LastHeard = newmobj.Sector.SoundTarget; - if (newmobj.SeeState != null && newmobj.LookForPlayers (true, null)) + if (newmobj.SeeState != null && newmobj.LookForPlayers (true)) { newmobj.SetState (newmobj.SeeState); } - if (!(newmobj.ObjectFlags & OF_EuthanizeMe)) + if (!newmobj.bDestroyed) { // telefrag anything in this spot newmobj.TeleportMove (newmobj.pos, true); @@ -401,13 +400,8 @@ extend class Actor // remove self (i.e., cube). Destroy (); } - */ - - native - void A_SpawnFly(class spawntype = null) // needs special treatment for default - ; - /* + void A_SpawnFly(class spawntype = null) { sound snd; if (spawntype != null) @@ -419,18 +413,13 @@ extend class Actor spawntype = "SpawnFire"; snd = "brain/spawn"; } - SpawnFly(self, spawntype, snd); + SpawnFly(spawntype, snd); } - */ - - native - void A_SpawnSound() - ; - /* + + void A_SpawnSound() { // travelling cube sound A_PlaySound("brain/cube", CHAN_BODY); SpawnFly("SpawnFire", "brain/spawn"); } - */ }