- Added Skulltag's HQ resite feature

- removed special handling for old ZSBSPs that threw out overlapping linedefs.
  If such nodes are encountered now a rebuild is forced instead of trying to
  work with the broken data.

- Update to ZDoom r1333:

- Added Karate Chris's new DMFlags submission.
- Fixed: The correct player class was not remembered when the menu had both
  a player class selection menu and an episode menu.
- Fixed: AddToConsole could write outside its working buffer.
- Fixed: 0 was no longer recognized as placeholder for 'no state' in A_Chase.
- Fixed: When picking up weapons the code did not check if it should switch away
  from weak weapons.

git-svn-id: http://mancubus.net/svn/hosted/gzdoom/trunk@279 b0f79afe-0144-0410-b225-9a4edf0717df
This commit is contained in:
Christoph Oelckers 2008-12-28 13:27:13 +00:00
parent 9ed7dd7fa3
commit 9446999c4c
39 changed files with 583 additions and 300 deletions

View file

@ -1,3 +1,14 @@
December 28, 2008 (Changes by Graf Zahl)
- Added Karate Chris's new DMFlags submission.
December 27, 2008 (Changes by Graf Zahl)
- Fixed: The correct player class was not remembered when the menu had both
a player class selection menu and an episode menu.
- Fixed: AddToConsole could write outside its working buffer.
- Fixed: 0 was no longer recognized as placeholder for 'no state' in A_Chase.
- Fixed: When picking up weapons the code did not check if it should switch away
from weak weapons.
December 20, 2008
- OggMod improperly decodes the right channel of stereo samples when sending
them to OggEnc, so I have no choice but to convert them to mono by chopping

View file

@ -6424,6 +6424,10 @@
RelativePath=".\src\gl\gl_hirestex.cpp"
>
</File>
<File
RelativePath=".\src\gl\gl_hqresize.cpp"
>
</File>
<File
RelativePath=".\src\gl\gl_light.cpp"
>
@ -6432,10 +6436,6 @@
RelativePath=".\src\gl\gl_menu.cpp"
>
</File>
<File
RelativePath=".\src\gl\gl_missinglines.cpp"
>
</File>
<File
RelativePath=".\src\gl\gl_missingtexture.cpp"
>
@ -6559,6 +6559,10 @@
RelativePath=".\src\gl\gl_include.h"
>
</File>
<File
RelativePath=".\src\gl\gl_hqresize.h"
>
</File>
<File
RelativePath=".\src\gl\gl_intern.h"
>

View file

@ -620,7 +620,6 @@ add_executable( zdoom WIN32
gl/gl_hirestex.cpp
gl/gl_light.cpp
gl/gl_menu.cpp
gl/gl_missinglines.cpp
gl/gl_missingtexture.cpp
gl/gl_models.cpp
gl/gl_models_md2.cpp

View file

@ -863,6 +863,10 @@ void AM_ToggleMap ()
if (gamestate != GS_LEVEL)
return;
// Don't activate the automap if we're not allowed to use it.
if (dmflags2 & DF2_NO_AUTOMAP)
return;
SB_state = screen->GetPageCount ();
if (!automapactive)
{
@ -1572,6 +1576,10 @@ void AM_drawPlayers ()
{
continue;
}
// We don't always want to show allies on the automap.
if (dmflags2 & DF2_NO_AUTOMAP_ALLIES && i != consoleplayer)
continue;
if (deathmatch && !demoplayback &&
!p->mo->IsTeammate (players[consoleplayer].mo) &&

View file

@ -232,7 +232,8 @@ CCMD (chase)
}
else
{
if (gamestate == GS_LEVEL && deathmatch && CheckCheatmode ())
// Check if we're allowed to use chasecam.
if (gamestate != GS_LEVEL || (!(dmflags2 & DF2_CHASECAM) && CheckCheatmode ()))
return;
Net_WriteByte (DEM_GENERICCHEAT);

View file

@ -667,7 +667,7 @@ void AddToConsole (int printlevel, const char *text)
}
len = (int)strlen (text);
size = len + 3;
size = len + 20;
if (addtype != NEWLINE)
{
@ -767,6 +767,15 @@ void AddToConsole (int printlevel, const char *text)
if (*work_p)
{
linestart = work_p - 1 - cc.Len();
if (linestart < work)
{
// The line start is outside the buffer.
// Make space for the newly inserted stuff.
size_t movesize = work-linestart;
memmove(work + movesize, work, strlen(work));
work_p += movesize;
linestart = work;
}
linestart[0] = TEXTCOLOR_ESCAPE;
strncpy (linestart + 1, cc, cc.Len());
}

View file

@ -99,6 +99,7 @@
#include "d_event.h"
#include "d_netinf.h"
#include "v_palette.h"
#include "m_cheat.h"
EXTERN_CVAR(Bool, hud_althud)
void DrawHUD();
@ -114,6 +115,7 @@ extern void M_SetDefaultMode ();
extern void R_ExecuteSetViewSize ();
extern void G_NewInit ();
extern void SetupPlayerClasses ();
extern bool CheckCheatmode ();
// PUBLIC FUNCTION PROTOTYPES ----------------------------------------------
@ -139,6 +141,7 @@ EXTERN_CVAR (Float, m_yaw)
EXTERN_CVAR (Bool, invertmouse)
EXTERN_CVAR (Bool, lookstrafe)
EXTERN_CVAR (Int, screenblocks)
EXTERN_CVAR (Bool, sv_cheats)
extern gameinfo_t SharewareGameInfo;
extern gameinfo_t RegisteredGameInfo;
@ -440,7 +443,58 @@ CVAR (Flag, sv_allowcrouch, dmflags, DF_YES_CROUCH);
//
//==========================================================================
CVAR (Int, dmflags2, 0, CVAR_SERVERINFO);
CUSTOM_CVAR (Int, dmflags2, 0, CVAR_SERVERINFO)
{
// Stop the automap if we aren't allowed to use it.
if ((self & DF2_NO_AUTOMAP) && automapactive)
AM_Stop ();
for (int i = 0; i < MAXPLAYERS; i++)
{
player_t *p = &players[i];
if (!playeringame[i])
continue;
// Revert our view to our own eyes if spying someone else.
if (self & DF2_DISALLOW_SPYING)
{
// The player isn't looking through its own eyes, so make it.
if (p->camera != p->mo)
{
p->camera = p->mo;
S_UpdateSounds (p->camera);
StatusBar->AttachToPlayer (p);
if (demoplayback || multiplayer)
StatusBar->ShowPlayerName ();
}
}
// Come out of chasecam mode if we're not allowed to use chasecam.
if (!(dmflags2 & DF2_CHASECAM) && !G_SkillProperty (SKILLP_DisableCheats) && !sv_cheats)
{
// Take us out of chasecam mode only.
if (p->cheats & CF_CHASECAM)
cht_DoCheat (p, CHT_CHASECAM);
}
// Change our autoaim settings if need be.
if (dmflags2 & DF2_NOAUTOAIM)
{
// Save our aimdist and set aimdist to 0.
p->userinfo.savedaimdist = p->userinfo.aimdist;
p->userinfo.aimdist = 0;
}
else
{
// Restore our aimdist.
p->userinfo.aimdist = p->userinfo.savedaimdist;
}
}
}
CVAR (Flag, sv_weapondrop, dmflags2, DF2_YES_WEAPONDROP);
CVAR (Flag, sv_noteamswitch, dmflags2, DF2_NO_TEAM_SWITCH);
CVAR (Flag, sv_doubleammo, dmflags2, DF2_YES_DOUBLEAMMO);
@ -452,7 +506,14 @@ CVAR (Flag, sv_norespawn, dmflags2, DF2_NO_RESPAWN);
CVAR (Flag, sv_losefrag, dmflags2, DF2_YES_LOSEFRAG);
CVAR (Flag, sv_respawnprotect, dmflags2, DF2_YES_RESPAWN_INVUL);
CVAR (Flag, sv_samespawnspot, dmflags2, DF2_SAME_SPAWN_SPOT);
CVAR (Flag, sv_infiniteinventory, dmflags2, DF2_INFINITE_INVENTORY)
CVAR (Flag, sv_infiniteinventory, dmflags2, DF2_INFINITE_INVENTORY);
CVAR (Flag, sv_killallmonsters, dmflags2, DF2_KILL_MONSTERS);
CVAR (Flag, sv_noautomap, dmflags2, DF2_NO_AUTOMAP);
CVAR (Flag, sv_noautomapallies, dmflags2, DF2_NO_AUTOMAP_ALLIES);
CVAR (Flag, sv_disallowspying, dmflags2, DF2_DISALLOW_SPYING);
CVAR (Flag, sv_chasecam, dmflags2, DF2_CHASECAM);
CVAR (Flag, sv_disallowsuicide, dmflags2, DF2_NOSUICIDE);
CVAR (Flag, sv_noautoaim, dmflags2, DF2_NOAUTOAIM);
//==========================================================================
//

View file

@ -370,11 +370,17 @@ void D_SetupUserInfo ()
}
if (autoaim > 35.f || autoaim < 0.f)
{
coninfo->aimdist = ANGLE_1*35;
if (dmflags & DF2_NOAUTOAIM)
coninfo->savedaimdist = ANGLE_1*35;
else
coninfo->aimdist = ANGLE_1*35;
}
else
{
coninfo->aimdist = abs ((int)(autoaim * (float)ANGLE_1));
if (dmflags & DF2_NOAUTOAIM)
coninfo->savedaimdist = abs ((int)(autoaim * (float)ANGLE_1));
else
coninfo->aimdist = abs ((int)(autoaim * (float)ANGLE_1));
}
coninfo->color = color;
coninfo->skin = R_FindSkin (skin, 0);
@ -684,11 +690,17 @@ void D_ReadUserInfoStrings (int i, BYTE **stream, bool update)
angles = atof (value);
if (angles > 35.f || angles < 0.f)
{
info->aimdist = ANGLE_1*35;
if (dmflags & DF2_NOAUTOAIM)
info->savedaimdist = ANGLE_1*35;
else
info->aimdist = ANGLE_1*35;
}
else
{
info->aimdist = abs ((int)(angles * (float)ANGLE_1));
if (dmflags & DF2_NOAUTOAIM)
info->savedaimdist = abs ((int)(angles * (float)ANGLE_1));
else
info->aimdist = abs ((int)(angles * (float)ANGLE_1));
}
}
break;
@ -804,6 +816,8 @@ FArchive &operator<< (FArchive &arc, userinfo_t &info)
arc.Read (&info.netname, sizeof(info.netname));
}
arc << info.team << info.aimdist << info.color << info.skin << info.gender << info.neverswitch;
if (SaveVersion >= 1333) arc << info.savedaimdist;
else info.savedaimdist = info.aimdist;
return arc;
}

View file

@ -82,8 +82,9 @@ public:
virtual void TweakSpeeds (int &forwardmove, int &sidemove);
virtual void MorphPlayerThink ();
virtual void ActivateMorphWeapon ();
virtual AWeapon *PickNewWeapon (const PClass *ammotype);
virtual AWeapon *BestWeapon (const PClass *ammotype);
AWeapon *PickNewWeapon (const PClass *ammotype);
AWeapon *BestWeapon (const PClass *ammotype);
void CheckWeaponSwitch(const PClass *ammotype);
virtual void GiveDeathmatchInventory ();
virtual void FilterCoopRespawnInventory (APlayerPawn *oldplayer);
@ -196,6 +197,7 @@ struct userinfo_t
{
char netname[MAXPLAYERNAME+1];
BYTE team;
int savedaimdist;
int aimdist;
int color;
int skin;

View file

@ -243,12 +243,17 @@ enum
DF2_YES_RESPAWN_INVUL = 1 << 10, // Player is temporarily invulnerable when respawned
// DF2_COOP_SHOTGUNSTART = 1 << 11, // All playres start with a shotgun when they respawn
DF2_SAME_SPAWN_SPOT = 1 << 12, // Players respawn in the same place they died (co-op)
DF2_YES_KEEPFRAGS = 1 << 13, // Don't clear frags after each level
DF2_NO_RESPAWN = 1 << 14, // Player cannot respawn
DF2_YES_LOSEFRAG = 1 << 15, // Lose a frag when killed. More incentive to try to
// // not get yerself killed
DF2_YES_LOSEFRAG = 1 << 15, // Lose a frag when killed. More incentive to try to not get yerself killed
DF2_INFINITE_INVENTORY = 1 << 16, // Infinite inventory.
DF2_KILL_MONSTERS = 1 << 17, // All monsters must be killed before the level exits.
DF2_NO_AUTOMAP = 1 << 18, // Players are allowed to see the automap.
DF2_NO_AUTOMAP_ALLIES = 1 << 19, // Allies can been seen on the automap.
DF2_DISALLOW_SPYING = 1 << 20, // You can spy on your allies.
DF2_CHASECAM = 1 << 21, // Players can use the chasecam cheat.
DF2_NOSUICIDE = 1 << 22, // Players are allowed to suicide.
DF2_NOAUTOAIM = 1 << 23, // Players cannot use autoaim.
};
// [RH] Compatibility flags.

View file

@ -724,6 +724,10 @@ static void ChangeSpy (bool forward)
return;
}
// We may not be allowed to spy on anyone.
if (dmflags2 & DF2_DISALLOW_SPYING)
return;
// Otherwise, cycle to the next player.
bool checkTeam = !demoplayback && deathmatch;
int pnum = players[consoleplayer].camera->player - players;

View file

@ -96,18 +96,9 @@ bool AAmmo::HandlePickup (AInventory *item)
assert (Owner != NULL);
if (oldamount == 0 && Owner != NULL && Owner->player != NULL &&
!Owner->player->userinfo.neverswitch &&
Owner->player->PendingWeapon == WP_NOCHANGE &&
(Owner->player->ReadyWeapon == NULL ||
(Owner->player->ReadyWeapon->WeaponFlags & WIF_WIMPY_WEAPON)))
if (oldamount == 0 && Owner != NULL && Owner->player != NULL)
{
AWeapon *best = barrier_cast<APlayerPawn *>(Owner)->BestWeapon (GetClass());
if (best != NULL && (Owner->player->ReadyWeapon == NULL ||
best->SelectionOrder < Owner->player->ReadyWeapon->SelectionOrder))
{
Owner->player->PendingWeapon = best;
}
barrier_cast<APlayerPawn *>(Owner)->CheckWeaponSwitch(GetClass());
}
}
return true;

View file

@ -129,7 +129,7 @@ struct FSpotList
ASpecialSpot *GetNextInList(int skipcounter)
{
if (++SkipCount > skipcounter)
if (Spots.Size() > 0 && ++SkipCount > skipcounter)
{
SkipCount = 0;

View file

@ -158,8 +158,17 @@ bool AWeapon::PickupForAmmo (AWeapon *ownedWeapon)
// Don't take ammo if the weapon sticks around.
if (!ShouldStay ())
{
int oldamount = 0;
if (ownedWeapon->Ammo1 != NULL) oldamount = ownedWeapon->Ammo1->Amount;
if (AmmoGive1 > 0) gotstuff = AddExistingAmmo (ownedWeapon->Ammo1, AmmoGive1);
if (AmmoGive2 > 0) gotstuff |= AddExistingAmmo (ownedWeapon->Ammo2, AmmoGive2);
AActor *Owner = ownedWeapon->Owner;
if (gotstuff && oldamount == 0 && Owner != NULL && Owner->player != NULL)
{
static_cast<APlayerPawn *>(Owner)->CheckWeaponSwitch(ownedWeapon->Ammo1->GetClass());
}
}
return gotstuff;
}

View file

@ -151,7 +151,7 @@ static void AddLine (seg_t *seg,sector_t * sector,subsector_t * polysub)
SetupWall.Clock();
wall.Process(seg, sector, backsector, polysub);
wall.Process(seg, sector, backsector, polysub, gl_render_segs);
rendered_lines++;
SetupWall.Unclock();

View file

@ -727,7 +727,6 @@ void gl_PreprocessLevel()
vt->vt = vtx;
}
}
gl_CollectMissingLines();
gl_InitVertexData();
gl_CreateSections();

View file

@ -806,6 +806,7 @@ static int __cdecl dicmp (const void *a, const void *b)
case GLDIT_POLY: break;
}
}
if (lights[0]!=lights[1]) return lights[0]-lights[1];
if (tx[0]!=tx[1]) return tx[0]-tx[1];
/*if (lights[0]!=lights[1])*/ return lights[0]-lights[1];
}

View file

@ -254,6 +254,7 @@ sector_t * gl_FakeFlat(sector_t * sec, sector_t * dest, bool back)
#endif
#endif
area_t in_area = ::in_area;
if (in_area==area_above)
{

View file

@ -131,11 +131,6 @@ angle_t gl_FrustumAngle();
void gl_LinkLights();
// ZDBSP shittiness compensation
void gl_CollectMissingLines();
void gl_RenderMissingLines();
void gl_SetActorLights(AActor *);
void gl_DeleteAllAttachedLights();
void gl_RecreateAllAttachedLights();

225
src/gl/gl_hqresize.cpp Normal file
View file

@ -0,0 +1,225 @@
/*
** gl_hqresize.cpp
** Contains high quality upsampling functions.
** So far Scale2x/3x/4x as described in http://scale2x.sourceforge.net/
** are implemented.
**
**---------------------------------------------------------------------------
** Copyright 2008 Benjamin Berkels
** All rights reserved.
**
** Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions
** are met:
**
** 1. Redistributions of source code must retain the above copyright
** notice, this list of conditions and the following disclaimer.
** 2. Redistributions in binary form must reproduce the above copyright
** notice, this list of conditions and the following disclaimer in the
** documentation and/or other materials provided with the distribution.
** 3. The name of the author may not be used to endorse or promote products
** derived from this software without specific prior written permission.
**
** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
**---------------------------------------------------------------------------
**
*/
#include "gl_hqresize.h"
#include "c_cvars.h"
CUSTOM_CVAR(Int, gl_texture_hqresize, 0, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_NOINITCALL)
{
if (self < 0 || self > 3) self = 0;
FGLTexture::FlushAll();
}
CUSTOM_CVAR(Int, gl_texture_hqresize_maxinputsize, 512, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_NOINITCALL)
{
if (self > 1024) self = 1024;
FGLTexture::FlushAll();
}
CUSTOM_CVAR(Int, gl_texture_hqresize_targets, 7, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_NOINITCALL)
{
FGLTexture::FlushAll();
}
CVAR (Flag, gl_texture_hqresize_textures, gl_texture_hqresize_targets, 1);
CVAR (Flag, gl_texture_hqresize_sprites, gl_texture_hqresize_targets, 2);
CVAR (Flag, gl_texture_hqresize_fonts, gl_texture_hqresize_targets, 4);
static void scale2x ( uint32* inputBuffer, uint32* outputBuffer, int inWidth, int inHeight )
{
const int width = 2* inWidth;
const int height = 2 * inHeight;
for ( int i = 0; i < inWidth; ++i )
{
const int iMinus = (i > 0) ? (i-1) : 0;
const int iPlus = (i < inWidth - 1 ) ? (i+1) : i;
for ( int j = 0; j < inHeight; ++j )
{
const int jMinus = (j > 0) ? (j-1) : 0;
const int jPlus = (j < inHeight - 1 ) ? (j+1) : j;
const uint32 A = inputBuffer[ iMinus +inWidth*jMinus];
const uint32 B = inputBuffer[ iMinus +inWidth*j ];
const uint32 C = inputBuffer[ iMinus +inWidth*jPlus];
const uint32 D = inputBuffer[ i +inWidth*jMinus];
const uint32 E = inputBuffer[ i +inWidth*j ];
const uint32 F = inputBuffer[ i +inWidth*jPlus];
const uint32 G = inputBuffer[ iPlus +inWidth*jMinus];
const uint32 H = inputBuffer[ iPlus +inWidth*j ];
const uint32 I = inputBuffer[ iPlus +inWidth*jPlus];
if (B != H && D != F) {
outputBuffer[2*i + width*2*j ] = D == B ? D : E;
outputBuffer[2*i + width*(2*j+1)] = B == F ? F : E;
outputBuffer[2*i+1 + width*2*j ] = D == H ? D : E;
outputBuffer[2*i+1 + width*(2*j+1)] = H == F ? F : E;
} else {
outputBuffer[2*i + width*2*j ] = E;
outputBuffer[2*i + width*(2*j+1)] = E;
outputBuffer[2*i+1 + width*2*j ] = E;
outputBuffer[2*i+1 + width*(2*j+1)] = E;
}
}
}
}
static void scale3x ( uint32* inputBuffer, uint32* outputBuffer, int inWidth, int inHeight )
{
const int width = 3* inWidth;
const int height = 3 * inHeight;
for ( int i = 0; i < inWidth; ++i )
{
const int iMinus = (i > 0) ? (i-1) : 0;
const int iPlus = (i < inWidth - 1 ) ? (i+1) : i;
for ( int j = 0; j < inHeight; ++j )
{
const int jMinus = (j > 0) ? (j-1) : 0;
const int jPlus = (j < inHeight - 1 ) ? (j+1) : j;
const uint32 A = inputBuffer[ iMinus +inWidth*jMinus];
const uint32 B = inputBuffer[ iMinus +inWidth*j ];
const uint32 C = inputBuffer[ iMinus +inWidth*jPlus];
const uint32 D = inputBuffer[ i +inWidth*jMinus];
const uint32 E = inputBuffer[ i +inWidth*j ];
const uint32 F = inputBuffer[ i +inWidth*jPlus];
const uint32 G = inputBuffer[ iPlus +inWidth*jMinus];
const uint32 H = inputBuffer[ iPlus +inWidth*j ];
const uint32 I = inputBuffer[ iPlus +inWidth*jPlus];
if (B != H && D != F) {
outputBuffer[3*i + width*3*j ] = D == B ? D : E;
outputBuffer[3*i + width*(3*j+1)] = (D == B && E != C) || (B == F && E != A) ? B : E;
outputBuffer[3*i + width*(3*j+2)] = B == F ? F : E;
outputBuffer[3*i+1 + width*3*j ] = (D == B && E != G) || (D == H && E != A) ? D : E;
outputBuffer[3*i+1 + width*(3*j+1)] = E;
outputBuffer[3*i+1 + width*(3*j+2)] = (B == F && E != I) || (H == F && E != C) ? F : E;
outputBuffer[3*i+2 + width*3*j ] = D == H ? D : E;
outputBuffer[3*i+2 + width*(3*j+1)] = (D == H && E != I) || (H == F && E != G) ? H : E;
outputBuffer[3*i+2 + width*(3*j+2)] = H == F ? F : E;
} else {
outputBuffer[3*i + width*3*j ] = E;
outputBuffer[3*i + width*(3*j+1)] = E;
outputBuffer[3*i + width*(3*j+2)] = E;
outputBuffer[3*i+1 + width*3*j ] = E;
outputBuffer[3*i+1 + width*(3*j+1)] = E;
outputBuffer[3*i+1 + width*(3*j+2)] = E;
outputBuffer[3*i+2 + width*3*j ] = E;
outputBuffer[3*i+2 + width*(3*j+1)] = E;
outputBuffer[3*i+2 + width*(3*j+2)] = E;
}
}
}
}
static void scale4x ( uint32* inputBuffer, uint32* outputBuffer, int inWidth, int inHeight )
{
int width = 2* inWidth;
int height = 2 * inHeight;
uint32 * buffer2x = new uint32[width*height];
scale2x ( reinterpret_cast<uint32*> ( inputBuffer ), reinterpret_cast<uint32*> ( buffer2x ), inWidth, inHeight );
width *= 2;
height *= 2;
scale2x ( reinterpret_cast<uint32*> ( buffer2x ), reinterpret_cast<uint32*> ( outputBuffer ), 2*inWidth, 2*inHeight );
delete[] buffer2x;
}
static unsigned char *scaleNxHelper( void (*scaleNxFunction) ( uint32* , uint32* , int , int),
const int N,
unsigned char *inputBuffer,
const int inWidth,
const int inHeight,
int &outWidth,
int &outHeight )
{
outWidth = N * inWidth;
outHeight = N *inHeight;
unsigned char * newBuffer = new unsigned char[outWidth*outHeight*4];
scaleNxFunction ( reinterpret_cast<uint32*> ( inputBuffer ), reinterpret_cast<uint32*> ( newBuffer ), inWidth, inHeight );
delete[] inputBuffer;
return newBuffer;
}
//===========================================================================
//
// [BB] Upsamples the texture in inputBuffer, frees inputBuffer and returns
// the upsampled buffer.
//
//===========================================================================
unsigned char *gl_CreateUpsampledTextureBuffer ( const FGLTexture *inputGLTexture, unsigned char *inputBuffer, const int inWidth, const int inHeight, int &outWidth, int &outHeight )
{
// [BB] Don't resample if the width or height of the input texture is bigger than gl_texture_hqresize_maxinputsize.
if ( ( inWidth > gl_texture_hqresize_maxinputsize ) || ( inHeight > gl_texture_hqresize_maxinputsize ) )
return inputBuffer;
// [BB] The hqnx upsampling (not the scaleN one) destroys partial transparency, don't upsamle textures using it.
if ( inputGLTexture->bIsTransparent == 1 )
return inputBuffer;
switch (inputGLTexture->tex->UseType)
{
case FTexture::TEX_Sprite:
case FTexture::TEX_SkinSprite:
if (!(gl_texture_hqresize_targets & 2)) return inputBuffer;
break;
case FTexture::TEX_FontChar:
if (!(gl_texture_hqresize_targets & 4)) return inputBuffer;
break;
default:
if (!(gl_texture_hqresize_targets & 1)) return inputBuffer;
break;
}
if (inputBuffer)
{
outWidth = inWidth;
outHeight = inHeight;
int type = gl_texture_hqresize;
switch (type)
{
case 1:
return scaleNxHelper( &scale2x, 2, inputBuffer, inWidth, inHeight, outWidth, outHeight );
case 2:
return scaleNxHelper( &scale3x, 3, inputBuffer, inWidth, inHeight, outWidth, outHeight );
case 3:
return scaleNxHelper( &scale4x, 4, inputBuffer, inWidth, inHeight, outWidth, outHeight );
}
}
return inputBuffer;
}

43
src/gl/gl_hqresize.h Normal file
View file

@ -0,0 +1,43 @@
/*
** gl_hqresize.h
** Contains high quality upsampling functions.
**
**---------------------------------------------------------------------------
** Copyright 2008 Benjamin Berkels
** All rights reserved.
**
** Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions
** are met:
**
** 1. Redistributions of source code must retain the above copyright
** notice, this list of conditions and the following disclaimer.
** 2. Redistributions in binary form must reproduce the above copyright
** notice, this list of conditions and the following disclaimer in the
** documentation and/or other materials provided with the distribution.
** 3. The name of the author may not be used to endorse or promote products
** derived from this software without specific prior written permission.
**
** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
**---------------------------------------------------------------------------
**
*/
#ifndef __GL_HQRESIZE_H__
#define __GL_HQRESIZE_H__
#include "gl_texture.h"
unsigned char *gl_CreateUpsampledTextureBuffer ( const FGLTexture *inputGLTexture, unsigned char *inputBuffer, const int inWidth, const int inHeight, int &outWidth, int &outHeight );
#endif // __GL_HQRESIZE_H__

View file

@ -39,6 +39,10 @@ EXTERN_CVAR (Bool, gl_lights_additive)
EXTERN_CVAR (Float, gl_light_ambient)
EXTERN_CVAR(Int, gl_billboard_mode)
EXTERN_CVAR(Int, gl_particles_style)
EXTERN_CVAR(Int, gl_texture_hqresize)
EXTERN_CVAR(Flag, gl_texture_hqresize_textures)
EXTERN_CVAR(Flag, gl_texture_hqresize_sprites)
EXTERN_CVAR(Flag, gl_texture_hqresize_fonts)
static value_t SpriteclipModes[]=
{
@ -133,6 +137,20 @@ static value_t Particles[] =
{ 2.0, "Smooth" },
};
static value_t HqResizeModes[] =
{
{ 0.0, "Off" },
{ 1.0, "Scale2x" },
{ 2.0, "Scale3x" },
{ 3.0, "Scale4x" },
};
static value_t HqResizeTargets[] =
{
{ 0.0, "Everything" },
{ 1.0, "Sprites/fonts" },
};
static value_t FogMode[] =
{
{ 0.0, "Off" },
@ -168,6 +186,10 @@ menuitem_t GLTextureItems[] = {
{ discrete, "Anisotropic filter", {&gl_texture_filter_anisotropic},{5.0},{0.0}, {0.0}, {Anisotropy} },
{ discrete, "Texture Format", {&gl_texture_format}, {8.0}, {0.0}, {0.0}, {TextureFormats} },
{ discrete, "Enable hires textures", {&gl_texture_usehires}, {2.0}, {0.0}, {0.0}, {YesNo} },
{ discrete, "High Quality Resize mode", {&gl_texture_hqresize}, {4.0}, {0.0}, {0.0}, {HqResizeModes} },
{ discrete, "Resize textures", {&gl_texture_hqresize_textures},{2.0}, {0.0}, {0.0}, {OnOff} },
{ discrete, "Resize sprites", {&gl_texture_hqresize_sprites}, {2.0}, {0.0}, {0.0}, {OnOff} },
{ discrete, "Resize fonts", {&gl_texture_hqresize_fonts}, {2.0}, {0.0}, {0.0}, {OnOff} },
{ discrete, "Precache GL textures", {&gl_precache}, {2.0}, {0.0}, {0.0}, {YesNo} },
};

View file

@ -1,239 +0,0 @@
/*
** gl_missinglines.cpp
** This mess is only needed because ZDBSP likes to throw out lines
** out of the BSP if they overlap
**
**---------------------------------------------------------------------------
** Copyright 2005 Christoph Oelckers
** All rights reserved.
**
** Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions
** are met:
**
** 1. Redistributions of source code must retain the above copyright
** notice, this list of conditions and the following disclaimer.
** 2. Redistributions in binary form must reproduce the above copyright
** notice, this list of conditions and the following disclaimer in the
** documentation and/or other materials provided with the distribution.
** 3. The name of the author may not be used to endorse or promote products
** derived from this software without specific prior written permission.
** 4. When not used as part of GZDoom or a GZDoom derivative, this code will be
** covered by the terms of the GNU Lesser General Public License as published
** by the Free Software Foundation; either version 2.1 of the License, or (at
** your option) any later version.
** 5. Full disclosure of the entire project's source code, except for third
** party libraries is mandatory. (NOTE: This clause is non-negotiable!)
**
** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
**---------------------------------------------------------------------------
**
*/
#include "gl/gl_include.h"
#include "p_local.h"
#include "gl/gl_struct.h"
#include "gl/gl_renderstruct.h"
#include "gl/gl_glow.h"
#include "gl/gl_data.h"
#include "gl/gl_basic.h"
#include "gl/gl_functions.h"
#include "gl/gl_geometric.h"
static seg_t * compareseg;
int firstmissingseg;
static int STACK_ARGS segcmp(const void * a, const void * b)
{
seg_t * seg1 = *((seg_t**)a);
seg_t * seg2 = *((seg_t**)b);
return
P_AproxDistance(seg2->v1->x - compareseg->v1->x, seg2->v1->y - compareseg->v1->y) -
P_AproxDistance(seg1->v1->x - compareseg->v1->x, seg1->v1->y - compareseg->v1->y);
//return (seg2->v1 - compareseg->v1).LengthSquared() - (seg1->v1 - compareseg->v1).LengthSquared();
}
//==========================================================================
//
// Collect all sidedefs which are not entirely covered by segs
//
// (Sigh! Why do I have to compensate for ZDBSP's shortcomings...)
//
//==========================================================================
void gl_CollectMissingLines()
{
firstmissingseg=numsegs;
TArray<seg_t> MissingSides;
TArray<seg_t*> * linesegs = new TArray<seg_t*>[numsides];
float * added_seglen = new float[numsides];
memset(added_seglen, 0, sizeof(float)*numsides);
for(int i=0;i<numsegs;i++)
{
seg_t * seg = &segs[i];
if (seg->sidedef!=NULL)
{
// collect all the segs and calculate the length they occupy on their sidedef
//added_seglen[seg->linedef-lines + side]+= (*seg->v2 - *seg->v1).Length();
#ifdef _MSC_VER
added_seglen[seg->sidedef - sides]+= (Vector(seg->v2)-Vector(seg->v1)).Length();
#else
Vector vec1(Vector(seg->v1));
Vector vec2(Vector(seg->v2));
Vector tmpVec = vec2-vec1;
added_seglen[seg->sidedef - sides]+= tmpVec.Length();
#endif
linesegs[seg->sidedef - sides].Push(seg);
}
}
MissingSides.Clear();
for(int i=0;i<numsides;i++)
{
side_t * side =&sides[i];
line_t * line = &lines[side->linenum];
//float linelen = (*line->v2 - *line->v1).Length();
#ifdef _MSC_VER
float linelen = (Vector(line->v2)-Vector(line->v1)).Length();
#else
Vector vec1(Vector(line->v1));
Vector vec2(Vector(line->v2));
Vector tmpVec = (vec2-vec1);
float linelen = tmpVec.Length();
#endif
if (added_seglen[i] < linelen -1)
{
Printf("Sidedef %d (linedef %d) incomplete (Length = %f of %f)\n",
i,side->linenum, added_seglen[i], linelen);
// create a seg for the sidedef
seg_t seg;
seg.sidedef = side;
seg.linedef = line;
if (side == &sides[line->sidenum[0]])
{
seg.v1 = line->v1;
seg.v2 = line->v2;
seg.frontsector = line->frontsector;
seg.backsector = line->backsector;
}
else
{
seg.v2 = line->v1;
seg.v1 = line->v2;
seg.backsector = line->frontsector;
seg.frontsector = line->backsector;
}
seg.Subsector = NULL;
seg.PartnerSeg=NULL;
seg.bPolySeg=false;
if (linesegs[i].Size()!=0)
{
// There are already segs for this line so
// we have to fill in the gaps. To make polyobject
// spawning possible the sidedef has do be properly
// split into segs that span its entire length
compareseg = &seg;
// Sort the segs so inserting new ones becomes easier
qsort(&linesegs[i][0], linesegs[i].Size(), sizeof(seg_t*), segcmp);
for(unsigned int j=0;j<linesegs[i].Size();j++)
{
if (linesegs[i][j]->v1 != seg.v1)
{
seg_t newseg = seg;
newseg.v2 = linesegs[i][j]->v1;
MissingSides.Push(newseg);
}
seg.v1 = linesegs[i][j]->v2;
}
}
if (seg.v1!=seg.v2)
{
MissingSides.Push(seg);
}
}
}
if (MissingSides.Size())
{
// Now we have to add the newly created segs to the segs array so
// that the polyobject spawn code has access to them.
seg_t * newsegs = new seg_t[numsegs + MissingSides.Size()];
memcpy(newsegs, segs, sizeof(seg_t) * numsegs);
memcpy(newsegs+numsegs, &MissingSides[0], sizeof(seg_t)*MissingSides.Size());
for(int i = 0; i < numsegs; i++)
{
if (newsegs[i].PartnerSeg && newsegs[i].PartnerSeg>=segs && newsegs[i].PartnerSeg<segs+numsegs)
newsegs[i].PartnerSeg = newsegs + (newsegs[i].PartnerSeg - segs);
else newsegs[i].PartnerSeg=NULL;
}
numsegs += MissingSides.Size();
delete [] segs;
segs=newsegs;
Printf("%d missing segs counted\n", MissingSides.Size());
}
delete [] linesegs;
delete [] added_seglen;
}
//==========================================================================
//
// Render those lines
//
//==========================================================================
void gl_RenderMissingLines()
{
for(int i=firstmissingseg;i<numsegs;i++)
{
seg_t * seg = &segs[i];
// This line has already been processed
if (seg->linedef->validcount==validcount) continue;
// Don't draw lines facing away from the viewer
divline_t dl = { seg->v1->x, seg->v1->y, seg->v2->x-seg->v1->x, seg->v2->y-seg->v1->y };
if (P_PointOnDivlineSide(viewx, viewy, &dl)) continue;
// Unfortunately there is no simple means to exclude lines here so we have
// to draw them all.
sector_t ffakesec, bfakesec;
sector_t * sector = gl_FakeFlat(seg->frontsector, &ffakesec, false);
sector_t * backsector;
if (seg->frontsector == seg->backsector) backsector=sector;
else if (!seg->backsector) backsector=NULL;
else backsector = gl_FakeFlat(seg->backsector, &bfakesec, true);
GLWall wall;
SetupWall.Clock();
wall.Process(seg, sector, backsector, NULL);
rendered_lines++;
SetupWall.Unclock();
}
}

View file

@ -55,7 +55,6 @@
// This is for debugging maps.
CVAR(Bool, gl_notexturefill, false, 0);
extern int firstmissingseg;
FreeList<gl_subsectorrendernode> SSR_List;
@ -939,7 +938,7 @@ ADD_STAT(missingtextures)
void GLDrawInfo::AddHackedSubsector(subsector_t * sub)
{
if (firstmissingseg==numsegs && !(level.flags & LEVEL_HEXENFORMAT))
if (!(level.flags & LEVEL_HEXENFORMAT))
{
SubsectorHackInfo sh={sub, 0};
SubsectorHacks.Push (sh);

View file

@ -57,6 +57,7 @@
#include "doomerrors.h"
#include "p_setup.h"
#include "x86.h"
#include "version.h"
node_t * gamenodes;
int numgamenodes;
@ -108,6 +109,49 @@ typedef struct
} gl5_mapnode_t;
#define GL5_NF_SUBSECTOR (1 << 31)
//==========================================================================
//
// Collect all sidedefs which are not entirely covered by segs
// Old ZDBSPs could create such maps. If such a BSP is discovered
// a node rebuild must be done to ensure proper rendering
//
//==========================================================================
int gl_CheckForMissingSegs()
{
float *added_seglen = new float[numsides];
int missing = 0;
memset(added_seglen, 0, sizeof(float)*numsides);
for(int i=0;i<numsegs;i++)
{
seg_t * seg = &segs[i];
if (seg->sidedef!=NULL)
{
// check all the segs and calculate the length they occupy on their sidedef
TVector2<double> vec1(seg->v2->x - seg->v1->x, seg->v2->y - seg->v1->y);
added_seglen[seg->sidedef - sides] += float(vec1.Length());
}
}
for(int i=0;i<numsides;i++)
{
side_t * side =&sides[i];
line_t * line = &lines[side->linenum];
TVector2<double> lvec(line->dx, line->dy);
float linelen = float(lvec.Length());
missing += (added_seglen[i] < linelen - 1);
}
delete [] added_seglen;
return missing;
}
//==========================================================================
//
// Checks whether the nodes are suitable for GL rendering
@ -144,7 +188,13 @@ bool gl_CheckForGLNodes()
}
// all subsectors were closed but there are no minisegs
// Although unlikely this can happen. Such nodes are not a problem.
return true;
// all that is left is to check whether the BSP covers all sidedefs completely.
int missing = gl_CheckForMissingSegs();
if (missing > 0)
{
Printf("%d missing segs counted\nThe BSP needs to be rebuilt", missing);
}
return missing == 0;
}
@ -186,7 +236,7 @@ static bool gl_LoadVertexes(FileReader * f, wadlump_t * lump)
// GLNodes V1 and V4 are unsupported.
// V1 because the precision is insufficient and
// V4 due to the missing partner segs
Printf("GL nodes v%d found. This format is not supported by GZDoom\n",
Printf("GL nodes v%d found. This format is not supported by "GAMENAME"\n",
(*(int *)gldata == gNd4)? 4:1);
delete [] gldata;
@ -256,7 +306,9 @@ bool gl_LoadGLSegs(FileReader * f, wadlump_t * lump)
f->Read(data, lump->Size);
segs=NULL;
try
#ifdef _MSC_VER
__try
#endif
{
if (!format5 && memcmp(data, "gNd3", 4))
{
@ -346,16 +398,19 @@ bool gl_LoadGLSegs(FileReader * f, wadlump_t * lump)
delete [] data;
return true;
}
catch(...)
#ifdef _MSC_VER
__except(1)
{
// Invalid data has the bas habit of requiring extensive checks here
// so let's just catch anything invalid and output a message.
// (at least under MSVC. GCC can't do SEH even for Windows... :( )
Printf("Invalid GL segs. The BSP will have to be rebuilt.\n");
delete [] data;
delete [] segs;
segs = NULL;
return false;
}
#endif
}
@ -612,7 +667,7 @@ bool gl_DoLoadGLNodes(FileReader * f, wadlump_t * lumps)
seg_t * seg = &segs[subsectors[i].firstline];
if (!seg->sidedef)
{
Printf("GWA file contains invalid nodes. The BSP has to be rebuilt.\n");
Printf("GL nodes contain invalid data. The BSP has to be rebuilt.\n");
delete [] nodes;
nodes = NULL;
delete [] subsectors;
@ -622,7 +677,14 @@ bool gl_DoLoadGLNodes(FileReader * f, wadlump_t * lumps)
return false;
}
}
return true;
// check whether the BSP covers all sidedefs completely.
int missing = gl_CheckForMissingSegs();
if (missing > 0)
{
Printf("%d missing segs counted in GL nodes.\nThe BSP has to be rebuilt", missing);
}
return missing == 0;
}
@ -898,5 +960,4 @@ void gl_CheckNodes(MapData * map)
gamesubsectors = subsectors;
numgamesubsectors = numsubsectors;
}
}

View file

@ -247,7 +247,7 @@ private:
public:
void Process(seg_t *seg, sector_t * frontsector, sector_t * backsector, subsector_t * polysub);
void Process(seg_t *seg, sector_t * frontsector, sector_t * backsector, subsector_t * polysub, bool render_segs);
void ProcessLowerMiniseg(seg_t *seg, sector_t * frontsector, sector_t * backsector);
void Draw(int pass);

View file

@ -342,7 +342,6 @@ static void ProcessScene()
// And now the crappy hacks that have to be done to avoid rendering anomalies:
gl_RenderMissingLines(); // Omitted lines by the node builder
gl_drawinfo->HandleMissingTextures(); // Missing upper/lower textures
gl_drawinfo->HandleHackedSubsectors(); // open sector hacks for deep water
gl_drawinfo->ProcessSectorStacks(); // merge visplanes of sector stacks

View file

@ -163,6 +163,8 @@ public:
line.sidedef = seg->sidedef;
line.linedef = seg->linedef;
line.refseg = seg;
line.polysub = NULL;
line.otherside = -1;
if (loop->numlines == 0)
{

View file

@ -625,7 +625,7 @@ void GLShader::Bind(int cm, int lightmode, float Speed)
void GLShader::Unbind()
{
if (gl.flags & RFL_GLSL)
if ((gl.flags & RFL_GLSL) && gl_activeShader != NULL)
{
gl.UseProgramObjectARB(0);
gl_activeShader=NULL;

View file

@ -159,11 +159,9 @@ struct FGLSectionLine
vertex_t *end;
side_t *sidedef;
line_t *linedef;
union
{
int otherside;
seg_t *refseg;
};
seg_t *refseg; // we need to reference at least one seg for each line.
subsector_t *polysub; // If this is part of a polyobject we need a reference to the containing subsector
int otherside;
};
struct FGLSectionLoop

View file

@ -59,6 +59,7 @@
#include "gl/gl_functions.h"
#include "gl/gl_shader.h"
#include "gl/gl_translate.h"
#include "gl/gl_hqresize.h"
CUSTOM_CVAR(Bool, gl_texture_usehires, true, CVAR_ARCHIVE|CVAR_NOINITCALL)
{
@ -1164,6 +1165,9 @@ unsigned char * FGLTexture::CreateTexBuffer(ETexUse use, int _cm, int translatio
tex->FTexture::CopyTrueColorPixels(&bmp, GetLeftOffset(use) - tex->LeftOffset, GetTopOffset(use) - tex->TopOffset);
}
// [BB] Potentially upsample the buffer.
buffer = gl_CreateUpsampledTextureBuffer ( this, buffer, W, H, w, h );
if ((!(gl.flags & RFL_GLSL) || !gl_warp_shader) && tex->bWarped && W <= 256 && H <= 256)
{
buffer = WarpBuffer(buffer, W, H, tex->bWarped);
@ -1209,7 +1213,7 @@ const PatchTextureInfo * FGLTexture::GetPatchTextureInfo()
//===========================================================================
//
// Checls if a shader needs to be used for this texture
// Checks if a shader needs to be used for this texture
//
//===========================================================================

View file

@ -1364,7 +1364,7 @@ void GLWall::DoFFloorBlocks(seg_t * seg,sector_t * frontsector,sector_t * backse
//
//
//==========================================================================
void GLWall::Process(seg_t *seg, sector_t * frontsector, sector_t * backsector, subsector_t * polysub)
void GLWall::Process(seg_t *seg, sector_t * frontsector, sector_t * backsector, subsector_t * polysub, bool render_segs)
{
vertex_t * v1, * v2;
fixed_t fch1;
@ -1410,7 +1410,7 @@ void GLWall::Process(seg_t *seg, sector_t * frontsector, sector_t * backsector,
glseg.fracleft=0;
glseg.fracright=1;
if (gl_render_segs)
if (render_segs)
{
if (abs(v1->x-v2->x) > abs(v1->y-v2->y))
{

View file

@ -267,6 +267,8 @@ static FSaveGameNode NewSaveNode;
static int epi; // Selected episode
static const char *saved_playerclass = NULL;
// PRIVATE MENU DEFINITIONS ------------------------------------------------
//
@ -1821,15 +1823,18 @@ void M_Episode (int choice)
if (AllSkills.Size() == 1)
{
saved_playerclass = NULL;
M_ChooseSkill(0);
return;
}
else if (EpisodeNoSkill[choice])
{
saved_playerclass = NULL;
M_ChooseSkill(AllSkills.Size() == 2? 1:2);
return;
}
M_StartupSkillMenu(NULL);
M_StartupSkillMenu(saved_playerclass);
saved_playerclass = NULL;
}
//==========================================================================
@ -1856,6 +1861,7 @@ static void SCClass (int option)
if (EpiDef.numitems > 1)
{
saved_playerclass = playerclass;
M_SetupNextMenu (&EpiDef);
}
else if (AllSkills.Size() == 1)
@ -1888,6 +1894,7 @@ static void M_ChooseClass (int choice)
if (EpiDef.numitems > 1)
{
saved_playerclass = playerclass;
M_SetupNextMenu (&EpiDef);
}
else if (AllSkills.Size() == 1)

View file

@ -1044,17 +1044,25 @@ static menuitem_t DMFlagsItems[] = {
{ bitflag, "Infinite ammo", {&dmflags}, {0}, {0}, {0}, {(value_t *)DF_INFINITE_AMMO} },
{ bitflag, "Infinite inventory", {&dmflags2}, {0}, {0}, {0}, {(value_t *)DF2_INFINITE_INVENTORY} },
{ bitflag, "No monsters", {&dmflags}, {0}, {0}, {0}, {(value_t *)DF_NO_MONSTERS} },
{ bitflag, "No monsters to exit", {&dmflags2}, {0}, {0}, {0}, {(value_t *)DF2_KILL_MONSTERS} },
{ bitflag, "Monsters respawn", {&dmflags}, {0}, {0}, {0}, {(value_t *)DF_MONSTERS_RESPAWN} },
{ bitflag, "No respawn", {&dmflags2}, {0}, {0}, {0}, {(value_t *)DF2_NO_RESPAWN} },
{ bitflag, "Items respawn", {&dmflags}, {0}, {0}, {0}, {(value_t *)DF_ITEMS_RESPAWN} },
{ bitflag, "Big powerups respawn", {&dmflags}, {0}, {0}, {0}, {(value_t *)DF_RESPAWN_SUPER} },
{ bitflag, "Fast monsters", {&dmflags}, {0}, {0}, {0}, {(value_t *)DF_FAST_MONSTERS} },
{ bitflag, "Degeneration", {&dmflags2}, {0}, {0}, {0}, {(value_t *)DF2_YES_DEGENERATION} },
{ bitflag, "Allow Autoaim", {&dmflags2}, {1}, {0}, {0}, {(value_t *)DF2_NOAUTOAIM} },
{ bitflag, "Disallow Suicide", {&dmflags2}, {1}, {0}, {0}, {(value_t *)DF2_NOSUICIDE} },
{ bitmask, "Allow jump", {&dmflags}, {3.0}, {DF_NO_JUMP|DF_YES_JUMP}, {0}, {DF_Jump} },
{ bitmask, "Allow crouch", {&dmflags}, {3.0}, {DF_NO_CROUCH|DF_YES_CROUCH}, {0}, {DF_Crouch} },
{ bitflag, "Allow freelook", {&dmflags}, {1}, {0}, {0}, {(value_t *)DF_NO_FREELOOK} },
{ bitflag, "Allow FOV", {&dmflags}, {1}, {0}, {0}, {(value_t *)DF_NO_FOV} },
{ bitflag, "Allow BFG aiming", {&dmflags2}, {1}, {0}, {0}, {(value_t *)DF2_NO_FREEAIMBFG} },
{ bitflag, "Allow automap", {&dmflags2}, {1}, {0}, {0}, {(value_t *)DF2_NO_AUTOMAP} },
{ bitflag, "Automap allies", {&dmflags2}, {1}, {0}, {0}, {(value_t *)DF2_NO_AUTOMAP_ALLIES} },
{ bitflag, "Allow spying", {&dmflags2}, {1}, {0}, {0}, {(value_t *)DF2_DISALLOW_SPYING} },
{ bitflag, "Chasecam cheat", {&dmflags2}, {0}, {0}, {0}, {(value_t *)DF2_CHASECAM} },
{ redtext, " ", {NULL}, {0}, {0}, {0}, {NULL} },
{ whitetext,"Deathmatch Settings", {NULL}, {0}, {0}, {0}, {NULL} },
{ bitflag, "Weapons stay", {&dmflags}, {0}, {0}, {0}, {(value_t *)DF_WEAPONS_STAY} },

View file

@ -1451,6 +1451,10 @@ CCMD (kill)
}
else
{
// If suiciding is disabled, then don't do it.
if (dmflags2 & DF2_NOSUICIDE)
return;
// Kill the player
Net_WriteByte (DEM_SUICIDE);
}

View file

@ -135,6 +135,10 @@ bool CheckIfExitIsGood (AActor *self, level_info_t *info)
if (self == NULL)
return true;
// We must kill all monsters to exit the level.
if ((dmflags2 & DF2_KILL_MONSTERS) && level.killed_monsters != level.total_monsters)
return false;
// Is this a deathmatch game and we're not allowed to exit?
if ((deathmatch || alwaysapplydmflags) && (dmflags & DF_NO_EXIT))
{

View file

@ -686,6 +686,31 @@ AWeapon *APlayerPawn::PickNewWeapon (const PClass *ammotype)
return best;
}
//===========================================================================
//
// APlayerPawn :: CheckWeaponSwitch
//
// Checks if weapons should be changed after picking up ammo
//
//===========================================================================
void APlayerPawn::CheckWeaponSwitch(const PClass *ammotype)
{
if (!player->userinfo.neverswitch &&
player->PendingWeapon == WP_NOCHANGE &&
(player->ReadyWeapon == NULL ||
(player->ReadyWeapon->WeaponFlags & WIF_WIMPY_WEAPON)))
{
AWeapon *best = BestWeapon (ammotype);
if (best != NULL && (player->ReadyWeapon == NULL ||
best->SelectionOrder < player->ReadyWeapon->SelectionOrder))
{
player->PendingWeapon = best;
}
}
}
//===========================================================================
//
// APlayerPawn :: GiveDeathmatchInventory

View file

@ -3,5 +3,5 @@
// This file was automatically generated by the
// updaterevision tool. Do not edit by hand.
#define ZD_SVN_REVISION_STRING "1327"
#define ZD_SVN_REVISION_NUMBER 1327
#define ZD_SVN_REVISION_STRING "1333"
#define ZD_SVN_REVISION_NUMBER 1333

View file

@ -325,7 +325,14 @@ do_stop:
sc.ScriptError("Negative jump offsets are not allowed");
}
x = new FxStateByIndex(bag.statedef.GetStateCount() + v, sc);
if (x > 0)
{
x = new FxStateByIndex(bag.statedef.GetStateCount() + v, sc);
}
else
{
x = new FxConstant((FState*)NULL, sc);
}
}
else
{