diff --git a/src/d_player.h b/src/d_player.h index e944d6734..7f57837c7 100644 --- a/src/d_player.h +++ b/src/d_player.h @@ -168,6 +168,9 @@ public: // [CW] Fades for when you are being damaged. PalEntry DamageFade; + // [SP] ViewBob Multiplier + double ViewBob; + bool UpdateWaterLevel (bool splash); bool ResetAirSupply (bool playgasp = true); diff --git a/src/p_pspr.cpp b/src/p_pspr.cpp index e5b076acd..abbd2284e 100644 --- a/src/p_pspr.cpp +++ b/src/p_pspr.cpp @@ -582,8 +582,9 @@ void P_BobWeapon (player_t *player, float *x, float *y, double ticfrac) if (curbob != 0) { - float bobx = float(player->bob * Rangex); - float boby = float(player->bob * Rangey); + //[SP] Added in decorate player.viewbob checks + float bobx = float(player->bob * Rangex * (float)player->mo->ViewBob); + float boby = float(player->bob * Rangey * (float)player->mo->ViewBob); switch (bobstyle) { case AWeapon::BobNormal: diff --git a/src/p_saveg.cpp b/src/p_saveg.cpp index ce5b6a74a..59e83d9e7 100644 --- a/src/p_saveg.cpp +++ b/src/p_saveg.cpp @@ -640,6 +640,12 @@ static void ReadOnePlayer(FSerializer &arc, bool skipload) playerTemp.Serialize(arc); if (!skipload) { + // This temp player has undefined pitch limits, so set them to something + // that should leave the pitch stored in the savegame intact when + // rendering. The real pitch limits will be set by P_SerializePlayers() + // via a net command, but that won't be processed in time for a screen + // wipe, so we need something here. + playerTemp.MaxPitch = playerTemp.MinPitch = playerTemp.mo->Angles.Pitch; CopyPlayer(&players[i], &playerTemp, name); } else diff --git a/src/p_user.cpp b/src/p_user.cpp index 0f3b6a516..e48712042 100644 --- a/src/p_user.cpp +++ b/src/p_user.cpp @@ -651,7 +651,8 @@ void APlayerPawn::Serialize(FSerializer &arc) ("fallingscreammaxn", FallingScreamMaxSpeed, def->FallingScreamMaxSpeed) ("userange", UseRange, def->UseRange) ("aircapacity", AirCapacity, def->AirCapacity) - ("viewheight", ViewHeight, def->ViewHeight); + ("viewheight", ViewHeight, def->ViewHeight) + ("viewbob", ViewBob, def->ViewBob); } //=========================================================================== @@ -1891,7 +1892,7 @@ void P_CalcHeight (player_t *player) { bob = 0; } - player->viewz = player->mo->Z() + player->viewheight + bob; + player->viewz = player->mo->Z() + player->viewheight + (bob * player->mo->ViewBob); // [SP] Allow DECORATE changes to view bobbing speed. if (player->mo->Floorclip && player->playerstate != PST_DEAD && player->mo->Z() <= player->mo->floorz) { diff --git a/src/r_bsp.cpp b/src/r_bsp.cpp index 934d2d3e5..8d423b3b3 100644 --- a/src/r_bsp.cpp +++ b/src/r_bsp.cpp @@ -105,6 +105,7 @@ TArray WallPortals(1000); // note: this array needs to go away as subsector_t *InSubsector; CVAR (Bool, r_drawflat, false, 0) // [RH] Don't texture segs? +EXTERN_CVAR(Bool, r_fullbrightignoresectorcolor); void R_StoreWallRange (int start, int stop); @@ -1108,7 +1109,7 @@ void R_Subsector (subsector_t *sub) } else { - basecolormap = frontsector->ColorMap; + basecolormap = (r_fullbrightignoresectorcolor && fixedlightlev >= 0) ? &FullNormalLight : frontsector->ColorMap; } portal = frontsector->ValidatePortal(sector_t::ceiling); @@ -1142,7 +1143,7 @@ void R_Subsector (subsector_t *sub) } else { - basecolormap = frontsector->ColorMap; + basecolormap = (r_fullbrightignoresectorcolor && fixedlightlev >= 0) ? &FullNormalLight : frontsector->ColorMap; } // killough 3/7/98: Add (x,y) offsets to flats, add deep water check diff --git a/src/r_data/colormaps.cpp b/src/r_data/colormaps.cpp index b46342463..2d3c0e49d 100644 --- a/src/r_data/colormaps.cpp +++ b/src/r_data/colormaps.cpp @@ -59,6 +59,7 @@ static bool R_CheckForFixedLights(const BYTE *colormaps); extern "C" { FDynamicColormap NormalLight; +FDynamicColormap FullNormalLight; //[SP] Emulate GZDoom brightness } bool NormalLightHasFixedLights; @@ -72,6 +73,7 @@ struct FakeCmap TArray fakecmaps; BYTE *realcolormaps; +BYTE *realfbcolormaps; //[SP] For fullbright use size_t numfakecmaps; @@ -459,6 +461,11 @@ void R_DeinitColormaps () delete[] realcolormaps; realcolormaps = NULL; } + if (realfbcolormaps != NULL) + { + delete[] realfbcolormaps; + realfbcolormaps = NULL; + } FreeSpecialLights(); } @@ -548,9 +555,20 @@ void R_InitColormaps () } } } + + // [SP] Create a copy of the colormap + if (!realfbcolormaps) + { + realfbcolormaps = new BYTE[256*NUMCOLORMAPS*fakecmaps.Size()]; + memcpy(realfbcolormaps, realcolormaps, 256*NUMCOLORMAPS*fakecmaps.Size()); + } + NormalLight.Color = PalEntry (255, 255, 255); NormalLight.Fade = 0; NormalLight.Maps = realcolormaps; + FullNormalLight.Color = PalEntry (255, 255, 255); + FullNormalLight.Fade = 0; + FullNormalLight.Maps = realfbcolormaps; NormalLightHasFixedLights = R_CheckForFixedLights(realcolormaps); numfakecmaps = fakecmaps.Size(); diff --git a/src/r_data/colormaps.h b/src/r_data/colormaps.h index 0764191a3..09006fc1e 100644 --- a/src/r_data/colormaps.h +++ b/src/r_data/colormaps.h @@ -80,6 +80,7 @@ extern BYTE DesaturateColormap[31][256]; extern "C" { extern FDynamicColormap NormalLight; +extern FDynamicColormap FullNormalLight; } extern bool NormalLightHasFixedLights; diff --git a/src/r_main.cpp b/src/r_main.cpp index 1e0de7ecc..4252f4155 100644 --- a/src/r_main.cpp +++ b/src/r_main.cpp @@ -455,6 +455,8 @@ void R_CopyStackedViewParameters() // //========================================================================== +EXTERN_CVAR(Bool, r_fullbrightignoresectorcolor) + void R_SetupColormap(player_t *player) { realfixedcolormap = NULL; @@ -481,6 +483,11 @@ void R_SetupColormap(player_t *player) else if (player->fixedlightlevel >= 0 && player->fixedlightlevel < NUMCOLORMAPS) { fixedlightlev = player->fixedlightlevel * 256; + // [SP] Emulate GZDoom's light-amp goggles. + if (r_fullbrightignoresectorcolor && fixedlightlev >= 0) + { + fixedcolormap = FullNormalLight.Maps; + } } } // [RH] Inverse light for shooting the Sigil diff --git a/src/r_segs.cpp b/src/r_segs.cpp index edb1949b6..48d8f1651 100644 --- a/src/r_segs.cpp +++ b/src/r_segs.cpp @@ -57,6 +57,7 @@ CVAR(Bool, r_np2, true, 0) +EXTERN_CVAR(Bool, r_fullbrightignoresectorcolor); //CVAR (Int, ty, 8, 0) //CVAR (Int, tx, 8, 0) @@ -313,7 +314,7 @@ void R_RenderMaskedSegRange (drawseg_t *ds, int x1, int x2) rw_scalestep = ds->iscalestep; if (fixedlightlev >= 0) - dc_colormap = basecolormap->Maps + fixedlightlev; + dc_colormap = (r_fullbrightignoresectorcolor) ? (FullNormalLight.Maps + fixedlightlev) : (basecolormap->Maps + fixedlightlev); else if (fixedcolormap != NULL) dc_colormap = fixedcolormap; @@ -630,7 +631,7 @@ void R_RenderFakeWall(drawseg_t *ds, int x1, int x2, F3DFloor *rover) } if (fixedlightlev >= 0) - dc_colormap = basecolormap->Maps + fixedlightlev; + dc_colormap = (r_fullbrightignoresectorcolor) ? (FullNormalLight.Maps + fixedlightlev) : (basecolormap->Maps + fixedlightlev); else if (fixedcolormap != NULL) dc_colormap = fixedcolormap; @@ -1788,7 +1789,7 @@ void R_RenderSegLoop () fixed_t xoffset = rw_offset; if (fixedlightlev >= 0) - dc_colormap = basecolormap->Maps + fixedlightlev; + dc_colormap = (r_fullbrightignoresectorcolor) ? (FullNormalLight.Maps + fixedlightlev) : (basecolormap->Maps + fixedlightlev); else if (fixedcolormap != NULL) dc_colormap = fixedcolormap; @@ -3185,13 +3186,13 @@ static void R_RenderDecal (side_t *wall, DBaseDecal *decal, drawseg_t *clipper, rereadcolormap = false; } - rw_light = rw_lightleft + (x1 - WallC.sx1) * rw_lightstep; + rw_light = rw_lightleft + (x1 - savecoord.sx1) * rw_lightstep; if (fixedlightlev >= 0) - dc_colormap = usecolormap->Maps + fixedlightlev; + dc_colormap = (r_fullbrightignoresectorcolor) ? (FullNormalLight.Maps + fixedlightlev) : (usecolormap->Maps + fixedlightlev); else if (fixedcolormap != NULL) dc_colormap = fixedcolormap; else if (!foggy && (decal->RenderFlags & RF_FULLBRIGHT)) - dc_colormap = usecolormap->Maps; + dc_colormap = (r_fullbrightignoresectorcolor) ? FullNormalLight.Maps : usecolormap->Maps; else calclighting = true; diff --git a/src/r_sky.cpp b/src/r_sky.cpp index 37312cbae..f29929c26 100644 --- a/src/r_sky.cpp +++ b/src/r_sky.cpp @@ -76,10 +76,20 @@ void R_InitSkyMap () int skyheight; FTexture *skytex1, *skytex2; + // Do not allow the null texture which has no bitmap and will crash. + if (sky1texture.isNull()) + { + sky1texture = TexMan.CheckForTexture("-noflat-", FTexture::TEX_Any); + } + if (sky2texture.isNull()) + { + sky2texture = TexMan.CheckForTexture("-noflat-", FTexture::TEX_Any); + } + skytex1 = TexMan(sky1texture, true); skytex2 = TexMan(sky2texture, true); - if (skytex1 == NULL) + if (skytex1 == nullptr) return; if ((level.flags & LEVEL_DOUBLESKY) && skytex1->GetHeight() != skytex2->GetHeight()) diff --git a/src/r_things.cpp b/src/r_things.cpp index 99ca68b60..a88624443 100644 --- a/src/r_things.cpp +++ b/src/r_things.cpp @@ -99,6 +99,7 @@ EXTERN_CVAR (Bool, st_scale) EXTERN_CVAR(Bool, r_shadercolormaps) EXTERN_CVAR(Int, r_drawfuzz) EXTERN_CVAR(Bool, r_deathcamera); +CVAR(Bool, r_fullbrightignoresectorcolor, true, CVAR_ARCHIVE | CVAR_GLOBALCONFIG); // // Sprite rotation 0 is facing the viewer, @@ -548,7 +549,7 @@ void R_DrawWallSprite(vissprite_t *spr) else if (fixedcolormap != NULL) dc_colormap = fixedcolormap; else if (!foggy && (spr->renderflags & RF_FULLBRIGHT)) - dc_colormap = usecolormap->Maps; + dc_colormap = (r_fullbrightignoresectorcolor) ? FullNormalLight.Maps : usecolormap->Maps; else calclighting = true; @@ -1066,7 +1067,8 @@ void R_ProjectSprite (AActor *thing, int fakeside, F3DFloor *fakefloor, F3DFloor vis->deltax = float(pos.X - ViewPos.X); vis->deltay = float(pos.Y - ViewPos.Y); vis->renderflags = renderflags; - if(thing->flags5 & MF5_BRIGHT) vis->renderflags |= RF_FULLBRIGHT; // kg3D + if(thing->flags5 & MF5_BRIGHT) + vis->renderflags |= RF_FULLBRIGHT; // kg3D vis->Style.RenderStyle = thing->RenderStyle; vis->FillColor = thing->fillcolor; vis->Translation = thing->Translation; // [RH] thing translation table @@ -1140,7 +1142,7 @@ void R_ProjectSprite (AActor *thing, int fakeside, F3DFloor *fakefloor, F3DFloor } else if (!foggy && ((renderflags & RF_FULLBRIGHT) || (thing->flags5 & MF5_BRIGHT))) { // full bright - vis->Style.colormap = mybasecolormap->Maps; + vis->Style.colormap = (r_fullbrightignoresectorcolor) ? FullNormalLight.Maps : mybasecolormap->Maps; } else { // diminished light @@ -1462,11 +1464,11 @@ void R_DrawPSprite(DPSprite *pspr, AActor *owner, float bobx, float boby, double } if (fixedlightlev >= 0) { - vis->Style.colormap = mybasecolormap->Maps + fixedlightlev; + vis->Style.colormap = (r_fullbrightignoresectorcolor) ? (FullNormalLight.Maps + fixedlightlev) : (mybasecolormap->Maps + fixedlightlev); } else if (!foggy && pspr->GetState()->GetFullbright()) { // full bright - vis->Style.colormap = mybasecolormap->Maps; // [RH] use basecolormap + vis->Style.colormap = (r_fullbrightignoresectorcolor) ? FullNormalLight.Maps : mybasecolormap->Maps; // [RH] use basecolormap } else { // local light @@ -1516,6 +1518,11 @@ void R_DrawPSprite(DPSprite *pspr, AActor *owner, float bobx, float boby, double { noaccel = true; } + // [SP] If emulating GZDoom fullbright, disable acceleration + if (r_fullbrightignoresectorcolor && fixedlightlev >= 0) + mybasecolormap = &FullNormalLight; + if (r_fullbrightignoresectorcolor && !foggy && pspr->GetState()->GetFullbright()) + mybasecolormap = &FullNormalLight; colormap_to_use = mybasecolormap; } else @@ -2057,7 +2064,7 @@ void R_DrawSprite (vissprite_t *spr) } else if (!foggy && (spr->renderflags & RF_FULLBRIGHT)) { // full bright - spr->Style.colormap = mybasecolormap->Maps; + spr->Style.colormap = (r_fullbrightignoresectorcolor) ? FullNormalLight.Maps : mybasecolormap->Maps; } else { // diminished light @@ -2615,7 +2622,7 @@ void R_ProjectParticle (particle_t *particle, const sector_t *sector, int shade, } else if (particle->bright) { - vis->Style.colormap = map; + vis->Style.colormap = (r_fullbrightignoresectorcolor) ? FullNormalLight.Maps : map; } else { diff --git a/src/textures/animations.cpp b/src/textures/animations.cpp index f46289f07..06c496d9a 100644 --- a/src/textures/animations.cpp +++ b/src/textures/animations.cpp @@ -1002,7 +1002,7 @@ void FTextureManager::UpdateAnimations (DWORD mstime) template<> FSerializer &Serialize(FSerializer &arc, const char *key, FDoorAnimation *&p, FDoorAnimation **def) { - FTextureID tex = p->BaseTexture; + FTextureID tex = p? p->BaseTexture : FNullTextureID(); Serialize(arc, key, tex, def ? &(*def)->BaseTexture : nullptr); if (arc.isReading()) { diff --git a/src/thingdef/thingdef_properties.cpp b/src/thingdef/thingdef_properties.cpp index 80ee6c22f..6321ebfe9 100644 --- a/src/thingdef/thingdef_properties.cpp +++ b/src/thingdef/thingdef_properties.cpp @@ -2945,6 +2945,26 @@ DEFINE_CLASS_PROPERTY_PREFIX(player, weaponslot, ISsssssssssssssssssssssssssssss } } +//========================================================================== +// +// [SP] Player.Viewbob +// +//========================================================================== +DEFINE_CLASS_PROPERTY_PREFIX(player, viewbob, F, PlayerPawn) +{ + PROP_DOUBLE_PARM(z, 0); + // [SP] Hard limits. This is to prevent terrywads from making players sick. + // Remember - this messes with a user option who probably has it set a + // certain way for a reason. I think a 1.5 limit is pretty generous, but + // it may be safe to increase it. I really need opinions from people who + // could be affected by this. + if (z < 0.0 || z > 1.5) + { + I_Error("ViewBob must be between 0.0 and 1.5."); + } + defaults->ViewBob = z; +} + //========================================================================== // //========================================================================== diff --git a/src/zscript/vmexec.cpp b/src/zscript/vmexec.cpp index 454f02d03..7ee89329a 100644 --- a/src/zscript/vmexec.cpp +++ b/src/zscript/vmexec.cpp @@ -11,21 +11,21 @@ #if COMPGOTO #define OP(x) x -#define NEXTOP do { unsigned op = pc->op; a = pc->a; pc++; goto *ops[op]; } while(0) +#define NEXTOP do { pc++; unsigned op = pc->op; a = pc->a; goto *ops[op]; } while(0) #else #define OP(x) case OP_##x -#define NEXTOP break +#define NEXTOP pc++; break #endif #define luai_nummod(a,b) ((a) - floor((a)/(b))*(b)) -#define A (pc[-1].a) -#define B (pc[-1].b) -#define C (pc[-1].c) -#define Cs (pc[-1].cs) -#define BC (pc[-1].i16u) -#define BCs (pc[-1].i16) -#define ABCs (pc[-1].i24) +#define A (pc[0].a) +#define B (pc[0].b) +#define C (pc[0].c) +#define Cs (pc[0].cs) +#define BC (pc[0].i16u) +#define BCs (pc[0].i16) +#define ABCs (pc[0].i24) #define JMPOFS(x) ((x)->i24) #define KC (konstd[C]) @@ -48,8 +48,8 @@ #define CMPJMP(test) \ if ((test) == (a & CMP_CHECK)) { \ - assert(pc->op == OP_JMP); \ - pc += 1 + JMPOFS(pc); \ + assert(pc[1].op == OP_JMP); \ + pc += 1 + JMPOFS(pc+1); \ } else { \ pc += 1; \ } diff --git a/src/zscript/vmexec.h b/src/zscript/vmexec.h index adf2986c5..3637f2c1c 100644 --- a/src/zscript/vmexec.h +++ b/src/zscript/vmexec.h @@ -52,11 +52,17 @@ begin: { #if !COMPGOTO VM_UBYTE op; - for(;;) switch(op = pc->op, a = pc->a, pc++, op) + for(;;) switch(op = pc->op, a = pc->a, op) #else + pc--; NEXTOP; #endif { +#if !COMPGOTO + default: + assert(0 && "Undefined opcode hit"); + NEXTOP; +#endif OP(LI): ASSERTD(a); reg.d[a] = BCs; @@ -367,13 +373,13 @@ begin: } NEXTOP; OP(JMP): - pc += JMPOFS(pc - 1); + pc += JMPOFS(pc); NEXTOP; OP(IJMP): ASSERTD(a); pc += (BCs + reg.d[a]); - assert(pc->op == OP_JMP); - pc += 1 + JMPOFS(pc); + assert(pc[1].op == OP_JMP); + pc += 1 + JMPOFS(pc+1); NEXTOP; OP(PARAMI): assert(f->NumParam < sfunc->MaxParam); @@ -490,7 +496,7 @@ begin: VMReturn returns[MAX_RETURNS]; int numret; - FillReturns(reg, f, returns, pc, C); + FillReturns(reg, f, returns, pc+1, C); if (call->Native) { numret = static_cast(call)->NativeCall(stack, reg.param + f->NumParam - B, B, returns, C); @@ -603,8 +609,8 @@ begin: { THROW(X_TOO_MANY_TRIES); } - assert((pc + JMPOFS(pc - 1))->op == OP_CATCH); - exception_frames[try_depth++] = pc + JMPOFS(pc - 1); + assert((pc + JMPOFS(pc) + 1)->op == OP_CATCH); + exception_frames[try_depth++] = pc + JMPOFS(pc) + 1; NEXTOP; OP(UNTRY): assert(a <= try_depth); @@ -704,8 +710,8 @@ begin: } if (cmp == (a & CMP_CHECK)) { - assert(pc->op == OP_JMP); - pc += 1 + JMPOFS(pc); + assert(pc[1].op == OP_JMP); + pc += 1 + JMPOFS(pc+1); } else { diff --git a/wadsrc/static/actors/shared/player.txt b/wadsrc/static/actors/shared/player.txt index ac5ceb0a7..08d9a252a 100644 --- a/wadsrc/static/actors/shared/player.txt +++ b/wadsrc/static/actors/shared/player.txt @@ -33,6 +33,7 @@ Actor PlayerPawn : Actor native Player.MugShotMaxHealth 0 Player.FlechetteType "ArtiPoisonBag3" Player.AirCapacity 1 + Player.ViewBob 1 Obituary "$OB_MPDEFAULT" } diff --git a/wadsrc/static/language.enu b/wadsrc/static/language.enu index 4b0f57c18..5c1961ea4 100644 --- a/wadsrc/static/language.enu +++ b/wadsrc/static/language.enu @@ -1787,6 +1787,7 @@ DSPLYMNU_PICKUPFADE = "Pickup Flash Intensity"; DSPLYMNU_PALLETEHACK = "DirectDraw palette hack"; // Not used DSPLYMNU_ATTACHEDSURFACES = "Use attached surfaces"; // Not used DSPLYMNU_SKYMODE = "Sky render mode"; +DSPLYMNU_GZDFULLBRIGHT = "Fullbright overrides sector color"; DSPLYMNU_DRAWFUZZ = "Use fuzz effect"; DSPLYMNU_TRANSSOUL = "Lost Soul translucency"; DSPLYMNU_FAKECONTRAST = "Use fake contrast"; diff --git a/wadsrc/static/menudef.txt b/wadsrc/static/menudef.txt index 063225fdd..6bbf8d5da 100644 --- a/wadsrc/static/menudef.txt +++ b/wadsrc/static/menudef.txt @@ -696,6 +696,7 @@ OptionMenu "VideoOptions" } Option "$DSPLYMNU_SKYMODE", "r_skymode", "SkyModes" + Option "$DSPLYMNU_GZDFULLBRIGHT", "r_fullbrightignoresectorcolor", "OnOff" Option "$DSPLYMNU_DRAWFUZZ", "r_drawfuzz", "Fuzziness" Slider "$DSPLYMNU_TRANSSOUL", "transsouls", 0.25, 1.0, 0.05, 2 Option "$DSPLYMNU_FAKECONTRAST", "r_fakecontrast", "Contrast"