Merge remote-tracking branch 'gzdoom/master' into newmaster

This commit is contained in:
Major Cooke 2020-04-07 09:21:57 -05:00
commit d29b514985
33 changed files with 450 additions and 544 deletions

View file

@ -1048,7 +1048,6 @@ set (PCH_SOURCES
gamedata/textures/formats/tgatexture.cpp
gamedata/textures/formats/stbtexture.cpp
gamedata/textures/hires/hqresize.cpp
gamedata/textures/hires/hirestex.cpp
gamedata/fonts/singlelumpfont.cpp
gamedata/fonts/singlepicfont.cpp
gamedata/fonts/specialfont.cpp

View file

@ -174,6 +174,26 @@ extern bool insave;
extern TDeletingArray<FLightDefaults *> LightDefaults;
CUSTOM_CVAR(Float, i_timescale, 1.0f, CVAR_NOINITCALL)
{
if (netgame)
{
Printf("Time scale cannot be changed in net games.\n");
self = 1.0f;
}
else if (self >= 0.05f)
{
I_FreezeTime(true);
TimeScale = self;
I_FreezeTime(false);
}
else
{
Printf("Time scale must be at least 0.05!\n");
}
}
// PUBLIC DATA DEFINITIONS -------------------------------------------------
CUSTOM_CVAR (Int, fraglimit, 0, CVAR_SERVERINFO)
@ -2883,6 +2903,7 @@ static int D_DoomMain_Internal (void)
int D_DoomMain()
{
int ret = 0;
GameTicRate = TICRATE;
try
{
ret = D_DoomMain_Internal();

View file

@ -315,6 +315,7 @@ CCMD (slot)
}
// [Nash] Option to display the name of the weapon being switched to.
if (players[consoleplayer].playerstate != PST_LIVE) return;
if (SendItemUse != players[consoleplayer].ReadyWeapon && (displaynametags & 2) && StatusBar && SmallFont && SendItemUse)
{
StatusBar->AttachMessage(Create<DHUDMessageFadeOut>(nullptr, SendItemUse->GetTag(),
@ -363,6 +364,7 @@ CCMD (weapnext)
}
// [BC] Option to display the name of the weapon being cycled to.
if (players[consoleplayer].playerstate != PST_LIVE) return;
if ((displaynametags & 2) && StatusBar && SmallFont && SendItemUse)
{
StatusBar->AttachMessage(Create<DHUDMessageFadeOut>(nullptr, SendItemUse->GetTag(),
@ -389,6 +391,7 @@ CCMD (weapprev)
}
// [BC] Option to display the name of the weapon being cycled to.
if (players[consoleplayer].playerstate != PST_LIVE) return;
if ((displaynametags & 2) && StatusBar && SmallFont && SendItemUse)
{
StatusBar->AttachMessage(Create<DHUDMessageFadeOut>(nullptr, SendItemUse->GetTag(),

View file

@ -1,414 +0,0 @@
//
//---------------------------------------------------------------------------
//
// Copyright(C) 2005-2016 Christoph Oelckers
// All rights reserved.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with this program. If not, see http://www.gnu.org/licenses/
//
//--------------------------------------------------------------------------
//
/*
** external hires texture management (i.e. Doomsday style texture packs)
**
*/
#ifdef _MSC_VER
#include <io.h>
#else
#include <unistd.h>
#endif
#include "w_wad.h"
#include "m_png.h"
#include "sbar.h"
#include "gi.h"
#include "cmdlib.h"
#include "bitmap.h"
#include "image.h"
#ifndef _WIN32
#define _access(a,b) access(a,b)
#endif
static int Doom2Wad = -1;
// quick'n dirty hack. Should be enough here...
static void SetDoom2Wad()
{
if (Doom2Wad == -1)
{
FString iwad = Wads.GetWadFullName(Wads.GetIwadNum());
iwad.ToLower();
if (iwad.IndexOf("plutonia") >= 0) Doom2Wad = 1;
else if (iwad.IndexOf("tnt") >= 0) Doom2Wad = 2;
else Doom2Wad = 0;
}
}
//==========================================================================
//
// Checks for the presence of a hires texture replacement in a Doomsday style PK3
//
//==========================================================================
int FTexture::CheckDDPK3()
{
static const char * doom1texpath[]= {
"data/jdoom/textures/doom/%s.%s", "data/jdoom/textures/doom-ult/%s.%s", "data/jdoom/textures/doom1/%s.%s", "data/jdoom/textures/%s.%s", NULL };
static const char * doom2texpath[]= {
"data/jdoom/textures/doom2/%s.%s", "data/jdoom/textures/%s.%s", NULL };
static const char * pluttexpath[]= {
"data/jdoom/textures/doom2-plut/%s.%s", "data/jdoom/textures/plutonia/%s.%s", "data/jdoom/textures/%s.%s", NULL };
static const char * tnttexpath[]= {
"data/jdoom/textures/doom2-tnt/%s.%s", "data/jdoom/textures/tnt/%s.%s", "data/jdoom/textures/%s.%s", NULL };
static const char * heretictexpath[]= {
"data/jheretic/textures/%s.%s", NULL };
static const char * hexentexpath[]= {
"data/jhexen/textures/%s.%s", NULL };
static const char * strifetexpath[]= {
"data/jstrife/textures/%s.%s", NULL };
static const char * chextexpath[]= {
"data/jchex/textures/%s.%s", NULL };
static const char * doomflatpath[]= {
"data/jdoom/flats/%s.%s", NULL };
static const char * hereticflatpath[]= {
"data/jheretic/flats/%s.%s", NULL };
static const char * hexenflatpath[]= {
"data/jhexen/flats/%s.%s", NULL };
static const char * strifeflatpath[]= {
"data/jstrife/flats/%s.%s", NULL };
static const char * chexflatpath[]= {
"data/jchex/flats/%s.%s", NULL };
FString checkName;
const char ** checklist;
ETextureType useType=UseType;
if (useType==ETextureType::SkinSprite || useType==ETextureType::Decal || useType==ETextureType::FontChar)
{
return -3;
}
bool ispatch = (useType==ETextureType::MiscPatch || useType==ETextureType::Sprite) ;
// for patches this doesn't work yet
if (ispatch) return -3;
if (!gameinfo.ConfigName.CompareNoCase("Doom"))
{
if (!(gameinfo.flags & GI_MAPxx))
{
checklist = useType==ETextureType::Flat? doomflatpath : doom1texpath;
}
else
{
SetDoom2Wad();
if (Doom2Wad == 1)
checklist = useType==ETextureType::Flat? doomflatpath : pluttexpath;
else if (Doom2Wad == 2)
checklist = useType==ETextureType::Flat? doomflatpath : tnttexpath;
else
checklist = useType==ETextureType::Flat? doomflatpath : doom2texpath;
}
}
else if (!gameinfo.ConfigName.CompareNoCase("Heretic"))
{
checklist = useType==ETextureType::Flat? hereticflatpath : heretictexpath;
}
else if (!gameinfo.ConfigName.CompareNoCase("Hexen"))
{
checklist = useType==ETextureType::Flat? hexenflatpath : hexentexpath;
}
else if (!gameinfo.ConfigName.CompareNoCase("Strife"))
{
checklist = useType==ETextureType::Flat? strifeflatpath : strifetexpath;
}
else if (!gameinfo.ConfigName.CompareNoCase("Chex"))
{
checklist = useType==ETextureType::Flat? chexflatpath : chextexpath;
}
else
return -3;
while (*checklist)
{
static const char * extensions[] = { "PNG", "JPG", "TGA", "PCX", NULL };
for (const char ** extp=extensions; *extp; extp++)
{
checkName.Format(*checklist, Name.GetChars(), *extp);
int lumpnum = Wads.CheckNumForFullName(checkName);
if (lumpnum >= 0) return lumpnum;
}
checklist++;
}
return -3;
}
//==========================================================================
//
// Checks for the presence of a hires texture replacement
//
//==========================================================================
int FTexture::CheckExternalFile(bool & hascolorkey)
{
static const char * doom1texpath[]= {
"%stextures/doom/doom1/%s.%s", "%stextures/doom/doom1/%s-ck.%s",
"%stextures/doom/%s.%s", "%stextures/doom/%s-ck.%s", "%stextures/%s.%s", "%stextures/%s-ck.%s", NULL
};
static const char * doom2texpath[]= {
"%stextures/doom/doom2/%s.%s", "%stextures/doom/doom2/%s-ck.%s",
"%stextures/doom/%s.%s", "%stextures/doom/%s-ck.%s", "%stextures/%s.%s", "%stextures/%s-ck.%s", NULL
};
static const char * pluttexpath[]= {
"%stextures/doom/plut/%s.%s", "%stextures/doom/plut/%s-ck.%s",
"%stextures/doom/doom2-plut/%s.%s", "%stextures/doom/doom2-plut/%s-ck.%s",
"%stextures/doom/%s.%s", "%stextures/doom/%s-ck.%s", "%stextures/%s.%s", "%stextures/%s-ck.%s", NULL
};
static const char * tnttexpath[]= {
"%stextures/doom/tnt/%s.%s", "%stextures/doom/tnt/%s-ck.%s",
"%stextures/doom/doom2-tnt/%s.%s", "%stextures/doom/doom2-tnt/%s-ck.%s",
"%stextures/doom/%s.%s", "%stextures/doom/%s-ck.%s", "%stextures/%s.%s", "%stextures/%s-ck.%s", NULL
};
static const char * heretictexpath[]= {
"%stextures/heretic/%s.%s", "%stextures/heretic/%s-ck.%s", "%stextures/%s.%s", "%stextures/%s-ck.%s", NULL
};
static const char * hexentexpath[]= {
"%stextures/hexen/%s.%s", "%stextures/hexen/%s-ck.%s", "%stextures/%s.%s", "%stextures/%s-ck.%s", NULL
};
static const char * strifetexpath[]= {
"%stextures/strife/%s.%s", "%stextures/strife/%s-ck.%s", "%stextures/%s.%s", "%stextures/%s-ck.%s", NULL
};
static const char * chextexpath[]= {
"%stextures/chex/%s.%s", "%stextures/chex/%s-ck.%s", "%stextures/%s.%s", "%stextures/%s-ck.%s", NULL
};
static const char * doom1flatpath[]= {
"%sflats/doom/doom1/%s.%s", "%stextures/doom/doom1/flat-%s.%s",
"%sflats/doom/%s.%s", "%stextures/doom/flat-%s.%s", "%sflats/%s.%s", "%stextures/flat-%s.%s", NULL
};
static const char * doom2flatpath[]= {
"%sflats/doom/doom2/%s.%s", "%stextures/doom/doom2/flat-%s.%s",
"%sflats/doom/%s.%s", "%stextures/doom/flat-%s.%s", "%sflats/%s.%s", "%stextures/flat-%s.%s", NULL
};
static const char * plutflatpath[]= {
"%sflats/doom/plut/%s.%s", "%stextures/doom/plut/flat-%s.%s",
"%sflats/doom/doom2-plut/%s.%s", "%stextures/doom/doom2-plut/flat-%s.%s",
"%sflats/doom/%s.%s", "%stextures/doom/flat-%s.%s", "%sflats/%s.%s", "%stextures/flat-%s.%s", NULL
};
static const char * tntflatpath[]= {
"%sflats/doom/tnt/%s.%s", "%stextures/doom/tnt/flat-%s.%s",
"%sflats/doom/doom2-tnt/%s.%s", "%stextures/doom/doom2-tnt/flat-%s.%s",
"%sflats/doom/%s.%s", "%stextures/doom/flat-%s.%s", "%sflats/%s.%s", "%stextures/flat-%s.%s", NULL
};
static const char * hereticflatpath[]= {
"%sflats/heretic/%s.%s", "%stextures/heretic/flat-%s.%s", "%sflats/%s.%s", "%stextures/flat-%s.%s", NULL
};
static const char * hexenflatpath[]= {
"%sflats/hexen/%s.%s", "%stextures/hexen/flat-%s.%s", "%sflats/%s.%s", "%stextures/flat-%s.%s", NULL
};
static const char * strifeflatpath[]= {
"%sflats/strife/%s.%s", "%stextures/strife/flat-%s.%s", "%sflats/%s.%s", "%stextures/flat-%s.%s", NULL
};
static const char * chexflatpath[]= {
"%sflats/chex/%s.%s", "%stextures/chex/flat-%s.%s", "%sflats/%s.%s", "%stextures/flat-%s.%s", NULL
};
static const char * doom1patchpath[]= {
"%spatches/doom/doom1/%s.%s", "%spatches/doom/%s.%s", "%spatches/%s.%s", NULL
};
static const char * doom2patchpath[]= {
"%spatches/doom/doom2/%s.%s", "%spatches/doom/%s.%s", "%spatches/%s.%s", NULL
};
static const char * plutpatchpath[]= {
"%spatches/doom/plut/%s.%s", "%spatches/doom/%s.%s", "%spatches/%s.%s", NULL
};
static const char * tntpatchpath[]= {
"%spatches/doom/tnt/%s.%s", "%spatches/doom/%s.%s", "%spatches/%s.%s", NULL
};
static const char * hereticpatchpath[]= {
"%spatches/heretic/%s.%s", "%spatches/%s.%s", NULL
};
static const char * hexenpatchpath[]= {
"%spatches/hexen/%s.%s", "%spatches/%s.%s", NULL
};
static const char * strifepatchpath[]= {
"%spatches/strife/%s.%s", "%spatches/%s.%s", NULL
};
static const char * chexpatchpath[]= {
"%spatches/chex/%s.%s", "%spatches/%s.%s", NULL
};
FString checkName;
const char ** checklist;
ETextureType useType = UseType;
if (useType == ETextureType::SkinSprite || useType == ETextureType::Decal || useType == ETextureType::FontChar)
{
return -3;
}
bool ispatch = (useType==ETextureType::MiscPatch || useType==ETextureType::Sprite) ;
// for patches this doesn't work yet
if (ispatch) return -3;
if (!gameinfo.ConfigName.CompareNoCase("Doom"))
{
if (!(gameinfo.flags & GI_MAPxx))
{
checklist = ispatch ? doom1patchpath : useType==ETextureType::Flat? doom1flatpath : doom1texpath;
}
else
{
SetDoom2Wad();
if (Doom2Wad == 1)
checklist = ispatch ? plutpatchpath : useType==ETextureType::Flat? plutflatpath : pluttexpath;
else if (Doom2Wad == 2)
checklist = ispatch ? tntpatchpath : useType==ETextureType::Flat? tntflatpath : tnttexpath;
else
checklist = ispatch ? doom2patchpath : useType==ETextureType::Flat? doom2flatpath : doom2texpath;
}
}
else if (!gameinfo.ConfigName.CompareNoCase("Heretic"))
{
checklist = ispatch ? hereticpatchpath : useType==ETextureType::Flat? hereticflatpath : heretictexpath;
}
else if (!gameinfo.ConfigName.CompareNoCase("Hexen"))
{
checklist = ispatch ? hexenpatchpath : useType==ETextureType::Flat? hexenflatpath : hexentexpath;
}
else if (!gameinfo.ConfigName.CompareNoCase("Strife"))
{
checklist = ispatch ?strifepatchpath : useType==ETextureType::Flat? strifeflatpath : strifetexpath;
}
else if (!gameinfo.ConfigName.CompareNoCase("Chex"))
{
checklist = ispatch ?chexpatchpath : useType==ETextureType::Flat? chexflatpath : chextexpath;
}
else
return -3;
while (*checklist)
{
static const char * extensions[] = { "PNG", "JPG", "TGA", "PCX", NULL };
for (const char ** extp=extensions; *extp; extp++)
{
checkName.Format(*checklist, progdir.GetChars(), Name.GetChars(), *extp);
if (_access(checkName, 0) == 0)
{
hascolorkey = !!strstr(checkName, "-ck.");
return Wads.AddExternalFile(checkName);
}
}
checklist++;
}
return -3;
}
//==========================================================================
//
// Checks for the presence of a hires texture replacement and loads it
//
//==========================================================================
bool FTexture::LoadHiresTexture(FTextureBuffer &texbuffer, bool checkonly)
{
if (HiresLump == -1)
{
bHiresHasColorKey = false;
HiresLump = CheckDDPK3();
if (HiresLump < 0) HiresLump = CheckExternalFile(bHiresHasColorKey);
if (HiresLump >= 0)
{
HiresTexture = FTexture::CreateTexture("", HiresLump, ETextureType::Any);
TexMan.AddTexture(HiresTexture); // let the texture manager manage this.
}
}
if (HiresTexture != nullptr)
{
int w = HiresTexture->GetWidth();
int h = HiresTexture->GetHeight();
if (!checkonly)
{
unsigned char * buffer = new unsigned char[w*(h + 1) * 4];
memset(buffer, 0, w * (h + 1) * 4);
FBitmap bmp(buffer, w * 4, w, h);
int trans;
auto Pixels = HiresTexture->GetBgraBitmap(nullptr, &trans);
bmp.Blit(0, 0, Pixels);
HiresTexture->CheckTrans(buffer, w*h, trans);
if (bHiresHasColorKey)
{
// This is a crappy Doomsday color keyed image
// We have to remove the key manually. :(
uint32_t * dwdata = (uint32_t*)buffer;
for (int i = (w*h); i > 0; i--)
{
if (dwdata[i] == 0xffffff00 || dwdata[i] == 0xffff00ff) dwdata[i] = 0;
}
}
texbuffer.mBuffer = buffer;
}
FContentIdBuilder contentId;
contentId.id = 0;
contentId.imageID = HiresTexture->GetImage()->GetId();
texbuffer.mWidth = w;
texbuffer.mHeight = h;
texbuffer.mContentId = contentId.id;
return true;
}
return false;
}

View file

@ -691,11 +691,6 @@ FTextureBuffer FTexture::CreateTexBuffer(int translation, int flags)
int isTransparent = -1;
bool checkonly = !!(flags & CTF_CheckOnly);
if (flags & CTF_CheckHires)
{
// No image means that this cannot be checked,
if (GetImage() && LoadHiresTexture(result, checkonly)) return result;
}
int exx = !!(flags & CTF_Expand);
W = GetWidth() + 2 * exx;

View file

@ -107,7 +107,6 @@ struct FloatRect
enum ECreateTexBufferFlags
{
CTF_CheckHires = 1, // use external hires replacement if found
CTF_Expand = 2, // create buffer with a one-pixel wide border
CTF_ProcessData = 4, // run postprocessing on the generated buffer. This is only needed when using the data for a hardware texture.
CTF_CheckOnly = 8, // Only runs the code to get a content ID but does not create a texture. Can be used to access a caching system for the hardware textures.
@ -385,8 +384,6 @@ protected:
FTexture *OffsetLess = nullptr;
// Paletted variant
FTexture *PalVersion = nullptr;
// External hires texture
FTexture *HiresTexture = nullptr;
// Material layers
FTexture *Brightmap = nullptr;
FTexture *Normal = nullptr; // Normal map texture
@ -504,8 +501,7 @@ public:
private:
int CheckDDPK3();
int CheckExternalFile(bool & hascolorkey);
bool LoadHiresTexture(FTextureBuffer &texbuffer, bool checkonly);
bool bSWSkyColorDone = false;
PalEntry FloorSkyColor;
PalEntry CeilingSkyColor;

View file

@ -1031,8 +1031,8 @@ static int DamageMobj (AActor *target, AActor *inflictor, AActor *source, int da
}
FName MeansOfDeath = mod;
// Spectral targets only take damage from spectral projectiles.
if (target->flags4 & MF4_SPECTRAL && !telefragDamage)
// Spectral targets only take damage from spectral projectiles unless forced or telefragging.
if ((target->flags4 & MF4_SPECTRAL) && !(flags & DMG_FORCED) && !telefragDamage)
{
if (inflictor == NULL || !(inflictor->flags4 & MF4_SPECTRAL))
{

View file

@ -103,8 +103,6 @@ void I_DetectOS()
if (10 == version.majorVersion) switch (version.minorVersion)
{
case 7: name = "Mac OS X Lion"; break;
case 8: name = "OS X Mountain Lion"; break;
case 9: name = "OS X Mavericks"; break;
case 10: name = "OS X Yosemite"; break;
case 11: name = "OS X El Capitan"; break;

View file

@ -37,7 +37,6 @@
#include "st_console.h"
#include "v_text.h"
#include "version.h"
#include "i_time.h"
static NSColor* RGB(const uint8_t red, const uint8_t green, const uint8_t blue)
@ -199,6 +198,7 @@ struct TimedUpdater
{
explicit TimedUpdater(const Function& function)
{
extern uint64_t I_msTime();
const unsigned int currentTime = I_msTime();
if (currentTime - m_previousTime > interval)

View file

@ -256,7 +256,8 @@ sector_t *FGLRenderer::RenderView(player_t* player)
NoInterpolateView = false;
// Shader start time does not need to be handled per level. Just use the one from the camera to render from.
gl_RenderState.CheckTimer(player->camera->Level->ShaderStartTime);
if (player->camera)
gl_RenderState.CheckTimer(player->camera->Level->ShaderStartTime);
// prepare all camera textures that have been used in the last frame.
// This must be done for all levels, not just the primary one!
for (auto Level : AllLevels())

View file

@ -319,8 +319,7 @@ void FGLRenderState::ApplyMaterial(FMaterial *mat, int clampmode, int translatio
int usebright = false;
int maxbound = 0;
// Textures that are already scaled in the texture lump will not get replaced by hires textures.
int flags = mat->isExpanded() ? CTF_Expand : (gl_texture_usehires && !tex->isScaled() && clampmode <= CLAMP_XY) ? CTF_CheckHires : 0;
int flags = mat->isExpanded() ? CTF_Expand : 0;
int numLayers = mat->GetLayers();
auto base = static_cast<FHardwareTexture*>(mat->GetLayer(0, translation));

View file

@ -52,7 +52,6 @@
EXTERN_CVAR (Bool, vid_vsync)
EXTERN_CVAR(Bool, r_drawvoxels)
EXTERN_CVAR(Int, gl_tonemap)
EXTERN_CVAR(Bool, gl_texture_usehires)
void gl_LoadExtensions();
void gl_PrintStartupLog();
@ -312,8 +311,7 @@ void OpenGLFrameBuffer::PrecacheMaterial(FMaterial *mat, int translation)
auto tex = mat->tex;
if (tex->isSWCanvas()) return;
// Textures that are already scaled in the texture lump will not get replaced by hires textures.
int flags = mat->isExpanded() ? CTF_Expand : (gl_texture_usehires && !tex->isScaled()) ? CTF_CheckHires : 0;
int flags = mat->isExpanded() ? CTF_Expand : 0;
int numLayers = mat->GetLayers();
auto base = static_cast<FHardwareTexture*>(mat->GetLayer(0, translation));

View file

@ -29,8 +29,6 @@
#include "hw_ihwtexture.h"
#include "hw_material.h"
EXTERN_CVAR(Bool, gl_texture_usehires)
//===========================================================================
//
// Quick'n dirty image rescaling.

View file

@ -80,11 +80,6 @@ CUSTOM_CVAR(Int, gl_texture_filter, 4, CVAR_ARCHIVE|CVAR_GLOBALCONFIG|CVAR_NOINI
screen->TextureFilterChanged();
}
CUSTOM_CVAR(Bool, gl_texture_usehires, true, CVAR_ARCHIVE|CVAR_NOINITCALL)
{
TexMan.FlushAll();
}
CVAR(Bool, gl_precache, false, CVAR_ARCHIVE)
//==========================================================================

View file

@ -10,7 +10,6 @@ EXTERN_CVAR(Bool, gl_texture)
EXTERN_CVAR(Int, gl_texture_filter)
EXTERN_CVAR(Float, gl_texture_filter_anisotropic)
EXTERN_CVAR(Int, gl_texture_format)
EXTERN_CVAR(Bool, gl_texture_usehires)
EXTERN_CVAR(Bool, gl_usefb)
EXTERN_CVAR(Int, gl_weaponlight)

View file

@ -267,7 +267,8 @@ sector_t *PolyFrameBuffer::RenderView(player_t *player)
NoInterpolateView = false;
// Shader start time does not need to be handled per level. Just use the one from the camera to render from.
GetRenderState()->CheckTimer(player->camera->Level->ShaderStartTime);
if (player->camera)
GetRenderState()->CheckTimer(player->camera->Level->ShaderStartTime);
// prepare all camera textures that have been used in the last frame.
// This must be done for all levels, not just the primary one!
for (auto Level : AllLevels())
@ -537,8 +538,7 @@ void PolyFrameBuffer::PrecacheMaterial(FMaterial *mat, int translation)
auto tex = mat->tex;
if (tex->isSWCanvas()) return;
// Textures that are already scaled in the texture lump will not get replaced by hires textures.
int flags = mat->isExpanded() ? CTF_Expand : (gl_texture_usehires && !tex->isScaled()) ? CTF_CheckHires : 0;
int flags = mat->isExpanded() ? CTF_Expand : 0;
auto base = static_cast<PolyHardwareTexture*>(mat->GetLayer(0, translation));
base->Precache(mat, translation, flags);

View file

@ -89,8 +89,7 @@ DCanvas *PolyHardwareTexture::GetImage(const FMaterialState &state)
if (tex->isHardwareCanvas()) clampmode = CLAMP_CAMTEX;
else if ((tex->isWarped() || tex->shaderindex >= FIRST_USER_SHADER) && clampmode <= CLAMP_XY) clampmode = CLAMP_NONE;
// Textures that are already scaled in the texture lump will not get replaced by hires textures.
int flags = state.mMaterial->isExpanded() ? CTF_Expand : (gl_texture_usehires && !tex->isScaled() && clampmode <= CLAMP_XY) ? CTF_CheckHires : 0;
int flags = state.mMaterial->isExpanded() ? CTF_Expand : 0;
return GetImage(tex, translation, flags);
}

View file

@ -280,6 +280,11 @@ void PolyRenderState::Apply()
mDrawCommands->SetShader(EFF_NONE, mTextureEnabled ? effectState : SHADER_NoTexture, mAlphaThreshold >= 0.f, false);
}
if (mMaterial.mMaterial && mMaterial.mMaterial->tex)
mStreamData.timer = static_cast<float>((double)(screen->FrameTime - firstFrame) * (double)mMaterial.mMaterial->tex->shaderspeed / 1000.);
else
mStreamData.timer = 0.0f;
PolyPushConstants constants;
constants.uFogEnabled = fogset;
constants.uTextureMode = mTextureMode == TM_NORMAL && mTempTM == TM_OPAQUE ? TM_OPAQUE : mTextureMode;

View file

@ -407,6 +407,60 @@ static void WriteVaryingWrap(float pos, float step, int x0, int x1, const float*
}
#endif
static void WriteVaryingWarp1(float posU, float posV, float stepU, float stepV, int x0, int x1, PolyTriangleThreadData* thread)
{
float pi2 = 3.14159265358979323846f * 2.0f;
float timer = thread->mainVertexShader.Data.timer * 0.125f;
const float* w = thread->scanline.W;
uint16_t* scanlineU = thread->scanline.U;
uint16_t* scanlineV = thread->scanline.V;
for (int x = x0; x < x1; x++)
{
float u = posU * w[x];
float v = posV * w[x];
v += g_sin(pi2 * (u + timer)) * 0.1f;
u += g_sin(pi2 * (v + timer)) * 0.1f;
u = u - std::floor(u);
v = v - std::floor(v);
scanlineU[x] = static_cast<uint32_t>(static_cast<int32_t>(u * static_cast<float>(0x1000'0000)) << 4) >> 16;
scanlineV[x] = static_cast<uint32_t>(static_cast<int32_t>(v * static_cast<float>(0x1000'0000)) << 4) >> 16;
posU += stepU;
posV += stepV;
}
}
static void WriteVaryingWarp2(float posU, float posV, float stepU, float stepV, int x0, int x1, PolyTriangleThreadData* thread)
{
float pi2 = 3.14159265358979323846f * 2.0f;
float timer = thread->mainVertexShader.Data.timer;
const float* w = thread->scanline.W;
uint16_t* scanlineU = thread->scanline.U;
uint16_t* scanlineV = thread->scanline.V;
for (int x = x0; x < x1; x++)
{
float u = posU * w[x];
float v = posV * w[x];
v += (0.5f + g_sin(pi2 * (v + timer * 0.61f + 900.f/8192.f)) + g_sin(pi2 * (u * 2.0f + timer * 0.36f + 300.0f/8192.0f))) * 0.025f;
u += (0.5f + g_sin(pi2 * (v + timer * 0.49f + 700.f/8192.f)) + g_sin(pi2 * (u * 2.0f + timer * 0.49f + 1200.0f/8192.0f))) * 0.025f;
u = u - std::floor(u);
v = v - std::floor(v);
scanlineU[x] = static_cast<uint32_t>(static_cast<int32_t>(u * static_cast<float>(0x1000'0000)) << 4) >> 16;
scanlineV[x] = static_cast<uint32_t>(static_cast<int32_t>(v * static_cast<float>(0x1000'0000)) << 4) >> 16;
posU += stepU;
posV += stepV;
}
}
#ifdef NO_SSE
static void WriteVaryingColor(float pos, float step, int x0, int x1, const float* w, uint8_t* varying)
{
@ -448,8 +502,28 @@ void WriteVaryings(int y, int x0, int x1, const TriDrawTriangleArgs* args, PolyT
float startX = x0 + (0.5f - args->v1->x);
float startY = y + (0.5f - args->v1->y);
WriteVaryingWrap(args->v1->u * args->v1->w + args->gradientX.U * startX + args->gradientY.U * startY, args->gradientX.U, x0, x1, thread->scanline.W, thread->scanline.U);
WriteVaryingWrap(args->v1->v * args->v1->w + args->gradientX.V * startX + args->gradientY.V * startY, args->gradientX.V, x0, x1, thread->scanline.W, thread->scanline.V);
void (*useShader)(float posU, float posV, float stepU, float stepV, int x0, int x1, PolyTriangleThreadData* thread) = nullptr;
if (thread->EffectState == SHADER_Warp1)
useShader = &WriteVaryingWarp1;
else if (thread->EffectState == SHADER_Warp2)
useShader = &WriteVaryingWarp2;
if (useShader)
{
useShader(
args->v1->u * args->v1->w + args->gradientX.U * startX + args->gradientY.U * startY,
args->v1->v * args->v1->w + args->gradientX.V * startX + args->gradientY.V * startY,
args->gradientX.U,
args->gradientX.V,
x0, x1,
thread);
}
else
{
WriteVaryingWrap(args->v1->u * args->v1->w + args->gradientX.U * startX + args->gradientY.U * startY, args->gradientX.U, x0, x1, thread->scanline.W, thread->scanline.U);
WriteVaryingWrap(args->v1->v * args->v1->w + args->gradientX.V * startX + args->gradientY.V * startY, args->gradientX.V, x0, x1, thread->scanline.W, thread->scanline.V);
}
WriteVarying(args->v1->worldX * args->v1->w + args->gradientX.WorldX * startX + args->gradientY.WorldX * startY, args->gradientX.WorldX, x0, x1, thread->scanline.W, thread->scanline.WorldX);
WriteVarying(args->v1->worldY * args->v1->w + args->gradientX.WorldY * startX + args->gradientY.WorldY * startY, args->gradientX.WorldY, x0, x1, thread->scanline.W, thread->scanline.WorldY);
WriteVarying(args->v1->worldZ * args->v1->w + args->gradientX.WorldZ * startX + args->gradientY.WorldZ * startY, args->gradientX.WorldZ, x0, x1, thread->scanline.W, thread->scanline.WorldZ);

View file

@ -39,8 +39,6 @@
#include "m_alloc.h"
#include "imagehelpers.h"
EXTERN_CVAR(Bool, gl_texture_usehires)
FSoftwareTexture *FTexture::GetSoftwareTexture()
{
@ -64,7 +62,7 @@ FSoftwareTexture::FSoftwareTexture(FTexture *tex)
mTexture = tex;
mSource = tex;
mBufferFlags = (gl_texture_usehires && !tex->isScaled() && tex->GetImage() && !tex->isSprite() ) ? CTF_CheckHires|CTF_ProcessData : CTF_ProcessData;
mBufferFlags = CTF_ProcessData;
auto info = tex->CreateTexBuffer(0, CTF_CheckOnly| mBufferFlags);
mPhysicalWidth = info.mWidth;
mPhysicalHeight = info.mHeight;

View file

@ -42,6 +42,7 @@
EXTERN_CVAR(Int, gl_texture_hqresizemult)
EXTERN_CVAR(Int, gl_texture_hqresizemode)
EXTERN_CVAR(Int, gl_texture_hqresize_targets)
FWarpTexture::FWarpTexture (FTexture *source, int warptype)
: FSoftwareTexture (source)
@ -63,7 +64,7 @@ const uint32_t *FWarpTexture::GetPixelsBgra()
if (time != GenTime[2])
{
if (gl_texture_hqresizemode == 0 || gl_texture_hqresizemult < 1)
if (gl_texture_hqresizemode == 0 || gl_texture_hqresizemult < 1 || !(gl_texture_hqresize_targets & 1))
resizeMult = 1;
auto otherpix = FSoftwareTexture::GetPixelsBgra();
@ -84,7 +85,7 @@ const uint8_t *FWarpTexture::GetPixels(int index)
if (time != GenTime[index])
{
if (gl_texture_hqresizemode == 0 || gl_texture_hqresizemult < 1)
if (gl_texture_hqresizemode == 0 || gl_texture_hqresizemult < 1 || !(gl_texture_hqresize_targets & 1))
resizeMult = 1;
const uint8_t *otherpix = FSoftwareTexture::GetPixels(index);

View file

@ -136,11 +136,13 @@ namespace swrenderer
if (thing->renderflags & RF_SPRITEFLIP)
renderflags ^= RF_XFLIP;
double yscale;
double yscale, origyscale;
int resizeMult = gl_texture_hqresizemult;
origyscale = spriteScale.Y / tex->GetScale().Y;
if (gl_texture_hqresizemode == 0 || gl_texture_hqresizemult < 1 || !(gl_texture_hqresize_targets & 2))
yscale = spriteScale.Y / tex->GetScale().Y;
else
yscale = spriteScale.Y / tex->GetScale().Y / gl_texture_hqresizemult;
resizeMult = 1;
yscale = origyscale / resizeMult;
// store information in a vissprite
RenderSprite *vis = thread->FrameMemory->NewObject<RenderSprite>();
@ -150,8 +152,8 @@ namespace swrenderer
vis->CurrentPortalUniq = renderportal->CurrentPortalUniq;
vis->yscale = float(viewport->InvZtoScale * yscale / wallc.sz1);
vis->idepth = float(1 / wallc.sz1);
vis->floorclip = thing->Floorclip / yscale;
vis->texturemid = tex->GetTopOffsetSW() - (viewport->viewpoint.Pos.Z - pos.Z + thing->Floorclip) / yscale;
vis->floorclip = thing->Floorclip / origyscale;
vis->texturemid = tex->GetTopOffsetSW() - (viewport->viewpoint.Pos.Z - pos.Z + thing->Floorclip / resizeMult) / yscale;
vis->x1 = wallc.sx1 < renderportal->WindowLeft ? renderportal->WindowLeft : wallc.sx1;
vis->x2 = wallc.sx2 > renderportal->WindowRight ? renderportal->WindowRight : wallc.sx2;
vis->heightsec = heightsec;

View file

@ -404,7 +404,8 @@ sector_t *VulkanFrameBuffer::RenderView(player_t *player)
NoInterpolateView = false;
// Shader start time does not need to be handled per level. Just use the one from the camera to render from.
GetRenderState()->CheckTimer(player->camera->Level->ShaderStartTime);
if (player->camera)
GetRenderState()->CheckTimer(player->camera->Level->ShaderStartTime);
// prepare all camera textures that have been used in the last frame.
// This must be done for all levels, not just the primary one!
for (auto Level : AllLevels())
@ -651,7 +652,7 @@ void VulkanFrameBuffer::PrecacheMaterial(FMaterial *mat, int translation)
if (tex->isSWCanvas()) return;
// Textures that are already scaled in the texture lump will not get replaced by hires textures.
int flags = mat->isExpanded() ? CTF_Expand : (gl_texture_usehires && !tex->isScaled()) ? CTF_CheckHires : 0;
int flags = mat->isExpanded() ? CTF_Expand : 0;
auto base = static_cast<VkHardwareTexture*>(mat->GetLayer(0, translation));
base->Precache(mat, translation, flags);

View file

@ -132,7 +132,7 @@ VulkanDescriptorSet *VkHardwareTexture::GetDescriptorSet(const FMaterialState &s
else if ((tex->isWarped() || tex->shaderindex >= FIRST_USER_SHADER) && clampmode <= CLAMP_XY) clampmode = CLAMP_NONE;
// Textures that are already scaled in the texture lump will not get replaced by hires textures.
int flags = state.mMaterial->isExpanded() ? CTF_Expand : (gl_texture_usehires && !tex->isScaled() && clampmode <= CLAMP_XY) ? CTF_CheckHires : 0;
int flags = state.mMaterial->isExpanded() ? CTF_Expand : 0;
if (tex->isHardwareCanvas()) static_cast<FCanvasTexture*>(tex)->NeedUpdate();

View file

@ -1629,6 +1629,23 @@ DEFINE_ACTION_FUNCTION_NATIVE(AActor, A_NoBlocking, A_Unblock)
return 0;
}
static void CopyBloodColor(AActor* self, AActor* other)
{
if (self && other)
{
self->BloodColor = other->BloodColor;
self->BloodTranslation = other->BloodTranslation;
}
}
DEFINE_ACTION_FUNCTION_NATIVE(AActor, CopyBloodColor, CopyBloodColor)
{
PARAM_SELF_PROLOGUE(AActor);
PARAM_OBJECT(other, AActor);
CopyBloodColor(self, other);
return 0;
}
//=====================================================================================
//
// Inventory exports

View file

@ -36,10 +36,6 @@
#include <chrono>
#include <thread>
#include "i_time.h"
#include "doomdef.h"
#include "c_cvars.h"
#include "doomstat.h"
#include "doomtype.h"
//==========================================================================
//
@ -50,27 +46,9 @@
static uint64_t FirstFrameStartTime;
static uint64_t CurrentFrameStartTime;
static uint64_t FreezeTime;
int GameTicRate;
static double TimeScale = 1.0;
CUSTOM_CVAR(Float, i_timescale, 1.0f, CVAR_NOINITCALL)
{
if (netgame)
{
Printf("Time scale cannot be changed in net games.\n");
self = 1.0f;
}
else if (self >= 0.05f)
{
I_FreezeTime(true);
TimeScale = self;
I_FreezeTime(false);
}
else
{
Printf("Time scale must be at least 0.05!\n");
}
}
double TimeScale = 1.0;
static uint64_t GetClockTimeNS()
{
@ -90,12 +68,12 @@ static uint64_t NSToMS(uint64_t ns)
static int NSToTic(uint64_t ns)
{
return static_cast<int>(ns * TICRATE / 1'000'000'000);
return static_cast<int>(ns * GameTicRate / 1'000'000'000);
}
static uint64_t TicToNS(int tic)
{
return static_cast<uint64_t>(tic) * 1'000'000'000 / TICRATE;
return static_cast<uint64_t>(tic) * 1'000'000'000 / GameTicRate;
}
void I_SetFrameTime()

View file

@ -2,6 +2,9 @@
#include <stdint.h>
extern int GameTicRate;
extern double TimeScale;
// Called by D_DoomLoop, sets the time for the current frame
void I_SetFrameTime();

View file

@ -78,6 +78,15 @@ public:
protected:
bool Grabbed;
POINT UngrabbedPointerPos;
private:
void RegisterRawInput();
void UnregisterRawInput();
void CheckDelayedUnregister(RAWINPUT* raw);
void ReleaseLegacyInput();
bool mDelayUnregister = false;
int mButtonsDown = 0;
};
class FDInputMouse : public FMouse
@ -569,22 +578,21 @@ void FRawMouse::Grab()
{
if (!Grabbed)
{
RAWINPUTDEVICE rid;
rid.usUsagePage = HID_GENERIC_DESKTOP_PAGE;
rid.usUsage = HID_GDP_MOUSE;
rid.dwFlags = RIDEV_CAPTUREMOUSE | RIDEV_NOLEGACY;
rid.hwndTarget = Window;
if (RegisterRawInputDevices(&rid, 1, sizeof(rid)))
if (!mDelayUnregister)
{
GetCursorPos(&UngrabbedPointerPos);
Grabbed = true;
SetCursorState(false);
// By setting the cursor position, we force the pointer image
// to change right away instead of having it delayed until
// some time in the future.
CenterMouse(-1, -1, NULL, NULL);
ReleaseLegacyInput();
RegisterRawInput();
mButtonsDown = 0;
}
else
{
mDelayUnregister = false;
}
GetCursorPos(&UngrabbedPointerPos);
while (ShowCursor(FALSE) >= 0);
Grabbed = true;
SetCursorState(false);
}
}
@ -598,19 +606,104 @@ void FRawMouse::Ungrab()
{
if (Grabbed)
{
RAWINPUTDEVICE rid;
rid.usUsagePage = HID_GENERIC_DESKTOP_PAGE;
rid.usUsage = HID_GDP_MOUSE;
rid.dwFlags = RIDEV_REMOVE;
rid.hwndTarget = NULL;
if (RegisterRawInputDevices(&rid, 1, sizeof(rid)))
// This is to prevent WM_RBUTTONUP from falling through to the application under the cursor when we release capture.
if (mButtonsDown == 0)
{
Grabbed = false;
ClearButtonState();
UnregisterRawInput();
}
else
{
mDelayUnregister = true;
}
Grabbed = false;
ClearButtonState();
SetCursorState(true);
SetCursorPos(UngrabbedPointerPos.x, UngrabbedPointerPos.y);
while (ShowCursor(TRUE) < 0);
}
}
//==========================================================================
//
// FRawMouse :: RegisterRawInput
//
//==========================================================================
void FRawMouse::RegisterRawInput()
{
RAWINPUTDEVICE rid;
rid.usUsagePage = HID_GENERIC_DESKTOP_PAGE;
rid.usUsage = HID_GDP_MOUSE;
rid.dwFlags = RIDEV_CAPTUREMOUSE | RIDEV_NOLEGACY | RIDEV_INPUTSINK;
rid.hwndTarget = Window;
RegisterRawInputDevices(&rid, 1, sizeof(rid));
}
//==========================================================================
//
// FRawMouse :: UnregisterRawInput
//
//==========================================================================
void FRawMouse::UnregisterRawInput()
{
RAWINPUTDEVICE rid;
rid.usUsagePage = HID_GENERIC_DESKTOP_PAGE;
rid.usUsage = HID_GDP_MOUSE;
rid.dwFlags = RIDEV_REMOVE;
rid.hwndTarget = NULL;
RegisterRawInputDevices(&rid, 1, sizeof(rid));
}
//==========================================================================
//
// FRawMouse :: ReleaseLegacyMouseDown
//
//==========================================================================
void FRawMouse::ReleaseLegacyInput()
{
// Send release of all pressed mouse buttons to the Windows legacy input system.
// If this isn't done the legacy input system may think the buttons are still down when we release the capture of input events.
const int vkeys[] = { VK_LBUTTON, VK_RBUTTON, VK_MBUTTON, VK_XBUTTON1, VK_XBUTTON2 };
const DWORD keyflags[] = { MOUSEEVENTF_LEFTUP, MOUSEEVENTF_RIGHTUP, MOUSEEVENTF_MIDDLEUP, MOUSEEVENTF_XUP, MOUSEEVENTF_XUP };
const DWORD mousedata[] = { 0, 0, 0, XBUTTON1, XBUTTON2 };
std::vector<INPUT> inputs;
for (int i = 0; i < 5; i++)
{
bool keydown = GetKeyState(vkeys[i]) < 0;
if (keydown)
{
INPUT input = {};
input.type = INPUT_MOUSE;
input.mi.dwExtraInfo = GetMessageExtraInfo();
input.mi.dwFlags = keyflags[i];
input.mi.mouseData = mousedata[i];
inputs.push_back(input);
}
}
SendInput((UINT)inputs.size(), inputs.data(), sizeof(INPUT));
}
void FRawMouse::CheckDelayedUnregister(RAWINPUT* raw)
{
// Track button state
for (DWORD i = 0; i < 5; i++)
{
DWORD down = 1 << (i * 2);
DWORD up = down << 1;
if (raw->data.mouse.usButtonFlags & down)
mButtonsDown |= (1 << i);
else if (raw->data.mouse.usButtonFlags & up)
mButtonsDown &= ~(1 << i);
}
if (mDelayUnregister && mButtonsDown == 0)
{
UnregisterRawInput();
mDelayUnregister = false;
}
}
@ -655,10 +748,7 @@ bool FRawMouse::ProcessRawInput(RAWINPUT *raw, int code)
int x = m_noprescale ? raw->data.mouse.lLastX : raw->data.mouse.lLastX << 2;
int y = -raw->data.mouse.lLastY;
PostMouseMove(x, y);
if (x | y)
{
CenterMouse(-1, -1, NULL, NULL);
}
CheckDelayedUnregister(raw);
return true;
}

View file

@ -204,24 +204,7 @@ void I_DetectOS(void)
{
case VER_PLATFORM_WIN32_NT:
osname = "NT";
if (info.dwMajorVersion == 5)
{
if (info.dwMinorVersion == 0)
{
osname = "2000";
}
if (info.dwMinorVersion == 1)
{
osname = "XP";
sys_ostype = 1; // legacy OS
}
else if (info.dwMinorVersion == 2)
{
osname = "Server 2003";
sys_ostype = 1; // legacy OS
}
}
else if (info.dwMajorVersion == 6)
if (info.dwMajorVersion == 6)
{
if (info.dwMinorVersion == 0)
{
@ -248,12 +231,12 @@ void I_DetectOS(void)
}
else if (info.dwMinorVersion == 4)
{
osname = (info.wProductType == VER_NT_WORKSTATION) ? "10 (beta)" : "Server 10 (beta)";
osname = (info.wProductType == VER_NT_WORKSTATION) ? "10 (beta)" : "Server 2016 (beta)";
}
}
else if (info.dwMajorVersion == 10)
{
osname = (info.wProductType == VER_NT_WORKSTATION) ? "10 (or higher)" : "Server 10 (or higher)";
osname = (info.wProductType == VER_NT_WORKSTATION) ? "10 (or higher)" : "Server 2016 (or higher)";
sys_ostype = 3; // modern OS
}
break;

View file

@ -162,11 +162,6 @@ AF40D0E49BD1B76D4B1AADD8212ADC46 // MAP01 (the wad that shall not be named =P)
limitpain
}
7C1913DEE396BA26CFF22A0E9369B7D2 // Nuke Mine, e1m2
{
pointonline
}
920F8D876ECD96D8C2A978FF1AB2B401 // Darken2.wad map01 - Nodes go out of bounds/beyond normal sector boundaries
CFEDB7FA89885E24856CAC9A2FB3CE58 // Darken2.wad map03 - GZDoomBuilder crashes when displaying Nodes
8E961FA7029761D5FAB3932C40F10CD2 // Darken2.wad map04 - Nodes go out of bounds/beyond normal sector boundaries
@ -198,6 +193,7 @@ EDA5CE7C462BD171BF8110AC56B67857 // pl2.wad map11
A9A9A728E689266939C1B71655F320CA // pl2.wad map25
62CA74092FC88C1E7FE2D0B1A8034E29 // pl2.wad map29
19E1CFD717FC6BBA9371F0F529B4CDFF // ur_final.wad map27
836E09559FF22A7A37C2587F7EAFF1EE // Requiem MAP29 - Incorrect sector lighting and vanishing items
{
rebuildnodes
}
@ -255,6 +251,7 @@ D7F6E9F08C39A17026349A04F8C0B0BE // Return to Hadron, e1m9
19D03FFC875589E21EDBB7AB74EF4AEF // Return to Hadron, e1m9, 2016.01.03 update
5BDA34DA60C0530794CC1EA2DA017976 // doom2.wad map14
5B3F118B337BFBFB8D5C81E98AF7B71D // Ancient Aliens map23
7C1913DEE396BA26CFF22A0E9369B7D2 // Nuke Mine, e1m2
{
pointonline
}

View file

@ -2535,7 +2535,6 @@ OptionMenu "GLTextureGLOptions" protected
Title "$GLTEXMNU_TITLE"
Option "$GLTEXMNU_TEXFILTER", gl_texture_filter, "FilterModes"
Option "$GLTEXMNU_ANISOTROPIC", gl_texture_filter_anisotropic, "Anisotropy"
Option "$GLTEXMNU_ENABLEHIRES", gl_texture_usehires, "YesNo"
ifOption(MMX)
{

View file

@ -1163,6 +1163,7 @@ class Actor : Thinker native
native bool A_SetSize(double newradius = -1, double newheight = -1, bool testpos = false);
native void A_SprayDecal(String name, double dist = 172);
native void A_SetMugshotState(String name);
native void CopyBloodColor(Actor other);
native void A_RearrangePointers(int newtarget, int newmaster = AAPTR_DEFAULT, int newtracer = AAPTR_DEFAULT, int flags=0);
native void A_TransferPointer(int ptr_source, int ptr_recipient, int sourcefield, int recipientfield=AAPTR_DEFAULT, int flags=0);

View file

@ -1778,6 +1778,176 @@ class LevelCompatibility : LevelPostProcessor
SetLineSpecial(11518, 9, 0, 0, 0, 0);
break;
}
case 'BA530202AF0BA0C6CBAE6A0C7076FB72': // Requiem MAP04
{
// Flag deathmatch berserk for 100% items in single-player
SetThingFlags(284, 17);
// Make Hell Knight trap switch repeatable to prevent softlock
SetLineFlags(823, Line.ML_REPEAT_SPECIAL);
break;
}
case '104415DDEBCAFB9783CA60807C46B57D': // Requiem MAP05
{
// Raise spectre pit near soulsphere if player drops into it
for(int i = 0; i < 4; i++)
{
SetLineSpecial(2130+i, Floor_LowerToHighest, 28, 8, 128);
SetLineActivation(2130+i, SPAC_Cross);
}
break;
}
case '1B0AF5286D4E914C5E903BC505E6A844': // Requiem MAP06
{
// Flag deathmatch berserks for 100% items in single-player
SetThingFlags(103, 17);
SetThingFlags(109, 17);
// Shooting the cross before all Imps spawn in can make 100%
// kills impossible, add line actions and change sector tag
for(int i = 0; i < 7; i++)
{
SetLineSpecial(1788+i, Floor_RaiseToNearest, 100, 32);
SetLineActivation(1788+i, SPAC_Cross);
}
SetLineSpecial(1796, Floor_RaiseToNearest, 100, 32);
SetLineActivation(1796, SPAC_Cross);
SetLineSpecial(1800, Floor_RaiseToNearest, 100, 32);
SetLineActivation(1800, SPAC_Cross);
SetLineSpecial(1802, Floor_RaiseToNearest, 100, 32);
SetLineActivation(1802, SPAC_Cross);
ClearSectorTags(412);
AddSectorTag(412, 100);
// Shootable cross at demon-faced floor changed to repeatable
// action to prevent softlock if "spikes" are raised again
SetLineFlags(2600, Line.ML_REPEAT_SPECIAL);
break;
}
case '3C10B1B017E902BE7CDBF2436DF56973': // Requiem MAP08
{
// Flag deathmatch soulsphere for 100% items in single-player
SetThingFlags(48, 17);
// Allow player to leave inescapable lift using the walls
for(int i = 0; i < 3; i++)
{
SetLineSpecial(2485+i, Plat_DownWaitUpStayLip, 68, 64, 105, 0);
SetLineActivation(2485+i, SPAC_Use);
SetLineFlags(2485+i, Line.ML_REPEAT_SPECIAL);
}
SetLineSpecial(848, Plat_DownWaitUpStayLip, 68, 64, 105, 0);
SetLineActivation(848, SPAC_UseBack);
SetLineFlags(848, Line.ML_REPEAT_SPECIAL);
SetLineSpecial(895, Plat_DownWaitUpStayLip, 68, 64, 105, 0);
SetLineActivation(895, SPAC_UseBack);
SetLineFlags(895, Line.ML_REPEAT_SPECIAL);
break;
}
case '14FE46ED0458979118007E1906A0C9BC': // Requiem MAP09
{
// Flag deathmatch items for 100% items in single-player
for(int i = 0; i < 6; i++)
SetThingFlags(371+i, 17);
for(int i = 0; i < 19; i++)
SetThingFlags(402+i, 17);
SetThingFlags(359, 17);
SetThingFlags(389, 17);
SetThingFlags(390, 17);
// Change sides of blue skull platform to be repeatable
for(int i = 0; i < 4; i++)
SetLineFlags(873+i, Line.ML_REPEAT_SPECIAL);
// Make switch that raises bars near yellow skull repeatable
SetLineFlags(2719, Line.ML_REPEAT_SPECIAL);
break;
}
case '53A6369C3C8DA4E7AC443A8F8684E38E': // Requiem MAP12
{
// Remove unreachable secrets
SetSectorSpecial(352, 0);
SetSectorSpecial(503, 0);
// Change action of eastern switch at pool of water so that it
// lowers the floor properly, making the secret accessible
SetLineSpecial(4873, Floor_LowerToLowest, 62, 8);
break;
}
case '2DAB6E4B19B4F2763695267D39CD0275': // Requiem MAP13
{
// Fix missing nukage at starting bridge on hardware renderer
for(int i = 0; i < 4; i++)
SetLineSectorRef(2152+i, Line.back, 8);
break;
}
case 'F55FB2A8DC68CFC75E4340EF4ED7A8BF': // Requiem MAP21
{
// Fix self-referencing floor hack
for(int i = 0; i < 4; i++)
SetLineSectorRef(3+i, Line.back, 219);
SetLineSpecial(8, Transfer_Heights, 80);
// Fix south side of pit hack so textures don't bleed through
// the fake floor on hardware renderer
SetLineSectorRef(267, Line.back, 63);
SetLineSectorRef(268, Line.back, 63);
SetLineSectorRef(270, Line.back, 63);
SetLineSectorRef(271, Line.back, 63);
SetLineSectorRef(274, Line.back, 63);
SetLineSectorRef(275, Line.back, 63);
SetLineSectorRef(3989, Line.back, 63);
SetLineSectorRef(3994, Line.back, 63);
// Fix fake 3D bridge on hardware renderer
SetLineSectorRef(506, Line.back, 841);
SetLineSectorRef(507, Line.back, 841);
SetLineSectorRef(536, Line.back, 841);
SetLineSectorRef(537, Line.back, 841);
SetLineSectorRef(541, Line.back, 841);
SetLineSectorRef(547, Line.back, 841);
AddSectorTag(90, 1000);
AddSectorTag(91, 1000);
SetSectorTexture(90, Sector.floor, "MFLR8_4");
SetSectorTexture(91, Sector.floor, "MFLR8_4");
SetLineSectorRef(553, Line.back, 841);
SetLineSectorRef(554, Line.back, 841);
SetLineSectorRef(559, Line.back, 841);
SetLineSectorRef(560, Line.back, 841);
SetLineSectorRef(562, Line.back, 841);
SetLineSectorRef(568, Line.back, 841);
AddSectorTag(96, 1000);
AddSectorTag(97, 1000);
SetSectorTexture(96, Sector.floor, "MFLR8_4");
SetSectorTexture(97, Sector.floor, "MFLR8_4");
SetLineSpecial(505, Transfer_Heights, 1000);
// Fix randomly appearing ceiling at deep water
SetLineSectorRef(1219, Line.front, 233);
SetLineSectorRef(1222, Line.front, 233);
SetLineSectorRef(1223, Line.front, 233);
SetLineSectorRef(1228, Line.front, 233);
// Make switch in sky room repeatable so player does not get
// trapped at red cross if returning a second time
SetLineFlags(3870, Line.ML_REPEAT_SPECIAL);
// Move unreachable item bonuses
SetThingXY(412, -112, 6768);
SetThingXY(413, -112, 6928);
SetThingXY(414, -96, 6928);
SetThingXY(415, -96, 6768);
// Remove unreachable secret at exit megasphere
SetSectorSpecial(123, 0);
break;
}
case '2499CF9A9351BE9BC4E9C66FC9F291A7': // Requiem MAP23
{
// Remove secret at switch that can only be scored by crouching
SetSectorSpecial(240, 0);
break;
}
}
}
}