diff --git a/CMakeLists.txt b/CMakeLists.txt index e9c955c9e..627d4c398 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -276,7 +276,7 @@ else() # If we're compiling with a custom GCC on the Mac (which we know since g++-4.2 doesn't support C++11) statically link libgcc. set( ALL_C_FLAGS "-static-libgcc" ) endif() - elseif( NOT MINGW ) + elseif( NOT MINGW AND NOT HAIKU ) # Generic GCC/Clang requires position independent executable to be enabled explicitly set( ALL_C_FLAGS "${ALL_C_FLAGS} -fPIE" ) set( CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -pie" ) diff --git a/libraries/ZVulkan/CMakeLists.txt b/libraries/ZVulkan/CMakeLists.txt index ef2c9e749..79e719dcb 100644 --- a/libraries/ZVulkan/CMakeLists.txt +++ b/libraries/ZVulkan/CMakeLists.txt @@ -202,7 +202,11 @@ if(WIN32) add_definitions(-DUNICODE -D_UNICODE) else() set(ZVULKAN_SOURCES ${ZVULKAN_SOURCES} ${ZVULKAN_UNIX_SOURCES}) - set(ZVULKAN_LIBS ${CMAKE_DL_LIBS} -ldl) + if(NOT HAIKU) + set(ZVULKAN_LIBS ${CMAKE_DL_LIBS} -ldl) + else() + set(ZVULKAN_LIBS ${CMAKE_DL_LIBS}) + endif() add_definitions(-DUNIX -D_UNIX) add_link_options(-pthread) endif() diff --git a/libraries/ZWidget/include/zwidget/window/window.h b/libraries/ZWidget/include/zwidget/window/window.h index ad59f1f02..f5a8da734 100644 --- a/libraries/ZWidget/include/zwidget/window/window.h +++ b/libraries/ZWidget/include/zwidget/window/window.h @@ -1,5 +1,6 @@ #pragma once +#include #include #include #include diff --git a/src/am_map.cpp b/src/am_map.cpp index 2466c0fdb..96740a144 100644 --- a/src/am_map.cpp +++ b/src/am_map.cpp @@ -170,6 +170,7 @@ CVAR(Bool, am_showmonsters, true, CVAR_ARCHIVE); CVAR(Bool, am_showitems, true, CVAR_ARCHIVE); CVAR(Bool, am_showtime, true, CVAR_ARCHIVE); CVAR(Bool, am_showtotaltime, false, CVAR_ARCHIVE); +CVAR(Bool, am_showlevelname, true, CVAR_ARCHIVE); CVAR(Int, am_colorset, 0, CVAR_ARCHIVE); CVAR(Bool, am_customcolors, true, CVAR_ARCHIVE); CVAR(Int, am_map_secrets, 1, CVAR_ARCHIVE); diff --git a/src/common/console/c_cvars.h b/src/common/console/c_cvars.h index 0fb2e6eb4..a7cda61e3 100644 --- a/src/common/console/c_cvars.h +++ b/src/common/console/c_cvars.h @@ -594,6 +594,8 @@ class FBoolCVarRef { FBoolCVar* ref; public: + int operator= (const FBoolCVarRef&) = delete; + int operator= (FBoolCVarRef&&) = delete; inline bool operator= (bool val) { *ref = val; return val; } inline operator bool () const { return **ref; } @@ -607,7 +609,11 @@ class FIntCVarRef FIntCVar* ref; public: + int operator= (const FIntCVarRef&) = delete; + int operator= (FIntCVarRef&&) = delete; + int operator= (int val) { *ref = val; return val; } + inline operator int () const { return **ref; } inline int operator *() const { return **ref; } inline FIntCVar* operator->() { return ref; } @@ -618,6 +624,8 @@ class FFloatCVarRef { FFloatCVar* ref; public: + int operator= (const FFloatCVarRef&) = delete; + int operator= (FFloatCVarRef&&) = delete; float operator= (float val) { *ref = val; return val; } inline operator float () const { return **ref; } @@ -630,6 +638,8 @@ class FStringCVarRef { FStringCVar* ref; public: + int operator= (const FStringCVarRef&) = delete; + int operator= (FStringCVarRef&&) = delete; const char* operator= (const char* val) { *ref = val; return val; } inline operator const char* () const { return **ref; } @@ -642,6 +652,8 @@ class FColorCVarRef { FColorCVar* ref; public: + int operator= (const FColorCVarRef&) = delete; + int operator= (FColorCVarRef&&) = delete; //uint32_t operator= (uint32_t val) { *ref = val; return val; } inline operator uint32_t () const { return **ref; } @@ -654,6 +666,9 @@ class FFlagCVarRef { FFlagCVar* ref; public: + int operator= (const FFlagCVarRef&) = delete; + int operator= (FFlagCVarRef&&) = delete; + inline bool operator= (bool val) { *ref = val; return val; } inline bool operator= (const FFlagCVar& val) { *ref = val; return val; } inline operator int () const { return **ref; } @@ -665,6 +680,9 @@ class FMaskCVarRef { FMaskCVar* ref; public: + int operator= (const FMaskCVarRef&) = delete; + int operator= (FMaskCVarRef&&) = delete; + //int operator= (int val) { *ref = val; return val; } inline operator int () const { return **ref; } inline int operator *() const { return **ref; } diff --git a/src/common/cutscenes/screenjob.cpp b/src/common/cutscenes/screenjob.cpp index de1da996f..83dd3113a 100644 --- a/src/common/cutscenes/screenjob.cpp +++ b/src/common/cutscenes/screenjob.cpp @@ -270,8 +270,10 @@ void ScreenJobDraw() ScaleOverrider ovr(twod); IFVIRTUALPTRNAME(cutscene.runner, NAME_ScreenJobRunner, RunFrame) { + int ret = 0; VMValue parm[] = { cutscene.runner, smoothratio }; - VMCall(func, parm, 2, nullptr, 0); + VMReturn rets[] = { &ret }; + VMCall(func, parm, 2, rets, 1); } } } diff --git a/src/common/engine/i_specialpaths.h b/src/common/engine/i_specialpaths.h index 01710b672..fb75230f5 100644 --- a/src/common/engine/i_specialpaths.h +++ b/src/common/engine/i_specialpaths.h @@ -2,7 +2,7 @@ #include "zstring.h" -#ifdef __unix__ +#if defined(__unix__) || defined(__HAIKU__) FString GetUserFile (const char *path); #endif FString M_GetAppDataPath(bool create); diff --git a/src/common/engine/sc_man.h b/src/common/engine/sc_man.h index a385b983c..5570e27c7 100644 --- a/src/common/engine/sc_man.h +++ b/src/common/engine/sc_man.h @@ -85,6 +85,11 @@ public: ParseVersion = ver; } + bool CheckParseVersion(VersionInfo ver) + { + return ParseVersion >= ver; + } + void SetCMode(bool cmode); void SetNoOctals(bool cmode) { NoOctals = cmode; } void SetNoFatalErrors(bool cmode) { NoFatalErrors = cmode; } diff --git a/src/common/engine/sc_man_scanner.re b/src/common/engine/sc_man_scanner.re index 5af7e62f9..83158632b 100644 --- a/src/common/engine/sc_man_scanner.re +++ b/src/common/engine/sc_man_scanner.re @@ -177,6 +177,7 @@ std2: /* Other keywords from UnrealScript */ 'abstract' { RET(TK_Abstract); } 'foreach' { RET(ParseVersion >= MakeVersion(4, 10, 0)? TK_ForEach : TK_Identifier); } + 'unsafe' { RET(ParseVersion >= MakeVersion(4, 14, 2)? TK_Unsafe : TK_Identifier); } 'true' { RET(TK_True); } 'false' { RET(TK_False); } 'none' { RET(TK_None); } diff --git a/src/common/engine/sc_man_tokens.h b/src/common/engine/sc_man_tokens.h index 487003125..85bb55d42 100644 --- a/src/common/engine/sc_man_tokens.h +++ b/src/common/engine/sc_man_tokens.h @@ -80,6 +80,7 @@ xx(TK_Color, "'color'") xx(TK_Goto, "'goto'") xx(TK_Abstract, "'abstract'") xx(TK_ForEach, "'foreach'") +xx(TK_Unsafe, "'unsafe'") xx(TK_True, "'true'") xx(TK_False, "'false'") xx(TK_None, "'none'") diff --git a/src/common/scripting/backend/codegen.cpp b/src/common/scripting/backend/codegen.cpp index 1fcaeae2c..d06841c83 100644 --- a/src/common/scripting/backend/codegen.cpp +++ b/src/common/scripting/backend/codegen.cpp @@ -12748,16 +12748,15 @@ ExpEmit FxFunctionPtrCast::Emit(VMFunctionBuilder *build) FxLocalVariableDeclaration::FxLocalVariableDeclaration(PType *type, FName name, FxExpression *initval, int varflags, const FScriptPosition &p) :FxExpression(EFX_LocalVariableDeclaration, p) { - // Local FVector isn't different from Vector - if (type == TypeFVector2) type = TypeVector2; - else if (type == TypeFVector3) type = TypeVector3; - else if (type == TypeFVector4) type = TypeVector4; - else if (type == TypeFQuaternion) type = TypeQuaternion; + if(type != type->GetLocalType()) + { + ScriptPosition.Message(MSG_WARNING, "Type '%s' not allowed in local variables, changing to '%s'", type->DescriptiveName(), type->GetLocalType()->DescriptiveName()); + } - ValueType = type; + ValueType = type->GetLocalType(); VarFlags = varflags; Name = name; - RegCount = type->RegCount; + RegCount = ValueType->RegCount; Init = initval; clearExpr = nullptr; } diff --git a/src/common/scripting/core/types.cpp b/src/common/scripting/core/types.cpp index d99f7eb13..20ce7e05d 100644 --- a/src/common/scripting/core/types.cpp +++ b/src/common/scripting/core/types.cpp @@ -359,6 +359,7 @@ void PType::StaticInit() TypeVector2->RegType = REGT_FLOAT; TypeVector2->RegCount = 2; TypeVector2->isOrdered = true; + TypeVector2->mDescriptiveName = "Vector2"; TypeVector3 = new PStruct(NAME_Vector3, nullptr); TypeVector3->AddField(NAME_X, TypeFloat64); @@ -373,6 +374,7 @@ void PType::StaticInit() TypeVector3->RegType = REGT_FLOAT; TypeVector3->RegCount = 3; TypeVector3->isOrdered = true; + TypeVector3->mDescriptiveName = "Vector3"; TypeVector4 = new PStruct(NAME_Vector4, nullptr); TypeVector4->AddField(NAME_X, TypeFloat64); @@ -389,6 +391,7 @@ void PType::StaticInit() TypeVector4->RegType = REGT_FLOAT; TypeVector4->RegCount = 4; TypeVector4->isOrdered = true; + TypeVector4->mDescriptiveName = "Vector4"; TypeFVector2 = new PStruct(NAME_FVector2, nullptr); @@ -401,6 +404,8 @@ void PType::StaticInit() TypeFVector2->RegType = REGT_FLOAT; TypeFVector2->RegCount = 2; TypeFVector2->isOrdered = true; + TypeFVector2->mDescriptiveName = "FVector2"; + TypeFVector2->SetLocalType(TypeVector2); TypeFVector3 = new PStruct(NAME_FVector3, nullptr); TypeFVector3->AddField(NAME_X, TypeFloat32); @@ -415,6 +420,8 @@ void PType::StaticInit() TypeFVector3->RegType = REGT_FLOAT; TypeFVector3->RegCount = 3; TypeFVector3->isOrdered = true; + TypeFVector3->mDescriptiveName = "FVector3"; + TypeFVector3->SetLocalType(TypeVector3); TypeFVector4 = new PStruct(NAME_FVector4, nullptr); TypeFVector4->AddField(NAME_X, TypeFloat32); @@ -431,6 +438,8 @@ void PType::StaticInit() TypeFVector4->RegType = REGT_FLOAT; TypeFVector4->RegCount = 4; TypeFVector4->isOrdered = true; + TypeFVector4->mDescriptiveName = "FVector4"; + TypeFVector4->SetLocalType(TypeVector4); TypeQuaternion = new PStruct(NAME_Quat, nullptr); @@ -447,6 +456,7 @@ void PType::StaticInit() TypeQuaternion->moveOp = OP_MOVEV4; TypeQuaternion->RegType = REGT_FLOAT; TypeQuaternion->RegCount = 4; + TypeQuaternion->mDescriptiveName = "Quat"; TypeQuaternion->isOrdered = true; TypeFQuaternion = new PStruct(NAME_FQuat, nullptr); @@ -464,6 +474,8 @@ void PType::StaticInit() TypeFQuaternion->RegType = REGT_FLOAT; TypeFQuaternion->RegCount = 4; TypeFQuaternion->isOrdered = true; + TypeFQuaternion->mDescriptiveName = "FQuat"; + TypeFQuaternion->SetLocalType(TypeQuaternion); Namespaces.GlobalNamespace->Symbols.AddSymbol(Create(NAME_sByte, TypeSInt8)); diff --git a/src/common/scripting/core/types.h b/src/common/scripting/core/types.h index f09ddb32b..8ae8b92ea 100644 --- a/src/common/scripting/core/types.h +++ b/src/common/scripting/core/types.h @@ -109,6 +109,13 @@ public: EScopeFlags ScopeFlags = (EScopeFlags)0; bool SizeKnown = true; + bool VMInternalStruct = false; + + PType * LocalType = nullptr; + + PType * SetLocalType(PType * LocalType) { this->LocalType = LocalType; return this; } + PType * GetLocalType() { return LocalType ? LocalType : this; } + PType(unsigned int size = 1, unsigned int align = 1); virtual ~PType(); virtual bool isNumeric() { return false; } diff --git a/src/common/scripting/frontend/zcc-parse.lemon b/src/common/scripting/frontend/zcc-parse.lemon index 199771949..95e99cfa3 100644 --- a/src/common/scripting/frontend/zcc-parse.lemon +++ b/src/common/scripting/frontend/zcc-parse.lemon @@ -427,11 +427,12 @@ struct_def(X) ::= EXTEND STRUCT(T) IDENTIFIER(A) LBRACE opt_struct_body(B) RBRAC } %type struct_flags{ClassFlagsBlock} -struct_flags(X) ::= . { X.Flags = 0; X.Version = {0, 0}; } -struct_flags(X) ::= struct_flags(A) UI. { X.Flags = A.Flags | ZCC_UIFlag; } -struct_flags(X) ::= struct_flags(A) PLAY. { X.Flags = A.Flags | ZCC_Play; } -struct_flags(X) ::= struct_flags(A) CLEARSCOPE. { X.Flags = A.Flags | ZCC_ClearScope; } -struct_flags(X) ::= struct_flags(A) NATIVE. { X.Flags = A.Flags | ZCC_Native; } +struct_flags(X) ::= . { X.Flags = 0; X.Version = {0, 0}; } +struct_flags(X) ::= struct_flags(A) UI. { X.Flags = A.Flags | ZCC_UIFlag; X.Version = A.Version; } +struct_flags(X) ::= struct_flags(A) PLAY. { X.Flags = A.Flags | ZCC_Play; X.Version = A.Version; } +struct_flags(X) ::= struct_flags(A) CLEARSCOPE. { X.Flags = A.Flags | ZCC_ClearScope; X.Version = A.Version; } +struct_flags(X) ::= struct_flags(A) NATIVE. { X.Flags = A.Flags | ZCC_Native; X.Version = A.Version; } +struct_flags(X) ::= struct_flags(A) UNSAFE LPAREN INTERNAL RPAREN. { X.Flags = A.Flags | ZCC_VMInternalStruct; X.Version = A.Version; } struct_flags(X) ::= struct_flags(A) VERSION LPAREN STRCONST(C) RPAREN. { X.Flags = A.Flags | ZCC_Version; X.Version = C.String->GetChars(); } opt_struct_body(X) ::= . { X = NULL; } @@ -957,6 +958,7 @@ type_name(X) ::= DOT dottable_id(A). /* Aggregate types */ %type aggregate_type {ZCC_Type *} +%type aggregate_type_pre {ZCC_Type *} %type type {ZCC_Type *} %type type_list {ZCC_Type *} %type type_list_or_void {ZCC_Type *} @@ -965,30 +967,92 @@ type_name(X) ::= DOT dottable_id(A). %type array_size{ZCC_Expression *} %type array_size_expr{ZCC_Expression *} -aggregate_type(X) ::= MAP(T) LT type_or_array(A) COMMA type_or_array(B) GT. /* ZSMap */ +aggregate_type_pre(X) ::= MAP(T) LT type_or_array(A) COMMA type_or_array(B). /* ZSMap */ { NEW_AST_NODE(MapType,map,T); map->KeyType = A; map->ValueType = B; X = map; + X->ArraySize = NULL; } -aggregate_type(X) ::= MAPITERATOR(T) LT type_or_array(A) COMMA type_or_array(B) GT. /* ZSMapIterator */ +aggregate_type_pre(X) ::= MAPITERATOR(T) LT type_or_array(A) COMMA type_or_array(B). /* ZSMapIterator */ { NEW_AST_NODE(MapIteratorType,map_it,T); map_it->KeyType = A; map_it->ValueType = B; X = map_it; + X->ArraySize = NULL; } -aggregate_type(X) ::= ARRAY(T) LT type_or_array(A) GT. /* TArray */ +aggregate_type_pre(X) ::= ARRAY(T) LT type_or_array(A). /* TArray */ { NEW_AST_NODE(DynArrayType,arr,T); arr->ElementType = A; X = arr; + X->ArraySize = NULL; } -aggregate_type(X) ::= func_ptr_type(A). { X = A; /*X-overwrites-A*/ } +aggregate_type_pre(X) ::= func_ptr_type(A). { X = A; /*X-overwrites-A*/ X->ArraySize = NULL; } + +aggregate_type_pre(X) ::= CLASS(T) LT dottable_id(A). /* class */ +{ + NEW_AST_NODE(ClassType,cls,T); + cls->Restriction = A; + X = cls; + X->ArraySize = NULL; +} + +aggregate_type(X) ::= aggregate_type_pre(A) GT. { X = A; X->ArraySize = NULL; } + +aggregate_type(X) ::= MAP(T) LT type_or_array(A) COMMA aggregate_type_pre(B) RSH. /* ZSMap> */ +{ + if(!stat->sc->CheckParseVersion(MakeVersion(4, 15, 1))) + { + stat->sc->ScriptMessage(">> without space in parametrized types only supported for zscript >= 4.15.1"); + FScriptPosition::ErrorCounter++; + } + NEW_AST_NODE(MapType,map,T); + map->KeyType = A; + map->ValueType = B; + X = map; + X->ArraySize = NULL; +} + +aggregate_type(X) ::= MAPITERATOR(T) LT type_or_array(A) COMMA aggregate_type_pre(B) RSH. /* ZSMapIterator> */ +{ + if(!stat->sc->CheckParseVersion(MakeVersion(4, 15, 1))) + { + stat->sc->ScriptMessage(">> without space in parametrized types only supported for zscript >= 4.15.1"); + FScriptPosition::ErrorCounter++; + } + NEW_AST_NODE(MapIteratorType,map_it,T); + map_it->KeyType = A; + map_it->ValueType = B; + X = map_it; + X->ArraySize = NULL; +} + +aggregate_type(X) ::= ARRAY(T) LT aggregate_type_pre(A) RSH. /* TArray> */ +{ + if(!stat->sc->CheckParseVersion(MakeVersion(4, 15, 1))) + { + stat->sc->ScriptMessage(">> without space in parametrized types only supported for zscript >= 4.15.1"); + FScriptPosition::ErrorCounter++; + } + NEW_AST_NODE(DynArrayType,arr,T); + arr->ElementType = A; + X = arr; + X->ArraySize = NULL; +} + +aggregate_type(X) ::= CLASS(T). /* class */ +{ + NEW_AST_NODE(ClassType,cls,T); + cls->Restriction = NULL; + X = cls; + X->ArraySize = NULL; +} %type func_ptr_type {ZCC_FuncPtrType *} %type func_ptr_params {ZCC_FuncPtrParamDecl *} @@ -1002,7 +1066,7 @@ fn_ptr_flag(X) ::= CLEARSCOPE. { X.Int = ZCC_ClearScope; } //fn_ptr_flag(X) ::= VIRTUALSCOPE. { X.Int = ZCC_VirtualScope; } //virtual scope not allowed -func_ptr_type(X) ::= FNTYPE(T) LT fn_ptr_flag(F) type_list_or_void(A) LPAREN func_ptr_params(B) RPAREN GT. /* Function<...(...)> */ +func_ptr_type(X) ::= FNTYPE(T) LT fn_ptr_flag(F) type_list_or_void(A) LPAREN func_ptr_params(B) RPAREN. /* Function<...(...)> */ { NEW_AST_NODE(FuncPtrType,fn_ptr,T); fn_ptr->RetType = A; @@ -1011,7 +1075,7 @@ func_ptr_type(X) ::= FNTYPE(T) LT fn_ptr_flag(F) type_list_or_void(A) LPAREN fun X = fn_ptr; } -func_ptr_type(X) ::= FNTYPE(T) LT VOID GT. /* Function */ +func_ptr_type(X) ::= FNTYPE(T) LT VOID. /* Function */ { NEW_AST_NODE(FuncPtrType,fn_ptr,T); fn_ptr->RetType = nullptr; @@ -1053,15 +1117,6 @@ func_ptr_param(X) ::= func_param_flags(A) type(B) AND. X = parm; } -aggregate_type(X) ::= CLASS(T) class_restrictor(A). /* class */ -{ - NEW_AST_NODE(ClassType,cls,T); - cls->Restriction = A; - X = cls; -} -class_restrictor(X) ::= . { X = NULL; } -class_restrictor(X) ::= LT dottable_id(A) GT. { X = A; /*X-overwrites-A*/ } - type(X) ::= type_name(A). { X = A; /*X-overwrites-A*/ X->ArraySize = NULL; } type(X) ::= aggregate_type(A). { X = A; /*X-overwrites-A*/ X->ArraySize = NULL; } @@ -1474,7 +1529,7 @@ primary(X) ::= LPAREN CLASS LT IDENTIFIER(A) GT RPAREN LPAREN func_expr_list(B) X = expr; } -primary(X) ::= LPAREN func_ptr_type(A) RPAREN LPAREN expr(B) RPAREN. [DOT] // function pointer type cast +primary(X) ::= LPAREN func_ptr_type(A) GT RPAREN LPAREN expr(B) RPAREN. [DOT] // function pointer type cast { NEW_AST_NODE(FunctionPtrCast, expr, A); expr->Operation = PEX_FunctionPtrCast; diff --git a/src/common/scripting/frontend/zcc_compile.cpp b/src/common/scripting/frontend/zcc_compile.cpp index a3296795e..fdc34b117 100644 --- a/src/common/scripting/frontend/zcc_compile.cpp +++ b/src/common/scripting/frontend/zcc_compile.cpp @@ -734,6 +734,8 @@ void ZCCCompiler::CreateStructTypes() syms = &OutNamespace->Symbols; } + + if (s->NodeName() == NAME__ && fileSystem.GetFileContainer(Lump) == 0) { // This is just a container for syntactic purposes. @@ -748,11 +750,24 @@ void ZCCCompiler::CreateStructTypes() { s->strct->Type = NewStruct(s->NodeName(), outer, false, AST.FileNo); } + if (s->strct->Flags & ZCC_Version) { s->strct->Type->mVersion = s->strct->Version; } + if (s->strct->Flags & ZCC_VMInternalStruct) + { + if(fileSystem.GetFileContainer(Lump) == 0) + { + s->strct->Type->VMInternalStruct = true; + } + else + { + Error(s->strct, "Internal structs are only allowed in the root pk3"); + } + } + auto &sf = s->Type()->ScopeFlags; if (mVersion >= MakeVersion(2, 4, 0)) { @@ -814,6 +829,12 @@ void ZCCCompiler::CreateClassTypes() PClass *parent; auto ParentName = c->cls->ParentName; + if (c->cls->Flags & ZCC_Internal) + { + Error(c->cls, "'Internal' not allowed for classes"); + } + + // The parent exists, we may create a type for this class if (ParentName != nullptr && ParentName->SiblingNext == ParentName) { parent = PClass::FindClass(ParentName->Id); @@ -850,7 +871,6 @@ void ZCCCompiler::CreateClassTypes() Error(c->cls, "Class '%s' cannot extend sealed class '%s'", FName(c->NodeName()).GetChars(), parent->TypeName.GetChars()); } - // The parent exists, we may create a type for this class if (c->cls->Flags & ZCC_Native) { // If this is a native class, its own type must also already exist and not be a runtime class. @@ -1873,7 +1893,7 @@ PType *ZCCCompiler::DetermineType(PType *outertype, ZCC_TreeNode *field, FName n { Error(field, "%s: @ not allowed for user scripts", name.GetChars()); } - retval = ResolveUserType(btype, btype->UserType, outertype? &outertype->Symbols : nullptr, true); + retval = ResolveUserType(outertype, btype, btype->UserType, outertype? &outertype->Symbols : nullptr, true); break; case ZCC_UserType: @@ -1903,7 +1923,7 @@ PType *ZCCCompiler::DetermineType(PType *outertype, ZCC_TreeNode *field, FName n default: - retval = ResolveUserType(btype, btype->UserType, outertype ? &outertype->Symbols : nullptr, false); + retval = ResolveUserType(outertype, btype, btype->UserType, outertype ? &outertype->Symbols : nullptr, false); break; } break; @@ -2158,7 +2178,7 @@ PType *ZCCCompiler::DetermineType(PType *outertype, ZCC_TreeNode *field, FName n * @param nativetype Distinguishes between searching for a native type or a user type. * @returns the PType found for this user type */ -PType *ZCCCompiler::ResolveUserType(ZCC_BasicType *type, ZCC_Identifier *id, PSymbolTable *symt, bool nativetype) +PType *ZCCCompiler::ResolveUserType(PType *outertype, ZCC_BasicType *type, ZCC_Identifier *id, PSymbolTable *symt, bool nativetype) { // Check the symbol table for the identifier. PSymbol *sym = nullptr; @@ -2175,10 +2195,18 @@ PType *ZCCCompiler::ResolveUserType(ZCC_BasicType *type, ZCC_Identifier *id, PSy return TypeError; } + //only allow references to internal types inside internal types + if (ptype->VMInternalStruct && !outertype->VMInternalStruct) + { + Error(type, "Type %s not accessible", FName(type->UserType->Id).GetChars()); + return TypeError; + } + if (id->SiblingNext != type->UserType) { assert(id->SiblingNext->NodeType == AST_Identifier); ptype = ResolveUserType( + outertype, type, static_cast(id->SiblingNext), &ptype->Symbols, diff --git a/src/common/scripting/frontend/zcc_compile.h b/src/common/scripting/frontend/zcc_compile.h index 19e9f8ff0..bf1407189 100644 --- a/src/common/scripting/frontend/zcc_compile.h +++ b/src/common/scripting/frontend/zcc_compile.h @@ -134,7 +134,7 @@ protected: FString FlagsToString(uint32_t flags); PType *DetermineType(PType *outertype, ZCC_TreeNode *field, FName name, ZCC_Type *ztype, bool allowarraytypes, bool formember); PType *ResolveArraySize(PType *baseType, ZCC_Expression *arraysize, PContainerType *cls, bool *nosize); - PType *ResolveUserType(ZCC_BasicType *type, ZCC_Identifier *id, PSymbolTable *sym, bool nativetype); + PType *ResolveUserType(PType *outertype, ZCC_BasicType *type, ZCC_Identifier *id, PSymbolTable *sym, bool nativetype); static FString UserTypeName(ZCC_BasicType *type); TArray OrderStructs(); void AddStruct(TArray &new_order, ZCC_StructWork *struct_def); diff --git a/src/common/scripting/frontend/zcc_parser.cpp b/src/common/scripting/frontend/zcc_parser.cpp index a713f2052..40d0564c7 100644 --- a/src/common/scripting/frontend/zcc_parser.cpp +++ b/src/common/scripting/frontend/zcc_parser.cpp @@ -251,6 +251,7 @@ static void InitTokenMap() TOKENDEF (TK_Do, ZCC_DO); TOKENDEF (TK_For, ZCC_FOR); TOKENDEF (TK_ForEach, ZCC_FOREACH); + TOKENDEF (TK_Unsafe, ZCC_UNSAFE); TOKENDEF (TK_While, ZCC_WHILE); TOKENDEF (TK_Until, ZCC_UNTIL); TOKENDEF (TK_If, ZCC_IF); diff --git a/src/common/scripting/frontend/zcc_parser.h b/src/common/scripting/frontend/zcc_parser.h index d0b6264da..bf20f5cac 100644 --- a/src/common/scripting/frontend/zcc_parser.h +++ b/src/common/scripting/frontend/zcc_parser.h @@ -41,30 +41,31 @@ struct ZCCToken // Variable / Function / Class modifiers enum { - ZCC_Native = 1 << 0, - ZCC_Static = 1 << 1, - ZCC_Private = 1 << 2, - ZCC_Protected = 1 << 3, - ZCC_Latent = 1 << 4, - ZCC_Final = 1 << 5, - ZCC_Meta = 1 << 6, - ZCC_Action = 1 << 7, - ZCC_Deprecated = 1 << 8, - ZCC_ReadOnly = 1 << 9, - ZCC_FuncConst = 1 << 10, - ZCC_Abstract = 1 << 11, - ZCC_Extension = 1 << 12, - ZCC_Virtual = 1 << 13, - ZCC_Override = 1 << 14, - ZCC_Transient = 1 << 15, - ZCC_VarArg = 1 << 16, - ZCC_UIFlag = 1 << 17, // there's also token called ZCC_UI - ZCC_Play = 1 << 18, - ZCC_ClearScope = 1 << 19, - ZCC_VirtualScope = 1 << 20, - ZCC_Version = 1 << 21, - ZCC_Internal = 1 << 22, - ZCC_Sealed = 1 << 23, + ZCC_Native = 1 << 0, + ZCC_Static = 1 << 1, + ZCC_Private = 1 << 2, + ZCC_Protected = 1 << 3, + ZCC_Latent = 1 << 4, + ZCC_Final = 1 << 5, + ZCC_Meta = 1 << 6, + ZCC_Action = 1 << 7, + ZCC_Deprecated = 1 << 8, + ZCC_ReadOnly = 1 << 9, + ZCC_FuncConst = 1 << 10, + ZCC_Abstract = 1 << 11, + ZCC_Extension = 1 << 12, + ZCC_Virtual = 1 << 13, + ZCC_Override = 1 << 14, + ZCC_Transient = 1 << 15, + ZCC_VarArg = 1 << 16, + ZCC_UIFlag = 1 << 17, // there's also token called ZCC_UI + ZCC_Play = 1 << 18, + ZCC_ClearScope = 1 << 19, + ZCC_VirtualScope = 1 << 20, + ZCC_Version = 1 << 21, + ZCC_Internal = 1 << 22, + ZCC_Sealed = 1 << 23, + ZCC_VMInternalStruct = 1 << 24, }; // Function parameter modifiers diff --git a/src/common/scripting/interface/vmnatives.cpp b/src/common/scripting/interface/vmnatives.cpp index c1bb2a2b5..1b4cdb746 100644 --- a/src/common/scripting/interface/vmnatives.cpp +++ b/src/common/scripting/interface/vmnatives.cpp @@ -853,6 +853,27 @@ DEFINE_ACTION_FUNCTION(_Wads, GetLumpFullName) ACTION_RETURN_STRING(fileSystem.GetFileFullName(lump)); } +DEFINE_ACTION_FUNCTION(_Wads, GetLumpContainer) +{ + PARAM_PROLOGUE; + PARAM_INT(lump); + ACTION_RETURN_INT(fileSystem.GetFileContainer(lump)); +} + +DEFINE_ACTION_FUNCTION(_Wads, GetContainerName) +{ + PARAM_PROLOGUE; + PARAM_INT(lump); + ACTION_RETURN_STRING(fileSystem.GetResourceFileName(lump)); +} + +DEFINE_ACTION_FUNCTION(_Wads, GetLumpFullPath) +{ + PARAM_PROLOGUE; + PARAM_INT(lump); + ACTION_RETURN_STRING(fileSystem.GetFileFullPath(lump)); +} + DEFINE_ACTION_FUNCTION(_Wads, GetLumpNamespace) { PARAM_PROLOGUE; diff --git a/src/common/utility/r_memory.h b/src/common/utility/r_memory.h index d9db538ca..41abe0be5 100644 --- a/src/common/utility/r_memory.h +++ b/src/common/utility/r_memory.h @@ -1,5 +1,6 @@ #pragma once +#include #include #include diff --git a/src/common/utility/vectors.h b/src/common/utility/vectors.h index e13fcea40..d901a7cc9 100644 --- a/src/common/utility/vectors.h +++ b/src/common/utility/vectors.h @@ -539,15 +539,9 @@ struct TVector3 return *this; } - // returns the XY fields as a 2D-vector. - constexpr const Vector2& XY() const + constexpr Vector2 XY() const { - return *reinterpret_cast(this); - } - - constexpr Vector2& XY() - { - return *reinterpret_cast(this); + return Vector2(X, Y); } // Add a 3D vector and a 2D vector. @@ -792,28 +786,16 @@ struct TVector4 } // returns the XY fields as a 2D-vector. - constexpr const Vector2& XY() const + constexpr Vector2 XY() const { - return *reinterpret_cast(this); + return Vector2(X, Y); } - constexpr Vector2& XY() + constexpr Vector3 XYZ() const { - return *reinterpret_cast(this); + return Vector3(X, Y, Z); } - // returns the XY fields as a 2D-vector. - constexpr const Vector3& XYZ() const - { - return *reinterpret_cast(this); - } - - constexpr Vector3& XYZ() - { - return *reinterpret_cast(this); - } - - // Test for approximate equality bool ApproximatelyEquals(const TVector4 &other) const { @@ -1796,7 +1778,9 @@ struct TRotator template inline TVector3::TVector3 (const TRotator &rot) { - XY() = rot.Pitch.Cos() * rot.Yaw.ToVector(); + auto XY = rot.Pitch.Cos() * rot.Yaw.ToVector(); + X = XY.X; + Y = XY.Y; Z = rot.Pitch.Sin(); } diff --git a/src/ct_chat.cpp b/src/ct_chat.cpp index a12bb9f20..b6d96aa4e 100644 --- a/src/ct_chat.cpp +++ b/src/ct_chat.cpp @@ -251,14 +251,18 @@ void CT_Drawer (void) { // [MK] allow the status bar to take over chat prompt drawing bool skip = false; - IFVIRTUALPTR(StatusBar, DBaseStatusBar, DrawChat) + + if(StatusBar) { - FString txt = ChatQueue; - VMValue params[] = { (DObject*)StatusBar, &txt }; - int rv; - VMReturn ret(&rv); - VMCall(func, params, countof(params), &ret, 1); - if (!!rv) return; + IFVIRTUALPTR(StatusBar, DBaseStatusBar, DrawChat) + { + FString txt = ChatQueue; + VMValue params[] = { (DObject*)StatusBar, &txt }; + int rv; + VMReturn ret(&rv); + VMCall(func, params, countof(params), &ret, 1); + if (!!rv) return; + } } FStringf prompt("%s ", GStrings.GetString("TXT_SAY")); @@ -269,8 +273,8 @@ void CT_Drawer (void) scalex = 1; int scale = active_con_scale(drawer); int screen_width = twod->GetWidth() / scale; - int screen_height= twod->GetHeight() / scale; - int st_y = StatusBar->GetTopOfStatusbar() / scale; + int screen_height = twod->GetHeight() / scale; + int st_y = StatusBar ? (StatusBar->GetTopOfStatusbar() / scale) : screen_height; y += ((twod->GetHeight() == viewheight && viewactive) || gamestate != GS_LEVEL) ? screen_height : st_y; diff --git a/src/d_main.cpp b/src/d_main.cpp index ebf73e917..f5ffeca81 100644 --- a/src/d_main.cpp +++ b/src/d_main.cpp @@ -316,7 +316,6 @@ CUSTOM_CVAR(Int, I_FriendlyWindowTitle, 1, CVAR_GLOBALCONFIG|CVAR_ARCHIVE|CVAR_N CVAR(Bool, cl_nointros, false, CVAR_ARCHIVE) bool RunningAsTool = false; -bool hud_toggled = false; bool wantToRestart; bool DrawFSHUD; // [RH] Draw fullscreen HUD? bool devparm; // started game with -devparm @@ -361,16 +360,18 @@ static int pagetic; // //========================================================================== +CVAR(Int, saved_screenblocks, 10, CVAR_ARCHIVE) +CVAR(Bool, saved_drawplayersprite, true, CVAR_ARCHIVE) +CVAR(Bool, saved_showmessages, true, CVAR_ARCHIVE) +CVAR(Bool, hud_toggled, false, CVAR_ARCHIVE) + void D_ToggleHud() { - static int saved_screenblocks; - static bool saved_drawplayersprite, saved_showmessages; - if ((hud_toggled = !hud_toggled)) { - saved_screenblocks = screenblocks; - saved_drawplayersprite = r_drawplayersprites; - saved_showmessages = show_messages; + saved_screenblocks = *screenblocks; + saved_drawplayersprite = *r_drawplayersprites; + saved_showmessages = *show_messages; screenblocks = 12; r_drawplayersprites = false; show_messages = false; @@ -379,9 +380,9 @@ void D_ToggleHud() } else { - screenblocks = saved_screenblocks; - r_drawplayersprites = saved_drawplayersprite; - show_messages = saved_showmessages; + screenblocks =*saved_screenblocks; + r_drawplayersprites = *saved_drawplayersprite; + show_messages = *saved_showmessages; } } CCMD(togglehud) diff --git a/src/d_main.h b/src/d_main.h index 0d4a33079..b5a08750c 100644 --- a/src/d_main.h +++ b/src/d_main.h @@ -34,7 +34,7 @@ #include "c_cvars.h" extern bool advancedemo; -extern bool hud_toggled; +EXTERN_CVAR(Bool, hud_toggled); void D_ToggleHud(); struct event_t; diff --git a/src/g_game.cpp b/src/g_game.cpp index baa010714..0e225bcba 100644 --- a/src/g_game.cpp +++ b/src/g_game.cpp @@ -300,7 +300,7 @@ CCMD (turnspeeds) } if (i <= 4) { - *angleturn[3] = *angleturn[2]; + *angleturn[3] = **angleturn[2]; } } } @@ -1000,6 +1000,8 @@ bool G_Responder (event_t *ev) if (gameaction == ga_nothing && (demoplayback || gamestate == GS_DEMOSCREEN || gamestate == GS_TITLELEVEL)) { + if (chatmodeon) chatmodeon = 0; + const char *cmd = Bindings.GetBind (ev->data1); if (ev->type == EV_KeyDown) diff --git a/src/g_level.cpp b/src/g_level.cpp index 265bdf68e..8bfa2c391 100644 --- a/src/g_level.cpp +++ b/src/g_level.cpp @@ -150,7 +150,7 @@ CUSTOM_CVAR(Bool, gl_notexturefill, false, CVAR_NOINITCALL) CUSTOM_CVAR(Int, gl_maplightmode, -1, CVAR_NOINITCALL | CVAR_CHEAT) // this is just for testing. -1 means 'inactive' { - if (self > 5 || self < -1) self = -1; + if (self > 4 || self < -1) self = -1; } CUSTOM_CVARD(Int, gl_lightmode, 1, CVAR_ARCHIVE, "Select lighting mode. 2 is vanilla accurate, 1 is accurate to the ZDoom software renderer and 0 is a less demanding non-shader implementation") diff --git a/src/g_statusbar/sbarinfo_commands.cpp b/src/g_statusbar/sbarinfo_commands.cpp index a28d43e19..e927b1616 100644 --- a/src/g_statusbar/sbarinfo_commands.cpp +++ b/src/g_statusbar/sbarinfo_commands.cpp @@ -1441,10 +1441,10 @@ class CommandDrawNumber : public CommandDrawString static VMFunction *func = nullptr; if (func == nullptr) PClass::FindFunction(&func, NAME_PlayerPawn, "GetEffectTicsForItem"); VMValue params[] = { statusBar->CPlayer->mo, inventoryItem }; - int retv; - VMReturn ret(&retv); - VMCall(func, params, 2, &ret, 1); - num = retv < 0? 0 : retv / TICRATE + 1; + int ret1 = 0, ret2 = 0; + VMReturn rets[] = { &ret1, &ret2 }; + VMCall(func, params, 2, rets, 2); + num = ret1 < 0? 0 : ret1 / TICRATE + 1; break; } case INVENTORY: diff --git a/src/g_statusbar/shared_sbar.cpp b/src/g_statusbar/shared_sbar.cpp index 9593842a1..a9aeb075f 100644 --- a/src/g_statusbar/shared_sbar.cpp +++ b/src/g_statusbar/shared_sbar.cpp @@ -85,6 +85,7 @@ EXTERN_CVAR (Bool, am_showsecrets) EXTERN_CVAR (Bool, am_showitems) EXTERN_CVAR (Bool, am_showtime) EXTERN_CVAR (Bool, am_showtotaltime) +EXTERN_CVAR (Bool, am_showlevelname) EXTERN_CVAR(Bool, inter_subtitles) EXTERN_CVAR(Bool, ui_screenborder_classic_scaling) @@ -598,6 +599,8 @@ void DBaseStatusBar::DoDrawAutomapHUD(int crdefault, int highlight) } FormatMapName(primaryLevel, crdefault, &textbuffer); + if (textbuffer.IsEmpty()) + return; if (!generic_ui) { diff --git a/src/gamedata/d_dehacked.cpp b/src/gamedata/d_dehacked.cpp index 9d8dc2106..4ed8e427e 100644 --- a/src/gamedata/d_dehacked.cpp +++ b/src/gamedata/d_dehacked.cpp @@ -139,6 +139,7 @@ static PClassActor* FindInfoName(int index, bool mustexist = false) cls = static_cast(RUNTIME_CLASS(AActor)->CreateDerivedClass(name.GetChars(), (unsigned)sizeof(AActor))); NewClassType(cls, -1); // This needs a VM type to work as intended. cls->InitializeDefaults(); + PClassActor::AllActorClasses.Push(cls); } if (cls) { @@ -1203,6 +1204,8 @@ static int PatchThing (int thingy, int flags) AActor *info; uint8_t dummy[sizeof(AActor)]; bool hadHeight = false; + bool hadProjHeight = false; + bool hadPhysHeight = false; bool hadTranslucency = false; bool hadStyle = false; FStateDefinitions statedef; @@ -1262,8 +1265,17 @@ static int PatchThing (int thingy, int flags) } else if (linelen == 6 && stricmp (Line1, "Height") == 0) { - info->Height = DEHToDouble(val); - info->projectilepassheight = 0; // needs to be disabled + // [XA] This is a bit more complex now, since projectilepassheight + // and "physical height" now both exist. if either of these are + // defined, then override the Height field accordingly. + if(!hadPhysHeight) + { + info->Height = DEHToDouble(val); + } + if(!hadProjHeight) + { + info->projectilepassheight = 0; // needs to be disabled + } hadHeight = true; } else if (linelen == 14 && stricmp (Line1, "Missile damage") == 0) @@ -1459,6 +1471,47 @@ static int PatchThing (int thingy, int flags) info->missilechancemult = DEHToDouble(val); } + // [XA] Fields for common GZDoom-specific values that + // are desirable to set in a cross-port DEHACKED mod. + // adding these prevents users from having to reimplement + // actors in zscript just to define these few fields. + else if (!stricmp(Line1, "Projectile pass height")) + { + info->projectilepassheight = DEHToDouble(val); + hadProjHeight = true; + } + else if (!stricmp(Line1, "Physical height")) + { + // [XA] This is a synonym for Height that is intended + // to be ignored in any ports that don't support + // projectilepassheight -- this is needed because + // other ports' "Height x" is actually equivalent + // to Zdoom's "ProjectilePassHeight x; Height y", + // i.e. the definition of the Height var is different. + info->Height = DEHToDouble(val); + hadPhysHeight = true; + } + else if (!stricmp(Line1, "Tag")) + { + stripwhite(Line2); + info->SetTag(Line2); + } + else if (!stricmp(Line1, "Obituary")) + { + stripwhite(Line2); + info->StringVar(NAME_Obituary) = Line2; + } + else if (!stricmp(Line1, "Melee obituary")) + { + stripwhite(Line2); + info->StringVar(NAME_HitObituary) = Line2; + } + else if (!stricmp(Line1, "Self obituary")) + { + stripwhite(Line2); + info->StringVar(NAME_SelfObituary) = Line2; + } + else if (linelen > 6) { if (stricmp (Line1 + linelen - 6, " frame") == 0) @@ -1727,12 +1780,23 @@ static int PatchThing (int thingy, int flags) else Printf (unknown_str, Line1, "Thing", thingy); } + // [XA] sanity check: to avoid ambiguity, an actor that defines + // ProjectilePassHeight must also define PhysicalHeight, and vice-versa. + if(hadPhysHeight && !hadProjHeight) + { + I_Error("Thing %d: DEHACKED actors that set 'Physical height' must also set 'Projectile pass height'\n", thingy); + } + else if(!hadPhysHeight && hadProjHeight) + { + I_Error("Thing %d: DEHACKED actors that set 'Projectile pass height' must also set 'Physical height'\n", thingy); + } + if (info != (AActor *)&dummy) { // Reset heights for things hanging from the ceiling that // don't specify a new height. if (info->flags & MF_SPAWNCEILING && - !hadHeight && + !hadHeight && !hadPhysHeight && thingy <= (int)OrgHeights.Size() && thingy > 0) { info->Height = OrgHeights[thingy - 1]; @@ -3714,7 +3778,11 @@ void FinishDehPatch () mysnprintf(typeNameBuilder, countof(typeNameBuilder), "DehackedPickup%d", nameindex++); bool newlycreated; subclass = static_cast(dehtype->CreateDerivedClass(typeNameBuilder, dehtype->Size, &newlycreated, 0)); - if (newlycreated) subclass->InitializeDefaults(); + if (newlycreated) + { + subclass->InitializeDefaults(); + PClassActor::AllActorClasses.Push(subclass); + } } while (subclass == nullptr); NewClassType(subclass, 0); // This needs a VM type to work as intended. diff --git a/src/gamedata/g_mapinfo.cpp b/src/gamedata/g_mapinfo.cpp index 84ff54d58..964cb6ece 100644 --- a/src/gamedata/g_mapinfo.cpp +++ b/src/gamedata/g_mapinfo.cpp @@ -1582,7 +1582,7 @@ DEFINE_MAP_OPTION(lightmode, false) parse.sc.MustGetNumber(); if (parse.sc.Number == 8 || parse.sc.Number == 16) info->lightmode = ELightMode::NotSet; - else if (parse.sc.Number >= 0 && parse.sc.Number <= 5) + else if (parse.sc.Number >= 0 && parse.sc.Number < 5) { info->lightmode = ELightMode(parse.sc.Number); } diff --git a/src/intermission/intermission.cpp b/src/intermission/intermission.cpp index 24915f9f7..0ae8e41da 100644 --- a/src/intermission/intermission.cpp +++ b/src/intermission/intermission.cpp @@ -325,8 +325,10 @@ void DIntermissionScreenCutscene::Drawer () ScaleOverrider ovr(twod); IFVIRTUALPTRNAME(mScreenJobRunner, NAME_ScreenJobRunner, RunFrame) { + int res = 0; VMValue parm[] = { mScreenJobRunner, I_GetTimeFrac() }; - VMCall(func, parm, 2, nullptr, 0); + VMReturn ret[] = { &res }; + VMCall(func, parm, 2, ret, 1); } } diff --git a/src/namedef_custom.h b/src/namedef_custom.h index abccd1cd8..843ca4c0a 100644 --- a/src/namedef_custom.h +++ b/src/namedef_custom.h @@ -483,6 +483,9 @@ xx(PowerupType) xx(PlayerPawn) xx(RipSound) xx(Archvile) +xx(Obituary) +xx(HitObituary) +xx(SelfObituary) xx(ResolveState) diff --git a/src/p_conversation.cpp b/src/p_conversation.cpp index f51d498f2..417b0e49f 100644 --- a/src/p_conversation.cpp +++ b/src/p_conversation.cpp @@ -218,8 +218,10 @@ static void TakeStrifeItem (player_t *player, PClassActor *itemtype, int amount) IFVM(Actor, TakeInventory) { + int taken = false; VMValue params[] = { player->mo, itemtype, amount, false, false }; - VMCall(func, params, 5, nullptr, 0); + VMReturn rets[] = { &taken }; + VMCall(func, params, 5, rets, 1); } } diff --git a/src/playsim/actor.h b/src/playsim/actor.h index 1466d8d3b..9fdfa9694 100644 --- a/src/playsim/actor.h +++ b/src/playsim/actor.h @@ -509,6 +509,7 @@ enum ActorRenderFlag2 RF2_ISOMETRICSPRITES = 0x0080, RF2_SQUAREPIXELS = 0x0100, // apply +ROLLSPRITE scaling math so that non rolling sprites get the same scaling RF2_STRETCHPIXELS = 0x0200, // don't apply SQUAREPIXELS for ROLLSPRITES + RF2_LIGHTMULTALPHA = 0x0400, // attached lights use alpha as intensity multiplier }; // This translucency value produces the closest match to Heretic's TINTTAB. diff --git a/src/playsim/dthinker.cpp b/src/playsim/dthinker.cpp index 043077068..dce8f8f00 100644 --- a/src/playsim/dthinker.cpp +++ b/src/playsim/dthinker.cpp @@ -355,12 +355,12 @@ void FThinkerCollection::SerializeThinkers(FSerializer &arc, bool hubLoad) else if (thinker->ObjectFlags & OF_JustSpawned) { FreshThinkers[i].AddTail(thinker); - thinker->PostSerialize(); + thinker->CallPostSerialize(); } else { Thinkers[i].AddTail(thinker); - thinker->PostSerialize(); + thinker->CallPostSerialize(); } } } @@ -773,6 +773,16 @@ void DThinker::PostSerialize() { } +void DThinker::CallPostSerialize() +{ + PostSerialize(); + IFOVERRIDENVIRTUALPTRNAME(this, NAME_Thinker, OnLoad) + { + VMValue params[] = { this }; + VMCall(func, params, 1, nullptr, 0); + } +} + //========================================================================== // // diff --git a/src/playsim/dthinker.h b/src/playsim/dthinker.h index 78dcd1520..03e9ecc91 100644 --- a/src/playsim/dthinker.h +++ b/src/playsim/dthinker.h @@ -104,6 +104,7 @@ public: virtual void PostBeginPlay (); // Called just before the first tick virtual void CallPostBeginPlay(); // different in actor. virtual void PostSerialize(); + void CallPostSerialize(); void Serialize(FSerializer &arc) override; size_t PropagateMark(); diff --git a/src/playsim/fragglescript/t_func.cpp b/src/playsim/fragglescript/t_func.cpp index f9fff1b9e..fe7699c35 100644 --- a/src/playsim/fragglescript/t_func.cpp +++ b/src/playsim/fragglescript/t_func.cpp @@ -2532,8 +2532,10 @@ void FParser::SF_PlayerWeapon() IFVM(PlayerPawn, PickNewWeapon) { + AActor* weap = nullptr; VMValue param[] = { Level->Players[playernum]->mo, (void*)nullptr }; - VMCall(func, param, 2, nullptr, 0); + VMReturn rets[] = { (void**)&weap }; + VMCall(func, param, 2, rets, 1); } } } diff --git a/src/playsim/mapthinkers/a_ceiling.cpp b/src/playsim/mapthinkers/a_ceiling.cpp index 1afdf4509..c2205fca9 100644 --- a/src/playsim/mapthinkers/a_ceiling.cpp +++ b/src/playsim/mapthinkers/a_ceiling.cpp @@ -72,6 +72,31 @@ void DCeiling::Serialize(FSerializer &arc) .Enum("crushmode", m_CrushMode); } +DEFINE_FIELD(DCeiling, m_Type) +DEFINE_FIELD(DCeiling, m_BottomHeight) +DEFINE_FIELD(DCeiling, m_TopHeight) +DEFINE_FIELD(DCeiling, m_Speed) +DEFINE_FIELD(DCeiling, m_Speed1) +DEFINE_FIELD(DCeiling, m_Speed2) +DEFINE_FIELD(DCeiling, m_Silent) +DEFINE_FIELD(DCeiling, m_CrushMode) + +DEFINE_ACTION_FUNCTION(DCeiling, getCrush) +{ + PARAM_SELF_PROLOGUE(DCeiling); + ACTION_RETURN_INT(self->getCrush()); +} +DEFINE_ACTION_FUNCTION(DCeiling, getDirection) +{ + PARAM_SELF_PROLOGUE(DCeiling); + ACTION_RETURN_INT(self->getDirection()); +} +DEFINE_ACTION_FUNCTION(DCeiling, getOldDirection) +{ + PARAM_SELF_PROLOGUE(DCeiling); + ACTION_RETURN_INT(self->getOldDirection()); +} + //============================================================================ // // diff --git a/src/playsim/mapthinkers/a_ceiling.h b/src/playsim/mapthinkers/a_ceiling.h index 2954fb118..92b0c22bb 100644 --- a/src/playsim/mapthinkers/a_ceiling.h +++ b/src/playsim/mapthinkers/a_ceiling.h @@ -47,6 +47,14 @@ public: crushSlowdown = 2 }; + ECeiling m_Type; + double m_BottomHeight; + double m_TopHeight; + double m_Speed; + double m_Speed1; // [RH] dnspeed of crushers + double m_Speed2; // [RH] upspeed of crushers + ECrushMode m_CrushMode; + int m_Silent; void Construct(sector_t *sec); void Construct(sector_t *sec, double speed1, double speed2, int silent); @@ -56,17 +64,10 @@ public: int getCrush() const { return m_Crush; } int getDirection() const { return m_Direction; } + int getOldDirection() const { return m_OldDirection; } protected: - ECeiling m_Type; - double m_BottomHeight; - double m_TopHeight; - double m_Speed; - double m_Speed1; // [RH] dnspeed of crushers - double m_Speed2; // [RH] upspeed of crushers int m_Crush; - ECrushMode m_CrushMode; - int m_Silent; int m_Direction; // 1 = up, 0 = waiting, -1 = down // [RH] Need these for BOOM-ish transferring ceilings diff --git a/src/playsim/mapthinkers/a_doors.cpp b/src/playsim/mapthinkers/a_doors.cpp index 2d8d2c70c..e32068565 100644 --- a/src/playsim/mapthinkers/a_doors.cpp +++ b/src/playsim/mapthinkers/a_doors.cpp @@ -40,6 +40,7 @@ #include "g_levellocals.h" #include "animations.h" #include "texturemanager.h" +#include "vm.h" //============================================================================ // @@ -64,6 +65,17 @@ void DDoor::Serialize(FSerializer &arc) ("lighttag", m_LightTag); } +DEFINE_FIELD(DDoor, m_Type) +DEFINE_FIELD(DDoor, m_TopDist) +DEFINE_FIELD(DDoor, m_BotSpot) +DEFINE_FIELD(DDoor, m_BotDist) +DEFINE_FIELD(DDoor, m_OldFloorDist) +DEFINE_FIELD(DDoor, m_Speed) +DEFINE_FIELD(DDoor, m_Direction) +DEFINE_FIELD(DDoor, m_TopWait) +DEFINE_FIELD(DDoor, m_TopCountdown) +DEFINE_FIELD(DDoor, m_LightTag) + //============================================================================ // // T_VerticalDoor diff --git a/src/playsim/mapthinkers/a_doors.h b/src/playsim/mapthinkers/a_doors.h index 88c0c5667..e815b55ae 100644 --- a/src/playsim/mapthinkers/a_doors.h +++ b/src/playsim/mapthinkers/a_doors.h @@ -17,16 +17,10 @@ public: doorWaitClose, }; - void Construct(sector_t *sector); - void Construct(sector_t *sec, EVlDoor type, double speed, int delay, int lightTag, int topcountdown); - - void Serialize(FSerializer &arc); - void Tick (); -protected: EVlDoor m_Type; double m_TopDist; double m_BotDist, m_OldFloorDist; - vertex_t *m_BotSpot; + vertex_t* m_BotSpot; double m_Speed; // 1 = up, 0 = waiting at top, -1 = down @@ -40,6 +34,12 @@ protected: int m_LightTag; + void Construct(sector_t *sector); + void Construct(sector_t *sec, EVlDoor type, double speed, int delay, int lightTag, int topcountdown); + + void Serialize(FSerializer &arc); + void Tick (); +protected: void DoorSound (bool raise, class DSeqNode *curseq=NULL) const; private: diff --git a/src/playsim/mapthinkers/a_floor.cpp b/src/playsim/mapthinkers/a_floor.cpp index 0d330e4e9..d4492d9e0 100644 --- a/src/playsim/mapthinkers/a_floor.cpp +++ b/src/playsim/mapthinkers/a_floor.cpp @@ -96,6 +96,22 @@ void DFloor::Serialize(FSerializer &arc) ("instant", m_Instant); } +DEFINE_FIELD(DFloor, m_Type) +DEFINE_FIELD(DFloor, m_Crush) +DEFINE_FIELD(DFloor, m_Direction) +DEFINE_FIELD(DFloor, m_NewSpecial) +DEFINE_FIELD(DFloor, m_Texture) +DEFINE_FIELD(DFloor, m_FloorDestDist) +DEFINE_FIELD(DFloor, m_Speed) +DEFINE_FIELD(DFloor, m_ResetCount) +DEFINE_FIELD(DFloor, m_OrgDist) +DEFINE_FIELD(DFloor, m_Delay) +DEFINE_FIELD(DFloor, m_PauseTime) +DEFINE_FIELD(DFloor, m_StepTime) +DEFINE_FIELD(DFloor, m_PerStepTime) +DEFINE_FIELD(DFloor, m_Hexencrush) +DEFINE_FIELD(DFloor, m_Instant) + //========================================================================== // // MOVE A FLOOR TO ITS DESTINATION (UP OR DOWN) @@ -887,6 +903,12 @@ void DElevator::Serialize(FSerializer &arc) ("interp_ceiling", m_Interp_Ceiling); } +DEFINE_FIELD(DElevator, m_Type) +DEFINE_FIELD(DElevator, m_Direction) +DEFINE_FIELD(DElevator, m_FloorDestDist) +DEFINE_FIELD(DElevator, m_CeilingDestDist) +DEFINE_FIELD(DElevator, m_Speed) + //========================================================================== // // @@ -957,7 +979,7 @@ void DElevator::Tick () } } - if (res == EMoveResult::pastdest) // if destination height acheived + if (res == EMoveResult::pastdest) // if destination height achieved { // make floor stop sound SN_StopSequence (m_Sector, CHAN_FLOOR); diff --git a/src/playsim/mapthinkers/a_floor.h b/src/playsim/mapthinkers/a_floor.h index e0331bca6..891ce948e 100644 --- a/src/playsim/mapthinkers/a_floor.h +++ b/src/playsim/mapthinkers/a_floor.h @@ -105,6 +105,13 @@ public: elevateLower }; + EElevator m_Type; + int m_Direction; + double m_FloorDestDist; + double m_CeilingDestDist; + double m_Speed; + + void Construct(sector_t *sec); void OnDestroy() override; @@ -112,11 +119,6 @@ public: void Tick (); protected: - EElevator m_Type; - int m_Direction; - double m_FloorDestDist; - double m_CeilingDestDist; - double m_Speed; TObjPtr m_Interp_Ceiling; TObjPtr m_Interp_Floor; diff --git a/src/playsim/mapthinkers/a_plats.cpp b/src/playsim/mapthinkers/a_plats.cpp index c688295e4..fb41a6559 100644 --- a/src/playsim/mapthinkers/a_plats.cpp +++ b/src/playsim/mapthinkers/a_plats.cpp @@ -36,6 +36,7 @@ #include "serializer.h" #include "p_spec.h" #include "g_levellocals.h" +#include "vm.h" static FRandom pr_doplat ("DoPlat"); @@ -62,6 +63,17 @@ void DPlat::Serialize(FSerializer &arc) ("tag", m_Tag); } +DEFINE_FIELD(DPlat, m_Type) +DEFINE_FIELD(DPlat, m_Speed) +DEFINE_FIELD(DPlat, m_Low) +DEFINE_FIELD(DPlat, m_High) +DEFINE_FIELD(DPlat, m_Wait) +DEFINE_FIELD(DPlat, m_Count) +DEFINE_FIELD(DPlat, m_Status) +DEFINE_FIELD(DPlat, m_OldStatus) +DEFINE_FIELD(DPlat, m_Crush) +DEFINE_FIELD(DPlat, m_Tag) + //----------------------------------------------------------------------------- // // diff --git a/src/playsim/mapthinkers/a_plats.h b/src/playsim/mapthinkers/a_plats.h index fd8d4e975..2427021ef 100644 --- a/src/playsim/mapthinkers/a_plats.h +++ b/src/playsim/mapthinkers/a_plats.h @@ -38,8 +38,6 @@ public: bool IsLift() const { return m_Type == platDownWaitUpStay || m_Type == platDownWaitUpStayStone; } void Construct(sector_t *sector); -protected: - double m_Speed; double m_Low; double m_High; @@ -50,6 +48,7 @@ protected: int m_Crush; int m_Tag; EPlatType m_Type; +protected: void PlayPlatSound (const char *sound); const char *GetSoundByType () const; diff --git a/src/playsim/p_effect.cpp b/src/playsim/p_effect.cpp index c16d4a982..dabf0ed16 100644 --- a/src/playsim/p_effect.cpp +++ b/src/playsim/p_effect.cpp @@ -1108,7 +1108,8 @@ DEFINE_ACTION_FUNCTION_NATIVE(FLevelLocals, SpawnVisualThinker, SpawnVisualThink void DVisualThinker::UpdateSpriteInfo() { PT.style = ERenderStyle(GetRenderStyle()); - if((PT.flags & SPF_LOCAL_ANIM) && PT.texture != AnimatedTexture) + + if ((PT.flags & SPF_LOCAL_ANIM) && PT.texture != AnimatedTexture) { AnimatedTexture = PT.texture; TexAnim.InitStandaloneAnimation(PT.animData, PT.texture, Level->maptime); @@ -1127,6 +1128,10 @@ DEFINE_ACTION_FUNCTION_NATIVE(DVisualThinker, UpdateSpriteInfo, UpdateSpriteInfo return 0; } +bool DVisualThinker::ValidTexture() +{ + return ((flags & VTF_IsParticle) || PT.texture.isValid()); +} // This runs just like Actor's, make sure to call Super.Tick() in ZScript. void DVisualThinker::Tick() @@ -1134,10 +1139,8 @@ void DVisualThinker::Tick() if (ObjectFlags & OF_EuthanizeMe) return; - // There won't be a standard particle for this, it's only for graphics. - if (!PT.texture.isValid()) + if (!ValidTexture()) { - Printf("No valid texture, destroyed"); Destroy(); return; } @@ -1156,7 +1159,6 @@ void DVisualThinker::Tick() PT.Pos.X = newxy.X; PT.Pos.Y = newxy.Y; PT.Pos.Z += PT.Vel.Z; - subsector_t * ss = Level->PointInRenderSubsector(PT.Pos); // Handle crossing a sector portal. @@ -1246,7 +1248,33 @@ DEFINE_ACTION_FUNCTION_NATIVE(DVisualThinker, SetTranslation, SetTranslation) return 0; } -static int IsFrozen(DVisualThinker * self) +int DVisualThinker::GetParticleType() const +{ + int flag = (flags & VTF_IsParticle); + switch (flag) + { + case VTF_ParticleSquare: + return PT_SQUARE; + case VTF_ParticleRound: + return PT_ROUND; + case VTF_ParticleSmooth: + return PT_SMOOTH; + } + return PT_DEFAULT; +} + +static int GetParticleType(DVisualThinker* self) +{ + return self->GetParticleType(); +} + +DEFINE_ACTION_FUNCTION_NATIVE(DVisualThinker, GetParticleType, GetParticleType) +{ + PARAM_SELF_PROLOGUE(DVisualThinker); + ACTION_RETURN_INT(self->GetParticleType()); +} + +static int IsFrozen(DVisualThinker* self) { return !!(self->Level->isFrozen() && !(self->PT.flags & SPF_NOTIMEFREEZE)); } diff --git a/src/playsim/p_effect.h b/src/playsim/p_effect.h index 29042b293..b23efb01b 100644 --- a/src/playsim/p_effect.h +++ b/src/playsim/p_effect.h @@ -53,6 +53,14 @@ struct FLevelLocals; // [RH] Particle details +enum EParticleStyle +{ + PT_DEFAULT = -1, // Use gl_particles_style + PT_SQUARE = 0, + PT_ROUND = 1, + PT_SMOOTH = 2, +}; + enum EParticleFlags { SPF_FULLBRIGHT = 1 << 0, diff --git a/src/playsim/p_interaction.cpp b/src/playsim/p_interaction.cpp index 60b6f3059..2d1f7d7d4 100644 --- a/src/playsim/p_interaction.cpp +++ b/src/playsim/p_interaction.cpp @@ -336,7 +336,10 @@ void AActor::Die (AActor *source, AActor *inflictor, int dmgflags, FName MeansOf } } - VMCall(func, params, 1, nullptr, 0); + AActor* unused = nullptr; + int unused2 = 0, unused3 = 0; + VMReturn ret[] = { (void**)&unused, &unused2, &unused3 }; + VMCall(func, params, 1, ret, 3); // Kill the dummy Actor if it didn't unmorph, otherwise checking the morph flags. Player pawns need // to stay, otherwise they won't respawn correctly. diff --git a/src/playsim/p_local.h b/src/playsim/p_local.h index 584cfc43f..6575ad3e5 100644 --- a/src/playsim/p_local.h +++ b/src/playsim/p_local.h @@ -106,7 +106,7 @@ enum EPuffFlags }; AActor *P_SpawnPuff(AActor *source, PClassActor *pufftype, const DVector3 &pos, DAngle hitdir, DAngle particledir, int updown, int flags = 0, AActor *vict = NULL); -void P_SpawnBlood (const DVector3 &pos, DAngle angle, int damage, AActor *originator); +AActor *P_SpawnBlood (const DVector3 &pos, DAngle angle, int damage, AActor *originator); void P_BloodSplatter (const DVector3 &pos, AActor *originator, DAngle hitangle); void P_BloodSplatter2 (const DVector3 &pos, AActor *originator, DAngle hitangle); void P_RipperBlood (AActor *mo, AActor *bleeder); diff --git a/src/playsim/p_map.cpp b/src/playsim/p_map.cpp index e1ccd2d3f..959fa7ac3 100644 --- a/src/playsim/p_map.cpp +++ b/src/playsim/p_map.cpp @@ -215,7 +215,7 @@ bool P_CanCrossLine(AActor *mo, line_t *line, DVector3 next) assert(VIndex != ~0u); } - VMValue params[] = { mo, line, next.X, next.Y, next.Z, false }; + VMValue params[] = { mo, line, next.X, next.Y, next.Z }; VMReturn ret; int retval; ret.IntAt(&retval); diff --git a/src/playsim/p_mobj.cpp b/src/playsim/p_mobj.cpp index 041dcdeb0..b256f756b 100644 --- a/src/playsim/p_mobj.cpp +++ b/src/playsim/p_mobj.cpp @@ -217,7 +217,6 @@ void AActor::Serialize(FSerializer &arc) A("angles", Angles) A("frame", frame) A("scale", Scale) - A("nolocalrender", NoLocalRender) // Note: This will probably be removed later since a better solution is needed A("renderstyle", RenderStyle) A("renderflags", renderflags) A("renderflags2", renderflags2) @@ -5751,8 +5750,10 @@ AActor *FLevelLocals::SpawnPlayer (FPlayerStart *mthing, int playernum, int flag IFVIRTUALPTRNAME(p->mo, NAME_PlayerPawn, ResetAirSupply) { + int drowning = 0; VMValue params[] = { p->mo, false }; - VMCall(func, params, 2, nullptr, 0); + VMReturn rets[] = { &drowning }; + VMCall(func, params, 2, rets, 1); } for (int ii = 0; ii < MAXPLAYERS; ++ii) @@ -5787,7 +5788,7 @@ AActor *FLevelLocals::SpawnPlayer (FPlayerStart *mthing, int playernum, int flag IFVM(PlayerPawn, FilterCoopRespawnInventory) { VMValue params[] = { p->mo, oldactor, ((heldWeap == nullptr || (heldWeap->ObjectFlags & OF_EuthanizeMe)) ? nullptr : heldWeap) }; - VMCall(func, params, 2, nullptr, 0); + VMCall(func, params, 3, nullptr, 0); } } if (oldactor != NULL) @@ -6441,9 +6442,9 @@ DEFINE_ACTION_FUNCTION(AActor, SpawnPuff) // //--------------------------------------------------------------------------- -void P_SpawnBlood (const DVector3 &pos1, DAngle dir, int damage, AActor *originator) +AActor *P_SpawnBlood (const DVector3 &pos1, DAngle dir, int damage, AActor *originator) { - AActor *th; + AActor *th = nullptr; PClassActor *bloodcls = originator->GetBloodType(); DVector3 pos = pos1; pos.Z += pr_spawnblood.Random2() / 64.; @@ -6528,6 +6529,8 @@ void P_SpawnBlood (const DVector3 &pos1, DAngle dir, int damage, AActor *origina if (bloodtype >= 1) P_DrawSplash2 (originator->Level, 40, pos, dir, 2, originator->BloodColor); + + return th; } DEFINE_ACTION_FUNCTION(AActor, SpawnBlood) @@ -6538,8 +6541,7 @@ DEFINE_ACTION_FUNCTION(AActor, SpawnBlood) PARAM_FLOAT(z); PARAM_ANGLE(dir); PARAM_INT(damage); - P_SpawnBlood(DVector3(x, y, z), dir, damage, self); - return 0; + ACTION_RETURN_OBJECT(P_SpawnBlood(DVector3(x, y, z), dir, damage, self)); } diff --git a/src/playsim/p_teleport.cpp b/src/playsim/p_teleport.cpp index a198f2b27..f26bb6fcb 100644 --- a/src/playsim/p_teleport.cpp +++ b/src/playsim/p_teleport.cpp @@ -249,7 +249,7 @@ bool P_Teleport (AActor *thing, DVector3 pos, DAngle angle, int flags) IFVIRTUALPTR(thing, AActor, PostTeleport) { VMValue params[] = { thing, pos.X, pos.Y, pos.Z, angle.Degrees(), flags }; - VMCall(func, params, countof(params), nullptr, 1); + VMCall(func, params, countof(params), nullptr, 0); } } return true; diff --git a/src/playsim/p_visualthinker.h b/src/playsim/p_visualthinker.h index 6cf9b5f9e..580bdfe97 100644 --- a/src/playsim/p_visualthinker.h +++ b/src/playsim/p_visualthinker.h @@ -20,6 +20,12 @@ enum EVisualThinkerFlags VTF_FlipY = 1 << 3, // flip the sprite on the x/y axis. VTF_DontInterpolate = 1 << 4, // disable all interpolation VTF_AddLightLevel = 1 << 5, // adds sector light level to 'LightLevel' + + VTF_ParticleDefault = 0x40, + VTF_ParticleSquare = 0x80, + VTF_ParticleRound = 0xC0, + VTF_ParticleSmooth = 0x100, + VTF_IsParticle = 0x1C0, // Renders as a particle instead }; class DVisualThinker : public DThinker @@ -54,6 +60,8 @@ public: void SetTranslation(FName trname); int GetRenderStyle() const; bool isFrozen(); + bool ValidTexture(); + int GetParticleType() const; int GetLightLevel(sector_t *rendersector) const; FVector3 InterpolatedPosition(double ticFrac) const; float InterpolatedRoll(double ticFrac) const; diff --git a/src/rendering/hwrenderer/hw_dynlightdata.cpp b/src/rendering/hwrenderer/hw_dynlightdata.cpp index 86f4de1b0..597ee2e92 100644 --- a/src/rendering/hwrenderer/hw_dynlightdata.cpp +++ b/src/rendering/hwrenderer/hw_dynlightdata.cpp @@ -96,7 +96,7 @@ void AddLightToList(FDynLightData &dld, int group, FDynamicLight * light, bool f cs = 1.0f; } - if (light->target) + if (light->target && (light->target->renderflags2 & RF2_LIGHTMULTALPHA)) cs *= (float)light->target->Alpha; info.r = light->GetRed() / 255.0f * cs; diff --git a/src/rendering/hwrenderer/scene/hw_bsp.cpp b/src/rendering/hwrenderer/scene/hw_bsp.cpp index df0e02b48..114d8592e 100644 --- a/src/rendering/hwrenderer/scene/hw_bsp.cpp +++ b/src/rendering/hwrenderer/scene/hw_bsp.cpp @@ -288,19 +288,25 @@ void HWDrawInfo::AddLine (seg_t *seg, bool portalclip, FRenderState& state) angle_t startAngle = clipper.GetClipAngle(seg->v2); angle_t endAngle = clipper.GetClipAngle(seg->v1); auto &clipperr = *rClipper; - angle_t startAngleR = clipperr.PointToPseudoAngle(seg->v2->fX(), seg->v2->fY()); - angle_t endAngleR = clipperr.PointToPseudoAngle(seg->v1->fX(), seg->v1->fY()); + angle_t startAngleR = 0; + angle_t endAngleR = 0; angle_t paddingR = 0x00200000; // Make radar clipping more aggressive (reveal less) - if(Viewpoint.IsAllowedOoB() && r_radarclipper && !(Level->flags3 & LEVEL3_NOFOGOFWAR) && (startAngleR - endAngleR >= ANGLE_180)) + if(Viewpoint.IsAllowedOoB() && r_radarclipper && !(Level->flags3 & LEVEL3_NOFOGOFWAR)) { - if (!seg->backsector) clipperr.SafeAddClipRange(startAngleR - paddingR, endAngleR + paddingR); - else if((seg->sidedef != nullptr) && !uint8_t(seg->sidedef->Flags & WALLF_POLYOBJ) && (currentsector->sectornum != seg->backsector->sectornum)) + startAngleR = clipperr.PointToPseudoAngle(seg->v2->fX(), seg->v2->fY()); + endAngleR = clipperr.PointToPseudoAngle(seg->v1->fX(), seg->v1->fY()); + + if (startAngleR - endAngleR >= ANGLE_180) { - if (in_area == area_default) in_area = hw_CheckViewArea(seg->v1, seg->v2, seg->frontsector, seg->backsector); - backsector = hw_FakeFlat(drawctx, seg->backsector, in_area, true); - if (hw_CheckClip(seg->sidedef, currentsector, backsector)) clipperr.SafeAddClipRange(startAngleR - paddingR, endAngleR + paddingR); - backsector = nullptr; + if (!seg->backsector) clipperr.SafeAddClipRange(startAngleR - paddingR, endAngleR + paddingR); + else if((seg->sidedef != nullptr) && !uint8_t(seg->sidedef->Flags & WALLF_POLYOBJ) && (currentsector->sectornum != seg->backsector->sectornum)) + { + if (in_area == area_default) in_area = hw_CheckViewArea(seg->v1, seg->v2, seg->frontsector, seg->backsector); + backsector = hw_FakeFlat(drawctx, seg->backsector, in_area, true); + if (hw_CheckClip(seg->sidedef, currentsector, backsector)) clipperr.SafeAddClipRange(startAngleR - paddingR, endAngleR + paddingR); + backsector = nullptr; + } } } @@ -711,7 +717,7 @@ void HWDrawInfo::DoSubsector(subsector_t * sub, FRenderState& state) if(Viewpoint.IsAllowedOoB() && sector->isSecret() && sector->wasSecret() && !r_radarclipper) return; // cull everything if subsector outside all relevant clippers - if ((sub->polys == nullptr)) + if (Viewpoint.IsAllowedOoB() && (sub->polys == nullptr)) { auto &clipper = *mClipper; auto &clipperv = *vClipper; diff --git a/src/rendering/hwrenderer/scene/hw_drawinfo.cpp b/src/rendering/hwrenderer/scene/hw_drawinfo.cpp index ed0dafa59..d53bdd3aa 100644 --- a/src/rendering/hwrenderer/scene/hw_drawinfo.cpp +++ b/src/rendering/hwrenderer/scene/hw_drawinfo.cpp @@ -224,8 +224,8 @@ void HWDrawInfo::ClearBuffers() void HWDrawInfo::UpdateCurrentMapSection() { int mapsection = Level->PointInRenderSubsector(Viewpoint.Pos)->mapsection; - if (Viewpoint.IsAllowedOoB()) - mapsection = Level->PointInRenderSubsector(Viewpoint.camera->Pos())->mapsection; + if (Viewpoint.IsAllowedOoB() || Viewpoint.IsOrtho()) + mapsection = Level->PointInRenderSubsector(Viewpoint.OffPos)->mapsection; CurrentMapSections.Set(mapsection); } @@ -319,20 +319,19 @@ int HWDrawInfo::SetFullbrightFlags(player_t *player) // //----------------------------------------------------------------------------- -angle_t HWDrawInfo::FrustumAngle() +angle_t OoBFrustumAngle(FRenderViewpoint* Viewpoint) { // If pitch is larger than this you can look all around at an FOV of 90 degrees - if (fabs(Viewpoint.HWAngles.Pitch.Degrees()) > 89.0) return 0xffffffff; - else if (fabs(Viewpoint.HWAngles.Pitch.Degrees()) > 46.0 && !Viewpoint.IsAllowedOoB()) return 0xffffffff; // Just like 4.12.2 and older did + if (fabs(Viewpoint->HWAngles.Pitch.Degrees()) > 89.0) return 0xffffffff; int aspMult = AspectMultiplier(r_viewwindow.WidescreenRatio); // 48 == square window - double absPitch = fabs(Viewpoint.HWAngles.Pitch.Degrees()); + double absPitch = fabs(Viewpoint->HWAngles.Pitch.Degrees()); // Smaller aspect ratios still clip too much. Need a better solution if (aspMult > 36 && absPitch > 30.0) return 0xffffffff; else if (aspMult > 40 && absPitch > 25.0) return 0xffffffff; else if (aspMult > 45 && absPitch > 20.0) return 0xffffffff; else if (aspMult > 47 && absPitch > 10.0) return 0xffffffff; - double xratio = r_viewwindow.FocalTangent / Viewpoint.PitchCos; + double xratio = r_viewwindow.FocalTangent / Viewpoint->PitchCos; double floatangle = 0.05 + atan ( xratio ) * 48.0 / aspMult; // this is radians angle_t a1 = DAngle::fromRad(floatangle).BAMs(); @@ -340,6 +339,28 @@ angle_t HWDrawInfo::FrustumAngle() return a1; } +angle_t HWDrawInfo::FrustumAngle() +{ + if (Viewpoint.IsAllowedOoB()) + { + return OoBFrustumAngle(&Viewpoint); + } + else + { + float tilt = fabs(Viewpoint.HWAngles.Pitch.Degrees()); + + // If the pitch is larger than this you can look all around at a FOV of 90° + if (tilt > 46.0f) return 0xffffffff; + + // ok, this is a gross hack that barely works... + // but at least it doesn't overestimate too much... + double floatangle = 2.0 + (45.0 + ((tilt / 1.9)))*Viewpoint.FieldOfView.Degrees() * 48.0 / AspectMultiplier(r_viewwindow.WidescreenRatio) / 90.0; + angle_t a1 = DAngle::fromDeg(floatangle).BAMs(); + if (a1 >= ANGLE_180) return 0xffffffff; + return a1; + } +} + //----------------------------------------------------------------------------- // // Setup the modelview matrix @@ -425,7 +446,9 @@ void HWDrawInfo::CreateScene(bool drawpsprites, FRenderState& state) { double a2 = 20.0 + 0.5*Viewpoint.FieldOfView.Degrees(); // FrustumPitch for vertical clipping if (a2 > 179.0) a2 = 179.0; - vClipper->SafeAddClipRangeDegPitches(vp.HWAngles.Pitch.Degrees() - a2, vp.HWAngles.Pitch.Degrees() + a2); // clip the suplex range + double pitchmult = !!(drawctx->portalState.PlaneMirrorFlag & 1) ? -1.0 : 1.0; + vClipper->SafeAddClipRangeDegPitches(pitchmult * vp.HWAngles.Pitch.Degrees() - a2, pitchmult * vp.HWAngles.Pitch.Degrees() + a2); // clip the suplex range + Viewpoint.PitchSin *= pitchmult; } // reset the portal manager @@ -1292,8 +1315,8 @@ void HWDrawInfo::ProcessScene(bool toscreen, FRenderState& state) drawctx->portalState.BeginScene(); int mapsection = Level->PointInRenderSubsector(Viewpoint.Pos)->mapsection; - if (Viewpoint.IsAllowedOoB()) - mapsection = Level->PointInRenderSubsector(Viewpoint.camera->Pos())->mapsection; + if (Viewpoint.IsAllowedOoB() || Viewpoint.IsOrtho()) + mapsection = Level->PointInRenderSubsector(Viewpoint.OffPos)->mapsection; CurrentMapSections.Set(mapsection); DrawScene(toscreen ? DM_MAINVIEW : DM_OFFSCREEN, state); diff --git a/src/rendering/hwrenderer/scene/hw_portal.cpp b/src/rendering/hwrenderer/scene/hw_portal.cpp index 4a30912c6..b06b8ec6c 100644 --- a/src/rendering/hwrenderer/scene/hw_portal.cpp +++ b/src/rendering/hwrenderer/scene/hw_portal.cpp @@ -332,6 +332,7 @@ void HWPortal::RemoveStencil(HWDrawInfo *di, FRenderState &state, bool usestenci bool needdepth = NeedDepthBuffer(); // Restore the old view + auto &vp = di->Viewpoint; if (vp.camera != nullptr) vp.camera->renderflags = (vp.camera->renderflags & ~RF_MAYBEINVISIBLE) | savedvisibility; diff --git a/src/rendering/hwrenderer/scene/hw_sky.cpp b/src/rendering/hwrenderer/scene/hw_sky.cpp index 71411ac2a..1e37d55d1 100644 --- a/src/rendering/hwrenderer/scene/hw_sky.cpp +++ b/src/rendering/hwrenderer/scene/hw_sky.cpp @@ -165,7 +165,6 @@ void HWWall::SkyPlane(HWWallDispatcher *di, FRenderState& state, sector_t *secto if (glport != NULL) { if (sector->PortalBlocksView(plane)) return; - if (di->di && screen->instack[1 - plane]) return; ptype = PORTALTYPE_SECTORSTACK; portal = glport; diff --git a/src/rendering/hwrenderer/scene/hw_spritelight.cpp b/src/rendering/hwrenderer/scene/hw_spritelight.cpp index cdc9146c2..523a14f63 100644 --- a/src/rendering/hwrenderer/scene/hw_spritelight.cpp +++ b/src/rendering/hwrenderer/scene/hw_spritelight.cpp @@ -217,7 +217,7 @@ void HWDrawInfo::GetDynSpriteLight(AActor *self, sun_trace_cache_t * traceCache, lg = light->GetGreen() / 255.0f; lb = light->GetBlue() / 255.0f; - if (light->target) + if (light->target && (light->target->renderflags2 & RF2_LIGHTMULTALPHA)) { float alpha = (float)light->target->Alpha; lr *= alpha; diff --git a/src/rendering/hwrenderer/scene/hw_sprites.cpp b/src/rendering/hwrenderer/scene/hw_sprites.cpp index bbec77694..fdd95b1be 100644 --- a/src/rendering/hwrenderer/scene/hw_sprites.cpp +++ b/src/rendering/hwrenderer/scene/hw_sprites.cpp @@ -1494,7 +1494,7 @@ void HWSprite::ProcessParticle(HWDrawInfo *di, FRenderState& state, particle_t * if (!particle || particle->alpha <= 0) return; - if (spr && spr->PT.texture.isNull()) + if (spr && !spr->ValidTexture()) return; lightlevel = hw_ClampLight(spr ? spr->GetLightLevel(sector) : sector->GetSpriteLight()); @@ -1563,17 +1563,29 @@ void HWSprite::ProcessParticle(HWDrawInfo *di, FRenderState& state, particle_t * if (paused || (di->Level->isFrozen() && !(particle->flags & SPF_NOTIMEFREEZE))) timefrac = 0.; - if (spr) + + if (spr && !(spr->flags & VTF_IsParticle)) { AdjustVisualThinker(di, spr, sector); } else { - bool has_texture = particle->texture.isValid(); - bool custom_animated_texture = (particle->flags & SPF_LOCAL_ANIM) && particle->animData.ok; - - int particle_style = has_texture ? 2 : gl_particles_style; // Treat custom texture the same as smooth particles - + bool has_texture = false; + bool custom_animated_texture = false; + int particle_style = 0; + float size = particle->size; + if (!spr) + { + has_texture = particle->texture.isValid(); + custom_animated_texture = (particle->flags & SPF_LOCAL_ANIM) && particle->animData.ok; + particle_style = has_texture ? 2 : gl_particles_style; // Treat custom texture the same as smooth particles + } + else + { + size = float(spr->Scale.X); + const int ptype = spr->GetParticleType(); + particle_style = (ptype != PT_DEFAULT) ? ptype : gl_particles_style; + } // [BB] Load the texture for round or smooth particles if (particle_style) { @@ -1635,7 +1647,7 @@ void HWSprite::ProcessParticle(HWDrawInfo *di, FRenderState& state, particle_t * if (particle_style == 1) factor = 1.3f / 7.f; else if (particle_style == 2) factor = 2.5f / 7.f; else factor = 1 / 7.f; - float scalefac=particle->size * factor; + float scalefac= size * factor; float ps = di->Level->pixelstretch; diff --git a/src/scripting/thingdef_data.cpp b/src/scripting/thingdef_data.cpp index e17e28c35..73d579e31 100644 --- a/src/scripting/thingdef_data.cpp +++ b/src/scripting/thingdef_data.cpp @@ -389,6 +389,7 @@ static FFlagDef ActorFlagDefs[]= DEFINE_FLAG(RF2, ISOMETRICSPRITES, AActor, renderflags2), DEFINE_FLAG(RF2, SQUAREPIXELS, AActor, renderflags2), DEFINE_FLAG(RF2, STRETCHPIXELS, AActor, renderflags2), + DEFINE_FLAG(RF2, LIGHTMULTALPHA, AActor, renderflags2), // Bounce flags DEFINE_FLAG2(BOUNCE_Walls, BOUNCEONWALLS, AActor, BounceFlags), diff --git a/src/scripting/vmthunks.cpp b/src/scripting/vmthunks.cpp index ab3dc5b94..2e994e84b 100644 --- a/src/scripting/vmthunks.cpp +++ b/src/scripting/vmthunks.cpp @@ -2269,6 +2269,7 @@ DEFINE_ACTION_FUNCTION_NATIVE(FLevelLocals, GetSpotState, GetSpotState) //--------------------------------------------------------------------------- EXTERN_CVAR(Int, am_showmaplabel) +EXTERN_CVAR(Bool, am_showlevelname) void FormatMapName(FLevelLocals *self, int cr, FString *result) { @@ -2282,13 +2283,19 @@ void FormatMapName(FLevelLocals *self, int cr, FString *result) if (self->info->MapLabel.IsNotEmpty()) { if (self->info->MapLabel.Compare("*")) - *result << self->info->MapLabel << ": "; + *result << self->info->MapLabel; } else if (am_showmaplabel == 1 || (am_showmaplabel == 2 && !ishub)) { - *result << self->MapName << ": "; + *result << self->MapName; + } + + if (am_showlevelname) + { + if (!result->IsEmpty()) + *result << ": "; + *result << mapnamecolor << self->LevelName; } - *result << mapnamecolor << self->LevelName; } DEFINE_ACTION_FUNCTION_NATIVE(FLevelLocals, FormatMapName, FormatMapName) diff --git a/tools/lemon/lemon.c b/tools/lemon/lemon.c index bdc004a17..45f458d72 100644 --- a/tools/lemon/lemon.c +++ b/tools/lemon/lemon.c @@ -53,7 +53,7 @@ extern int access(char *path, int mode); #endif static int showPrecedenceConflict = 0; -static void *msort(void *list, void *next, int (*cmp)()); +static void *msort(void *list, void *next, int (*cmp)(void*, void*)); /* ** Compilers are getting increasingly pedantic about type conversions @@ -72,12 +72,12 @@ static struct action *Action_new(void); static struct action *Action_sort(struct action *); /********** From the file "build.h" ************************************/ -void FindRulePrecedences(); -void FindFirstSets(); -void FindStates(); -void FindLinks(); -void FindFollowSets(); -void FindActions(); +void FindRulePrecedences(struct lemon *xp); +void FindFirstSets(struct lemon *lemp); +void FindStates(struct lemon *lemp); +void FindLinks(struct lemon *lemp); +void FindFollowSets(struct lemon *lemp); +void FindActions(struct lemon *lemp); /********* From the file "configlist.h" *********************************/ void Configlist_init(void); @@ -359,7 +359,7 @@ struct symbol **Symbol_arrayof(void); /* Routines to manage the state table */ -int Configcmp(const char *, const char *); +int Configcmp(void *, void *); struct state *State_new(void); void State_init(void); int State_insert(struct state *, struct config *); @@ -403,10 +403,10 @@ static struct action *Action_new(void){ ** positive if the first action is less than, equal to, or greater than ** the first */ -static int actioncmp(ap1,ap2) -struct action *ap1; -struct action *ap2; +static int actioncmp(void *_ap1,void *_ap2) { + struct action * ap1 = (struct action *)_ap1; + struct action * ap2 = (struct action *)_ap2; int rc; rc = ap1->sp->index - ap2->sp->index; if( rc==0 ){ @@ -1757,9 +1757,9 @@ int main(int argc, char **argv) ** The "next" pointers for elements in the lists a and b are ** changed. */ -static void *merge(void *a,void *b,int (*cmp)(),size_t offset) +static void *merge(void *a,void *b,int (*cmp)(void *a, void *b),size_t offset) { - char *ptr, *head; + void *ptr, *head; if( a==0 ){ head = b; @@ -1805,11 +1805,11 @@ static void *merge(void *a,void *b,int (*cmp)(),size_t offset) ** The "next" pointers for elements in list are changed. */ #define LISTSIZE 30 -static void *msort(void *list,void *next,int (*cmp)()) +static void *msort(void *list,void *next,int (*cmp)(void*, void*)) { size_t offset; - char *ep; - char *set[LISTSIZE]; + void *ep; + void *set[LISTSIZE]; int i; offset = (size_t)next - (size_t)list; for(i=0; irp->index - b->rp->index; if( x==0 ) x = a->dot - b->dot; @@ -5147,8 +5145,10 @@ int Configcmp(const char *_a,const char *_b) } /* Compare two states */ -PRIVATE int statecmp(struct config *a, struct config *b) +PRIVATE int statecmp(void *_a, void *_b) { + const struct config *a = (const struct config *) _a; + const struct config *b = (const struct config *) _b; int rc; for(rc=0; rc==0 && a && b; a=a->bp, b=b->bp){ rc = a->rp->index - b->rp->index; @@ -5377,7 +5377,7 @@ int Configtable_insert(struct config *data) h = ph & (x4a->size-1); np = x4a->ht[h]; while( np ){ - if( Configcmp((const char *) np->data,(const char *) data)==0 ){ + if( Configcmp(np->data, data)==0 ){ /* An existing entry with the same key is found. */ /* Fail because overwrite is not allows. */ return 0; @@ -5430,7 +5430,7 @@ struct config *Configtable_find(struct config *key) h = confighash(key) & (x4a->size-1); np = x4a->ht[h]; while( np ){ - if( Configcmp((const char *) np->data,(const char *) key)==0 ) break; + if( Configcmp(np->data,key)==0 ) break; np = np->next; } return np ? np->data : 0; diff --git a/wadsrc/static/language.def b/wadsrc/static/language.def index 4118f44a6..84f152d77 100644 --- a/wadsrc/static/language.def +++ b/wadsrc/static/language.def @@ -391,6 +391,27 @@ TAG_ARTIINVULNERABILITY = "$$TXT_ARTIINVULNERABILITY"; TAG_ARTITELEPORT = "$$TXT_ARTITELEPORT"; TAG_ARTITOMEOFPOWER = "$$TXT_ARTITOMEOFPOWER"; TAG_ARTITORCH = "$$TXT_ARTITORCH"; +TAG_ITEMBAGOFHOLDING = "$$TXT_ITEMBAGOFHOLDING"; +TAG_ITEMSHIELD1 = "$$TXT_ITEMSHIELD2"; +TAG_ITEMSHIELD2 = "$$TXT_ITEMSHIELD2"; +TAG_GOTGREENKEY = "$$TXT_GOTGREENKEY"; +TAG_GOTBLUEKEY = "$$TXT_GOTBLUEKEY"; +TAG_GOTYELLOWKEY = "$$TXT_GOTYELLOWKEY"; +TAG_ITEMSUPERMAP = "$$TXT_ITEMSUPERMAP"; + +TAG_KEY_STEEL = "$$TXT_KEY_STEEL"; +TAG_KEY_CAVE = "$$TXT_KEY_CAVE"; +TAG_KEY_AXE = "$$TXT_KEY_AXE"; +TAG_KEY_FIRE = "$$TXT_KEY_FIRE"; +TAG_KEY_EMERALD = "$$TXT_KEY_EMERALD"; +TAG_KEY_DUNGEON = "$$TXT_KEY_DUNGEON"; +TAG_KEY_SILVER = "$$TXT_KEY_SILVER"; +TAG_KEY_RUSTED = "$$TXT_KEY_RUSTED"; +TAG_KEY_HORN = "$$TXT_KEY_HORN"; +TAG_KEY_SWAMP = "$$TXT_KEY_SWAMP"; +TAG_KEY_CASTLE = "$$TXT_KEY_CASTLE"; + +TAG_ITEMHEALTH = "$$TXT_ITEMHEALTH"; // newly added text not in the string table diff --git a/wadsrc/static/zscript/actors/actor.zs b/wadsrc/static/zscript/actors/actor.zs index 351a75f1d..32127c669 100644 --- a/wadsrc/static/zscript/actors/actor.zs +++ b/wadsrc/static/zscript/actors/actor.zs @@ -775,7 +775,7 @@ class Actor : Thinker native native Actor OldSpawnMissile(Actor dest, class type, Actor owner = null); native Actor SpawnPuff(class pufftype, vector3 pos, double hitdir, double particledir, int updown, int flags = 0, Actor victim = null); - native void SpawnBlood (Vector3 pos1, double dir, int damage); + native Actor SpawnBlood (Vector3 pos1, double dir, int damage); native void BloodSplatter (Vector3 pos, double hitangle, bool axe = false); native bool HitWater (sector sec, Vector3 pos, bool checkabove = false, bool alert = true, bool force = false, int flags = 0); native void PlaySpawnSound(Actor missile); diff --git a/wadsrc/static/zscript/actors/heretic/hereticammo.zs b/wadsrc/static/zscript/actors/heretic/hereticammo.zs index 6464cf9dc..daf6d3ea7 100644 --- a/wadsrc/static/zscript/actors/heretic/hereticammo.zs +++ b/wadsrc/static/zscript/actors/heretic/hereticammo.zs @@ -237,6 +237,7 @@ Class BagOfHolding : BackpackItem Default { Inventory.PickupMessage "$TXT_ITEMBAGOFHOLDING"; + Tag "$TAG_ITEMBAGOFHOLDING"; +COUNTITEM +FLOATBOB } diff --git a/wadsrc/static/zscript/actors/heretic/hereticarmor.zs b/wadsrc/static/zscript/actors/heretic/hereticarmor.zs index 8cbcb9fbc..b95a71ad9 100644 --- a/wadsrc/static/zscript/actors/heretic/hereticarmor.zs +++ b/wadsrc/static/zscript/actors/heretic/hereticarmor.zs @@ -7,6 +7,7 @@ Class SilverShield : BasicArmorPickup { +FLOATBOB Inventory.Pickupmessage "$TXT_ITEMSHIELD1"; + Tag "$TAG_ITEMSHIELD1"; Inventory.Icon "SHLDA0"; Armor.Savepercent 50; Armor.Saveamount 100; @@ -27,6 +28,7 @@ Class EnchantedShield : BasicArmorPickup { +FLOATBOB Inventory.Pickupmessage "$TXT_ITEMSHIELD2"; + Tag "$TAG_ITEMSHIELD2"; Inventory.Icon "SHD2A0"; Armor.Savepercent 75; Armor.Saveamount 200; diff --git a/wadsrc/static/zscript/actors/heretic/hereticartifacts.zs b/wadsrc/static/zscript/actors/heretic/hereticartifacts.zs index b620b04b4..117d37586 100644 --- a/wadsrc/static/zscript/actors/heretic/hereticartifacts.zs +++ b/wadsrc/static/zscript/actors/heretic/hereticartifacts.zs @@ -9,6 +9,7 @@ Class SuperMap : MapRevealer +FLOATBOB Inventory.MaxAmount 0; Inventory.PickupMessage "$TXT_ITEMSUPERMAP"; + Tag "$TAG_ITEMSUPERMAP"; } States { diff --git a/wadsrc/static/zscript/actors/heretic/heretickeys.zs b/wadsrc/static/zscript/actors/heretic/heretickeys.zs index d5532ce01..b2bf3f363 100644 --- a/wadsrc/static/zscript/actors/heretic/heretickeys.zs +++ b/wadsrc/static/zscript/actors/heretic/heretickeys.zs @@ -16,6 +16,7 @@ Class KeyGreen : HereticKey Default { Inventory.PickupMessage "$TXT_GOTGREENKEY"; + Tag "$TAG_GOTGREENKEY"; Inventory.Icon "GKEYICON"; } States @@ -33,6 +34,7 @@ Class KeyBlue : HereticKey Default { Inventory.PickupMessage "$TXT_GOTBLUEKEY"; + Tag "$TAG_GOTBLUEKEY"; Inventory.Icon "BKEYICON"; } States @@ -50,6 +52,7 @@ Class KeyYellow : HereticKey Default { Inventory.PickupMessage "$TXT_GOTYELLOWKEY"; + Tag "$TAG_GOTYELLOWKEY"; Inventory.Icon "YKEYICON"; } States diff --git a/wadsrc/static/zscript/actors/hexen/hexenkeys.zs b/wadsrc/static/zscript/actors/hexen/hexenkeys.zs index 9bf9f426c..c0ec85ce7 100644 --- a/wadsrc/static/zscript/actors/hexen/hexenkeys.zs +++ b/wadsrc/static/zscript/actors/hexen/hexenkeys.zs @@ -14,6 +14,7 @@ class KeySteel : HexenKey { Inventory.Icon "KEYSLOT1"; Inventory.PickupMessage "$TXT_KEY_STEEL"; + Tag "$TAG_KEY_STEEL"; } States { @@ -29,6 +30,7 @@ class KeyCave : HexenKey { Inventory.Icon "KEYSLOT2"; Inventory.PickupMessage "$TXT_KEY_CAVE"; + Tag "$TAG_KEY_CAVE"; } States { @@ -44,6 +46,7 @@ class KeyAxe : HexenKey { Inventory.Icon "KEYSLOT3"; Inventory.PickupMessage "$TXT_KEY_AXE"; + Tag "$TAG_KEY_AXE"; } States { @@ -59,6 +62,7 @@ class KeyFire : HexenKey { Inventory.Icon "KEYSLOT4"; Inventory.PickupMessage "$TXT_KEY_FIRE"; + Tag "$TAG_KEY_FIRE"; } States { @@ -74,6 +78,7 @@ class KeyEmerald : HexenKey { Inventory.Icon "KEYSLOT5"; Inventory.PickupMessage "$TXT_KEY_EMERALD"; + Tag "$TAG_KEY_EMERALD"; } States { @@ -89,6 +94,7 @@ class KeyDungeon : HexenKey { Inventory.Icon "KEYSLOT6"; Inventory.PickupMessage "$TXT_KEY_DUNGEON"; + Tag "$TAG_KEY_DUNGEON"; } States { @@ -104,6 +110,7 @@ class KeySilver : HexenKey { Inventory.Icon "KEYSLOT7"; Inventory.PickupMessage "$TXT_KEY_SILVER"; + Tag "$TAG_KEY_SILVER"; } States { @@ -119,6 +126,7 @@ class KeyRusted : HexenKey { Inventory.Icon "KEYSLOT8"; Inventory.PickupMessage "$TXT_KEY_RUSTED"; + Tag "$TAG_KEY_RUSTED"; } States { @@ -134,6 +142,7 @@ class KeyHorn : HexenKey { Inventory.Icon "KEYSLOT9"; Inventory.PickupMessage "$TXT_KEY_HORN"; + Tag "$TAG_KEY_HORN"; } States { @@ -149,6 +158,7 @@ class KeySwamp : HexenKey { Inventory.Icon "KEYSLOTA"; Inventory.PickupMessage "$TXT_KEY_SWAMP"; + Tag "$TAG_KEY_SWAMP"; } States { @@ -164,6 +174,7 @@ class KeyCastle : HexenKey { Inventory.Icon "KEYSLOTB"; Inventory.PickupMessage "$TXT_KEY_CASTLE"; + Tag "$TAG_KEY_CASTLE"; } States { diff --git a/wadsrc/static/zscript/actors/inventory/inventory.zs b/wadsrc/static/zscript/actors/inventory/inventory.zs index 607c4f7c4..40a89cb08 100644 --- a/wadsrc/static/zscript/actors/inventory/inventory.zs +++ b/wadsrc/static/zscript/actors/inventory/inventory.zs @@ -85,6 +85,11 @@ class Inventory : Actor Inventory.PickupSound "misc/i_pkup"; Inventory.PickupMessage "$TXT_DEFAULTPICKUPMSG"; } + + override void OnLoad() + { + UpdateLocalPickupStatus(); + } //native override void Tick(); @@ -1113,6 +1118,11 @@ class Inventory : Actor return pickedUp[client.PlayerNumber()]; } + void UpdateLocalPickupStatus() + { + DisableLocalRendering(consoleplayer, pickedUp[consoleplayer]); + } + // When items are dropped, clear their local pick ups. void ClearLocalPickUps() { diff --git a/wadsrc/static/zscript/actors/inventory/stateprovider.zs b/wadsrc/static/zscript/actors/inventory/stateprovider.zs index e02287258..bba4adb3b 100644 --- a/wadsrc/static/zscript/actors/inventory/stateprovider.zs +++ b/wadsrc/static/zscript/actors/inventory/stateprovider.zs @@ -413,7 +413,7 @@ class StateProvider : Inventory // //--------------------------------------------------------------------------- - action void A_ReFire(statelabel flash = null) + action void A_ReFire(statelabel flash = null, bool autoSwitch = true) { let player = player; bool pending; @@ -438,7 +438,7 @@ class StateProvider : Inventory else { player.refire = 0; - player.ReadyWeapon.CheckAmmo (player.ReadyWeapon.bAltFire? Weapon.AltFire : Weapon.PrimaryFire, true); + player.ReadyWeapon.CheckAmmo (player.ReadyWeapon.bAltFire? Weapon.AltFire : Weapon.PrimaryFire, autoSwitch); } } diff --git a/wadsrc/static/zscript/actors/player/player.zs b/wadsrc/static/zscript/actors/player/player.zs index 6bfb58344..1af41c1c0 100644 --- a/wadsrc/static/zscript/actors/player/player.zs +++ b/wadsrc/static/zscript/actors/player/player.zs @@ -1289,7 +1289,7 @@ class PlayerPawn : Actor if (player.turnticks) { player.turnticks--; - Angle += (180. / TURN180_TICKS); + A_SetAngle(Angle + (180. / TURN180_TICKS), SPF_INTERPOLATE); } else { diff --git a/wadsrc/static/zscript/actors/raven/ravenhealth.zs b/wadsrc/static/zscript/actors/raven/ravenhealth.zs index cf7c79d0a..7bf14ae15 100644 --- a/wadsrc/static/zscript/actors/raven/ravenhealth.zs +++ b/wadsrc/static/zscript/actors/raven/ravenhealth.zs @@ -5,6 +5,7 @@ class CrystalVial : Health +FLOATBOB Inventory.Amount 10; Inventory.PickupMessage "$TXT_ITEMHEALTH"; + Tag "$TAG_ITEMHEALTH"; } States { diff --git a/wadsrc/static/zscript/actors/shared/dynlights.zs b/wadsrc/static/zscript/actors/shared/dynlights.zs index f10652c07..5db76c128 100644 --- a/wadsrc/static/zscript/actors/shared/dynlights.zs +++ b/wadsrc/static/zscript/actors/shared/dynlights.zs @@ -80,6 +80,7 @@ class DynamicLight : Actor +FIXMAPTHINGPOS +INVISIBLE +NOTONAUTOMAP + +LIGHTMULTALPHA } //========================================================================== diff --git a/wadsrc/static/zscript/constants.zs b/wadsrc/static/zscript/constants.zs index a0d06596b..7f8f03572 100644 --- a/wadsrc/static/zscript/constants.zs +++ b/wadsrc/static/zscript/constants.zs @@ -1532,6 +1532,20 @@ enum EVisualThinkerFlags VTF_FlipY = 1 << 3, // flip the sprite on the x/y axis. VTF_DontInterpolate = 1 << 4, // disable all interpolation VTF_AddLightLevel = 1 << 5, // adds sector light level to 'LightLevel' + + VTF_ParticleDefault = 0x40, + VTF_ParticleSquare = 0x80, + VTF_ParticleRound = 0xC0, + VTF_ParticleSmooth = 0x100, + VTF_IsParticle = 0x1C0 +}; + +enum EParticleStyle +{ + PT_DEFAULT = -1, // Use gl_particles_style + PT_SQUARE = 0, + PT_ROUND = 1, + PT_SMOOTH = 2, }; enum ESetBoneMode diff --git a/wadsrc/static/zscript/doombase.zs b/wadsrc/static/zscript/doombase.zs index b0e5530b9..ffd5b461c 100644 --- a/wadsrc/static/zscript/doombase.zs +++ b/wadsrc/static/zscript/doombase.zs @@ -192,6 +192,7 @@ class Thinker : Object native play virtual native void Tick(); virtual native void PostBeginPlay(); + virtual void OnLoad() {} native void ChangeStatNum(int stat); static clearscope int Tics2Seconds(int tics) @@ -652,12 +653,108 @@ class SectorEffect : Thinker native class Mover : SectorEffect native {} +class Elevator : Mover native +{ + enum EElevator + { + elevateUp, + elevateDown, + elevateCurrent, + // [RH] For FloorAndCeiling_Raise/Lower + elevateRaise, + elevateLower + }; + + native readonly EElevator m_Type; + native readonly int m_Direction; + native readonly double m_FloorDestDist; + native readonly double m_CeilingDestDist; + native readonly double m_Speed; +} + class MovingFloor : Mover native {} +class Plat : MovingFloor native +{ + enum EPlatState + { + up, + down, + waiting, + in_stasis + }; + + enum EPlatType + { + platPerpetualRaise, + platDownWaitUpStay, + platDownWaitUpStayStone, + platUpWaitDownStay, + platUpNearestWaitDownStay, + platDownByValue, + platUpByValue, + platUpByValueStay, + platRaiseAndStay, + platToggle, + platDownToNearestFloor, + platDownToLowestCeiling, + platRaiseAndStayLockout, + }; + + bool IsLift() const { return m_Type == platDownWaitUpStay || m_Type == platDownWaitUpStayStone; } + + native readonly double m_Speed; + native readonly double m_Low; + native readonly double m_High; + native readonly int m_Wait; + native readonly int m_Count; + native readonly EPlatState m_Status; + native readonly EPlatState m_OldStatus; + native readonly int m_Crush; + native readonly int m_Tag; + native readonly EPlatType m_Type; +} + class MovingCeiling : Mover native {} +class Door : MovingCeiling native +{ + enum EVlDoor + { + doorClose, + doorOpen, + doorRaise, + doorWaitRaise, + doorCloseWaitOpen, + doorWaitClose, + }; + + native readonly EVlDoor m_Type; + native readonly double m_TopDist; + native readonly double m_BotDist, m_OldFloorDist; + native readonly Vertex m_BotSpot; + native readonly double m_Speed; + + // 1 = up, 0 = waiting at top, -1 = down + enum EDirection + { + dirDown = -1, + dirWait, + dirUp, + } + native readonly int m_Direction; + + // tics to wait at the top + native readonly int m_TopWait; + // (keep in case a door going down is reset) + // when it reaches 0, start going down + native readonly int m_TopCountdown; + + native readonly int m_LightTag; +} + class Floor : MovingFloor native { // only here so that some constants and functions can be added. Not directly usable yet. @@ -700,6 +797,37 @@ class Floor : MovingFloor native genFloorChg }; + enum EStair + { + buildUp, + buildDown + }; + + enum EStairType + { + stairUseSpecials = 1, + stairSync = 2, + stairCrush = 4, + }; + + native readonly EFloor m_Type; + native readonly int m_Crush; + native readonly bool m_Hexencrush; + native readonly bool m_Instant; + native readonly int m_Direction; + native readonly SecSpecial m_NewSpecial; + native readonly TextureID m_Texture; + native readonly double m_FloorDestDist; + native readonly double m_Speed; + + // [RH] New parameters used to reset and delay stairs + native readonly double m_OrgDist; + native readonly int m_ResetCount; + native readonly int m_Delay; + native readonly int m_PauseTime; + native readonly int m_StepTime; + native readonly int m_PerStepTime; + deprecated("3.8", "Use Level.CreateFloor() instead") static bool CreateFloor(sector sec, int floortype, line ln, double speed, double height = 0, int crush = -1, int change = 0, bool crushmode = false, bool hereticlower = false) { return level.CreateFloor(sec, floortype, ln, speed, height, crush, change, crushmode, hereticlower); @@ -745,7 +873,29 @@ class Ceiling : MovingCeiling native crushHexen = 1, crushSlowdown = 2 } - + + // 1 = up, 0 = waiting, -1 = down + enum EDirection + { + dirDown = -1, + dirWait, + dirUp, + } + + native readonly ECeiling m_Type; + native readonly double m_BottomHeight; + native readonly double m_TopHeight; + native readonly double m_Speed; + native readonly double m_Speed1; // [RH] dnspeed of crushers + native readonly double m_Speed2; // [RH] upspeed of crushers + native readonly ECrushMode m_CrushMode; + native readonly int m_Silent; + + bool IsCrusher() const { return m_Type == ceilCrushAndRaise || m_Type == ceilLowerAndCrush || m_Type == ceilCrushRaiseAndStay; } + native int getCrush() const; + native int getDirection() const; + native int getOldDirection() const; + deprecated("3.8", "Use Level.CreateCeiling() instead") static bool CreateCeiling(sector sec, int type, line ln, double speed, double speed2, double height = 0, int crush = -1, int silent = 0, int change = 0, int crushmode = crushDoom) { return level.CreateCeiling(sec, type, ln, speed, speed2, height, crush, silent, change, crushmode); diff --git a/wadsrc/static/zscript/engine/base.zs b/wadsrc/static/zscript/engine/base.zs index fa212ba38..48eb46343 100644 --- a/wadsrc/static/zscript/engine/base.zs +++ b/wadsrc/static/zscript/engine/base.zs @@ -189,7 +189,7 @@ struct Vector3 } */ -struct _ native // These are the global variables, the struct is only here to avoid extending the parser for this. +struct _ native unsafe(internal) // These are the global variables, the struct is only here to avoid extending the parser for this. { native readonly Array AllClasses; native internal readonly Map AllServices; @@ -893,6 +893,9 @@ struct Wads // todo: make FileSystem an alias to 'Wads' native static string GetLumpName(int lump); native static string GetLumpFullName(int lump); native static int GetLumpNamespace(int lump); + native static int GetLumpContainer(int lump); + native static string GetContainerName(int lump); + native static string GetLumpFullPath(int lump); } enum EmptyTokenType @@ -903,7 +906,7 @@ enum EmptyTokenType // Although String is a builtin type, this is a convenient way to attach methods to it. // All of these methods are available on strings -struct StringStruct native +struct StringStruct native unsafe(internal) { native static vararg String Format(String fmt, ...); native vararg void AppendFormat(String fmt, ...); @@ -952,7 +955,7 @@ struct Translation version("2.4") } // Convenient way to attach functions to Quat -struct QuatStruct native +struct QuatStruct native unsafe(internal) { native static Quat SLerp(Quat from, Quat to, double t); native static Quat NLerp(Quat from, Quat to, double t); diff --git a/wadsrc/static/zscript/engine/dynarrays.zs b/wadsrc/static/zscript/engine/dynarrays.zs index f9e6a680d..d21c70e1a 100644 --- a/wadsrc/static/zscript/engine/dynarrays.zs +++ b/wadsrc/static/zscript/engine/dynarrays.zs @@ -1,7 +1,7 @@ // The VM uses 7 integral data types, so for dynamic array support we need one specific set of functions for each of these types. // Do not use these structs directly, they are incomplete and only needed to create prototypes for the needed functions. -struct DynArray_I8 native +struct DynArray_I8 native unsafe(internal) { native readonly int Size; @@ -21,7 +21,7 @@ struct DynArray_I8 native native void Clear (); } -struct DynArray_I16 native +struct DynArray_I16 native unsafe(internal) { native readonly int Size; @@ -41,7 +41,7 @@ struct DynArray_I16 native native void Clear (); } -struct DynArray_I32 native +struct DynArray_I32 native unsafe(internal) { native readonly int Size; @@ -62,7 +62,7 @@ struct DynArray_I32 native native void Clear (); } -struct DynArray_F32 native +struct DynArray_F32 native unsafe(internal) { native readonly int Size; @@ -82,7 +82,7 @@ struct DynArray_F32 native native void Clear (); } -struct DynArray_F64 native +struct DynArray_F64 native unsafe(internal) { native readonly int Size; @@ -102,7 +102,7 @@ struct DynArray_F64 native native void Clear (); } -struct DynArray_Ptr native +struct DynArray_Ptr native unsafe(internal) { native readonly int Size; @@ -122,7 +122,7 @@ struct DynArray_Ptr native native void Clear (); } -struct DynArray_Obj native +struct DynArray_Obj native unsafe(internal) { native readonly int Size; @@ -142,7 +142,7 @@ struct DynArray_Obj native native void Clear (); } -struct DynArray_String native +struct DynArray_String native unsafe(internal) { native readonly int Size; diff --git a/wadsrc/static/zscript/engine/maps.zs b/wadsrc/static/zscript/engine/maps.zs index b871edf05..dbc2f4dad 100644 --- a/wadsrc/static/zscript/engine/maps.zs +++ b/wadsrc/static/zscript/engine/maps.zs @@ -1,5 +1,5 @@ -struct Map_I32_I8 native +struct Map_I32_I8 native unsafe(internal) { native void Copy(Map_I32_I8 other); native void Move(Map_I32_I8 other); @@ -18,7 +18,7 @@ struct Map_I32_I8 native native void Remove(int key); } -struct MapIterator_I32_I8 native +struct MapIterator_I32_I8 native unsafe(internal) { native bool Init(Map_I32_I8 other); native bool ReInit(); @@ -31,7 +31,7 @@ struct MapIterator_I32_I8 native native void SetValue(int value); } -struct Map_I32_I16 native +struct Map_I32_I16 native unsafe(internal) { native void Copy(Map_I32_I16 other); native void Move(Map_I32_I16 other); @@ -50,7 +50,7 @@ struct Map_I32_I16 native native void Remove(int key); } -struct MapIterator_I32_I16 native +struct MapIterator_I32_I16 native unsafe(internal) { native bool Init(Map_I32_I16 other); native bool ReInit(); @@ -63,7 +63,7 @@ struct MapIterator_I32_I16 native native void SetValue(int value); } -struct Map_I32_I32 native +struct Map_I32_I32 native unsafe(internal) { native void Copy(Map_I32_I32 other); native void Move(Map_I32_I32 other); @@ -82,7 +82,7 @@ struct Map_I32_I32 native native void Remove(int key); } -struct MapIterator_I32_I32 native +struct MapIterator_I32_I32 native unsafe(internal) { native bool Init(Map_I32_I32 other); native bool ReInit(); @@ -95,7 +95,7 @@ struct MapIterator_I32_I32 native native void SetValue(int value); } -struct Map_I32_F32 native +struct Map_I32_F32 native unsafe(internal) { native void Copy(Map_I32_F32 other); native void Move(Map_I32_F32 other); @@ -114,7 +114,7 @@ struct Map_I32_F32 native native void Remove(int key); } -struct MapIterator_I32_F32 native +struct MapIterator_I32_F32 native unsafe(internal) { native bool Init(Map_I32_F32 other); native bool ReInit(); @@ -127,7 +127,7 @@ struct MapIterator_I32_F32 native native void SetValue(double value); } -struct Map_I32_F64 native +struct Map_I32_F64 native unsafe(internal) { native void Copy(Map_I32_F64 other); native void Move(Map_I32_F64 other); @@ -146,7 +146,7 @@ struct Map_I32_F64 native native void Remove(int key); } -struct MapIterator_I32_F64 native +struct MapIterator_I32_F64 native unsafe(internal) { native bool Init(Map_I32_F64 other); native bool ReInit(); @@ -159,7 +159,7 @@ struct MapIterator_I32_F64 native native void SetValue(double value); } -struct Map_I32_Obj native +struct Map_I32_Obj native unsafe(internal) { native void Copy(Map_I32_Obj other); native void Move(Map_I32_Obj other); @@ -178,7 +178,7 @@ struct Map_I32_Obj native native void Remove(int key); } -struct MapIterator_I32_Obj native +struct MapIterator_I32_Obj native unsafe(internal) { native bool Init(Map_I32_Obj other); native bool ReInit(); @@ -191,7 +191,7 @@ struct MapIterator_I32_Obj native native void SetValue(Object value); } -struct Map_I32_Ptr native +struct Map_I32_Ptr native unsafe(internal) { native void Copy(Map_I32_Ptr other); native void Move(Map_I32_Ptr other); @@ -210,7 +210,7 @@ struct Map_I32_Ptr native native void Remove(int key); } -struct MapIterator_I32_Ptr native +struct MapIterator_I32_Ptr native unsafe(internal) { native bool Init(Map_I32_Ptr other); native bool Next(); @@ -220,7 +220,7 @@ struct MapIterator_I32_Ptr native native void SetValue(voidptr value); } -struct Map_I32_Str native +struct Map_I32_Str native unsafe(internal) { native void Copy(Map_I32_Str other); native void Move(Map_I32_Str other); @@ -239,7 +239,7 @@ struct Map_I32_Str native native void Remove(int key); } -struct MapIterator_I32_Str native +struct MapIterator_I32_Str native unsafe(internal) { native bool Init(Map_I32_Str other); native bool ReInit(); @@ -254,7 +254,7 @@ struct MapIterator_I32_Str native // --------------- -struct Map_Str_I8 native +struct Map_Str_I8 native unsafe(internal) { native void Copy(Map_Str_I8 other); native void Move(Map_Str_I8 other); @@ -273,7 +273,7 @@ struct Map_Str_I8 native native void Remove(String key); } -struct MapIterator_Str_I8 native +struct MapIterator_Str_I8 native unsafe(internal) { native bool Init(Map_Str_I8 other); native bool ReInit(); @@ -286,7 +286,7 @@ struct MapIterator_Str_I8 native native void SetValue(int value); } -struct Map_Str_I16 native +struct Map_Str_I16 native unsafe(internal) { native void Copy(Map_Str_I16 other); native void Move(Map_Str_I16 other); @@ -305,7 +305,7 @@ struct Map_Str_I16 native native void Remove(String key); } -struct MapIterator_Str_I16 native +struct MapIterator_Str_I16 native unsafe(internal) { native bool Init(Map_Str_I16 other); native bool ReInit(); @@ -318,7 +318,7 @@ struct MapIterator_Str_I16 native native void SetValue(int value); } -struct Map_Str_I32 native +struct Map_Str_I32 native unsafe(internal) { native void Copy(Map_Str_I32 other); native void Move(Map_Str_I32 other); @@ -337,7 +337,7 @@ struct Map_Str_I32 native native void Remove(String key); } -struct MapIterator_Str_I32 native +struct MapIterator_Str_I32 native unsafe(internal) { native bool Init(Map_Str_I32 other); native bool ReInit(); @@ -350,7 +350,7 @@ struct MapIterator_Str_I32 native native void SetValue(int value); } -struct Map_Str_F32 native +struct Map_Str_F32 native unsafe(internal) { native void Copy(Map_Str_F32 other); native void Move(Map_Str_F32 other); @@ -369,7 +369,7 @@ struct Map_Str_F32 native native void Remove(String key); } -struct MapIterator_Str_F32 native +struct MapIterator_Str_F32 native unsafe(internal) { native bool Init(Map_Str_F32 other); native bool ReInit(); @@ -382,7 +382,7 @@ struct MapIterator_Str_F32 native native void SetValue(double value); } -struct Map_Str_F64 native +struct Map_Str_F64 native unsafe(internal) { native void Copy(Map_Str_F64 other); native void Move(Map_Str_F64 other); @@ -401,7 +401,7 @@ struct Map_Str_F64 native native void Remove(String key); } -struct MapIterator_Str_F64 native +struct MapIterator_Str_F64 native unsafe(internal) { native bool Init(Map_Str_F64 other); native bool ReInit(); @@ -414,7 +414,7 @@ struct MapIterator_Str_F64 native native void SetValue(double value); } -struct Map_Str_Obj native +struct Map_Str_Obj native unsafe(internal) { native void Copy(Map_Str_Obj other); native void Move(Map_Str_Obj other); @@ -433,7 +433,7 @@ struct Map_Str_Obj native native void Remove(String key); } -struct MapIterator_Str_Obj native +struct MapIterator_Str_Obj native unsafe(internal) { native bool Init(Map_Str_Obj other); native bool ReInit(); @@ -446,7 +446,7 @@ struct MapIterator_Str_Obj native native void SetValue(Object value); } -struct Map_Str_Ptr native +struct Map_Str_Ptr native unsafe(internal) { native void Copy(Map_Str_Ptr other); native void Move(Map_Str_Ptr other); @@ -465,7 +465,7 @@ struct Map_Str_Ptr native native void Remove(String key); } -struct MapIterator_Str_Ptr native +struct MapIterator_Str_Ptr native unsafe(internal) { native bool Init(Map_Str_Ptr other); native bool ReInit(); @@ -478,7 +478,7 @@ struct MapIterator_Str_Ptr native native void SetValue(voidptr value); } -struct Map_Str_Str native +struct Map_Str_Str native unsafe(internal) { native void Copy(Map_Str_Str other); native void Move(Map_Str_Str other); @@ -497,7 +497,7 @@ struct Map_Str_Str native native void Remove(String key); } -struct MapIterator_Str_Str native +struct MapIterator_Str_Str native unsafe(internal) { native bool Init(Map_Str_Str other); native bool ReInit(); diff --git a/wadsrc/static/zscript/engine/ui/menu/optionmenuitems.zs b/wadsrc/static/zscript/engine/ui/menu/optionmenuitems.zs index 9fc0d66ff..39430278a 100644 --- a/wadsrc/static/zscript/engine/ui/menu/optionmenuitems.zs +++ b/wadsrc/static/zscript/engine/ui/menu/optionmenuitems.zs @@ -184,7 +184,7 @@ class OptionMenuItemCommand : OptionMenuItemSubmenu return self; } - private native static void DoCommand(String cmd, bool unsafe); // This is very intentionally limited to this menu item to prevent abuse. + private native static void DoCommand(String cmd, bool is_unsafe); // This is very intentionally limited to this menu item to prevent abuse. override bool Activate() { diff --git a/wadsrc/static/zscript/visualthinker.zs b/wadsrc/static/zscript/visualthinker.zs index d5dc2253a..34c4643f5 100644 --- a/wadsrc/static/zscript/visualthinker.zs +++ b/wadsrc/static/zscript/visualthinker.zs @@ -60,4 +60,30 @@ Class VisualThinker : Thinker native } return p; } + + native int GetParticleType() const; + + void SetParticleType(EParticleStyle type = PT_DEFAULT) + { + switch(type) + { + Default: + VisualThinkerFlags = (VisualThinkerFlags & ~VTF_IsParticle) | VTF_ParticleDefault; + break; + case PT_SQUARE: + VisualThinkerFlags = (VisualThinkerFlags & ~VTF_IsParticle) | VTF_ParticleSquare; + break; + case PT_ROUND: + VisualThinkerFlags = (VisualThinkerFlags & ~VTF_IsParticle) | VTF_ParticleRound; + break; + case PT_SMOOTH: + VisualThinkerFlags = (VisualThinkerFlags & ~VTF_IsParticle) | VTF_ParticleSmooth; + break; + } + } + + void DisableParticle() + { + VisualThinkerFlags &= ~VTF_IsParticle; + } }