From 7debab7ff479d96a6046c613e14c958820f0a892 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Wed, 3 Aug 2022 14:13:42 +0200 Subject: [PATCH] - refined wall sprite check so that orthogonally aligned sprites are only aligned to orthogonal walls. Here even the slightest deviation can create problems. --- source/common/engine/sc_man.h | 10 +- source/common/rendering/gl/gl_framebuffer.cpp | 1 + .../common/rendering/gl_load/gl_interface.cpp | 14 ++- .../rendering/gles/gles_framebuffer.cpp | 1 + .../common/rendering/gles/gles_framebuffer.h | 1 + source/common/rendering/gles/gles_system.cpp | 5 + .../hwrenderer/data/hw_viewpointbuffer.cpp | 9 +- .../vulkan/system/vk_framebuffer.cpp | 1 + source/common/scripting/backend/codegen.cpp | 85 ++++++++++++++- source/common/scripting/backend/codegen.h | 4 +- source/common/scripting/core/types.cpp | 4 + source/common/scripting/core/types.h | 1 + .../common/scripting/frontend/zcc_compile.cpp | 100 ++++++++++++++++-- .../common/scripting/frontend/zcc_compile.h | 3 + .../common/scripting/interface/vmnatives.cpp | 2 +- source/core/rendering/scene/hw_walls.cpp | 31 +++--- source/core/version.h | 2 +- 17 files changed, 233 insertions(+), 41 deletions(-) diff --git a/source/common/engine/sc_man.h b/source/common/engine/sc_man.h index a39b8f5c36a..62b9f033434 100644 --- a/source/common/engine/sc_man.h +++ b/source/common/engine/sc_man.h @@ -12,19 +12,19 @@ struct VersionInfo uint16_t minor; uint32_t revision; - bool operator <=(const VersionInfo& o) const + constexpr bool operator <=(const VersionInfo& o) const { return o.major > this->major || (o.major == this->major && o.minor > this->minor) || (o.major == this->major && o.minor == this->minor && o.revision >= this->revision); } - bool operator >=(const VersionInfo& o) const + constexpr bool operator >=(const VersionInfo& o) const { return o.major < this->major || (o.major == this->major && o.minor < this->minor) || (o.major == this->major && o.minor == this->minor && o.revision <= this->revision); } - bool operator > (const VersionInfo& o) const + constexpr bool operator > (const VersionInfo& o) const { return o.major < this->major || (o.major == this->major && o.minor < this->minor) || (o.major == this->major && o.minor == this->minor && o.revision < this->revision); } - bool operator < (const VersionInfo& o) const + constexpr bool operator < (const VersionInfo& o) const { return o.major > this->major || (o.major == this->major && o.minor > this->minor) || (o.major == this->major && o.minor == this->minor && o.revision > this->revision); } @@ -32,7 +32,7 @@ struct VersionInfo }; // Cannot be a constructor because Lemon would puke on it. -inline VersionInfo MakeVersion(unsigned int ma, unsigned int mi, unsigned int re = 0) +constexpr VersionInfo MakeVersion(unsigned int ma, unsigned int mi, unsigned int re = 0) { return{ (uint16_t)ma, (uint16_t)mi, (uint32_t)re }; } diff --git a/source/common/rendering/gl/gl_framebuffer.cpp b/source/common/rendering/gl/gl_framebuffer.cpp index 52cf004d032..3913a21e131 100644 --- a/source/common/rendering/gl/gl_framebuffer.cpp +++ b/source/common/rendering/gl/gl_framebuffer.cpp @@ -484,6 +484,7 @@ void OpenGLFrameBuffer::SetSaveBuffers(bool yes) void OpenGLFrameBuffer::BeginFrame() { SetViewportRects(nullptr); + mViewpoints->Clear(); if (GLRenderer != nullptr) GLRenderer->BeginFrame(); } diff --git a/source/common/rendering/gl_load/gl_interface.cpp b/source/common/rendering/gl_load/gl_interface.cpp index 344a3d4fac5..ea011819bc8 100644 --- a/source/common/rendering/gl_load/gl_interface.cpp +++ b/source/common/rendering/gl_load/gl_interface.cpp @@ -44,7 +44,8 @@ static TArray m_Extensions; RenderContext gl; -static double realglversion; // this is public so the statistics code can access it. +static double realglversion; +static bool bindless; //========================================================================== // @@ -156,7 +157,7 @@ void gl_LoadExtensions() #ifdef _WIN32 if (strstr(gl.vendorstring, "ATI Tech")) { - gl.flags |= RFL_NO_CLIP_PLANES; // gl_ClipDistance is horribly broken on ATI GL3 drivers for Windows. (TBD: Relegate to vintage build? Maybe after the next survey.) + gl.flags |= RFL_NO_CLIP_PLANES; // gl_ClipDistance is horribly broken on ATI GL3 drivers for Windows. } #endif gl.glslversion = 3.31f; // Force GLSL down to 3.3. @@ -201,6 +202,8 @@ void gl_LoadExtensions() glGetIntegerv(GL_MAX_TEXTURE_SIZE, &gl.max_texturesize); glPixelStorei(GL_UNPACK_ALIGNMENT, 1); + + bindless = CheckExtension("GL_ARB_bindless_texture"); } //========================================================================== @@ -247,9 +250,14 @@ void gl_PrintStartupLog() } } +void setGlVersion(double glv) +{ + realglversion = glv; +} + std::pair gl_getInfo() { // gl_ARB_bindless_texture is the closest we can get to determine Vulkan support from OpenGL. // This isn't foolproof because Intel doesn't support it but for NVidia and AMD support of this extension means Vulkan support. - return std::make_pair(realglversion, CheckExtension("GL_ARB_bindless_texture")); + return std::make_pair(realglversion, bindless); } diff --git a/source/common/rendering/gles/gles_framebuffer.cpp b/source/common/rendering/gles/gles_framebuffer.cpp index c858e969f93..db2a69902b4 100644 --- a/source/common/rendering/gles/gles_framebuffer.cpp +++ b/source/common/rendering/gles/gles_framebuffer.cpp @@ -369,6 +369,7 @@ void OpenGLFrameBuffer::WaitForCommands(bool finish) void OpenGLFrameBuffer::BeginFrame() { SetViewportRects(nullptr); + mViewpoints->Clear(); if (GLRenderer != nullptr) GLRenderer->BeginFrame(); } diff --git a/source/common/rendering/gles/gles_framebuffer.h b/source/common/rendering/gles/gles_framebuffer.h index d7c7587f809..3cf32f179d5 100644 --- a/source/common/rendering/gles/gles_framebuffer.h +++ b/source/common/rendering/gles/gles_framebuffer.h @@ -22,6 +22,7 @@ class OpenGLFrameBuffer : public SystemGLFrameBuffer explicit OpenGLFrameBuffer() {} OpenGLFrameBuffer(void *hMonitor, bool fullscreen) ; ~OpenGLFrameBuffer(); + int Backend() override { return 0; } void InitializeState() override; void Update() override; diff --git a/source/common/rendering/gles/gles_system.cpp b/source/common/rendering/gles/gles_system.cpp index 51f8ee6a204..edaa86afafa 100644 --- a/source/common/rendering/gles/gles_system.cpp +++ b/source/common/rendering/gles/gles_system.cpp @@ -9,6 +9,7 @@ CVAR(Bool, gles_use_mapped_buffer, false, 0); CVAR(Bool, gles_force_glsl_v100, false, 0); CVAR(Int, gles_max_lights_per_surface, 32, 0); EXTERN_CVAR(Bool, gl_customshader); +void setGlVersion(double glv); #if USE_GLES2 @@ -191,5 +192,9 @@ namespace OpenGLESRenderer #endif gles.numlightvectors = (gles.maxlights * LIGHT_VEC4_NUM); + + const char* glversion = (const char*)glGetString(GL_VERSION); + setGlVersion( strtod(glversion, NULL)); + } } diff --git a/source/common/rendering/hwrenderer/data/hw_viewpointbuffer.cpp b/source/common/rendering/hwrenderer/data/hw_viewpointbuffer.cpp index 90001b7b976..f60cda5e102 100644 --- a/source/common/rendering/hwrenderer/data/hw_viewpointbuffer.cpp +++ b/source/common/rendering/hwrenderer/data/hw_viewpointbuffer.cpp @@ -117,11 +117,16 @@ int HWViewpointBuffer::SetViewpoint(FRenderState &di, HWViewpointUniforms *vp) void HWViewpointBuffer::Clear() { + bool needNewPipeline = mUploadIndex > 0; // Clear might be called multiple times before any actual rendering + mUploadIndex = 0; mClipPlaneInfo.Clear(); - mPipelinePos++; - mPipelinePos %= mPipelineNbr; + if (needNewPipeline) + { + mPipelinePos++; + mPipelinePos %= mPipelineNbr; + } mBuffer = mBufferPipeline[mPipelinePos]; } diff --git a/source/common/rendering/vulkan/system/vk_framebuffer.cpp b/source/common/rendering/vulkan/system/vk_framebuffer.cpp index 55ce448fdc6..b93e5978495 100644 --- a/source/common/rendering/vulkan/system/vk_framebuffer.cpp +++ b/source/common/rendering/vulkan/system/vk_framebuffer.cpp @@ -419,6 +419,7 @@ TArray VulkanFrameBuffer::GetScreenshotBuffer(int &pitch, ESSType &colo void VulkanFrameBuffer::BeginFrame() { SetViewportRects(nullptr); + mViewpoints->Clear(); mCommands->BeginFrame(); mTextureManager->BeginFrame(); mScreenBuffers->BeginFrame(screen->mScreenViewport.width, screen->mScreenViewport.height, screen->mSceneViewport.width, screen->mSceneViewport.height); diff --git a/source/common/scripting/backend/codegen.cpp b/source/common/scripting/backend/codegen.cpp index 175b6206ed8..96ceef6c52c 100644 --- a/source/common/scripting/backend/codegen.cpp +++ b/source/common/scripting/backend/codegen.cpp @@ -104,8 +104,8 @@ FCompileContext::FCompileContext(PNamespace *cg, PFunction *fnc, PPrototype *ret if (fnc != nullptr) Class = fnc->OwningClass; } -FCompileContext::FCompileContext(PNamespace *cg, PContainerType *cls, bool fromdecorate) - : ReturnProto(nullptr), Function(nullptr), Class(cls), FromDecorate(fromdecorate), StateIndex(-1), StateCount(0), Lump(-1), CurGlobals(cg) +FCompileContext::FCompileContext(PNamespace *cg, PContainerType *cls, bool fromdecorate, const VersionInfo& info) + : ReturnProto(nullptr), Function(nullptr), Class(cls), FromDecorate(fromdecorate), StateIndex(-1), StateCount(0), Lump(-1), CurGlobals(cg), Version(info) { } @@ -2678,13 +2678,26 @@ FxBinary::~FxBinary() // //========================================================================== -bool FxBinary::Promote(FCompileContext &ctx, bool forceint) +bool FxBinary::Promote(FCompileContext &ctx, bool forceint, bool shiftop) { // math operations of unsigned ints results in an unsigned int. (16 and 8 bit values never get here, they get promoted to regular ints elsewhere already.) if (left->ValueType == TypeUInt32 && right->ValueType == TypeUInt32) { ValueType = TypeUInt32; } + // If one side is an unsigned 32-bit int and the other side is a signed 32-bit int, the signed side is implicitly converted to unsigned, + else if (!ctx.FromDecorate && left->ValueType == TypeUInt32 && right->ValueType == TypeSInt32 && !shiftop && ctx.Version >= MakeVersion(4, 9, 0)) + { + right = new FxIntCast(right, false, false, true); + right = right->Resolve(ctx); + ValueType = TypeUInt32; + } + else if (!ctx.FromDecorate && left->ValueType == TypeSInt32 && right->ValueType == TypeUInt32 && !shiftop && ctx.Version >= MakeVersion(4, 9, 0)) + { + left = new FxIntCast(left, false, false, true); + left = left->Resolve(ctx); + ValueType = TypeUInt32; + } else if (left->IsInteger() && right->IsInteger()) { ValueType = TypeSInt32; // Addition and subtraction forces all integer-derived types to signed int. @@ -2728,6 +2741,15 @@ bool FxBinary::Promote(FCompileContext &ctx, bool forceint) delete this; return false; } + + // shift operators are different: The left operand defines the type and the right operand must always be made unsigned + if (shiftop) + { + ValueType = left->ValueType == TypeUInt32 ? TypeUInt32 : TypeSInt32; + right = new FxIntCast(right, false, false, true); + right = right->Resolve(ctx); + } + return true; } @@ -3324,6 +3346,59 @@ FxExpression *FxCompareRel::Resolve(FCompileContext& ctx) } else if (left->IsNumeric() && right->IsNumeric()) { + if (left->IsInteger() && right->IsInteger()) + { + if (ctx.Version >= MakeVersion(4, 9, 0)) + { + // We need to do more checks here to catch problem cases. + if (left->ValueType == TypeUInt32 && right->ValueType == TypeSInt32) + { + if (left->isConstant() && !right->isConstant()) + { + auto val = static_cast(left)->GetValue().GetUInt(); + if (val > INT_MAX) + { + ScriptPosition.Message(MSG_WARNING, "Comparison of signed value with out of range unsigned constant"); + } + } + else if (right->isConstant() && !left->isConstant()) + { + auto val = static_cast(right)->GetValue().GetInt(); + if (val < 0) + { + ScriptPosition.Message(MSG_WARNING, "Comparison of unsigned value with negative constant"); + } + } + else if (!left->isConstant() && !right->isConstant()) + { + ScriptPosition.Message(MSG_WARNING, "Comparison between signed and unsigned value"); + } + } + else if (left->ValueType == TypeSInt32 && right->ValueType == TypeUInt32) + { + if (left->isConstant() && !right->isConstant()) + { + auto val = static_cast(left)->GetValue().GetInt(); + if (val < 0) + { + ScriptPosition.Message(MSG_WARNING, "Comparison of unsigned value with negative constant"); + } + } + else if (right->isConstant() && !left->isConstant()) + { + auto val = static_cast(right)->GetValue().GetUInt(); + if (val > INT_MAX) + { + ScriptPosition.Message(MSG_WARNING, "Comparison of signed value with out of range unsigned constant"); + } + } + else if (!left->isConstant() && !right->isConstant()) + { + ScriptPosition.Message(MSG_WARNING, "Comparison between signed and unsigned value"); + } + } + } + } Promote(ctx); } else @@ -3929,7 +4004,7 @@ FxExpression *FxShift::Resolve(FCompileContext& ctx) if (left->IsNumeric() && right->IsNumeric()) { - if (!Promote(ctx, true)) return nullptr; + if (!Promote(ctx, true, true)) return nullptr; if ((left->ValueType == TypeUInt32 && ctx.Version >= MakeVersion(3, 7)) && Operator == TK_RShift) Operator = TK_URShift; } else @@ -8233,7 +8308,7 @@ FxExpression *FxMemberFunctionCall::Resolve(FCompileContext& ctx) member->membervar = newfield; Self = nullptr; delete this; - member->ValueType = TypeUInt32; + member->ValueType = TypeSInt32; return member; } else diff --git a/source/common/scripting/backend/codegen.h b/source/common/scripting/backend/codegen.h index 0bf71e5a5cb..2e361770024 100644 --- a/source/common/scripting/backend/codegen.h +++ b/source/common/scripting/backend/codegen.h @@ -93,7 +93,7 @@ struct FCompileContext FString VersionString; FCompileContext(PNamespace *spc, PFunction *func, PPrototype *ret, bool fromdecorate, int stateindex, int statecount, int lump, const VersionInfo &ver); - FCompileContext(PNamespace *spc, PContainerType *cls, bool fromdecorate); // only to be used to resolve constants! + FCompileContext(PNamespace *spc, PContainerType *cls, bool fromdecorate, const VersionInfo& ver); // only to be used to resolve constants! PSymbol *FindInClass(FName identifier, PSymbolTable *&symt); PSymbol *FindInSelfClass(FName identifier, PSymbolTable *&symt); @@ -910,7 +910,7 @@ class FxBinary : public FxExpression FxBinary(int, FxExpression*, FxExpression*); ~FxBinary(); - bool Promote(FCompileContext &ctx, bool forceint = false); + bool Promote(FCompileContext &ctx, bool forceint = false, bool shiftop = false); }; //========================================================================== diff --git a/source/common/scripting/core/types.cpp b/source/common/scripting/core/types.cpp index 01f83ba8910..fb844c62a68 100644 --- a/source/common/scripting/core/types.cpp +++ b/source/common/scripting/core/types.cpp @@ -334,6 +334,7 @@ void PType::StaticInit() TypeVector2->moveOp = OP_MOVEV2; TypeVector2->RegType = REGT_FLOAT; TypeVector2->RegCount = 2; + TypeVector2->isOrdered = true; TypeVector3 = new PStruct(NAME_Vector3, nullptr); TypeVector3->AddField(NAME_X, TypeFloat64); @@ -347,6 +348,7 @@ void PType::StaticInit() TypeVector3->moveOp = OP_MOVEV3; TypeVector3->RegType = REGT_FLOAT; TypeVector3->RegCount = 3; + TypeVector3->isOrdered = true; TypeFVector2 = new PStruct(NAME_FVector2, nullptr); @@ -358,6 +360,7 @@ void PType::StaticInit() TypeFVector2->moveOp = OP_MOVEV2; TypeFVector2->RegType = REGT_FLOAT; TypeFVector2->RegCount = 2; + TypeFVector2->isOrdered = true; TypeFVector3 = new PStruct(NAME_FVector3, nullptr); TypeFVector3->AddField(NAME_X, TypeFloat32); @@ -371,6 +374,7 @@ void PType::StaticInit() TypeFVector3->moveOp = OP_MOVEV3; TypeFVector3->RegType = REGT_FLOAT; TypeFVector3->RegCount = 3; + TypeFVector3->isOrdered = true; Namespaces.GlobalNamespace->Symbols.AddSymbol(Create(NAME_sByte, TypeSInt8)); Namespaces.GlobalNamespace->Symbols.AddSymbol(Create(NAME_Byte, TypeUInt8)); diff --git a/source/common/scripting/core/types.h b/source/common/scripting/core/types.h index e8d07e91a7c..959d66bdacd 100644 --- a/source/common/scripting/core/types.h +++ b/source/common/scripting/core/types.h @@ -537,6 +537,7 @@ class PStruct : public PContainerType PStruct(FName name, PTypeBase *outer, bool isnative = false); bool isNative; + bool isOrdered = false; // Some internal structs require explicit construction and destruction of fields the VM cannot handle directly so use these two functions for it. VMFunction *mConstructor = nullptr; VMFunction *mDestructor = nullptr; diff --git a/source/common/scripting/frontend/zcc_compile.cpp b/source/common/scripting/frontend/zcc_compile.cpp index 9e3daeaef0f..16940339a46 100644 --- a/source/common/scripting/frontend/zcc_compile.cpp +++ b/source/common/scripting/frontend/zcc_compile.cpp @@ -68,7 +68,7 @@ const char * ZCCCompiler::GetStringConst(FxExpression *ex, FCompileContext &ctx) int ZCCCompiler::IntConstFromNode(ZCC_TreeNode *node, PContainerType *cls) { - FCompileContext ctx(OutNamespace, cls, false); + FCompileContext ctx(OutNamespace, cls, false, mVersion); FxExpression *ex = new FxIntCast(ConvertNode(node), false); ex = ex->Resolve(ctx); if (ex == nullptr) return 0; @@ -82,7 +82,7 @@ int ZCCCompiler::IntConstFromNode(ZCC_TreeNode *node, PContainerType *cls) FString ZCCCompiler::StringConstFromNode(ZCC_TreeNode *node, PContainerType *cls) { - FCompileContext ctx(OutNamespace, cls, false); + FCompileContext ctx(OutNamespace, cls, false, mVersion); FxExpression *ex = new FxStringCast(ConvertNode(node)); ex = ex->Resolve(ctx); if (ex == nullptr) return ""; @@ -1144,7 +1144,7 @@ void ZCCCompiler::AddConstant(ZCC_ConstantWork &constant) bool ZCCCompiler::CompileConstant(ZCC_ConstantWork *work) { - FCompileContext ctx(OutNamespace, work->cls, false); + FCompileContext ctx(OutNamespace, work->cls, false, mVersion); FxExpression *exp = ConvertNode(work->node->Value); try { @@ -1185,7 +1185,7 @@ void ZCCCompiler::CompileArrays(ZCC_StructWork *work) ConvertNodeList(values, sas->Values); bool fail = false; - FCompileContext ctx(OutNamespace, work->Type(), false); + FCompileContext ctx(OutNamespace, work->Type(), false, mVersion); char *destmem = (char *)ClassDataAllocator.Alloc(values.Size() * ztype->Align); memset(destmem, 0, values.Size() * ztype->Align); @@ -1325,7 +1325,7 @@ void ZCCCompiler::CompileAllFields() { // Create copies of the arrays which can be altered auto Classes = this->Classes; - auto Structs = this->Structs; + auto Structs = OrderStructs(); TMap HasNativeChildren; // first step: Look for native classes with native children. @@ -1612,6 +1612,83 @@ bool ZCCCompiler::CompileFields(PContainerType *type, TArray ZCCCompiler::OrderStructs() +{ + TArray new_order; + + for (auto struct_def : Structs) + { + if (std::find(new_order.begin(), new_order.end(), struct_def) != new_order.end()) + { + continue; + } + AddStruct(new_order, struct_def); + } + return new_order; +} + +//========================================================================== +// +// ZCCCompiler :: AddStruct +// +// Adds a struct to the Structs array, preceded by all its dependant structs +// +//========================================================================== + +void ZCCCompiler::AddStruct(TArray &new_order, ZCC_StructWork *my_def) +{ + PStruct *my_type = static_cast(my_def->Type()); + if (my_type) + { + if (my_type->isOrdered) + { + return; + } + my_type->isOrdered = true; + } + + // Find all struct fields and add them before this one + for (const auto field : my_def->Fields) + { + PType *fieldtype = DetermineType(my_type, field, field->Names->Name, field->Type, true, true); + if (fieldtype->isStruct() && !static_cast(fieldtype)->isOrdered) + { + AddStruct(new_order, StructTypeToWork(static_cast(fieldtype))); + } + } + new_order.Push(my_def); +} + +//========================================================================== +// +// ZCCCompiler :: StructTypeToWork +// +// Find the ZCC_StructWork that corresponds to a PStruct +// +//========================================================================== + +ZCC_StructWork *ZCCCompiler::StructTypeToWork(const PStruct *type) const +{ + assert(type->isStruct()); + for (auto &def : Structs) + { + if (def->Type() == type) + { + return def; + } + } + assert(false && "Struct not found"); + return nullptr; +} + //========================================================================== // // ZCCCompiler :: FieldFlagsToString @@ -1937,7 +2014,7 @@ PType *ZCCCompiler::ResolveArraySize(PType *baseType, ZCC_Expression *arraysize, indices = std::move(fixedIndices); } - FCompileContext ctx(OutNamespace, cls, false); + FCompileContext ctx(OutNamespace, cls, false, mVersion); for (auto index : indices) { // There is no float->int casting here. @@ -2270,7 +2347,7 @@ void ZCCCompiler::CompileFunction(ZCC_StructWork *c, ZCC_FuncDeclarator *f, bool FxExpression *x = new FxTypeCast(ConvertNode(p->Default), type, false); - FCompileContext ctx(OutNamespace, c->Type(), false); + FCompileContext ctx(OutNamespace, c->Type(), false, mVersion); x = x->Resolve(ctx); if (x != nullptr) @@ -2731,7 +2808,14 @@ FxExpression *ZCCCompiler::ConvertNode(ZCC_TreeNode *ast, bool substitute) } else if (cnst->Type->isInt()) { - return new FxConstant(cnst->IntVal, *ast); + if (cnst->Type == TypeUInt32) + { + return new FxConstant((unsigned)cnst->IntVal, *ast); + } + else + { + return new FxConstant(cnst->IntVal, *ast); + } } else if (cnst->Type == TypeBool) { diff --git a/source/common/scripting/frontend/zcc_compile.h b/source/common/scripting/frontend/zcc_compile.h index ca1beb3f25c..adfadaff150 100644 --- a/source/common/scripting/frontend/zcc_compile.h +++ b/source/common/scripting/frontend/zcc_compile.h @@ -135,6 +135,9 @@ class ZCCCompiler 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, PSymbolTable *sym, bool nativetype); + TArray OrderStructs(); + void AddStruct(TArray &new_order, ZCC_StructWork *struct_def); + ZCC_StructWork *StructTypeToWork(const PStruct *type) const; void CompileFunction(ZCC_StructWork *c, ZCC_FuncDeclarator *f, bool forclass); diff --git a/source/common/scripting/interface/vmnatives.cpp b/source/common/scripting/interface/vmnatives.cpp index bc7d08db7f1..5a7d25cce76 100644 --- a/source/common/scripting/interface/vmnatives.cpp +++ b/source/common/scripting/interface/vmnatives.cpp @@ -998,7 +998,7 @@ DEFINE_ACTION_FUNCTION(DOptionMenuItemCommand, DoCommand) } UnsafeExecutionScope scope(unsafe); - C_DoCommand(cmd); + AddCommandString(cmd); return 0; } diff --git a/source/core/rendering/scene/hw_walls.cpp b/source/core/rendering/scene/hw_walls.cpp index 8038636ab44..a4144a36db3 100644 --- a/source/core/rendering/scene/hw_walls.cpp +++ b/source/core/rendering/scene/hw_walls.cpp @@ -70,24 +70,27 @@ static walltype* IsOnWall(tspritetype* tspr, int height, DVector2& outpos) // angle of the sprite must either be the wall's normal or the negative wall's normal to be aligned. if (deltaang >= 512 - maxangdelta && deltaang <= 512 + maxangdelta) { - // orthogonal lines do not check the actual position so that certain off-sector sprites get handled properly. - // In Wanton Destruction's airplane level there's such a sprite assigned to the wrong sector. - if (d.X == 0) + if (!((tspr->ang) & 510)) { - double newdist = fabs(tx - wal.pos.X); - if (newdist < maxorthdist) + // orthogonal lines do not check the actual position so that certain off-sector sprites get handled properly. + // In Wanton Destruction's airplane level there's such a sprite assigned to the wrong sector. + if (d.X == 0) { - maxorthdist = newdist; - best = &wal; + double newdist = fabs(tx - wal.pos.X); + if (newdist < maxorthdist) + { + maxorthdist = newdist; + best = &wal; + } } - } - else if (d.Y == 0) - { - double newdist = fabs(ty - wal.pos.Y); - if (newdist < maxorthdist) + else if (d.Y == 0) { - maxorthdist = newdist; - best = &wal; + double newdist = fabs(ty - wal.pos.Y); + if (newdist < maxorthdist) + { + maxorthdist = newdist; + best = &wal; + } } } else diff --git a/source/core/version.h b/source/core/version.h index 9e21579cf2d..15baa3547f7 100644 --- a/source/core/version.h +++ b/source/core/version.h @@ -49,7 +49,7 @@ const char *GetVersionString(); #define RC_PRODUCTVERSION2 VERSIONSTR // These are for content versioning. #define VER_MAJOR 4 -#define VER_MINOR 7 +#define VER_MINOR 9 #define VER_REVISION 0 #define ENG_MAJOR 1